!=============================================================================
!
! Routines:
!
! (1) inread_kernel()
!
!     Read input parameters from file kernel.inp
!
!     input: none
!
!     output: xct%nvb_co
!             xct%ncb_co
!             xct%ecute    energy cutoff used to calculate the
!                          interaction matrices (see Rohlfing and Louie PRB 2000 eq. 43-45)
!             xct%read_kpoints     tells whether the list of k-points is taken
!                          from "WFN_fi" or from the input "kpoints"
!                          (useful if you are working with partial samplings)
!             flagbz = 0   use all symmetries to unfold the Brillouin zone
!                    = 1   do not unfold the Brillouin zone (default)
!
!=============================================================================

#include "f_defs.h"

subroutine inread_kernel(xct,flagbz,q0vec,qg)

  use global_m
  implicit none

  type (xctinfo), intent(out) :: xct
  integer, intent(out) :: flagbz  
  real(DP), intent(out) :: q0vec(3)
  type (grid), intent(out) :: qg


  character*256 :: keyword,line,errmsg,blockword
  integer :: iostat


  integer :: ii,jj,itestq
  real(DP) :: qpt_read(3,MAX_KPTS),div
  
  PUSH_SUB(inread_kernel)

#ifdef MPI
  ! Non-root nodes should wait for root to read the whole file.
  ! That way, we can be sure root gets a chance to write errors before
  ! any die call is issued by another node. Root calls MPI_Barrier below.
  if(peinf%inode /= 0) call MPI_Barrier(MPI_COMM_WORLD, mpierr)
#endif

!-------------------------
! Set default values

  xct%ecute=0.d0
  xct%ecutg=0.d0
  xct%read_kpoints = .false.
  xct%icutv=0
  xct%iscreen=0
  xct%iwritecoul=0
  xct%truncval(1:3)=0.0d0
  xct%bLowComm=.false.
  xct%shift(:)=0.d0
  xct%qflag=1
  xct%finiteq(:)=0.d0
  xct%ilowmem=0
  flagbz=1
  xct%efermi_input=0.0d0
  xct%rfermi=.true.
  xct%iwriteint=1
  xct%freplacebz=.false.
  xct%fwritebz=.false.
  xct%degeneracy_check_override=.true.
  xct%die_outside_sphere=.false.
  xct%extended_kernel=.false.
  xct%theory=0
  xct%coulomb_mod%short_range_frac_fock=1.0d0
  xct%coulomb_mod%long_range_frac_fock=1.0d0
  xct%coulomb_mod%screening_length=0.0d0
  xct%coul_mod_flag=.false.
  xct%patched_sampling_co=.false.
#ifdef HDF5
  xct%use_hdf5 = .true.
#else
  xct%use_hdf5 = .false.
#endif

!-----------------------------------
! Never ending loop...

  do while(0.eq.0)

! Actually the loop ends when the end of the file is reached

    read(8,'(a256)',iostat=iostat) line
    if(iostat < 0) exit

! Skip comment lines

    if(len_trim(line).eq.0) cycle
    if(line(1:1).eq.'#') cycle

! Determine keyword:

    keyword=line(1:scan(line," ")-1)
    line=adjustl(line(scan(line," ")+1:256))
    
    if(trim(keyword).eq.'number_val_bands') then
      read(line,*,err=110) xct%nvb_co
    elseif(trim(keyword).eq.'number_cond_bands') then
      read(line,*,err=110) xct%ncb_co
    elseif(trim(keyword).eq.'dont_use_hdf5') then
      xct%use_hdf5 = .false.
    elseif(trim(keyword).eq.'screened_coulomb_cutoff') then
      read(line,*,err=110) xct%ecute
    elseif(trim(keyword).eq.'bare_coulomb_cutoff') then
      read(line,*,err=110) xct%ecutg
    elseif(trim(keyword).eq.'read_kpoints') then
      xct%read_kpoints = .true.
    elseif(trim(keyword).eq.'screening_semiconductor') then
      xct%iscreen=0
    elseif(trim(keyword).eq.'screening_graphene') then
      xct%iscreen=1
    elseif(trim(keyword).eq.'screening_metal') then
      xct%iscreen=2
    elseif(trim(keyword).eq.'spherical_truncation') then
      xct%icutv=2
    elseif(trim(keyword).eq.'cell_wire_truncation') then
      xct%icutv=4
    elseif(trim(keyword).eq.'cell_box_truncation') then
      xct%icutv=5
    elseif(trim(keyword).eq.'cell_slab_truncation') then
      xct%icutv=6
    elseif(trim(keyword).eq.'write_vcoul') then
      xct%iwritecoul=1
    elseif(trim(keyword).eq.'comm_mpi') then
      xct%iwriteint=1
    elseif(trim(keyword).eq.'comm_disk') then
      xct%iwriteint=0
    elseif(trim(keyword).eq.'low_comm') then
      xct%bLowComm=.true.
    elseif(trim(keyword).eq.'low_memory') then
      xct%ilowmem=1
    elseif(trim(keyword).eq.'high_memory') then
      xct%ilowmem=-1
    elseif(trim(keyword).eq.'coulomb_truncation_radius') then
      read(line,*,err=110) xct%truncval(1)
    elseif(trim(keyword).eq.'fermi_level') then
      read(line,*,err=110) xct%efermi_input
    elseif(trim(keyword).eq.'fermi_level_absolute') then
      xct%rfermi=.false.
    elseif(trim(keyword).eq.'fermi_level_relative') then
      xct%rfermi=.true.
    elseif(trim(keyword).eq.'no_symmetries_coarse_grid') then
      flagbz = 1
    elseif(trim(keyword).eq.'use_symmetries_coarse_grid') then
      flagbz = 0
    elseif(trim(keyword).eq.'fullbz_replace') then
      xct%freplacebz=.true.
    elseif(trim(keyword).eq.'fullbz_write') then
      xct%fwritebz=.true.
