!> @file
!! Initialization for XANES calcul
!! @author Copyright (C) 2013-2014 BigDFT group
!!    This file is distributed under the terms of the
!!    GNU General Public License, see ~/COPYING file
!!    or http://www.gnu.org/copyleft/gpl.txt .
!!    For the list of contributors, see ~/AUTHORS

!> converts the bound of the lr descriptors in local bounds of the plr locregs
pure subroutine bounds_to_plr_limits(thatway,icoarse,plr,nl1,nl2,nl3,nu1,nu2,nu3)
  use locregs
  implicit none
  logical, intent(in) :: thatway !< if .true., the plr descriptors has to be filled
  !! if .false., the nl bounds are filled from the plr
  integer, intent(in) :: icoarse !<controls whether to assign coarse or fine
  !!limits. Can be 1 or 2.
  !!The 2 case cannot be doe before
  !!the case with 1 has been filled
  type(locreg_descriptors), intent(inout) :: plr !<projectors locreg
  integer, intent(inout) :: nl1,nl2,nl3,nu1,nu2,nu3 !<lower and upper bounds of locregs

  if (thatway) then
     if (icoarse==1) then !coarse limits (to be done first)
        plr%ns1=nl1
        plr%ns2=nl2
        plr%ns3=nl3

        plr%d%n1=nu1-nl1
        plr%d%n2=nu2-nl2
        plr%d%n3=nu3-nl3
     else if (icoarse == 2) then
        plr%d%nfl1=nl1-plr%ns1
        plr%d%nfl2=nl2-plr%ns2
        plr%d%nfl3=nl3-plr%ns3

        plr%d%nfu1=nu1-plr%ns1
        plr%d%nfu2=nu2-plr%ns2
        plr%d%nfu3=nu3-plr%ns3
!!$         else
!!$            stop 'WRONG icoarse'
     end if
  else
     if (icoarse==1) then !coarse limits
        nl1=plr%ns1
        nl2=plr%ns2
        nl3=plr%ns3

        nu1=plr%d%n1+plr%ns1
        nu2=plr%d%n2+plr%ns2
        nu3=plr%d%n3+plr%ns3
     else if (icoarse == 2) then
        nl1=plr%d%nfl1+plr%ns1
        nl2=plr%d%nfl2+plr%ns2
        nl3=plr%d%nfl3+plr%ns3

        nu1=plr%d%nfu1+plr%ns1
        nu2=plr%d%nfu2+plr%ns2
        nu3=plr%d%nfu3+plr%ns3
!!$         else
!!$            stop 'WRONG icoarse, false case'
     end if
  end if

end subroutine bounds_to_plr_limits

!> Fill the preconditioning projectors for a given atom 
subroutine fillPcProjOnTheFly(PPD, Glr, iat, at, hx,hy,hz,startjorb,ecut_pc,   initial_istart_c ) 
  !use module_base
  use module_types
  use compression
  use locregs, only: locreg_descriptors
  use module_abscalc
  use yaml_output
  use module_bigdft_arrays
  implicit none
  type(pcproj_data_type),  intent(in) ::PPD
  type(locreg_descriptors),  intent(in):: Glr
  integer, intent(in)  ::iat, startjorb
  real(gp), intent(in) ::  ecut_pc, hx,hy,hz
  !! real(gp), pointer :: gaenes(:)
  integer, intent(in) :: initial_istart_c
  type(atoms_data), intent(in) :: at

  ! local variables  
  type(locreg_descriptors) :: Plr
  real(gp) kx, ky, kz
  integer :: jorb, ncplx, istart_c
  real(wp), dimension(PPD%G%ncoeff ) :: Gocc
  character(len=*), parameter :: subname='fillPcProjOnTheFly'

  istart_c=initial_istart_c

  Plr%d%n1 = Glr%d%n1
  Plr%d%n2 = Glr%d%n2
  Plr%d%n3 = Glr%d%n3
!!$  Plr%geocode = at%astruct%geocode
  call yaml_warning('Here Plr%mesh has to be implemented. Needed for gaussians_to_wavelets_orb.')

  call copy_wfd(PPD%pc_nl%projs(iat)%region%plr%wfd, Plr%wfd)

!!$   Plr%wfd%keyv(:)  = &
!!$        PPD%pc_nlpspd%keyv_p(  PPD%pc_nlpspd%nseg_p(2*iat-2)+1:  PPD%pc_nlpspd%nseg_p(2*iat)   )
!!$   Plr%wfd%keyg(1:2, :)  = &
!!$        PPD%pc_nlpspd%keyg_p( 1:2,  PPD%pc_nlpspd%nseg_p(2*iat-2)+1:  PPD%pc_nlpspd%nseg_p(2*iat)   )

  kx=0.0_gp
  ky=0.0_gp
  kz=0.0_gp

  Gocc=0.0_wp

  jorb=startjorb

  do while( jorb<=PPD%G%ncoeff .and. PPD%iorbtolr(jorb)== iat) 
     if( PPD%gaenes(jorb)<ecut_pc) then

        Gocc(jorb)=1.0_wp
        ncplx=1
        call gaussians_to_wavelets_orb(ncplx,Plr,hx,hy,hz,kx,ky,kz,PPD%G,&
             Gocc(1),PPD%pc_nl%shared_proj(1))
        Gocc(jorb)=0.0_wp

        !! ---------------  use this to plot projectors
!!$              write(orbname,'(A,i4.4)')'pc_',iproj
!!$              Plr%bounds = Glr%bounds
!!$              Plr%d          = Glr%d
!!$              call plot_wf_cube(orbname,at,Plr,hx,hy,hz,PPD%G%rxyz, PPD%pc_proj(istart_c) ,"1234567890" ) 

        istart_c=istart_c + (   Plr%wfd%nvctr_c    +   7*Plr%wfd%nvctr_f   )


     endif
     jorb=jorb+1

     if(jorb> PPD%G%ncoeff) exit

  end do

  call deallocate_wfd(Plr%wfd)

END SUBROUTINE fillPcProjOnTheFly


!> Fill the preconditioning projectors for a given atom 
subroutine fillPawProjOnTheFly(PAWD, Glr, iat,  hx,hy,hz,kx,ky,kz,startjorb,   initial_istart_c, geocode, at, iatat) 
  !use module_base
  use ao_inguess, only: atomic_info
  use module_types
  use compression
  use locregs, only: locreg_descriptors
  use module_abscalc
  use yaml_output
  use module_bigdft_arrays
  implicit none
  type(pawproj_data_type),  intent(in) ::PAWD
  type(locreg_descriptors),  intent(in):: Glr
  integer, intent(in)  ::iat, startjorb
  real(gp), intent(in) ::   hx,hy,hz,kx,ky,kz
  integer, intent(in) :: initial_istart_c
  character(len=1), intent(in) :: geocode !< @copydoc poisson_solver::doc::geocode
  type(atoms_data) :: at
  integer :: iatat

  ! local variables  
  type(locreg_descriptors) :: Plr
  integer :: jorb, ncplx, istart_c
  real(wp), dimension(PAWD%G%ncoeff ) :: Gocc
  character(len=*), parameter :: subname='fillPawProjOnTheFly'


  !!Just for extracting the covalent radius and rprb
!  integer :: nsccode,mxpl,mxchg
  real(gp) ::rcov, cutoff!amu,rprb,ehomo,
!  character(len=2) :: symbol


  istart_c=initial_istart_c

  Plr%d%n1 = Glr%d%n1
  Plr%d%n2 = Glr%d%n2
  Plr%d%n3 = Glr%d%n3
!!$  Plr%geocode = geocode
  call yaml_warning('Here Plr%mesh has to be implemented. Needed for gaussians_c_to_wavelets_orb.')

  call copy_wfd(PAWD%paw_nl%projs(iat)%region%plr%wfd, Plr%wfd)

