!===============================================================================
!
! Routines:
!
! (1) inread()  Originally By ?         Last Modified 7/8/2008 (JRD)
!
!     Reads parameters from sigma.inp for the current job.
!
!===============================================================================

#include "f_defs.h"

subroutine inread(sig)

  use global_m
  use scissors_m
  use inread_common_m
  implicit none

  type (siginfo), intent(out) :: sig

  character*256 :: blockword,keyword,line, errmsg
  integer :: ii,jj,kk,nkpt_read,nqpt_read,ndiag_read,noff_read
  integer :: nbnmin,nbnmax,itestq,iostat
  
  real(DP) :: kpt_read(3,MAX_KPTS),qpt_read(3,MAX_KPTS),div
  integer :: off1_read(MAX_BANDS),off2_read(MAX_BANDS),off3_read(MAX_BANDS)
  integer :: band_occ(MAX_BANDS),diag(MAX_BANDS),spinmin,spinmax
  logical :: q0vec_read, VXC_exists, found

  PUSH_SUB(inread)

#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

!----------------------
! Initialize sig%igamma

  sig%igamma = 0

!----------------------
! Initialize wcoul0
  sig%wcoul0 = ZERO


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

  q0vec_read = .false.
  nkpt_read=0
  nqpt_read=0
  noff_read=0
  band_occ=0
  nbnmin=0
  nbnmax=0
  spinmin=1
  spinmax=1
  diag=0
#ifdef HDF5
  sig%use_hdf5 = .true.
#else
  sig%use_hdf5 = .false.