! There is no problem with degeneracy in kernel, actually.
!    elseif(trim(keyword).eq.'degeneracy_check_override') then
!      xct%degeneracy_check_override=.true.
    elseif(trim(keyword).eq.'die_outside_sphere') then
      xct%die_outside_sphere=.true.
    elseif(trim(keyword).eq.'ignore_outside_sphere') then
      xct%die_outside_sphere=.false.
    else
      write(errmsg,'(3a)') 'Unexpected keyword ', trim(keyword), ' was found in kernel.inp.'
      call die(errmsg, only_root_writes = .true.)
    end if
  enddo
  
  if(abs(xct%ecute).lt.TOL_Zero .and. xct%theory.eq.0) then
    call die("The screened_coulomb_cutoff keyword could not be found.")
  endif

! FHJ: How many kernel blocks to compute?
  if (xct%extended_kernel) then
    if (peinf%inode==0) write(6,'(1x,a)') &
      "Calculating the kernel for all possible (n1,n2)->(n1',n2') transitions."
    xct%n1b_co = xct%nvb_co + xct%ncb_co
    xct%n2b_co = xct%n1b_co
    if (xct%ilowmem>=0.and.peinf%inode==0) then
      write (6,'(1x,a)') 'Note: this type of kernel calculation requires the high_memory flag.'
    endif
    xct%ilowmem=-1
  else
    if (peinf%inode==0) write(6,'(1x,a)') &
      "Calculating the kernel only for (v,c)->(v',c') transitions."
    xct%n1b_co = xct%nvb_co
    xct%n2b_co = xct%ncb_co
  endif
  if (peinf%inode==0) write(6,*)

! JRD: Make a note if we have finite Q

! JRD: What screening is present?

  if(peinf%inode.eq.0) then
    if(xct%iscreen.eq.0) then
      write(6,800)
    elseif(xct%iscreen.eq.1) then
      write(6,801)
    elseif(xct%iscreen.eq.2) then
      write(6,802)
    else
      call die('Need to specify screening type')
    endif
  endif
800 format(1x,'Running with Semiconductor Screening',/)
801 format(1x,'Running with Graphene Screening',/)
802 format(1x,'Running with Metal Screening',/)

  if(peinf%inode == 0) then
    if(xct%iwriteint == 1) then ! comm_mpi
      if(peinf%npes > 1) then
        write(6,803)
      else
        write(6,805)
      endif
    else ! comm_disk
      write(6,804)
    endif
  endif
803 format(1x,'We are communicating via MPI',/)
804 format(1x,'We are communicating via disk',/)
805 format(1x,'We are not communicating',/)

  if (peinf%inode == 0) then
    if (xct%ilowmem == 1) then
      write(6,'(1x,a)') 'We are using the low-memory option.'
    elseif (xct%ilowmem == -1) then
      write(6,'(1x,a)') 'We are using the high-memory option.'
    endif
    if(xct%bLowComm) then
      write(6,'(1x,a)') 'We are using the low-communication option.'
    endif
  endif

! JRD: What truncation scheme are we using?

  if(peinf%inode.eq.0) then
    if(xct%icutv.eq.0) then
      write(6,900)
    elseif(xct%icutv.eq.2) then
      write(6,902)
      write(6,912)xct%truncval(1)
    elseif(xct%icutv.eq.4) then
      write(6,904)
    elseif(xct%icutv.eq.5) then
      write(6,905)
    elseif(xct%icutv.eq.6) then
      write(6,906)
    endif
  endif
900 format(1x,'We are using no truncation',/)
902 format(1x,'We are using a truncated Coulomb interaction (spherical)')
904 format(1x,'We are using a truncated Coulomb interaction: Cell Wire',/)
905 format(1x,'We are using a truncated Coulomb interaction: Cell Box',/)
906 format(1x,'We are using a truncated Coulomb interaction: Cell Slab',/)
912 format(1x,'r_cut = ',f10.6,' Bohr'/)
  
#ifdef MPI
  ! root lets the others go after it is done reading (see beginning of function)
  if(peinf%inode == 0) call MPI_Barrier(MPI_COMM_WORLD, mpierr)
#endif

  POP_SUB(inread_kernel)
  
  return
  
110 write(errmsg,'(3a)') 'Unexpected characters were found while reading the value for the keyword ', &
      trim(keyword), '. '
  call die(errmsg, only_root_writes = .true.)
  
end subroutine inread_kernel