!!$   Plr%wfd%keyv(:)  = PAWD%paw_nlpspd%keyv_p(  PAWD%paw_nlpspd%nseg_p(2*iat-2)+1:  PAWD%paw_nlpspd%nseg_p(2*iat)   )
!!$   Plr%wfd%keyg(1:2, :)  = PAWD%paw_nlpspd%keyg_p( 1:2,  PAWD%paw_nlpspd%nseg_p(2*iat-2)+1:  PAWD%paw_nlpspd%nseg_p(2*iat)   )

  if (kx**2 + ky**2 + kz**2 == 0.0_gp) then
     ncplx=1
  else
     ncplx=2
  end if

  Gocc=0.0_wp

  jorb=startjorb

  !!Just for extracting the covalent radius 
  call atomic_info(at%nzatom( at%astruct%iatype(iatat)), at%nelpsp(at%astruct%iatype(iatat)) ,  &
       rcov=rcov)

  !call eleconf(at%nzatom( at%astruct%iatype(iatat)), at%nelpsp(at%astruct%iatype(iatat)) ,  &
  !     &   symbol, rcov, rprb, ehomo,neleconf, nsccode, mxpl, mxchg, amu)

  cutoff=rcov*1.5_gp

  do while( jorb<=PAWD%G%ncoeff         .and. PAWD%iorbtolr(jorb)== iat)      
     Gocc(jorb)=1.0_wp

     call gaussians_c_to_wavelets_orb(ncplx,Plr,hx,hy,hz,kx,ky,kz,PAWD%G,&
          &   Gocc(1),  PAWD%paw_nl%shared_proj(1), cutoff  )

     Gocc(jorb)=0.0_wp
!!$     !! ---------------  use this to plot projectors
!!$              write(orbname,'(A,i4.4)')'paw2_',jorb
!!$              Plr%bounds = Glr%bounds
!!$              Plr%d          = Glr%d
!!$              call plot_wf_cube(orbname,PAWD%at,Plr,hx,hy,hz,PAWD%G%rxyz, PAWD%paw_proj(istart_c) ,"1234567890" ) 

     istart_c=istart_c + (   Plr%wfd%nvctr_c    +   7*Plr%wfd%nvctr_f   ) * ncplx


     jorb=jorb+1

     if(jorb> PAWD%G%ncoeff) exit

  end do

  call deallocate_wfd(Plr%wfd)

END SUBROUTINE fillPawProjOnTheFly


!> Determine localization region for all preconditioning projectors, but do not yet fill the descriptor arrays
subroutine createPcProjectorsArrays(iproc,nproc,n1,n2,n3,rxyz,at,orbs,&
     cpmult,fpmult,hx,hy,hz, ecut_pc, &
     PPD, Glr)
  !use module_base
  use module_types
  use compression
  use locregs, only: locreg_descriptors
  use module_abscalc
  use module_interfaces, only: gaussian_pswf_basis
  use gaussians, only: deallocate_gwf
  use psp_projectors_base
  use f_precisions, only: f_byte
  use module_bigdft_arrays
  implicit none
  integer, intent(in) :: iproc,nproc,n1,n2,n3
  real(gp), intent(in) :: cpmult,fpmult,hx,hy,hz
  type(atoms_data), intent(in) :: at
  type(orbitals_data), intent(in) :: orbs

  real(gp), dimension(3,at%astruct%nat), intent(in) :: rxyz
  !real(gp), dimension(at%astruct%ntypes,3), intent(in) :: radii_cf
  real(gp), intent(in):: ecut_pc

  type(pcproj_data_type) :: PPD

  type(locreg_descriptors),  intent(in):: Glr


  !local variables
  character(len=*), parameter :: subname='createPcProjectorsArrays'
  integer :: mseg,mproj, mvctr
  integer, dimension(2,3) :: nboxc, nboxf
  integer :: iat,iseg, istart_c
  logical(f_byte), dimension(:,:,:), allocatable :: logridc, logridf


  integer :: ng
  logical :: enlargerprb
  real(wp), dimension(:), pointer :: Gocc

  integer, pointer :: iorbto_l(:)
  integer, pointer :: iorbto_m(:)
  integer, pointer :: iorbto_ishell(:)
  integer, pointer :: iorbto_iexpobeg(:)

  integer :: nspin
  integer ::  jorb
  integer :: iproj, startjorb
  real(gp) :: Pcpmult
  integer :: mprojtot, nvctr_c, nvctr_f
  integer :: nprojel_tmp

  Pcpmult=1.5*cpmult

  ng=21
  enlargerprb = .false.
  nspin=1

  nullify(PPD%G%rxyz)
  call gaussian_pswf_basis(ng,enlargerprb,iproc,nspin,at,rxyz,PPD%G,Gocc, PPD%gaenes, &
       &   PPD%iorbtolr,iorbto_l, iorbto_m,  iorbto_ishell,iorbto_iexpobeg  )  


  ! allocated  : gaenes, Gocc , PPD%iorbtolr,iorbto_l, iorbto_m,  iorbto_ishell,iorbto_iexpobeg


!!$ ========================================================================================



  PPD%pc_nl%nregions=at%astruct%nat
  call allocate_daubechies_projectors_ptr(PPD%pc_nl%projs, at%astruct%nat)

  logridc = f_malloc((/ 0.to.n1, 0.to.n2, 0.to.n3 /),id='logrid')
  logridf = f_malloc((/ 0.to.n1, 0.to.n2, 0.to.n3 /),id='logrid')


  call localize_projectors(iproc,nproc,Glr%mesh_coarse,Pcpmult,fpmult,rxyz,&
       logridc,at,orbs,PPD%pc_nl)

  ! the above routine counts atomic projector and the number of their element for psp
  ! We must therefore correct , later, nlpspd%nprojel  and nlpspd%nproj
  !-------------------

!!$  -- this one delayed, waiting for the correct pc_nlpspd%nprojel, pc_nlpspd%nproj
!!$  --
!!$  allocate(pc_proj(pc_nlpspd%nprojel+ndebug),stat=i_stat)
!!$  call memocc(i_stat,pc_proj,'pc_proj',subname)
  PPD%ecut_pc=ecut_pc

  PPD%pc_nl%nprojel=0
  PPD%pc_nl%nproj  =0

