LCOV - code coverage report
Current view: top level - src/79_seqpar_mpi - m_lobpcgwf_old.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 70.2 % 615 432
Test Date: 2026-09-21 19:39:32 Functions: 100.0 % 1 1

            Line data    Source code
       1              : !!****m* ABINIT/m_lobpcgwf_old
       2              : !! NAME
       3              : !!   m_lobpcgwf_old
       4              : !!
       5              : !! FUNCTION
       6              : !!
       7              : !!
       8              : !! COPYRIGHT
       9              : !!  Copyright (C) 2008-2026 ABINIT group ()
      10              : !!  This file is distributed under the terms of the
      11              : !!  GNU General Public License, see ~abinit/COPYING
      12              : !!  or http://www.gnu.org/copyleft/gpl.txt .
      13              : !!
      14              : !! SOURCE
      15              : 
      16              : #if defined HAVE_CONFIG_H
      17              : #include "config.h"
      18              : #endif
      19              : 
      20              : #include "abi_common.h"
      21              : 
      22              : module m_lobpcgwf_old
      23              : 
      24              :  implicit none
      25              : 
      26              :  private
      27              : !!***
      28              : 
      29              :  public :: lobpcgwf
      30              : !!***
      31              : 
      32              : contains
      33              : !!***
      34              : 
      35              : !!****f* ABINIT/lobpcgwf
      36              : !! NAME
      37              : !! lobpcgwf
      38              : !!
      39              : !! FUNCTION
      40              : !! this routine updates the whole wave functions at a given k-point,
      41              : !! using the lobpcg method
      42              : !! for a given spin-polarization, from a fixed hamiltonian
      43              : !! but might also simply compute eigenvectors and eigenvalues at this k point.
      44              : !! it will also update the matrix elements of the hamiltonian.
      45              : !!
      46              : !! COPYRIGHT
      47              : !! Copyright (C) 1998-2026 ABINIT group (FBottin,GZ,AR,MT,FDahm)
      48              : !! this file is distributed under the terms of the
      49              : !! gnu general public license, see ~abinit/COPYING
      50              : !! or http://www.gnu.org/copyleft/gpl.txt .
      51              : !! for the initials of contributors, see ~abinit/doc/developers/contributors.txt .
      52              : !!
      53              : !! INPUTS
      54              : !!  dtset <type(dataset_type)>=all input variales for this dataset
      55              : !!  gs_hamk <type(gs_hamiltonian_type)>=all data for the hamiltonian at k
      56              : !!  icg=shift to be applied on the location of data in the array cg
      57              : !!  igsc=shift to be applied on the location of data in the array gsc
      58              : !!  kinpw(npw)=(modified) kinetic energy for each plane wave (hartree)
      59              : !!  mcg=second dimension of the cg array
      60              : !!  mgsc=second dimension of the gsc array
      61              : !!  mpi_enreg=information about MPI parallelization
      62              : !!  nband_k=number of bands at this k point for that spin polarization
      63              : !!  nbdblock : number of blocks
      64              : !!  npw_k=number of plane waves at this k point
      65              : !!  prtvol=control print volume and debugging output
      66              : !!  use_totvnlx=1 if one has to compute totvnlx
      67              : !!
      68              : !! OUTPUT
      69              : !!  resid_k(nband_k)=residuals for each states
      70              : !!  subham(nband_k*(nband_k+1))=the matrix elements of h
      71              : !!  If gs_hamk%usepaw==0:
      72              : !!    gsc(2,mgsc)=<g|s|c> matrix elements (s=overlap)
      73              : !!    totvnlx(nband_k*use_totvnlx,nband_k*use_totvnlx)=the matrix elements of vnl+vfockACE
      74              : !!
      75              : !! SIDE EFFECTS
      76              : !!  cg(2,mcg)=updated wavefunctions
      77              : !!
      78              : !! SOURCE
      79              : 
      80         4500 : subroutine lobpcgwf(cg,dtset,gs_hamk,gsc,icg,igsc,kinpw,mcg,mgsc,mpi_enreg,&
      81         2250 : &                   nband_k,nbdblock,npw_k,prtvol,resid_k,subham,totvnlx,use_totvnlx)
      82              : 
      83              : 
      84              :  use, intrinsic :: iso_c_binding
      85              :  use defs_basis
      86              :  use m_abicore
      87              :  use m_lobpcg
      88              :  use m_gputk
      89              :  use m_abi_linalg
      90              :  use m_wfutils
      91              :  use m_xmpi
      92              :  use m_errors
      93              :  use m_dtset
      94              : 
      95              :  use defs_abitypes, only : mpi_type
      96              :  use m_time,        only : timab
      97              :  use m_hamiltonian, only : gs_hamiltonian_type
      98              :  use m_pawcprj,     only : pawcprj_type
      99              :  use m_getghc,      only : getghc
     100              :  use m_prep_kgb,    only : prep_getghc
     101              : #ifdef HAVE_GPU
     102              :  use m_gputk
     103              : #endif
     104              : 
     105              : !Arguments ------------------------------------
     106              :  integer,intent(in) :: icg,igsc,mcg,mgsc,nband_k,nbdblock,npw_k,prtvol,use_totvnlx
     107              :  type(gs_hamiltonian_type),intent(inout) :: gs_hamk
     108              :  type(dataset_type),intent(in) :: dtset
     109              :  type(mpi_type),intent(in) :: mpi_enreg
     110              :  real(dp),intent(inout) :: cg(2,mcg),gsc(2,mgsc)
     111              :  real(dp),intent(in) :: kinpw(npw_k)
     112              :  real(dp),intent(out) :: resid_k(nband_k)
     113              :  real(dp),intent(inout) :: subham(nband_k*(nband_k+1))
     114              :  real(dp),intent(inout) :: totvnlx((3-gs_hamk%istwf_k)*nband_k*use_totvnlx,nband_k*use_totvnlx)
     115              : 
     116              : !Local variables-------------------------------
     117              :  integer, parameter :: tim_getghc=5
     118              :  integer :: activepsize,activersize,bblocksize,bigorder,blocksize,cpopt
     119              :  integer :: cond_try
     120              :  integer :: iblocksize,iblock,ierr,ii,info,istwf_k,isubh
     121              :  integer :: iterationnumber
     122              :  integer :: iwavef,i1,i2,i3,i4,maxiterations,my_nspinor
     123              :  integer :: nrestart,optekin,optpcon,restart
     124              :  integer :: sij_opt,timopt,tim_wfcopy,tim_xeigen
     125              :  integer :: tim_xortho,tim_xprecon,use_lapack_gpu,use_linalg_gpu,vectsize
     126              :  logical :: gen_eigenpb
     127              :  integer :: cplx
     128              :  real(dp) :: condestgramb,deltae,deold,dum
     129              :  complex(dp) :: cminusone
     130              :  real(dp) :: zvar(2)
     131              :  logical :: havetoprecon
     132              :  real(dp) :: tsec(2)
     133         2250 :  real(dp), allocatable :: gwavef(:,:),cwavef(:,:),gvnlxc(:,:)
     134         2250 :  real(dp), allocatable :: swavef(:,:)
     135         2250 :  real(dp), allocatable :: residualnorms(:),eigen(:)
     136         2250 :  real(dp), allocatable :: tmpeigen(:)
     137         2250 :  real(dp), allocatable :: pcon(:,:)
     138         2250 :  real(dp), allocatable, target :: blockvectorx(:,:),blockvectorvx(:,:),blockvectorax(:,:),blockvectorbx(:,:)
     139         2250 :  real(dp), allocatable, target :: blockvectorr(:,:),blockvectorvr(:,:),blockvectorar(:,:),blockvectorbr(:,:)
     140         2250 :  real(dp), allocatable, target :: blockvectorp(:,:),blockvectorvp(:,:),blockvectorap(:,:),blockvectorbp(:,:),blockvectordumm(:,:)
     141         2250 :  real(dp), allocatable, target :: blockvectory(:,:),blockvectorby(:,:),blockvectorz(:,:)
     142         2250 :  real(dp), allocatable, target :: gramxax(:,:),gramxar(:,:),gramxap(:,:),gramrar(:,:),gramrap(:,:),grampap(:,:)
     143         2250 :  real(dp), allocatable, target :: gramxbx(:,:),gramxbr(:,:),gramxbp(:,:),gramrbr(:,:),gramrbp(:,:),grampbp(:,:)
     144         2250 :  real(dp), allocatable, target :: coordx1(:,:),coordx2(:,:),coordx3(:,:),lambda(:,:),grama(:,:),gramb(:,:),gramyx(:,:)
     145         2250 :  real(dp), allocatable :: tmpgramb(:,:),transf3(:,:,:),transf5(:,:,:)
     146         2250 :  real(dp), allocatable :: tsubham(:,:)
     147         2250 :  type(pawcprj_type), allocatable :: cprj_dum(:,:)
     148              :  character(len=500) :: message
     149              :  character, dimension(2) :: cparam
     150              :  type(c_ptr) :: A_gpu,C_gpu,coordx2_gpu,coordx3_gpu,bblockvector_gpu,gram_gpu
     151              :  type(c_ptr) :: blockvectorr_gpu,blockvectorar_gpu,blockvectorbr_gpu
     152              : 
     153              : !Index of a given band
     154              : !gramindex(iblocksize)=(iblocksize-1)*cplx+1
     155              : 
     156              : ! *********************************************************************
     157              : 
     158              :  DBG_ENTER("COLL")
     159              : 
     160         2250 :  call timab(530,1,tsec)
     161         2250 :  if(abs(dtset%timopt)==4) then
     162            0 :    call timab(520,1,tsec)
     163              :  end if
     164              : 
     165              : !###########################################################################
     166              : !################ INITIALISATION  ##########################################
     167              : !###########################################################################
     168              : 
     169              : !For timing
     170         2250 :  timopt=dtset%timopt
     171         2250 :  tim_wfcopy=584
     172              :  !tim_xcopy=584
     173         2250 :  tim_xeigen=587
     174              :  !tim_xgemm=532
     175         2250 :  tim_xortho=535
     176         2250 :  tim_xprecon=536
     177              :  !tim_xtrsm=535
     178              : 
     179              : !Variables
     180         2250 :  maxiterations=dtset%nline
     181         2250 :  gen_eigenpb=(gs_hamk%usepaw==1)
     182         2250 :  my_nspinor=max(1,dtset%nspinor/mpi_enreg%nproc_spinor)
     183         2250 :  cminusone=-cone
     184         2250 :  istwf_k=gs_hamk%istwf_k
     185         2250 :  info = 0
     186         2250 :  cparam(1)='t'
     187         2250 :  cparam(2)='c'
     188              : 
     189              : !Depends on istwfk
     190         2250 :  if ( istwf_k == 2 ) then
     191          182 :    cplx=1
     192          182 :    if (mpi_enreg%me_g0 == 1) then
     193           83 :      vectsize=2*npw_k*my_nspinor-1
     194              :    else
     195           99 :      vectsize=2*npw_k*my_nspinor
     196              :    end if
     197              :  else
     198         2068 :    cplx=2
     199         2068 :    vectsize=npw_k*my_nspinor
     200              :  end if
     201              : 
     202              : !For preconditionning
     203         2250 :  optekin=0;if (dtset%wfoptalg>10) optekin=0
     204         2250 :  optpcon=1;if (dtset%wfoptalg>10) optpcon=0
     205              : 
     206              : !For communication
     207              :  !blocksize=mpi_enreg%nproc_fft
     208              :  !if(mpi_enreg%paral_kgb==1) blocksize=mpi_enreg%nproc_band*mpi_enreg%bandpp
     209         2250 :  blocksize=nband_k/dtset%nblock_lobpcg
     210              :  !IF you want to compare with new lobpcg in sequential uncomment the following
     211              :  !line
     212              :  !blocksize=mpi_enreg%nproc_band*mpi_enreg%bandpp
     213              : 
     214              : !Iniitializations/allocations of GPU parallelism
     215         2250 :  use_linalg_gpu=0;use_lapack_gpu=0
     216         2250 :  if ((dtset%gpu_option==ABI_GPU_LEGACY).and. &
     217         2250 : & (vectsize*blocksize*blocksize>dtset%gpu_linalg_limit)) use_linalg_gpu=1
     218         2250 :  if (dtset%gpu_option==ABI_GPU_OPENMP) use_linalg_gpu=1
     219              : #ifdef HAVE_GPU_HIP
     220              :  use_linalg_gpu=0
     221              : #endif
     222              : #if defined HAVE_LINALG_MAGMA
     223              :  use_lapack_gpu=use_linalg_gpu
     224              : #endif
     225         2250 :  if(use_linalg_gpu==1) then
     226            0 :    call alloc_on_gpu(A_gpu,             INT(cplx, c_size_t)*dp*vectsize*blocksize)
     227            0 :    call alloc_on_gpu(C_gpu,             INT(cplx, c_size_t)*dp*vectsize*blocksize)
     228            0 :    call alloc_on_gpu(blockvectorr_gpu,  INT(cplx, c_size_t)*dp*vectsize*blocksize)
     229            0 :    call alloc_on_gpu(blockvectorar_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
     230            0 :    call alloc_on_gpu(blockvectorbr_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
     231            0 :    call alloc_on_gpu(coordx2_gpu,       INT(cplx, c_size_t)*dp*blocksize*blocksize)
     232            0 :    call alloc_on_gpu(coordx3_gpu,       INT(cplx, c_size_t)*dp*blocksize*blocksize)
     233              :  end if
     234              : 
     235        13658 :  ABI_MALLOC(cprj_dum, (gs_hamk%natom, 1))
     236              : 
     237              :  ! Work arrays eventually mapped on GPU via OpenMP
     238         6750 :  ABI_MALLOC(cwavef,(2,npw_k*my_nspinor*blocksize))
     239         4500 :  ABI_MALLOC(gwavef,(2,npw_k*my_nspinor*blocksize))
     240         4500 :  ABI_MALLOC(gvnlxc,(2,npw_k*my_nspinor*blocksize))
     241         4500 :  ABI_MALLOC(swavef,(2,npw_k*my_nspinor*blocksize))
     242              : #ifdef HAVE_OPENMP_OFFLOAD
     243              :  !$OMP TARGET ENTER DATA MAP(alloc:cwavef,gwavef,gvnlxc,swavef) IF(dtset%gpu_option==ABI_GPU_OPENMP)
     244              : #endif
     245              : 
     246         2250 :  if(abs(dtset%timopt)==4) then
     247            0 :    call timab(520,2,tsec)
     248              :  end if
     249              : 
     250              : !###########################################################################
     251              : !################ BIG LOOP OVER BLOCKS  ####################################
     252              : !###########################################################################
     253              : 
     254         7886 :  do iblock=1,nbdblock
     255              : 
     256         5636 :    if(abs(dtset%timopt)==4) then
     257            0 :      call timab(521,1,tsec)
     258              :    end if
     259              : 
     260         5636 :    havetoprecon=.true.
     261         5636 :    nrestart=0
     262         5636 :    bblocksize=(iblock-1)*blocksize
     263              : 
     264              : !  allocations
     265        22544 :    ABI_MALLOC(pcon,(npw_k,blocksize))
     266        22544 :    ABI_MALLOC(blockvectorx,(cplx*vectsize,blocksize))
     267        16908 :    ABI_MALLOC(blockvectorax,(cplx*vectsize,blocksize))
     268        16908 :    ABI_MALLOC(blockvectorbx,(cplx*vectsize,blocksize))
     269        16908 :    ABI_MALLOC(blockvectorr,(cplx*vectsize,blocksize))
     270        16908 :    ABI_MALLOC(blockvectorar,(cplx*vectsize,blocksize))
     271        16908 :    ABI_MALLOC(blockvectorbr,(cplx*vectsize,blocksize))
     272        16908 :    ABI_MALLOC(blockvectorp,(cplx*vectsize,blocksize))
     273        16908 :    ABI_MALLOC(blockvectorap,(cplx*vectsize,blocksize))
     274        16908 :    ABI_MALLOC(blockvectorbp,(cplx*vectsize,blocksize))
     275        16908 :    ABI_MALLOC(blockvectordumm,(cplx*vectsize,blocksize))
     276        22544 :    ABI_MALLOC(gramxax,(cplx*blocksize,blocksize))
     277        16908 :    ABI_MALLOC(gramxar,(cplx*blocksize,blocksize))
     278        16908 :    ABI_MALLOC(gramxap,(cplx*blocksize,blocksize))
     279        16908 :    ABI_MALLOC(gramrar,(cplx*blocksize,blocksize))
     280        16908 :    ABI_MALLOC(gramrap,(cplx*blocksize,blocksize))
     281        16908 :    ABI_MALLOC(grampap,(cplx*blocksize,blocksize))
     282        16908 :    ABI_MALLOC(gramxbx,(cplx*blocksize,blocksize))
     283        16908 :    ABI_MALLOC(gramxbr,(cplx*blocksize,blocksize))
     284        16908 :    ABI_MALLOC(gramxbp,(cplx*blocksize,blocksize))
     285        16908 :    ABI_MALLOC(gramrbr,(cplx*blocksize,blocksize))
     286        16908 :    ABI_MALLOC(gramrbp,(cplx*blocksize,blocksize))
     287        16908 :    ABI_MALLOC(grampbp,(cplx*blocksize,blocksize))
     288        28180 :    ABI_MALLOC(transf3,(cplx*blocksize,blocksize,3))
     289        28180 :    ABI_MALLOC(transf5,(cplx*blocksize,blocksize,5))
     290        16908 :    ABI_MALLOC(lambda,(cplx*blocksize,blocksize))
     291        16908 :    ABI_MALLOC(residualnorms,(blocksize))
     292              : 
     293        22544 :    ABI_MALLOC(blockvectory,(cplx*vectsize,bblocksize))
     294        16908 :    ABI_MALLOC(blockvectorby,(cplx*vectsize,bblocksize))
     295        22544 :    ABI_MALLOC(gramyx,(cplx*bblocksize,blocksize))
     296         5636 :    if (gs_hamk%usepaw==0) then
     297         2496 :      ABI_MALLOC(blockvectorvx,(cplx*vectsize,blocksize))
     298         2496 :      ABI_MALLOC(blockvectorvr,(cplx*vectsize,blocksize))
     299         2496 :      ABI_MALLOC(blockvectorvp,(cplx*vectsize,blocksize))
     300              :    end if
     301              : 
     302         5636 :    if(use_linalg_gpu==1) then
     303            0 :      if(iblock/=1) then
     304            0 :        call alloc_on_gpu(bblockvector_gpu, INT(cplx, c_size_t)*dp*vectsize*bblocksize)
     305            0 :        call alloc_on_gpu(gram_gpu,         INT(cplx, c_size_t)*dp*bblocksize*blocksize)
     306              :      else
     307            0 :        call alloc_on_gpu(bblockvector_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
     308            0 :        call alloc_on_gpu(gram_gpu,         INT(cplx, c_size_t)*dp*blocksize*blocksize)
     309              :      end if
     310              :    end if
     311              : 
     312              : ! Initialize global variables in m_wfutils.
     313         5636 :    call setWFParameter(cplx,mpi_enreg%me_g0,npw_k,my_nspinor,icg,igsc,blocksize)
     314              : 
     315              : !  transfer array of wf coeff in iblock to blockvectorx
     316              :    call wfcopy('D',blocksize*vectsize,cg,1,blockvectorx,1,blocksize,iblock,'C',withbbloc=.true.,&
     317         5636 : &   timopt=timopt,tim_wfcopy=tim_wfcopy)
     318              : 
     319              : !  !!!!!!!!!!!!!!!!!!!!!!!! Begin if iblock /=1 !!!!!!!!!!!!!!!!!!!!!!!!!!
     320              : !  transfer array of wf coeff less than iblock to blockvectory
     321         5636 :    if(iblock /=1) then
     322              :      call wfcopy('D',bblocksize*vectsize,cg,1,blockvectory,1,bblocksize,iblock,'C',withbbloc=.false.,&
     323         3386 : &     timopt=timopt,tim_wfcopy=tim_wfcopy)
     324              : 
     325         3386 :      if(gen_eigenpb) then
     326              :        call wfcopy('D',bblocksize*vectsize,gsc,1,blockvectorby,1,bblocksize,iblock,'S',withbbloc=.false.,&
     327         3258 : &       timopt=timopt,tim_wfcopy=tim_wfcopy)
     328              :      else
     329        62824 :        blockvectorby = blockvectory
     330              :      end if
     331              : 
     332              : !    b-orthogonalize x to the constraint y (supposed b-orthonormal)
     333              : !    blockvectorx=blockvectorx-matmul(blockvectory,matmul((blockvectorby)^T,blockvectorx))
     334              : 
     335              :      call abi_xgemm(cparam(cplx),'n',bblocksize,blocksize,vectsize,cone,blockvectorby,&
     336         3386 : &     vectsize,blockvectorx,vectsize,czero,gramyx,bblocksize,x_cplx=x_cplx)
     337              : 
     338         3386 :      if(abs(dtset%timopt)==3) then
     339            0 :        call timab(533,1,tsec)
     340              :      end if
     341         3386 :      call xmpi_sum(gramyx,mpi_enreg%comm_bandspinorfft,ierr)
     342         3386 :      if(abs(dtset%timopt)==3) then
     343            0 :        call timab(533,2,tsec)
     344              :      end if
     345              : 
     346              :      call abi_xgemm('n','n',vectsize,blocksize,bblocksize,cminusone,blockvectory,&
     347         3386 : &     vectsize,gramyx,bblocksize,cone,blockvectorx,vectsize,x_cplx=x_cplx)
     348              : 
     349              :    end if
     350              : !  !!!!!!!!!!!!!!!!!!!!!!!! End if iblock /=1 !!!!!!!!!!!!!!!!!!!!!!!!!!!
     351              : 
     352              :    call wfcopy('I',vectsize*blocksize,blockvectorx,1,cwavef,1,blocksize,iblock,'W',withbbloc=.false.,&
     353         5636 : &   timopt=timopt,tim_wfcopy=tim_wfcopy)
     354              : 
     355         5636 :    if(abs(dtset%timopt)==4) then
     356            0 :      call timab(521,2,tsec)
     357              :    end if
     358         5636 :    if(abs(dtset%timopt)==4) then
     359            0 :      call timab(526,1,tsec)
     360              :    end if
     361              : 
     362         5636 :    cpopt=-1;sij_opt=0;if (gen_eigenpb) sij_opt=1
     363              : 
     364              : #ifdef HAVE_OPENMP_OFFLOAD
     365              :    !$OMP TARGET UPDATE TO(cwavef) IF(dtset%gpu_option==ABI_GPU_OPENMP)
     366              : #endif
     367         5636 :    if (mpi_enreg%paral_kgb==0) then
     368              :      call getghc(cpopt,cwavef,cprj_dum,gwavef,swavef,gs_hamk,gvnlxc,dum,&
     369          836 : &     mpi_enreg,blocksize,prtvol,sij_opt,tim_getghc,0)
     370              :    else
     371              :      call prep_getghc(cwavef,gs_hamk,gvnlxc,gwavef,swavef,dum,blocksize,mpi_enreg,&
     372         4800 : &     prtvol,sij_opt,cpopt,cprj_dum,already_transposed=.false.)
     373              :    end if
     374              : #ifdef HAVE_OPENMP_OFFLOAD
     375              :    !$OMP TARGET UPDATE FROM(gwavef,gvnlxc,swavef) IF(dtset%gpu_option==ABI_GPU_OPENMP)
     376              : #endif
     377         5636 :    if(abs(dtset%timopt)==4) then
     378            0 :      call timab(526,2,tsec)
     379              :    end if
     380         5636 :    if(abs(dtset%timopt)==4) then
     381            0 :      call timab(522,1,tsec)
     382              :    end if
     383              : 
     384         5636 :    if ( gen_eigenpb ) then
     385              :      call wfcopy('D',vectsize*blocksize,swavef,1,blockvectorbx,1,blocksize,iblock,'W',withbbloc=.false.,&
     386         4804 : &     timopt=timopt,tim_wfcopy=tim_wfcopy)
     387              :    else
     388              :      call wfcopy('D',vectsize*blocksize,gvnlxc,1,blockvectorvx,1,blocksize,iblock,'W',withbbloc=.false.,&
     389          832 : &     timopt=timopt,tim_wfcopy=tim_wfcopy)
     390       626448 :      blockvectorbx = blockvectorx
     391              :    end if
     392              : 
     393              :    call wfcopy('D',vectsize*blocksize,gwavef,1,blockvectorax,1,blocksize,iblock,'W',withbbloc=.false.,&
     394         5636 : &   timopt=timopt,tim_wfcopy=tim_wfcopy)
     395              : 
     396              :    call abi_xorthonormalize(blockvectorx,blockvectorbx,blocksize,mpi_enreg%comm_bandspinorfft,gramxbx,vectsize,&
     397         5636 : &   x_cplx,timopt=timopt,tim_xortho=tim_xortho)
     398              : 
     399         5636 :    call abi_xtrsm('r','u','n','n',vectsize,blocksize,cone,gramxbx,blocksize,blockvectorbx,vectsize,x_cplx=x_cplx)
     400         5636 :    call abi_xtrsm('r','u','n','n',vectsize,blocksize,cone,gramxbx,blocksize,blockvectorax,vectsize,x_cplx=x_cplx)
     401              : 
     402         5636 :    if (gs_hamk%usepaw==0) then
     403          832 :      call abi_xtrsm('r','u','n','n',vectsize,blocksize,cone,gramxbx,blocksize,blockvectorvx,vectsize,x_cplx=x_cplx)
     404              :    end if
     405              : 
     406              : !  Do rayleigh ritz on a in space x
     407              : !  gramxax=matmul(transpose(blockvectorx),blockvectorax)
     408              :    call abi_xgemm(cparam(cplx),'n',blocksize,blocksize,vectsize,cone,blockvectorx,&
     409         5636 : &   vectsize,blockvectorax,vectsize,czero,gramxax,blocksize,x_cplx=x_cplx)
     410              : 
     411         5636 :    if(abs(dtset%timopt)==3) then
     412            0 :      call timab(533,1,tsec)
     413              :    end if
     414         5636 :    call xmpi_sum(gramxax,mpi_enreg%comm_bandspinorfft,ierr)
     415         5636 :    if(abs(dtset%timopt)==3) then
     416            0 :      call timab(533,2,tsec)
     417              :    end if
     418        11272 :    ABI_MALLOC(eigen,(blocksize))
     419              : 
     420              :    call abi_xheev('v','u',blocksize,gramxax,blocksize,eigen,x_cplx=cplx,istwf_k=istwf_k, &
     421         5636 :    timopt=timopt,tim_xeigen=tim_xeigen,use_slk=dtset%use_slk,use_gpu_magma=use_lapack_gpu)
     422              : 
     423              : !  blockvectorx=matmul(blockvectorx,gramxax)
     424              :    call abi_xgemm('n','n',vectsize,blocksize,blocksize,cone,blockvectorx,&
     425         5636 : &   vectsize,gramxax,blocksize,czero,blockvectordumm,vectsize,x_cplx=x_cplx)
     426      6334194 :    blockvectorx = blockvectordumm
     427              : 
     428              : !  blockvectorax=matmul(blockvectorax,gramxax)
     429              :    call abi_xgemm('n','n',vectsize,blocksize,blocksize,cone,blockvectorax,&
     430         5636 : &   vectsize,gramxax,blocksize,czero,blockvectordumm,vectsize,x_cplx=x_cplx)
     431      6334194 :    blockvectorax = blockvectordumm
     432              : 
     433              : !  blockvectorvx=matmul(blockvectorvx,gramxax)
     434         5636 :    if (gs_hamk%usepaw==0) then
     435              :      call abi_xgemm('n','n',vectsize,blocksize,blocksize,cone,blockvectorvx,&
     436          832 : &     vectsize,gramxax,blocksize,czero,blockvectordumm,vectsize,x_cplx=x_cplx)
     437       626448 :      blockvectorvx = blockvectordumm
     438              :    end if
     439              : 
     440              : !  blockvectorbx=matmul(blockvectorbx,gramxax)
     441              :    call abi_xgemm('n','n',vectsize,blocksize,blocksize,cone,blockvectorbx,&
     442         5636 : &   vectsize,gramxax,blocksize,czero,blockvectordumm,vectsize,x_cplx=x_cplx)
     443      6334194 :    blockvectorbx = blockvectordumm
     444              : 
     445              : #if FC_CRAY
     446              :    lambda(:,:) = zero
     447              :    do iblocksize=1,blocksize
     448              :      lambda(cplx*(iblocksize-1)+1,iblocksize) = eigen(iblocksize)
     449              :    end do
     450              : #else
     451        32336 :    do iblocksize=1,blocksize
     452        80100 :      zvar=(/eigen(iblocksize),zero/)
     453        32336 :      call abi_xcopy(1,zvar,1,lambda(cplx*(iblocksize-1)+1:cplx*iblocksize,iblocksize),1,x_cplx=x_cplx)
     454              :    end do
     455              : #endif
     456              : 
     457         5636 :    ABI_FREE(eigen)
     458              : 
     459         5636 :    if(abs(dtset%timopt)==4) then
     460            0 :      call timab(522,2,tsec)
     461              :    end if
     462              : 
     463              : !  ###########################################################################
     464              : !  ################ PERFORM LOOP ON NLINE ####################################
     465              : !  ###########################################################################
     466              : !  now the main alogrithm
     467        33474 :    iter: do iterationnumber=1,maxiterations
     468              : 
     469        28923 :      if(abs(dtset%timopt)==4) then
     470            0 :        call timab(523,1,tsec)
     471              :      end if
     472              : 
     473              : !    Build residual
     474              : !    blockvectorr=blockvectorax-matmul(blockvectorx,lambda)
     475              :      call xprecon(blockvectorbx,lambda,blocksize,&
     476              : &     iterationnumber,kinpw,mpi_enreg,npw_k,my_nspinor,&
     477        28923 : &     optekin,optpcon,pcon,blockvectorax,blockvectorr,vectsize,timopt=timopt,tim_xprecon=tim_xprecon)
     478              : 
     479     33624786 :      residualnorms=sum(blockvectorr**2,dim=1)
     480              : 
     481        28923 :      if(abs(dtset%timopt)==3) then
     482            0 :        call timab(533,1,tsec)
     483              :      end if
     484        28923 :      call xmpi_sum(residualnorms,mpi_enreg%comm_bandspinorfft,ierr)
     485        28923 :      if(abs(dtset%timopt)==3) then
     486            0 :        call timab(533,2,tsec)
     487              :      end if
     488              : 
     489       192104 :      resid_k(bblocksize+1:bblocksize+blocksize)=residualnorms(1:blocksize)
     490              : 
     491              : !    If residual sufficiently small stop line minimizations
     492       221027 :      if (abs(maxval(residualnorms(1:blocksize)))<dtset%tolwfr_diago) then
     493            8 :        if (prtvol > 0) then
     494              :          write(message, '(a,i0,a,i0,a,es12.4)' ) &
     495            0 : &         ' lobpcgwf: block ',iblock,' converged after ',iterationnumber,&
     496            0 : &         ' line minimizations: maxval(resid(1:blocksize)) =',maxval(residualnorms(1:blocksize))
     497            0 :          call wrtout(std_out,message,'PERS')
     498              :        end if
     499              :        havetoprecon=.false.
     500              :        exit
     501              :      end if
     502              : 
     503        28915 :      if(use_linalg_gpu==1) then
     504            0 :        call copy_on_gpu(blockvectorr, blockvectorr_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
     505              :      end if
     506              : 
     507        28915 :      if(iblock /=1) then
     508              : !      Residuals orthogonal to blockvectorby
     509              : !      blockvectorr=blockvectorr-matmul(blockvectory,matmul((blockvectorby)^T,blockvectorr))
     510              : 
     511        13700 :        if(use_linalg_gpu==1) then
     512            0 :          call copy_on_gpu(blockvectorby, bblockvector_gpu, INT(cplx, c_size_t)*dp*vectsize*bblocksize)
     513              :          call gpu_xgemm(cplx,cparam(cplx),'n',bblocksize,blocksize,vectsize,cone,bblockvector_gpu,&
     514            0 : &         vectsize,blockvectorr_gpu,vectsize,czero,gram_gpu,bblocksize)
     515            0 :          call copy_from_gpu(gramyx, gram_gpu, INT(cplx, c_size_t)*dp*bblocksize*blocksize)
     516              :        else
     517              :          call abi_xgemm(cparam(cplx),'n',bblocksize,blocksize,vectsize,cone,blockvectorby,&
     518        13700 : &         vectsize,blockvectorr,vectsize,czero,gramyx,bblocksize,x_cplx=x_cplx)
     519              :        end if
     520              : 
     521        13700 :        if(abs(dtset%timopt)==3) then
     522            0 :          call timab(533,1,tsec)
     523              :        end if
     524        13700 :        call xmpi_sum(gramyx,mpi_enreg%comm_bandspinorfft,ierr)
     525        13700 :        if(abs(dtset%timopt)==3) then
     526            0 :          call timab(533,2,tsec)
     527              :        end if
     528              : 
     529        13700 :        if(use_linalg_gpu==1) then
     530            0 :          call copy_on_gpu(gramyx,       gram_gpu,         INT(cplx, c_size_t)*dp*bblocksize*blocksize)
     531            0 :          call copy_on_gpu(blockvectory, bblockvector_gpu, INT(cplx, c_size_t)*dp*vectsize*bblocksize)
     532              :          call gpu_xgemm(cplx,'n','n',vectsize,blocksize,bblocksize,cminusone,bblockvector_gpu,&
     533            0 : &         vectsize,gram_gpu,bblocksize,cone,blockvectorr_gpu,vectsize)
     534              :        else
     535              :          call abi_xgemm('n','n',vectsize,blocksize,bblocksize,cminusone,blockvectory,&
     536        13700 : &         vectsize,gramyx,bblocksize,cone,blockvectorr,vectsize,x_cplx=x_cplx)
     537              :        end if
     538              : 
     539              :      end if
     540              : 
     541              : !    Residuals orthogonal to blockvectorx
     542              : !    blockvectorr=blockvectorr-matmul(blockvectorx,matmul((blockvectorbx)^T,blockvectorr))
     543        28915 :      if(use_linalg_gpu==1) then
     544            0 :        call copy_on_gpu(blockvectorbx, C_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
     545              :        call gpu_xgemm(cplx,cparam(cplx),'n',blocksize,blocksize,vectsize,cone,C_gpu,&
     546            0 : &       vectsize,blockvectorr_gpu,vectsize,czero,gram_gpu,blocksize)
     547            0 :        call copy_from_gpu(gramxax, gram_gpu, INT(cplx, c_size_t)*dp*blocksize*blocksize)
     548              :      else
     549              :        call abi_xgemm(cparam(cplx),'n',blocksize,blocksize,vectsize,cone,blockvectorbx,&
     550        28915 : &       vectsize,blockvectorr,vectsize,czero,gramxax,blocksize,x_cplx=x_cplx)
     551              :      end if
     552              : 
     553        28915 :      if(abs(dtset%timopt)==3) then
     554            0 :        call timab(533,1,tsec)
     555              :      end if
     556        28915 :      call xmpi_sum(gramxax,mpi_enreg%comm_bandspinorfft,ierr)
     557        28915 :      if(abs(dtset%timopt)==3) then
     558            0 :        call timab(533,2,tsec)
     559              :      end if
     560              : 
     561        28915 :      if(use_linalg_gpu==1) then
     562            0 :        call copy_on_gpu(gramxax,      gram_gpu, INT(cplx, c_size_t)*dp*blocksize*blocksize)
     563            0 :        call copy_on_gpu(blockvectorx, C_gpu,    INT(cplx, c_size_t)*dp*vectsize*blocksize)
     564              :        call gpu_xgemm(cplx,'n','n',vectsize,blocksize,blocksize,cminusone,C_gpu,&
     565            0 : &       vectsize,gram_gpu,blocksize,cone,blockvectorr_gpu,vectsize)
     566            0 :        call copy_from_gpu(blockvectorr, blockvectorr_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
     567              :      else
     568              :        call abi_xgemm('n','n',vectsize,blocksize,blocksize,cminusone,blockvectorx,&
     569        28915 : &       vectsize,gramxax,blocksize,cone,blockvectorr,vectsize,x_cplx=x_cplx)
     570              :      end if
     571              : 
     572              :      call wfcopy('I',vectsize*blocksize,blockvectorr,1,cwavef,1,blocksize,iblock,'W',withbbloc=.false.,&
     573        28915 : &     timopt=timopt,tim_wfcopy=tim_wfcopy)
     574              : 
     575        28915 :      cpopt=-1;sij_opt=0;if (gen_eigenpb) sij_opt=1
     576              : 
     577        28915 :      if(abs(dtset%timopt)==4) then
     578            0 :        call timab(523,2,tsec)
     579              :      end if
     580        28915 :      if(abs(dtset%timopt)==4) then
     581            0 :        call timab(526,1,tsec)
     582              :      end if
     583              : 
     584              : #ifdef HAVE_OPENMP_OFFLOAD
     585              :      !$OMP TARGET UPDATE TO(cwavef) IF(dtset%gpu_option==ABI_GPU_OPENMP)
     586              : #endif
     587        28915 :      if (mpi_enreg%paral_kgb==0) then
     588              :        call getghc(cpopt,cwavef,cprj_dum,gwavef,swavef,gs_hamk,gvnlxc,dum,&
     589         5363 : &       mpi_enreg,blocksize,prtvol,sij_opt,tim_getghc,0)
     590              :      else
     591              :        call prep_getghc(cwavef,gs_hamk,gvnlxc,gwavef,swavef,dum,blocksize,mpi_enreg,&
     592        23552 : &       prtvol,sij_opt,cpopt,cprj_dum,already_transposed=.false.)
     593              :      end if
     594              : #ifdef HAVE_OPENMP_OFFLOAD
     595              :      !$OMP TARGET UPDATE FROM(gwavef,gvnlxc,swavef) IF(dtset%gpu_option==ABI_GPU_OPENMP)
     596              : #endif
     597              : 
     598        28915 :      if(abs(dtset%timopt)==4) then
     599            0 :        call timab(526,2,tsec)
     600              :      end if
     601        28915 :      if(abs(dtset%timopt)==4) then
     602            0 :        call timab(524,1,tsec)
     603              :      end if
     604              : 
     605        28915 :      if (gen_eigenpb) then
     606              :        call wfcopy('D',vectsize*blocksize,swavef,1,blockvectorbr,1,blocksize,iblock,'W',withbbloc=.false.,&
     607        23365 : &       timopt=timopt,tim_wfcopy=tim_wfcopy)
     608              :      else
     609      4113243 :        blockvectorbr = blockvectorr
     610              :        call wfcopy('D',vectsize*blocksize,gvnlxc,1,blockvectorvr,1,blocksize,iblock,'W',withbbloc=.false.,&
     611         5550 : &       timopt=timopt,tim_wfcopy=tim_wfcopy)
     612              :      end if
     613              : 
     614              :      call wfcopy('D',vectsize*blocksize,gwavef,1,blockvectorar,1,blocksize,iblock,'W',withbbloc=.false.,&
     615        28915 : &     timopt=timopt,tim_wfcopy=tim_wfcopy)
     616              : 
     617        28915 :      if(use_linalg_gpu==1) then
     618            0 :        call copy_on_gpu(blockvectorbr, blockvectorbr_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
     619              :        call gpu_xorthonormalize(blockvectorr_gpu,blockvectorbr_gpu,blocksize,mpi_enreg%comm_bandspinorfft,gram_gpu,vectsize,&
     620            0 : &       x_cplx,timopt=timopt,tim_xortho=tim_xortho)
     621            0 :        call copy_from_gpu(blockvectorr,  blockvectorr_gpu,  INT(cplx, c_size_t)*dp*vectsize*blocksize)
     622            0 :        call gpu_xtrsm(cplx,'r','u','n','n',vectsize,blocksize,cone,gram_gpu,blocksize,blockvectorbr_gpu,vectsize)
     623            0 :        call copy_from_gpu(blockvectorbr, blockvectorbr_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
     624            0 :        call copy_on_gpu(blockvectorar,   blockvectorar_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
     625            0 :        call gpu_xtrsm(cplx,'r','u','n','n',vectsize,blocksize,cone,gram_gpu,blocksize,blockvectorar_gpu,vectsize)
     626            0 :        call copy_from_gpu(blockvectorar, blockvectorar_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
     627            0 :        if (gs_hamk%usepaw==0) then
     628            0 :          call copy_on_gpu(blockvectorvr,   A_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
     629            0 :          call gpu_xtrsm(cplx,'r','u','n','n',vectsize,blocksize,cone,gram_gpu,blocksize,A_gpu,vectsize)
     630            0 :          call copy_from_gpu(blockvectorvr, A_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
     631              :        end if
     632            0 :        call copy_from_gpu(gramrbr, gram_gpu, INT(cplx, c_size_t)*dp*blocksize*blocksize)
     633              :      else
     634              :        call abi_xorthonormalize(blockvectorr,blockvectorbr,blocksize,mpi_enreg%comm_bandspinorfft,gramrbr,vectsize,&
     635        28915 : &       x_cplx,timopt=timopt,tim_xortho=tim_xortho)
     636        28915 :        call abi_xtrsm('r','u','n','n',vectsize,blocksize,cone,gramrbr,blocksize,blockvectorbr,vectsize,x_cplx=x_cplx)
     637        28915 :        call abi_xtrsm('r','u','n','n',vectsize,blocksize,cone,gramrbr,blocksize,blockvectorar,vectsize,x_cplx=x_cplx)
     638        28915 :        if (gs_hamk%usepaw==0) then
     639         5550 :          call abi_xtrsm('r','u','n','n',vectsize,blocksize,cone,gramrbr,blocksize,blockvectorvr,vectsize,x_cplx=x_cplx)
     640              :        end if
     641              :      end if
     642              : 
     643        28915 :      if(iterationnumber>1) then
     644        23283 :        if(use_linalg_gpu==1) then
     645            0 :          call copy_on_gpu(blockvectorp,    A_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
     646            0 :          call copy_on_gpu(blockvectorbp,   C_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
     647              :          call gpu_xorthonormalize(A_gpu,C_gpu,blocksize,mpi_enreg%comm_bandspinorfft,gram_gpu,vectsize,&
     648            0 : &         x_cplx,timopt=timopt,tim_xortho=tim_xortho)
     649            0 :          call copy_from_gpu(blockvectorp,  A_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
     650            0 :          call gpu_xtrsm(cplx,'r','u','n','n',vectsize,blocksize,cone,gram_gpu,blocksize,C_gpu,vectsize)
     651            0 :          call copy_from_gpu(blockvectorbp, C_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
     652            0 :          call copy_on_gpu(blockvectorap,   A_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
     653            0 :          call gpu_xtrsm(cplx,'r','u','n','n',vectsize,blocksize,cone,gram_gpu,blocksize,A_gpu,vectsize)
     654            0 :          call copy_from_gpu(blockvectorap, A_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
     655            0 :          if (gs_hamk%usepaw==0) then
     656            0 :            call copy_on_gpu(blockvectorvp, A_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
     657            0 :            call gpu_xtrsm(cplx,'r','u','n','n',vectsize,blocksize,cone,gram_gpu,blocksize,A_gpu,vectsize)
     658            0 :            call copy_from_gpu(blockvectorvp, A_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
     659              :          end if
     660            0 :          call copy_from_gpu(grampbp, gram_gpu, INT(cplx, c_size_t)*dp*blocksize*blocksize)
     661              :        else
     662              : !        call orthonormalize(blockvectorp,blockvectorbp,blockvectorap)
     663              :          call abi_xorthonormalize(blockvectorp,blockvectorbp,blocksize,mpi_enreg%comm_bandspinorfft,grampbp,vectsize,&
     664        23283 : &         x_cplx,timopt=timopt,tim_xortho=tim_xortho)
     665              : !        blockvectorap=matmul(blockvectorap,grampbp)
     666        23283 :          call abi_xtrsm('r','u','n','n',vectsize,blocksize,cone,grampbp,blocksize,blockvectorbp,vectsize,x_cplx=x_cplx)
     667        23283 :          call abi_xtrsm('r','u','n','n',vectsize,blocksize,cone,grampbp,blocksize,blockvectorap,vectsize,x_cplx=x_cplx)
     668        23283 :          if (gs_hamk%usepaw==0) then
     669         4722 :            call abi_xtrsm('r','u','n','n',vectsize,blocksize,cone,grampbp,blocksize,blockvectorvp,vectsize,x_cplx=x_cplx)
     670              :          end if
     671              :        end if
     672              :      end if
     673              : 
     674        28915 :      activersize=blocksize
     675        28915 :      if (iterationnumber==1) then
     676        28915 :        activepsize=0
     677              :        restart=1
     678              :      else
     679        23283 :        activepsize=blocksize
     680        23283 :        restart=0
     681              :      end if
     682              : 
     683              : !    gramxar=matmul((blockvectorax)^T,blockvectorr)
     684              : !    gramrar=matmul((blockvectorar)^T,blockvectorr)
     685              : !    gramxax=matmul((blockvectorax)^T,blockvectorx)
     686        28915 :      if(use_linalg_gpu==1) then
     687            0 :        call copy_on_gpu(blockvectorax, A_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
     688              : 
     689              :        call gpu_xgemm(cplx,cparam(cplx),'n',blocksize,blocksize,vectsize,cone,A_gpu,&
     690            0 : &       vectsize,blockvectorr_gpu,vectsize,czero,gram_gpu,blocksize)
     691            0 :        call copy_from_gpu(gramxar, gram_gpu, INT(cplx, c_size_t)*dp*blocksize*blocksize)
     692              : 
     693              :        call gpu_xgemm(cplx,cparam(cplx),'n',blocksize,blocksize,vectsize,cone,blockvectorar_gpu,&
     694            0 : &       vectsize,blockvectorr_gpu,vectsize,czero,gram_gpu,blocksize)
     695            0 :        call copy_from_gpu(gramrar, gram_gpu, INT(cplx, c_size_t)*dp*blocksize*blocksize)
     696              : 
     697            0 :        call copy_on_gpu(blockvectorx, C_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
     698              :        call gpu_xgemm(cplx,cparam(cplx),'n',blocksize,blocksize,vectsize,cone,A_gpu,&
     699            0 : &       vectsize,C_gpu,vectsize,czero,gram_gpu,blocksize)
     700              : 
     701            0 :        call copy_from_gpu(gramxax, gram_gpu, INT(cplx, c_size_t)*dp*blocksize*blocksize)
     702              :      else
     703              :        call abi_xgemm(cparam(cplx),'n',blocksize,blocksize,vectsize,cone,blockvectorax,&
     704        28915 : &       vectsize,blockvectorr,vectsize,czero,gramxar,blocksize,x_cplx=x_cplx)
     705              :        call abi_xgemm(cparam(cplx),'n',blocksize,blocksize,vectsize,cone,blockvectorar,&
     706        28915 : &       vectsize,blockvectorr,vectsize,czero,gramrar,blocksize,x_cplx=x_cplx)
     707              :        call abi_xgemm(cparam(cplx),'n',blocksize,blocksize,vectsize,cone,blockvectorax,&
     708        28915 : &       vectsize,blockvectorx,vectsize,czero,gramxax,blocksize,x_cplx=x_cplx)
     709              :      end if
     710              : 
     711      2833751 :      transf3(:,:,1) = gramxar
     712      2833751 :      transf3(:,:,2) = gramrar
     713      2833751 :      transf3(:,:,3) = gramxax
     714        28915 :      if(abs(dtset%timopt)==3) then
     715            0 :        call timab(533,1,tsec)
     716              :      end if
     717        28915 :      call xmpi_sum(transf3,mpi_enreg%comm_bandspinorfft,ierr)
     718        28915 :      if(abs(dtset%timopt)==3) then
     719            0 :        call timab(533,2,tsec)
     720              :      end if
     721              : 
     722      2862666 :      gramxar = transf3(:,:,1)
     723      2862666 :      gramrar = transf3(:,:,2)
     724      2862666 :      gramxax = transf3(:,:,3)
     725              : 
     726              : !    gramxbx=matmul((blockvectorbx)^T,blockvectorx)
     727              : !    gramrbr=matmul((blockvectorbr)^T,blockvectorr)
     728              : !    gramxbr=matmul((blockvectorbx)^T,blockvectorr)
     729              : !    Note that the gramb matrix is more easier to construct than grama:
     730              : !    i) <x|B|x>=<r|B|r>=<p|B|p>=(1;0)
     731              : !    since the x, r and p blockvector are normalized
     732              : !    ii) <r|B|x>=(0;0)
     733              : !    since the x and r blockvector are orthogonalized
     734              : !    iii) The <p|B|r> and <p|B|x> have to be computed.
     735      2833751 :      gramxbx(:,:)=zero
     736      2833751 :      gramrbr(:,:)=zero
     737      2833751 :      gramxbr(:,:)=zero
     738       192072 :      do iblocksize=1,blocksize
     739       163157 :        gramxbx(cplx*(iblocksize-1)+1,iblocksize) = one
     740       192072 :        gramrbr(cplx*(iblocksize-1)+1,iblocksize) = one
     741              :      end do
     742              : 
     743              : !    ###########################################################################
     744              : !    ################ PERFORM LOOP ON COND #####################################
     745              : !    ###########################################################################
     746              : 
     747        28915 :      i1=0;i2=blocksize;i3=2*blocksize;i4=3*blocksize
     748        28915 :      cond: do cond_try=1,2 !2 when restart
     749        28915 :        if (restart==0) then
     750              : 
     751              : !        gramxap=matmul((blockvectorax)^T,blockvectorp)
     752              : !        gramrap=matmul((blockvectorar)^T,blockvectorp)
     753              : !        grampap=matmul((blockvectorap)^T,blockvectorp)
     754              : !        gramxbp=matmul((blockvectorbx)^T,blockvectorp)
     755              : !        gramrbp=matmul((blockvectorbr)^T,blockvectorp)
     756              : !        grampbp=matmul((blockvectorbp)^T,blockvectorp)
     757        23283 :          if(use_linalg_gpu==1) then
     758            0 :            call copy_on_gpu(blockvectorp, C_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
     759            0 :            call copy_on_gpu(blockvectorax,A_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
     760              :            call gpu_xgemm(cplx,cparam(cplx),'n',blocksize,blocksize,vectsize,&
     761            0 : &           cone,A_gpu,vectsize,C_gpu,vectsize,czero,gram_gpu,blocksize)
     762            0 :            call copy_from_gpu(gramxap, gram_gpu, INT(cplx, c_size_t)*dp*blocksize*blocksize)
     763              :            call gpu_xgemm(cplx,cparam(cplx),'n',blocksize,blocksize,vectsize,&
     764            0 : &           cone,blockvectorar_gpu,vectsize,C_gpu,vectsize,czero,gram_gpu,blocksize)
     765            0 :            call copy_from_gpu(gramrap, gram_gpu,  INT(cplx, c_size_t)*dp*blocksize*blocksize)
     766            0 :            call copy_on_gpu(blockvectorap, A_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
     767              :            call gpu_xgemm(cplx,cparam(cplx),'n',blocksize,blocksize,vectsize,&
     768            0 : &           cone,A_gpu,vectsize,C_gpu,vectsize,czero,gram_gpu,blocksize)
     769            0 :            call copy_from_gpu(grampap, gram_gpu,  INT(cplx, c_size_t)*dp*blocksize*blocksize)
     770            0 :            call copy_on_gpu(blockvectorbx, A_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
     771              :            call gpu_xgemm(cplx,cparam(cplx),'n',blocksize,blocksize,vectsize,&
     772            0 : &           cone,A_gpu,vectsize,C_gpu,vectsize,czero,gram_gpu,blocksize)
     773            0 :            call copy_from_gpu(gramxbp, gram_gpu, INT(cplx, c_size_t)*dp*blocksize*blocksize)
     774              :            call gpu_xgemm(cplx,cparam(cplx),'n',blocksize,blocksize,vectsize,&
     775            0 : &           cone,blockvectorbr_gpu,vectsize,C_gpu,vectsize,czero,gram_gpu,blocksize)
     776            0 :            call copy_from_gpu(gramrbp, gram_gpu, INT(cplx, c_size_t)*dp*blocksize*blocksize)
     777              :          else
     778              :            call abi_xgemm(cparam(cplx),'n',blocksize,blocksize,vectsize,cone,blockvectorax,&
     779        23283 : &           vectsize,blockvectorp,vectsize,czero,gramxap,blocksize,x_cplx=x_cplx)
     780              :            call abi_xgemm(cparam(cplx),'n',blocksize,blocksize,vectsize,cone,blockvectorar,&
     781        23283 : &           vectsize,blockvectorp,vectsize,czero,gramrap,blocksize,x_cplx=x_cplx)
     782              :            call abi_xgemm(cparam(cplx),'n',blocksize,blocksize,vectsize,cone,blockvectorap,&
     783        23283 : &           vectsize,blockvectorp,vectsize,czero,grampap,blocksize,x_cplx=x_cplx)
     784              :            call abi_xgemm(cparam(cplx),'n',blocksize,blocksize,vectsize,cone,blockvectorbx,&
     785        23283 : &           vectsize,blockvectorp,vectsize,czero,gramxbp,blocksize,x_cplx=x_cplx)
     786              :            call abi_xgemm(cparam(cplx),'n',blocksize,blocksize,vectsize,cone,blockvectorbr,&
     787        23283 : &           vectsize,blockvectorp,vectsize,czero,gramrbp,blocksize,x_cplx=x_cplx)
     788              :          end if
     789              : !        It's not necessary to compute the last one: <p|B|p>=(1;0) (see above)
     790      2402221 :          transf5(:,:,1)=gramxap(:,:)
     791      2402221 :          transf5(:,:,2)=gramrap(:,:)
     792      2402221 :          transf5(:,:,3)=grampap(:,:)
     793      2402221 :          transf5(:,:,4)=gramxbp(:,:)
     794      2402221 :          transf5(:,:,5)=gramrbp(:,:)
     795        23283 :          if(abs(dtset%timopt)==3) then
     796            0 :            call timab(533,1,tsec)
     797              :          end if
     798        23283 :          call xmpi_sum(transf5,mpi_enreg%comm_bandspinorfft,ierr)
     799        23283 :          if(abs(dtset%timopt)==3) then
     800            0 :            call timab(533,2,tsec)
     801              :          end if
     802      2402221 :          gramxap(:,:)=transf5(:,:,1)
     803      2402221 :          gramrap(:,:)=transf5(:,:,2)
     804      2402221 :          grampap(:,:)=transf5(:,:,3)
     805      2402221 :          gramxbp(:,:)=transf5(:,:,4)
     806      2402221 :          gramrbp(:,:)=transf5(:,:,5)
     807      2402221 :          grampbp(:,:)=zero
     808       159752 :          do iblocksize=1,blocksize
     809       159752 :            grampbp(cplx*(iblocksize-1)+1,iblocksize) = one
     810              :          end do
     811        23283 :          bigorder=i4
     812        93132 :          ABI_MALLOC(grama,(cplx*i4,i4))
     813        69849 :          ABI_MALLOC(gramb,(cplx*i4,i4))
     814        69849 :          ABI_MALLOC(eigen,(i4))
     815              : !        ABI_MALLOC(coordx,(cplx*i4,blocksize))
     816        93132 :          ABI_MALLOC(coordx1,(cplx*blocksize,blocksize))
     817        69849 :          ABI_MALLOC(coordx2,(cplx*blocksize,blocksize))
     818        69849 :          ABI_MALLOC(coordx3,(cplx*blocksize,blocksize))
     819     41206539 :          grama(:,:)=zero;gramb(:,:)=zero
     820      2402221 :          grama(gramindex(i1+1):gramindex(i2)+cplx-1,i1+1:i2)=gramxax
     821      2402221 :          grama(gramindex(i1+1):gramindex(i2)+cplx-1,i2+1:i3)=gramxar
     822      2402221 :          grama(gramindex(i1+1):gramindex(i2)+cplx-1,i3+1:i4)=gramxap
     823      2378938 :          grama(gramindex(i2+1):gramindex(i3)+cplx-1,i2+1:i3)=gramrar
     824      2402221 :          grama(gramindex(i2+1):gramindex(i3)+cplx-1,i3+1:i4)=gramrap
     825      2402221 :          grama(gramindex(i3+1):gramindex(i4)+cplx-1,i3+1:i4)=grampap
     826      2402221 :          gramb(gramindex(i1+1):gramindex(i2)+cplx-1,i1+1:i2)=gramxbx
     827      2402221 :          gramb(gramindex(i1+1):gramindex(i2)+cplx-1,i2+1:i3)=gramxbr
     828      2402221 :          gramb(gramindex(i1+1):gramindex(i2)+cplx-1,i3+1:i4)=gramxbp
     829      2402221 :          gramb(gramindex(i2+1):gramindex(i3)+cplx-1,i2+1:i3)=gramrbr
     830      2402221 :          gramb(gramindex(i2+1):gramindex(i3)+cplx-1,i3+1:i4)=gramrbp
     831      2425504 :          gramb(gramindex(i3+1):gramindex(i4)+cplx-1,i3+1:i4)=grampbp
     832              :        else
     833         5632 :          bigorder=i3
     834        22528 :          ABI_MALLOC(grama,(cplx*i3,i3))
     835        22528 :          ABI_MALLOC(gramb,(cplx*i3,i3))
     836        16896 :          ABI_MALLOC(eigen,(i3))
     837              : !        ABI_MALLOC(coordx,(cplx*i3,blocksize))
     838        22528 :          ABI_MALLOC(coordx1,(cplx*blocksize,blocksize))
     839        22528 :          ABI_MALLOC(coordx2,(cplx*blocksize,blocksize))
     840      3306064 :          grama(:,:)=zero;gramb(:,:)=zero
     841       431530 :          grama(gramindex(i1+1):gramindex(i2)+cplx-1,i1+1:i2)=gramxax
     842       431530 :          grama(gramindex(i1+1):gramindex(i2)+cplx-1,i2+1:i3)=gramxar
     843       431530 :          grama(gramindex(i2+1):gramindex(i3)+cplx-1,i2+1:i3)=gramrar
     844       431530 :          gramb(gramindex(i1+1):gramindex(i2)+cplx-1,i1+1:i2)=gramxbx
     845       431530 :          gramb(gramindex(i1+1):gramindex(i2)+cplx-1,i2+1:i3)=gramxbr
     846       431530 :          gramb(gramindex(i2+1):gramindex(i3)+cplx-1,i2+1:i3)=gramrbr
     847              :        end if
     848              : 
     849       115660 :        ABI_MALLOC(tmpgramb,(cplx*bigorder,bigorder))
     850        86745 :        ABI_MALLOC(tmpeigen,(bigorder))
     851     22299674 :        tmpgramb=gramb
     852              : 
     853              :        call abi_xheev('v','u',bigorder,tmpgramb,bigorder,tmpeigen,x_cplx=cplx,istwf_k=istwf_k, &
     854        28915 : &       timopt=timopt,tim_xeigen=tim_xeigen,use_slk=dtset%use_slk,use_gpu_magma=use_lapack_gpu)
     855              : 
     856        28915 :        condestgramb=tmpeigen(bigorder)/tmpeigen(1)
     857        28915 :        ABI_FREE(tmpgramb)
     858        28915 :        ABI_FREE(tmpeigen)
     859              : 
     860        28915 :        if (condestgramb.gt.1d+5.or.condestgramb.lt.0.d0.or.info/=0) then
     861            0 :          write(std_out,*)'condition number of the Gram matrix = ',condestgramb
     862            0 :          if (cond_try==1.and.restart==0) then
     863            0 :            ABI_FREE(grama)
     864            0 :            ABI_FREE(gramb)
     865            0 :            ABI_FREE(eigen)
     866              : !          ABI_FREE(coordx)
     867            0 :            ABI_FREE(coordx1)
     868            0 :            ABI_FREE(coordx2)
     869            0 :            if(bigorder==i4) then
     870            0 :              ABI_FREE(coordx3)
     871              :            end if
     872            0 :            if (nrestart.gt.1) then
     873            0 :              ABI_WARNING('the minimization is stopped for this block')
     874            0 :              exit iter
     875              :            else
     876            0 :              restart=1
     877            0 :              nrestart=nrestart+1
     878            0 :              call wrtout(std_out,'Lobpcgwf: restart performed',"PERS")
     879              :            end if
     880              :          else
     881            0 :            ABI_WARNING('Gramm matrix ill-conditionned: results may be unpredictable')
     882              :          end if
     883              :        else
     884              :          exit cond
     885              :        end if
     886              :      end do cond
     887              : 
     888              : !    ###########################################################################
     889              : !    ################ END LOOP ON COND #########################################
     890              : !    ###########################################################################
     891              : 
     892              :      call abi_xhegv(1,'v','u',bigorder,grama,bigorder,gramb,bigorder,eigen,x_cplx=cplx,istwf_k=istwf_k, &
     893        28915 :      timopt=timopt,tim_xeigen=tim_xeigen,use_slk=dtset%use_slk,use_gpu_magma=use_lapack_gpu)
     894              : 
     895        28915 :      deltae=-one
     896       192072 :      do iblocksize=1,blocksize
     897       479756 :        zvar(1:cplx)=lambda(cplx*(iblocksize-1)+1:cplx*(iblocksize-1)+cplx,iblocksize)
     898       163157 :        deltae=max(deltae,abs(cmplx(zvar(1),zvar(2))-eigen(iblocksize)))
     899              : #ifdef FC_CRAY
     900              :        ! Weird numerical error occurs with Cray when using abi_xcopy
     901              :        lambda(cplx*(iblocksize-1)+1,iblocksize) = eigen(iblocksize)
     902              :        if (cplx==2) lambda(cplx*iblocksize,iblocksize) = zero
     903              : #else
     904       489471 :        zvar=(/eigen(iblocksize),zero/)
     905       192072 :        call abi_xcopy(1,zvar,1,lambda(cplx*(iblocksize-1)+1,iblocksize),1,x_cplx=x_cplx)
     906              : #endif
     907              :      end do
     908              : 
     909              : !    DEBUG
     910              : !    write(std_out,*)'eigen',eigen(1:blocksize)
     911              : !    ENDDEBUG
     912              : 
     913              : !    coordx(1:bigorder*cplx,1:blocksize)=grama(1:bigorder*cplx,1:blocksize)
     914      2833751 :      coordx1(:,:) =  grama(1+i1*cplx : i2*cplx,1:blocksize)
     915      2833751 :      coordx2(:,:) =  grama(1+i2*cplx : i3*cplx,1:blocksize)
     916        28915 :      if(bigorder==i4) then
     917      2402221 :        coordx3(:,:) =  grama(1+i3*cplx : i4*cplx,1:blocksize)
     918              :      end if
     919              : 
     920              : 
     921        28915 :      if(use_linalg_gpu==1) then
     922            0 :        call copy_on_gpu(coordx2, coordx2_gpu, INT(cplx, c_size_t)*dp*blocksize*blocksize)
     923            0 :        if(bigorder==i4) then
     924            0 :          call copy_on_gpu(coordx3, coordx3_gpu, INT(cplx, c_size_t)*dp*blocksize*blocksize)
     925              :        end if
     926              :      end if
     927              : 
     928        28915 :      ABI_FREE(grama)
     929        28915 :      ABI_FREE(gramb)
     930        28915 :      ABI_FREE(eigen)
     931        28915 :      if (restart==0 .and. iterationnumber >1) then
     932              : 
     933              : !      blockvectorp=matmul(blockvectorr,coordx(i2+1:i3,:))+&
     934              : !      &               matmul(blockvectorp,coordx(i3+1:i4,:))
     935        23283 :        if(use_linalg_gpu==1) then
     936              : !        call copy_on_gpu(blockvectorr, blockvectorr_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
     937              :          call gpu_xgemm(cplx,'n','n',vectsize,blocksize,blocksize,cone,blockvectorr_gpu,&
     938            0 : &         vectsize,coordx2_gpu,blocksize,czero,C_gpu,vectsize)
     939            0 :          call copy_on_gpu(blockvectorp, A_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
     940              :          call gpu_xgemm(cplx,'n','n',vectsize,blocksize,blocksize,cone,A_gpu,vectsize,&
     941            0 : &         coordx3_gpu,blocksize,cone,C_gpu,vectsize)
     942            0 :          call copy_from_gpu(blockvectorp, C_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
     943              :        else
     944              :          call abi_xgemm('n','n',vectsize,blocksize,blocksize,cone,blockvectorr,&
     945        23283 : &         vectsize,coordx2,blocksize,czero,blockvectordumm,vectsize,x_cplx=x_cplx)
     946              :          call abi_xgemm('n','n',vectsize,blocksize,blocksize,cone,blockvectorp,&
     947        23283 : &         vectsize,coordx3,blocksize,cone,blockvectordumm,vectsize,x_cplx=x_cplx)
     948     27286240 :          blockvectorp = blockvectordumm
     949              :        end if
     950              : 
     951              : !      blockvectorap=matmul(blockvectorar,coordx(i2+1:i3,:))+&
     952              : !      &                matmul(blockvectorap,coordx(i3+1:i4,:))
     953        23283 :        if(use_linalg_gpu==1) then
     954              : !        call copy_on_gpu(blockvectorar,blockvectorar_gpu,cplx*dp*vectsize*blocksize)
     955              :          call gpu_xgemm(cplx,'n','n',vectsize,blocksize,blocksize,cone,blockvectorar_gpu,&
     956            0 : &         vectsize,coordx2_gpu,blocksize,czero,C_gpu,vectsize)
     957            0 :          call copy_on_gpu(blockvectorap, A_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
     958              :          call gpu_xgemm(cplx,'n','n',vectsize,blocksize,blocksize,cone,A_gpu,vectsize,&
     959            0 : &         coordx3_gpu,blocksize,cone,C_gpu,vectsize)
     960            0 :          call copy_from_gpu(blockvectorap, C_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
     961              :        else
     962              :          call abi_xgemm('n','n',vectsize,blocksize,blocksize,cone,blockvectorar,&
     963        23283 : &         vectsize,coordx2,blocksize,czero,blockvectordumm,vectsize,x_cplx=x_cplx)
     964              :          call abi_xgemm('n','n',vectsize,blocksize,blocksize,cone,blockvectorap,&
     965        23283 : &         vectsize,coordx3,blocksize,cone,blockvectordumm,vectsize,x_cplx=x_cplx)
     966     27286240 :          blockvectorap = blockvectordumm
     967              :        end if
     968              : 
     969              : 
     970              : !      blockvectorvp=matmul(blockvectorvr,coordx(i2+1:i3,:))+&
     971              : !      &                matmul(blockvectorvp,coordx(i3+1:i4,:))
     972        23283 :        if (gs_hamk%usepaw==0) then
     973         4722 :          if(use_linalg_gpu==1) then
     974            0 :            call copy_on_gpu(blockvectorvr, A_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
     975              :            call gpu_xgemm(cplx,'n','n',vectsize,blocksize,blocksize,cone,A_gpu,&
     976            0 : &           vectsize,coordx2_gpu,blocksize,czero,C_gpu,vectsize)
     977            0 :            call copy_on_gpu(blockvectorvp, A_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
     978              :            call gpu_xgemm(cplx,'n','n',vectsize,blocksize,blocksize,cone,A_gpu,&
     979            0 : &           vectsize,coordx3_gpu,blocksize,cone,C_gpu,vectsize)
     980            0 :            call copy_from_gpu(blockvectorvp, C_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
     981              :          else
     982              :            call abi_xgemm('n','n',vectsize,blocksize,blocksize,cone,blockvectorvr,&
     983         4722 : &           vectsize,coordx2,blocksize,czero,blockvectordumm,vectsize,x_cplx=x_cplx)
     984              :            call abi_xgemm('n','n',vectsize,blocksize,blocksize,cone,blockvectorvp,&
     985         4722 : &           vectsize,coordx3,blocksize,cone,blockvectordumm,vectsize,x_cplx=x_cplx)
     986      3491147 :            blockvectorvp = blockvectordumm
     987              :          end if
     988              :        end if
     989              : 
     990              : !      blockvectorbp=matmul(blockvectorbr,coordx(i2+1:i3,:))+&
     991              : !      &                matmul(blockvectorbp,coordx(i3+1:i4,:))
     992        23283 :        if(use_linalg_gpu==1) then
     993              : !        call copy_on_gpu(blockvectorbr,blockvectorbr_gpu,cplx*dp*vectsize*blocksize)
     994              :          call gpu_xgemm(cplx,'n','n',vectsize,blocksize,blocksize,cone,blockvectorbr_gpu,&
     995            0 : &         vectsize,coordx2_gpu,blocksize,czero,C_gpu,vectsize)
     996            0 :          call copy_on_gpu(blockvectorbp, A_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
     997              :          call gpu_xgemm(cplx,'n','n',vectsize,blocksize,blocksize,cone,A_gpu,vectsize,&
     998            0 : &         coordx3_gpu,blocksize,cone,C_gpu,vectsize)
     999            0 :          call copy_from_gpu(blockvectorbp, C_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
    1000              :        else
    1001              :          call abi_xgemm('n','n',vectsize,blocksize,blocksize,cone,blockvectorbr,&
    1002        23283 : &         vectsize,coordx2,blocksize,czero,blockvectordumm,vectsize,x_cplx=x_cplx)
    1003              :          call abi_xgemm('n','n',vectsize,blocksize,blocksize,cone,blockvectorbp,&
    1004        23283 : &         vectsize,coordx3,blocksize,cone,blockvectordumm,vectsize,x_cplx=x_cplx)
    1005     27286240 :          blockvectorbp = blockvectordumm
    1006              :        end if
    1007              : 
    1008              :      else
    1009              : 
    1010              : !      blockvectoSz =matmul(blockvectorr,coordx(i2+1:i3,:))
    1011         5632 :        if(use_linalg_gpu==1) then
    1012              : !        call copy_on_gpu(blockvectorr,blockvectorr_gpu,cplx*dp*vectsize*blocksize)
    1013              :          call gpu_xgemm(cplx,'n','n',vectsize,blocksize,blocksize,cone,blockvectorr_gpu,&
    1014            0 : &         vectsize,coordx2_gpu,blocksize,czero,C_gpu,vectsize)
    1015            0 :          call copy_from_gpu(blockvectorp, C_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
    1016              :        else
    1017              :          call abi_xgemm('n','n',vectsize,blocksize,blocksize,cone,blockvectorr,&
    1018         5632 : &         vectsize,coordx2,blocksize,czero,blockvectorp,vectsize,x_cplx=x_cplx)
    1019              :        end if
    1020              : 
    1021              : !      blockvectorap=matmul(blockvectorar,coordx(i2+1:i3,:))
    1022         5632 :        if(use_linalg_gpu==1) then
    1023              : !        call copy_on_gpu(blockvectorar,blockvectorar_gpu,cplx*dp*vectsize*blocksize)
    1024              :          call gpu_xgemm(cplx,'n','n',vectsize,blocksize,blocksize,cone,blockvectorar_gpu,&
    1025            0 : &         vectsize,coordx2_gpu,blocksize,czero,C_gpu,vectsize)
    1026            0 :          call copy_from_gpu(blockvectorap, C_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
    1027              :        else
    1028              :          call abi_xgemm('n','n',vectsize,blocksize,blocksize,cone,blockvectorar,&
    1029         5632 : &         vectsize,coordx2,blocksize,czero,blockvectorap,vectsize,x_cplx=x_cplx)
    1030              :        end if
    1031              : !      blockvectorvp=matmul(blockvectorvr,coordx(i2+1:i3,:))
    1032         5632 :        if (gs_hamk%usepaw==0) then
    1033          828 :          if(use_linalg_gpu==1) then
    1034            0 :            call copy_on_gpu(blockvectorvr, A_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
    1035              :            call gpu_xgemm(cplx,'n','n',vectsize,blocksize,blocksize,cone,A_gpu,&
    1036            0 : &           vectsize,coordx2_gpu,blocksize,czero,C_gpu,vectsize)
    1037            0 :            call copy_from_gpu(blockvectorvp, C_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
    1038              :          else
    1039              :            call abi_xgemm('n','n',vectsize,blocksize,blocksize,cone,blockvectorvr,&
    1040          828 : &           vectsize,coordx2,blocksize,czero,blockvectorvp,vectsize,x_cplx=x_cplx)
    1041              :          end if
    1042              :        end if
    1043              : 
    1044              : !      blockvectorbp=matmul(blockvectorbr,coordx(i2+1:i3,:))
    1045         5632 :        if(use_linalg_gpu==1) then
    1046              : !        call copy_on_gpu(blockvectorbr,blockvectorbr_gpu,cplx*dp*vectsize*blocksize)
    1047              :          call gpu_xgemm(cplx,'n','n',vectsize,blocksize,blocksize,cone,blockvectorbr_gpu,&
    1048            0 : &         vectsize,coordx2_gpu,blocksize,czero,C_gpu,vectsize)
    1049            0 :          call copy_from_gpu(blockvectorbp, C_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
    1050              :        else
    1051              :          call abi_xgemm('n','n',vectsize,blocksize,blocksize,cone,blockvectorbr,&
    1052         5632 : &         vectsize,coordx2,blocksize,czero,blockvectorbp,vectsize,x_cplx=x_cplx)
    1053              :        end if
    1054              :      end if
    1055              : 
    1056        28915 :      if(use_linalg_gpu==1) then
    1057            0 :        call copy_on_gpu(coordx1, coordx2_gpu, INT(cplx, c_size_t)*dp*blocksize*blocksize)
    1058              :      end if
    1059              : 
    1060              : !    blockvectorx = matmul(blockvectorx,coordx(i1+1:i2,:))+blockvectorp
    1061              :      if(use_linalg_gpu==1) then
    1062            0 :        call copy_on_gpu(blockvectorx, A_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
    1063              :        call gpu_xgemm(cplx,'n','n',vectsize,blocksize,blocksize,cone,A_gpu,&
    1064            0 : &       vectsize,coordx2_gpu,blocksize,czero,C_gpu,vectsize)
    1065            0 :        call copy_from_gpu(blockvectordumm, C_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
    1066              :      else
    1067              :        call abi_xgemm('n','n',vectsize,blocksize,blocksize,cone,blockvectorx,&
    1068        28915 : &       vectsize,coordx1,blocksize,czero,blockvectordumm,vectsize,x_cplx=x_cplx)
    1069              :      end if
    1070     33616082 :      blockvectorx = blockvectordumm+blockvectorp
    1071              : 
    1072              : !    blockvectorax= matmul(blockvectorax,coordx(i1+1:i2,:))+blockvectorap
    1073        28915 :      if(use_linalg_gpu==1) then
    1074            0 :        call copy_on_gpu(blockvectorax, A_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
    1075              :        call gpu_xgemm(cplx,'n','n',vectsize,blocksize,blocksize,cone,A_gpu,&
    1076            0 : &       vectsize,coordx2_gpu,blocksize,czero,C_gpu,vectsize)
    1077            0 :        call copy_from_gpu(blockvectordumm, C_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
    1078              :      else
    1079              :        call abi_xgemm('n','n',vectsize,blocksize,blocksize,cone,blockvectorax,&
    1080        28915 : &       vectsize,coordx1,blocksize,czero,blockvectordumm,vectsize,x_cplx=x_cplx)
    1081              :      end if
    1082     33616082 :      blockvectorax = blockvectordumm+blockvectorap
    1083              : 
    1084              : !    blockvectorvx= matmul(blockvectorvx,coordx(i1+1:i2,:))+blockvectorvp
    1085        28915 :      if (gs_hamk%usepaw==0) then
    1086         5550 :        if(use_linalg_gpu==1) then
    1087            0 :          call copy_on_gpu(blockvectorvx, A_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
    1088              :          call gpu_xgemm(cplx,'n','n',vectsize,blocksize,blocksize,cone,A_gpu,&
    1089            0 : &         vectsize,coordx2_gpu,blocksize,czero,C_gpu,vectsize)
    1090            0 :          call copy_from_gpu(blockvectordumm, C_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
    1091              :        else
    1092              :          call abi_xgemm('n','n',vectsize,blocksize,blocksize,cone,blockvectorvx,&
    1093         5550 : &         vectsize,coordx1,blocksize,czero,blockvectordumm,vectsize,x_cplx=x_cplx)
    1094              :        end if
    1095      4113243 :        blockvectorvx = blockvectordumm+blockvectorvp
    1096              :      end if
    1097              : 
    1098              : !    blockvectorbx= matmul(blockvectorbx,coordx(i1+1:i2,:))+blockvectorbp
    1099        28915 :      if(use_linalg_gpu==1) then
    1100            0 :        call copy_on_gpu(blockvectorbx, A_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
    1101              :        call gpu_xgemm(cplx,'n','n',vectsize,blocksize,blocksize,cone,A_gpu,&
    1102            0 : &       vectsize,coordx2_gpu,blocksize,czero,C_gpu,vectsize)
    1103            0 :        call copy_from_gpu(blockvectordumm, C_gpu, INT(cplx, c_size_t)*dp*vectsize*blocksize)
    1104              :      else
    1105              :        call abi_xgemm('n','n',vectsize,blocksize,blocksize,cone,blockvectorbx,&
    1106        28915 : &       vectsize,coordx1,blocksize,czero,blockvectordumm,vectsize,x_cplx=x_cplx)
    1107              :      end if
    1108     33616082 :      blockvectorbx = blockvectordumm+blockvectorbp
    1109              : 
    1110              : !    ABI_FREE(coordx)
    1111        28915 :      ABI_FREE(coordx1)
    1112        28915 :      ABI_FREE(coordx2)
    1113        28915 :      if(bigorder==i4) then
    1114        23283 :        ABI_FREE(coordx3)
    1115              :      end if
    1116              : 
    1117              : !    Check convergence on energy and eventually exit
    1118        28915 :      if (iterationnumber==1) then
    1119         5632 :        deold=deltae
    1120        23283 :      else if (iterationnumber>1) then
    1121        23283 :        if ((abs(deltae)<0.005*abs(deold)).and.(iterationnumber/=maxiterations))then
    1122         1077 :          if(prtvol>=10)then
    1123              :            write(message, '(2(a,i4),1x,a,1p,e12.4,a,e12.4,a)' ) &
    1124            0 : &           ' lobpcgwf: block',iblock,', line',iterationnumber,&
    1125            0 : &           ', deltae=',deltae,' < 0.005*',deold,' =>skip lines !'
    1126            0 :            call wrtout(std_out,message,'PERS')
    1127              :          end if
    1128              :          exit
    1129        22206 :        else if (abs(deltae)>0.005*abs(deold)) then
    1130        21669 :          if(prtvol>=10)then
    1131              :            write(message, '(2(a,i4),1x,a,1p,e12.4,a,e12.4,a)' ) &
    1132            0 : &           ' lobpcgwf: block',iblock,', line',iterationnumber,&
    1133            0 : &           ', deltae=',deltae,' > 0.005*',deold,' =>keep on working !'
    1134            0 :            call wrtout(std_out,message,'PERS')
    1135              :          end if
    1136              :        end if
    1137              :      end if
    1138              : 
    1139       119142 :      if(abs(dtset%timopt)==4) then
    1140            0 :        call timab(524,2,tsec)
    1141              :      end if
    1142              : 
    1143              :    end do iter
    1144              : 
    1145              : !  ###########################################################################
    1146              : !  ################## END LOOP ON NLINE ######################################
    1147              : !  ###########################################################################
    1148              : 
    1149         5636 :    if(abs(dtset%timopt)==4) then
    1150            0 :      call timab(525,1,tsec)
    1151              :    end if
    1152              : 
    1153         5636 :    if (havetoprecon) then
    1154              :      call xprecon(blockvectorbx,lambda,blocksize,&
    1155              : &     iterationnumber,kinpw,mpi_enreg,npw_k,my_nspinor,&
    1156         5628 : &     optekin,optpcon,pcon,blockvectorax,blockvectorr,vectsize,timopt=timopt,tim_xprecon=tim_xprecon)
    1157              : 
    1158      6325490 :      residualnorms=sum(abs(blockvectorr)**2,dim=1)
    1159              : 
    1160         5628 :      if(abs(dtset%timopt)==3) then
    1161            0 :        call timab(533,1,tsec)
    1162              :      end if
    1163         5628 :      call xmpi_sum(residualnorms,mpi_enreg%comm_bandspinorfft,ierr)
    1164         5628 :      if(abs(dtset%timopt)==3) then
    1165            0 :        call timab(533,2,tsec)
    1166              :      end if
    1167              : 
    1168        32304 :      resid_k(bblocksize+1:bblocksize+blocksize)=residualnorms(1:blocksize)
    1169              :    end if
    1170              : 
    1171              :    call wfcopy('I',vectsize*blocksize,blockvectorx,1,cg,1,blocksize,iblock,'C',withbbloc=.true.,&
    1172         5636 : &   timopt=timopt,tim_wfcopy=tim_wfcopy)
    1173              : 
    1174         5636 :    if(gen_eigenpb) then
    1175              :      call wfcopy('I',vectsize*blocksize,blockvectorbx,1,gsc,1,blocksize,iblock,'S',withbbloc=.true.,&
    1176         4804 : &     timopt=timopt,tim_wfcopy=tim_wfcopy)
    1177              :    end if
    1178              : 
    1179              : !  The Vnl+VFockACE part of the Hamiltonian is no more stored in the packed form such as it was the case for subvnlx(:).
    1180              : !  Now, the full matrix is stored in totvnlx(:,:). This trick permits:
    1181              : !  1) to avoid the reconstruction of the total matrix in vtowfk.F90 (double loop over bands)
    1182              : !  2) to use two optimized matrix-matrix blas routine for general (in lobpcgccwf.F90) or hermitian (in vtowfk.F90)
    1183              : !  operators, zgemm.f and zhemm.f respectively, rather than a triple loop in both cases.
    1184         5636 :    iwavef=iblock*blocksize
    1185         5636 :    isubh=1+2*bblocksize*(bblocksize+1)/2
    1186              : 
    1187        22544 :    ABI_MALLOC(blockvectorz,(cplx*vectsize,iwavef))
    1188         5636 :    if(bblocksize > 0 ) then
    1189    153725699 :      blockvectorz(:,1:bblocksize) = blockvectory(:,1:bblocksize)
    1190              :    end if
    1191      6328558 :    blockvectorz(:,bblocksize+1:iwavef) = blockvectorx(:,1:blocksize)
    1192              : 
    1193        22544 :    ABI_MALLOC(tsubham,(cplx*iwavef,blocksize))
    1194      1700447 :    tsubham(:,:)=zero
    1195              :    call abi_xgemm(cparam(cplx),'n',iwavef,blocksize,vectsize,cone,blockvectorz,vectsize,&
    1196         5636 : &   blockvectorax,vectsize,czero,tsubham,iwavef,x_cplx=x_cplx)
    1197              : 
    1198         5636 :    if (gs_hamk%usepaw==0) then
    1199              :      ! MG FIXME: Here gfortran4.9 allocates temporary array for C in abi_d2zgemm.
    1200              :      call abi_xgemm(cparam(cplx),'n',blocksize,iwavef,vectsize,cone,blockvectorvx,vectsize,&
    1201         8560 : &     blockvectorz,vectsize,czero,totvnlx(cplx*bblocksize+1:cplx*iwavef,1:iwavef),blocksize,x_cplx=x_cplx)
    1202              :    end if
    1203              : 
    1204        32336 :    do iblocksize=1,blocksize
    1205       782714 :      do ii=1,bblocksize+iblocksize
    1206       750378 :        if ( cplx == 1 ) then
    1207         6297 :          subham(isubh)  = tsubham(ii,iblocksize)
    1208         6297 :          subham(isubh+1)= zero
    1209              :        else
    1210       744081 :          subham(isubh)  = tsubham(2*ii-1,iblocksize)
    1211       744081 :          subham(isubh+1)= tsubham(2*ii  ,iblocksize)
    1212              :        end if
    1213       777078 :        isubh=isubh+2
    1214              :      end do
    1215              :    end do
    1216         5636 :    ABI_FREE(tsubham)
    1217         5636 :    ABI_FREE(blockvectorz)
    1218              : !  comm for subham and subvnlx are made in vtowfk
    1219              : 
    1220         5636 :    ABI_FREE(pcon)
    1221         5636 :    ABI_FREE(blockvectory)
    1222         5636 :    ABI_FREE(blockvectorby)
    1223         5636 :    ABI_FREE(gramyx)
    1224         5636 :    ABI_FREE(blockvectorx)
    1225         5636 :    ABI_FREE(blockvectorax)
    1226         5636 :    ABI_FREE(blockvectorbx)
    1227         5636 :    ABI_FREE(blockvectorr)
    1228         5636 :    ABI_FREE(blockvectorar)
    1229         5636 :    ABI_FREE(blockvectorbr)
    1230         5636 :    ABI_FREE(blockvectorp)
    1231         5636 :    ABI_FREE(blockvectorap)
    1232         5636 :    ABI_FREE(blockvectorbp)
    1233         5636 :    if (gs_hamk%usepaw==0) then
    1234          832 :      ABI_FREE(blockvectorvx)
    1235          832 :      ABI_FREE(blockvectorvp)
    1236          832 :      ABI_FREE(blockvectorvr)
    1237              :    end if
    1238         5636 :    ABI_FREE(blockvectordumm)
    1239         5636 :    ABI_FREE(gramxax)
    1240         5636 :    ABI_FREE(gramxar)
    1241         5636 :    ABI_FREE(gramxap)
    1242         5636 :    ABI_FREE(gramrar)
    1243         5636 :    ABI_FREE(gramrap)
    1244         5636 :    ABI_FREE(grampap)
    1245         5636 :    ABI_FREE(gramxbx)
    1246         5636 :    ABI_FREE(gramxbr)
    1247         5636 :    ABI_FREE(gramxbp)
    1248         5636 :    ABI_FREE(gramrbr)
    1249         5636 :    ABI_FREE(gramrbp)
    1250         5636 :    ABI_FREE(grampbp)
    1251         5636 :    ABI_FREE(transf3)
    1252         5636 :    ABI_FREE(transf5)
    1253         5636 :    ABI_FREE(lambda)
    1254         5636 :    ABI_FREE(residualnorms)
    1255        13522 :    if(use_linalg_gpu==1) then
    1256            0 :      call dealloc_on_gpu(bblockvector_gpu)
    1257            0 :      call dealloc_on_gpu(gram_gpu)
    1258              :    end if
    1259              : 
    1260              :  end do  ! End big loop over bands inside blocks
    1261              : 
    1262              : #ifdef HAVE_OPENMP_OFFLOAD
    1263              :  !$OMP TARGET EXIT DATA MAP(delete:cwavef,gwavef,gvnlxc,swavef) IF(dtset%gpu_option==ABI_GPU_OPENMP)
    1264              : #endif
    1265         2250 :  ABI_FREE(cwavef)
    1266         2250 :  ABI_FREE(gwavef)
    1267         2250 :  ABI_FREE(gvnlxc)
    1268         2250 :  ABI_FREE(swavef)
    1269         6908 :  ABI_FREE(cprj_dum)
    1270              : 
    1271         2250 :  if(use_linalg_gpu==1) then
    1272            0 :    call dealloc_on_gpu(blockvectorr_gpu)
    1273            0 :    call dealloc_on_gpu(blockvectorar_gpu)
    1274            0 :    call dealloc_on_gpu(blockvectorbr_gpu)
    1275            0 :    call dealloc_on_gpu(A_gpu)
    1276            0 :    call dealloc_on_gpu(C_gpu)
    1277            0 :    call dealloc_on_gpu(coordx2_gpu)
    1278            0 :    call dealloc_on_gpu(coordx3_gpu)
    1279              :    !call gpu_linalg_shutdown()
    1280              :  end if
    1281              : 
    1282         2250 :  if(abs(dtset%timopt)==4) then
    1283            0 :    call timab(525,2,tsec)
    1284              :  end if
    1285         2250 :  call timab(530,2,tsec)
    1286              : 
    1287              :  DBG_ENTER("COLL")
    1288              : 
    1289              :  contains
    1290              : 
    1291        28915 :    function gramindex(iblocksize)
    1292              : 
    1293              :    integer :: gramindex,iblocksize
    1294       269780 :    gramindex=(iblocksize-1)*cplx+1
    1295         2250 :  end function gramindex
    1296              : 
    1297              : end subroutine lobpcgwf
    1298              : !!***
    1299              : 
    1300              : end module m_lobpcgwf_old
    1301              : !!***
        

Generated by: LCOV version 2.3-1