#endif
  sig%loff=0
  sig%toff=0
  sig%freq_dep=1
  sig%nFreq=1
  sig%exact_ch=-1
  sig%freqevalmin=-1.0d3
  sig%freqevalstep=-1.0d0
  sig%nfreqeval=1
  sig%iuseremainder=0
  sig%nkn=0
  sig%nq=0
  sig%nq0=0
  sig%nq1=0
  sig%subsample=.false.
  sig%ndiag=0
  sig%noffdiag=0
  sig%nspin=0
  call scissors_zero(sig%scis)
  call scissors_zero(sig%scis_outer)
  sig%spl_tck%n=0 
  sig%spl_tck_outer%n=0
  sig%avgpot=0.0d0
  sig%avgpot_outer=0.0d0
  sig%tol = TOL_Degeneracy
  sig%ggpsum=2
  sig%use_xdat=.false.
  sig%use_vxcdat=.TRUE.
  sig%use_vxc2dat=.TRUE.
  sig%ecuts=0.d0
  sig%ecutb=0.d0
  sig%ntband=0
  sig%fdf=2
  sig%dw=1.0d0
  sig%xfrac=1.0d0
  sig%gamma=0.5d0
  sig%sexcut=4.0d0
  sig%icutv=0
  sig%iscreen=0
  sig%iwritecoul=0
  sig%truncval(1:3)=0.0d0
  sig%ncrit=0
  sig%efermi_input=0.0d0
  sig%rfermi=.true.
  sig%fullConvLog=0
  sig%qgrid(1:3)=0
  sig%avgcut=TOL_Zero
  sig%iwriteint=1
  sig%freplacebz=.false.
  sig%fwritebz=.false.
  sig%degeneracy_check_override=.false.
  sig%offdiagsym=.true.
  sig%qgridsym=.true.
  sig%die_outside_sphere=.true.
  sig%averagew=.true.
  peinf%npools=0
  sig%eqp_corrections=.false.
  sig%eqp_outer_corrections=.false.
  sig%coulomb_mod%short_range_frac_fock=1.0d0
  sig%coulomb_mod%long_range_frac_fock=1.0d0
  sig%coulomb_mod%screening_length=0.0d0
  sig%coul_mod_flag=.false.

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

  do while(0.eq.0)

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

    read(55,'(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.'begin') then
      blockword=line(1:scan(line," ")-1)
      ii=0
      do while(trim(line).ne.'end')
        read(55,'(a256)',iostat=iostat) line
        if(iostat /= 0) then
          write(errmsg,'(3a)') 'The end of the file was reached while reading elements of the ', &
            trim(blockword),' block.'
          call die(errmsg, only_root_writes = .true.)
        endif
        
        if(trim(line).ne.'end') then
          ii=ii+1
          if(trim(blockword).eq.'kpoints') then
            call check_bounds_nkq(ii, 'k', 'begin kpoints')
            read(line,*,err=112) (kpt_read(jj,ii),jj=1,3),div
            kpt_read(1:3,ii)=kpt_read(1:3,ii)/div
          elseif(trim(blockword).eq.'qpoints') then
            call check_bounds_nkq(ii, 'q', 'begin qpoints')
            read(line,*,err=112) (qpt_read(jj,ii),jj=1,3),div,itestq
            qpt_read(1:3,ii)=qpt_read(1:3,ii)/div
            ! for Hartree-Fock
            if (itestq.eq.1) then
              sig%nq0 = sig%nq0 + 1
              if (.not.q0vec_read) then
                sig%q0vec(1:3)=qpt_read(1:3,ii)
                q0vec_read = .true.
              endif
            endif
          elseif(trim(blockword).eq.'diag') then
            call check_bounds_nbands(ii, 'begin diag')
            read(line,*,err=112) diag(ii)
          elseif(trim(blockword).eq.'offdiag') then
            call check_bounds_nbands(ii, 'begin offdiag')
            read(line,*,err=112) off1_read(ii),off2_read(ii),off3_read(ii)
          else
            write(errmsg,'(3a)') 'Unexpected blockword ', trim(blockword), ' was found in sigma.inp.'
            call die(errmsg, only_root_writes = .true.)
          end if
        end if
      end do
      if(trim(blockword).eq.'kpoints') then
        nkpt_read=ii
      elseif(trim(blockword).eq.'qpoints') then
        nqpt_read=ii
      elseif(trim(blockword).eq.'diag') then
        ndiag_read=ii
      elseif(trim(blockword).eq.'offdiag') then
        noff_read=ii
      endif

! Spline scissors
    elseif(trim(keyword).eq.'spline_scissors') then
      if (peinf%inode==0) then
        write(6,*) 'Reading spline coefficients from `spline_scissors.dat`'
        write(6,*)
        ! read number of pts, knots, coefficients, degree
        call open_file(20,file='spline_scissors.dat',form='formatted',status='old')
        read(20,*) sig%spl_tck%n
        SAFE_ALLOCATE(sig%spl_tck%t, (sig%spl_tck%n))
        SAFE_ALLOCATE(sig%spl_tck%c, (sig%spl_tck%n))
        read(20,*) (sig%spl_tck%t(ii), ii=1,sig%spl_tck%n)
        read(20,*) (sig%spl_tck%c(ii), ii=1,sig%spl_tck%n)
        read(20,*) sig%spl_tck%k
        call close_file(20)
      endif

! Spline scissors, outer
    elseif(trim(keyword).eq.'spline_scissors_outer') then
      if (peinf%inode==0) then
        write(6,*) 'Reading outer spline coefficients from `spline_scissors_outer.dat`'
        write(6,*)
        ! read number of pts, knots, coefficients, degree
        call open_file(20,file='spline_scissors_outer.dat',form='formatted',status='old')
        read(20,*) sig%spl_tck_outer%n
        SAFE_ALLOCATE(sig%spl_tck_outer%t, (sig%spl_tck_outer%n))
        SAFE_ALLOCATE(sig%spl_tck_outer%c, (sig%spl_tck_outer%n))
        read(20,*) (sig%spl_tck_outer%t(ii), ii=1,sig%spl_tck_outer%n)
        read(20,*) (sig%spl_tck_outer%c(ii), ii=1,sig%spl_tck_outer%n)
        read(20,*) sig%spl_tck_outer%k
        call close_file(20)
      endif

! The average potential on the faces of the unit cell in the non-periodic directions for the bands in WFN_inner

    elseif(trim(keyword).eq.'avgpot') then
      read(line,*,err=110) sig%avgpot

! The average potential on the faces of the unit cell in the non-periodic directions for the bands in WFN_outer

    elseif(trim(keyword).eq.'avgpot_outer') then
      read(line,*,err=110) sig%avgpot_outer

! Frequency dependence of the inverse dielectric matrix

    elseif(trim(keyword).eq.'frequency_dependence') then
      read(line,*,err=110) sig%freq_dep

! Frequency grid for numerical integration of full-frequency sigma (may be different from Epsilon)

    elseif(trim(keyword).eq.'init_frequency_eval') then
      read(line,*,err=110) sig%freqevalmin
    elseif(trim(keyword).eq.'delta_frequency_eval') then
      read(line,*,err=110) sig%freqevalstep
    elseif(trim(keyword).eq.'number_frequency_eval') then
      read(line,*,err=110) sig%nfreqeval

! Use full frequency tail for better energies

    elseif(trim(keyword).eq.'use_epsilon_remainder') then
      sig%iuseremainder = 1

! Grid of Qs in Epsilon

    elseif(trim(keyword).eq.'qgrid') then
      read(line,*,err=110) sig%qgrid(1), sig%qgrid(2), sig%qgrid(3)

! Compute the exact static CH

    elseif(trim(keyword).eq.'exact_static_ch') then
      read(line,*,err=110) sig%exact_ch

! Full CH convergence logging of all calculated bands

    elseif(trim(keyword).eq.'full_ch_conv_log') then
      read(line,*,err=110) sig%fullConvLog

! Half sum or full sum over G and G` vectors

    elseif(trim(keyword).eq.'ggpsum') then
      read(line,*,err=110) sig%ggpsum
      sig%ggpsum=2
! JRD. Tmp message
      if (peinf%inode .eq. 0) write(6,*) "ggpsum keyword no longer supported"

! Use use_xdat to skip the computation of bare exchange

    elseif(trim(keyword).eq.'use_xdat') then
      sig%use_xdat = .true.

! Use dont_use_vxcdat to compute exchange-correlation matrix elements from VXC

    elseif(trim(keyword).eq.'dont_use_vxcdat') then
      sig%use_vxcdat = .false.
    elseif(trim(keyword).eq.'dont_use_vxc2dat') then
      sig%use_vxc2dat = .false.
    elseif(trim(keyword).eq.'dont_use_hdf5') then
      sig%use_hdf5 = .false.
    elseif(trim(keyword).eq.'number_kpoints') then
      read(line,*,err=110) sig%nkn ! FHJ: deprecated
    elseif(trim(keyword).eq.'number_qpoints') then
      read(line,*,err=110) sig%nq ! FHJ: deprecated
    elseif(trim(keyword).eq.'number_sigma_pools') then
      read(line,*,err=110) peinf%npools
    elseif(trim(keyword).eq.'bare_coulomb_cutoff') then
      read(line,*,err=110) sig%ecutb
    elseif(trim(keyword).eq.'cell_average_cutoff') then
      read(line,*,err=110) sig%avgcut
    elseif(trim(keyword).eq.'screened_coulomb_cutoff') then
      read(line,*,err=110) sig%ecuts
    elseif(trim(keyword).eq.'number_bands') then
      read(line,*,err=110) sig%ntband
      call check_bounds_nbands(sig%ntband, 'number_bands')
    elseif(trim(keyword).eq.'band_index_min') then
      read(line,*,err=110) nbnmin
    elseif(trim(keyword).eq.'band_index_max') then
      read(line,*,err=110) nbnmax
    elseif(trim(keyword).eq.'spin_index_min') then
      read(line,*,err=110) spinmin
    elseif(trim(keyword).eq.'spin_index_max') then
      read(line,*,err=110) spinmax
    elseif(trim(keyword).eq.'finite_difference_form') then
      read(line,*,err=110) sig%fdf
    elseif(trim(keyword).eq.'finite_difference_spacing') then
      read(line,*,err=110) sig%dw
    elseif(trim(keyword).eq.'bare_exchange_fraction') then
      read(line,*,err=110) sig%xfrac
    elseif(trim(keyword).eq.'short_range_frac_fock') then
      read(line,*,err=110) sig%coulomb_mod%short_range_frac_fock
    elseif(trim(keyword).eq.'long_range_frac_fock') then
      read(line,*,err=110) sig%coulomb_mod%long_range_frac_fock
    elseif(trim(keyword).eq.'screening_length') then
      read(line,*,err=110) sig%coulomb_mod%screening_length
    elseif(trim(keyword).eq.'coulomb_truncation_radius') then
      read(line,*,err=110) sig%truncval(1)
    elseif(trim(keyword).eq.'spherical_truncation') then
      sig%icutv=2
    elseif(trim(keyword).eq.'cell_wire_truncation') then
      sig%icutv=4
    elseif(trim(keyword).eq.'cell_box_truncation') then
      sig%icutv=5
    elseif(trim(keyword).eq.'cell_slab_truncation') then
      sig%icutv=6
    elseif(trim(keyword).eq.'write_vcoul') then
      sig%iwritecoul=1
    elseif(trim(keyword).eq.'tol_degeneracy') then
      read(line,*,err=110) sig%tol
    elseif(trim(keyword).eq.'gpp_broadening') then
      read(line,*,err=110) sig%gamma
    elseif(trim(keyword).eq.'gpp_sexcutoff') then
      read(line,*,err=110) sig%sexcut
    elseif(trim(keyword).eq.'wavefunction_cutoff') then
      if(peinf%inode.eq.0) then
        write(0,123)
      endif
123   format(1x,"WARNING: Found keyword wavefunction_cutoff in the input file.",/,&
        10x,"This option is obsolete, use program wfnreduce instead.",/)
    elseif(trim(keyword).eq.'number_diag') then
      read(line,*,err=110) sig%ndiag
    elseif(trim(keyword).eq.'number_offdiag') then
      read(line,*,err=110) sig%noffdiag
    elseif(trim(keyword).eq.'sigma_matrix') then
      read(line,*,err=110) sig%loff, sig%toff
    elseif(trim(keyword).eq.'screening_semiconductor') then
      sig%iscreen=0
    elseif(trim(keyword).eq.'screening_graphene') then
      sig%iscreen=1
    elseif(trim(keyword).eq.'screening_metal') then
      sig%iscreen=2
    elseif(trim(keyword).eq.'band_occupation') then
      read(line,*,err=110) (band_occ(ii),ii=1,sig%ntband)
    elseif(trim(keyword).eq.'number_partial_occup') then
      read(line,*,err=110) sig%ncrit
    elseif(trim(keyword).eq.'ncrit') then
      if(peinf%inode.eq.0) then
        write(0,124)           
      endif
124   format(1x,"WARNING: Found keyword ncrit in the input file.",/,&
        10x,"This option is deprecated, use keyword number_partial_occup instead.",/)
      read(line,*,err=110) sig%ncrit
    elseif(trim(keyword).eq.'fermi_level') then
      read(line,*,err=110) sig%efermi_input
    elseif(trim(keyword).eq.'fermi_level_absolute') then
      sig%rfermi=.false.
    elseif(trim(keyword).eq.'fermi_level_relative') then
      sig%rfermi=.true.
    elseif(trim(keyword).eq.'comm_mpi') then
      sig%iwriteint=1
    elseif(trim(keyword).eq.'comm_disk') then
      sig%iwriteint=0
    elseif(trim(keyword).eq.'fullbz_replace') then
      sig%freplacebz=.true.
    elseif(trim(keyword).eq.'fullbz_write') then
      sig%fwritebz=.true.
    elseif(trim(keyword).eq.'degeneracy_check_override') then
      sig%degeneracy_check_override=.true.
    elseif(trim(keyword).eq.'no_symmetries_offdiagonals') then
      sig%offdiagsym=.false.
    elseif(trim(keyword).eq.'no_symmetries_q_grid') then
      sig%qgridsym=.false.
    elseif(trim(keyword).eq.'use_symmetries_q_grid') then
      sig%qgridsym=.true.
    elseif(trim(keyword).eq.'die_outside_sphere') then
      sig%die_outside_sphere=.true.
    elseif(trim(keyword).eq.'ignore_outside_sphere') then
      sig%die_outside_sphere=.false.
    elseif(trim(keyword).eq.'eqp_corrections') then
      sig%eqp_corrections=.true.
    elseif(trim(keyword).eq.'eqp_outer_corrections') then
      sig%eqp_outer_corrections=.true.
    elseif(trim(keyword).eq.'skip_averagew') then
      sig%averagew = .false.
    else
      call scissors_inread(keyword, line, sig%scis, found)
      if(.not. found) call scissors_inread(keyword, line, sig%scis_outer, found, "_outer")
      if(.not. found) then
        write(errmsg,'(3a)') 'Unexpected keyword ', trim(keyword), ' was found in sigma.inp.'
        call die(errmsg, only_root_writes = .true.)
      endif
    end if
  enddo

  ! entered in Ryd, stored in eV since kp%el and kp%elda are soon converted to eV.
  sig%tol = sig%tol * RYD

  if (peinf%inode==0 .and. sig%nkn>0) then
    write(0,'(/,a)') 'WARNING: the `number_kpoints` flag is deprecated. The code now'
    write(0,'(a,/)') 'automatically figures out the number of q-points from the input.'
  endif
  sig%nkn = nkpt_read
  if (peinf%inode==0 .and. sig%nq>0) then
    write(0,'(/,a)') 'WARNING: the `number_qpoints` flag is deprecated. The code now'
    write(0,'(a,/)') 'automatically figures out the number of k-points from the input.'
  endif
  sig%nq = nqpt_read
  if(sig%freq_dep==-1 .and. sig%nq<1) then
    write(0,'(/,a)') 'ERROR: Hartree-Fock calculations require a list of q-points'
    call die('The `begin qpoints` block could not be found.', only_root_writes=.true.)
  endif
  sig%nq1 = sig%nq - sig%nq0

  if(any(sig%qgrid(1:3) == 0).and.sig%freq_dep.eq.-1) then
    call die('qgrid must be specified for Hartree-Fock.', only_root_writes = .true.)
  endif
  
  if(.not. q0vec_read .and. sig%freq_dep .eq. -1) then
    call die('No q0 specified in qpoints block.', only_root_writes = .true.)
  endif
  
  SAFE_ALLOCATE(sig%kpt, (3,sig%nkn))
  sig%kpt(1:3,1:sig%nkn)=kpt_read(1:3,1:sig%nkn)
 
! This was true when we were not averaging V as well. So while a misnomer (ie we are
! not really averaging W but V and recalculating eps such that epsinv*V(q0vec) = epsnewinv*V(q=0)
! we still use this flag to be true.
  !if (sig%iscreen .eq. 2) then
  !  sig%averagew = .false.
  !endif

  if (sig%nq>0) then
    if (sig%freq_dep/=-1) then
      if (peinf%inode==0) &
        write(0,'(/,a,/)') 'WARNING: ignoring the qpoints block for calculations other than HF.'
    else
      SAFE_ALLOCATE(sig%qpt, (3,sig%nq))
      sig%qpt(1:3,1:sig%nq)=qpt_read(1:3,1:sig%nq)
    endif
  endif
  
  if(sig%ndiag.ne.0) then
    SAFE_ALLOCATE(sig%diag, (sig%ndiag))
    sig%diag(1:sig%ndiag)=diag(1:sig%ndiag)
  endif
  
  if(sig%ndiag.eq.0.and.nbnmin*nbnmax.ne.0) then
    sig%ndiag= nbnmax - nbnmin + 1
    ndiag_read = sig%ndiag
    SAFE_ALLOCATE(sig%diag, (sig%ndiag))
    do ii=1,sig%ndiag
      sig%diag(ii)= ii + nbnmin - 1
    enddo
  endif
  
  if(sig%ndiag.eq.0.and.nbnmin*nbnmax.eq.0) then
    write(errmsg,'(a,3i6)') 'Incomprehensible list of energy bands: ', sig%ndiag, nbnmin, nbnmax
    call die(errmsg, only_root_writes = .true.)
  endif
  
  if(ndiag_read.lt.sig%ndiag) then
    if(peinf%inode.eq.0) then
      write(0,*) 'The number of diagonal elements found in the diag block (',ndiag_read,')'
      write(0,*) '  is smaller than the one specified by the keyword number_diag (',sig%ndiag,').'
    endif
    call die("ndiag too small", only_root_writes = .true.)
  endif
  
  ! no finite-difference evaluation unless GPP
  if(sig%freq_dep /= 1 .and. sig%freq_dep /= 3) sig%fdf=-2

  if(ndiag_read.gt.sig%ndiag) then
    if(peinf%inode.eq.0) then
      write(0,887) ndiag_read, sig%ndiag, sig%ndiag
    endif
  endif
887 format(1x,"WARNING: The number of diag elements in the diag block (",i4,") is larger",/,&
      3x,"than the one specified by the keyword number_diag (",i4,").",/,&
      3x,"The program will continue using only",i4,1x,"diagonal elements.",/)
  
  if(nbnmin*nbnmax.eq.0) then
    nbnmin=max_bands
    nbnmax=-max_bands
    do ii=1,sig%ndiag
      if (sig%diag(ii).lt.nbnmin) nbnmin=sig%diag(ii)
      if (sig%diag(ii).gt.nbnmax) nbnmax=sig%diag(ii)
    enddo
  endif
  
  sig%bmin=nbnmin
  sig%bmax=nbnmax

  if(sig%loff.lt.-2.or.(sig%loff.gt.0.and.sig%loff.lt.nbnmin).or. &
    sig%loff.gt.nbnmax.or.sig%toff.lt.-1.or.sig%toff.gt.1) then
    call die("sigma_matrix parameters out of range", only_root_writes = .true.)
  endif
  
  if(sig%loff.ne.0) then
    if(noff_read.ne.0.or.sig%noffdiag.gt.0) then
      if(peinf%inode.eq.0) then
        write(0,994)
      endif
    endif
    kk=0
    do ii=nbnmin,nbnmax
      do jj=nbnmin,nbnmax
        if (sig%toff.eq.-1.and.ii.lt.jj) cycle
        if (sig%toff.eq.1.and.ii.gt.jj) cycle
        kk=kk+1
        off1_read(kk)=ii
        off2_read(kk)=jj
        if (sig%loff.eq.-1) then
          off3_read(kk)=ii
        else if (sig%loff.eq.-2) then
          off3_read(kk)=jj
        else
          off3_read(kk)=sig%loff
        endif
      enddo
    enddo
    sig%noffdiag=kk
    noff_read=sig%noffdiag
  endif
994 format(1x,"WARNING: both offdiag and sigma_matrix found in sigma.inp.",/,&
      3x,"The latter overrides the former.",/)
  
  if(noff_read.lt.sig%noffdiag) then
    if(peinf%inode.eq.0) then
      write(0,997) noff_read, sig%noffdiag
    endif
    call die("offdiag error", only_root_writes = .true.)
  endif
997 format(1x,"The number of offdiag elements in the offdiag block (",i4,") is",/,&
      3x,"smaller than the one specified by the keyword number_offdiag (",i4,").")
  
  if(noff_read.gt.sig%noffdiag) then
    if(peinf%inode.eq.0) then
      write(0,996) noff_read, sig%noffdiag, sig%noffdiag
    endif
  endif
996 format(1x,"WARNING: The number of offdiag elements in the offdiag block (",i4,") is",/,&
      3x,"larger than the one specified by the keyword number_offdiag (",i4,").",/,&
      3x,"The program will continue using only",i4,1x,"offdiag elements.",/)
  
  ! allocate even if noffdiag = 0 since sunf90 -xcheck will complain when passed unallocated to read_matrix_elements
  SAFE_ALLOCATE(sig%off1, (sig%noffdiag))
  SAFE_ALLOCATE(sig%off2, (sig%noffdiag))
  SAFE_ALLOCATE(sig%off3, (sig%noffdiag))
  if(sig%noffdiag.gt.0) then
    sig%off1(1:sig%noffdiag)=off1_read(1:sig%noffdiag)
    sig%off2(1:sig%noffdiag)=off2_read(1:sig%noffdiag)
    sig%off3(1:sig%noffdiag)=off3_read(1:sig%noffdiag)
  endif
  
  if(abs(sig%ecuts).lt.TOL_Zero) then
    call die("The screened_coulomb_cutoff keyword could not be found.", only_root_writes = .true.)
  endif
  
  if(abs(sig%ecutb).lt.TOL_Zero) then
    call die("The bare_coulomb_cutoff keyword could not be found.", only_root_writes = .true.)
  endif

  if(sig%ecuts > sig%ecutb) then
    call die("The screened_coulomb_cutoff cannot be greater than the bare_coulomb_cutoff.", only_root_writes = .true.)
  endif

  ! FHJ: Make sure the user entered a valid number of bands
  call check_consistency_nbands(sig%ntband, .true.)
  
  do ii=1,sig%ndiag
    if (sig%diag(ii).gt.sig%ntband) then
      write(errmsg,'(a,3i6)') 'The band_index_max cannot be greater than number_bands: ', ii, sig%diag(ii), sig%ntband
      call die(errmsg, only_root_writes = .true.)
    endif
  enddo
  
  if(spinmin.eq.1.and.spinmax.eq.1) then
    sig%nspin=1
    sig%spin_index(1)=1
    sig%spin_index(2)=2 ! only used for spinor case
  elseif(spinmin.eq.2.and.spinmax.eq.2) then
    sig%nspin=1
    sig%spin_index(1)=2
  elseif(spinmin.eq.1.and.spinmax.eq.2) then
    sig%nspin=2
    sig%spin_index(1)=1
    sig%spin_index(2)=2
  else
    write(errmsg,'(a,i2,a,i2,a,i2)') 'Illegal range of spin indices from ', spinmin, ' to ', spinmax
    call die(errmsg, only_root_writes = .true.)
  endif

!------------------------------
! Build the map sig%offmap
!         sig%off1(ii) = sig%diag(sig%offmap(ii,1))
!         sig%off2(ii) = sig%diag(sig%offmap(ii,2))
!         sig%off3(ii) = sig%diag(sig%offmap(ii,3))
! This is done only if sig%noffdiag .ne. 0

  if(sig%noffdiag.gt.0) then
    SAFE_ALLOCATE(sig%offmap, (sig%noffdiag,3))
    sig%offmap(1:sig%noffdiag, 1:3) = 0
    do ii=1,sig%noffdiag
      do jj=1,sig%ndiag
        if(sig%diag(jj) .eq. sig%off1(ii)) sig%offmap(ii, 1) = jj
        if(sig%diag(jj) .eq. sig%off2(ii)) sig%offmap(ii, 2) = jj
        if(sig%diag(jj) .eq. sig%off3(ii)) sig%offmap(ii, 3) = jj
      enddo
      
      if(sig%offmap(ii, 1) == 0) then
        write(errmsg,'(a,i6,a)') 'Off-diagonal matrix el. requested for band ', &
          sig%off1(ii),' but no corresponding diagonal matrix el. is requested'
        call die(errmsg, only_root_writes = .true.)
      endif
      
      if(sig%offmap(ii, 2) == 0) then
        write(errmsg,'(a,i6,a)') 'Off-diagonal matrix el. requested for band ', &
          sig%off2(ii),' but no corresponding diagonal matrix el. is requested'
        call die(errmsg, only_root_writes = .true.)
      endif
      
      if(sig%offmap(ii, 3) == 0) then
        write(errmsg,'(a,i6,a)') 'Off-diagonal matrix el. requested at energy of band ', &
          sig%off3(ii),' but no corresponding diagonal matrix el. is requested'
        call die(errmsg, only_root_writes = .true.)
      endif
    enddo
  endif ! sig%noffdiag.gt.0
  
  SAFE_ALLOCATE(sig%band_index, (sig%ntband))
  sig%nvband=0
  jj=0
  do ii=1,sig%ntband
    sig%nvband=sig%nvband+band_occ(ii)
    if(band_occ(ii).eq.1) then
      jj=jj+1
      sig%band_index(ii)=jj
    endif
  enddo
  do ii=1,sig%ntband
    if(band_occ(ii).eq.0) then
      jj=jj+1
      sig%band_index(ii)=jj
    endif
  enddo
  if((sig%nvband+sig%ncrit).eq.0) then
    call die("The band_occupation keyword could not be found or was placed before the number_bands keyword.", &
      only_root_writes = .true.)
  endif
  
  if(sig%fullConvLog.lt.0.or.sig%fullConvLog.gt.2) then
    call die('Invalid full_ch_conv_log', only_root_writes = .true.)
  endif

! gsm: What frequency dependence we are using?

  if(peinf%inode.eq.0) then
    if(sig%freq_dep.eq.-1) then
      write(6,699)
      write(7,699)
    elseif(sig%freq_dep.eq.0) then
      write(6,700)
      write(7,700)
    elseif(sig%freq_dep.eq.1) then
      write(6,701)
      write(7,701)
    elseif(sig%freq_dep.eq.2) then
      write(6,702)
      write(7,702)
    elseif(sig%freq_dep.eq.3) then
      write(6,703)
      write(7,703)
    else
      call die('Need to specify frequency dependence')
    endif
  endif
699 format(1x,'Using the Hartree-Fock approximation',/)
700 format(1x,'Using the static COHSEX approximation',/)
701 format(1x,'Using the Generalized Plasmon Pole model',/)
702 format(1x,'Using the full frequency-dependent inverse dielectric matrix',/)
703 format(1x,'Using the Generalized Plasmon Pole model (GN flavor)',/)

  if(peinf%inode == 0) then
    if(sig%iwriteint == 1) then ! comm_mpi
      if(peinf%npes > 1) then
        write(6,803)
        write(7,803)
      else
        write(6,805)
        write(7,805)
      endif
    else ! comm_disk
      write(6,804)
      write(7,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',/)

! gsm: Do we compute the exact static CH?

  if(sig%exact_ch.eq.-1) then ! set default according to freq_dep
    if(sig%freq_dep .eq. 0) then
      sig%exact_ch = 1
    else
      sig%exact_ch = 0
    endif
  endif
  if(sig%freq_dep.ne.-1) then ! HF has no CH sum so don`t write any comments about it
    if(sig%exact_ch.eq.0) then
      if(peinf%inode.eq.0) write(6,750)
      if(peinf%inode.eq.0) write(7,750)
    elseif(sig%exact_ch.eq.1.and.sig%freq_dep.eq.0) then
      if(peinf%inode.eq.0) write(6,751)
      if(peinf%inode.eq.0) write(7,751)
      if(sig%ntband .gt. max(maxval(sig%diag(1:sig%ndiag)), sig%nvband + sig%ncrit)) then
        ! this makes that we do not waste time and memory with the unoccupied bands which will not be used
        sig%ntband = max(maxval(sig%diag(1:sig%ndiag)), sig%nvband + sig%ncrit)
        if(peinf%inode.eq.0) &
          write(0,'(a)') "WARNING: Resetting number_bands to number of bands actually needed for exact static CH."
      endif
    elseif(sig%exact_ch.eq.1.and.(sig%freq_dep.eq.1.or.sig%freq_dep.eq.2&
& .or. sig%freq_dep.eq.3)) then
      if(peinf%inode.eq.0) write(6,752)
      if(peinf%inode.eq.0) write(7,752)
      if(peinf%inode.eq.0) write(0,753)
    else
      call die('Illegal value for exact_static_ch')
    endif
  endif
750 format(1x,'Computing CH as a partial sum over empty bands',/)
751 format(1x,'Computing the exact static CH',/)
752 format(1x,'Computing CH as a partial sum over empty bands with the static remainder',/)
753 format(1x,'WARNING: Static remainder is an experimental feature',/, &
      3x,'Only use if you know what you''re doing',/)
  
! gsm: Do we run half sum or full sum over G and G` vectors?

  if(peinf%inode.eq.0) then
    if(sig%ggpsum.eq.1) then
      write(6,771)
      write(7,771)
    elseif(sig%ggpsum.eq.2) then
      write(6,772)
      write(7,772)
    else
      call die('Need to set ggpsum to either 1 or 2')
    endif
  endif
771 format(1x,'Computing half sum over G and G'' vectors',/)
772 format(1x,'Computing full sum over G and G'' vectors',/)
  
! JRD: What screening is present?

  if(peinf%inode.eq.0) then
    if(sig%ncrit < 0) then
      call die("number_partial_occup < 0")
    endif

    if(sig%iscreen.eq.0) then
      if(sig%ncrit > 0) then
        write(0,'(a)') "WARNING: Semiconductor screening is inappropriate for number_partial_occup > 0."
        write(0,'(a)') "If a band really crosses the Fermi level, graphene or metal screening must be used."
        ! this only makes sense if ncrit was used to handle two spins, or
        ! to tune the number of conduction and valence bands for optimal parallelization.
      endif
      write(6,800)
      write(7,800)
    elseif(sig%iscreen.eq.1) then
      if(sig%ncrit == 0) then
        write(0,*) "WARNING: Graphene screening usually should have number_partial_occup > 0."
      endif
      write(6,801)
      write(7,801)
    elseif(sig%iscreen.eq.2) then
      if(sig%ncrit == 0) then
        write(0,*) "WARNING: Metal screening usually should have number_partial_occup > 0."
      endif
      write(6,802)
      write(7,802)
    else
      call die('Unknown 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',/)

! JRD: What truncation scheme are we using?

  if(peinf%inode.eq.0) then
    if(sig%icutv.eq.0) then
      write(6,900)
      write(7,900)
    elseif(sig%icutv.eq.2) then
      write(6,902)
      write(7,902)
      write(6,912)sig%truncval(1)
      write(7,912)sig%truncval(1)
    elseif(sig%icutv.eq.4) then
      write(6,904)
      write(7,904)
    elseif(sig%icutv.eq.5) then
      write(6,905)
      write(7,905)
    elseif(sig%icutv.eq.6) then
      write(6,906)
      write(7,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'/)

  if(peinf%inode.eq.0) then
    if(sig%ncrit.gt.0) then
      write(6,951)sig%ncrit
      write(7,951)sig%ncrit
951   format(1x,'We have partially occupied bands',/, &
        1x,'number_partial_occup (ncrit) =',i3,/)
    endif
  endif

  if(sig%use_xdat) then
    inquire(file='x.dat', exist=sig%use_xdat)
    if(sig%use_xdat .and. peinf%inode == 0) then
      write(6,899)
      write(7,899)
899   format(1x,"Reading bare exchange matrix elements from x.dat file."/)
    endif
  endif
  if(sig%use_vxcdat) then
    inquire(file='vxc.dat', exist=sig%use_vxcdat)
    if(sig%use_vxcdat .and. peinf%inode == 0) then
      write(6,898)
      write(7,898)
898   format(1x,"Reading exchange-correlation matrix elements from vxc.dat file",/)
    endif
  endif
  if(.not. sig%use_vxcdat) then
    inquire(file='VXC', exist=VXC_exists)
    if(.not. VXC_exists) call die("VXC file is missing.", only_root_writes = .true.)
    if(peinf%inode == 0) then
      write(6,897)
      write(7,897)
897   format(1x,"Computing exchange-correlation matrix elements from VXC file",/)
    endif
  endif
  ! This is for hybrid functional like calculation (one shot)
  if (sig%freq_dep.eq.-1 .and. ((1.0d0 - sig%coulomb_mod%long_range_frac_fock > TOL_SMALL) .or. &
    (1.0d0 - sig%coulomb_mod%short_range_frac_fock > TOL_SMALL)))  then

    sig%coul_mod_flag = .true.             
    if(sig%use_vxc2dat) then
      inquire(file='vxc2.dat', exist=sig%use_vxc2dat)
      if(sig%use_vxc2dat .and. peinf%inode == 0) then
        write(6,896)
        write(7,896)
896     format(1x,"Reading exchange-correlation matrix elements from vxc2.dat file",/)
      endif
    endif
    if(.not. sig%use_vxc2dat) then
      inquire(file='VXC2', exist=VXC_exists)
      if(.not. VXC_exists) call die("VXC2 file is missing.", only_root_writes = .true.)
      if(peinf%inode == 0) then
        write(6,895)
        write(7,895)
895     format(1x,"Computing exchange-correlation matrix elements from VXC2 file",/)
      endif
    endif
  endif
  
#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)

  ! FHJ: Broadcast spline scissors (this must be called after the barrier)
  ! FHJ: inner splines
  call MPI_BCAST(sig%spl_tck%n, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, mpierr)
  if ( sig%spl_tck%n > 0 ) then
    if(peinf%inode/=0) then
      SAFE_ALLOCATE(sig%spl_tck%t, (sig%spl_tck%n))
      SAFE_ALLOCATE(sig%spl_tck%c, (sig%spl_tck%n))
    endif
    call MPI_BCAST(sig%spl_tck%t, sig%spl_tck%n, MPI_REAL_DP, 0, MPI_COMM_WORLD, mpierr)
    call MPI_BCAST(sig%spl_tck%c, sig%spl_tck%n, MPI_REAL_DP, 0, MPI_COMM_WORLD, mpierr)
    call MPI_BCAST(sig%spl_tck%k, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, mpierr)
  endif
  ! FHJ: outer splines
  call MPI_BCAST(sig%spl_tck_outer%n, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, mpierr)
  if ( sig%spl_tck_outer%n > 0 ) then
    if(peinf%inode/=0) then
      SAFE_ALLOCATE(sig%spl_tck_outer%t, (sig%spl_tck_outer%n))
      SAFE_ALLOCATE(sig%spl_tck_outer%c, (sig%spl_tck_outer%n))
    endif
    call MPI_BCAST(sig%spl_tck_outer%t, sig%spl_tck_outer%n, MPI_REAL_DP, 0, MPI_COMM_WORLD, mpierr)
    call MPI_BCAST(sig%spl_tck_outer%c, sig%spl_tck_outer%n, MPI_REAL_DP, 0, MPI_COMM_WORLD, mpierr)
    call MPI_BCAST(sig%spl_tck_outer%k, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, mpierr)
  endif
#endif

  POP_SUB(inread)

  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.)
  
112 write(errmsg,'(3a)') 'Unexpected characters were found while reading elements of the ', &
      trim(blockword),' block.'
  call die(errmsg, only_root_writes = .true.)
  
end subroutine inread