!!$ =========================================================================================  

  mprojtot=0
  jorb=1  
  ! After having determined the size of the projector descriptor arrays fill them
  do iat=1,at%astruct%nat

     mproj=0

     do while(jorb<=PPD%G%ncoeff .and. PPD%iorbtolr(jorb)== iat)

        if( PPD%gaenes(jorb)<ecut_pc) then
           mproj=mproj+1
        endif
        if(jorb==PPD%G%ncoeff) exit
        jorb=jorb+1
     end do

     mprojtot=mprojtot+mproj
     PPD%pc_nl%projs(iat)%mproj=mproj
     PPD%pc_nl%nproj=PPD%pc_nl%nproj+mproj


     if (mproj.ne.0) then 

        nprojel_tmp=0

        call bounds_to_plr_limits(.false.,1,PPD%pc_nl%projs(iat)%region%plr,&
             nboxc(1,1), nboxc(1,2), nboxc(1,3), nboxc(2,1), nboxc(2,2), nboxc(2,3))
        call fill_logrid(Glr%mesh_coarse,nboxc(1,1), nboxc(2,1), nboxc(1,2), nboxc(2,2), nboxc(1,3), nboxc(2,3),0,1,  &
             &   at%astruct%ntypes,at%astruct%iatype(iat),rxyz(1,iat),at%radii_cf(1,3),Pcpmult,logridc)

        call bounds_to_plr_limits(.false.,2,PPD%pc_nl%projs(iat)%region%plr,&
             nboxf(1,1), nboxf(1,2), nboxf(1,3), nboxf(2,1), nboxf(2,2), nboxf(2,3))
        call fill_logrid(Glr%mesh_coarse,nboxf(1,1), nboxf(2,1), nboxf(1,2), nboxf(2,2), nboxf(1,3), nboxf(2,3),0,1,  &
             &   at%astruct%ntypes,at%astruct%iatype(iat),rxyz(1,iat),at%radii_cf(1,2),fpmult,logridf)

        call init_wfd_from_sub_grids(PPD%pc_nl%projs(iat)%region%plr%wfd, n1, n2, n3, &
             logridc, nboxc, logridf, nboxf, .true.)

        mvctr =PPD%pc_nl%projs(iat)%region%plr%wfd%nvctr_c
        nprojel_tmp =nprojel_tmp +mproj*mvctr

        mvctr =PPD%pc_nl%projs(iat)%region%plr%wfd%nvctr_f
        nprojel_tmp=nprojel_tmp+mproj*mvctr*7

        if( PPD%DistProjApply)  then
           PPD%pc_nl%nprojel=max(PPD%pc_nl%nprojel,nprojel_tmp   )
        else
           PPD%pc_nl%nprojel= PPD%pc_nl%nprojel+nprojel_tmp 
        endif

     endif

  enddo


  PPD%pc_nl%shared_proj=f_malloc0_ptr(PPD%pc_nl%nprojel,id='pc_proj')
!  allocate(PPD%pc_nl%proj(PPD%pc_nl%nprojel+ndebug),stat=i_stat)
!  call memocc(i_stat,PPD%pc_proj,'pc_proj',subname)

  PPD%iproj_to_ene = f_malloc_ptr(mprojtot ,id='PPD%iproj_to_ene')
  PPD%iproj_to_factor = f_malloc_ptr(mprojtot ,id='PPD%iproj_to_factor')
  PPD%iproj_to_l = f_malloc_ptr(mprojtot ,id='PPD%iproj_to_l')
  PPD%mprojtot=mprojtot


  startjorb=1
  jorb=1
  istart_c=1
  Gocc(:)=0.0_wp

  iproj=0
  do iat=1,at%astruct%nat

     mproj=0
     do while( jorb<=PPD%G%ncoeff         .and. PPD%iorbtolr(jorb)== iat)
        if( PPD%gaenes(jorb)<ecut_pc) then
           mproj=mproj+1
        endif
        if(jorb==PPD%G%ncoeff) exit
        jorb=jorb+1
     end do

     PPD%ilr_to_mproj(iat)=mproj
     if( mproj>0) then
        nvctr_c  =PPD%pc_nl%projs(iat)%region%plr%wfd%nvctr_c!PPD%pc_nlpspd%nvctr_p(2*iat-1)-PPD%pc_nlpspd%nvctr_p(2*iat-2)
        nvctr_f  =PPD%pc_nl%projs(iat)%region%plr%wfd%nvctr_f!PPD%pc_nlpspd%nvctr_p(2*iat  )-PPD%pc_nlpspd%nvctr_p(2*iat-1)

        jorb=startjorb
        do while( jorb<=PPD%G%ncoeff         .and. PPD%iorbtolr(jorb)== iat) 
           if( PPD%gaenes(jorb)<ecut_pc) then
              iproj=iproj+1
              PPD%iproj_to_ene(iproj) = PPD%gaenes(jorb)
              PPD%iproj_to_l(iproj)   = iorbto_l(jorb)

              istart_c=istart_c + (   nvctr_c    +   7*nvctr_f   )
           endif
           jorb=jorb+1

           if(jorb> PPD%G%ncoeff) exit
        end do


        if( .not. PPD%DistProjApply) then
           istart_c= istart_c-mproj*(nvctr_c+7*nvctr_f)

           call fillPcProjOnTheFly(PPD, Glr, iat, at, hx,hy,hz, startjorb,ecut_pc ,  istart_c ) 
           istart_c= istart_c+mproj*(nvctr_c+7*nvctr_f)

!!$
!!$           ncplx=1
!!$           rdum=0.0_gp
!!$
!!$           mbvctr_c=PPD%pc_nlpspd%nvctr_p(2*iat-1)-PPD%pc_nlpspd%nvctr_p(2*iat-2)
!!$           mbvctr_f=PPD%pc_nlpspd%nvctr_p(2*iat  )-PPD%pc_nlpspd%nvctr_p(2*iat-1)
!!$           
!!$           mbseg_c=PPD%pc_nlpspd%nseg_p(2*iat-1)-PPD%pc_nlpspd%nseg_p(2*iat-2)
!!$           mbseg_f=PPD%pc_nlpspd%nseg_p(2*iat  )-PPD%pc_nlpspd%nseg_p(2*iat-1)
!!$           jseg_c=PPD%pc_nlpspd%nseg_p(2*iat-2)+1
!!$              
!!$           do idum=1, 9
!!$              call wpdot_wrap(ncplx,  &
!!$                   mbvctr_c,mbvctr_f,mbseg_c,mbseg_f,PPD%pc_nlpspd%keyv_p(jseg_c),&
!!$                   PPD%pc_nlpspd%keyg_p(1,jseg_c),PPD%pc_proj(istart_c-idum*(nvctr_c+7*nvctr_f)),& 
!!$                   mbvctr_c,mbvctr_f,mbseg_c,mbseg_f,PPD%pc_nlpspd%keyv_p(jseg_c),&
!!$                   PPD%pc_nlpspd%keyg_p(1,jseg_c),&
!!$                   PPD%pc_proj(istart_c-idum*(nvctr_c+7*nvctr_f)),&
!!$                   rdum)
!!$           end do
        endif

     end if

     !! add condition on istartc_c to see if it is < nelprj

     startjorb=jorb

  enddo

  if( .not. PPD%DistProjApply) then
     call deallocate_gwf(PPD%G)
  endif

!  call free_pspd_ptr(PPD%pc_nl%pspd)
!!$  do iat=1,at%astruct%nat
!!$     call deallocate_nonlocal_psp_descriptors(PPD%pc_nl%pspd(iat))
!!$  end do

  call f_free_ptr(PPD%pc_nl%shared_proj)

  call f_free(logridc)
  call f_free(logridf)
  call f_free_ptr(Gocc)

  call f_free_ptr(iorbto_l)
  call f_free_ptr(iorbto_m)
  call f_free_ptr(iorbto_ishell)
  call f_free_ptr(iorbto_iexpobeg)

END SUBROUTINE createPcProjectorsArrays


