LCOV - code coverage report
Current view: top level - src/45_xgTools - m_xg_nonlop.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 92.9 % 1543 1434
Test Date: 2026-09-21 22:40:37 Functions: 95.2 % 42 40

            Line data    Source code
       1              : !!****m* ABINIT/m_xg_nonlop
       2              : !! NAME
       3              : !! m_xg_nonlop
       4              : !!
       5              : !! FUNCTION
       6              : !!  This module provides functions to compute the nonlocal operator by means of the BLAS GEMM
       7              : !!  routine. By treating ndat simultaneous wavefunctions, it is able to exploit BLAS3 routines,
       8              : !!  which leads to excellent CPU efficiency and OpenMP scalability.
       9              : !!
      10              : !! COPYRIGHT
      11              : !! Copyright (C) 2022-2026 ABINIT group (LB)
      12              : !! This file is distributed under the terms of the
      13              : !! GNU General Public License, see ~abinit/COPYING
      14              : !! or http://www.gnu.org/copyleft/gpl.txt .
      15              : !!
      16              : !! SOURCE
      17              : 
      18              : #if defined HAVE_CONFIG_H
      19              : #include "config.h"
      20              : #endif
      21              : 
      22              : #include "abi_common.h"
      23              : 
      24              : module m_xg_nonlop
      25              : 
      26              :  use defs_basis
      27              :  use m_errors
      28              :  use m_abicore
      29              :  use m_xmpi
      30              : ! use m_abi_linalg
      31              :  use m_xg
      32              :  use m_xomp
      33              : #ifdef HAVE_OPENMP
      34              :  use omp_lib
      35              : #endif
      36              : 
      37              :  use m_time, only : timab
      38              :  use defs_abitypes, only : MPI_type
      39              : 
      40              :  use m_paw_ij, only : paw_ij_type
      41              :  use m_pawtab, only : pawtab_type
      42              : 
      43              :  implicit none
      44              : 
      45              :  private
      46              : 
      47              :  double precision, parameter :: inv_sqrt2 = 1/sqrt2
      48              : 
      49              :  ! Independent timers of xg_nonlop :
      50              :  integer, parameter :: tim_getcprj    = 2101
      51              :  integer, parameter :: tim_apply_prj  = 2102
      52              :  integer, parameter :: tim_apply_Aij  = 2103
      53              :  integer, parameter :: tim_mult_cprj  = 2104
      54              :  integer, parameter :: tim_make_k     = 2105
      55              :  integer, parameter :: tim_make_Dij   = 2106
      56              :  integer, parameter :: tim_make_Sij   = 2107
      57              :  integer, parameter :: tim_make_ekb   = 2108
      58              :  integer, parameter :: tim_apply_diag = 2109
      59              :  integer, parameter :: tim_init       = 2110
      60              : 
      61              :  ! Timers that depend on other xg_nonlop timers :
      62              :  integer, parameter :: tim_getXSY     = 2120
      63              :  integer, parameter :: tim_getXHY     = 2121
      64              :  integer, parameter :: tim_getHmeSX   = 2122
      65              :  integer, parameter :: tim_iter_refinement = 2123
      66              : 
      67              :  integer, parameter :: tim_getcprj_gemm     = 2130
      68              :  integer, parameter :: tim_getcprj_copy     = 2131
      69              :  integer, parameter :: tim_getcprj_mpi      = 2132
      70              :  integer, parameter :: tim_getcprj_otf      = 2133
      71              : 
      72              :  integer, parameter :: tim_apply_prj_gemm   = 2135
      73              :  integer, parameter :: tim_apply_prj_copy   = 2136
      74              :  integer, parameter :: tim_apply_prj_mpi    = 2137
      75              :  integer, parameter :: tim_apply_prj_otf    = 2138
      76              : 
      77              :  integer, parameter :: tim_mult_cprj_gemm   = 2140
      78              :  integer, parameter :: tim_mult_cprj_copy   = 2141
      79              :  integer, parameter :: tim_mult_cprj_mpi    = 2142
      80              : 
      81              :  integer, parameter :: tim_forces_stress      = 2150
      82              :  integer, parameter :: tim_fst_start          = 2151
      83              :  integer, parameter :: tim_fst_cprj_deriv_f   = 2152
      84              :  integer, parameter :: tim_fst_cprj_deriv_str = 2153
      85              :  integer, parameter :: tim_fst_mult_cprj_f    = 2154
      86              :  integer, parameter :: tim_fst_mult_cprj_str  = 2155
      87              :  integer, parameter :: tim_fst_work_str       = 2156
      88              : 
      89              :  integer, parameter, public :: DERIV_ATOM   = 1
      90              :  integer, parameter, public :: DERIV_STRESS = 2
      91              : 
      92              :  type,public :: xg_nonlop_t
      93              : 
      94              :    integer :: cplex
      95              :    integer :: cplex_alldij
      96              :    integer :: cprjdim
      97              :    integer :: comm_atom
      98              :    integer :: comm_band
      99              :    integer :: npw_k
     100              :    integer :: total_npw_k
     101              :    integer :: max_npw_k
     102              :    integer :: me_band
     103              :    integer :: my_natom
     104              :    integer :: natom
     105              :    integer :: mkmem
     106              :    integer :: nlmn_max
     107              :    integer :: ntypat
     108              :    integer :: nspinor
     109              :    integer :: space_pw
     110              :    integer :: space_cprj
     111              :    integer :: space_Dij
     112              :    logical :: paw
     113              :    integer :: option
     114              :    real(dp) :: weight
     115              : 
     116              :    integer, pointer :: mpi_atmtab(:)
     117              :    integer, pointer :: indlmn(:,:,:)
     118              :    integer, pointer :: nattyp(:)
     119              : 
     120              :    integer,allocatable :: l_npw_k(:)
     121              :    integer,allocatable :: l_shift_npw_k(:)
     122              : 
     123              :    real(dp), pointer :: sij_triangular_mat(:,:)
     124              : 
     125              :    integer, allocatable :: nlmn_natom(:)
     126              :    integer, allocatable :: nlmn_ntypat(:)
     127              : 
     128              :    real(dp), pointer :: ffnl_k(:,:,:,:)
     129              :    real(dp), pointer :: ph3d_k(:,:,:)
     130              : 
     131              :    real(dp), pointer :: kpg_k(:,:)
     132              : 
     133              :    type(xg_t),pointer :: projectors(:)
     134              :    type(xg_t),pointer :: projectors_k
     135              : 
     136              :    type(xg_t),pointer :: ffnl_gather(:)
     137              :    type(xg_t),pointer :: ffnl_gather_k
     138              : 
     139              :    type(xg_t),pointer :: ph3d_gather(:)
     140              :    type(xg_t),pointer :: ph3d_gather_k
     141              : 
     142              :    ! non paw only:
     143              :    type(xg_t) :: ekb
     144              :    ! end non paw only
     145              : 
     146              :    ! paw only:
     147              :    type(xg_t),pointer :: gram_proj(:)
     148              :    type(xg_t),pointer :: gram_proj_k
     149              : 
     150              :    type(xg_t) :: Dij
     151              :    type(xgBlock_t) :: Dij_spin
     152              :    type(xg_t) :: Sij
     153              : 
     154              :    type(xg_t) :: Sijm1
     155              :    type(xg_t), pointer :: invSij_approx(:)
     156              :    type(xg_t), pointer :: invSij_approx_k
     157              :    ! end paw only
     158              : 
     159              :  end type xg_nonlop_t
     160              : !!***
     161              : 
     162              :   ! To initialize/make/destroy xg_nonlop object
     163              :   public :: xg_nonlop_init
     164              :   public :: xg_nonlop_make_k
     165              :   public :: xg_nonlop_destroy
     166              :   public :: xg_nonlop_make_ekb    ! non paw only
     167              :   public :: xg_nonlop_destroy_ekb ! non paw only
     168              :   public :: xg_nonlop_update_weight
     169              :   public :: xg_nonlop_init_cplex_alldij ! paw only
     170              :   public :: xg_nonlop_make_Dij    ! paw only
     171              :   public :: xg_nonlop_set_Dij_spin! paw only
     172              :   public :: xg_nonlop_make_Sij    ! paw only
     173              :   public :: xg_nonlop_destroy_Dij ! paw only
     174              :   public :: xg_nonlop_destroy_Sij ! paw only
     175              :   ! Generic operations
     176              :   public :: xg_nonlop_getcprj
     177              :   public :: xg_nonlop_apply_Aij
     178              :   public :: xg_nonlop_precond_iterative_refinement
     179              :   public :: xg_nonlop_mult_cprj
     180              :   public :: xg_nonlop_apply_prj
     181              :   public :: xg_nonlop_colwiseXAX
     182              :   public :: xg_nonlop_colwiseXDX
     183              :   public :: xg_nonlop_getXAY
     184              :   public :: xg_nonlop_getXDY
     185              :   public :: xg_nonlop_getAX
     186              :   public :: xg_nonlop_getDX
     187              :   ! Specific operations (using Sij/Dij or ekb arrays)
     188              :   public :: xg_nonlop_getXHY
     189              :   public :: xg_nonlop_getHX
     190              :   public :: xg_nonlop_colwiseXHX
     191              :   public :: xg_nonlop_getXSY   ! paw only
     192              :   public :: xg_nonlop_getSX    ! paw only
     193              :   public :: xg_nonlop_getSm1X  ! paw only
     194              :   public :: xg_nonlop_getHmeSX ! paw only
     195              :   public :: xg_nonlop_forces_stress
     196              : 
     197              : contains
     198              : !!***
     199              : 
     200              : !!****f* m_xg_nonlop/xg_nonlop_init
     201              : !! NAME
     202              : !! xg_nonlop_init
     203              : !!
     204              : !! FUNCTION
     205              : !! Initalization of the xg_nonlop_kpt array
     206              : !!
     207              : !! INPUTS
     208              : !!
     209              : !! SOURCE
     210              : 
     211          162 :  subroutine xg_nonlop_init(xg_nonlop,indlmn,my_natom,nattyp,mkmem,ntypat,nspinor,ucvol,usepaw,&
     212          162 :      xg_nonlop_option,me_band,comm_band,comm_atom,mpi_atmtab)
     213              : 
     214              :    integer ,intent(in) :: me_band,comm_band,comm_atom
     215              :    integer ,intent(in) :: my_natom
     216              :    integer ,intent(in) :: mkmem
     217              :    integer ,intent(in) :: ntypat
     218              :    integer ,intent(in) :: nspinor
     219              :    integer ,intent(in) :: usepaw
     220              :    integer ,intent(in) :: xg_nonlop_option
     221              :    real(dp),intent(in) :: ucvol
     222              :    type(xg_nonlop_t),intent(inout) :: xg_nonlop
     223              : 
     224              :    integer,optional,intent(in),target :: mpi_atmtab(:)
     225              :    integer,intent(in),target :: indlmn(:,:,:)
     226              :    integer,intent(in),target :: nattyp(:)
     227              :    real(dp) :: tsec(2)
     228              : 
     229              :    integer :: itypat,cprjdim,nlmn,nlmn_max,natom,shift,nmpi,nattyp_i
     230              : 
     231          162 :    call timab(tim_init,1,tsec)
     232              : 
     233          162 :    xg_nonlop%mkmem=mkmem
     234          162 :    xg_nonlop%nspinor=nspinor
     235          162 :    xg_nonlop%comm_atom=comm_atom
     236          162 :    if (xmpi_comm_size(comm_atom)>1) then
     237          108 :      if (present(mpi_atmtab)) then
     238          108 :        xg_nonlop%mpi_atmtab=>mpi_atmtab
     239              :      else
     240            0 :        ABI_ERROR("mpi_atmtab must be present")
     241              :      end if
     242              :    else
     243           54 :      xg_nonlop%mpi_atmtab=>null()
     244              :    end if
     245          162 :    xg_nonlop%my_natom=my_natom
     246          162 :    xg_nonlop%me_band=me_band
     247          162 :    xg_nonlop%comm_band=comm_band
     248              : 
     249          162 :    if (xg_nonlop_option==0.or.xg_nonlop_option==1) then
     250          162 :      xg_nonlop%option = xg_nonlop_option
     251              :    else
     252            0 :      ABI_ERROR('Wrong value of xg_nonlop_option')
     253              :    end if
     254              : 
     255          162 :    xg_nonlop%paw=usepaw==1
     256              : 
     257          162 :    xg_nonlop%space_pw=0
     258          162 :    xg_nonlop%space_cprj=0
     259          162 :    xg_nonlop%space_Dij=0
     260              : 
     261          162 :    xg_nonlop%weight=four_pi/sqrt(ucvol)
     262          162 :    xg_nonlop%ntypat=ntypat
     263              : 
     264          162 :    xg_nonlop%nattyp=>nattyp
     265          162 :    xg_nonlop%indlmn=>indlmn
     266              : 
     267          162 :    natom=0
     268          476 :    do itypat=1,ntypat
     269          476 :      natom = natom + nattyp(itypat)
     270              :    end do
     271              : 
     272          486 :    ABI_MALLOC(xg_nonlop%nlmn_ntypat,(ntypat))
     273          486 :    ABI_MALLOC(xg_nonlop%nlmn_natom,(natom))
     274              : 
     275          162 :    cprjdim=0
     276          162 :    shift=0
     277          162 :    nlmn_max=0
     278          476 :    do itypat=1,ntypat
     279         4842 :      nlmn = count(indlmn(3,:,itypat)>0)
     280          314 :      if (nlmn>nlmn_max) nlmn_max=nlmn
     281          314 :      xg_nonlop%nlmn_ntypat(itypat) = nlmn
     282          314 :      nattyp_i = nattyp(itypat)
     283          476 :      if (nattyp_i>0) then
     284          310 :        cprjdim = cprjdim + nattyp_i*nlmn
     285          674 :        xg_nonlop%nlmn_natom(1+shift:nattyp_i+shift) = nlmn
     286              :        shift = shift + nattyp_i
     287              :      end if
     288              :    end do
     289          162 :    xg_nonlop%nlmn_max = nlmn_max
     290          162 :    xg_nonlop%natom = natom
     291          162 :    xg_nonlop%cprjdim = cprjdim
     292              : 
     293         1585 :    ABI_MALLOC(xg_nonlop%projectors,(mkmem))
     294         1423 :    ABI_MALLOC(xg_nonlop%ffnl_gather,(mkmem))
     295         1423 :    ABI_MALLOC(xg_nonlop%ph3d_gather,(mkmem))
     296          162 :    if (xg_nonlop%paw) then
     297         1183 :      ABI_MALLOC(xg_nonlop%gram_proj,(mkmem))
     298         1183 :      ABI_MALLOC(xg_nonlop%invSij_approx,(mkmem))
     299              :    end if
     300              : 
     301          162 :   nmpi = xmpi_comm_size(xg_nonlop%comm_band)
     302          486 :   ABI_MALLOC(xg_nonlop%l_npw_k,(nmpi))
     303          324 :   ABI_MALLOC(xg_nonlop%l_shift_npw_k,(nmpi))
     304              : 
     305          162 :   call timab(tim_init,2,tsec)
     306              : 
     307          162 :  end subroutine xg_nonlop_init
     308              : !!***
     309              : 
     310              : !!****f* m_xg_nonlop/xg_nonlop_update_weight
     311              : !! NAME
     312              : !! xg_nonlop_init
     313              : !!
     314              : !! FUNCTION
     315              : !! Compute new weights with respect to ucvol
     316              : !!
     317              : !! INPUTS
     318              : !!
     319              : !! SOURCE
     320         2572 :  subroutine xg_nonlop_update_weight(xg_nonlop,ucvol)
     321              : 
     322              :    type(xg_nonlop_t),intent(inout) :: xg_nonlop
     323              :    real(dp),intent(in) :: ucvol
     324              : 
     325         2572 :    xg_nonlop%weight=four_pi/sqrt(ucvol)
     326              : 
     327         2572 :  end subroutine xg_nonlop_update_weight
     328              : !!***
     329              : 
     330              : !!****f* m_xg_nonlop/xg_nonlop_init_cplex_alldij
     331              : !! NAME
     332              : !! xg_nonlop_init_cplex_alldij
     333              : !!
     334              : !! FUNCTION
     335              : !!
     336              : !! INPUTS
     337              : !!
     338              : !! SOURCE
     339          142 :  subroutine xg_nonlop_init_cplex_alldij(xg_nonlop,paw_ij)
     340              : 
     341              :    type(paw_ij_type),intent(in)    :: paw_ij(:)
     342              :    type(xg_nonlop_t),intent(inout) :: xg_nonlop
     343              : 
     344              :    logical :: paral_atom
     345              :    integer :: iatom,iatom_tot,ierr
     346              :    integer,allocatable :: l_cplex(:)
     347              :    real(dp) :: tsec(2)
     348              : 
     349          142 :    call timab(tim_init,1,tsec)
     350              : 
     351          142 :    paral_atom=(xmpi_comm_size(xg_nonlop%comm_atom)>1)
     352              : 
     353          426 :    ABI_MALLOC(l_cplex,(xg_nonlop%natom))
     354          466 :    l_cplex=0
     355          280 :    do iatom=1,xg_nonlop%my_natom ! loop over atoms treated by this proc
     356          138 :      iatom_tot=iatom;if (paral_atom) iatom_tot=xg_nonlop%mpi_atmtab(iatom)
     357          280 :      l_cplex(iatom_tot)=paw_ij(iatom)%cplex_dij
     358              :    end do
     359          142 :    call xmpi_sum(l_cplex,xg_nonlop%comm_atom,ierr)
     360          142 :    xg_nonlop%cplex_alldij = 0
     361          466 :    do iatom=1,xg_nonlop%natom ! loop over all atoms
     362          466 :      if (xg_nonlop%cplex_alldij<l_cplex(iatom)) xg_nonlop%cplex_alldij=l_cplex(iatom)
     363              :    end do
     364          142 :    ABI_FREE(l_cplex)
     365              : 
     366          142 :    call timab(tim_init,2,tsec)
     367              : 
     368          142 :  end subroutine xg_nonlop_init_cplex_alldij
     369              : !!***
     370              : 
     371          162 :  subroutine xg_nonlop_destroy(xg_nonlop)
     372              : 
     373              :   type(xg_nonlop_t),intent(inout) :: xg_nonlop
     374              : 
     375              :   integer :: ikpt
     376              : 
     377          162 :   if (xg_nonlop%paw) then
     378          138 :     call xg_nonlop_destroy_Sij(xg_nonlop) ! Can be destroyed before
     379          138 :     call xg_nonlop_destroy_Dij(xg_nonlop) ! Can be destroyed before
     380              :   else
     381           24 :     call xg_nonlop_destroy_ekb(xg_nonlop) ! Can be destroyed before
     382              :   end if
     383              : 
     384          162 :   ABI_FREE(xg_nonlop%nlmn_ntypat)
     385          162 :   ABI_FREE(xg_nonlop%nlmn_natom)
     386              : 
     387          162 :   ABI_FREE(xg_nonlop%l_npw_k)
     388          162 :   ABI_FREE(xg_nonlop%l_shift_npw_k)
     389              : 
     390         1261 :   do ikpt=1,xg_nonlop%mkmem
     391         1099 :     call xg_free(xg_nonlop%projectors(ikpt))
     392         1099 :     call xg_free(xg_nonlop%ffnl_gather(ikpt))
     393         1099 :     call xg_free(xg_nonlop%ph3d_gather(ikpt))
     394         1261 :     if (xg_nonlop%paw) then
     395          907 :       call xg_free(xg_nonlop%gram_proj(ikpt))
     396          907 :       call xg_free(xg_nonlop%invSij_approx(ikpt))
     397              :     end if
     398              :   end do
     399          162 :   ABI_FREE(xg_nonlop%projectors)
     400          162 :   ABI_FREE(xg_nonlop%ffnl_gather)
     401          162 :   ABI_FREE(xg_nonlop%ph3d_gather)
     402          162 :   if (xg_nonlop%paw) then
     403          138 :     ABI_FREE(xg_nonlop%gram_proj)
     404          138 :     ABI_FREE(xg_nonlop%invSij_approx)
     405              :   end if
     406              : 
     407          162 :  end subroutine xg_nonlop_destroy
     408              : !!***
     409              : 
     410           24 :  subroutine xg_nonlop_make_ekb(xg_nonlop,ekb)
     411              : 
     412              :   type(xg_nonlop_t),intent(inout) :: xg_nonlop
     413              :   real(dp), intent(in) :: ekb(:,:)
     414              : 
     415              :   integer :: itypat, ilmn, iln, nlmn, nlmn_max, ntypat
     416           24 :   real(dp),pointer :: ekb_(:)
     417              :   real(dp) :: tsec(2)
     418              :   type(xgBlock_t) :: ekb_itypat
     419              : 
     420              : ! *************************************************************************
     421              : 
     422           24 :   call timab(tim_make_ekb,1,tsec)
     423              : 
     424           24 :   if (xg_nonlop%paw) then
     425            0 :     ABI_ERROR('Not implemented with paw=True.')
     426              :   end if
     427              : 
     428           24 :   ntypat   = xg_nonlop%ntypat
     429           24 :   nlmn_max = xg_nonlop%nlmn_max
     430              : 
     431           24 :   call xg_init(xg_nonlop%ekb,SPACE_R,nlmn_max,ntypat,xmpi_comm_self)
     432              : 
     433           72 :   do itypat=1,ntypat
     434              : 
     435           48 :     nlmn=xg_nonlop%nlmn_ntypat(itypat)
     436           48 :     call xg_setBlock(xg_nonlop%ekb,ekb_itypat,nlmn,1,fcol=itypat)
     437           48 :     call xgBlock_reverseMap_1D(ekb_itypat,ekb_)
     438         1584 :     do ilmn=1,nlmn
     439         1512 :       iln=xg_nonlop%indlmn(5,ilmn,itypat)
     440         1560 :       ekb_(ilmn) = ekb(iln,itypat)
     441              :     end do
     442              : 
     443              :   end do
     444              : 
     445           24 :   call timab(tim_make_ekb,2,tsec)
     446              : 
     447           24 :  end subroutine xg_nonlop_make_ekb
     448              : !!***
     449              : 
     450         2188 :  subroutine xg_nonlop_make_Dij(xg_nonlop,paw_ij,nsppol,atindx)
     451              : 
     452              :   type(xg_nonlop_t),intent(inout) :: xg_nonlop
     453              :   type(paw_ij_type),intent(in)    :: paw_ij(:)
     454              :   integer,intent(in)              :: nsppol
     455              :   integer,intent(in)              :: atindx(:)
     456              : 
     457              :   logical :: paral_atom
     458              :   integer :: isppol, iatom, iatom_input, iatom_type, nlmn, nlmn_max, natom, nspinor, shift
     459              :   integer :: ilmn, jlmn, j0lmn, jjlmn, ijlmn
     460              :   integer :: cplex_alldij,cplex_dij,isp,isps,jsp,jsps,ijsp
     461         2188 :   real(dp),pointer :: Dij_iatom_(:,:)
     462              :   real(dp) :: tsec(2)
     463              :   type(xgBlock_t) :: Dij_iatom
     464              : 
     465              : ! *************************************************************************
     466              : 
     467         2188 :   call timab(tim_make_Dij,1,tsec)
     468              : 
     469         2188 :   if (.not.xg_nonlop%paw) then
     470            0 :     ABI_ERROR('Not implemented with paw=False.')
     471              :   end if
     472              : 
     473         2188 :   nspinor  = xg_nonlop%nspinor
     474         2188 :   natom    = xg_nonlop%natom
     475         2188 :   nlmn_max = xg_nonlop%nlmn_max
     476              : 
     477         2188 :   paral_atom=(xmpi_comm_size(xg_nonlop%comm_atom)>1)
     478              : 
     479         2188 :   cplex_alldij = xg_nonlop%cplex_alldij
     480         2188 :   if (cplex_alldij==1) then
     481         1645 :     xg_nonlop%space_Dij=SPACE_R
     482          543 :   else if (cplex_alldij==2) then
     483          543 :     xg_nonlop%space_Dij=SPACE_C
     484              :   else
     485            0 :     ABI_ERROR('Bad cplex_alldij')
     486              :   end if
     487              : 
     488         2188 :   call xg_init(xg_nonlop%Dij,xg_nonlop%space_Dij,nspinor*nlmn_max,nspinor*nlmn_max*natom*nsppol,xmpi_comm_null)
     489              : 
     490         4440 :   do isppol=1,nsppol
     491              : 
     492         6518 :     do iatom=1,xg_nonlop%my_natom ! loop over atoms treated by this proc
     493         2078 :       iatom_input = iatom
     494         2078 :       if (paral_atom) iatom_input=xg_nonlop%mpi_atmtab(iatom) ! mpi_atmtab(iatom) has the ordering of the input file
     495         2078 :       iatom_type = atindx(iatom_input) ! convert iatom from input file to iatom ordered by type
     496         2078 :       nlmn=xg_nonlop%nlmn_natom(iatom_type)
     497         2078 :       shift=1+(iatom_type-1)*nspinor*nlmn_max+(isppol-1)*natom*nspinor*nlmn_max
     498         2078 :       call xg_setBlock(xg_nonlop%Dij,Dij_iatom,nspinor*nlmn,nspinor*nlmn,fcol=shift)
     499         2078 :       cplex_dij=paw_ij(iatom)%cplex_dij
     500         2078 :       call xgBlock_reverseMap(Dij_iatom,Dij_iatom_)
     501         6822 :       do jsp=1,nspinor
     502         2492 :         jsps = (jsp-1)*nlmn
     503        27246 :         do jlmn=1,nlmn
     504        22676 :           j0lmn=jlmn*(jlmn-1)/2
     505        22676 :           jjlmn=j0lmn+jlmn
     506        55708 :           do isp=1,nspinor
     507        30540 :             isps = (isp-1)*nlmn
     508        30540 :             if (nspinor==1) then
     509              :               ijsp = isppol
     510              :             else
     511        15728 :               if (isp==jsp) then
     512              :                 ijsp = isp
     513         7864 :               else if (isp==1) then
     514              :                 ijsp = 3 ! up/down
     515              :               else
     516         3932 :                 ijsp = 4 ! down/up
     517              :               end if
     518              :             end if
     519              :             ! see m_hamiltonian:pawdij2ekb
     520        30540 :             if (cplex_dij==1) then
     521        14812 :               Dij_iatom_(cplex_alldij*(jlmn+isps-1)+1,jlmn+jsps) = paw_ij(iatom)%dij(jjlmn,ijsp)
     522        14812 :               if (cplex_alldij==2) Dij_iatom_(2*(jlmn+isps),jlmn+jsps) = zero
     523              :             else
     524        15728 :               Dij_iatom_(2*(jlmn+isps-1)+1,jlmn+jsps) = paw_ij(iatom)%dij(2*jjlmn-1,ijsp)
     525        15728 :               Dij_iatom_(2*(jlmn+isps)    ,jlmn+jsps) = paw_ij(iatom)%dij(2*jjlmn  ,ijsp)
     526              :             end if
     527       195926 :             do ilmn=1,jlmn-1
     528              :               ! see m_hamiltonian:pawdij2ekb and opernlc_ylm
     529       142710 :               ijlmn=j0lmn+ilmn
     530       173250 :               if (cplex_dij==1) then
     531        65342 :                 Dij_iatom_(cplex_alldij*(ilmn+isps-1)+1,jlmn+jsps) = paw_ij(iatom)%dij(ijlmn,ijsp)
     532        65342 :                 if (cplex_alldij==2) Dij_iatom_(2*(ilmn+isps),jlmn+jsps) = zero
     533        65342 :                 Dij_iatom_(cplex_alldij*(jlmn+jsps-1)+1,ilmn+isps) = paw_ij(iatom)%dij(ijlmn,ijsp)
     534        65342 :                 if (cplex_alldij==2) Dij_iatom_(2*(jlmn+jsps),ilmn+isps) = zero
     535              :               else
     536        77368 :                 Dij_iatom_(2*(ilmn+isps-1)+1,jlmn+jsps) = paw_ij(iatom)%dij(2*ijlmn-1,ijsp)
     537        77368 :                 Dij_iatom_(2*(ilmn+isps)    ,jlmn+jsps) = paw_ij(iatom)%dij(2*ijlmn  ,ijsp)
     538        77368 :                 Dij_iatom_(2*(jlmn+jsps-1)+1,ilmn+isps) = paw_ij(iatom)%dij(2*ijlmn-1,ijsp)
     539        77368 :                 Dij_iatom_(2*(jlmn+jsps)    ,ilmn+isps) =-paw_ij(iatom)%dij(2*ijlmn  ,ijsp)
     540              :               end if
     541              :             end do
     542              :           end do
     543              :         end do
     544              :       end do
     545              :     end do
     546              : 
     547              :   end do
     548              : 
     549              : ! Communication in case of distribution over atomic sites
     550         2188 :   if (paral_atom) then
     551         1692 :     call xgBlock_mpi_sum(xg_nonlop%Dij%self,comm=xg_nonlop%comm_atom)
     552              :   end if
     553              : 
     554         2188 :   call timab(tim_make_Dij,2,tsec)
     555              : 
     556         2188 :  end subroutine xg_nonlop_make_Dij
     557              : !!***
     558              : 
     559         2252 :  subroutine xg_nonlop_set_Dij_spin(xg_nonlop,isppol)
     560              : 
     561              :   integer,intent(in) :: isppol
     562              :   type(xg_nonlop_t),intent(inout) :: xg_nonlop
     563              : 
     564              :   integer :: shift,nlmn_max,nspinor,natom
     565              : 
     566         2252 :   nspinor  = xg_nonlop%nspinor
     567         2252 :   natom    = xg_nonlop%natom
     568         2252 :   nlmn_max = xg_nonlop%nlmn_max
     569              : 
     570         2252 :   if (isppol/=1) then ! isppol must be 1 or 2 if nspinor==1, and must be 1 of nspinor==2
     571           64 :     if (isppol/=2.or.nspinor/=1) then
     572            0 :       ABI_ERROR('wrong isppol')
     573              :     end if
     574              :   end if
     575              : 
     576         2252 :   shift=1+(isppol-1)*natom*nspinor*nlmn_max
     577         2252 :   call xg_setBlock(xg_nonlop%Dij,xg_nonlop%Dij_spin,nspinor*nlmn_max,nspinor*nlmn_max*natom,fcol=shift)
     578              : 
     579         2252 :  end subroutine xg_nonlop_set_Dij_spin
     580              : !!***
     581              : 
     582          138 :  subroutine xg_nonlop_make_Sij(xg_nonlop,pawtab,inv_sij)
     583              : 
     584              :   type(xg_nonlop_t),intent(inout) :: xg_nonlop
     585              :   type(pawtab_type),intent(in) :: pawtab(:)
     586              :   logical,optional,intent(in) :: inv_sij
     587              : 
     588              :   logical :: inv_sij_
     589              :   integer :: itypat, nlmn, nlmn_max, ntypat, shift
     590              :   integer :: ilmn, jlmn, j0lmn, jjlmn, ijlmn
     591          138 :   real(dp),pointer :: Sij_itypat_(:,:)
     592              :   real(dp) :: tsec(2)
     593              :   type(xg_t) :: work
     594              :   type(xgBlock_t) :: Sij_itypat,Sijm1_itypat
     595              : 
     596              : ! *************************************************************************
     597              : 
     598          138 :   call timab(tim_make_Sij,1,tsec)
     599              : 
     600          138 :   if (.not.xg_nonlop%paw) then
     601            0 :     ABI_ERROR('Not implemented with paw=False.')
     602              :   end if
     603              : 
     604          138 :   ntypat   = xg_nonlop%ntypat
     605          138 :   nlmn_max = xg_nonlop%nlmn_max
     606              : 
     607          138 :   call xg_init(xg_nonlop%Sij,SPACE_R,nlmn_max,nlmn_max*ntypat,xmpi_comm_self)
     608              : 
     609          138 :   inv_sij_ = .false.
     610          138 :   if (present(inv_sij)) inv_sij_ = inv_sij
     611              : 
     612          138 :   if (inv_sij_) then
     613          102 :     call xg_init(xg_nonlop%Sijm1,SPACE_R,nlmn_max,nlmn_max*ntypat,xmpi_comm_self)
     614              :   end if
     615              : 
     616          404 :   do itypat=1,ntypat
     617              : 
     618          266 :     nlmn=xg_nonlop%nlmn_ntypat(itypat)
     619              : 
     620          266 :     shift=1+(itypat-1)*nlmn_max
     621          266 :     call xg_setBlock(xg_nonlop%Sij,Sij_itypat,nlmn,nlmn,fcol=shift)
     622          266 :     call xgBlock_reverseMap(Sij_itypat,Sij_itypat_)
     623         2584 :     do jlmn=1,nlmn
     624         2318 :       j0lmn=jlmn*(jlmn-1)/2
     625         2318 :       jjlmn=j0lmn+jlmn
     626         2318 :       Sij_itypat_(jlmn,jlmn) = pawtab(itypat)%sij(jjlmn)
     627        12407 :       do ilmn=1,jlmn-1
     628         9823 :         ijlmn=j0lmn+ilmn
     629         9823 :         Sij_itypat_(ilmn,jlmn) = pawtab(itypat)%sij(ijlmn)
     630        12141 :         Sij_itypat_(jlmn,ilmn) = pawtab(itypat)%sij(ijlmn)
     631              :       end do
     632              :     end do
     633          404 :     if (inv_sij_) then
     634          207 :       call xg_init(work,SPACE_R,nlmn,nlmn,xmpi_comm_self)
     635          207 :       call xg_setBlock(xg_nonlop%Sijm1,Sijm1_itypat,nlmn,nlmn,fcol=shift)
     636          207 :       call xgBlock_invert_sy(Sijm1_itypat,work%self,xg_input=Sij_itypat)
     637          207 :       call xg_free(work)
     638              :     end if
     639              : 
     640              :   end do
     641              : 
     642          138 :   call timab(tim_make_Sij,2,tsec)
     643              : 
     644          138 :  end subroutine xg_nonlop_make_Sij
     645              : !!***
     646              : 
     647           24 :  subroutine xg_nonlop_destroy_ekb(xg_nonlop)
     648              : 
     649              :   type(xg_nonlop_t),intent(inout) :: xg_nonlop
     650              : 
     651              : ! *************************************************************************
     652              : 
     653           24 :   if (xg_nonlop%paw) then
     654            0 :     ABI_ERROR('Not implemented with paw=True.')
     655              :   end if
     656              : 
     657           24 :   call xg_free(xg_nonlop%ekb)
     658              : 
     659           24 :  end subroutine xg_nonlop_destroy_ekb
     660              : !!***
     661              : 
     662         2326 :  subroutine xg_nonlop_destroy_Dij(xg_nonlop)
     663              : 
     664              :   type(xg_nonlop_t),intent(inout) :: xg_nonlop
     665              : 
     666              : ! *************************************************************************
     667              : 
     668         2326 :   if (.not.xg_nonlop%paw) then
     669            0 :     ABI_ERROR('Not implemented with paw=False.')
     670              :   end if
     671              : 
     672         2326 :   call xg_free(xg_nonlop%Dij)
     673              : 
     674         2326 :  end subroutine xg_nonlop_destroy_Dij
     675              : !!***
     676              : 
     677          138 :  subroutine xg_nonlop_destroy_Sij(xg_nonlop)
     678              : 
     679              :   type(xg_nonlop_t),intent(inout) :: xg_nonlop
     680              : 
     681              : ! *************************************************************************
     682              : 
     683          138 :   if (.not.xg_nonlop%paw) then
     684            0 :     ABI_ERROR('Not implemented with paw=False.')
     685              :   end if
     686              : 
     687          138 :   call xg_free(xg_nonlop%Sij)
     688          138 :   call xg_free(xg_nonlop%Sijm1)
     689              : 
     690          138 :  end subroutine xg_nonlop_destroy_Sij
     691              : !!***
     692              : 
     693         2320 :  subroutine xg_nonlop_compute_projs(xg_nonlop)
     694              : 
     695              :   type(xg_nonlop_t),intent(inout) :: xg_nonlop
     696              : 
     697         2320 :   complex(dp),pointer :: projectors_k_(:,:)
     698         2320 :   real(dp),pointer :: projectors_k_real(:,:)
     699         2320 :   real(dp),pointer :: ffnl_gather_k_(:,:)
     700         2320 :   complex(dp),pointer :: ph3d_gather_k_(:,:)
     701         2320 :   real(dp),pointer :: ph3d_gather_k_real(:,:)
     702              : 
     703              :   integer :: shift_itypat,shift_itypat_nlmn,ntypat,nattyp_i,shift_ipw
     704              :   integer :: icol,ilmn,nlmn,il,ipw,ia,iatom,itypat
     705              :   real(dp) :: ffnl_ipw
     706              :   complex(dp) :: cil(4),ph3d_ipw,ctmp
     707              :   logical :: compute_gather
     708              : 
     709         2320 :   ntypat = xg_nonlop%ntypat
     710              : 
     711              : ! 4pi/sqrt(ucvol) * (-i)^l
     712         2320 :   cil(1) = ( 1.0_DP, 0.0_DP) * xg_nonlop%weight
     713         2320 :   cil(2) = ( 0.0_DP,-1.0_DP) * xg_nonlop%weight
     714         2320 :   cil(3) = (-1.0_DP, 0.0_DP) * xg_nonlop%weight
     715         2320 :   cil(4) = ( 0.0_DP, 1.0_DP) * xg_nonlop%weight
     716              : 
     717         2320 :   compute_gather = xg_nonlop%option==0
     718              : 
     719         2320 :   if (compute_gather) then
     720         2192 :     call xgBlock_zero(xg_nonlop%ffnl_gather_k%self)
     721         2192 :     call xgBlock_zero(xg_nonlop%ph3d_gather_k%self)
     722         2192 :     call xgBlock_reverseMap(xg_nonlop%ffnl_gather_k%self,ffnl_gather_k_)
     723              :   end if
     724              : 
     725         2320 :   shift_ipw = xg_nonlop%l_shift_npw_k(xg_nonlop%me_band+1)
     726              : 
     727         3654 :   select case(xg_nonlop%space_pw)
     728              : 
     729              :     case (SPACE_C)
     730              : 
     731         1334 :       call xgBlock_reverseMap(xg_nonlop%projectors_k%self,projectors_k_)
     732         1334 :       if (compute_gather) then
     733         1206 :         call xgBlock_reverseMap(xg_nonlop%ph3d_gather_k%self,ph3d_gather_k_)
     734              :       end if
     735              :       shift_itypat=0
     736              :       shift_itypat_nlmn=0
     737              :       !$omp parallel default (none) &
     738              :       !$omp& shared(xg_nonlop,ph3d_gather_k_,ffnl_gather_k_,projectors_k_), &
     739              :       !$omp& firstprivate(compute_gather,ntypat,shift_ipw,shift_itypat,shift_itypat_nlmn,cil), &
     740              :       !$omp& private(itypat,nattyp_i,nlmn,ia,ilmn,ipw,iatom,il,ph3d_ipw,ffnl_ipw,icol)
     741         4048 :       do itypat = 1, ntypat
     742         2714 :         nlmn = xg_nonlop%nlmn_ntypat(itypat)
     743         2714 :         nattyp_i = xg_nonlop%nattyp(itypat)
     744         4048 :         if (nattyp_i>0) then
     745              :           !! projectors = 4pi/sqrt(ucvol) * (-i)^l * conj(ph3d) * ffnl
     746              :           !$omp do collapse(3)
     747         5350 :           do ia = 1, nattyp_i
     748        30478 :             do ilmn=1,nlmn
     749      2192660 :               do ipw=1,xg_nonlop%npw_k
     750      2164832 :                 iatom = ia + shift_itypat
     751      2164832 :                 il=mod(xg_nonlop%indlmn(1,ilmn,itypat),4)+1
     752      2164832 :                 ph3d_ipw = cmplx( xg_nonlop%ph3d_k(1,ipw,iatom), xg_nonlop%ph3d_k(2,ipw,iatom), kind=DP)
     753      2164832 :                 ffnl_ipw = xg_nonlop%ffnl_k(ipw, 1, ilmn, itypat)
     754              :                 !
     755      2164832 :                 if (compute_gather) then
     756      2096544 :                   ph3d_gather_k_(ipw+shift_ipw,iatom) = ph3d_ipw
     757      2096544 :                   ffnl_gather_k_(ipw+shift_ipw,ilmn+(itypat-1)*xg_nonlop%nlmn_max) = ffnl_ipw
     758              :                 end if
     759              :                 !
     760      2164832 :                 icol = ilmn + (ia-1)*nlmn + shift_itypat_nlmn
     761      2189960 :                 projectors_k_(ipw,icol) = cil(il) * conjg(ph3d_ipw) * ffnl_ipw
     762              :               end do
     763              :             end do
     764              :           end do
     765              :           !$omp end do
     766         2650 :           shift_itypat      = shift_itypat      + nattyp_i
     767         2650 :           shift_itypat_nlmn = shift_itypat_nlmn + nattyp_i*nlmn
     768              :         end if
     769              :       end do
     770              :       !$omp end parallel
     771              : 
     772              :     case (SPACE_CR)
     773              : 
     774          986 :       call xgBlock_reverseMap(xg_nonlop%projectors_k%self,projectors_k_real)
     775          986 :       if (compute_gather) then
     776          986 :         call xgBlock_reverseMap(xg_nonlop%ph3d_gather_k%self,ph3d_gather_k_real)
     777              :       end if
     778              :       shift_itypat=0
     779              :       shift_itypat_nlmn=0
     780              :       !$omp parallel default (none) &
     781              :       !$omp& shared(xg_nonlop,ph3d_gather_k_real,ffnl_gather_k_,projectors_k_real), &
     782              :       !$omp& firstprivate(compute_gather,ntypat,shift_ipw,shift_itypat,shift_itypat_nlmn,cil), &
     783              :       !$omp& private(itypat,nattyp_i,nlmn,ia,ilmn,ipw,iatom,il,ph3d_ipw,ffnl_ipw,icol,ctmp)
     784         2948 :       do itypat = 1, ntypat
     785         1962 :         nlmn = xg_nonlop%nlmn_ntypat(itypat)
     786         1962 :         nattyp_i = xg_nonlop%nattyp(itypat)
     787         2948 :         if (nattyp_i>0) then
     788              :           !! projectors = 4pi/sqrt(ucvol) * (-i)^l * conj(ph3d) * ffnl
     789              :           !$omp do collapse(3)
     790         3934 :           do ia = 1, nattyp_i
     791        34950 :             do ilmn=1,nlmn
     792       952300 :               do ipw=1,xg_nonlop%npw_k
     793       919312 :                 iatom = ia + shift_itypat
     794       919312 :                 il=mod(xg_nonlop%indlmn(1,ilmn,itypat),4)+1
     795       919312 :                 ph3d_ipw = cmplx( xg_nonlop%ph3d_k(1,ipw,iatom), xg_nonlop%ph3d_k(2,ipw,iatom), kind=DP)
     796       919312 :                 ffnl_ipw = xg_nonlop%ffnl_k(ipw, 1, ilmn, itypat)
     797              :                 !
     798       919312 :                 if (compute_gather) then
     799       919312 :                   ph3d_gather_k_real(2*(ipw+shift_ipw)-1,iatom) = dble(ph3d_ipw)
     800       919312 :                   ph3d_gather_k_real(2*(ipw+shift_ipw)  ,iatom) = dimag(ph3d_ipw)
     801       919312 :                   ffnl_gather_k_(ipw+shift_ipw,ilmn+(itypat-1)*xg_nonlop%nlmn_max) = ffnl_ipw
     802              :                 end if
     803              :                 !
     804       919312 :                 ctmp = cil(il) * conjg(ph3d_ipw) * ffnl_ipw
     805       919312 :                 icol = ilmn + (ia-1)*nlmn + shift_itypat_nlmn
     806       919312 :                 projectors_k_real(2*ipw-1,icol) = dble(ctmp)
     807       950328 :                 projectors_k_real(2*ipw  ,icol) = dimag(ctmp)
     808              :               end do
     809              :             end do
     810              :           end do
     811              :           !$omp end do
     812         1962 :           shift_itypat      = shift_itypat      + nattyp_i
     813         1962 :           shift_itypat_nlmn = shift_itypat_nlmn + nattyp_i*nlmn
     814              :         end if
     815              :       end do
     816              :       !$omp end parallel
     817              : 
     818              :     case default
     819         2320 :       ABI_ERROR("Wrong space")
     820              : 
     821              :   end select
     822              : 
     823         2320 :   if (compute_gather) then
     824         2192 :     call xgBlock_mpi_sum(xg_nonlop%ffnl_gather_k%self,comm=xg_nonlop%comm_band)
     825         2192 :     call xgBlock_mpi_sum(xg_nonlop%ph3d_gather_k%self,comm=xg_nonlop%comm_band)
     826              :   end if
     827              : 
     828         2320 :  end subroutine xg_nonlop_compute_projs
     829              : !!***
     830              : 
     831        18300 :  subroutine xg_nonlop_compute_projs_deriv_atom(xg_nonlop,projs_deriv_atom)
     832              : 
     833              :   type(xgBlock_t),intent(inout) :: projs_deriv_atom
     834              :   type(xg_nonlop_t),intent(in) :: xg_nonlop
     835              : 
     836        18300 :   complex(dp),pointer :: projectors_k_(:,:)
     837        18300 :   complex(dp),pointer :: projectors_deriv_atom_k_(:,:)
     838        18300 :   real(dp),pointer :: projectors_k_real(:,:)
     839        18300 :   real(dp),pointer :: projectors_deriv_atom_k_real(:,:)
     840              : 
     841              :   integer :: shift_itypat_nlmn,shift_itypat_3nlmn,ntypat,nattyp_i
     842              :   integer :: icol,icol_deriv,ilmn,nlmn,ipw,ia,itypat,idir
     843              :   complex(dp) :: ctmp
     844              :   real(dp) :: tmp,proj_deriv_ipw_re,proj_deriv_ipw_im
     845              : 
     846        18300 :   if (.not.associated(xg_nonlop%projectors_k)) then
     847            0 :     ABI_ERROR('projectors_k should be associated')
     848              :   end if
     849              : 
     850        18300 :   if (rows(projs_deriv_atom)/=xg_nonlop%npw_k) then
     851            0 :     ABI_ERROR('rows(projs_deriv_atom)/=npw_k')
     852              :   end if
     853        18300 :   if (cols(projs_deriv_atom)/=3*xg_nonlop%cprjdim) then
     854            0 :     ABI_ERROR('cols(projs_deriv_atom)/=3*cprjdim')
     855              :   end if
     856              : 
     857        18300 :   ntypat = xg_nonlop%ntypat
     858              : 
     859        28903 :   select case(xg_nonlop%space_pw)
     860              : 
     861              :     case (SPACE_C)
     862              : 
     863        10603 :       call xgBlock_reverseMap(xg_nonlop%projectors_k%self,projectors_k_)
     864        10603 :       call xgBlock_reverseMap(projs_deriv_atom,projectors_deriv_atom_k_)
     865        10603 :       shift_itypat_nlmn=0
     866        10603 :       shift_itypat_3nlmn=0
     867              :       !$omp parallel default (none) &
     868              :       !$omp& shared(xg_nonlop,projectors_k_,projectors_deriv_atom_k_), &
     869              :       !$omp& firstprivate(ntypat,shift_itypat_nlmn,shift_itypat_3nlmn), &
     870              :       !$omp& private(itypat,nattyp_i,nlmn,ia,ilmn,ipw,idir,icol,icol_deriv,ctmp)
     871        32376 :       do itypat = 1, ntypat
     872        21773 :         nlmn = xg_nonlop%nlmn_ntypat(itypat)
     873        21773 :         nattyp_i = xg_nonlop%nattyp(itypat)
     874        32376 :         if (nattyp_i>0) then
     875              :           !! projectors_deriv_atom(k+G) = -i * 2pi * (k+G)_idir * projectors(k+G)
     876              :           !$omp do collapse(4)
     877        42379 :           do ia = 1, nattyp_i
     878       230887 :             do ilmn=1,nlmn
     879     16228673 :               do ipw=1,xg_nonlop%npw_k
     880     64264280 :                 do idir=1,3
     881     48056829 :                   icol = ilmn + (ia-1)*nlmn + shift_itypat_nlmn
     882     48056829 :                   ctmp = ( 0.0_DP, -1.0_DP) * two_pi * xg_nonlop%kpg_k(ipw,idir)
     883     48056829 :                   icol_deriv = ilmn + (idir-1)*nlmn + (ia-1)*3*nlmn + shift_itypat_3nlmn
     884     64075772 :                   projectors_deriv_atom_k_(ipw,icol_deriv) = ctmp * projectors_k_(ipw,icol)
     885              :                 end do
     886              :               end do
     887              :             end do
     888              :           end do
     889              :           !$omp end do
     890        21157 :           shift_itypat_nlmn  = shift_itypat_nlmn  + nattyp_i*nlmn
     891        21157 :           shift_itypat_3nlmn = shift_itypat_3nlmn + nattyp_i*3*nlmn
     892              :         end if
     893              :       end do
     894              :       !$omp end parallel
     895              : 
     896              :     case (SPACE_CR)
     897              : 
     898         7697 :       call xgBlock_reverseMap(xg_nonlop%projectors_k%self,projectors_k_real)
     899         7697 :       call xgBlock_reverseMap(projs_deriv_atom,projectors_deriv_atom_k_real)
     900         7697 :       shift_itypat_nlmn=0
     901         7697 :       shift_itypat_3nlmn=0
     902              :       !$omp parallel default (none) &
     903              :       !$omp& shared(xg_nonlop,projectors_k_real,projectors_deriv_atom_k_real), &
     904              :       !$omp& firstprivate(ntypat,shift_itypat_nlmn,shift_itypat_3nlmn), &
     905              :       !$omp& private(itypat,nattyp_i,nlmn,ia,ilmn,ipw,idir,icol,icol_deriv,tmp), &
     906              :       !$omp& private(proj_deriv_ipw_re,proj_deriv_ipw_im)
     907        23074 :       do itypat = 1, ntypat
     908        15377 :         nlmn = xg_nonlop%nlmn_ntypat(itypat)
     909        15377 :         nattyp_i = xg_nonlop%nattyp(itypat)
     910        23074 :         if (nattyp_i>0) then
     911              :           !! projectors_deriv_atom(k+G) = -i * 2pi * (k+G)_idir * projectors(k+G)
     912              :           !$omp do collapse(4)
     913        30771 :           do ia = 1, nattyp_i
     914       220063 :             do ilmn=1,nlmn
     915      6104064 :               do ipw=1,xg_nonlop%npw_k
     916     23786804 :                 do idir=1,3
     917     17698134 :                   icol = ilmn + (ia-1)*nlmn + shift_itypat_nlmn
     918     17698134 :                   tmp  = - two_pi * xg_nonlop%kpg_k(ipw,idir)
     919     17698134 :                   icol_deriv = ilmn + (idir-1)*nlmn + (ia-1)*3*nlmn + shift_itypat_3nlmn
     920              :                   !! Re(projectors_deriv_atom) =  2pi * (k+G)_idir * Im(projectors)
     921              :                   !! Im(projectors_deriv_atom) = -2pi * (k+G)_idir * Re(projectors)
     922     17698134 :                   proj_deriv_ipw_re = - tmp * projectors_k_real(2*ipw  ,icol)
     923     17698134 :                   proj_deriv_ipw_im =   tmp * projectors_k_real(2*ipw-1,icol)
     924     17698134 :                   projectors_deriv_atom_k_real(2*ipw-1,icol_deriv) = proj_deriv_ipw_re
     925     23597512 :                   projectors_deriv_atom_k_real(2*ipw  ,icol_deriv) = proj_deriv_ipw_im
     926              :                 end do
     927              :               end do
     928              :             end do
     929              :           end do
     930              :           !$omp end do
     931        15377 :           shift_itypat_nlmn  = shift_itypat_nlmn  + nattyp_i*nlmn
     932        15377 :           shift_itypat_3nlmn = shift_itypat_3nlmn + nattyp_i*3*nlmn
     933              :         end if
     934              :       end do
     935              :       !$omp end parallel
     936              : 
     937              :     case default
     938        18300 :       ABI_ERROR("Wrong space")
     939              : 
     940              :   end select
     941              : 
     942        18300 :  end subroutine xg_nonlop_compute_projs_deriv_atom
     943              : !!***
     944              : 
     945         1140 :  subroutine xg_nonlop_compute_projs_deriv_stress(xg_nonlop,projs_deriv_stress)
     946              : 
     947              :   type(xgBlock_t),intent(inout) :: projs_deriv_stress
     948              :   type(xg_nonlop_t),intent(in) :: xg_nonlop
     949              : 
     950         1140 :   complex(dp),pointer :: projectors_k_(:,:)
     951         1140 :   complex(dp),pointer :: projectors_deriv_stress_k_(:,:)
     952         1140 :   real(dp),pointer :: projectors_k_real(:,:)
     953         1140 :   real(dp),pointer :: projectors_deriv_stress_k_real(:,:)
     954              : 
     955              :   integer :: shift_itypat,shift_itypat_nlmn,shift_itypat_6nlmn,ntypat,nattyp_i
     956              :   integer :: iatom,icol_shift,icol_deriv,ilmn,nlmn,ipw,ia,itypat,idir,il
     957              :   complex(dp) :: ctmp(3),cil(4),ph3d_ipw,cipw
     958              :   real(dp) :: ffnl_ipw(3)
     959              : 
     960         1140 :   if (rows(projs_deriv_stress)/=xg_nonlop%npw_k) then
     961            0 :     ABI_ERROR('rows(projs_deriv_atom)/=npw_k')
     962              :   end if
     963         1140 :   if (cols(projs_deriv_stress)/=6*xg_nonlop%cprjdim) then
     964            0 :     ABI_ERROR('cols(projs_deriv_stress)/=6*cprjdim')
     965              :   end if
     966              : 
     967         1140 :   ntypat = xg_nonlop%ntypat
     968              : 
     969              : ! 4pi/sqrt(ucvol) * (-i)^l
     970         1140 :   cil(1) = ( 1.0_DP, 0.0_DP) * xg_nonlop%weight
     971         1140 :   cil(2) = ( 0.0_DP,-1.0_DP) * xg_nonlop%weight
     972         1140 :   cil(3) = (-1.0_DP, 0.0_DP) * xg_nonlop%weight
     973         1140 :   cil(4) = ( 0.0_DP, 1.0_DP) * xg_nonlop%weight
     974              : 
     975         1871 :   select case(xg_nonlop%space_pw)
     976              : 
     977              :     case (SPACE_C)
     978              : 
     979          731 :       call xgBlock_reverseMap(xg_nonlop%projectors_k%self,projectors_k_)
     980          731 :       call xgBlock_reverseMap(projs_deriv_stress,projectors_deriv_stress_k_)
     981          731 :       shift_itypat=0
     982          731 :       shift_itypat_nlmn=0
     983          731 :       shift_itypat_6nlmn=0
     984              :       !$omp parallel default (none) &
     985              :       !$omp& shared(xg_nonlop,projectors_k_,projectors_deriv_stress_k_), &
     986              :       !$omp& firstprivate(cil,ntypat,shift_itypat,shift_itypat_nlmn,shift_itypat_6nlmn), &
     987              :       !$omp& private(il,iatom,itypat,nattyp_i,nlmn,ia,ilmn,ipw,idir,icol_shift,icol_deriv), &
     988              :       !$omp& private(ctmp,ph3d_ipw,ffnl_ipw)
     989         2176 :       do itypat = 1, ntypat
     990         1445 :         nlmn = xg_nonlop%nlmn_ntypat(itypat)
     991         1445 :         nattyp_i = xg_nonlop%nattyp(itypat)
     992         2176 :         if (nattyp_i>0) then
     993              :           !! projectors_deriv_stress(k+G)_ab = 4pi/sqrt(ucvol) * (-i)^l * conj(ph3d) * (-(k+G)_b) * d/d(K_a)[ffnl_deriv(k+G)]
     994              :           !$omp do collapse(3)
     995         2891 :           do ia = 1, nattyp_i
     996        17279 :             do ilmn=1,nlmn
     997      1381698 :               do ipw=1,xg_nonlop%npw_k
     998      1365832 :                 iatom = ia + shift_itypat
     999      1365832 :                 il=mod(xg_nonlop%indlmn(1,ilmn,itypat),4)+1
    1000      1365832 :                 ph3d_ipw = cmplx( xg_nonlop%ph3d_k(1,ipw,iatom), xg_nonlop%ph3d_k(2,ipw,iatom), kind=DP)
    1001      5463328 :                 ffnl_ipw(:) = xg_nonlop%ffnl_k(ipw, 2:4, ilmn, itypat)
    1002      5463328 :                 ctmp(:) = - cil(il) * conjg(ph3d_ipw) * xg_nonlop%kpg_k(ipw,:)
    1003      1365832 :                 icol_shift = ilmn + (ia-1)*6*nlmn + shift_itypat_6nlmn
    1004              :                 ! diagonal part
    1005      5463328 :                 do idir=1,3
    1006      4097496 :                   icol_deriv = icol_shift + (idir-1)*nlmn
    1007      5463328 :                   projectors_deriv_stress_k_(ipw,icol_deriv) = ctmp(idir) * ffnl_ipw(idir)
    1008              :                 end do
    1009              :                 ! off-diagonal part (which is symmetric)
    1010      5463328 :                 ctmp(:) = half*ctmp(:)
    1011      1365832 :                 icol_deriv = icol_shift + (4-1)*nlmn
    1012      1365832 :                 projectors_deriv_stress_k_(ipw,icol_deriv) = ctmp(2) * ffnl_ipw(3) + ctmp(3) * ffnl_ipw(2)
    1013      1365832 :                 icol_deriv = icol_shift + (5-1)*nlmn
    1014      1365832 :                 projectors_deriv_stress_k_(ipw,icol_deriv) = ctmp(1) * ffnl_ipw(3) + ctmp(3) * ffnl_ipw(1)
    1015      1365832 :                 icol_deriv = icol_shift + (6-1)*nlmn
    1016      1380220 :                 projectors_deriv_stress_k_(ipw,icol_deriv) = ctmp(1) * ffnl_ipw(2) + ctmp(2) * ffnl_ipw(1)
    1017              :               end do
    1018              :             end do
    1019              :           end do
    1020              :           !$omp end do
    1021         1413 :           shift_itypat       = shift_itypat       + nattyp_i
    1022         1413 :           shift_itypat_nlmn  = shift_itypat_nlmn  + nattyp_i*nlmn
    1023         1413 :           shift_itypat_6nlmn = shift_itypat_6nlmn + nattyp_i*6*nlmn
    1024              :         end if
    1025              :       end do
    1026              :       !$omp end parallel
    1027              : 
    1028              :     case (SPACE_CR)
    1029              : 
    1030          409 :       call xgBlock_reverseMap(xg_nonlop%projectors_k%self,projectors_k_real)
    1031          409 :       call xgBlock_reverseMap(projs_deriv_stress,projectors_deriv_stress_k_real)
    1032          409 :       shift_itypat=0
    1033          409 :       shift_itypat_nlmn=0
    1034          409 :       shift_itypat_6nlmn=0
    1035              :       !$omp parallel default (none) &
    1036              :       !$omp& shared(xg_nonlop,projectors_k_real,projectors_deriv_stress_k_real), &
    1037              :       !$omp& firstprivate(cil,ntypat,shift_itypat,shift_itypat_nlmn,shift_itypat_6nlmn), &
    1038              :       !$omp& private(il,iatom,itypat,nattyp_i,nlmn,ia,ilmn,ipw,idir,icol_shift,icol_deriv), &
    1039              :       !$omp& private(ctmp,cipw,ph3d_ipw,ffnl_ipw)
    1040         1210 :       do itypat = 1, ntypat
    1041          801 :         nlmn = xg_nonlop%nlmn_ntypat(itypat)
    1042          801 :         nattyp_i = xg_nonlop%nattyp(itypat)
    1043         1210 :         if (nattyp_i>0) then
    1044              :           !! projectors_deriv_stress(k+G)_ab = 4pi/sqrt(ucvol) * (-i)^l * conj(ph3d) * (-(k+G)_b) * d/d(K_a)[ffnl_deriv(k+G)]
    1045              :           !$omp do collapse(3)
    1046         1619 :           do ia = 1, nattyp_i
    1047        14519 :             do ilmn=1,nlmn
    1048       454776 :               do ipw=1,xg_nonlop%npw_k
    1049       441058 :                 iatom = ia + shift_itypat
    1050       441058 :                 il=mod(xg_nonlop%indlmn(1,ilmn,itypat),4)+1
    1051       441058 :                 ph3d_ipw = cmplx( xg_nonlop%ph3d_k(1,ipw,iatom), xg_nonlop%ph3d_k(2,ipw,iatom), kind=DP)
    1052      1764232 :                 ffnl_ipw(:) = xg_nonlop%ffnl_k(ipw, 2:4, ilmn, itypat)
    1053      1764232 :                 ctmp(:) = - cil(il) * conjg(ph3d_ipw) * xg_nonlop%kpg_k(ipw,:)
    1054       441058 :                 icol_shift = ilmn + (ia-1)*6*nlmn + shift_itypat_6nlmn
    1055              :                 ! diagonal part
    1056      1764232 :                 do idir=1,3
    1057      1323174 :                   icol_deriv = icol_shift + (idir-1)*nlmn
    1058      1323174 :                   projectors_deriv_stress_k_real(2*ipw-1,icol_deriv) =  dble(ctmp(idir)) * ffnl_ipw(idir)
    1059      1764232 :                   projectors_deriv_stress_k_real(2*ipw  ,icol_deriv) = dimag(ctmp(idir)) * ffnl_ipw(idir)
    1060              :                 end do
    1061              :                 ! off-diagonal part (which is symmetric)
    1062      1764232 :                 ctmp(:) = half*ctmp(:)
    1063              : 
    1064       441058 :                 icol_deriv = icol_shift + (4-1)*nlmn
    1065       441058 :                 cipw = ctmp(2) * ffnl_ipw(3) + ctmp(3) * ffnl_ipw(2)
    1066       441058 :                 projectors_deriv_stress_k_real(2*ipw-1,icol_deriv) =  dble(cipw)
    1067       441058 :                 projectors_deriv_stress_k_real(2*ipw  ,icol_deriv) = dimag(cipw)
    1068              : 
    1069       441058 :                 icol_deriv = icol_shift + (5-1)*nlmn
    1070       441058 :                 cipw = ctmp(1) * ffnl_ipw(3) + ctmp(3) * ffnl_ipw(1)
    1071       441058 :                 projectors_deriv_stress_k_real(2*ipw-1,icol_deriv) =  dble(cipw)
    1072       441058 :                 projectors_deriv_stress_k_real(2*ipw  ,icol_deriv) = dimag(cipw)
    1073              : 
    1074       441058 :                 icol_deriv = icol_shift + (6-1)*nlmn
    1075       441058 :                 cipw = ctmp(1) * ffnl_ipw(2) + ctmp(2) * ffnl_ipw(1)
    1076       441058 :                 projectors_deriv_stress_k_real(2*ipw-1,icol_deriv) =  dble(cipw)
    1077       453958 :                 projectors_deriv_stress_k_real(2*ipw  ,icol_deriv) = dimag(cipw)
    1078              : 
    1079              :               end do
    1080              :             end do
    1081              :           end do
    1082              :           !$omp end do
    1083          801 :           shift_itypat       = shift_itypat       + nattyp_i
    1084          801 :           shift_itypat_nlmn  = shift_itypat_nlmn  + nattyp_i*nlmn
    1085          801 :           shift_itypat_6nlmn = shift_itypat_6nlmn + nattyp_i*6*nlmn
    1086              :         end if
    1087              :       end do
    1088              :       !$omp end parallel
    1089              : 
    1090              :     case default
    1091         1140 :       ABI_ERROR("Wrong space")
    1092              : 
    1093              :   end select
    1094              : 
    1095         1140 :  end subroutine xg_nonlop_compute_projs_deriv_stress
    1096              : !!***
    1097              : 
    1098       865236 :  subroutine xg_nonlop_compute_projs_otf(xg_nonlop,projs_otf,index_mpi)
    1099              : 
    1100              :   integer,intent(in) :: index_mpi
    1101              :   type(xg_nonlop_t),intent(in) :: xg_nonlop
    1102              :   type(xgBlock_t),intent(inout) :: projs_otf
    1103              : 
    1104       865236 :   complex(dp),pointer :: projectors_k_(:,:)
    1105       865236 :   real(dp),pointer :: projectors_k_real(:,:)
    1106       865236 :   real(dp),pointer :: ffnl_gather_k_(:,:)
    1107       865236 :   complex(dp),pointer :: ph3d_gather_k_(:,:)
    1108       865236 :   real(dp),pointer :: ph3d_gather_k_real(:,:)
    1109              : 
    1110              :   integer :: nmpi,npw_k
    1111              :   integer :: shift_itypat,shift_itypat_nlmn,ntypat,nattyp_i,shift_ipw
    1112              :   integer :: icol,ilmn,nlmn,il,ipw,ia,iatom,itypat
    1113              :   real(dp) :: ffnl_ipw,ph3d_ipw_r(2)
    1114              :   complex(dp) :: cil(4),ph3d_ipw,ctmp
    1115              : 
    1116       865236 :   if (xg_nonlop%option/=0) then
    1117            0 :     ABI_ERROR('xg_nonlop%option/=0')
    1118              :   end if
    1119              : 
    1120       865236 :   nmpi = xmpi_comm_size(xg_nonlop%comm_band)
    1121       865236 :   if (index_mpi<0.or.index_mpi>nmpi-1) then
    1122            0 :     ABI_ERROR('index_mpi should be between 0 and size(comm_band)-1')
    1123              :   end if
    1124              : 
    1125       865236 :   npw_k = xg_nonlop%l_npw_k(index_mpi+1)
    1126       865236 :   shift_ipw = xg_nonlop%l_shift_npw_k(index_mpi+1)
    1127              : 
    1128       865236 :   if (rows(projs_otf)/=npw_k) then
    1129            0 :     ABI_ERROR('rows(projs_otf)/=npw_k!')
    1130              :   end if
    1131       865236 :   if (cols(projs_otf)/=xg_nonlop%cprjdim) then
    1132            0 :     ABI_ERROR('cols(projs_otf)/=cprjdim!')
    1133              :   end if
    1134              : 
    1135       865236 :   ntypat = xg_nonlop%ntypat
    1136              : 
    1137              : ! 4pi/sqrt(ucvol) * (-i)^l
    1138       865236 :   cil(1) = ( 1.0_DP, 0.0_DP) * xg_nonlop%weight
    1139       865236 :   cil(2) = ( 0.0_DP,-1.0_DP) * xg_nonlop%weight
    1140       865236 :   cil(3) = (-1.0_DP, 0.0_DP) * xg_nonlop%weight
    1141       865236 :   cil(4) = ( 0.0_DP, 1.0_DP) * xg_nonlop%weight
    1142              : 
    1143       865236 :   call xgBlock_reverseMap(xg_nonlop%ffnl_gather_k%self,ffnl_gather_k_)
    1144              : 
    1145      1273380 :   select case(xg_nonlop%space_pw)
    1146              : 
    1147              :     case (SPACE_C)
    1148              : 
    1149       408144 :       call xgBlock_reverseMap(projs_otf,projectors_k_)
    1150       408144 :       call xgBlock_reverseMap(xg_nonlop%ph3d_gather_k%self,ph3d_gather_k_)
    1151       408144 :       shift_itypat=0
    1152       408144 :       shift_itypat_nlmn=0
    1153              :       !$omp parallel default (none) &
    1154              :       !$omp& shared(xg_nonlop,ph3d_gather_k_,ffnl_gather_k_,projectors_k_), &
    1155              :       !$omp& firstprivate(ntypat,npw_k,shift_ipw,shift_itypat,shift_itypat_nlmn,cil), &
    1156              :       !$omp& private(itypat,nattyp_i,nlmn,ia,ilmn,ipw,iatom,il,ph3d_ipw,ffnl_ipw,icol)
    1157      1224432 :       do itypat = 1, ntypat
    1158       816288 :         nlmn = xg_nonlop%nlmn_ntypat(itypat)
    1159       816288 :         nattyp_i = xg_nonlop%nattyp(itypat)
    1160      1224432 :         if (nattyp_i>0) then
    1161              :           !! projectors = 4pi/sqrt(ucvol)* conj(ph3d) * ffnl * (-i)^l
    1162              :           !$omp do collapse(3)
    1163      1632576 :           do ia = 1, nattyp_i
    1164      8162880 :             do ilmn=1,nlmn
    1165    239950512 :               do ipw=1,npw_k
    1166    232603920 :                 iatom = ia + shift_itypat
    1167    232603920 :                 il=mod(xg_nonlop%indlmn(1,ilmn,itypat),4)+1
    1168    232603920 :                 ph3d_ipw = ph3d_gather_k_(ipw+shift_ipw,iatom)
    1169    232603920 :                 ffnl_ipw = ffnl_gather_k_(ipw+shift_ipw,ilmn+(itypat-1)*xg_nonlop%nlmn_max)
    1170              :                 !
    1171    232603920 :                 icol = ilmn + (ia-1)*nlmn + shift_itypat_nlmn
    1172    239134224 :                 projectors_k_(ipw,icol) = cil(il) * conjg(ph3d_ipw) * ffnl_ipw
    1173              :               end do
    1174              :             end do
    1175              :           end do
    1176              :           !$omp end do
    1177       816288 :           shift_itypat      = shift_itypat      + nattyp_i
    1178       816288 :           shift_itypat_nlmn = shift_itypat_nlmn + nattyp_i*nlmn
    1179              :         end if
    1180              :       end do
    1181              :       !$omp end parallel
    1182              : 
    1183              :     case(SPACE_CR)
    1184              : 
    1185       457092 :       call xgBlock_reverseMap(projs_otf,projectors_k_real)
    1186       457092 :       call xgBlock_reverseMap(xg_nonlop%ph3d_gather_k%self,ph3d_gather_k_real)
    1187       457092 :       shift_itypat=0
    1188       457092 :       shift_itypat_nlmn=0
    1189              :       !$omp parallel default (none) &
    1190              :       !$omp& shared(xg_nonlop,ph3d_gather_k_real,ffnl_gather_k_,projectors_k_real), &
    1191              :       !$omp& firstprivate(ntypat,npw_k,shift_ipw,shift_itypat,shift_itypat_nlmn,cil), &
    1192              :       !$omp& private(itypat,nattyp_i,nlmn,ia,ilmn,ipw,iatom,il,ph3d_ipw_r,ffnl_ipw,icol,ctmp)
    1193      1371276 :       do itypat = 1, ntypat
    1194       914184 :         nlmn = xg_nonlop%nlmn_ntypat(itypat)
    1195       914184 :         nattyp_i = xg_nonlop%nattyp(itypat)
    1196      1371276 :         if (nattyp_i>0) then
    1197              :           !! projectors = 4pi/sqrt(ucvol)* conj(ph3d) * ffnl * (-i)^l
    1198              :           !$omp do collapse(3)
    1199      1828368 :           do ia = 1, nattyp_i
    1200     14977548 :             do ilmn=1,nlmn
    1201    247695219 :               do ipw=1,npw_k
    1202    233631855 :                 iatom = ia + shift_itypat
    1203    233631855 :                 il=mod(xg_nonlop%indlmn(1,ilmn,itypat),4)+1
    1204    233631855 :                 ph3d_ipw_r(1) = ph3d_gather_k_real(2*(ipw+shift_ipw)-1,iatom)
    1205    233631855 :                 ph3d_ipw_r(2) = ph3d_gather_k_real(2*(ipw+shift_ipw)  ,iatom)
    1206    233631855 :                 ffnl_ipw = ffnl_gather_k_(ipw+shift_ipw,ilmn+(itypat-1)*xg_nonlop%nlmn_max)
    1207              :                 !
    1208    233631855 :                 ctmp = cmplx( ph3d_ipw_r(1), ph3d_ipw_r(2), kind=DP)
    1209    233631855 :                 ctmp = cil(il) * conjg(ctmp) * ffnl_ipw
    1210    233631855 :                 icol = ilmn + (ia-1)*nlmn + shift_itypat_nlmn
    1211    233631855 :                 projectors_k_real(2*ipw-1,icol) = dble(ctmp)
    1212    246781035 :                 projectors_k_real(2*ipw  ,icol) = dimag(ctmp)
    1213              :               end do
    1214              :             end do
    1215              :           end do
    1216              :           !$omp end do
    1217       914184 :           shift_itypat      = shift_itypat      + nattyp_i
    1218       914184 :           shift_itypat_nlmn = shift_itypat_nlmn + nattyp_i*nlmn
    1219              :         end if
    1220              :       end do
    1221              :       !$omp end parallel
    1222              : 
    1223              :     case default
    1224       865236 :       ABI_ERROR("Wrong space")
    1225              : 
    1226              :   end select
    1227              : 
    1228       865236 :  end subroutine xg_nonlop_compute_projs_otf
    1229              : !!***
    1230              : 
    1231        18244 :  subroutine xg_nonlop_make_k(xg_nonlop,ikpt,istwf_k,me_g0,me_g0_fft,npw_k,ffnl_k,ph3d_k,kpg_k,compute_proj,&
    1232              :      compute_invS_approx,compute_gram)
    1233              : 
    1234              :   type(xg_nonlop_t),intent(inout) :: xg_nonlop
    1235              : 
    1236              :   logical ,intent(in) :: compute_proj
    1237              :   integer ,intent(in) :: ikpt
    1238              :   integer ,intent(in) :: istwf_k
    1239              :   integer, intent(in) :: me_g0
    1240              :   integer, intent(in) :: me_g0_fft
    1241              :   integer, intent(in) :: npw_k
    1242              :   real(dp), intent(in), target :: ffnl_k(:,:,:,:)
    1243              :   real(dp), intent(in), target :: ph3d_k(:,:,:)
    1244              :   real(dp), intent(in), target :: kpg_k(:,:)
    1245              :   logical ,optional,intent(in) :: compute_invS_approx
    1246              :   logical ,optional,intent(in) :: compute_gram
    1247              : 
    1248              :   logical :: compute_gram_,compute_invS_approx_
    1249        18244 :   real(dp),pointer :: gram_proj_k_(:,:),Sijm1_(:,:)
    1250              :   integer :: ierr, iblock, shift, shiftc, shift_sij, shift_itypat, itypat, ilmn, jlmn, nlmn, nlmn_max, ia
    1251              :   integer :: cplex,nattyp_i,ntypat,ncols,nmpi,me_g0_loc,me_g0_fft_loc,space_cprj
    1252              :   !integer :: cols,cond
    1253              :   real(dp) :: tsec(2)
    1254              :   type(xg_t) :: work
    1255              :   type(xgBlock_t) :: projs,invSij_approx_k_itypat,Sijm1_itypat
    1256              : 
    1257              : ! *************************************************************************
    1258              : 
    1259        18244 :   call timab(tim_make_k,1,tsec)
    1260              : 
    1261        18244 :   me_g0_loc = -1
    1262        18244 :   me_g0_fft_loc = -1
    1263        18244 :   if (istwf_k==1) then
    1264        10357 :     xg_nonlop%cplex=2
    1265        10357 :     xg_nonlop%space_pw=SPACE_C
    1266        10357 :     xg_nonlop%space_cprj=SPACE_C
    1267              :   else ! istwf_k>1
    1268         7887 :     xg_nonlop%cplex=1
    1269         7887 :     xg_nonlop%space_pw=SPACE_CR
    1270         7887 :     xg_nonlop%space_cprj=SPACE_R
    1271         7887 :     me_g0_loc = 0
    1272         7887 :     me_g0_fft_loc = 0
    1273         7887 :     if (istwf_k==2.and.me_g0==1) then
    1274          431 :       me_g0_loc = me_g0
    1275          431 :       me_g0_fft_loc = me_g0_fft
    1276              :     end if
    1277              :   end if
    1278              : 
    1279        18244 :   cplex = xg_nonlop%cplex
    1280        18244 :   space_cprj = xg_nonlop%space_cprj
    1281              : 
    1282        18244 :   xg_nonlop%npw_k = npw_k
    1283              : 
    1284        73416 :   xg_nonlop%l_npw_k(:) = 0
    1285        18244 :   xg_nonlop%l_npw_k(xg_nonlop%me_band+1) = npw_k
    1286        18244 :   call xmpi_sum(xg_nonlop%l_npw_k,xg_nonlop%comm_band,ierr)
    1287              : 
    1288        73416 :   xg_nonlop%total_npw_k = sum(xg_nonlop%l_npw_k)
    1289        73416 :   xg_nonlop%max_npw_k = maxval(xg_nonlop%l_npw_k)
    1290              : 
    1291        18244 :   xg_nonlop%l_shift_npw_k(1) = 0
    1292        18244 :   nmpi = xmpi_comm_size(xg_nonlop%comm_band)
    1293        55172 :   do iblock=2,nmpi
    1294        55172 :     xg_nonlop%l_shift_npw_k(iblock) = xg_nonlop%l_shift_npw_k(iblock-1) + xg_nonlop%l_npw_k(iblock-1)
    1295              :   end do
    1296              : 
    1297        18244 :   ntypat = xg_nonlop%ntypat
    1298        18244 :   nlmn_max = xg_nonlop%nlmn_max
    1299              : 
    1300        18244 :   xg_nonlop%ph3d_k => ph3d_k
    1301        18244 :   xg_nonlop%ffnl_k => ffnl_k
    1302              : 
    1303        18244 :   xg_nonlop%kpg_k => kpg_k
    1304              : 
    1305        18244 :   xg_nonlop%projectors_k  => xg_nonlop%projectors(ikpt)
    1306        18244 :   if (xg_nonlop%option==0) then
    1307        17220 :     xg_nonlop%ffnl_gather_k => xg_nonlop%ffnl_gather(ikpt)
    1308        17220 :     xg_nonlop%ph3d_gather_k => xg_nonlop%ph3d_gather(ikpt)
    1309              :   end if
    1310              : 
    1311        18244 :   if (xg_nonlop%paw) then
    1312        15172 :     xg_nonlop%gram_proj_k => xg_nonlop%gram_proj(ikpt)
    1313        15172 :     xg_nonlop%invSij_approx_k => xg_nonlop%invSij_approx(ikpt)
    1314              :   end if
    1315              : 
    1316        18244 :   if (compute_proj) then
    1317              : 
    1318              :     call xg_init(xg_nonlop%projectors_k,xg_nonlop%space_pw,npw_k,xg_nonlop%cprjdim,&
    1319         2320 :       xg_nonlop%comm_band,me_g0=me_g0_loc)
    1320              : 
    1321         2320 :     if (xg_nonlop%option==0) then
    1322         2192 :       call xg_init(xg_nonlop%ffnl_gather_k,SPACE_R,xg_nonlop%total_npw_k,nlmn_max*ntypat,xmpi_comm_null)
    1323              :       call xg_init(xg_nonlop%ph3d_gather_k,xg_nonlop%space_pw,xg_nonlop%total_npw_k,xg_nonlop%natom,&
    1324         2192 :         xmpi_comm_null,me_g0=me_g0_fft_loc)
    1325              :     end if
    1326              : 
    1327         2320 :     call xg_nonlop_compute_projs(xg_nonlop)
    1328              : 
    1329         2320 :     compute_invS_approx_=.false.
    1330         2320 :     if (present(compute_invS_approx)) compute_invS_approx_ = compute_invS_approx
    1331         1160 :     if (compute_invS_approx_) then
    1332              : 
    1333          770 :       if (.not.xg_nonlop%paw) then
    1334            0 :         ABI_ERROR('Not implemented with paw=False.')
    1335              :       end if
    1336              : 
    1337              :       !invSij_approx_k is allocated here as space_pw depends on k-point
    1338          770 :       call xg_init(xg_nonlop%invSij_approx_k,space_cprj,nlmn_max,nlmn_max*ntypat,xmpi_comm_self)
    1339              : 
    1340          770 :       shift_itypat=1
    1341         2334 :       do itypat = 1, ntypat
    1342         1564 :         nlmn = xg_nonlop%nlmn_ntypat(itypat)
    1343         1564 :         nattyp_i = xg_nonlop%nattyp(itypat)
    1344         2334 :         if (nattyp_i>0) then
    1345         1540 :           shift_sij = 1+(itypat-1)*nlmn_max
    1346         1540 :           call xgBlock_setBlock(xg_nonlop%projectors_k%self,projs,npw_k,nlmn,fcol=shift_itypat)
    1347         1540 :           call xg_setBlock(xg_nonlop%invSij_approx_k,invSij_approx_k_itypat,nlmn,nlmn,fcol=shift_sij)
    1348         1540 :           call xg_setBlock(xg_nonlop%Sijm1,Sijm1_itypat,nlmn,nlmn,fcol=shift_sij)
    1349         1540 :           if (space_cprj==SPACE_R) then
    1350          496 :             call xgBlock_copy(Sijm1_itypat,invSij_approx_k_itypat)
    1351              :           else
    1352         1044 :             call xgBlock_r2c(Sijm1_itypat,invSij_approx_k_itypat,1)
    1353              :           end if
    1354         1540 :           call xg_init(work,space_cprj,nlmn,nlmn,xmpi_comm_self)
    1355         1540 :           call xgBlock_gemm('t','n',1.0d0,projs,projs,0.0d0,work%self,comm=xg_nonlop%comm_band)
    1356         1540 :           call xgBlock_add(invSij_approx_k_itypat,work%self)
    1357         1540 :           call xgBlock_invert_sy(invSij_approx_k_itypat,work%self)
    1358         1540 :           call xg_free(work)
    1359         1540 :           shift_itypat = shift_itypat + nlmn*nattyp_i
    1360              :         end if
    1361              :       end do
    1362              : 
    1363              :     end if
    1364              : 
    1365         2320 :     compute_gram_=.false.
    1366         2320 :     if (present(compute_gram)) compute_gram_ = compute_gram
    1367         1160 :     if (compute_gram_) then
    1368              : 
    1369          770 :       if (.not.xg_nonlop%paw) then
    1370            0 :         ABI_ERROR('Not implemented with paw=False.')
    1371              :       end if
    1372          770 :       cplex=xg_nonlop%cplex
    1373          770 :       ncols = xg_nonlop%cprjdim
    1374          770 :       call xg_init(xg_nonlop%gram_proj_k,space_cprj,ncols,ncols,xmpi_comm_self)
    1375          770 :       projs = xg_nonlop%projectors_k%self
    1376          770 :       call xgBlock_gemm('t','n',1.0d0,projs,projs,0.0d0,xg_nonlop%gram_proj_k%self,comm=xg_nonlop%comm_band)
    1377          770 :       call xgBlock_reverseMap(xg_nonlop%gram_proj_k%self,gram_proj_k_)
    1378          770 :       shift=0
    1379          770 :       shiftc=0
    1380         2334 :       do itypat = 1, ntypat
    1381         1564 :         nlmn = xg_nonlop%nlmn_ntypat(itypat)
    1382         1564 :         nattyp_i = xg_nonlop%nattyp(itypat)
    1383         2334 :         if (nattyp_i>0) then
    1384         1540 :           shift_sij = 1+(itypat-1)*nlmn_max
    1385         1540 :           call xg_setBlock(xg_nonlop%Sijm1,Sijm1_itypat,nlmn,nlmn,fcol=shift_sij)
    1386         1540 :           call xgBlock_reverseMap(Sijm1_itypat,Sijm1_)
    1387         3096 :           do ia = 1, nattyp_i
    1388        14084 :             do jlmn=1,nlmn
    1389       115748 :               do ilmn=1,nlmn
    1390              :                 gram_proj_k_(shiftc+cplex*(ilmn-1)+1,shift+jlmn) = gram_proj_k_(shiftc+cplex*(ilmn-1)+1,shift+jlmn) &
    1391       114192 :                   & + Sijm1_(ilmn,jlmn)
    1392              :               end do
    1393              :             end do
    1394         1556 :             shift  = shift  + nlmn
    1395         3096 :             shiftc = shiftc + cplex*nlmn
    1396              :           end do
    1397              :         end if
    1398              :       end do
    1399              : 
    1400              :       !ITEST
    1401              :       !write(903,*) 'make_cprj, compute gram', cols, space_cprj==SPACE_C
    1402              :       !call xgBlock_hermitian_pd_cond(xg_nonlop%gram_proj_k%self, cols, cond)
    1403              :       !write(903,*) 'cond(B)=', cond
    1404              :       !flush(903)
    1405              :       !ITEST
    1406              : 
    1407              :     end if
    1408              : 
    1409              :   end if ! compute_proj
    1410              : 
    1411        18244 :   call timab(tim_make_k,2,tsec)
    1412              : 
    1413        18244 :  end subroutine xg_nonlop_make_k
    1414              : !!***
    1415              : 
    1416       679140 : subroutine xg_nonlop_set_nmpi(xg_nonlop,X,cprjX,nmpi,blocksize,fft_representation)
    1417              : 
    1418              :    type(xg_nonlop_t), intent(in) :: xg_nonlop
    1419              :    type(xgBlock_t), intent(in) :: X
    1420              :    type(xgBlock_t), intent(in) :: cprjX
    1421              :    integer, intent(out) :: blocksize,nmpi
    1422              :    logical, intent(out) :: fft_representation
    1423              : 
    1424              :    integer :: nspinor,npw
    1425              :    type(xgBlock_t) :: projs
    1426              : 
    1427       679140 :    if (.not.associated(xg_nonlop%projectors_k)) then
    1428            0 :      ABI_ERROR('projectors_k should be associated')
    1429              :    end if
    1430              : 
    1431       679140 :    projs = xg_nonlop%projectors_k%self
    1432              : 
    1433       679140 :    npw = xg_nonlop%npw_k
    1434       679140 :    nspinor = xg_nonlop%nspinor
    1435       679140 :    blocksize = cols(cprjX)
    1436              : 
    1437              :    ! Check projector sizes
    1438       679140 :    if (npw/=rows(projs)) then
    1439            0 :      ABI_ERROR('npw/=rows(projs)')
    1440              :    end if
    1441       679140 :    if (xg_nonlop%cprjdim/=cols(projs)) then
    1442            0 :      ABI_ERROR('cols(projs)/=cprjdim')
    1443              :    end if
    1444              :    ! Check cprj sizes
    1445       679140 :    if (rows(cprjX)/=xg_nonlop%cprjdim) then
    1446            0 :      ABI_ERROR('rows(cprjX)/=cprjdim')
    1447              :    end if
    1448              :    ! rows(projs), cols(projs) and rows(cprj) are checked.
    1449              :    ! Now we check : rows(X),cols(X) and cols(cprj) depending on mpi
    1450       679140 :    nmpi = xmpi_comm_size(comm(cprjX))
    1451       679140 :    if (nmpi==1) then ! sequential
    1452       196864 :      if (xmpi_comm_size(comm(X))/=1) then
    1453            0 :        ABI_ERROR('size(comm(X))/=1')
    1454              :      end if
    1455       196864 :      if (rows(X)/=npw*nspinor) then
    1456            0 :        ABI_ERROR('rows(X)/=npw*nspinor')
    1457              :      end if
    1458       196864 :      if (cols(X)*nspinor/=blocksize) then
    1459            0 :        ABI_ERROR('cols(cprjX)/=cols(X)*nspinor')
    1460              :      end if
    1461              :    else ! MPI
    1462              :      ! FFT representation (X have all rows, cols are distributed)
    1463       482276 :      if (rows(X)==xg_nonlop%total_npw_k*nspinor) then
    1464       343900 :        fft_representation = .True.
    1465       343900 :        if (xmpi_comm_size(comm(X))/=1) then
    1466            0 :          ABI_ERROR('size(comm(X))/=1')
    1467              :        end if
    1468       343900 :        if (cols(X)*nspinor/=blocksize) then
    1469            0 :          ABI_ERROR('cols(cprjX)/=cols(X)*nspinor')
    1470              :        end if
    1471              :      ! Linalg representation (X have all cols, rows are distributed)
    1472              :      else
    1473       138376 :        fft_representation = .False.
    1474       138376 :        if (comm(X)/=comm(cprjX)) then
    1475            0 :          ABI_ERROR('comm(X)/=comm(cprjX)')
    1476              :        end if
    1477       138376 :        if (rows(X)/=npw*nspinor) then
    1478            0 :          ABI_ERROR('rows(X)/=npw*nspinor')
    1479              :        end if
    1480       138376 :        if (cols(X)*nspinor/=blocksize*nmpi) then
    1481            0 :          ABI_ERROR('cols(cprjX)*nmpi/=cols(X)*nspinor')
    1482              :        end if
    1483              :      end if
    1484              :    end if
    1485              : 
    1486       679140 : end subroutine xg_nonlop_set_nmpi
    1487              : 
    1488              : !!****f* m_xg_nonlop/xg_nonlop_getcprj
    1489              : !! NAME
    1490              : !!
    1491              : !! FUNCTION
    1492              : !!
    1493              : !! INPUTS
    1494              : !!
    1495       728616 : subroutine xg_nonlop_getcprj(xg_nonlop,X,cprjX,work_mpi)
    1496              : 
    1497              :    type(xg_nonlop_t), intent(in)    :: xg_nonlop
    1498              :    type(xgBlock_t)  , intent(in   ) :: X
    1499              :    type(xgBlock_t)  , intent(inout) :: cprjX,work_mpi
    1500              : 
    1501              :    real(dp) :: tsec(2)
    1502              :    integer :: ierr,iblock,nmpi,npw,npw_max,blocksize,nspinor,shift,shift_row
    1503              :    integer :: source,dest,tag,request,me_band,me_g0_loc
    1504              :    logical :: fft_representation
    1505              :    type(xgBlock_t) :: X_block,X_spinor,projs,work_mpi_npw
    1506              :    type(xg_t) :: work_npw
    1507              : 
    1508       364308 :    call timab(tim_getcprj,1,tsec)
    1509              : 
    1510       364308 :    call xg_nonlop_set_nmpi(xg_nonlop,X,cprjX,nmpi,blocksize,fft_representation)
    1511              : 
    1512       364308 :    nspinor = xg_nonlop%nspinor
    1513       364308 :    projs = xg_nonlop%projectors_k%self
    1514              : 
    1515       364308 :    call xgBlock_reshape_spinor(X,X_spinor,nspinor,ROWS2COLS)
    1516              : 
    1517       364308 :    if (nmpi==1) then
    1518              : 
    1519       106394 :      call timab(tim_getcprj_gemm,1,tsec)
    1520       106394 :      call xgBlock_gemm('t','n',1.0d0,projs,X_spinor,0.d0,cprjX)
    1521       106394 :      call timab(tim_getcprj_gemm,2,tsec)
    1522              : 
    1523              :    else
    1524              : 
    1525       257914 :      me_band=xg_nonlop%me_band
    1526              : 
    1527       257914 :      if (fft_representation) then ! FFT representation (X have all rows, cols are distributed)
    1528              : 
    1529       177488 :        npw_max = xg_nonlop%max_npw_k
    1530              : 
    1531       177488 :        if (rows(work_mpi)/=npw_max) then
    1532            0 :          ABI_ERROR('rows(work)/=npw_max')
    1533              :        end if
    1534       177488 :        if (cols(work_mpi)/=xg_nonlop%cprjdim) then
    1535            0 :          ABI_ERROR('rows(work)/=cprjdim')
    1536              :        end if
    1537              : 
    1538              :        ! npw_max=npw_tot/Nmpi and blocksize=nband/Nmpi so size(work_npw) ~ 1/Nmpi^2
    1539       177488 :        call xg_init(work_npw,xg_nonlop%space_pw,npw_max,blocksize,xmpi_comm_null,me_g0=me_g0(X))
    1540              : 
    1541       859696 :        do iblock=1,nmpi
    1542              : 
    1543       859696 :          if (iblock==1) then
    1544       177488 :            npw = xg_nonlop%l_npw_k(me_band+1)
    1545       177488 :            shift_row = xg_nonlop%l_shift_npw_k(me_band+1)
    1546       177488 :            call xg_setBlock(work_npw,X_block,npw,blocksize)
    1547              : 
    1548       177488 :            call timab(tim_getcprj_copy,1,tsec)
    1549       177488 :            call xgBlock_partialcopy(X_spinor,X_block,shift_row,0,BIG2SMALL)
    1550       177488 :            call timab(tim_getcprj_copy,2,tsec)
    1551              : 
    1552       177488 :            call timab(tim_getcprj_gemm,1,tsec)
    1553       177488 :            call xgBlock_gemm('t','n',1.0d0,projs,X_block,0.d0,cprjX)
    1554       177488 :            call timab(tim_getcprj_gemm,2,tsec)
    1555              : 
    1556              :          else
    1557       504720 :            tag  = iblock
    1558       504720 :            dest = mod(me_band-(iblock-1),nmpi)
    1559       504720 :            if (dest<0) dest=dest+nmpi
    1560              : 
    1561       504720 :            if (xg_nonlop%option==1) then
    1562        55488 :              call timab(tim_getcprj_mpi,1,tsec)
    1563        55488 :              call xgBlock_mpi_isend(projs,dest,tag,request,comm=xg_nonlop%comm_band)
    1564        55488 :              call timab(tim_getcprj_mpi,2,tsec)
    1565              :            end if
    1566              : 
    1567       504720 :            source = mod(me_band+(iblock-1),nmpi)
    1568       504720 :            npw = xg_nonlop%l_npw_k(source+1)
    1569       504720 :            shift_row = xg_nonlop%l_shift_npw_k(source+1)
    1570       504720 :            me_g0_loc = -1
    1571       504720 :            if (xg_nonlop%space_pw==SPACE_CR) then
    1572       247608 :              me_g0_loc = me_g0(X)
    1573       247608 :              if (shift_row>0) me_g0_loc = 0
    1574              :            end if
    1575       504720 :            call xg_setBlock(work_npw,X_block,npw,blocksize)
    1576              : 
    1577       504720 :            call timab(tim_getcprj_copy,1,tsec)
    1578       504720 :            call xgBlock_partialcopy(X_spinor,X_block,shift_row,0,BIG2SMALL)
    1579       504720 :            call timab(tim_getcprj_copy,2,tsec)
    1580              : 
    1581       504720 :            call xgBlock_setBlock(work_mpi,work_mpi_npw,npw_max,xg_nonlop%cprjdim)
    1582       504720 :            call xgBlock_free_reshape(work_mpi_npw,npw,xg_nonlop%cprjdim,new_me_g0=me_g0_loc)
    1583              : 
    1584       504720 :            if (xg_nonlop%option==1) then
    1585        55488 :              call timab(tim_getcprj_mpi,1,tsec)
    1586        55488 :              call xgBlock_mpi_recv(work_mpi_npw,source,tag,comm=xg_nonlop%comm_band)
    1587        55488 :              call timab(tim_getcprj_mpi,2,tsec)
    1588       449232 :            else if (xg_nonlop%option==0) then
    1589       449232 :              call timab(tim_getcprj_otf,1,tsec)
    1590       449232 :              call xg_nonlop_compute_projs_otf(xg_nonlop,work_mpi_npw,source)
    1591       449232 :              call timab(tim_getcprj_otf,2,tsec)
    1592              :            else
    1593            0 :              ABI_ERROR("Wrong xg_nonlop%option")
    1594              :            end if
    1595              : 
    1596       504720 :            call timab(tim_getcprj_gemm,1,tsec)
    1597       504720 :            call xgBlock_gemm('t','n',1.0d0,work_mpi_npw,X_block,1.d0,cprjX)
    1598       504720 :            call timab(tim_getcprj_gemm,2,tsec)
    1599              : 
    1600       504720 :            if (xg_nonlop%option==1) then
    1601        55488 :              call timab(tim_getcprj_mpi,1,tsec)
    1602        55488 :              call xmpi_wait(request,ierr)
    1603        55488 :              call timab(tim_getcprj_mpi,2,tsec)
    1604              :            end if
    1605              : 
    1606              :          end if
    1607              : 
    1608              :        end do
    1609              : 
    1610       177488 :        call xg_free(work_npw)
    1611              : 
    1612              :      else ! Linalg representation (X have all cols, rows are distributed)
    1613              : 
    1614        80426 :        call xgBlock_check(cprjX,work_mpi)
    1615              : 
    1616       387078 :        do iblock=1,nmpi
    1617       306652 :          shift=1+(iblock-1)*blocksize
    1618       306652 :          call xgBlock_setBlock(X_spinor,X_block,rows(X_spinor),blocksize,fcol=shift)
    1619              : 
    1620       306652 :          call timab(tim_getcprj_gemm,1,tsec)
    1621       306652 :          call xgBlock_gemm('t','n',1.0d0,projs,X_block,0.d0,work_mpi)
    1622       306652 :          call timab(tim_getcprj_gemm,2,tsec)
    1623              :          ! We do the mpi sum outside xgBlock_gemm just to include the timing in tim_getcprj_mpi,
    1624              :          ! (instead of tim_gemm_mpi).
    1625       306652 :          call timab(tim_getcprj_mpi,1,tsec)
    1626       306652 :          call xgBlock_mpi_sum(work_mpi,comm=xg_nonlop%comm_band)
    1627       306652 :          call timab(tim_getcprj_mpi,2,tsec)
    1628              : 
    1629       387078 :          if (me_band==iblock-1) then
    1630        80426 :            call timab(tim_getcprj_copy,1,tsec)
    1631        80426 :            call xgBlock_copy(work_mpi,cprjX)
    1632        80426 :            call timab(tim_getcprj_copy,2,tsec)
    1633              :          end if
    1634              :        end do
    1635              : 
    1636              :      end if
    1637              : 
    1638              :    end if
    1639              : 
    1640       364308 :    call timab(tim_getcprj,2,tsec)
    1641              : 
    1642       364308 :  end subroutine xg_nonlop_getcprj
    1643              : !!***
    1644              : 
    1645              : !!****f* m_xg_nonlop/xg_nonlop_getcprj_deriv
    1646              : !! NAME
    1647              : !!
    1648              : !! FUNCTION
    1649              : !!
    1650              : !! INPUTS
    1651              : !!
    1652        19440 : subroutine xg_nonlop_getcprj_deriv(xg_nonlop,X,cprjX,work_mpi,option)
    1653              : 
    1654              :    type(xg_nonlop_t), intent(in)    :: xg_nonlop
    1655              :    type(xgBlock_t)  , intent(in)    :: X
    1656              :    integer          , intent(in)    :: option
    1657              :    type(xgBlock_t)  , intent(inout) :: cprjX,work_mpi
    1658              : 
    1659              : !   real(dp) :: tsec(2)
    1660              :    integer :: iblock,nmpi,npw,blocksize,nspinor,shift
    1661              :    integer :: me_band,proj_size
    1662              :    type(xgBlock_t) :: X_block,X_spinor
    1663              :    type(xg_t) :: projs_deriv
    1664              : 
    1665              : !   call timab(tim_getcprj,1,tsec)
    1666              : 
    1667        19440 :    npw = xg_nonlop%npw_k
    1668        19440 :    nspinor = xg_nonlop%nspinor
    1669        19440 :    blocksize = cols(cprjX)
    1670              : 
    1671        19440 :    if (option==DERIV_ATOM) then
    1672        18300 :      proj_size = 3*xg_nonlop%cprjdim
    1673         1140 :    else if (option==DERIV_STRESS) then
    1674         1140 :      proj_size = 6*xg_nonlop%cprjdim
    1675              :    else
    1676            0 :      ABI_ERROR('Bad option')
    1677              :    end if
    1678              :    ! Check cprj sizes
    1679        19440 :    if (rows(cprjX)/=proj_size) then
    1680            0 :      ABI_ERROR('rows(cprjX)/=proj_size')
    1681              :    end if
    1682              :    ! Now we check : rows(X),cols(X) and cols(cprj) depending on mpi
    1683        19440 :    nmpi = xmpi_comm_size(comm(cprjX))
    1684        19440 :    if (nmpi==1) then ! sequential
    1685         6496 :      if (xmpi_comm_size(comm(X))/=1) then
    1686            0 :        ABI_ERROR('size(comm(X))/=1')
    1687              :      end if
    1688         6496 :      if (rows(X)/=npw*nspinor) then
    1689            0 :        ABI_ERROR('rows(X)/=npw*nspinor')
    1690              :      end if
    1691         6496 :      if (cols(X)*nspinor/=blocksize) then
    1692            0 :        ABI_ERROR('cols(cprjX)/=cols(X)*nspinor')
    1693              :      end if
    1694              :    else ! MPI
    1695              :      ! Linalg representation (X have all cols, rows are distributed)
    1696        12944 :      if (comm(X)/=comm(cprjX)) then
    1697            0 :        ABI_ERROR('comm(X)/=comm(cprjX)')
    1698              :      end if
    1699        12944 :      if (rows(X)/=npw*nspinor) then
    1700            0 :        ABI_ERROR('rows(X)/=npw*nspinor')
    1701              :      end if
    1702        12944 :      if (cols(X)*nspinor/=blocksize*nmpi) then
    1703            0 :        ABI_ERROR('cols(cprjX)*nmpi/=cols(X)*nspinor')
    1704              :      end if
    1705              :    end if
    1706              : 
    1707        19440 :    call xg_init(projs_deriv,xg_nonlop%space_pw,npw,proj_size,comm=xg_nonlop%comm_band,me_g0=me_g0(X))
    1708              : 
    1709        18300 :    select case (option)
    1710              :      case (DERIV_ATOM)
    1711        18300 :        call xg_nonlop_compute_projs_deriv_atom(xg_nonlop,projs_deriv%self)
    1712              :      case (DERIV_STRESS)
    1713        19440 :        call xg_nonlop_compute_projs_deriv_stress(xg_nonlop,projs_deriv%self)
    1714              :    end select
    1715              : 
    1716        19440 :    call xgBlock_reshape_spinor(X,X_spinor,nspinor,ROWS2COLS)
    1717              : 
    1718        19440 :    if (nmpi==1) then
    1719              : 
    1720              : !     call timab(tim_getcprj_gemm,1,tsec)
    1721         6496 :      call xgBlock_gemm('t','n',1.0d0,projs_deriv%self,X_spinor,0.d0,cprjX)
    1722              : !     call timab(tim_getcprj_gemm,2,tsec)
    1723              : 
    1724              :    else
    1725              : 
    1726        12944 :      me_band=xg_nonlop%me_band
    1727              : 
    1728        12944 :      call xgBlock_check(cprjX,work_mpi)
    1729              : 
    1730        62128 :      do iblock=1,nmpi
    1731        49184 :        shift=1+(iblock-1)*blocksize
    1732        49184 :        call xgBlock_setBlock(X_spinor,X_block,rows(X_spinor),blocksize,fcol=shift)
    1733              : 
    1734              : !       call timab(tim_getcprj_gemm,1,tsec)
    1735        49184 :        call xgBlock_gemm('t','n',1.0d0,projs_deriv%self,X_block,0.d0,work_mpi)
    1736              : !       call timab(tim_getcprj_gemm,2,tsec)
    1737              :        ! We do the mpi sum outside xgBlock_gemm just to include the timing in tim_getcprj_mpi,
    1738              :        ! (instead of tim_gemm_mpi).
    1739              : !       call timab(tim_getcprj_mpi,1,tsec)
    1740        49184 :        call xgBlock_mpi_sum(work_mpi,comm=xg_nonlop%comm_band)
    1741              : !       call timab(tim_getcprj_mpi,2,tsec)
    1742              : 
    1743        62128 :        if (me_band==iblock-1) then
    1744              : !         call timab(tim_getcprj_copy,1,tsec)
    1745        12944 :          call xgBlock_copy(work_mpi,cprjX)
    1746              : !         call timab(tim_getcprj_copy,2,tsec)
    1747              :        end if
    1748              :      end do
    1749              : 
    1750              :    end if
    1751              : 
    1752        19440 :    call xg_free(projs_deriv)
    1753              : !   call timab(tim_getcprj,2,tsec)
    1754              : 
    1755        19440 :  end subroutine xg_nonlop_getcprj_deriv
    1756              : !!***
    1757              : 
    1758       629664 :  subroutine xg_nonlop_apply_prj(xg_nonlop,cprjX,X,work_mpi)
    1759              : 
    1760              :    type(xg_nonlop_t), intent(in) :: xg_nonlop
    1761              :    type(xgBlock_t), intent(in) :: cprjX
    1762              :    type(xgBlock_t), intent(inout) :: X,work_mpi
    1763              : 
    1764              :    logical :: fft_representation
    1765              :    integer :: nmpi,npw,blocksize,iblock,shift_col,nspinor!,nband,npw
    1766              :    integer :: me_band,shift_row,npw_max
    1767              :    integer :: ierr,source,dest,tag,request
    1768              :    real(dp) :: tsec(2)
    1769              :    type(xgBlock_t) :: projs
    1770              :    type(xgBlock_t) :: X_spinor,X_block,work_mpi_npw
    1771              :    type(xg_t) :: work_npw
    1772              : 
    1773       314832 :    call timab(tim_apply_prj,1,tsec)
    1774              : 
    1775       314832 :    call xg_nonlop_set_nmpi(xg_nonlop,X,cprjX,nmpi,blocksize,fft_representation)
    1776              : 
    1777       314832 :    projs = xg_nonlop%projectors_k%self
    1778              : 
    1779       314832 :    nspinor = xg_nonlop%nspinor
    1780       314832 :    call xgBlock_reshape_spinor(X,X_spinor,nspinor,ROWS2COLS)
    1781              : 
    1782       314832 :    if (nmpi==1) then
    1783              : 
    1784        90470 :      call timab(tim_apply_prj_gemm,1,tsec)
    1785        90470 :      call xgBlock_gemm('n','n',1.0d0,projs,cprjX,1.d0,X_spinor)
    1786        90470 :      call timab(tim_apply_prj_gemm,2,tsec)
    1787              : 
    1788              :    else
    1789              : 
    1790       224362 :      me_band = xg_nonlop%me_band
    1791              : 
    1792       224362 :      if (fft_representation) then ! FFT representation (X have all rows, cols are distributed)
    1793              : 
    1794       166412 :        npw_max = xg_nonlop%max_npw_k
    1795              : 
    1796       166412 :        if (rows(work_mpi)/=npw_max) then
    1797            0 :          ABI_ERROR('rows(work)/=npw_max')
    1798              :        end if
    1799       166412 :        if (cols(work_mpi)/=xg_nonlop%cprjdim) then
    1800            0 :          ABI_ERROR('rows(work)/=cprjdim')
    1801              :        end if
    1802              : 
    1803              :        ! npw_max=npw_tot/Nmpi and blocksize=nband/Nmpi so size(work_npw) ~ 1/Nmpi^2
    1804       166412 :        call xg_init(work_npw,xg_nonlop%space_pw,npw_max,blocksize,xmpi_comm_null)
    1805              : 
    1806       804316 :        do iblock=1,nmpi
    1807              : 
    1808       804316 :          if (iblock==1) then
    1809       166412 :            npw = xg_nonlop%l_npw_k(me_band+1)
    1810       166412 :            call xg_setBlock(work_npw,X_block,npw,blocksize)
    1811       166412 :            shift_row = xg_nonlop%l_shift_npw_k(me_band+1)
    1812              : 
    1813       166412 :            call timab(tim_apply_prj_copy,1,tsec)
    1814       166412 :            call xgBlock_partialcopy(X_spinor,X_block,shift_row,0,BIG2SMALL)
    1815       166412 :            call timab(tim_apply_prj_copy,2,tsec)
    1816              : 
    1817       166412 :            call timab(tim_apply_prj_gemm,1,tsec)
    1818       166412 :            call xgBlock_gemm('n','n',1.0d0,projs,cprjX,1.d0,X_block)
    1819       166412 :            call timab(tim_apply_prj_gemm,2,tsec)
    1820              : 
    1821       166412 :            call timab(tim_apply_prj_copy,1,tsec)
    1822       166412 :            call xgBlock_partialcopy(X_block,X_spinor,shift_row,0,SMALL2BIG)
    1823       166412 :            call timab(tim_apply_prj_copy,2,tsec)
    1824              :          else
    1825       471492 :            tag  = iblock
    1826       471492 :            dest = mod(me_band-(iblock-1),nmpi)
    1827       471492 :            if (dest<0) dest=dest+nmpi
    1828              : 
    1829       471492 :            if (xg_nonlop%option==1) then
    1830        55488 :              call timab(tim_apply_prj_mpi,1,tsec)
    1831        55488 :              call xgBlock_mpi_isend(projs,dest,tag,request,comm=xg_nonlop%comm_band)
    1832        55488 :              call timab(tim_apply_prj_mpi,2,tsec)
    1833              :            end if
    1834              : 
    1835       471492 :            source = mod(me_band+(iblock-1),nmpi)
    1836       471492 :            npw = xg_nonlop%l_npw_k(source+1)
    1837       471492 :            call xg_setBlock(work_npw,X_block,npw,blocksize)
    1838       471492 :            shift_row = xg_nonlop%l_shift_npw_k(source+1)
    1839              : 
    1840       471492 :            call timab(tim_apply_prj_copy,1,tsec)
    1841       471492 :            call xgBlock_partialcopy(X_spinor,X_block,shift_row,0,BIG2SMALL)
    1842       471492 :            call timab(tim_apply_prj_copy,2,tsec)
    1843              : 
    1844       471492 :            call xgBlock_setBlock(work_mpi,work_mpi_npw,npw_max,xg_nonlop%cprjdim)
    1845       471492 :            call xgBlock_free_reshape(work_mpi_npw,npw,xg_nonlop%cprjdim)
    1846              : 
    1847       471492 :            if (xg_nonlop%option==1) then
    1848        55488 :              call timab(tim_apply_prj_mpi,1,tsec)
    1849        55488 :              call xgBlock_mpi_recv(work_mpi_npw,source,tag,comm=xg_nonlop%comm_band)
    1850        55488 :              call timab(tim_apply_prj_mpi,2,tsec)
    1851       416004 :            else if (xg_nonlop%option==0) then
    1852       416004 :              call timab(tim_apply_prj_otf,1,tsec)
    1853       416004 :              call xg_nonlop_compute_projs_otf(xg_nonlop,work_mpi_npw,source)
    1854       416004 :              call timab(tim_apply_prj_otf,2,tsec)
    1855              :            else
    1856            0 :              ABI_ERROR("Wrong xg_nonlop%option")
    1857              :            end if
    1858              : 
    1859       471492 :            call timab(tim_apply_prj_gemm,1,tsec)
    1860       471492 :            call xgBlock_gemm('n','n',1.0d0,work_mpi_npw,cprjX,1.d0,X_block)
    1861       471492 :            call timab(tim_apply_prj_gemm,2,tsec)
    1862              : 
    1863       471492 :            call timab(tim_apply_prj_copy,1,tsec)
    1864       471492 :            call xgBlock_partialcopy(X_block,X_spinor,shift_row,0,SMALL2BIG)
    1865       471492 :            call timab(tim_apply_prj_copy,2,tsec)
    1866              : 
    1867       471492 :            if (xg_nonlop%option==1) then
    1868        55488 :              call timab(tim_apply_prj_mpi,1,tsec)
    1869        55488 :              call xmpi_wait(request,ierr)
    1870        55488 :              call timab(tim_apply_prj_mpi,2,tsec)
    1871              :            end if
    1872              :          end if
    1873              : 
    1874              :        end do
    1875              : 
    1876       166412 :        call xg_free(work_npw)
    1877              : 
    1878              :      else ! Linalg representation (X have all cols, rows are distributed)
    1879              : 
    1880        57950 :        call xgBlock_check(cprjX,work_mpi)
    1881              : 
    1882       278762 :        do iblock=1,nmpi
    1883              : 
    1884       220812 :          shift_col = 1 + mod(me_band+iblock-1,nmpi) * cols(cprjX)
    1885              : 
    1886       220812 :          call xgBlock_setBlock(X_spinor,X_block,rows(X_spinor),cols(cprjX),fcol=shift_col)
    1887              : 
    1888       278762 :          if (iblock==1) then
    1889              : 
    1890        57950 :            call timab(tim_apply_prj_gemm,1,tsec)
    1891        57950 :            call xgBlock_gemm('n','n',1.0d0,projs,cprjX,1.d0,X_block)
    1892        57950 :            call timab(tim_apply_prj_gemm,2,tsec)
    1893              : 
    1894              :          else
    1895              : 
    1896       162862 :            call timab(tim_apply_prj_mpi,1,tsec)
    1897       162862 :            tag = iblock
    1898       162862 :            dest = mod(me_band-(iblock-1),nmpi)
    1899       162862 :            if (dest<0) dest=dest+nmpi
    1900       162862 :            call xgBlock_mpi_isend(cprjX,dest,tag,request)
    1901       162862 :            source = mod(me_band+(iblock-1),nmpi)
    1902       162862 :            call xgBlock_mpi_recv(work_mpi,source,tag)
    1903       162862 :            call timab(tim_apply_prj_mpi,2,tsec)
    1904              : 
    1905       162862 :            call timab(tim_apply_prj_gemm,1,tsec)
    1906       162862 :            call xgBlock_gemm('n','n',1.0d0,projs,work_mpi,1.d0,X_block)
    1907       162862 :            call timab(tim_apply_prj_gemm,2,tsec)
    1908              : 
    1909       162862 :            call timab(tim_apply_prj_mpi,1,tsec)
    1910       162862 :            call xmpi_wait(request,ierr)
    1911       162862 :            call timab(tim_apply_prj_mpi,2,tsec)
    1912              : 
    1913              :          end if
    1914              : 
    1915              :        end do
    1916              : 
    1917              :      end if
    1918              : 
    1919              :    end if
    1920              : 
    1921       314832 :    call timab(tim_apply_prj,2,tsec)
    1922              : 
    1923       314832 :  end subroutine xg_nonlop_apply_prj
    1924              : !!***
    1925              : 
    1926       142520 :  subroutine xg_nonlop_apply_diag(xg_nonlop,diag_op,cprjin,cprjout)
    1927              : 
    1928              :    type(xg_nonlop_t), intent(in) :: xg_nonlop
    1929              :    type(xgBlock_t), intent(in) :: diag_op
    1930              :    type(xgBlock_t), intent(in) :: cprjin
    1931              :    type(xgBlock_t), intent(inout) :: cprjout
    1932              : 
    1933              :    logical :: loop_over_atoms
    1934              :    integer :: ia, iband, cprjdim, shift_itypat, iatom, itypat, nattyp_i, nlmn, shift
    1935              :    integer :: space_cprj, cplex, nlmn_max
    1936              :    integer :: nspinor, nrows, ncols
    1937              : 
    1938              :    type(xg_t)        :: cprjin_nlmn_max,cprjout_nlmn_max
    1939              :    type(xgBlock_t) :: cprjin_nlmn,cprjout_nlmn,diag_op_iatom
    1940        71260 :    real(dp),pointer :: cprjin_nlmn_(:,:),cprjout_nlmn_(:,:)
    1941        71260 :    real(dp),pointer :: cprjin_(:,:),cprjout_(:,:)
    1942              :    real(dp) :: tsec(2)
    1943              : 
    1944        71260 :    call timab(tim_apply_diag,1,tsec)
    1945              : 
    1946        71260 :    call xgBlock_getsize(cprjin,nrows,ncols)
    1947              : 
    1948        71260 :    cprjdim = xg_nonlop%cprjdim
    1949        71260 :    if (nrows/=cprjdim) then
    1950            0 :      ABI_ERROR('nrows/=cprjdim')
    1951              :    end if
    1952        71260 :    call xgBlock_check(cprjin,cprjout)
    1953              : 
    1954        71260 :    space_cprj = space(cprjin)
    1955        71260 :    if (space_cprj==SPACE_C) then
    1956              :      cplex=2
    1957              :    else
    1958        59308 :      cplex=1
    1959              :    end if
    1960              : 
    1961        71260 :    nspinor=xg_nonlop%nspinor
    1962        71260 :    nlmn_max=xg_nonlop%nlmn_max
    1963              : 
    1964              :    ! Create work spaces for cprj of ONE atom for ALL bands
    1965        71260 :    call xg_init(cprjin_nlmn_max ,space_cprj,nlmn_max,ncols)
    1966        71260 :    call xg_init(cprjout_nlmn_max,space_cprj,nlmn_max,ncols)
    1967              : 
    1968        71260 :    call xgBlock_reverseMap(cprjin ,cprjin_ )
    1969        71260 :    call xgBlock_reverseMap(cprjout,cprjout_)
    1970              : 
    1971        71260 :    if (cols(diag_op) == xg_nonlop%ntypat) then
    1972              :      loop_over_atoms = .false.
    1973            0 :    else if (cols(diag_op) == xg_nonlop%natom) then
    1974              :      loop_over_atoms = .true.
    1975              :    else
    1976            0 :      ABI_ERROR('wrong cols for diag_op!')
    1977              :    end if
    1978        71260 :    shift = 0
    1979        71260 :    shift_itypat = 0
    1980       213780 :    do itypat=1,xg_nonlop%ntypat
    1981       142520 :      nlmn=xg_nonlop%nlmn_ntypat(itypat)
    1982       142520 :      nattyp_i=xg_nonlop%nattyp(itypat)
    1983       213780 :      if (nattyp_i>0) then
    1984       142520 :        call xg_setBlock(cprjin_nlmn_max ,cprjin_nlmn ,nlmn,ncols)
    1985       142520 :        call xg_setBlock(cprjout_nlmn_max,cprjout_nlmn,nlmn,ncols)
    1986       142520 :        call xgBlock_reverseMap(cprjin_nlmn ,cprjin_nlmn_ )
    1987       142520 :        call xgBlock_reverseMap(cprjout_nlmn,cprjout_nlmn_)
    1988       142520 :        if (.not.loop_over_atoms) then
    1989       142520 :          call xgBlock_setBlock(diag_op,diag_op_iatom,nlmn,1,fcol=itypat)
    1990              :        end if
    1991       285040 :        do ia=1,nattyp_i
    1992       142520 :          if (loop_over_atoms) then
    1993            0 :            iatom = ia + shift_itypat
    1994            0 :            call xgBlock_setBlock(diag_op,diag_op_iatom,nlmn,1,fcol=iatom)
    1995              :          end if
    1996              :          ! Copy cprj of ONE atom for ALL bands from cprjin to cprin_nlmn
    1997       546560 :          do iband=1,ncols
    1998     32411960 :            cprjin_nlmn_(1:cplex*nlmn,iband) = cprjin_(1+shift:cplex*nlmn+shift,iband)
    1999              :          end do
    2000       142520 :          call xgBlock_apply_diag(cprjin_nlmn,diag_op_iatom,1,Y=cprjout_nlmn)
    2001       546560 :          do iband=1,ncols
    2002              :            cprjout_(1+shift:cplex*nlmn+shift,iband) = cprjout_(1+shift:cplex*nlmn+shift,iband) &
    2003     32411960 :            & + cprjout_nlmn_(1:cplex*nlmn,iband)
    2004              :          end do
    2005       285040 :          shift=shift+cplex*nlmn
    2006              :        end do
    2007       142520 :        shift_itypat = shift_itypat + nattyp_i
    2008              :      end if
    2009              : 
    2010              :    end do
    2011              : 
    2012        71260 :    call xg_free(cprjin_nlmn_max)
    2013        71260 :    call xg_free(cprjout_nlmn_max)
    2014              : 
    2015        71260 :    call timab(tim_apply_diag,2,tsec)
    2016              : 
    2017        71260 :  end subroutine xg_nonlop_apply_diag
    2018              : !!***
    2019              : 
    2020      2827252 :  subroutine xg_nonlop_apply_Aij(xg_nonlop,Aij,cprjin,cprjout,A_with_spin)
    2021              : 
    2022              :    type(xg_nonlop_t), intent(in) :: xg_nonlop
    2023              :    type(xgBlock_t), intent(in) :: Aij
    2024              :    type(xgBlock_t), intent(in) :: cprjin
    2025              :    type(xgBlock_t), intent(inout) :: cprjout
    2026              :    logical,optional,intent(in) :: A_with_spin
    2027              : 
    2028              :    logical :: loop_over_atoms
    2029              :    integer :: ia, iband, cprjdim, shift_itypat, iatom, itypat, nattyp_i, nlmn, shift
    2030              :    integer :: space_aij, space_cprj, cplex, nlmn_max
    2031              :    integer :: nspinor, nrows, ncols, nrows_A, ncols_A
    2032              :    integer :: nlmn_1atom,nlmn_max_1atom,ncols_1atom
    2033              : 
    2034              :    type(xg_t)        :: cprjin_nlmn_max,cprjout_nlmn_max
    2035              :    type(xg_t),target :: Aij_complex
    2036              :    type(xgBlock_t) :: cprjin_nlmn,cprjout_nlmn
    2037              :    type(xgBlock_t) :: Aij_iatom,Aij_iatom_
    2038      1413626 :    real(dp),pointer :: cprjin_nlmn_(:,:),cprjout_nlmn_(:,:)
    2039      1413626 :    real(dp),pointer :: cprjin_(:,:),cprjout_(:,:)
    2040              :    real(dp) :: tsec(2)
    2041              :    logical :: aij_r2c,A_with_spin_
    2042              : 
    2043      1413626 :    call timab(tim_apply_Aij,1,tsec)
    2044              : 
    2045      1413626 :    call xgBlock_getsize(cprjin,nrows,ncols)
    2046              : 
    2047      1413626 :    cprjdim = xg_nonlop%cprjdim
    2048      1413626 :    if (nrows/=cprjdim) then
    2049            0 :      ABI_ERROR('nrows/=cprjdim')
    2050              :    end if
    2051      1413626 :    call xgBlock_check(cprjin,cprjout)
    2052              : 
    2053      1413626 :    space_cprj = space(cprjin)
    2054      1413626 :    if (space_cprj==SPACE_C) then
    2055              :      cplex=2
    2056              :    else
    2057       522161 :      cplex=1
    2058              :    end if
    2059      1413626 :    space_aij = space(Aij)
    2060      1413626 :    aij_r2c = .false.
    2061      1413626 :    if (space_cprj/=space_aij) then
    2062       345425 :      if (space_aij==SPACE_R.and.space_cprj==SPACE_C) then
    2063              :        aij_r2c = .true.
    2064              :      else
    2065            0 :        ABI_ERROR('space_aij and space_cprj are not compatible')
    2066              :      end if
    2067              :    end if
    2068              : 
    2069      1413626 :    nspinor=xg_nonlop%nspinor
    2070      1413626 :    nlmn_max=xg_nonlop%nlmn_max
    2071              : 
    2072      1413626 :    A_with_spin_=.true.
    2073      1413626 :    if (present(A_with_spin)) then
    2074       708025 :      A_with_spin_=A_with_spin
    2075              :    end if
    2076       708025 :    if (A_with_spin_) then
    2077       705601 :      nlmn_max_1atom = nlmn_max * nspinor
    2078       705601 :      ncols_1atom = ncols / nspinor
    2079              :    else
    2080       708025 :      nlmn_max_1atom = nlmn_max
    2081       708025 :      ncols_1atom = ncols
    2082              :    end if
    2083              : 
    2084      1413626 :    if (aij_r2c) then
    2085       345425 :      if (rows(Aij) /= nlmn_max) then
    2086            0 :        ABI_ERROR('wrong rows for Aij')
    2087              :      end if
    2088       345425 :      if (cols(Aij) == xg_nonlop%ntypat*nlmn_max) then
    2089              :        loop_over_atoms = .false.
    2090        18421 :      else if (cols(Aij) == xg_nonlop%natom*nlmn_max) then
    2091              :        loop_over_atoms = .true.
    2092              :      else
    2093            0 :        ABI_ERROR('wrong cols for Aij (aij_r2c)')
    2094              :      end if
    2095              :    else
    2096      1068201 :      if (rows(Aij) /= nlmn_max_1atom) then
    2097            0 :        ABI_ERROR('wrong rows for Aij')
    2098              :      end if
    2099      1068201 :      if (cols(Aij) == xg_nonlop%ntypat*nlmn_max_1atom) then
    2100              :        loop_over_atoms = .false.
    2101        18070 :      else if (cols(Aij) == xg_nonlop%natom*nlmn_max_1atom) then
    2102              :        loop_over_atoms = .true.
    2103              :      else
    2104            0 :        ABI_ERROR('wrong cols for Aij')
    2105              :      end if
    2106              :    end if
    2107              : 
    2108              :    ! Create work spaces for cprj of ONE atom for ALL bands
    2109      1413626 :    call xg_init(cprjin_nlmn_max ,space_cprj,nlmn_max_1atom,ncols_1atom)
    2110      1413626 :    call xg_init(cprjout_nlmn_max,space_cprj,nlmn_max_1atom,ncols_1atom)
    2111              : 
    2112      1413626 :    call xgBlock_reverseMap(cprjin ,cprjin_ )
    2113      1413626 :    call xgBlock_reverseMap(cprjout,cprjout_)
    2114              : 
    2115      1413626 :    shift = 0
    2116      1413626 :    shift_itypat = 0
    2117      4231761 :    do itypat=1,xg_nonlop%ntypat
    2118      2818135 :      nlmn=xg_nonlop%nlmn_ntypat(itypat)
    2119      2818135 :      if (A_with_spin_) then
    2120      1377521 :        nlmn_1atom = nlmn*nspinor
    2121              :      else
    2122      1440614 :        nlmn_1atom = nlmn
    2123              :      end if
    2124      2818135 :      nattyp_i=xg_nonlop%nattyp(itypat)
    2125      4231761 :      if (nattyp_i>0) then
    2126      2768036 :        call xg_setBlock(cprjin_nlmn_max ,cprjin_nlmn ,nlmn_1atom,ncols_1atom)
    2127      2768036 :        call xg_setBlock(cprjout_nlmn_max,cprjout_nlmn,nlmn_1atom,ncols_1atom)
    2128      2768036 :        call xgBlock_reverseMap(cprjin_nlmn ,cprjin_nlmn_ )
    2129      2768036 :        call xgBlock_reverseMap(cprjout_nlmn,cprjout_nlmn_)
    2130      2768036 :        if (aij_r2c) call xg_init(Aij_complex,SPACE_C,nlmn_1atom,nlmn_1atom)
    2131      2768036 :        if (.not.loop_over_atoms) then
    2132      2718988 :          if (aij_r2c) then
    2133       627647 :            call xgBlock_setBlock(Aij,Aij_iatom,nlmn,nlmn,fcol=1+(itypat-1)*nlmn_max)
    2134              :          else
    2135      2091341 :            call xgBlock_setBlock(Aij,Aij_iatom,nlmn_1atom,nlmn_1atom,fcol=1+(itypat-1)*nlmn_max_1atom)
    2136              :          end if
    2137              :        end if
    2138      5609800 :        do ia=1,nattyp_i
    2139      2841764 :          if (loop_over_atoms) then
    2140        73894 :            iatom = ia + shift_itypat
    2141        73894 :            if (aij_r2c) then
    2142        37754 :              call xgBlock_setBlock(Aij,Aij_iatom,nlmn,nlmn,fcol=1+(iatom-1)*nlmn_max)
    2143              :            else
    2144        36140 :              call xgBlock_setBlock(Aij,Aij_iatom,nlmn_1atom,nlmn_1atom,fcol=1+(iatom-1)*nlmn_max_1atom)
    2145              :            end if
    2146              :          end if
    2147      2841764 :          call xgBlock_getsize(Aij_iatom,nrows_A,ncols_A)
    2148      2841764 :          if (.not.aij_r2c) then
    2149      2149602 :            if (nrows_A/=nlmn_1atom) then
    2150            0 :              ABI_ERROR('nrows_A/=nlmn_1atom')
    2151              :            end if
    2152      2149602 :            if (ncols_A/=nlmn_1atom) then
    2153            0 :              ABI_ERROR('ncols_A/=nlmn_1atom')
    2154              :            end if
    2155              :          else
    2156       692162 :            if (nrows_A/=nlmn) then
    2157            0 :              ABI_ERROR('nrows_A/=nlmn')
    2158              :            end if
    2159       692162 :            if (ncols_A/=nlmn) then
    2160            0 :              ABI_ERROR('ncols_A/=nlmn')
    2161              :            end if
    2162              :          end if
    2163              :          ! if needed, transfer real matrix to a complex one
    2164      2841764 :          if (aij_r2c) then
    2165       692162 :            call xgBlock_r2c(Aij_iatom,Aij_complex%self,nspinor)
    2166       692162 :            Aij_iatom_ = Aij_complex%self
    2167              :          else
    2168      2149602 :            Aij_iatom_ = Aij_iatom
    2169              :          end if
    2170              :          ! Copy cprj of ONE atom for ALL bands from cprjin to cprin_nlmn
    2171      2841764 :          if (A_with_spin_) then
    2172      5332134 :            do iband=1,ncols_1atom
    2173    121269702 :              cprjin_nlmn_(1:cplex*nlmn,iband) = cprjin_(1+shift:cplex*nlmn+shift,1+nspinor*(iband-1))
    2174              :            end do
    2175      1412514 :            if (nspinor==2) then
    2176      1367358 :              do iband=1,ncols_1atom
    2177     39094014 :                cprjin_nlmn_(1+cplex*nlmn:2*cplex*nlmn,iband) = cprjin_(1+shift:cplex*nlmn+shift,nspinor*iband)
    2178              :              end do
    2179              :            end if
    2180              :          else
    2181     12099738 :            do iband=1,ncols_1atom
    2182    330920090 :              cprjin_nlmn_(1:cplex*nlmn,iband) = cprjin_(1+shift:cplex*nlmn+shift,iband)
    2183              :            end do
    2184              :          end if
    2185              : 
    2186      2841764 :          call xgBlock_gemm('n','n',1.0d0,Aij_iatom_,cprjin_nlmn,0.d0,cprjout_nlmn,timing=.false.)
    2187              : 
    2188      2841764 :          if (A_with_spin_) then
    2189      5332134 :            do iband=1,ncols_1atom
    2190              :              cprjout_(1+shift:cplex*nlmn+shift,1+nspinor*(iband-1)) = cprjout_(1+shift:cplex*nlmn+shift,1+nspinor*(iband-1)) &
    2191    121269702 :              & + cprjout_nlmn_(1:cplex*nlmn,iband)
    2192              :            end do
    2193      1412514 :            if (nspinor==2) then
    2194      1367358 :              do iband=1,ncols_1atom
    2195              :                cprjout_(1+shift:cplex*nlmn+shift,nspinor*iband) = cprjout_(1+shift:cplex*nlmn+shift,nspinor*iband) &
    2196     39094014 :                & + cprjout_nlmn_(1+cplex*nlmn:2*cplex*nlmn,iband)
    2197              :              end do
    2198              :            end if
    2199              :          else
    2200     12099738 :            do iband=1,ncols_1atom
    2201              :              cprjout_(1+shift:cplex*nlmn+shift,iband) = cprjout_(1+shift:cplex*nlmn+shift,iband) &
    2202    330920090 :              & + cprjout_nlmn_(1:cplex*nlmn,iband)
    2203              :            end do
    2204              :          end if
    2205      8451564 :          shift=shift+cplex*nlmn
    2206              :        end do
    2207              : 
    2208      2768036 :        if (aij_r2c) call xg_free(Aij_complex)
    2209      2768036 :        shift_itypat = shift_itypat + nattyp_i
    2210              :      end if
    2211              : 
    2212              :    end do
    2213              : 
    2214      1413626 :    call xg_free(cprjin_nlmn_max)
    2215      1413626 :    call xg_free(cprjout_nlmn_max)
    2216              : 
    2217      1413626 :    call timab(tim_apply_Aij,2,tsec)
    2218              : 
    2219      1413626 :  end subroutine xg_nonlop_apply_Aij
    2220              : !!***
    2221              : 
    2222       189900 :  subroutine xg_nonlop_precond_iterative_refinement(xg_nonlop,A,precond,cprj_in,cprj_out,cprj_work)
    2223              : 
    2224              :    type(xg_nonlop_t), intent(in)  :: xg_nonlop
    2225              :    type(xgBlock_t), intent(in   ) :: A,precond
    2226              :    type(xgBlock_t), intent(in   ) :: cprj_in
    2227              :    type(xgBlock_t), intent(inout) :: cprj_out,cprj_work
    2228              : 
    2229              :    integer :: iter,cprjdim,ncols,additional_steps_to_take
    2230              :    !integer :: rows_A
    2231              :    real(dp), parameter :: tolerance = 1e-14 ! maximum relative error. TODO: use tolwfr ?
    2232              :    type(xg_t) :: err
    2233              :    !real(dp) :: cond
    2234              :    real(dp) :: norm,max_err,previous_max_err,convergence_rate,tsec(2)
    2235              : 
    2236        94950 :    call timab(tim_iter_refinement,1,tsec)
    2237              : 
    2238              :    ! Note that precond is block-diagonal whereas A is not
    2239              : 
    2240        94950 :    cprjdim = xg_nonlop%cprjdim
    2241        94950 :    ncols   = cols(cprj_in)
    2242        94950 :    if (cprjdim/=rows(cprj_in)) then
    2243            0 :      ABI_ERROR('Wrong size for cprj_in')
    2244              :    end if
    2245        94950 :    call xgBlock_check(cprj_in,cprj_out)
    2246        94950 :    call xgBlock_check(cprj_in,cprj_work)
    2247        94950 :    if (rows(A)/=cprjdim.or.cols(A)/=cprjdim) then
    2248            0 :      ABI_ERROR('Wrong size for A')
    2249              :    end if
    2250              : 
    2251        94950 :    call xg_init(err,SPACE_R,ncols,1,xmpi_comm_self)
    2252              : 
    2253        94950 :    call xgBlock_colwiseNorm2(cprj_in,err%self,max_val=norm)
    2254              : 
    2255              :    ! Y_0 = PX (with P block diagonal and "close" to A^-1)
    2256        94950 :    call xgBlock_zero(cprj_out)
    2257        94950 :    call xg_nonlop_apply_Aij(xg_nonlop,precond,cprj_in,cprj_out,A_with_spin=.false.)
    2258              : 
    2259        94950 :    additional_steps_to_take = -1
    2260       708025 :    do iter=1,30
    2261              :      ! compute AY_i
    2262       708025 :      call xgBlock_gemm('n','n',1.0d0,A,cprj_out,0.0d0,cprj_work)
    2263              :      ! ITEST
    2264              :      !write(903,*) 'Apply getBm1X to spd matrix of size', rows(A), cols(A)
    2265              :      !rows_A = rows(A)
    2266              :      !call xgBlock_hermitian_pd_cond(A, rows_A, cond)
    2267              :      !write(903,*) 'cond(B)=', cond
    2268              :      !flush(903)
    2269              :      ! ITEST
    2270              :      ! RES = AY_i - X
    2271       708025 :      call xgBlock_saxpy(cprj_work,-1.0d0,cprj_in)
    2272       708025 :      call xgBlock_colwiseNorm2(cprj_work,err%self,max_val=max_err)
    2273       708025 :      max_err = sqrt(max_err / norm)
    2274       708025 :      if(max_err < tolerance .or. additional_steps_to_take == 1) then
    2275              :        exit
    2276              :        ! We might stall and never get to the specified precision because of machine errors.
    2277              :        ! If we got to 1e-10, extrapolate convergence rate and determine the number of additional
    2278              :        ! steps to take to reach precision
    2279       613085 :      else if(max_err < 1e-10 .and. additional_steps_to_take == -1) then
    2280        94950 :        convergence_rate = -LOG(1e-10) / iter
    2281        94950 :        additional_steps_to_take = CEILING(-LOG(tolerance/1e-10)/convergence_rate) + 1
    2282       518135 :      else if(additional_steps_to_take > 0) then
    2283        94555 :        if(previous_max_err<max_err)exit
    2284        94545 :        additional_steps_to_take = additional_steps_to_take - 1
    2285              :      end if
    2286       613075 :      previous_max_err=max_err
    2287              :      ! RES = X - AY_i
    2288       613075 :      call xgBlock_scale(cprj_work,-1.0d0,1)
    2289              :      ! Y_(i+1) = Y_i + P RES
    2290      1416050 :      call xg_nonlop_apply_Aij(xg_nonlop,precond,cprj_work,cprj_out,A_with_spin=.false.)
    2291              :    end do
    2292              : 
    2293        94950 :    call xg_free(err)
    2294              : 
    2295        94950 :    call timab(tim_iter_refinement,2,tsec)
    2296              : 
    2297        94950 :  end subroutine xg_nonlop_precond_iterative_refinement
    2298              : !!***
    2299              : 
    2300       442258 :  subroutine xg_nonlop_mult_cprj(xg_nonlop,cprj_left,cprj_right,res,blocksize)
    2301              : 
    2302              :    type(xg_nonlop_t), intent(in) :: xg_nonlop
    2303              :    type(xgBlock_t), intent(in) :: cprj_left,cprj_right
    2304              :    type(xgBlock_t), intent(inout) :: res
    2305              :    integer, intent(in),optional :: blocksize
    2306              : 
    2307              :    integer :: space_res
    2308              :    integer :: blocksize_,blocksize_spinor,iblock_mpi,nblocks_mpi,shift_row,shift_col,shift_col_mpi
    2309              :    integer :: iblock_left,iblock_right,nblocks_left,nblocks_right
    2310              :    integer :: res_nrows,res_ncols,cprjdim
    2311              :    integer :: nrows_r,nrows_l,ncols_r,ncols_l,nspinor
    2312              :    integer :: comm_cprj,tag,request,ierr,me_band,source,dest
    2313              :    logical :: multiblock
    2314              :    real(dp) :: tsec(2)
    2315              :    type(xg_t) :: res_work_mpi,res_block,res_block_mpi,cprj_work_mpi
    2316              :    type(xgBlock_t) :: cprj_left_spinor,cprj_right_spinor
    2317              : 
    2318       442258 :    call timab(tim_mult_cprj,1,tsec)
    2319              : 
    2320       442258 :    comm_cprj = comm(cprj_right)
    2321       442258 :    nblocks_mpi = xmpi_comm_size(comm_cprj)
    2322              : 
    2323       442258 :    cprjdim = xg_nonlop%cprjdim
    2324       442258 :    nspinor = xg_nonlop%nspinor
    2325              : 
    2326       442258 :    call xgBlock_reshape_spinor(cprj_right,cprj_right_spinor,nspinor,COLS2ROWS)
    2327       442258 :    call xgBlock_reshape_spinor(cprj_left ,cprj_left_spinor ,nspinor,COLS2ROWS)
    2328              : 
    2329       442258 :    nrows_r = rows(cprj_right_spinor)
    2330       442258 :    nrows_l = rows(cprj_left_spinor)
    2331              : 
    2332       442258 :    ncols_r = cols(cprj_right_spinor)
    2333       442258 :    ncols_l = cols(cprj_left_spinor)
    2334              : 
    2335       442258 :    me_band = xg_nonlop%me_band
    2336              : 
    2337       442258 :    if (nrows_r/=nspinor*cprjdim) then
    2338            0 :      ABI_ERROR("rows(cprj_right)/=nspinor*cprjdim")
    2339              :    end if
    2340       442258 :    if (nrows_l/=nspinor*cprjdim) then
    2341            0 :      ABI_ERROR("rows(cprj_left)/=nspinor*cprjdim")
    2342              :    end if
    2343       442258 :    if (rows(res)/=nblocks_mpi*ncols_l) then
    2344            0 :      ABI_ERROR("rows(res)/=nblocks_mpi*cols(cprj_left)")
    2345              :    end if
    2346       442258 :    if (cols(res)/=nblocks_mpi*ncols_r) then
    2347            0 :      ABI_ERROR("cols(res)/=nblocks_mpi*cols(cprj_right)")
    2348              :    end if
    2349              : 
    2350       442258 :    blocksize_ = ncols_r
    2351       442258 :    if (present(blocksize)) then
    2352       442258 :      if (mod(blocksize,nspinor)/=0) then
    2353            0 :        ABI_ERROR("wrong blocksize (nspinor)")
    2354              :      end if
    2355       442258 :      if (mod(ncols_l,blocksize / nspinor)/=0) then
    2356            0 :        ABI_ERROR("wrong blocksize")
    2357              :      end if
    2358              :      blocksize_ = blocksize
    2359              :    end if
    2360              : 
    2361       442258 :    if (nblocks_mpi==1) then
    2362              : 
    2363       159474 :      call timab(tim_mult_cprj_gemm,1,tsec)
    2364       159474 :      call xgBlock_gemm('t','n',1.0d0,cprj_left_spinor,cprj_right_spinor,1.d0,res)
    2365       159474 :      call timab(tim_mult_cprj_gemm,2,tsec)
    2366              : 
    2367              :    else
    2368              : 
    2369       282784 :      blocksize_spinor = blocksize_ / nspinor
    2370       282784 :      nblocks_right = ncols_r / blocksize_spinor
    2371       282784 :      nblocks_left  = ncols_l / blocksize_spinor
    2372              : 
    2373       282784 :      multiblock = .false.
    2374       282784 :      if (nblocks_right>1.or.nblocks_left>1) then
    2375       164454 :        multiblock = .true.
    2376              :      end if
    2377              : 
    2378       282784 :      res_nrows        = rows(res)
    2379       282784 :      res_ncols        = cols(res)
    2380              : 
    2381       282784 :      space_res = space(cprj_right)
    2382              : 
    2383       282784 :      call xg_init(res_block_mpi,space_res,ncols_l,ncols_r,xmpi_comm_null)
    2384       282784 :      if (multiblock) then
    2385       164454 :        call xg_init(res_block,space_res,blocksize_spinor,blocksize_spinor,xmpi_comm_null)
    2386              :      end if
    2387       282784 :      call xg_init(res_work_mpi,space_res,res_nrows,res_ncols,xmpi_comm_null)
    2388       282784 :      call xgBlock_zero(res_work_mpi%self)
    2389              : 
    2390       282784 :      call xg_init(cprj_work_mpi,space_res,nspinor*cprjdim,ncols_r,comm_cprj)
    2391              : 
    2392      1353528 :      do iblock_mpi=1,nblocks_mpi
    2393              : 
    2394      1070744 :        if (iblock_mpi==1) then
    2395              : 
    2396       282784 :          call timab(tim_mult_cprj_gemm,1,tsec)
    2397       282784 :          call xgBlock_gemm('t','n',1.0d0,cprj_left_spinor,cprj_right_spinor,0.d0,res_block_mpi%self)
    2398       282784 :          call timab(tim_mult_cprj_gemm,2,tsec)
    2399              : 
    2400              :        else
    2401              : 
    2402       787960 :          call timab(tim_mult_cprj_mpi,1,tsec)
    2403       787960 :          tag = iblock_mpi
    2404       787960 :          dest = mod(me_band-(iblock_mpi-1),nblocks_mpi)
    2405       787960 :          if (dest<0) dest=dest+nblocks_mpi
    2406       787960 :          call xgBlock_mpi_isend(cprj_right_spinor,dest,tag,request)
    2407       787960 :          source = mod(me_band+(iblock_mpi-1),nblocks_mpi)
    2408       787960 :          call xgBlock_mpi_recv(cprj_work_mpi%self,source,tag)
    2409       787960 :          call timab(tim_mult_cprj_mpi,2,tsec)
    2410              : 
    2411       787960 :          call timab(tim_mult_cprj_gemm,1,tsec)
    2412       787960 :          call xgBlock_gemm('t','n',1.0d0,cprj_left_spinor,cprj_work_mpi%self,0.d0,res_block_mpi%self)
    2413       787960 :          call timab(tim_mult_cprj_gemm,2,tsec)
    2414              : 
    2415              :        end if
    2416              : 
    2417      1070744 :        if (.not.multiblock) then
    2418       447764 :          shift_row = me_band*ncols_l
    2419       447764 :          shift_col = mod(me_band+iblock_mpi-1,res_ncols)*ncols_r
    2420       447764 :          if (shift_col>=res_ncols) shift_col = shift_col - res_ncols
    2421              : 
    2422       447764 :          call timab(tim_mult_cprj_copy,1,tsec)
    2423       447764 :          call xgBlock_partialcopy(res_block_mpi%self,res_work_mpi%self,shift_row,shift_col,SMALL2BIG)
    2424       447764 :          call timab(tim_mult_cprj_copy,2,tsec)
    2425              : 
    2426              :        else
    2427      1458812 :          do iblock_right=1,nblocks_right
    2428      3689348 :            do iblock_left=1,nblocks_left
    2429      2230536 :              shift_row = (iblock_left-1)*blocksize_spinor
    2430      2230536 :              shift_col = (iblock_right-1)*blocksize_spinor
    2431              : 
    2432      2230536 :              call timab(tim_mult_cprj_copy,1,tsec)
    2433      2230536 :              call xgBlock_partialcopy(res_block_mpi%self,res_block%self,shift_row,shift_col,BIG2SMALL)
    2434      2230536 :              call timab(tim_mult_cprj_copy,2,tsec)
    2435              : 
    2436      2230536 :              shift_row = (me_band*blocksize_spinor) + (iblock_left-1)*res_nrows/nblocks_left
    2437      2230536 :              shift_col_mpi = mod(me_band+iblock_mpi-1,res_ncols/nblocks_right)*blocksize_spinor
    2438      2230536 :              if (shift_col_mpi>=res_ncols/nblocks_right) shift_col_mpi = shift_col_mpi - res_ncols/nblocks_right
    2439      2230536 :              shift_col = shift_col_mpi + (iblock_right-1)*res_ncols/nblocks_right
    2440              : 
    2441      2230536 :              call timab(tim_mult_cprj_copy,1,tsec)
    2442      2230536 :              call xgBlock_partialcopy(res_block%self,res_work_mpi%self,shift_row,shift_col,SMALL2BIG)
    2443      3066368 :              call timab(tim_mult_cprj_copy,2,tsec)
    2444              : 
    2445              :            end do
    2446              :          end do
    2447              :        end if
    2448              : 
    2449      1353528 :        if (iblock_mpi>1) then
    2450       787960 :          call timab(tim_mult_cprj_mpi,1,tsec)
    2451       787960 :          call xmpi_wait(request,ierr)
    2452       787960 :          call timab(tim_mult_cprj_mpi,2,tsec)
    2453              :        end if
    2454              : 
    2455              :      end do
    2456              : 
    2457       282784 :      call timab(tim_mult_cprj_mpi,1,tsec)
    2458       282784 :      call xgBlock_mpi_sum(res_work_mpi%self,comm=comm_cprj)
    2459       282784 :      call timab(tim_mult_cprj_mpi,2,tsec)
    2460              : 
    2461       282784 :      call xgBlock_add(res,res_work_mpi%self)
    2462              : 
    2463       282784 :      if (multiblock) then
    2464       164454 :        call xg_free(res_block)
    2465              :      end if
    2466       282784 :      call xg_free(res_block_mpi)
    2467       282784 :      call xg_free(res_work_mpi)
    2468       282784 :      call xg_free(cprj_work_mpi)
    2469              : 
    2470              :    end if
    2471              : 
    2472       442258 :    call timab(tim_mult_cprj,2,tsec)
    2473              : 
    2474       442258 :  end subroutine xg_nonlop_mult_cprj
    2475              : !!***
    2476              : 
    2477        12920 : subroutine xg_nonlop_colwiseXAX(xg_nonlop,Aij,cprj,cprj_work,res)
    2478              : 
    2479              :    type(xg_nonlop_t), intent(in) :: xg_nonlop
    2480              :    type(xgBlock_t), intent(in) :: cprj,Aij
    2481              :    type(xgBlock_t), intent(inout) :: cprj_work,res
    2482              : 
    2483              :    integer :: ncols
    2484              :    type(xgBlock_t) :: cprj_spinor,cprj_work_spinor
    2485              : 
    2486        12920 :    call xgBlock_check(cprj,cprj_work)
    2487        12920 :    ncols = cols(cprj)
    2488        12920 :    if (ncols/=xg_nonlop%nspinor*rows(res)) then
    2489            0 :      ABI_ERROR('Wrong cols for cprj or res.')
    2490              :    end if
    2491              : 
    2492        12920 :    call xgBlock_zero(cprj_work)
    2493        12920 :    call xg_nonlop_apply_Aij(xg_nonlop,Aij,cprj,cprj_work)
    2494              : 
    2495        12920 :    call xgBlock_reshape_spinor(cprj     ,cprj_spinor     ,xg_nonlop%nspinor,COLS2ROWS)
    2496        12920 :    call xgBlock_reshape_spinor(cprj_work,cprj_work_spinor,xg_nonlop%nspinor,COLS2ROWS)
    2497        12920 :    call xgBlock_colwiseDotProduct(cprj_spinor,cprj_work_spinor,res,comm_loc=xmpi_comm_null)
    2498              : 
    2499        12920 : end subroutine xg_nonlop_colwiseXAX
    2500              : !!***
    2501              : 
    2502         3264 : subroutine xg_nonlop_colwiseXDX(xg_nonlop,diag,cprj,cprj_work,res)
    2503              : 
    2504              :    type(xg_nonlop_t), intent(in) :: xg_nonlop
    2505              :    type(xgBlock_t), intent(in) :: cprj,diag
    2506              :    type(xgBlock_t), intent(inout) :: cprj_work,res
    2507              : 
    2508              :    integer :: ncols,space_diag,space_res
    2509              :    type(xgBlock_t) :: cprj_spinor,cprj_work_spinor
    2510              :    type(xg_t) :: res_complex
    2511              : 
    2512         3264 :    call xgBlock_check(cprj,cprj_work)
    2513         3264 :    ncols = cols(cprj)
    2514         3264 :    if (ncols/=xg_nonlop%nspinor*rows(res)) then
    2515            0 :      ABI_ERROR('Wrong cols for cprj or res.')
    2516              :    end if
    2517         3264 :    space_diag = space(diag)
    2518         3264 :    space_res = space(res)
    2519         3264 :    if (space_diag==SPACE_C) then
    2520            0 :      if (space_res/=SPACE_C) then
    2521            0 :        ABI_ERROR('space(res) should be SPACE_C.')
    2522              :      end if
    2523         3264 :    else if (space_diag/=SPACE_R) then
    2524            0 :      ABI_ERROR('space(diag) should be SPACE_C or SPACE_R.')
    2525              :    end if
    2526              : 
    2527         3264 :    call xgBlock_zero(cprj_work)
    2528         3264 :    call xg_nonlop_apply_diag(xg_nonlop,diag,cprj,cprj_work)
    2529              : 
    2530         3264 :    call xgBlock_reshape_spinor(cprj     ,cprj_spinor     ,xg_nonlop%nspinor,COLS2ROWS)
    2531         3264 :    call xgBlock_reshape_spinor(cprj_work,cprj_work_spinor,xg_nonlop%nspinor,COLS2ROWS)
    2532              : 
    2533              :    ! If space_diag==SPACE_R, the result is actually real and can be stored in a xgBlock with SPACE_R
    2534         3264 :    if ( space_diag==SPACE_R .and. space_res==SPACE_R .and. space(cprj)==SPACE_C) then
    2535          544 :      call xg_init(res_complex,SPACE_C,rows(res),cols(res))
    2536          544 :      call xgBlock_colwiseDotProduct(cprj_spinor,cprj_work_spinor,res_complex%self,comm_loc=xmpi_comm_null)
    2537          544 :      call xgBlock_c2r(res_complex%self,res)
    2538          544 :      call xg_free(res_complex)
    2539              :    else
    2540         2720 :      call xgBlock_colwiseDotProduct(cprj_spinor,cprj_work_spinor,res,comm_loc=xmpi_comm_null)
    2541              :    end if
    2542              : 
    2543         3264 : end subroutine xg_nonlop_colwiseXDX
    2544              : !!***
    2545              : 
    2546         3264 : subroutine xg_nonlop_colwiseXHX(xg_nonlop,cprj,cprj_work,res)
    2547              : 
    2548              :    type(xg_nonlop_t), intent(in) :: xg_nonlop
    2549              :    type(xgBlock_t), intent(in) :: cprj
    2550              :    type(xgBlock_t), intent(inout) :: cprj_work,res
    2551              : 
    2552              :    integer :: nmpi,ncols,nres,shift
    2553              : !   type(xg_t) :: res_mpi
    2554              :    type(xgBlock_t) :: res_mpi,res_tmp
    2555              : 
    2556         3264 :    if (cols(res)/=1) then
    2557            0 :      ABI_ERROR('cols(res)/=1')
    2558              :    end if
    2559         3264 :    nmpi = xmpi_comm_size(comm(cprj))
    2560         3264 :    ncols = cols(cprj)
    2561         3264 :    nres = rows(res)
    2562         3264 :    if (nres*xg_nonlop%nspinor/=nmpi*ncols) then
    2563            0 :      ABI_ERROR('rows(res)*nspinor/=nmpi*cols(cprj))')
    2564              :    end if
    2565              : 
    2566         3264 :    call xgBlock_zero(res)
    2567              : 
    2568         3264 :    if (nmpi==1) then
    2569         1088 :      res_mpi = res
    2570              :    else
    2571         2176 :      call xgBlock_setBlock(res,res_tmp,nres,1)
    2572         2176 :      call xgBlock_reshape(res_tmp,1,nres)
    2573         2176 :      shift = xg_nonlop%me_band*ncols
    2574         2176 :      call xgBlock_setBlock(res_tmp,res_mpi,1,ncols,fcol=1+shift)
    2575         2176 :      call xgBlock_reshape(res_mpi,ncols,1)
    2576              :    end if
    2577              : 
    2578         3264 :    if (xg_nonlop%paw) then
    2579            0 :      call xg_nonlop_colwiseXAX(xg_nonlop,xg_nonlop%Dij_spin,cprj,cprj_work,res_mpi)
    2580              :    else
    2581         3264 :      call xg_nonlop_colwiseXDX(xg_nonlop,xg_nonlop%ekb%self,cprj,cprj_work,res_mpi)
    2582              :    end if
    2583              : 
    2584         3264 :    call xgBlock_mpi_sum(res,comm=xg_nonlop%comm_band)
    2585              : 
    2586         3264 : end subroutine xg_nonlop_colwiseXHX
    2587              : !!***
    2588              : 
    2589       410705 : subroutine xg_nonlop_getXAY(xg_nonlop,Aij,cprj_left,cprj_right,cprj_work,res,blocksize)
    2590              : 
    2591              :    type(xg_nonlop_t), intent(in) :: xg_nonlop
    2592              :    type(xgBlock_t), intent(in) :: cprj_left,cprj_right,Aij
    2593              :    type(xgBlock_t), intent(inout) :: cprj_work,res
    2594              :    integer,intent(in),optional :: blocksize
    2595              : 
    2596              :    integer :: blocksize_
    2597              : 
    2598       410705 :    call xgBlock_zero(cprj_work)
    2599       410705 :    call xg_nonlop_apply_Aij(xg_nonlop,Aij,cprj_right,cprj_work)
    2600              : 
    2601       410705 :    blocksize_ = cols(cprj_right)
    2602       410705 :    if (present(blocksize)) then
    2603       410705 :      blocksize_ = blocksize
    2604              :    end if
    2605       410705 :    call xg_nonlop_mult_cprj(xg_nonlop,cprj_left,cprj_work,res,blocksize=blocksize_)
    2606              : 
    2607       410705 :  end subroutine xg_nonlop_getXAY
    2608              : !!***
    2609              : 
    2610        31553 : subroutine xg_nonlop_getXDY(xg_nonlop,diag,cprj_left,cprj_right,cprj_work,res,blocksize)
    2611              : 
    2612              :    type(xg_nonlop_t), intent(in) :: xg_nonlop
    2613              :    type(xgBlock_t), intent(in) :: cprj_left,cprj_right,diag
    2614              :    type(xgBlock_t), intent(inout) :: cprj_work,res
    2615              :    integer,intent(in),optional :: blocksize
    2616              : 
    2617              :    integer :: blocksize_
    2618              : 
    2619        31553 :    call xgBlock_zero(cprj_work)
    2620        31553 :    call xg_nonlop_apply_diag(xg_nonlop,diag,cprj_right,cprj_work)
    2621              : 
    2622        31553 :    blocksize_ = cols(cprj_right)
    2623        31553 :    if (present(blocksize)) then
    2624        31553 :      blocksize_ = blocksize
    2625              :    end if
    2626        31553 :    call xg_nonlop_mult_cprj(xg_nonlop,cprj_left,cprj_work,res,blocksize=blocksize_)
    2627              : 
    2628        31553 :  end subroutine xg_nonlop_getXDY
    2629              : !!***
    2630              : 
    2631       255088 : subroutine xg_nonlop_getXSY(xg_nonlop,cprj_left,cprj_right,cprj_work,res,blocksize)
    2632              : 
    2633              :    type(xg_nonlop_t), intent(in) :: xg_nonlop
    2634              :    type(xgBlock_t), intent(inout) :: cprj_left,cprj_right,cprj_work,res
    2635              :    integer,intent(in),optional :: blocksize
    2636              : 
    2637              :    integer :: blocksize_
    2638              : 
    2639              :    real(dp) :: tsec(2)
    2640              : 
    2641       255088 :    call timab(tim_getXSY,1,tsec)
    2642              : 
    2643       255088 :    if (.not.xg_nonlop%paw) then
    2644            0 :      ABI_ERROR('Not implemented with paw=False.')
    2645              :    end if
    2646              : 
    2647       255088 :    blocksize_ = cols(cprj_right)
    2648       255088 :    if (present(blocksize)) then
    2649       217434 :      blocksize_ = blocksize
    2650              :    end if
    2651       255088 :    call xg_nonlop_getXAY(xg_nonlop,xg_nonlop%Sij%self,cprj_left,cprj_right,cprj_work,res,blocksize=blocksize_)
    2652              : 
    2653       255088 :    call timab(tim_getXSY,2,tsec)
    2654              : 
    2655       255088 :  end subroutine xg_nonlop_getXSY
    2656              : !!***
    2657              : 
    2658       187170 : subroutine xg_nonlop_getXHY(xg_nonlop,cprj_left,cprj_right,cprj_work,res,blocksize)
    2659              : 
    2660              :    type(xg_nonlop_t), intent(in) :: xg_nonlop
    2661              :    type(xgBlock_t), intent(inout) :: cprj_left,cprj_right,cprj_work,res
    2662              :    integer,intent(in),optional :: blocksize
    2663              : 
    2664              :    integer :: blocksize_
    2665              : 
    2666              :    real(dp) :: tsec(2)
    2667              : 
    2668       187170 :    call timab(tim_getXHY,1,tsec)
    2669              : 
    2670       187170 :    blocksize_ = cols(cprj_right)
    2671       187170 :    if (present(blocksize)) then
    2672       187170 :      blocksize_ = blocksize
    2673              :    end if
    2674       187170 :    if (xg_nonlop%paw) then
    2675       155617 :      call xg_nonlop_getXAY(xg_nonlop,xg_nonlop%Dij_spin,cprj_left,cprj_right,cprj_work,res,blocksize=blocksize_)
    2676              :    else
    2677        31553 :      call xg_nonlop_getXDY(xg_nonlop,xg_nonlop%ekb%self,cprj_left,cprj_right,cprj_work,res,blocksize=blocksize_)
    2678              :    end if
    2679              : 
    2680       187170 :    call timab(tim_getXHY,2,tsec)
    2681              : 
    2682       187170 :  end subroutine xg_nonlop_getXHY
    2683              : !!***
    2684              : 
    2685       330546 :  subroutine xg_nonlop_getAX(xg_nonlop,Aij,Xin,cprjin,cprj_work,work_mpi,Xout)
    2686              : 
    2687              :    use iso_c_binding
    2688              : 
    2689              :    type(xg_nonlop_t), intent(in) :: xg_nonlop
    2690              :    type(xgBlock_t), intent(in) :: cprjin,Aij
    2691              :    type(xgBlock_t), intent(inout) :: Xin,cprj_work,work_mpi
    2692              :    type(xgBlock_t), optional, intent(inout) :: Xout
    2693              : 
    2694              :    integer :: nblocks,nspinor
    2695              :    integer :: nrows,nrows_cprj
    2696              :    integer :: ncols,ncols_cprj
    2697              : 
    2698       110182 :    nblocks = xmpi_comm_size(comm(cprjin))
    2699              : 
    2700       110182 :    nspinor = xg_nonlop%nspinor
    2701              : 
    2702              :    ! check sizes
    2703       110182 :    if (present(Xout)) then
    2704            0 :      call xgBlock_check(Xin,Xout)
    2705              :    end if
    2706       110182 :    call xgBlock_check(cprjin,cprj_work)
    2707       110182 :    call xgBlock_getsize(Xin,nrows,ncols)
    2708       110182 :    call xgBlock_getsize(cprjin,nrows_cprj,ncols_cprj)
    2709              : 
    2710              :    ! cprj_work = sum_j Saij cprjin
    2711       110182 :    call xgBlock_zero(cprj_work)
    2712       110182 :    call xg_nonlop_apply_Aij(xg_nonlop,Aij,cprjin,cprj_work)
    2713              : 
    2714              :    ! Xout = Xin + sum_ai pai cprj_work
    2715       110182 :    if (present(Xout)) then
    2716            0 :      call xgBlock_copy(Xin,Xout)
    2717            0 :      call xg_nonlop_apply_prj(xg_nonlop,cprj_work,Xout,work_mpi)
    2718              :    else ! in place version
    2719       110182 :      call xg_nonlop_apply_prj(xg_nonlop,cprj_work,Xin,work_mpi)
    2720              :    end if
    2721              : 
    2722       110182 :  end subroutine xg_nonlop_getAX
    2723              : 
    2724       103665 :  subroutine xg_nonlop_getDX(xg_nonlop,diag,Xin,cprjin,cprj_work,work_mpi,Xout)
    2725              : 
    2726              :    use iso_c_binding
    2727              : 
    2728              :    type(xg_nonlop_t), intent(in) :: xg_nonlop
    2729              :    type(xgBlock_t), intent(in) :: cprjin,diag
    2730              :    type(xgBlock_t), intent(inout) :: Xin,cprj_work,work_mpi
    2731              :    type(xgBlock_t), optional, intent(inout) :: Xout
    2732              : 
    2733              :    integer :: nblocks,nspinor
    2734              :    integer :: nrows,nrows_cprj
    2735              :    integer :: ncols,ncols_cprj
    2736              : 
    2737        34555 :    nblocks = xmpi_comm_size(comm(cprjin))
    2738              : 
    2739        34555 :    nspinor = xg_nonlop%nspinor
    2740              : 
    2741              :    ! check sizes
    2742        34555 :    if (present(Xout)) then
    2743            0 :      call xgBlock_check(Xin,Xout)
    2744              :    end if
    2745        34555 :    call xgBlock_check(cprjin,cprj_work)
    2746        34555 :    call xgBlock_getsize(Xin,nrows,ncols)
    2747        34555 :    call xgBlock_getsize(cprjin,nrows_cprj,ncols_cprj)
    2748              : 
    2749              :    ! cprj_work = sum_j Saij cprjin
    2750        34555 :    call xgBlock_zero(cprj_work)
    2751        34555 :    call xg_nonlop_apply_diag(xg_nonlop,diag,cprjin,cprj_work)
    2752              : 
    2753              :    ! Xout = Xin + sum_ai pai cprj_work
    2754        34555 :    if (present(Xout)) then
    2755            0 :      call xgBlock_copy(Xin,Xout)
    2756            0 :      call xg_nonlop_apply_prj(xg_nonlop,cprj_work,Xout,work_mpi)
    2757              :    else ! in place version
    2758        34555 :      call xg_nonlop_apply_prj(xg_nonlop,cprj_work,Xin,work_mpi)
    2759              :    end if
    2760              : 
    2761        34555 :  end subroutine xg_nonlop_getDX
    2762              : 
    2763       142425 :  subroutine xg_nonlop_getHX(xg_nonlop,Xin,cprjin,cprj_work,work_mpi,Xout)
    2764              : 
    2765              :    use iso_c_binding
    2766              : 
    2767              :    type(xg_nonlop_t), intent(in) :: xg_nonlop
    2768              :    type(xgBlock_t), intent(in) :: cprjin
    2769              :    type(xgBlock_t), intent(inout) :: Xin,cprj_work,work_mpi
    2770              :    type(xgBlock_t), optional, intent(inout) :: Xout
    2771              : 
    2772       142425 :    if (present(Xout)) then
    2773            0 :      if (xg_nonlop%paw) then
    2774            0 :        call xg_nonlop_getAX(xg_nonlop,xg_nonlop%Dij_spin,Xin,cprjin,cprj_work,work_mpi,Xout=Xout)
    2775              :      else
    2776            0 :        call xg_nonlop_getDX(xg_nonlop,xg_nonlop%ekb%self,Xin,cprjin,cprj_work,work_mpi,Xout=Xout)
    2777              :      end if
    2778              :    else
    2779       142425 :      if (xg_nonlop%paw) then
    2780       107870 :        call xg_nonlop_getAX(xg_nonlop,xg_nonlop%Dij_spin,Xin,cprjin,cprj_work,work_mpi)
    2781              :      else
    2782        34555 :        call xg_nonlop_getDX(xg_nonlop,xg_nonlop%ekb%self,Xin,cprjin,cprj_work,work_mpi)
    2783              :      end if
    2784              :    end if
    2785              : 
    2786       142425 :  end subroutine xg_nonlop_getHX
    2787              : 
    2788         2312 :  subroutine xg_nonlop_getSX(xg_nonlop,Xin,cprjin,cprj_work,work_mpi,Xout)
    2789              : 
    2790              :    use iso_c_binding
    2791              : 
    2792              :    type(xg_nonlop_t), intent(in) :: xg_nonlop
    2793              :    type(xgBlock_t), intent(in) :: cprjin
    2794              :    type(xgBlock_t), intent(inout) :: Xin,cprj_work,work_mpi
    2795              :    type(xgBlock_t), optional, intent(inout) :: Xout
    2796              : 
    2797         2312 :    if (.not.xg_nonlop%paw) then
    2798            0 :      ABI_ERROR('Not implemented with paw=False.')
    2799              :    end if
    2800              : 
    2801         2312 :    call xg_nonlop_getAX(xg_nonlop,xg_nonlop%Sij%self,Xin,cprjin,cprj_work,work_mpi,Xout)
    2802              : 
    2803         2312 :  end subroutine xg_nonlop_getSX
    2804              : 
    2805       284850 :  subroutine xg_nonlop_getSm1X(xg_nonlop,Xin,cprjin,cprj_work1,cprj_work2,work_mpi,Xout)
    2806              : 
    2807              :    use iso_c_binding
    2808              : 
    2809              :    type(xg_nonlop_t), intent(in) :: xg_nonlop
    2810              :    type(xgBlock_t), intent(in) :: cprjin
    2811              :    type(xgBlock_t), intent(inout) :: Xin,cprj_work1,cprj_work2,work_mpi
    2812              :    type(xgBlock_t), optional, intent(inout) :: Xout
    2813              : 
    2814              :    integer :: nblocks,nspinor
    2815              :    integer :: nrows,nrows_cprj
    2816              :    integer :: ncols,ncols_cprj
    2817              : 
    2818        94950 :    if (.not.xg_nonlop%paw) then
    2819            0 :      ABI_ERROR('Not implemented with paw=False.')
    2820              :    end if
    2821              : 
    2822        94950 :    nblocks = xmpi_comm_size(comm(cprjin))
    2823              : 
    2824        94950 :    nspinor = xg_nonlop%nspinor
    2825              : 
    2826        94950 :    if (present(Xout)) then
    2827            0 :      call xgBlock_check(Xin,Xout)
    2828              :    end if
    2829        94950 :    call xgBlock_check(cprjin,cprj_work1)
    2830        94950 :    call xgBlock_check(cprjin,cprj_work2)
    2831        94950 :    call xgBlock_getsize(Xin,nrows,ncols)
    2832        94950 :    call xgBlock_getsize(cprjin,nrows_cprj,ncols_cprj)
    2833        94950 :    if (.not.associated(xg_nonlop%invSij_approx_k)) then
    2834            0 :      ABI_ERROR('invSij_approx not associated')
    2835              :    end if
    2836        94950 :    if (.not.associated(xg_nonlop%gram_proj_k)) then
    2837            0 :      ABI_ERROR('gram_proj_k should be associated')
    2838              :    end if
    2839              : 
    2840              :    call xg_nonlop_precond_iterative_refinement(xg_nonlop,xg_nonlop%gram_proj_k%self,xg_nonlop%invSij_approx_k%self,&
    2841        94950 :      & cprjin,cprj_work1,cprj_work2)
    2842        94950 :    call xgBlock_scale(cprj_work1,-1.0d0,1)
    2843              : 
    2844              :    ! Xout = Xin + sum_ai pai cprj_work
    2845        94950 :    if (present(Xout)) then
    2846            0 :      call xgBlock_copy(Xin,Xout)
    2847            0 :      call xg_nonlop_apply_prj(xg_nonlop,cprj_work1,Xout,work_mpi)
    2848              :    else ! in place version
    2849        94950 :      call xg_nonlop_apply_prj(xg_nonlop,cprj_work1,Xin,work_mpi)
    2850              :    end if
    2851              : 
    2852        94950 :  end subroutine xg_nonlop_getSm1X
    2853              : 
    2854       450870 :  subroutine xg_nonlop_getHmeSX(xg_nonlop,Xin,cprjin,Xout,eigen,cprj_work,work_mpi,no_H)
    2855              : 
    2856              :    use iso_c_binding
    2857              : 
    2858              :    type(xg_nonlop_t), intent(in) :: xg_nonlop
    2859              :    type(xgBlock_t), intent(in) :: Xin,eigen,cprjin
    2860              :    type(xgBlock_t), intent(inout) :: Xout,cprj_work,work_mpi
    2861              :    logical,optional,intent(in) :: no_H
    2862              : 
    2863              :    real(dp) :: tsec(2)
    2864              :    integer :: nblocks,shift
    2865              :    integer :: nrows,ncols,nrows_out,ncols_out
    2866              :    integer :: nrows_diag,ncols_diag
    2867              :    integer :: nrows_cprj,ncols_cprj
    2868              :    integer :: nrows_cprj_work,ncols_cprj_work
    2869              :    integer :: nspinor
    2870              :    logical :: no_H_
    2871              :    type(xgBlock_t) :: cprj_work_spinor
    2872              : 
    2873        75145 :    call timab(tim_getHmeSX,1,tsec)
    2874              : 
    2875        75145 :    if (.not.xg_nonlop%paw) then
    2876            0 :      ABI_ERROR('Not implemented with paw=False.')
    2877              :    end if
    2878              : 
    2879        75145 :    nblocks = xmpi_comm_size(comm(cprjin))
    2880              : 
    2881        75145 :    nspinor = xg_nonlop%nspinor
    2882              : 
    2883        75145 :    call xgBlock_getsize(Xin,nrows,ncols)
    2884        75145 :    call xgBlock_getsize(Xout,nrows_out,ncols_out)
    2885        75145 :    call xgBlock_getsize(eigen,nrows_diag,ncols_diag)
    2886        75145 :    call xgBlock_getsize(cprjin,nrows_cprj,ncols_cprj)
    2887        75145 :    call xgBlock_getsize(cprj_work,nrows_cprj_work,ncols_cprj_work)
    2888        75145 :    if (ncols/=nrows_diag.or.ncols*nspinor/=nblocks*ncols_cprj.or.ncols_cprj/=ncols_cprj_work.or.ncols/=ncols_out) then
    2889            0 :      ABI_ERROR('wrong ncols')
    2890              :    end if
    2891        75145 :    if (nrows/=nrows_out) then
    2892            0 :      ABI_ERROR('nrows/=nrows_out')
    2893              :    end if
    2894        75145 :    if (nrows_cprj/=nrows_cprj_work) then
    2895            0 :      ABI_ERROR('nrows_cprj/=nrows_cprj_work')
    2896              :    end if
    2897        75145 :    if (ncols_diag/=1) then
    2898            0 :      ABI_ERROR('ncols_diag should be one')
    2899              :    end if
    2900              : 
    2901              :    ! cprj_work = sum_j Saij cprjin
    2902        75145 :    call xgBlock_zero(cprj_work)
    2903        75145 :    call xg_nonlop_apply_Aij(xg_nonlop,xg_nonlop%Sij%self,cprjin,cprj_work)
    2904              : 
    2905              :    ! cprj_work = - e cprj_work = -e sum_j Saij cprjin
    2906        75145 :    shift = xg_nonlop%me_band*ncols_cprj/xg_nonlop%nspinor
    2907        75145 :    call xgBlock_reshape_spinor(cprj_work,cprj_work_spinor,nspinor,COLS2ROWS)
    2908        75145 :    call xgBlock_ymax(cprj_work_spinor,eigen,shift,nblocks)
    2909              : 
    2910        75145 :    no_H_=.False.
    2911        75145 :    if (present(no_H)) then
    2912        12920 :      no_H_ = no_H
    2913              :    end if
    2914        12920 :    if (.not.no_H_) then
    2915              :      ! cprj_work = sum_j Daij cprjin + cprj_work
    2916        62225 :      call xg_nonlop_apply_Aij(xg_nonlop,xg_nonlop%Dij_spin,cprjin,cprj_work)
    2917              :    end if
    2918              : 
    2919              :    ! Xout = Xout + sum_ai pai cprj_work
    2920        75145 :    call xg_nonlop_apply_prj(xg_nonlop,cprj_work,Xout,work_mpi)
    2921              : 
    2922              :    ! Xout = Xout - e Xin
    2923        75145 :    call xgBlock_yxmax(Xout,eigen,Xin)
    2924              : 
    2925        75145 :    call timab(tim_getHmeSX,2,tsec)
    2926              : 
    2927        75145 :  end subroutine xg_nonlop_getHmeSX
    2928              : !!***
    2929              : 
    2930              : !!****f* m_xg_nonlop/xg_nonlop_forces
    2931              : !! NAME
    2932              : !!
    2933              : !! FUNCTION
    2934              : !!
    2935              : !! INPUTS
    2936              : !!
    2937        19100 : subroutine xg_nonlop_forces_stress(xg_nonlop,Xin,cprjin,cprj_work,eigen,forces,stress,gprimd)
    2938              : 
    2939              :    use m_geometry, only : strconv
    2940              : 
    2941              :    type(xg_nonlop_t), intent(in) :: xg_nonlop
    2942              :    type(xgBlock_t), intent(in) :: Xin,eigen
    2943              :    type(xgBlock_t), intent(in) :: cprjin
    2944              :    type(xgBlock_t), intent(inout) :: cprj_work
    2945              :    type(xgBlock_t), optional, intent(inout) :: forces
    2946              :    type(xgBlock_t), optional, intent(inout) :: stress
    2947              :    real(dp), optional, intent(in) :: gprimd(:,:)
    2948              : 
    2949              :    real(dp) :: tsec(2)
    2950              :    integer :: cplex,iband
    2951              :    integer :: nmpi,shift
    2952              :    integer :: nrows,ncols,ncols_cprj,ncols_cprj_nospin
    2953              :    integer :: nrows_diag,ncols_diag
    2954              :    integer :: nspinor,space_cprj
    2955              : 
    2956              :    type(xg_t) :: cprj_deriv,work_mpi_deriv,dot,dot_all
    2957        19100 :    real(dp), pointer :: dot_(:,:),dot_all_(:,:)
    2958              :    logical :: do_forces,do_stress
    2959              :    real(dp) :: work(6)
    2960        19100 :    real(dp), pointer :: stress_(:,:)
    2961              :    type(xgBlock_t) :: cprjin_spinor,cprj_work_spinor
    2962              : 
    2963        19100 :    call timab(tim_forces_stress,1,tsec)
    2964              : 
    2965        19100 :    call timab(tim_fst_start,1,tsec)
    2966              : 
    2967        19100 :    if (comm(Xin)/=xg_nonlop%comm_band) then
    2968            0 :      ABI_ERROR('wrong communicator')
    2969              :    end if
    2970              : 
    2971        19100 :    nmpi = xmpi_comm_size(comm(Xin))
    2972        19100 :    nspinor = xg_nonlop%nspinor
    2973              : 
    2974        19100 :    call xgBlock_getsize(Xin,nrows,ncols)
    2975        19100 :    call xgBlock_getsize(eigen,nrows_diag,ncols_diag)
    2976        19100 :    if (ncols/=nrows_diag) then
    2977            0 :      ABI_ERROR('wrong ncols')
    2978              :    end if
    2979        19100 :    if (ncols_diag/=1) then
    2980            0 :      ABI_ERROR('ncols_diag should be one')
    2981              :    end if
    2982              : 
    2983        19100 :    ncols_cprj = ncols*nspinor/nmpi
    2984        19100 :    ncols_cprj_nospin = ncols/nmpi
    2985              : 
    2986        19100 :    space_cprj = xg_nonlop%space_cprj
    2987              : 
    2988        19100 :    do_forces = .false.
    2989        19100 :    if (present(forces)) then
    2990        18300 :      do_forces = .true.
    2991        18300 :      if (rows(forces)/=3*xg_nonlop%natom) then
    2992            0 :        ABI_ERROR('rows(forces)/=3*natom')
    2993              :      end if
    2994        18300 :      if (cols(forces)/=ncols) then
    2995            0 :        ABI_ERROR('cols(forces)/=ncols')
    2996              :      end if
    2997              :    end if
    2998              : 
    2999        19100 :    do_stress = .false.
    3000        19100 :    if (present(stress)) then
    3001         1140 :      do_stress = .true.
    3002         1140 :      if (.not.present(gprimd)) then
    3003            0 :        ABI_ERROR('If stress is present, gprimd must be present too')
    3004              :      end if
    3005         1140 :      if (rows(stress)/=6) then
    3006            0 :        ABI_ERROR('rows(stress)/=6')
    3007              :      end if
    3008         1140 :      if (cols(stress)/=ncols) then
    3009            0 :        ABI_ERROR('cols(stress)/=ncols')
    3010              :      end if
    3011              :    end if
    3012              : 
    3013        19100 :    call xgBlock_zero(cprj_work)
    3014        19100 :    if (xg_nonlop%paw) then
    3015              :      ! cprj_work = sum_j Saij cprjin
    3016        17212 :      call xg_nonlop_apply_Aij(xg_nonlop,xg_nonlop%Sij%self,cprjin,cprj_work)
    3017              :      ! cprj_work = - e cprj_work = -e sum_j Saij cprjin
    3018        17212 :      shift = xg_nonlop%me_band*ncols_cprj_nospin
    3019        17212 :      call xgBlock_reshape_spinor(cprj_work,cprj_work_spinor,nspinor,COLS2ROWS)
    3020        17212 :      call xgBlock_ymax(cprj_work_spinor,eigen,shift,nmpi)
    3021              :    end if
    3022              : 
    3023              :    ! cprj_work = sum_j Daij cprjin + cprj_work
    3024        19100 :    if (xg_nonlop%paw) then
    3025        17212 :      call xg_nonlop_apply_Aij(xg_nonlop,xg_nonlop%Dij_spin,cprjin,cprj_work)
    3026              :    else
    3027         1888 :      call xg_nonlop_apply_diag(xg_nonlop,xg_nonlop%ekb%self,cprjin,cprj_work)
    3028              :    end if
    3029              : 
    3030        19100 :    call timab(tim_fst_start,2,tsec)
    3031              : 
    3032        19100 :    if (do_forces) then
    3033              : 
    3034        18300 :      call xg_init(cprj_deriv    ,space_cprj,3*xg_nonlop%cprjdim,ncols_cprj,comm=xg_nonlop%comm_band)
    3035        18300 :      call xg_init(work_mpi_deriv,space_cprj,3*xg_nonlop%cprjdim,ncols_cprj,comm=xg_nonlop%comm_band)
    3036              : 
    3037        18300 :      call timab(tim_fst_cprj_deriv_f,1,tsec)
    3038        18300 :      call xg_nonlop_getcprj_deriv(xg_nonlop,Xin,cprj_deriv%self,work_mpi_deriv%self,DERIV_ATOM)
    3039        18300 :      call timab(tim_fst_cprj_deriv_f,2,tsec)
    3040              : 
    3041        18300 :      call xg_free(work_mpi_deriv)
    3042              : 
    3043        18300 :      call xgBlock_zero(forces)
    3044              : 
    3045        18300 :      call timab(tim_fst_mult_cprj_f,1,tsec)
    3046        18300 :      call xg_nonlop_mult_cprj_forces(xg_nonlop,cprj_work,cprj_deriv%self,forces)
    3047        18300 :      call timab(tim_fst_mult_cprj_f,2,tsec)
    3048              : 
    3049        18300 :      call xg_free(cprj_deriv)
    3050              : 
    3051              :    end if
    3052              : 
    3053        19100 :    if (do_stress) then
    3054              : 
    3055         1140 :      call xg_init(cprj_deriv    ,space_cprj,6*xg_nonlop%cprjdim,ncols_cprj,comm=xg_nonlop%comm_band)
    3056         1140 :      call xg_init(work_mpi_deriv,space_cprj,6*xg_nonlop%cprjdim,ncols_cprj,comm=xg_nonlop%comm_band)
    3057              : 
    3058         1140 :      call timab(tim_fst_cprj_deriv_str,1,tsec)
    3059         1140 :      call xg_nonlop_getcprj_deriv(xg_nonlop,Xin,cprj_deriv%self,work_mpi_deriv%self,DERIV_STRESS)
    3060         1140 :      call timab(tim_fst_cprj_deriv_str,2,tsec)
    3061              : 
    3062         1140 :      call xg_free(work_mpi_deriv)
    3063              : 
    3064         1140 :      call xgBlock_zero(stress)
    3065              : 
    3066         1140 :      call timab(tim_fst_mult_cprj_str,1,tsec)
    3067         1140 :      call xg_nonlop_mult_cprj_stress(xg_nonlop,cprj_work,cprj_deriv%self,stress)
    3068         1140 :      call timab(tim_fst_mult_cprj_str,2,tsec)
    3069              : 
    3070         1140 :      call xg_free(cprj_deriv)
    3071              : 
    3072         1140 :      call timab(tim_fst_work_str,1,tsec)
    3073         1140 :      call xg_init(dot,space_cprj,ncols_cprj_nospin,1)
    3074              : 
    3075         1140 :      call xgBlock_reshape_spinor(cprjin,cprjin_spinor,nspinor,COLS2ROWS)
    3076         1140 :      call xgBlock_reshape_spinor(cprj_work,cprj_work_spinor,nspinor,COLS2ROWS)
    3077         1140 :      call xgBlock_colwiseDotProduct(cprjin_spinor,cprj_work_spinor,dot%self,comm_loc=xmpi_comm_null)
    3078              : 
    3079         1140 :      cplex=1
    3080         1140 :      if (space_cprj==SPACE_C) cplex=2
    3081              : 
    3082         1140 :      call xg_init(dot_all,space_cprj,ncols,1)
    3083         1140 :      if (xmpi_comm_size(xg_nonlop%comm_band)>1) then
    3084          768 :        call xgBlock_zero(dot_all%self)
    3085          768 :        call xgBlock_reverseMap(dot%self,dot_)
    3086          768 :        call xgBlock_reverseMap(dot_all%self,dot_all_)
    3087          768 :        shift = cplex*xg_nonlop%me_band*ncols_cprj_nospin
    3088         2752 :        do iband=1,ncols_cprj_nospin
    3089         2752 :          dot_all_(1+cplex*(iband-1)+shift,1) = dot_(1+cplex*(iband-1),1)
    3090              :        end do
    3091          768 :        call xgBlock_mpi_sum(dot_all%self,comm=xg_nonlop%comm_band)
    3092              :      else
    3093          372 :        call xgBlock_reverseMap(dot%self,dot_all_)
    3094              :      end if
    3095              : 
    3096         1140 :      call xgBlock_reverseMap(stress,stress_)
    3097              : 
    3098        11208 :      do iband=1,ncols
    3099        70476 :        work = stress_(:,iband)
    3100        10068 :        call strconv(work,gprimd,work)
    3101        40272 :        stress_(1:3,iband) = work(1:3) - dot_all_(1+cplex*(iband-1),1)
    3102        41412 :        stress_(4:6,iband) = work(4:6)
    3103              :      end do
    3104              : 
    3105         1140 :      call xg_free(dot)
    3106         1140 :      call xg_free(dot_all)
    3107              : 
    3108         1140 :      call timab(tim_fst_work_str,2,tsec)
    3109              : 
    3110              :    end if
    3111              : 
    3112        19100 :    call timab(tim_forces_stress,2,tsec)
    3113              : 
    3114        19100 :  end subroutine xg_nonlop_forces_stress
    3115              : !!***
    3116              : 
    3117        18300 :  subroutine xg_nonlop_mult_cprj_forces(xg_nonlop,cprj,cprj_deriv,forces)
    3118              : 
    3119              :    type(xg_nonlop_t), intent(in) :: xg_nonlop
    3120              :    type(xgBlock_t), intent(in) :: cprj,cprj_deriv
    3121              :    type(xgBlock_t), intent(inout) :: forces
    3122              : 
    3123              :    !real(dp) :: tsec(2)
    3124              :    integer :: ia,idir,ilmn,iband,iband_spinor,my_iband,itypat,nlmn,nattyp_i
    3125              :    integer :: ispinor,iforces,icprj,icprj_deriv
    3126              :    integer :: ncols_cprj,ncols_cprj_nospin
    3127              :    integer :: nspinor
    3128              :    integer :: shift_itypat,shift_itypat_nlmn,shift_itypat_3nlmn
    3129              : 
    3130        18300 :    real(dp), pointer :: forces_(:,:)
    3131        18300 :    complex(dp), pointer :: cprj_(:,:),cprj_deriv_(:,:)
    3132        18300 :    real(dp), pointer :: cprj_real(:,:),cprj_deriv_real(:,:)
    3133              :    real(dp) :: forces_tmp
    3134              : 
    3135        18300 :    nspinor = xg_nonlop%nspinor
    3136              : 
    3137        18300 :    ncols_cprj = cols(cprj)
    3138        18300 :    ncols_cprj_nospin = ncols_cprj/nspinor
    3139              : 
    3140        18300 :    call xgBlock_reverseMap(forces,forces_)
    3141              : 
    3142        28903 :    select case(xg_nonlop%space_cprj)
    3143              : 
    3144              :      case (SPACE_C)
    3145              : 
    3146        10603 :        call xgBlock_reverseMap(cprj,cprj_)
    3147        10603 :        call xgBlock_reverseMap(cprj_deriv,cprj_deriv_)
    3148              : 
    3149        10603 :        shift_itypat=0
    3150        10603 :        shift_itypat_nlmn=0
    3151        10603 :        shift_itypat_3nlmn=0
    3152              :        !$omp parallel default (none) &
    3153              :        !$omp& shared(xg_nonlop,forces_,cprj_deriv_,cprj_), &
    3154              :        !$omp& firstprivate(shift_itypat,shift_itypat_nlmn,shift_itypat_3nlmn,ncols_cprj_nospin,nspinor), &
    3155              :        !$omp& private(itypat,nattyp_i,nlmn,ia,ilmn,idir,iforces,my_iband), &
    3156              :        !$omp& private(iband_spinor,icprj,icprj_deriv,forces_tmp)
    3157        32376 :        do itypat = 1, xg_nonlop%ntypat
    3158        21773 :          nlmn = xg_nonlop%nlmn_ntypat(itypat)
    3159        21773 :          nattyp_i = xg_nonlop%nattyp(itypat)
    3160        32376 :          if (nattyp_i>0) then
    3161              :            !$omp do collapse(3)
    3162        91565 :            do iband=1,ncols_cprj_nospin
    3163       163021 :              do ia = 1, nattyp_i
    3164       356232 :                do idir=1,3
    3165              :                  forces_tmp = zero
    3166       512880 :                  do ispinor=1,nspinor
    3167      3146064 :                    do ilmn=1,nlmn
    3168      2633184 :                      iband_spinor = ispinor + nspinor*(iband-1)
    3169      2633184 :                      icprj       = ilmn + nlmn*(ia-1) + shift_itypat_nlmn
    3170      2633184 :                      icprj_deriv = ilmn + nlmn*(idir-1) + 3*nlmn*(ia-1) + shift_itypat_3nlmn
    3171              :                      forces_tmp = forces_tmp &
    3172      2931696 :                        & + 2 * dble(conjg(cprj_deriv_(icprj_deriv,iband_spinor))*cprj_(icprj,iband_spinor))
    3173              :                    end do
    3174              :                  end do
    3175       214368 :                  iforces  = idir + 3*(ia-1) + shift_itypat
    3176       214368 :                  my_iband = iband + xg_nonlop%me_band*ncols_cprj_nospin
    3177       285824 :                  forces_(iforces,my_iband) = forces_(iforces,my_iband) + forces_tmp
    3178              :                end do
    3179              :              end do
    3180              :            end do
    3181              :            !$omp end do
    3182        21157 :            shift_itypat       = shift_itypat       + 3*nattyp_i
    3183        21157 :            shift_itypat_nlmn  = shift_itypat_nlmn  + nattyp_i*nlmn
    3184        21157 :            shift_itypat_3nlmn = shift_itypat_3nlmn + nattyp_i*3*nlmn
    3185              :          end if
    3186              :        end do
    3187              :        !$omp end parallel
    3188              : 
    3189              :      case (SPACE_R)
    3190              : 
    3191         7697 :        call xgBlock_reverseMap(cprj,cprj_real)
    3192         7697 :        call xgBlock_reverseMap(cprj_deriv,cprj_deriv_real)
    3193              : 
    3194         7697 :        shift_itypat=0
    3195         7697 :        shift_itypat_nlmn=0
    3196         7697 :        shift_itypat_3nlmn=0
    3197              :        !$omp parallel default (none) &
    3198              :        !$omp& shared(xg_nonlop,forces_,cprj_deriv_real,cprj_real), &
    3199              :        !$omp& firstprivate(shift_itypat,shift_itypat_nlmn,shift_itypat_3nlmn,ncols_cprj_nospin,nspinor), &
    3200              :        !$omp& private(itypat,nattyp_i,nlmn,ia,ilmn,idir,iforces,my_iband), &
    3201              :        !$omp& private(iband_spinor,icprj,icprj_deriv,forces_tmp)
    3202        23074 :        do itypat = 1, xg_nonlop%ntypat
    3203        15377 :          nlmn = xg_nonlop%nlmn_ntypat(itypat)
    3204        15377 :          nattyp_i = xg_nonlop%nattyp(itypat)
    3205        23074 :          if (nattyp_i>0) then
    3206              :            !$omp do collapse(3)
    3207        50357 :            do iband=1,ncols_cprj_nospin
    3208        85373 :              do ia = 1, nattyp_i
    3209       175044 :                do idir=1,3
    3210              :                  forces_tmp = zero
    3211       210096 :                  do ispinor=1,nspinor
    3212      1648224 :                    do ilmn=1,nlmn
    3213      1438128 :                      iband_spinor = ispinor + nspinor*(iband-1)
    3214      1438128 :                      icprj       = ilmn + nlmn*(ia-1) + shift_itypat_nlmn
    3215      1438128 :                      icprj_deriv = ilmn + nlmn*(idir-1) + 3*nlmn*(ia-1) + shift_itypat_3nlmn
    3216              :                      forces_tmp = forces_tmp &
    3217      1543176 :                        & + 2 * cprj_deriv_real(icprj_deriv,iband_spinor)*cprj_real(icprj,iband_spinor)
    3218              :                    end do
    3219              :                  end do
    3220       105048 :                  iforces  = idir + 3*(ia-1) + shift_itypat
    3221       105048 :                  my_iband = iband + xg_nonlop%me_band*ncols_cprj_nospin
    3222       140064 :                  forces_(iforces,my_iband) = forces_(iforces,my_iband) + forces_tmp
    3223              :                end do
    3224              :              end do
    3225              :            end do
    3226              :            !$omp end do
    3227        15377 :            shift_itypat       = shift_itypat       + 3*nattyp_i
    3228        15377 :            shift_itypat_nlmn  = shift_itypat_nlmn  + nattyp_i*nlmn
    3229        15377 :            shift_itypat_3nlmn = shift_itypat_3nlmn + nattyp_i*3*nlmn
    3230              :          end if
    3231              :        end do
    3232              :        !$omp end parallel
    3233              : 
    3234              :      case default
    3235        18300 :        ABI_ERROR("Wrong space")
    3236              : 
    3237              :    end select
    3238              : 
    3239        18300 :    call xgBlock_mpi_sum(forces,comm=xg_nonlop%comm_band)
    3240              : 
    3241        18300 :  end subroutine xg_nonlop_mult_cprj_forces
    3242              : 
    3243              : !!****f* m_xg_nonlop/xg_nonlop_stress
    3244              : !! NAME
    3245              : !!
    3246              : !! FUNCTION
    3247              : !!
    3248              : !! INPUTS
    3249              : !!
    3250         1140 : subroutine xg_nonlop_mult_cprj_stress(xg_nonlop,cprj,cprj_deriv,stress)
    3251              : 
    3252              :    type(xg_nonlop_t), intent(in) :: xg_nonlop
    3253              :    type(xgBlock_t), intent(in) :: cprj
    3254              :    type(xgBlock_t), intent(in) :: cprj_deriv
    3255              :    type(xgBlock_t), intent(inout) :: stress
    3256              : 
    3257              :    !real(dp) :: tsec(2)
    3258              :    integer :: ia,idir,ilmn,iband,iband_spinor,my_iband,itypat,nlmn,nattyp_i
    3259              :    integer :: ispinor,icprj,icprj_deriv
    3260              :    integer :: ncols_cprj,ncols_cprj_nospin,nspinor
    3261              :    integer :: shift_itypat,shift_itypat_nlmn,shift_itypat_6nlmn
    3262              : 
    3263         1140 :    complex(dp), pointer :: cprj_(:,:),cprj_deriv_(:,:)
    3264         1140 :    real(dp), pointer :: cprj_real(:,:),cprj_deriv_real(:,:)
    3265         1140 :    real(dp), pointer :: stress_(:,:)
    3266              :    real(dp) :: stress_tmp
    3267              : 
    3268              : !   call timab(tim_getHmeSX,1,tsec)
    3269              : 
    3270         1140 :    nspinor = xg_nonlop%nspinor
    3271              : 
    3272         1140 :    ncols_cprj = cols(cprj)
    3273         1140 :    ncols_cprj_nospin = ncols_cprj/nspinor
    3274              : 
    3275         1140 :    call xgBlock_reverseMap(stress,stress_)
    3276              : 
    3277         1871 :    select case(xg_nonlop%space_cprj)
    3278              : 
    3279              :      case (SPACE_C)
    3280              : 
    3281          731 :        call xgBlock_reverseMap(cprj,cprj_)
    3282          731 :        call xgBlock_reverseMap(cprj_deriv,cprj_deriv_)
    3283              : 
    3284          731 :        shift_itypat=0
    3285          731 :        shift_itypat_nlmn=0
    3286          731 :        shift_itypat_6nlmn=0
    3287              :        !$omp parallel default (none) &
    3288              :        !$omp& shared(xg_nonlop,stress_,cprj_deriv_,cprj_), &
    3289              :        !$omp& firstprivate(shift_itypat,shift_itypat_nlmn,shift_itypat_6nlmn,ncols_cprj_nospin,nspinor), &
    3290              :        !$omp& private(itypat,nattyp_i,nlmn,ia,ilmn,idir,my_iband), &
    3291              :        !$omp& private(iband_spinor,icprj,icprj_deriv,stress_tmp)
    3292         2176 :        do itypat = 1, xg_nonlop%ntypat
    3293         1445 :          nlmn = xg_nonlop%nlmn_ntypat(itypat)
    3294         1445 :          nattyp_i = xg_nonlop%nattyp(itypat)
    3295         2176 :          if (nattyp_i>0) then
    3296              :            !$omp do collapse(2)
    3297         7309 :            do iband=1,ncols_cprj_nospin
    3298        42685 :              do idir=1,6
    3299              :                stress_tmp = zero
    3300        83472 :                do ispinor=1,nspinor
    3301       138288 :                  do ia = 1, nattyp_i
    3302       634560 :                    do ilmn=1,nlmn
    3303       531648 :                      iband_spinor = ispinor + nspinor*(iband-1)
    3304       531648 :                      icprj       = ilmn + nlmn*(ia-1) + shift_itypat_nlmn
    3305       531648 :                      icprj_deriv = ilmn + nlmn*(idir-1) + 6*nlmn*(ia-1) + shift_itypat_6nlmn
    3306              :                      stress_tmp = stress_tmp &
    3307       586464 :                        & + 2 * dble(conjg(cprj_deriv_(icprj_deriv,iband_spinor))*cprj_(icprj,iband_spinor))
    3308              :                    end do
    3309              :                  end do
    3310              :                end do
    3311        35376 :                my_iband = iband + xg_nonlop%me_band*ncols_cprj_nospin
    3312        41272 :                stress_(idir,my_iband) = stress_(idir,my_iband) + stress_tmp
    3313              :              end do
    3314              :            end do
    3315              :            !$omp end do
    3316         1413 :            shift_itypat       = shift_itypat       + 6*nattyp_i
    3317         1413 :            shift_itypat_nlmn  = shift_itypat_nlmn  + nattyp_i*nlmn
    3318         1413 :            shift_itypat_6nlmn = shift_itypat_6nlmn + nattyp_i*6*nlmn
    3319              :          end if
    3320              :        end do
    3321              :        !$omp end parallel
    3322              : 
    3323              :      case (SPACE_R)
    3324              : 
    3325          409 :        call xgBlock_reverseMap(cprj,cprj_real)
    3326          409 :        call xgBlock_reverseMap(cprj_deriv,cprj_deriv_real)
    3327              : 
    3328          409 :        shift_itypat=0
    3329          409 :        shift_itypat_nlmn=0
    3330          409 :        shift_itypat_6nlmn=0
    3331              :        !$omp parallel default (none) &
    3332              :        !$omp& shared(xg_nonlop,stress_,cprj_deriv_real,cprj_real), &
    3333              :        !$omp& firstprivate(shift_itypat,shift_itypat_nlmn,shift_itypat_6nlmn,ncols_cprj_nospin,nspinor), &
    3334              :        !$omp& private(itypat,nattyp_i,nlmn,ia,ilmn,idir,my_iband), &
    3335              :        !$omp& private(iband_spinor,icprj,icprj_deriv,stress_tmp)
    3336         1210 :        do itypat = 1, xg_nonlop%ntypat
    3337          801 :          nlmn = xg_nonlop%nlmn_ntypat(itypat)
    3338          801 :          nattyp_i = xg_nonlop%nattyp(itypat)
    3339         1210 :          if (nattyp_i>0) then
    3340              :            !$omp do collapse(2)
    3341         3653 :            do iband=1,ncols_cprj_nospin
    3342        20765 :              do idir=1,6
    3343              :                stress_tmp = zero
    3344        34224 :                do ispinor=1,nspinor
    3345        51552 :                  do ia = 1, nattyp_i
    3346       303720 :                    do ilmn=1,nlmn
    3347       269280 :                      iband_spinor = ispinor + nspinor*(iband-1)
    3348       269280 :                      icprj       = ilmn + nlmn*(ia-1) + shift_itypat_nlmn
    3349       269280 :                      icprj_deriv = ilmn + nlmn*(idir-1) + 6*nlmn*(ia-1) + shift_itypat_6nlmn
    3350              :                      stress_tmp = stress_tmp &
    3351       286608 :                        & + 2 * cprj_deriv_real(icprj_deriv,iband_spinor)*cprj_real(icprj,iband_spinor)
    3352              :                    end do
    3353              :                  end do
    3354              :                end do
    3355        17112 :                my_iband = iband + xg_nonlop%me_band*ncols_cprj_nospin
    3356        19964 :                stress_(idir,my_iband) = stress_(idir,my_iband) + stress_tmp
    3357              :              end do
    3358              :            end do
    3359              :            !$omp end do
    3360          801 :            shift_itypat       = shift_itypat       + 6*nattyp_i
    3361          801 :            shift_itypat_nlmn  = shift_itypat_nlmn  + nattyp_i*nlmn
    3362          801 :            shift_itypat_6nlmn = shift_itypat_6nlmn + nattyp_i*6*nlmn
    3363              :          end if
    3364              :        end do
    3365              :        !$omp end parallel
    3366              : 
    3367              :      case default
    3368         1140 :        ABI_ERROR("Wrong space")
    3369              : 
    3370              :    end select
    3371              : 
    3372         1140 :    call xgBlock_mpi_sum(stress,comm=xg_nonlop%comm_band)
    3373              : 
    3374              : 
    3375              : !   call timab(tim_getHmeSX,2,tsec)
    3376              : 
    3377         1140 :  end subroutine xg_nonlop_mult_cprj_stress
    3378              : !!***
    3379              : 
    3380            0 : end module m_xg_nonlop
    3381              : !!***
        

Generated by: LCOV version 2.3-1