!> Determine localization region for all preconditioning projectors, but do not yet fill the descriptor arrays
subroutine createPawProjectorsArrays(iproc,n1,n2,n3,rxyz,at,orbs,&
     cpmult,fpmult,hx,hy,hz, &
     PAWD, Glr)
  use module_bigdft_arrays
  use module_interfaces, only: gaussian_pswf_basis_for_paw
  !use module_base
  use module_types
  use compression
  use locregs, only: locreg_descriptors
  use psp_projectors_base, only: DFT_PSP_projectors_null
  use module_abscalc
  use at_domain, only: domain_geocode
  use f_precisions, only: f_byte
  implicit none
  integer, intent(in) :: iproc,n1,n2,n3
  real(gp), intent(in) :: cpmult,fpmult,hx,hy,hz
  type(atoms_data), intent(in) :: at
  type(orbitals_data), intent(in) :: orbs

  real(gp), dimension(3,at%astruct%nat), intent(in) :: rxyz
  !real(gp), dimension(at%astruct%ntypes,3), intent(in) :: radii_cf

  type(PAWproj_data_type) ::PAWD

  type(locreg_descriptors),  intent(in):: Glr

  !local variables
  character(len=*), parameter :: subname='createPawProjectorsArrays'

  integer :: mseg,mproj, mvctr
  integer, dimension(2,3) :: nboxc, nboxf
  integer :: iat,iseg, istart_c
  logical(f_byte), dimension(:,:,:), allocatable :: logridc, logridf

  real(wp), dimension(:), pointer :: Gocc

  integer, pointer :: iorbto_l(:)
  integer, pointer :: iorbto_paw_nchannels(:)
  integer, pointer :: iorbto_m(:)
  integer, pointer :: iorbto_ishell(:)
  integer, pointer :: iorbto_iexpobeg(:)

  integer :: ncplx
  real(gp) :: kx,ky,kz
  integer ::  jorb
  integer :: iproj, startjorb
  real(gp) :: Pcpmult
  integer :: nvctr_c, nvctr_f
  integer :: iatat

  integer :: ikpt,iskpt,iekpt

  Pcpmult=1.0*cpmult


  nullify(PAWD%G%rxyz)

  call gaussian_pswf_basis_for_paw(at,rxyz,PAWD%G, &
       &   PAWD%iorbtolr,iorbto_l, iorbto_m,  iorbto_ishell,iorbto_iexpobeg  ,&
       &   iorbto_paw_nchannels, PAWD%iprojto_imatrixbeg )  


  Gocc = f_malloc0_ptr(PAWD%G%ncoeff,id='Gocc')
  

  ! allocated  : gaenes, Gocc , PAWD%iorbtolr,iorbto_l, iorbto_m,  iorbto_ishell,iorbto_iexpobeg, iorbto_paw_nchannels

!!$ ========================================================================================
  !---------
  !start from a null structure
  PAWD%paw_nl=DFT_PSP_projectors_null()

  logridc = f_malloc((/ 0.to.n1, 0.to.n2, 0.to.n3 /),id='logrid')
  logridf = f_malloc((/ 0.to.n1, 0.to.n2, 0.to.n3 /),id='logrid')

  call localize_projectors_paw(iproc,n1,n2,n3,hx,hy,hz,Pcpmult,1*fpmult,rxyz,&
       logridc,at,orbs,PAWD)

  ! the above routine counts atomic projector and the number of their element for psp
  ! We must therefore correct , later, nlpspd%nprojel  and nlpspd%nproj
  !-------------------

  PAWD%paw_nl%shared_proj=f_malloc0_ptr(PAWD%paw_nl%nprojel,id='paw_proj')

!!$  allocate(PAWD%paw_proj(PAWD%paw_nlpspd%nprojel+ndebug),stat=i_stat)
!!$  call memocc(i_stat,PAWD%paw_proj,'paw_proj',subname)

  PAWD%ilr_to_mproj = f_malloc_ptr(PAWD%G%nat  ,id='PAWD%ilr_to_mproj')
  PAWD%iproj_to_l = f_malloc_ptr(PAWD%paw_nl%nproj ,id='PAWD%iproj_to_l')
  PAWD%iproj_to_paw_nchannels = f_malloc_ptr(PAWD%paw_nl%nproj,id='PAWD%iproj_to_paw_nchannels')

!!$ =========================================================================================  

  jorb=1  
  ! After having determined the size of the projector descriptor arrays fill them
  iat=0
  do iatat=1, at%astruct%nat
     if (  at%paw_NofL(at%astruct%iatype(iatat)).gt.0  ) then
        iat=iat+1
        mproj=0
        do while( jorb<=PAWD%G%ncoeff         .and. PAWD%iorbtolr(jorb)== iat)
           mproj=mproj+1
           if(jorb==PAWD%G%ncoeff) exit
           jorb=jorb+1
        end do

        PAWD%paw_nl%nproj=PAWD%paw_nl%nproj+mproj
        if (mproj.ne.0) then 

           call bounds_to_plr_limits(.false.,1,PAWD%paw_nl%projs(iat)%region%plr,&
                nboxc(1,1), nboxc(1,2), nboxc(1,3), nboxc(2,1), nboxc(2,2), nboxc(2,3))
           call fill_logrid(Glr%mesh_coarse,nboxc(1,1), nboxc(2,1), nboxc(1,2), nboxc(2,2), nboxc(1,3), nboxc(2,3),0,1,  &
                &   at%astruct%ntypes,at%astruct%iatype(iatat),rxyz(1,iatat),at%radii_cf(1,3),Pcpmult,logridc)

           call bounds_to_plr_limits(.false.,2,PAWD%paw_nl%projs(iat)%region%plr,&
                nboxf(1,1), nboxf(1,2), nboxf(1,3), nboxf(2,1), nboxf(2,2), nboxf(2,3))
           call fill_logrid(Glr%mesh_coarse,nboxf(1,1), nboxf(2,1), nboxf(1,2), nboxf(2,2), nboxf(1,3), nboxf(2,3),0,1,  &
                &   at%astruct%ntypes,at%astruct%iatype(iatat),rxyz(1,iatat),at%radii_cf(1,2),fpmult,logridf)

           call init_wfd_from_sub_grids(PAWD%paw_nl%projs(iat)%region%plr%wfd, n1, n2, n3, &
                logridc, nboxc, logridf, nboxf, .true.)
        endif
     endif
  enddo

  if (orbs%norbp > 0) then
     iskpt=orbs%iokpt(1)
     iekpt=orbs%iokpt(orbs%norbp)
  else
     iskpt=1
     iekpt=1
  end if

  istart_c=1
  do ikpt=iskpt,iekpt     

     !features of the k-point ikpt
     kx=orbs%kpts(1,ikpt)
     ky=orbs%kpts(2,ikpt)
     kz=orbs%kpts(3,ikpt)
     !!  write( *, '(A,i4,1x,A,3(1x,d20.10))') " IKPT , " , ikpt, " K " , orbs%kpts(:,ikpt)
     !evaluate the complexity of the k-point
     if (kx**2 + ky**2 + kz**2 == 0.0_gp) then
        ncplx=1
     else
        ncplx=2
     end if

     startjorb=1
     jorb=1
     Gocc(:)=0.0_wp
     iproj=0

     iat=0
     do iatat=1, at%astruct%nat
        if (  at%paw_NofL(at%astruct%iatype(iatat)).gt.0  ) then
           iat=iat+1
           mproj=0
           do while( jorb<=PAWD%G%ncoeff         .and. PAWD%iorbtolr(jorb)== iat)
              mproj=mproj+1
              if(jorb==PAWD%G%ncoeff) exit
              jorb=jorb+1
           end do

           PAWD%ilr_to_mproj(iat)=mproj
           if( mproj>0) then
              nvctr_c  =PAWD%paw_nl%projs(iat)%region%plr%wfd%nvctr_c
              nvctr_f  =PAWD%paw_nl%projs(iat)%region%plr%wfd%nvctr_f

              jorb=startjorb
              do while( jorb<=PAWD%G%ncoeff  .and. PAWD%iorbtolr(jorb)== iat) 
                 iproj=iproj+1
                 PAWD%iproj_to_l(iproj)   = iorbto_l(jorb)
                 PAWD%iproj_to_paw_nchannels(iproj)   = iorbto_paw_nchannels(jorb)
                 istart_c=istart_c + (   nvctr_c    +   7*nvctr_f   )*ncplx
                 jorb=jorb+1
                 if(jorb> PAWD%G%ncoeff) exit
              end do
              if( .not. PAWD%DistProjApply) then
                 istart_c= istart_c-mproj*(nvctr_c+7*nvctr_f)*ncplx
                 call fillPawProjOnTheFly(PAWD, Glr, iat,  hx,hy,hz, kx,ky,kz, startjorb,&
                      &   istart_c, domain_geocode(at%astruct%dom) , at, iatat) 
                 istart_c= istart_c+mproj*(nvctr_c+7*nvctr_f)*ncplx
              endif
           end if
           startjorb=jorb
        end if
     enddo
  enddo
  if (istart_c-1 /= PAWD%paw_nl%nprojel) stop 'incorrect once-and-for-all psp generation'

  if( .not. PAWD%DistProjApply) then
     call deallocate_gwf_c(PAWD%G)
  endif

  call f_free(logridc)
  call f_free(logridf)
  call f_free_ptr(Gocc)

  call f_free_ptr(iorbto_l)
  call f_free_ptr(iorbto_paw_nchannels)

  call f_free_ptr(iorbto_m)
  call f_free_ptr(iorbto_ishell)
  call f_free_ptr(iorbto_iexpobeg)


END SUBROUTINE createPawProjectorsArrays

!> Localize the projectors for pseudopotential calculations
subroutine localize_projectors(iproc,nproc,mesh,cpmult,fpmult,rxyz,&
     logrid,at,orbs,nl)
  use module_precisions
  use module_types, only: atoms_data,orbitals_data
  use yaml_output
  use box
  use psp_projectors_base, only: DFT_PSP_projectors, atomic_projector_iter, &
       & atomic_projector_iter_new, atomic_projector_iter_next
  use psp_projectors, only: pregion_size
  use public_enums, only: PSPCODE_GTH, PSPCODE_HGH, PSPCODE_HGH_K, PSPCODE_HGH_K_NLCC
  use locregs, only: init_lr
  use at_domain, only: domain_geocode,domain,change_domain_BC
  use module_bigdft_arrays
  use module_bigdft_profiling
  use module_bigdft_mpi
  use module_bigdft_config
  implicit none
  integer, intent(in) :: iproc,nproc
  real(gp), intent(in) :: cpmult,fpmult
  type(cell), intent(in) :: mesh
  type(atoms_data), intent(in) :: at
  type(orbitals_data), intent(in) :: orbs
  type(DFT_PSP_projectors), intent(inout) :: nl
  real(gp), dimension(3,at%astruct%nat), intent(in) :: rxyz
  !real(gp), dimension(at%astruct%ntypes,3), intent(in) :: radii_cf
  logical(f_byte), dimension(0:mesh%ndims(1)-1,0:mesh%ndims(2)-1,0:mesh%ndims(3)-1), intent(inout) :: logrid
  !Local variables
  !n(c) logical :: cmplxprojs
  type(atomic_projector_iter) :: iter
  integer :: istart,ityp,iat,mproj,nl1,nu1,nl2,nu2,nl3,nu3,mvctr,mseg,nprojelat,i,l
  integer :: ikpt,nkptsproj,ikptp,izero,natp,isat
  integer :: ns1t,ns2t,ns3t,n1t,n2t,n3t
  integer, dimension(2,3) :: nbox, nb
  real(gp) :: maxfullvol,totfullvol,totzerovol,fullvol,maxrad,maxzerovol,rad
  integer,dimension(:,:),allocatable :: reducearr
  type(domain) :: dom

  call f_routine(id='localize_projectors')
  
  istart=0
  nl%nproj=0
  nl%nprojel=0

  ! Parallelize over the atoms
  call distribute_on_tasks(at%astruct%nat, iproc, nproc, natp, isat)

  reducearr = f_malloc0((/18,at%astruct%nat/),id='reducearr')

  !do iat=1,at%astruct%nat
  do iat=isat+1,isat+natp

     call atomic_projector_iter_new(iter, nl%pbasis(iat))
     mproj = iter%nproj
     
     !assign the number of projector to the localization region
     nl%projs(iat)%mproj=mproj

     if (mproj /= 0) then 

        !if some projectors are there at least one locreg interacts with the psp
        nl%projs(iat)%region%nlr=1

        !if (iproc.eq.0) write(*,'(1x,a,2(1x,i0))')&
        !     'projector descriptors for atom with mproj ',iat,mproj
        nl%nproj=nl%nproj+mproj

        ! coarse grid quantities
        call pregion_size(mesh,rxyz(1,iat),at%radii_cf(at%astruct%iatype(iat),3),&
             cpmult,nbox)
        nl1=nbox(1,1)
        nl2=nbox(1,2)
        nl3=nbox(1,3)
        nu1=nbox(2,1)
        nu2=nbox(2,2)
        nu3=nbox(2,3)

        ns1t=nl1; ns2t=nl2; ns3t=nl3
        n1t=nu1; n2t=nu2; n3t=nu3

        !these routines are associated to the handling of a locreg
        call fill_logrid(mesh,nl1,nu1,nl2,nu2,nl3,nu3,0,1,&
             at%astruct%ntypes,at%astruct%iatype(iat),rxyz(1,iat),at%radii_cf(1,3),&
             cpmult,logrid)
        call num_segkeys(mesh%ndims(1)-1,mesh%ndims(2)-1,mesh%ndims(3)-1,nl1,nu1,nl2,nu2,nl3,nu3,logrid,mseg,mvctr)

        nl%projs(iat)%region%plr%wfd%nseg_c=mseg
        nl%projs(iat)%region%plr%wfd%nvctr_c=mvctr

        istart=istart+mvctr*mproj

        nprojelat=mvctr*mproj

        !print *,'iat,mvctr',iat,mvctr,mseg,mproj

        ! fine grid quantities
        call pregion_size(mesh,rxyz(1,iat),at%radii_cf(at%astruct%iatype(iat),2),fpmult,nbox)
        nl1=nbox(1,1)
        nl2=nbox(1,2)
        nl3=nbox(1,3)
        nu1=nbox(2,1)
        nu2=nbox(2,2)
        nu3=nbox(2,3)

        nb(1, :) = (/ ns1t, ns2t, ns3t /)
        nb(2, :) = (/ n1t, n2t, n3t /)

        call fill_logrid(mesh,nl1,nu1,nl2,nu2,nl3,nu3,0,1,  &
             at%astruct%ntypes,at%astruct%iatype(iat),rxyz(1,iat),&
             at%radii_cf(1,2),fpmult,logrid)
        call num_segkeys(mesh%ndims(1)-1,mesh%ndims(2)-1,mesh%ndims(3)-1,nl1,nu1,nl2,nu2,nl3,nu3,logrid,mseg,mvctr)
        !if (iproc.eq.0) write(*,'(1x,a,2(1x,i0))') 'mseg,mvctr, fine  projectors ',mseg,mvctr

        !to be tested, particularly with respect to the
        !shift of the locreg for the origin of the
        !coordinate system
        dom=change_domain_BC(mesh%dom,geocode='F')
        !call init_lr(nl%projs(iat)%region%plr, 'F', 0.5_gp * mesh%hgrids, &
        call init_lr(nl%projs(iat)%region%plr, dom, 0.5_gp * mesh%hgrids, &
             nb, nbox, .false., at%astruct%dom, .false.)

        nl%projs(iat)%region%plr%wfd%nseg_f=mseg
        nl%projs(iat)%region%plr%wfd%nvctr_f=mvctr

        istart=istart+7*mvctr*mproj
        nprojelat=nprojelat+7*mvctr*mproj
        nl%nprojel=max(nl%nprojel,nprojelat)

        !print *,'iat,nprojelat',iat,nprojelat,mvctr,mseg

     else  !(atom has no nonlocal PSP, e.g. H)
        !Pb of inout
        izero=0

        !this is not really needed, see below
        call bounds_to_plr_limits(.true.,1,nl%projs(iat)%region%plr,&
             izero,izero,izero,izero,izero,izero)

        nl%projs(iat)%region%plr%wfd%nseg_c=0
        nl%projs(iat)%region%plr%wfd%nvctr_c=0
        nl%projs(iat)%region%plr%wfd%nseg_f=0
        nl%projs(iat)%region%plr%wfd%nvctr_f=0

        !! the following is necessary to the creation of preconditioning projectors
        !! coarse grid quantities ( when used preconditioners are applied to all atoms
        !! even H if present )
        call pregion_size(mesh,rxyz(1,iat),&
             at%radii_cf(at%astruct%iatype(iat),3),cpmult, nbox)
        nl1=nbox(1,1)
        nl2=nbox(1,2)
        nl3=nbox(1,3)
        nu1=nbox(2,1)
        nu2=nbox(2,2)
        nu3=nbox(2,3)

        call bounds_to_plr_limits(.true.,1,nl%projs(iat)%region%plr,&
             nl1,nl2,nl3,nu1,nu2,nu3)

        ! fine grid quantities
        call pregion_size(mesh,rxyz(1,iat),at%radii_cf(at%astruct%iatype(iat),2),fpmult,nbox)
        nl1=nbox(1,1)
        nl2=nbox(1,2)
        nl3=nbox(1,3)
        nu1=nbox(2,1)
        nu2=nbox(2,2)
        nu3=nbox(2,3)

        call bounds_to_plr_limits(.true.,2,nl%projs(iat)%region%plr,&
             nl1,nl2,nl3,nu1,nu2,nu3)
     endif

     ! Copy the data for the communication
     reducearr( 1,iat) = nl%projs(iat)%mproj
     reducearr( 2,iat) = nl%projs(iat)%region%nlr
     reducearr( 3,iat) = nl%projs(iat)%region%plr%wfd%nseg_c
     reducearr( 4,iat) = nl%projs(iat)%region%plr%wfd%nvctr_c
     reducearr( 5,iat) = nl%projs(iat)%region%plr%wfd%nseg_f
     reducearr( 6,iat) = nl%projs(iat)%region%plr%wfd%nvctr_f
     reducearr( 7,iat) = nl%projs(iat)%region%plr%ns1
     reducearr( 8,iat) = nl%projs(iat)%region%plr%ns2
     reducearr( 9,iat) = nl%projs(iat)%region%plr%ns3
     reducearr(10,iat) = nl%projs(iat)%region%plr%d%n1
     reducearr(11,iat) = nl%projs(iat)%region%plr%d%n2
     reducearr(12,iat) = nl%projs(iat)%region%plr%d%n3
     reducearr(13,iat) = nl%projs(iat)%region%plr%d%nfl1
     reducearr(14,iat) = nl%projs(iat)%region%plr%d%nfl2
     reducearr(15,iat) = nl%projs(iat)%region%plr%d%nfl3
     reducearr(16,iat) = nl%projs(iat)%region%plr%d%nfu1
     reducearr(17,iat) = nl%projs(iat)%region%plr%d%nfu2
     reducearr(18,iat) = nl%projs(iat)%region%plr%d%nfu3
  enddo

  ! Distribute the data to all process, using an allreduce
  if (nproc > 1) call fmpi_allreduce(reducearr, FMPI_SUM, comm=bigdft_mpi%mpi_comm)
  !$omp parallel default(none) shared(at, nl, reducearr) private(iat)
  !$omp do schedule(static)
  do iat=1,at%astruct%nat
      nl%projs(iat)%mproj           = reducearr( 1,iat)
      nl%projs(iat)%region%nlr             = reducearr( 2,iat)
      nl%projs(iat)%region%plr%wfd%nseg_c  = reducearr( 3,iat)
      nl%projs(iat)%region%plr%wfd%nvctr_c = reducearr( 4,iat)
      nl%projs(iat)%region%plr%wfd%nseg_f  = reducearr( 5,iat)
      nl%projs(iat)%region%plr%wfd%nvctr_f = reducearr( 6,iat)
      nl%projs(iat)%region%plr%ns1         = reducearr( 7,iat)
      nl%projs(iat)%region%plr%ns2         = reducearr( 8,iat)
      nl%projs(iat)%region%plr%ns3         = reducearr( 9,iat)
      nl%projs(iat)%region%plr%d%n1        = reducearr(10,iat)
      nl%projs(iat)%region%plr%d%n2        = reducearr(11,iat)
      nl%projs(iat)%region%plr%d%n3        = reducearr(12,iat)
      nl%projs(iat)%region%plr%d%nfl1      = reducearr(13,iat)
      nl%projs(iat)%region%plr%d%nfl2      = reducearr(14,iat)
      nl%projs(iat)%region%plr%d%nfl3      = reducearr(15,iat)
      nl%projs(iat)%region%plr%d%nfu1      = reducearr(16,iat)
      nl%projs(iat)%region%plr%d%nfu2      = reducearr(17,iat)
      nl%projs(iat)%region%plr%d%nfu3      = reducearr(18,iat)
  end do
  !$omp end do
  !$omp end parallel
  call f_free(reducearr)
  call fmpi_allreduce(nl%nproj, 1, FMPI_SUM, comm=bigdft_mpi%mpi_comm)
  call fmpi_allreduce(nl%nprojel, 1, FMPI_MAX, comm=bigdft_mpi%mpi_comm)
  call fmpi_allreduce(istart, 1, FMPI_SUM, comm=bigdft_mpi%mpi_comm)
  istart = istart + 1


  !control the strategy to be applied following the memory limit
  !if the projectors takes too much memory allocate only one atom at the same time
  !control the memory of the projectors expressed in GB
  if (memorylimit /= 0.e0 .and. .not. nl%on_the_fly .and. &
       real(istart-1,kind=4) > memorylimit*134217728.0e0) then
     nl%on_the_fly =.true.
  end if

  !calculate the fraction of the projector array used for allocate zero values
  !control the hardest and the softest gaussian
  totzerovol=0.0_gp
  maxfullvol=0.0_gp
  totfullvol=0.0_gp
  maxzerovol=0.0_gp
  do iat=1,at%astruct%nat
     ityp=at%astruct%iatype(iat)
     if (at%npspcode(ityp) == PSPCODE_GTH .or. &
          & at%npspcode(ityp) == PSPCODE_HGH .or. &
          & at%npspcode(ityp) == PSPCODE_HGH_K .or. &
          & at%npspcode(ityp) == PSPCODE_HGH_K_NLCC) then
        maxrad=min(maxval(at%psppar(1:4,0,ityp)),cpmult/15.0_gp*at%radii_cf(ityp,3))
        nl%zerovol=0.0_gp
        fullvol=0.0_gp
        do l=1,4
           do i=1,3
              if (at%psppar(l,i,ityp) /= 0.0_gp) then
                 rad=min(at%psppar(l,0,ityp),cpmult/15.0_gp*at%radii_cf(ityp,3))
                 nl%zerovol=nl%zerovol+(maxrad**3-rad**3)
                 fullvol=fullvol+maxrad**3
              end if
           end do
        end do
        if (fullvol >= maxfullvol .and. fullvol > 0.0_gp) then
           maxzerovol=nl%zerovol/fullvol
           maxfullvol=fullvol
        end if
        totzerovol=totzerovol+nl%zerovol
        totfullvol=totfullvol+fullvol
     end if
  end do

  !assign the total quantity per atom
  nl%zerovol=0.d0
  if (totfullvol /= 0.0_gp) then
     if (nl%on_the_fly) then
        nl%zerovol=maxzerovol
     else
        nl%zerovol=totzerovol/totfullvol
     end if
  end if

  !here is the point in which the projector strategy should be decided
  !DistProjApply shoud never change after this point

  !number of elements of the projectors
  if (.not. nl%on_the_fly) nl%nprojel=istart-1

  !Compute the multiplying coefficient for nprojel in case of imaginary k points.
  !activate the complex projector if there are kpoints
  !TO BE COMMENTED OUT
  !n(c) cmplxprojs= (orbs%kpts(1,1)**2+orbs%kpts(2,1)**2+orbs%kpts(3,1)**2 >0) .or. orbs%nkpts>1
  nkptsproj=1
  if ((.not. nl%on_the_fly) .and. orbs%norbp > 0) then
     nkptsproj = 0
     do ikptp=1,orbs%nkptsp
        ikpt=orbs%iskpts+ikptp
        if (any(orbs%kpts(:,ikpt) /= 0.0_gp) .and. &
             &  orbs%nspinor > 1) then
           nkptsproj = nkptsproj + 2
        else
           nkptsproj = nkptsproj + 1
        end if
     end do
  else if (nl%on_the_fly) then
     do ikptp=1,orbs%nkptsp
        ikpt=orbs%iskpts+ikptp
        if (any(orbs%kpts(:,ikpt) /= 0.0_gp) .and. &
             &  orbs%nspinor > 1) then
           nkptsproj = max(nkptsproj, 2)
        end if
     end do
  !else if (orbs%norbp == 0) then
  !   nkptsproj=0 !no projectors to fill without on-the-fly
  end if
  nl%nprojel=nkptsproj*nl%nprojel

  !print *,'iproc,nkptsproj',bigdft_mpi%iproc,nkptsproj,nl%nprojel,orbs%iskpts,orbs%iskpts+orbs%nkptsp

  call f_release_routine()

END SUBROUTINE localize_projectors

subroutine localize_projectors_paw(iproc,n1,n2,n3,hx,hy,hz,cpmult,fpmult,rxyz,&
     logrid,at,orbs,PAWD)
  !use module_base
  use module_types
  use module_abscalc
  use psp_projectors_base
  use box
  use at_domain
  use psp_projectors, only: pregion_size
  use numerics, only: onehalf,pi
  use f_precisions, only: f_byte
  implicit none
  integer, intent(in) :: iproc,n1,n2,n3
  real(gp), intent(in) :: cpmult,fpmult,hx,hy,hz
  type(atoms_data), intent(in) :: at
  type(orbitals_data), intent(in) :: orbs

  real(gp), dimension(3,at%astruct%nat), intent(in) :: rxyz
  !real(gp), dimension(at%astruct%ntypes,3), intent(in) :: radii_cf
  logical(f_byte), dimension(0:n1,0:n2,0:n3), intent(inout) :: logrid
  type(PAWproj_data_type) ::PAWD

  !Local variables
  integer :: istart,ityp,natyp,iat,mproj,nl1,nu1,nl2,nu2,nl3,nu3,mvctr,mseg,nprojelat,i,l
  integer :: ikpt,nkptsproj,ikptp
  integer, dimension(2,3) :: nbox
  real(gp) :: maxfullvol,totfullvol,totzerovol,zerovol,fullvol,maxrad,maxzerovol,rad
  integer :: natpaw
  type(cell) :: mesh
  type(domain) :: dom

  if (iproc.eq.0) then
     write(*,'(1x,a)')&
          '------------------------------------------------------------ PSP Projectors Creation'
     write(*,'(1x,a4,4x,a4,2(1x,a))')&
          'Type','Name','Number of atoms','Number of paw projectors per atom'
  end if
  
  istart=1
  PAWD%paw_nl%nproj=0
  PAWD%paw_nl%nprojel=0

  if (iproc ==0) then
     !print the number of projectors to be created
     do ityp=1,at%astruct%ntypes
        natyp=0
        mproj=0
        if(at%paw_NofL(ityp).gt.0) then
           do iat=1,at%astruct%nat
              if (at%astruct%iatype(iat) == ityp) then
                 if(natyp.eq.0) then
                    call numb_proj_paw(ityp,mproj)                    
                 endif
                 natyp=natyp+1
              endif
           end do
           write(*,'(1x,i4,2x,a6,1x,i15,i21)')&
                ityp,trim(at%astruct%atomnames(ityp)),natyp,mproj
        end if
     end do
  end if

  !count number of PAW projectors
  natpaw=0
  do iat=1,at%astruct%nat
     if(  at%paw_NofL(at%astruct%iatype(iat)).gt.0) then
        call numb_proj_paw(at%astruct%iatype(iat),mproj)
        if (mproj /= 0) then 
           natpaw=natpaw+1
        end if
     end if
  end do
  PAWD%paw_nl%nregions=natpaw

  call allocate_daubechies_projectors_ptr(PAWD%paw_nl%projs, PAWD%paw_nl%nregions)
  !mesh=cell_new(at%astruct%geocode,[n1+1,n2+1,n3+1],[hx,hy,hz])
  !dom=domain_new(units=ATOMIC_UNITS,bc=geocode_to_bc_enum(at%astruct%geocode),&
  !          alpha_bc=onehalf*pi,beta_ac=onehalf*pi,gamma_ab=onehalf*pi,acell=[n1+1,n2+1,n3+1]*[hx,hy,hz])
  !mesh=cell_new(dom,[n1+1,n2+1,n3+1],[hx,hy,hz])
  mesh=cell_new(at%astruct%dom,[n1+1,n2+1,n3+1],[hx,hy,hz])

  natpaw=0
  do iat=1,at%astruct%nat

     if(  at%paw_NofL(at%astruct%iatype(iat)).gt.0) then

        call numb_proj_paw(at%astruct%iatype(iat),mproj)

        if (mproj /= 0) then 
           natpaw=natpaw+1
           PAWD%paw_nl%projs(iat)%mproj=mproj
           PAWD%paw_nl%nproj=PAWD%paw_nl%nproj+mproj

           ! coarse grid quantities
           call pregion_size(mesh,rxyz(1,iat),at%radii_cf(at%astruct%iatype(iat),3),cpmult, nbox)
           nl1=nbox(1,1)
           nl2=nbox(1,2)
           nl3=nbox(1,3)
           nu1=nbox(2,1)
           nu2=nbox(2,2)
           nu3=nbox(2,3)

           call bounds_to_plr_limits(.true.,1,PAWD%paw_nl%projs(natpaw)%region%plr,&
                 nl1,nl2,nl3,nu1,nu2,nu3)

           call fill_logrid(domain_geocode(at%astruct%dom),n1,n2,n3,nl1,nu1,nl2,nu2,nl3,nu3,0,1,  &
                at%astruct%ntypes,at%astruct%iatype(iat),rxyz(1,iat),at%radii_cf(1,3),cpmult,hx,hy,hz,logrid)
           call num_segkeys(n1,n2,n3,nl1,nu1,nl2,nu2,nl3,nu3,logrid,mseg,mvctr)

           PAWD%paw_nl%projs(natpaw)%region%plr%wfd%nseg_c=mseg
           PAWD%paw_nl%projs(natpaw)%region%plr%wfd%nvctr_c=mvctr

           istart=istart+mvctr*mproj

           nprojelat=mvctr*mproj

           !print *,'iat,mvctr',iat,mvctr,mseg,mproj

           ! fine grid quantities

           call pregion_size(mesh,rxyz(1,iat),at%radii_cf(at%astruct%iatype(iat),2),&
                fpmult,nbox)
           nl1=nbox(1,1)
           nl2=nbox(1,2)
           nl3=nbox(1,3)
           nu1=nbox(2,1)
           nu2=nbox(2,2)
           nu3=nbox(2,3)

           call bounds_to_plr_limits(.true.,2,PAWD%paw_nl%projs(natpaw)%region%plr,&
                 nl1,nl2,nl3,nu1,nu2,nu3)

           call fill_logrid(domain_geocode(at%astruct%dom),n1,n2,n3,nl1,nu1,nl2,nu2,nl3,nu3,0,1,  &
                at%astruct%ntypes,at%astruct%iatype(iat),rxyz(1,iat),&
                at%radii_cf(1,2),fpmult,hx,hy,hz,logrid)
           call num_segkeys(n1,n2,n3,nl1,nu1,nl2,nu2,nl3,nu3,logrid,mseg,mvctr)
           !if (iproc.eq.0) write(*,'(1x,a,2(1x,i0))') 'mseg,mvctr, fine  projectors ',mseg,mvctr
           PAWD%paw_nl%projs(natpaw)%region%plr%wfd%nseg_f=mseg
           PAWD%paw_nl%projs(natpaw)%region%plr%wfd%nvctr_f=mvctr

           istart=istart+7*mvctr*mproj
           nprojelat=nprojelat+7*mvctr*mproj

           PAWD%paw_nl%nprojel=max(PAWD%paw_nl%nprojel,nprojelat)

           !print *,'iat,nprojelat',iat,nprojelat,mvctr,mseg

        else  !(atom has no nonlocal PSP, e.g. H)

           PAWD%paw_nl%projs(natpaw)%region%plr%wfd%nseg_c=0
           PAWD%paw_nl%projs(natpaw)%region%plr%wfd%nvctr_c=0
           PAWD%paw_nl%projs(natpaw)%region%plr%wfd%nseg_f=0
           PAWD%paw_nl%projs(natpaw)%region%plr%wfd%nvctr_f=0

           !! the following is necessary to the creation of preconditioning projectors

           ! coarse grid quantities
           call pregion_size(mesh,rxyz(1,iat),at%radii_cf(at%astruct%iatype(iat),3),cpmult, nbox)
           nl1=nbox(1,1)
           nl2=nbox(1,2)
           nl3=nbox(1,3)
           nu1=nbox(2,1)
           nu2=nbox(2,2)
           nu3=nbox(2,3)
           
           call bounds_to_plr_limits(.true.,1,PAWD%paw_nl%projs(natpaw)%region%plr,&
                nl1,nl2,nl3,nu1,nu2,nu3)

           ! fine grid quantities
           call pregion_size(mesh,rxyz(1,iat),at%radii_cf(at%astruct%iatype(iat),2),fpmult,nbox)
           nl1=nbox(1,1)
           nl2=nbox(1,2)
           nl3=nbox(1,3)
           nu1=nbox(2,1)
           nu2=nbox(2,2)
           nu3=nbox(2,3)

           call bounds_to_plr_limits(.true.,2,PAWD%paw_nl%projs(natpaw)%region%plr,&
                nl1,nl2,nl3,nu1,nu2,nu3)
        endif
     endif
  enddo
  
  
  !   if (memorylimit /= 0.e0 .and. .not. DistProjApply .and. &
  !        real(istart-1,kind=4) > memorylimit*134217728.0e0) then
  !      if (iproc == 0) then
  !         write(*,'(44x,a)') '------ On-the-fly paw projectors application'
  !      end if
  !      DistProjApply =.true.
  !   end if
  
  PAWD%paw_nl%on_the_fly=PAWD%DistProjApply

  !calculate the fraction of the projector array used for allocate zero values
  !control the hardest and the softest gaussian
  totzerovol=0.0_gp
  maxfullvol=0.0_gp
  totfullvol=0.0_gp
  do iat=1,at%astruct%nat
     if(  at%paw_NofL(at%astruct%iatype(iat)).gt.0) then
        ityp=at%astruct%iatype(iat)
        maxrad=min(maxval(at%psppar(1:4,0,ityp)),cpmult/15.0_gp*at%radii_cf(ityp,3))
        zerovol=0.0_gp
        fullvol=0.0_gp
        do l=1,4
           do i=1,3
              if (at%psppar(l,i,ityp) /= 0.0_gp) then
                 rad=min(at%psppar(l,0,ityp),cpmult/15.0_gp*at%radii_cf(ityp,3))
                 zerovol=zerovol+(maxrad**3-rad**3)
                 fullvol=fullvol+maxrad**3
              end if
           end do
        end do
        if (fullvol >= maxfullvol .and. fullvol > 0.0_gp) then
           maxzerovol=zerovol/fullvol
           maxfullvol=fullvol
        end if
        totzerovol=totzerovol+zerovol
        totfullvol=totfullvol+fullvol
     endif
  end do

  !assign the total quantity per atom
  PAWD%paw_nl%zerovol=0.d0
  if (totfullvol /= 0.0_gp) then
     if (PAWD%paw_nl%on_the_fly) then
        PAWD%paw_nl%zerovol=maxzerovol
     else
        PAWD%paw_nl%zerovol=totzerovol/totfullvol
     end if
  end if

  !here is the point in which the projector strategy should be decided
  !DistProjApply shoud never change after this point

  !number of elements of the projectors
  if (.not. PAWD%paw_nl%on_the_fly) PAWD%paw_nl%nprojel=istart-1

  nkptsproj=1
  if (.not.PAWD%paw_nl%on_the_fly .and. orbs%norbp > 0) then
     nkptsproj = 0
     !the new solution did not work when there is no orbital on the processor
     do ikptp=1,orbs%nkptsp! orbs%iokpt(1), orbs%iokpt(orbs%norbp)
        ikpt=orbs%iskpts+ikptp
!!$         print *, " k points ", orbs%kpts

        if (any(orbs%kpts(:,ikpt) /= 0.0_gp) .and. &
             &  orbs%nspinor > 1) then
           nkptsproj = nkptsproj + 2
        else
           nkptsproj = nkptsproj + 1
        end if
     end do
  else if (PAWD%paw_nl%on_the_fly) then
     !the new solution did not work when there is no orbital on the processor
     do ikptp=1,orbs%nkptsp! orbs%iokpt(1), orbs%iokpt(orbs%norbp)
        ikpt=orbs%iskpts+ikptp
        if (any(orbs%kpts(:,ikpt) /= 0.0_gp) .and. &
             &  orbs%nspinor > 1) then
           nkptsproj = max(nkptsproj, 2)
        end if
     end do
  end if
  !   print *, " nkptsproj EST    ", nkptsproj
  !   print *, " PAWD%paw_nlpspd%nprojel EST  ", PAWD%paw_nlpspd%nprojel

  PAWD%paw_nl%nprojel=nkptsproj*PAWD%paw_nl%nprojel
  if (iproc == 0) then
     if (PAWD%paw_nl%on_the_fly) then
        write(*,'(44x,a)') '------  PAWD: On-the-fly projectors application'
     else
        write(*,'(44x,a)') '------'
     end if
     write(*,'(1x,a,i21)') 'Total number of projectors =',PAWD%paw_nl%nproj
     write(*,'(1x,a,i21)') 'Total number of components =',PAWD%paw_nl%nprojel
     write(*,'(1x,a,i21)') 'Percent of zero components =',nint(100.0_gp*zerovol)
  end if

contains
  
subroutine numb_proj_paw(ityp,mproj)
  integer , intent(in):: ityp
  integer, intent(out):: mproj
  

  integer :: il,jtyp

  mproj=0
  il=0
  do jtyp=1,ityp-1
     il=il+at%paw_NofL(jtyp)
  enddo
  do i =1, at%paw_NofL(ityp)
     il=il+1
     if( at%paw_l(il).ge.0) then
        mproj=mproj+at%paw_nofchannels(il)*(2*at%paw_l(il) +1)
     else
        mproj=mproj+at%paw_nofchannels(il)*(-2*at%paw_l(il) -1)        
     endif
  enddo
end subroutine numb_proj_paw

END subroutine localize_projectors_paw
