param_read Subroutine

public subroutine param_read()

Uses

  • proc~~param_read~~UsesGraph proc~param_read param_read module~w90_constants w90_constants proc~param_read->module~w90_constants module~w90_utility w90_utility proc~param_read->module~w90_utility module~w90_io w90_io proc~param_read->module~w90_io module~w90_utility->module~w90_constants module~w90_io->module~w90_constants

Read parameters and calculate derived values

Note on parallelization: this function should be called from the root node only!

elseif(nfermi==0) then
    ! This happens when both found_fermi_energy=.false. and
    ! fermi_energy_scan=.false. Functionalities that require
    ! specifying a Fermi level should give an error message
    allocate(fermi_energy_list(1),stat=ierr) ! helps streamline things

AAM_2017-03-27: if nfermi is zero (ie, fermi_energy* parameters are not set in input file) then allocate fermi_energy_list with length 1 and set to zero as default.

Arguments

None

Calls

proc~~param_read~~CallsGraph proc~param_read param_read proc~get_smearing_index get_smearing_index proc~param_read->proc~get_smearing_index proc~param_get_projections param_get_projections proc~param_read->proc~param_get_projections proc~param_uppercase param_uppercase proc~param_read->proc~param_uppercase proc~param_get_keyword_kpath param_get_keyword_kpath proc~param_read->proc~param_get_keyword_kpath proc~internal_set_kmesh internal_set_kmesh proc~param_read->proc~internal_set_kmesh proc~param_get_keyword_vector param_get_keyword_vector proc~param_read->proc~param_get_keyword_vector proc~param_in_file param_in_file proc~param_read->proc~param_in_file proc~param_get_range_vector param_get_range_vector proc~param_read->proc~param_get_range_vector proc~get_module_kmesh get_module_kmesh proc~param_read->proc~get_module_kmesh proc~utility_metric utility_metric proc~param_read->proc~utility_metric proc~param_get_keyword_block param_get_keyword_block proc~param_read->proc~param_get_keyword_block proc~param_get_atoms param_get_atoms proc~param_read->proc~param_get_atoms proc~param_get_centre_constraints param_get_centre_constraints proc~param_read->proc~param_get_centre_constraints proc~io_error io_error proc~param_read->proc~io_error proc~param_get_keyword param_get_keyword proc~param_read->proc~param_get_keyword proc~param_get_block_length param_get_block_length proc~param_read->proc~param_get_block_length proc~param_get_vector_length param_get_vector_length proc~param_read->proc~param_get_vector_length proc~io_file_unit io_file_unit proc~param_read->proc~io_file_unit proc~param_get_projections->proc~io_error proc~utility_strip utility_strip proc~param_get_projections->proc~utility_strip proc~utility_string_to_coord utility_string_to_coord proc~param_get_projections->proc~utility_string_to_coord proc~param_get_keyword_vector->proc~io_error proc~param_in_file->proc~io_file_unit proc~utility_lowercase utility_lowercase proc~param_in_file->proc~utility_lowercase proc~get_module_kmesh->proc~internal_set_kmesh proc~param_get_keyword_block->proc~io_error proc~param_get_atoms->proc~io_error proc~param_get_atoms->proc~param_get_block_length proc~param_get_centre_constraint_from_column param_get_centre_constraint_from_column proc~param_get_centre_constraints->proc~param_get_centre_constraint_from_column

Called by

proc~~param_read~~CalledByGraph proc~param_read param_read program~wannier wannier program~wannier->proc~param_read proc~wannier_run wannier_run proc~wannier_run->proc~param_read proc~wannier_setup wannier_setup proc~wannier_setup->proc~param_read program~postw90 postw90 program~postw90->proc~param_read

Contents

Source Code


Source Code

  subroutine param_read()
    !==================================================================!
    !                                                                  !
    !! Read parameters and calculate derived values
    !!
    !! Note on parallelization: this function should be called
    !! from the root node only!
    !!
    !                                                                  !
    !===================================================================
    use w90_constants, only: bohr, eps6, cmplx_i
    use w90_utility, only: utility_recip_lattice, utility_metric
    use w90_io, only: io_error, io_file_unit, seedname, post_proc_flag
    implicit none

    !local variables
    real(kind=dp)  :: real_lattice_tmp(3, 3)
    integer :: nkp, i, j, n, k, itmp, i_temp, i_temp2, eig_unit, loop, ierr, iv_temp(3), rows
    logical :: found, found2, lunits, chk_found
    character(len=6) :: spin_str
    real(kind=dp) :: cosa(3), rv_temp(3)
    integer, allocatable, dimension(:, :) :: nnkpts_block
    integer, allocatable, dimension(:) :: nnkpts_idx

    call param_in_file

    !%%%%%%%%%%%%%%%%
    ! Site symmetry
    !%%%%%%%%%%%%%%%%

    ! default value is lsitesymmetry=.false.
    call param_get_keyword('site_symmetry', found, l_value=lsitesymmetry)!YN:

    ! default value is symmetrize_eps=0.001
    call param_get_keyword('symmetrize_eps', found, r_value=symmetrize_eps)!YN:

    !%%%%%%%%%%%%%%%%
    ! Transport
    !%%%%%%%%%%%%%%%%

    transport = .false.
    call param_get_keyword('transport', found, l_value=transport)

    tran_read_ht = .false.
    call param_get_keyword('tran_read_ht', found, l_value=tran_read_ht)

    tran_easy_fix = .false.
    call param_get_keyword('tran_easy_fix', found, l_value=tran_easy_fix)

    if (transport .and. tran_read_ht) restart = ' '

    !%%%%%%%%%%%%%%%%
    !System variables
    !%%%%%%%%%%%%%%%%

    timing_level = 1             ! Verbosity of timing output info
    call param_get_keyword('timing_level', found, i_value=timing_level)

    iprint = 1             ! Verbosity
    call param_get_keyword('iprint', found, i_value=iprint)

    optimisation = 3             ! Verbosity
    call param_get_keyword('optimisation', found, i_value=optimisation)

    if (transport .and. tran_read_ht) goto 301

    !ivo
    call param_get_keyword('effective_model', found, l_value=effective_model)

    energy_unit = 'ev'          !
    call param_get_keyword('energy_unit', found, c_value=energy_unit)

    length_unit = 'ang'         !
    lenconfac = 1.0_dp
    call param_get_keyword('length_unit', found, c_value=length_unit)
    if (length_unit .ne. 'ang' .and. length_unit .ne. 'bohr') &
      call io_error('Error: value of length_unit not recognised in param_read')
    if (length_unit .eq. 'bohr') lenconfac = 1.0_dp/bohr

    wvfn_formatted = .false.       ! formatted or "binary" file
    call param_get_keyword('wvfn_formatted', found, l_value=wvfn_formatted)

    spn_formatted = .false.       ! formatted or "binary" file
    call param_get_keyword('spn_formatted', found, l_value=spn_formatted)

    uHu_formatted = .false.       ! formatted or "binary" file
    call param_get_keyword('uhu_formatted', found, l_value=uHu_formatted)

    spin = 1
    call param_get_keyword('spin', found, c_value=spin_str)
    if (found) then
      if (index(spin_str, 'up') > 0) then
        spin = 1
      elseif (index(spin_str, 'down') > 0) then
        spin = 2
      else
        call io_error('Error: unrecognised value of spin found: '//trim(spin_str))
      end if
    end if

    num_wann = -99
    call param_get_keyword('num_wann', found, i_value=num_wann)
    if (.not. found) call io_error('Error: You must specify num_wann')
    if (num_wann <= 0) call io_error('Error: num_wann must be greater than zero')

    num_exclude_bands = 0
    call param_get_range_vector('exclude_bands', found, num_exclude_bands, lcount=.true.)
    if (found) then
      if (num_exclude_bands < 1) call io_error('Error: problem reading exclude_bands')
      if (allocated(exclude_bands)) deallocate (exclude_bands)
      allocate (exclude_bands(num_exclude_bands), stat=ierr)
      if (ierr /= 0) call io_error('Error allocating exclude_bands in param_read')
      call param_get_range_vector('exclude_bands', found, num_exclude_bands, .false., exclude_bands)
      if (any(exclude_bands < 1)) &
        call io_error('Error: exclude_bands must contain positive numbers')
    end if

    ! AAM_2016-09-16: some changes to logic to patch a problem with uninitialised num_bands in library mode
!    num_bands       =   -1
    call param_get_keyword('num_bands', found, i_value=i_temp)
    if (found .and. library) write (stdout, '(/a)') ' Ignoring <num_bands> in input file'
    if (.not. library .and. .not. effective_model) then
      if (found) num_bands = i_temp
      if (.not. found) num_bands = num_wann
    end if
    ! GP: I subtract it here, but only the first time when I pass the total number of bands
    ! In later calls, I need to pass instead num_bands already subtracted.
    if (library .and. library_param_read_first_pass) num_bands = num_bands - num_exclude_bands
    if (.not. effective_model) then
      if (found .and. num_bands < num_wann) then
        write (stdout, *) 'num_bands', num_bands
        write (stdout, *) 'num_wann', num_wann
        call io_error('Error: num_bands must be greater than or equal to num_wann')
      endif
    endif

    num_dump_cycles = 100          ! frequency to write backups at
    call param_get_keyword('num_dump_cycles', found, i_value=num_dump_cycles)
    if (num_dump_cycles < 0) call io_error('Error: num_dump_cycles must be positive')

    num_print_cycles = 1          ! frequency to write at
    call param_get_keyword('num_print_cycles', found, i_value=num_print_cycles)
    if (num_print_cycles < 0) call io_error('Error: num_print_cycles must be positive')

    devel_flag = ' '          !
    call param_get_keyword('devel_flag', found, c_value=devel_flag)

!    mp_grid=-99
    call param_get_keyword_vector('mp_grid', found, 3, i_value=iv_temp)
    if (found .and. library) write (stdout, '(a)') ' Ignoring <mp_grid> in input file'
    if (.not. library .and. .not. effective_model) then
      if (found) mp_grid = iv_temp
      if (.not. found) then
        call io_error('Error: You must specify dimensions of the Monkhorst-Pack grid by setting mp_grid')
      elseif (any(mp_grid < 1)) then
        call io_error('Error: mp_grid must be greater than zero')
      end if
      num_kpts = mp_grid(1)*mp_grid(2)*mp_grid(3)
    end if

![ysl-b]
    ltmp = .false.
    call param_get_keyword('gamma_only', found, l_value=ltmp)
    if (.not. library) then
      gamma_only = ltmp
      if (gamma_only .and. (num_kpts .ne. 1)) &
        call io_error('Error: gamma_only is true, but num_kpts > 1')
    else
      if (found) write (stdout, '(a)') ' Ignoring <gamma_only> in input file'
    endif
![ysl-e]

!    aam: automatic_mp_grid no longer used
!    automatic_mp_grid = .false.
!    call param_get_keyword('automatic_mp_grid',found,l_value=automatic_mp_grid)

    postproc_setup = .false.            ! set to true to write .nnkp file and exit
    call param_get_keyword('postproc_setup', found, l_value=postproc_setup)
    ! We allow this keyword to be overriden by a command line arg -pp
    if (post_proc_flag) postproc_setup = .true.

    cp_pp = .false.                  ! set to true if doing CP post-processing
    call param_get_keyword('cp_pp', found, l_value=cp_pp)

    calc_only_A = .false.
    call param_get_keyword('calc_only_A', found, l_value=calc_only_A)

    restart = ' '
    call param_get_keyword('restart', found, c_value=restart)
    if (found) then
      if ((restart .ne. 'default') .and. (restart .ne. 'wannierise') &
          .and. (restart .ne. 'plot') .and. (restart .ne. 'transport')) then
        call io_error('Error in input file: value of restart not recognised')
      else
        inquire (file=trim(seedname)//'.chk', exist=chk_found)
        if (.not. chk_found) &
          call io_error('Error: restart requested but '//trim(seedname)//'.chk file not found')
      endif
    endif
    !post processing takes priority (user is not warned of this)
    if (postproc_setup) restart = ' '

    write_r2mn = .false.
    call param_get_keyword('write_r2mn', found, l_value=write_r2mn)

    write_proj = .false.
    call param_get_keyword('write_proj', found, l_value=write_proj)

    ltmp = .false.  ! by default our WF are not spinors
    call param_get_keyword('spinors', found, l_value=ltmp)
    if (.not. library) then
      spinors = ltmp
    else
      if (found) write (stdout, '(a)') ' Ignoring <spinors> in input file'
    endif
!    if(spinors .and. (2*(num_wann/2))/=num_wann) &
!       call io_error('Error: For spinor WF num_wann must be even')

    ! We need to know if the bands are double degenerate due to spin, e.g. when
    ! calculating the DOS
    if (spinors) then
      num_elec_per_state = 1
    else
      num_elec_per_state = 2
    endif
    call param_get_keyword('num_elec_per_state', found, i_value=num_elec_per_state)
    if ((num_elec_per_state /= 1) .and. (num_elec_per_state /= 2)) &
      call io_error('Error: num_elec_per_state can be only 1 or 2')
    if (spinors .and. num_elec_per_state /= 1) &
      call io_error('Error: when spinors = T num_elec_per_state must be 1')

    translate_home_cell = .false.
    call param_get_keyword('translate_home_cell', found, l_value=translate_home_cell)

    write_xyz = .false.
    call param_get_keyword('write_xyz', found, l_value=write_xyz)

    write_hr_diag = .false.
    call param_get_keyword('write_hr_diag', found, l_value=write_hr_diag)

    !%%%%%%%%%%%
    ! Wannierise
    !%%%%%%%%%%%

    num_iter = 100
    call param_get_keyword('num_iter', found, i_value=num_iter)
    if (num_iter < 0) call io_error('Error: num_iter must be positive')

    num_cg_steps = 5
    call param_get_keyword('num_cg_steps', found, i_value=num_cg_steps)
    if (num_cg_steps < 0) call io_error('Error: num_cg_steps must be positive')

    conv_tol = 1.0e-10_dp
    call param_get_keyword('conv_tol', found, r_value=conv_tol)
    if (conv_tol < 0.0_dp) call io_error('Error: conv_tol must be positive')

    conv_noise_amp = -1.0_dp
    call param_get_keyword('conv_noise_amp', found, r_value=conv_noise_amp)

    conv_window = -1
    if (conv_noise_amp > 0.0_dp) conv_window = 5
    call param_get_keyword('conv_window', found, i_value=conv_window)

    conv_noise_num = 3
    call param_get_keyword('conv_noise_num', found, i_value=conv_noise_num)
    if (conv_noise_num < 0) call io_error('Error: conv_noise_num must be positive')

    guiding_centres = .false.
    call param_get_keyword('guiding_centres', found, l_value=guiding_centres)

    num_guide_cycles = 1
    call param_get_keyword('num_guide_cycles', found, i_value=num_guide_cycles)
    if (num_guide_cycles < 0) call io_error('Error: num_guide_cycles must be >= 0')

    num_no_guide_iter = 0
    call param_get_keyword('num_no_guide_iter', found, i_value=num_no_guide_iter)
    if (num_no_guide_iter < 0) call io_error('Error: num_no_guide_iter must be >= 0')

    fixed_step = -999.0_dp; lfixstep = .false.
    call param_get_keyword('fixed_step', found, r_value=fixed_step)
    if (found .and. (fixed_step < 0.0_dp)) call io_error('Error: fixed_step must be > 0')
    if (fixed_step > 0.0_dp) lfixstep = .true.

    trial_step = 2.0_dp
    call param_get_keyword('trial_step', found, r_value=trial_step)
    if (found .and. lfixstep) call io_error('Error: cannot specify both fixed_step and trial_step')

    precond = .false.
    call param_get_keyword('precond', found, l_value=precond)

    slwf_num = num_wann
    selective_loc = .false.
    call param_get_keyword('slwf_num', found, i_value=slwf_num)
    if (found) then
      if (slwf_num .gt. num_wann .or. slwf_num .lt. 1) then
        call io_error('Error: slwf_num must be an integer between 1 and num_wann')
      end if
      if (slwf_num .lt. num_wann) selective_loc = .true.
    end if

    slwf_constrain = .false.
    call param_get_keyword('slwf_constrain', found, l_value=slwf_constrain)
    if (found .and. slwf_constrain) then
      if (selective_loc) then
        allocate (ccentres_frac(num_wann, 3), stat=ierr)
        if (ierr /= 0) call io_error('Error allocating ccentres_frac in param_get_centre_constraints')
        allocate (ccentres_cart(num_wann, 3), stat=ierr)
        if (ierr /= 0) call io_error('Error allocating ccentres_cart in param_get_centre_constraints')
      else
        write (stdout, *) ' No selective localisation requested. Ignoring constraints on centres'
        slwf_constrain = .false.
      end if
    end if

    slwf_lambda = 1.0_dp
    call param_get_keyword('slwf_lambda', found, r_value=slwf_lambda)
    if (found) then
      if (slwf_lambda < 0.0_dp) call io_error('Error: slwf_lambda  must be positive.')
    endif

    !%%%%%%%%%
    ! Plotting
    !%%%%%%%%%

    wannier_plot = .false.
    call param_get_keyword('wannier_plot', found, l_value=wannier_plot)

    wannier_plot_supercell = 2

    call param_get_vector_length('wannier_plot_supercell', found, length=i)
    if (found) then
      if (i .eq. 1) then
        call param_get_keyword_vector('wannier_plot_supercell', found, 1, &
                                      i_value=wannier_plot_supercell)
        wannier_plot_supercell(2) = wannier_plot_supercell(1)
        wannier_plot_supercell(3) = wannier_plot_supercell(1)
      elseif (i .eq. 3) then
        call param_get_keyword_vector('wannier_plot_supercell', found, 3, &
                                      i_value=wannier_plot_supercell)
      else
        call io_error('Error: wannier_plot_supercell must be provided as either one integer or a vector of three integers')
      end if
      if (any(wannier_plot_supercell <= 0)) &
        call io_error('Error: wannier_plot_supercell elements must be greater than zero')
    end if

    wannier_plot_format = 'xcrysden'
    call param_get_keyword('wannier_plot_format', found, c_value=wannier_plot_format)

    wannier_plot_mode = 'crystal'
    call param_get_keyword('wannier_plot_mode', found, c_value=wannier_plot_mode)

    wannier_plot_spinor_mode = 'total'
    call param_get_keyword('wannier_plot_spinor_mode', found, c_value=wannier_plot_spinor_mode)
    wannier_plot_spinor_phase = .true.
    call param_get_keyword('wannier_plot_spinor_phase', found, l_value=wannier_plot_spinor_phase)

    call param_get_range_vector('wannier_plot_list', found, num_wannier_plot, lcount=.true.)
    if (found) then
      if (num_wannier_plot < 1) call io_error('Error: problem reading wannier_plot_list')
      if (allocated(wannier_plot_list)) deallocate (wannier_plot_list)
      allocate (wannier_plot_list(num_wannier_plot), stat=ierr)
      if (ierr /= 0) call io_error('Error allocating wannier_plot_list in param_read')
      call param_get_range_vector('wannier_plot_list', found, num_wannier_plot, .false., wannier_plot_list)
      if (any(wannier_plot_list < 1) .or. any(wannier_plot_list > num_wann)) &
        call io_error('Error: wannier_plot_list asks for a non-valid wannier function to be plotted')
    else
      ! we plot all wannier functions
      num_wannier_plot = num_wann
      if (allocated(wannier_plot_list)) deallocate (wannier_plot_list)
      allocate (wannier_plot_list(num_wannier_plot), stat=ierr)
      if (ierr /= 0) call io_error('Error allocating wannier_plot_list in param_read')
      do loop = 1, num_wann
        wannier_plot_list(loop) = loop
      end do
    end if

    wannier_plot_radius = 3.5_dp
    call param_get_keyword('wannier_plot_radius', found, r_value=wannier_plot_radius)

    wannier_plot_scale = 1.0_dp
    call param_get_keyword('wannier_plot_scale', found, r_value=wannier_plot_scale)

    ! checks
    if (wannier_plot) then
      if ((index(wannier_plot_format, 'xcrys') .eq. 0) .and. (index(wannier_plot_format, 'cub') .eq. 0)) &
        call io_error('Error: wannier_plot_format not recognised')
      if ((index(wannier_plot_mode, 'crys') .eq. 0) .and. (index(wannier_plot_mode, 'mol') .eq. 0)) &
        call io_error('Error: wannier_plot_mode not recognised')
      if ((index(wannier_plot_spinor_mode, 'total') .eq. 0) .and. (index(wannier_plot_spinor_mode, 'up') .eq. 0) &
          .and. (index(wannier_plot_spinor_mode, 'down') .eq. 0)) &
        call io_error('Error: wannier_plot_spinor_mode not recognised')
      if (wannier_plot_radius < 0.0_dp) call io_error('Error: wannier_plot_radius must be positive')
      if (wannier_plot_scale < 0.0_dp) call io_error('Error: wannier_plot_scale must be positive')
    endif

    write_u_matrices = .false.
    call param_get_keyword('write_u_matrices', found, l_value=write_u_matrices)

    bands_plot = .false.
    call param_get_keyword('bands_plot', found, l_value=bands_plot)

    write_bvec = .false.
    call param_get_keyword('write_bvec', found, l_value=write_bvec)

    bands_num_points = 100
    call param_get_keyword('bands_num_points', found, i_value=bands_num_points)

    bands_plot_format = 'gnuplot'
    call param_get_keyword('bands_plot_format', found, c_value=bands_plot_format)

    bands_plot_mode = 's-k'
    call param_get_keyword('bands_plot_mode', found, c_value=bands_plot_mode)

    bands_plot_dim = 3
    call param_get_keyword('bands_plot_dim', found, i_value=bands_plot_dim)

    num_bands_project = 0
    call param_get_range_vector('bands_plot_project', found, num_bands_project, lcount=.true.)
    if (found) then
      if (num_bands_project < 1) call io_error('Error: problem reading bands_plot_project')
      if (allocated(bands_plot_project)) deallocate (bands_plot_project)
      allocate (bands_plot_project(num_bands_project), stat=ierr)
      if (ierr /= 0) call io_error('Error allocating bands_plot_project in param_read')
      call param_get_range_vector('bands_plot_project', found, num_bands_project, .false., bands_plot_project)
      if (any(bands_plot_project < 1) .or. any(bands_plot_project > num_wann)) &
        call io_error('Error: bands_plot_project asks for a non-valid wannier function to be projected')
    endif

    bands_num_spec_points = 0
    call param_get_block_length('kpoint_path', found, i_temp)
    if (found) then
      bands_num_spec_points = i_temp*2
      if (allocated(bands_label)) deallocate (bands_label)
      allocate (bands_label(bands_num_spec_points), stat=ierr)
      if (ierr /= 0) call io_error('Error allocating bands_label in param_read')
      if (allocated(bands_spec_points)) deallocate (bands_spec_points)
      allocate (bands_spec_points(3, bands_num_spec_points), stat=ierr)
      if (ierr /= 0) call io_error('Error allocating bands_spec_points in param_read')
      call param_get_keyword_kpath
    end if
    if (.not. found .and. bands_plot) &
      call io_error('A bandstructure plot has been requested but there is no kpoint_path block')

    ! checks
    if (bands_plot) then
      if ((index(bands_plot_format, 'gnu') .eq. 0) .and. (index(bands_plot_format, 'xmgr') .eq. 0)) &
        call io_error('Error: bands_plot_format not recognised')
      if ((index(bands_plot_mode, 's-k') .eq. 0) .and. (index(bands_plot_mode, 'cut') .eq. 0)) &
        call io_error('Error: bands_plot_mode not recognised')
      if (bands_num_points < 0) call io_error('Error: bands_num_points must be positive')
    endif

    fermi_surface_plot = .false.
    call param_get_keyword('fermi_surface_plot', found, l_value=fermi_surface_plot)

    fermi_surface_num_points = 50
    call param_get_keyword('fermi_surface_num_points', found, i_value=fermi_surface_num_points)

    fermi_surface_plot_format = 'xcrysden'
    call param_get_keyword('fermi_surface_plot_format', &
                           found, c_value=fermi_surface_plot_format)

    nfermi = 0
    found_fermi_energy = .false.
    call param_get_keyword('fermi_energy', found, r_value=fermi_energy)
    if (found) then
      found_fermi_energy = .true.
      nfermi = 1
    endif
    !
    fermi_energy_scan = .false.
    call param_get_keyword('fermi_energy_min', found, r_value=fermi_energy_min)
    if (found) then
      if (found_fermi_energy) call io_error( &
        'Error: Cannot specify both fermi_energy and fermi_energy_min')
      fermi_energy_scan = .true.
      fermi_energy_max = fermi_energy_min + 1.0_dp
      call param_get_keyword('fermi_energy_max', found, &
                             r_value=fermi_energy_max)
      if (found .and. fermi_energy_max <= fermi_energy_min) call io_error( &
        'Error: fermi_energy_max must be larger than fermi_energy_min')
      fermi_energy_step = 0.01_dp
      call param_get_keyword('fermi_energy_step', found, &
                             r_value=fermi_energy_step)
      if (found .and. fermi_energy_step <= 0.0_dp) call io_error( &
        'Error: fermi_energy_step must be positive')
      nfermi = nint(abs((fermi_energy_max - fermi_energy_min)/fermi_energy_step)) + 1
    endif
    !
    if (found_fermi_energy) then
      if (allocated(fermi_energy_list)) deallocate (fermi_energy_list)
      allocate (fermi_energy_list(1), stat=ierr)
      fermi_energy_list(1) = fermi_energy
    elseif (fermi_energy_scan) then
      if (nfermi .eq. 1) then
        fermi_energy_step = 0.0_dp
      else
        fermi_energy_step = (fermi_energy_max - fermi_energy_min)/real(nfermi - 1, dp)
      endif
      if (allocated(fermi_energy_list)) deallocate (fermi_energy_list)
      allocate (fermi_energy_list(nfermi), stat=ierr)
      do i = 1, nfermi
        fermi_energy_list(i) = fermi_energy_min + (i - 1)*fermi_energy_step
      enddo
!!    elseif(nfermi==0) then
!!        ! This happens when both found_fermi_energy=.false. and
!!        ! fermi_energy_scan=.false. Functionalities that require
!!        ! specifying a Fermi level should give an error message
!!        allocate(fermi_energy_list(1),stat=ierr) ! helps streamline things
!!
!! AAM_2017-03-27: if nfermi is zero (ie, fermi_energy* parameters are not set in input file)
!! then allocate fermi_energy_list with length 1 and set to zero as default.
    else
      if (allocated(fermi_energy_list)) deallocate (fermi_energy_list)
      allocate (fermi_energy_list(1), stat=ierr)
      fermi_energy_list(1) = 0.0_dp
    endif
    if (ierr /= 0) call io_error( &
      'Error allocating fermi_energy_list in param_read')

    ! checks
    if (fermi_surface_plot) then
      if ((index(fermi_surface_plot_format, 'xcrys') .eq. 0)) &
        call io_error('Error: fermi_surface_plot_format not recognised')
      if (fermi_surface_num_points < 0) &
        call io_error('Error: fermi_surface_num_points must be positive')
    endif

    kslice = .false.
    call param_get_keyword('kslice', found, l_value=kslice)

    kslice_task = 'fermi_lines'
    call param_get_keyword('kslice_task', found, c_value=kslice_task)
    if (kslice .and. index(kslice_task, 'fermi_lines') == 0 .and. &
        index(kslice_task, 'curv') == 0 .and. &
        index(kslice_task, 'morb') == 0 .and. &
        index(kslice_task, 'shc') == 0) call io_error &
      ('Error: value of kslice_task not recognised in param_read')
    if (kslice .and. index(kslice_task, 'curv') > 0 .and. &
        index(kslice_task, 'morb') > 0) call io_error &
      ("Error: kslice_task cannot include both 'curv' and 'morb'")
    if (kslice .and. index(kslice_task, 'shc') > 0 .and. &
        index(kslice_task, 'morb') > 0) call io_error &
      ("Error: kslice_task cannot include both 'shc' and 'morb'")
    if (kslice .and. index(kslice_task, 'shc') > 0 .and. &
        index(kslice_task, 'curv') > 0) call io_error &
      ("Error: kslice_task cannot include both 'shc' and 'curv'")

    kslice_2dkmesh(1:2) = 50
    call param_get_vector_length('kslice_2dkmesh', found, length=i)
    if (found) then
      if (i == 1) then
        call param_get_keyword_vector('kslice_2dkmesh', found, 1, &
                                      i_value=kslice_2dkmesh)
        kslice_2dkmesh(2) = kslice_2dkmesh(1)
      elseif (i == 2) then
        call param_get_keyword_vector('kslice_2dkmesh', found, 2, &
                                      i_value=kslice_2dkmesh)
      else
        call io_error('Error: kslice_2dkmesh must be provided as either' &
                      //' one integer or a vector of two integers')
      endif
      if (any(kslice_2dkmesh <= 0)) &
        call io_error('Error: kslice_2dkmesh elements must be' &
                      //' greater than zero')
    endif

    kslice_corner = 0.0_dp
    call param_get_keyword_vector('kslice_corner', found, 3, r_value=kslice_corner)

    kslice_b1(1) = 1.0_dp
    kslice_b1(2) = 0.0_dp
    kslice_b1(3) = 0.0_dp
    call param_get_keyword_vector('kslice_b1', found, 3, r_value=kslice_b1)

    kslice_b2(1) = 0.0_dp
    kslice_b2(2) = 1.0_dp
    kslice_b2(3) = 0.0_dp
    call param_get_keyword_vector('kslice_b2', found, 3, r_value=kslice_b2)

    kslice_fermi_lines_colour = 'none'
    call param_get_keyword('kslice_fermi_lines_colour', found, &
                           c_value=kslice_fermi_lines_colour)
    if (kslice .and. index(kslice_fermi_lines_colour, 'none') == 0 .and. &
        index(kslice_fermi_lines_colour, 'spin') == 0) call io_error &
      ('Error: value of kslice_fermi_lines_colour not recognised ' &
       //'in param_read')

!    slice_plot_format         = 'plotmv'
!    call param_get_keyword('slice_plot_format',found,c_value=slice_plot_format)

    ! [gp-begin, Apr 20, 2012]

    ! By default: Gaussian
    smr_index = 0
    call param_get_keyword('smr_type', found, c_value=ctmp)
    if (found) smr_index = get_smearing_index(ctmp, 'smr_type')

    ! By default: adaptive smearing
    adpt_smr = .true.
    call param_get_keyword('adpt_smr', found, l_value=adpt_smr)

    ! By default: a=sqrt(2)
    adpt_smr_fac = sqrt(2.0_dp)
    call param_get_keyword('adpt_smr_fac', found, r_value=adpt_smr_fac)
    if (found .and. (adpt_smr_fac <= 0._dp)) &
      call io_error('Error: adpt_smr_fac must be greater than zero')

    ! By default: 1 eV
    adpt_smr_max = 1.0_dp
    call param_get_keyword('adpt_smr_max', found, r_value=adpt_smr_max)
    if (adpt_smr_max <= 0._dp) &
      call io_error('Error: adpt_smr_max must be greater than zero')

    ! By default: if adpt_smr is manually set to false by the user, but he/she doesn't
    ! define smr_fixed_en_width: NO smearing, i.e. just the histogram
    smr_fixed_en_width = 0.0_dp
    call param_get_keyword('smr_fixed_en_width', found, r_value=smr_fixed_en_width)
    if (found .and. (smr_fixed_en_width < 0._dp)) &
      call io_error('Error: smr_fixed_en_width must be greater than or equal to zero')
    ! [gp-end]

    !IVO

    dos = .false.
    call param_get_keyword('dos', found, l_value=dos)

    berry = .false.
    call param_get_keyword('berry', found, l_value=berry)

    transl_inv = .false.
    call param_get_keyword('transl_inv', found, l_value=transl_inv)

    berry_task = ' '
    call param_get_keyword('berry_task', found, c_value=berry_task)
    if (berry .and. .not. found) call io_error &
      ('Error: berry=T and berry_task is not set')
    if (berry .and. index(berry_task, 'ahc') == 0 .and. index(berry_task, 'morb') == 0 &
        .and. index(berry_task, 'kubo') == 0 .and. index(berry_task, 'sc') == 0 &
        .and. index(berry_task, 'shc') == 0) call io_error &
      ('Error: value of berry_task not recognised in param_read')

    ! Stepan
    gyrotropic = .false.
    call param_get_keyword('gyrotropic', found, l_value=gyrotropic)
    gyrotropic_task = 'all'
    call param_get_keyword('gyrotropic_task', found, c_value=gyrotropic_task)
    gyrotropic_box(:, :) = 0.0
    gyrotropic_degen_thresh = 0.0_dp
    call param_get_keyword('gyrotropic_degen_thresh', found, r_value=gyrotropic_degen_thresh)

    do i = 1, 3
      gyrotropic_box(i, i) = 1.0_dp
      gyrotropic_box_tmp(:) = 0.0_dp
      call param_get_keyword_vector('gyrotropic_box_b'//achar(48 + i), found, 3, r_value=gyrotropic_box_tmp)
      if (found) gyrotropic_box(i, :) = gyrotropic_box_tmp(:)
    enddo
    gyrotropic_box_corner(:) = 0.0_dp
    call param_get_keyword_vector('gyrotropic_box_center', found, 3, r_value=gyrotropic_box_tmp)
    if (found) gyrotropic_box_corner(:) = &
      gyrotropic_box_tmp(:) - 0.5*(gyrotropic_box(1, :) + gyrotropic_box(2, :) + gyrotropic_box(3, :))

    call param_get_range_vector('gyrotropic_band_list', found, gyrotropic_num_bands, lcount=.true.)
    if (found) then
      if (gyrotropic_num_bands < 1) call io_error('Error: problem reading gyrotropic_band_list')
      if (allocated(gyrotropic_band_list)) deallocate (gyrotropic_band_list)
      allocate (gyrotropic_band_list(gyrotropic_num_bands), stat=ierr)
      if (ierr /= 0) call io_error('Error allocating gyrotropic_band_list in param_read')
      call param_get_range_vector('gyrotropic_band_list', found, gyrotropic_num_bands, .false., gyrotropic_band_list)
      if (any(gyrotropic_band_list < 1) .or. any(gyrotropic_band_list > num_wann)) &
        call io_error('Error: gyrotropic_band_list asks for a non-valid bands')
    else
      ! include all bands in the calculation
      gyrotropic_num_bands = num_wann
      if (allocated(gyrotropic_band_list)) deallocate (gyrotropic_band_list)
      allocate (gyrotropic_band_list(gyrotropic_num_bands), stat=ierr)
      if (ierr /= 0) call io_error('Error allocating gyrotropic_band_list in param_read')
      do loop = 1, num_wann
        gyrotropic_band_list(loop) = loop
      end do
    end if

    smr_max_arg = 5.0
    call param_get_keyword('smr_max_arg', found, r_value=smr_max_arg)
    if (found .and. (smr_max_arg <= 0._dp)) &
      call io_error('Error: smr_max_arg must be greater than zero')

    gyrotropic_smr_max_arg = smr_max_arg
    call param_get_keyword('gyrotropic_smr_max_arg', found, &
                           r_value=gyrotropic_smr_max_arg)
    if (found .and. (gyrotropic_smr_max_arg <= 0._dp)) call io_error &
      ('Error: gyrotropic_smr_max_arg must be greater than zero')

!-------------------------------------------------------
!    alpha=0
!    call param_get_keyword('alpha',found,i_value=alpha)

!    beta=0
!    call param_get_keyword('beta',found,i_value=beta)

!    gamma=0
!    call param_get_keyword('gamma',found,i_value=gamma)
!-------------------------------------------------------

    berry_curv_adpt_kmesh = 1
    call param_get_keyword('berry_curv_adpt_kmesh', found, &
                           i_value=berry_curv_adpt_kmesh)
    if (berry_curv_adpt_kmesh < 1) &
      call io_error( &
      'Error:  berry_curv_adpt_kmesh must be a positive integer')

    berry_curv_adpt_kmesh_thresh = 100.0_dp
    call param_get_keyword('berry_curv_adpt_kmesh_thresh', found, &
                           r_value=berry_curv_adpt_kmesh_thresh)

    berry_curv_unit = 'ang2'
    call param_get_keyword('berry_curv_unit', found, c_value=berry_curv_unit)
    if (berry_curv_unit .ne. 'ang2' .and. berry_curv_unit .ne. 'bohr2') &
      call io_error &
      ('Error: value of berry_curv_unit not recognised in param_read')

    wanint_kpoint_file = .false.
    call param_get_keyword('wanint_kpoint_file', found, &
                           l_value=wanint_kpoint_file)

!    smear_temp = -1.0_dp
!    call param_get_keyword('smear_temp',found,r_value=smear_temp)

    kubo_adpt_smr = adpt_smr
    call param_get_keyword('kubo_adpt_smr', found, l_value=kubo_adpt_smr)

    kubo_adpt_smr_fac = adpt_smr_fac
    call param_get_keyword('kubo_adpt_smr_fac', found, &
                           r_value=kubo_adpt_smr_fac)
    if (found .and. (kubo_adpt_smr_fac <= 0._dp)) call io_error &
      ('Error: kubo_adpt_smr_fac must be greater than zero')

    kubo_adpt_smr_max = adpt_smr_max
    call param_get_keyword('kubo_adpt_smr_max', found, &
                           r_value=kubo_adpt_smr_max)
    if (kubo_adpt_smr_max <= 0._dp) call io_error &
      ('Error: kubo_adpt_smr_max must be greater than zero')

    kubo_smr_fixed_en_width = smr_fixed_en_width
    call param_get_keyword('kubo_smr_fixed_en_width', found, &
                           r_value=kubo_smr_fixed_en_width)
    if (found .and. (kubo_smr_fixed_en_width < 0._dp)) call io_error &
      ('Error: kubo_smr_fixed_en_width must be greater than or equal to zero')

    gyrotropic_smr_fixed_en_width = smr_fixed_en_width
    call param_get_keyword('gyrotropic_smr_fixed_en_width', found, &
                           r_value=gyrotropic_smr_fixed_en_width)
    if (found .and. (gyrotropic_smr_fixed_en_width < 0._dp)) call io_error &
      ('Error: gyrotropic_smr_fixed_en_width must be greater than or equal to zero')

    sc_phase_conv = 1
    call param_get_keyword('sc_phase_conv', found, i_value=sc_phase_conv)
    if ((sc_phase_conv .ne. 1) .and. ((sc_phase_conv .ne. 2))) call io_error('Error: sc_phase_conv must be either 1 or 2')

    scissors_shift = 0.0_dp
    call param_get_keyword('scissors_shift', found, &
                           r_value=scissors_shift)

    shc_freq_scan = .false.
    call param_get_keyword('shc_freq_scan', found, l_value=shc_freq_scan)

    shc_alpha = 1
    call param_get_keyword('shc_alpha', found, i_value=shc_alpha)
    if (found .and. (shc_alpha < 1 .or. shc_alpha > 3)) call io_error &
      ('Error:  shc_alpha must be 1, 2 or 3')

    shc_beta = 2
    call param_get_keyword('shc_beta', found, i_value=shc_beta)
    if (found .and. (shc_beta < 1 .or. shc_beta > 3)) call io_error &
      ('Error:  shc_beta must be 1, 2 or 3')

    shc_gamma = 3
    call param_get_keyword('shc_gamma', found, i_value=shc_gamma)
    if (found .and. (shc_gamma < 1 .or. shc_gamma > 3)) call io_error &
      ('Error:  shc_gamma must be 1, 2 or 3')

    shc_bandshift = .false.
    call param_get_keyword('shc_bandshift', found, l_value=shc_bandshift)
    shc_bandshift = shc_bandshift .and. berry .and. .not. (index(berry_task, 'shc') == 0)
    if ((abs(scissors_shift) > 1.0e-7_dp) .and. shc_bandshift) &
      call io_error('Error: shc_bandshift and scissors_shift cannot be used simultaneously')

    shc_bandshift_firstband = 0
    call param_get_keyword('shc_bandshift_firstband', found, i_value=shc_bandshift_firstband)
    if (shc_bandshift .and. (.not. found)) &
      call io_error('Error: shc_bandshift required but no shc_bandshift_firstband provided')
    if ((shc_bandshift_firstband < 1) .and. found) &
      call io_error('Error: shc_bandshift_firstband must >= 1')

    shc_bandshift_energyshift = 0._dp
    call param_get_keyword('shc_bandshift_energyshift', found, r_value=shc_bandshift_energyshift)
    if (shc_bandshift .and. (.not. found)) &
      call io_error('Error: shc_bandshift required but no shc_bandshift_energyshift provided')

    spin_moment = .false.
    call param_get_keyword('spin_moment', found, &
                           l_value=spin_moment)

    spin_axis_polar = 0.0_dp
    call param_get_keyword('spin_axis_polar', found, &
                           r_value=spin_axis_polar)

    spin_axis_azimuth = 0.0_dp
    call param_get_keyword('spin_axis_azimuth', found, &
                           r_value=spin_axis_azimuth)

    spin_decomp = .false.
    call param_get_keyword('spin_decomp', found, l_value=spin_decomp)

    if (spin_decomp .and. (num_elec_per_state .ne. 1)) then
      call io_error('spin_decomp can be true only if num_elec_per_state is 1')
    end if

    use_degen_pert = .false.
    call param_get_keyword('use_degen_pert', found, &
                           l_value=use_degen_pert)

    degen_thr = 1.0d-4
    call param_get_keyword('degen_thr', found, r_value=degen_thr)

    kpath = .false.
    call param_get_keyword('kpath', found, l_value=kpath)

    kpath_task = 'bands'
    call param_get_keyword('kpath_task', found, c_value=kpath_task)
    if (kpath .and. index(kpath_task, 'bands') == 0 .and. &
        index(kpath_task, 'curv') == 0 .and. &
        index(kpath_task, 'morb') == 0 .and. &
        index(kpath_task, 'shc') == 0) call io_error &
      ('Error: value of kpath_task not recognised in param_read')
    if (bands_num_spec_points == 0 .and. kpath) &
      call io_error('Error: a kpath plot has been requested but there is no kpoint_path block')

    kpath_num_points = 100
    call param_get_keyword('kpath_num_points', found, &
                           i_value=kpath_num_points)
    if (kpath_num_points < 0) &
      call io_error('Error: kpath_num_points must be positive')

    kpath_bands_colour = 'none'
    call param_get_keyword('kpath_bands_colour', found, &
                           c_value=kpath_bands_colour)
    if (kpath .and. index(kpath_bands_colour, 'none') == 0 .and. &
        index(kpath_bands_colour, 'spin') == 0 .and. &
        index(kpath_bands_colour, 'shc') == 0) call io_error &
      ('Error: value of kpath_bands_colour not recognised in param_read')
    if (kpath .and. index(kpath_task, 'shc') > 0 .and. &
        index(kpath_task, 'spin') > 0) call io_error &
      ("Error: kpath_task cannot include both 'shc' and 'spin'")

    ! set to a negative default value
    num_valence_bands = -99
    call param_get_keyword('num_valence_bands', found, i_value=num_valence_bands)
    if (found .and. (num_valence_bands .le. 0)) &
      call io_error('Error: num_valence_bands should be greater than zero')
    ! there is a check on this parameter later

    dos_task = 'dos_plot'
    if (dos) then
      dos_plot = .true.
    else
      dos_plot = .false.
    endif
    call param_get_keyword('dos_task', found, c_value=dos_task)
    if (dos) then
      if (index(dos_task, 'dos_plot') == 0 .and. &
          index(dos_task, 'find_fermi_energy') == 0) call io_error &
        ('Error: value of dos_task not recognised in param_read')
      if (index(dos_task, 'dos_plot') > 0) dos_plot = .true.
      if (index(dos_task, 'find_fermi_energy') > 0 .and. found_fermi_energy) &
        call io_error &
        ('Error: Cannot set "dos_task = find_fermi_energy" and give a value to "fermi_energy"')
    end if

!    sigma_abc_onlyorb=.false.
!    call param_get_keyword('sigma_abc_onlyorb',found,l_value=sigma_abc_onlyorb)

! -------------------------------------------------------------------

    !IVO_END

    dos_energy_step = 0.01_dp
    call param_get_keyword('dos_energy_step', found, r_value=dos_energy_step)

    dos_adpt_smr = adpt_smr
    call param_get_keyword('dos_adpt_smr', found, l_value=dos_adpt_smr)

    dos_adpt_smr_fac = adpt_smr_fac
    call param_get_keyword('dos_adpt_smr_fac', found, r_value=dos_adpt_smr_fac)
    if (found .and. (dos_adpt_smr_fac <= 0._dp)) &
      call io_error('Error: dos_adpt_smr_fac must be greater than zero')

    dos_adpt_smr_max = adpt_smr_max
    call param_get_keyword('dos_adpt_smr_max', found, r_value=dos_adpt_smr_max)
    if (dos_adpt_smr_max <= 0._dp) call io_error &
      ('Error: dos_adpt_smr_max must be greater than zero')

    dos_smr_fixed_en_width = smr_fixed_en_width
    call param_get_keyword('dos_smr_fixed_en_width', found, r_value=dos_smr_fixed_en_width)
    if (found .and. (dos_smr_fixed_en_width < 0._dp)) &
      call io_error('Error: dos_smr_fixed_en_width must be greater than or equal to zero')

!    dos_gaussian_width        = 0.1_dp
!    call param_get_keyword('dos_gaussian_width',found,r_value=dos_gaussian_width)

!    dos_plot_format           = 'gnuplot'
!    call param_get_keyword('dos_plot_format',found,c_value=dos_plot_format)

    call param_get_range_vector('dos_project', found, num_dos_project, &
                                lcount=.true.)
    if (found) then
      if (num_dos_project < 1) call io_error('Error: problem reading dos_project')
      if (allocated(dos_project)) deallocate (dos_project)
      allocate (dos_project(num_dos_project), stat=ierr)
      if (ierr /= 0) call io_error('Error allocating dos_project in param_read')
      call param_get_range_vector('dos_project', found, num_dos_project, &
                                  .false., dos_project)
      if (any(dos_project < 1) .or. any(dos_project > num_wann)) call io_error &
        ('Error: dos_project asks for out-of-range Wannier functions')
    else
      ! by default plot all
      num_dos_project = num_wann
      if (allocated(dos_project)) deallocate (dos_project)
      allocate (dos_project(num_dos_project), stat=ierr)
      if (ierr /= 0) call io_error('Error allocating dos_project in param_read')
      do i = 1, num_dos_project
        dos_project(i) = i
      end do
    endif

    hr_plot = .false.
    call param_get_keyword('hr_plot', found, l_value=hr_plot)
    if (found) call io_error('Input parameter hr_plot is no longer used. Please use write_hr instead.')
    write_hr = .false.
    call param_get_keyword('write_hr', found, l_value=write_hr)

    write_rmn = .false.
    call param_get_keyword('write_rmn', found, l_value=write_rmn)

    write_tb = .false.
    call param_get_keyword('write_tb', found, l_value=write_tb)

    hr_cutoff = 0.0_dp
    call param_get_keyword('hr_cutoff', found, r_value=hr_cutoff)

    dist_cutoff_mode = 'three_dim'
    call param_get_keyword('dist_cutoff_mode', found, c_value=dist_cutoff_mode)
    if ((index(dist_cutoff_mode, 'three_dim') .eq. 0) &
        .and. (index(dist_cutoff_mode, 'two_dim') .eq. 0) &
        .and. (index(dist_cutoff_mode, 'one_dim') .eq. 0)) &
      call io_error('Error: dist_cutoff_mode not recognised')

! aam_2012-04-13: moved later
!    dist_cutoff                 = 1000.0_dp
!    call param_get_keyword('dist_cutoff',found,r_value=dist_cutoff)

    one_dim_axis = 'none'
    call param_get_keyword('one_dim_axis', found, c_value=one_dim_axis)
    one_dim_dir = 0
    if (index(one_dim_axis, 'x') > 0) one_dim_dir = 1
    if (index(one_dim_axis, 'y') > 0) one_dim_dir = 2
    if (index(one_dim_axis, 'z') > 0) one_dim_dir = 3
    if (transport .and. .not. tran_read_ht .and. (one_dim_dir .eq. 0)) call io_error('Error: one_dim_axis not recognised')
    if (bands_plot .and. (index(bands_plot_mode, 'cut') .ne. 0)&
       & .and. ((bands_plot_dim .ne. 3) .or. (index(dist_cutoff_mode, 'three_dim') .eq. 0))&
       & .and. (one_dim_dir .eq. 0)) &
         call io_error('Error: one_dim_axis not recognised')

301 continue

    use_ws_distance = .true.
    call param_get_keyword('use_ws_distance', found, l_value=use_ws_distance)

    ws_distance_tol = 1.e-5_dp
    call param_get_keyword('ws_distance_tol', found, r_value=ws_distance_tol)

    ws_search_size = 2

    call param_get_vector_length('ws_search_size', found, length=i)
    if (found) then
      if (i .eq. 1) then
        call param_get_keyword_vector('ws_search_size', found, 1, &
                                      i_value=ws_search_size)
        ws_search_size(2) = ws_search_size(1)
        ws_search_size(3) = ws_search_size(1)
      elseif (i .eq. 3) then
        call param_get_keyword_vector('ws_search_size', found, 3, &
                                      i_value=ws_search_size)
      else
        call io_error('Error: ws_search_size must be provided as either one integer or a vector of three integers')
      end if
      if (any(ws_search_size <= 0)) &
        call io_error('Error: ws_search_size elements must be greater than zero')
    end if

    !%%%%%%%%%%%%%%%%
    ! Transport
    !%%%%%%%%%%%%%%%%

    transport_mode = 'bulk'
    call param_get_keyword('transport_mode', found, c_value=transport_mode)

!    if ( .not.tran_read_ht  .and. (index(transport_mode,'lcr').ne.0) ) &
!       call io_error('Error: transport_mode.eq.lcr not compatible with tran_read_ht.eq.false')

    tran_win_min = -3.0_dp
    call param_get_keyword('tran_win_min', found, r_value=tran_win_min)

    tran_win_max = 3.0_dp
    call param_get_keyword('tran_win_max', found, r_value=tran_win_max)

    tran_energy_step = 0.01_dp
    call param_get_keyword('tran_energy_step', found, r_value=tran_energy_step)

    tran_num_bb = 0
    call param_get_keyword('tran_num_bb', found, i_value=tran_num_bb)

    tran_num_ll = 0
    call param_get_keyword('tran_num_ll', found, i_value=tran_num_ll)

    tran_num_rr = 0
    call param_get_keyword('tran_num_rr', found, i_value=tran_num_rr)

    tran_num_cc = 0
    call param_get_keyword('tran_num_cc', found, i_value=tran_num_cc)

    tran_num_lc = 0
    call param_get_keyword('tran_num_lc', found, i_value=tran_num_lc)

    tran_num_cr = 0
    call param_get_keyword('tran_num_cr', found, i_value=tran_num_cr)

    tran_num_bandc = 0
    call param_get_keyword('tran_num_bandc', found, i_value=tran_num_bandc)

    tran_write_ht = .false.
    call param_get_keyword('tran_write_ht', found, l_value=tran_write_ht)

    tran_use_same_lead = .true.
    call param_get_keyword('tran_use_same_lead', found, l_value=tran_use_same_lead)

    tran_num_cell_ll = 0
    call param_get_keyword('tran_num_cell_ll', found, i_value=tran_num_cell_ll)

    tran_num_cell_rr = 0
    call param_get_keyword('tran_num_cell_rr', found, i_value=tran_num_cell_rr)

    tran_group_threshold = 0.15_dp
    call param_get_keyword('tran_group_threshold', found, r_value=tran_group_threshold)

    dist_cutoff = 1000.0_dp
    call param_get_keyword('dist_cutoff', found, r_value=dist_cutoff)

    dist_cutoff_hc = dist_cutoff
    call param_get_keyword('dist_cutoff_hc', found, r_value=dist_cutoff_hc)

    ! checks
    if (transport) then
      if ((index(transport_mode, 'bulk') .eq. 0) .and. (index(transport_mode, 'lcr') .eq. 0)) &
        call io_error('Error: transport_mode not recognised')
      if (tran_num_bb < 0) call io_error('Error: tran_num_bb < 0')
      if (tran_num_ll < 0) call io_error('Error: tran_num_ll < 0')
      if (tran_num_rr < 0) call io_error('Error: tran_num_rr < 0')
      if (tran_num_cc < 0) call io_error('Error: tran_num_cc < 0')
      if (tran_num_lc < 0) call io_error('Error: tran_num_lc < 0')
      if (tran_num_cr < 0) call io_error('Error: tran_num_cr < 0')
      if (tran_num_bandc < 0) call io_error('Error: tran_num_bandc < 0')
      if (tran_num_cell_ll < 0) call io_error('Error: tran_num_cell_ll < 0')
      if (tran_num_cell_rr < 0) call io_error('Error: tran_num_cell_rr < 0')
      if (tran_group_threshold < 0.0_dp) call io_error('Error: tran_group_threshold < 0')
    endif

    if (transport .and. tran_read_ht) goto 302

    !%%%%%%%%%%%%%%%%
    ! Disentanglement
    !%%%%%%%%%%%%%%%%

    disentanglement = .false.
    if (num_bands > num_wann) disentanglement = .true.

    ! These must be read here, before the check on the existence of the .eig file!
    geninterp = .false.
    call param_get_keyword('geninterp', found, l_value=geninterp)
    boltzwann = .false.
    call param_get_keyword('boltzwann', found, l_value=boltzwann)

    ! Read the eigenvalues from wannier.eig
    eig_found = .false.
    if (.not. library .and. .not. effective_model) then

      if (.not. postproc_setup) then
        inquire (file=trim(seedname)//'.eig', exist=eig_found)
        if (.not. eig_found) then
          if (disentanglement) then
            call io_error('No '//trim(seedname)//'.eig file found. Needed for disentanglement')
          else if ((bands_plot .or. dos_plot .or. fermi_surface_plot .or. write_hr .or. boltzwann &
                    .or. geninterp)) then
            call io_error('No '//trim(seedname)//'.eig file found. Needed for interpolation')
          end if
        else
          ! Allocate only here
          allocate (eigval(num_bands, num_kpts), stat=ierr)
          if (ierr /= 0) call io_error('Error allocating eigval in param_read')

          eig_unit = io_file_unit()
          open (unit=eig_unit, file=trim(seedname)//'.eig', form='formatted', status='old', err=105)
          do k = 1, num_kpts
            do n = 1, num_bands
              read (eig_unit, *, err=106, end=106) i, j, eigval(n, k)
              if ((i .ne. n) .or. (j .ne. k)) then
                write (stdout, '(a)') 'Found a mismatch in '//trim(seedname)//'.eig'
                write (stdout, '(a,i0,a,i0)') 'Wanted band  : ', n, ' found band  : ', i
                write (stdout, '(a,i0,a,i0)') 'Wanted kpoint: ', k, ' found kpoint: ', j
                write (stdout, '(a)') ' '
                write (stdout, '(a)') 'A common cause of this error is using the wrong'
                write (stdout, '(a)') 'number of bands. Check your input files.'
                write (stdout, '(a)') 'If your pseudopotentials have shallow core states remember'
                write (stdout, '(a)') 'to account for these electrons.'
                write (stdout, '(a)') ' '
                call io_error('param_read: mismatch in '//trim(seedname)//'.eig')
              end if
            enddo
          end do
          close (eig_unit)
        end if
      end if
    end if

    if (library .and. allocated(eigval)) eig_found = .true.

    dis_win_min = -1.0_dp; dis_win_max = 0.0_dp
    if (eig_found) dis_win_min = minval(eigval)
    call param_get_keyword('dis_win_min', found, r_value=dis_win_min)

    if (eig_found) dis_win_max = maxval(eigval)
    call param_get_keyword('dis_win_max', found, r_value=dis_win_max)
    if (eig_found .and. (dis_win_max .lt. dis_win_min)) &
      call io_error('Error: param_read: check disentanglement windows')

    dis_froz_min = -1.0_dp; dis_froz_max = 0.0_dp
    ! no default for dis_froz_max
    frozen_states = .false.
    call param_get_keyword('dis_froz_max', found, r_value=dis_froz_max)
    if (found) then
      frozen_states = .true.
      dis_froz_min = dis_win_min ! default value for the bottom of frozen window
    end if
    call param_get_keyword('dis_froz_min', found2, r_value=dis_froz_min)
    if (eig_found) then
      if (dis_froz_max .lt. dis_froz_min) &
        call io_error('Error: param_read: check disentanglement frozen windows')
      if (found2 .and. .not. found) &
        call io_error('Error: param_read: found dis_froz_min but not dis_froz_max')
    endif

    dis_num_iter = 200
    call param_get_keyword('dis_num_iter', found, i_value=dis_num_iter)
    if (dis_num_iter < 0) call io_error('Error: dis_num_iter must be positive')

    dis_mix_ratio = 0.5_dp
    call param_get_keyword('dis_mix_ratio', found, r_value=dis_mix_ratio)
    if (dis_mix_ratio <= 0.0_dp .or. dis_mix_ratio > 1.0_dp) &
      call io_error('Error: dis_mix_ratio must be greater than 0.0 but not greater than 1.0')

    dis_conv_tol = 1.0e-10_dp
    call param_get_keyword('dis_conv_tol', found, r_value=dis_conv_tol)
    if (dis_conv_tol < 0.0_dp) call io_error('Error: dis_conv_tol must be positive')

    dis_conv_window = 3
    call param_get_keyword('dis_conv_window', found, i_value=dis_conv_window)
    if (dis_conv_window < 0) call io_error('Error: dis_conv_window must be positive')

    ! GS-start
    dis_spheres_first_wann = 1
    call param_get_keyword('dis_spheres_first_wann', found, i_value=dis_spheres_first_wann)
    if (dis_spheres_first_wann < 1) call io_error('Error: dis_spheres_first_wann must be greater than 0')
    if (dis_spheres_first_wann > num_bands - num_wann + 1) &
      call io_error('Error: dis_spheres_first_wann is larger than num_bands-num_wann+1')
    dis_spheres_num = 0
    call param_get_keyword('dis_spheres_num', found, i_value=dis_spheres_num)
    if (dis_spheres_num < 0) call io_error('Error: dis_spheres_num cannot be negative')
    if (dis_spheres_num > 0) then
      allocate (dis_spheres(4, dis_spheres_num), stat=ierr)
      if (ierr /= 0) call io_error('Error allocating dis_spheres in param_read')
      call param_get_keyword_block('dis_spheres', found, dis_spheres_num, 4, r_value=dis_spheres)
      if (.not. found) call io_error('Error: Did not find dis_spheres in the input file')
      do nkp = 1, dis_spheres_num
        if (dis_spheres(4, nkp) < 1.0e-15_dp) &
          call io_error('Error: radius for dis_spheres must be > 0')
      enddo
    endif
    ! GS-end

    ! [gp-begin, Jun 1, 2012]
    !%%%%%%%%%%%%%%%%%%%%
    ! General band interpolator (geninterp)
    !%%%%%%%%%%%%%%%%%%%%
    geninterp_alsofirstder = .false.
    call param_get_keyword('geninterp_alsofirstder', found, l_value=geninterp_alsofirstder)
    geninterp_single_file = .true.
    call param_get_keyword('geninterp_single_file', found, l_value=geninterp_single_file)
    ! [gp-end, Jun 1, 2012]

    ! [gp-begin, Apr 12, 2012]
    !%%%%%%%%%%%%%%%%%%%%
    ! Boltzmann transport
    !%%%%%%%%%%%%%%%%%%%%
    ! Note: to be put AFTER the disentanglement routines!

    boltz_calc_also_dos = .false.
    call param_get_keyword('boltz_calc_also_dos', found, l_value=boltz_calc_also_dos)

    boltz_calc_also_dos = boltz_calc_also_dos .and. boltzwann

    ! 0 means the normal 3d case for the calculation of the Seebeck coefficient
    ! The other valid possibilities are 1,2,3 for x,y,z respectively
    boltz_2d_dir_num = 0
    call param_get_keyword('boltz_2d_dir', found, c_value=boltz_2d_dir)
    if (found) then
      if (trim(boltz_2d_dir) == 'no') then
        boltz_2d_dir_num = 0
      elseif (trim(boltz_2d_dir) == 'x') then
        boltz_2d_dir_num = 1
      elseif (trim(boltz_2d_dir) == 'y') then
        boltz_2d_dir_num = 2
      elseif (trim(boltz_2d_dir) == 'z') then
        boltz_2d_dir_num = 3
      else
        call io_error('Error: boltz_2d_dir can only be "no", "x", "y" or "z".')
      end if
    end if

    boltz_dos_energy_step = 0.001_dp
    call param_get_keyword('boltz_dos_energy_step', found, r_value=boltz_dos_energy_step)
    if (found .and. (boltz_dos_energy_step <= 0._dp)) &
      call io_error('Error: boltz_dos_energy_step must be positive')

    if (allocated(eigval)) then
      boltz_dos_energy_min = minval(eigval) - 0.6667_dp
    else
      ! Boltz_dos cannot run if eigval is not allocated.
      ! We just set here a default numerical value.
      boltz_dos_energy_min = -1.0_dp
    end if
    call param_get_keyword('boltz_dos_energy_min', found, r_value=boltz_dos_energy_min)
    if (allocated(eigval)) then
      boltz_dos_energy_max = maxval(eigval) + 0.6667_dp
    else
      ! Boltz_dos cannot run if eigval is not allocated.
      ! We just set here a default numerical value.
      boltz_dos_energy_max = 0.0_dp
    end if
    call param_get_keyword('boltz_dos_energy_max', found, r_value=boltz_dos_energy_max)
    if (boltz_dos_energy_max <= boltz_dos_energy_min) &
      call io_error('Error: boltz_dos_energy_max must be greater than boltz_dos_energy_min')

    boltz_dos_adpt_smr = adpt_smr
    call param_get_keyword('boltz_dos_adpt_smr', found, l_value=boltz_dos_adpt_smr)

    boltz_dos_adpt_smr_fac = adpt_smr_fac
    call param_get_keyword('boltz_dos_adpt_smr_fac', found, r_value=boltz_dos_adpt_smr_fac)
    if (found .and. (boltz_dos_adpt_smr_fac <= 0._dp)) &
      call io_error('Error: boltz_dos_adpt_smr_fac must be greater than zero')

    boltz_dos_adpt_smr_max = adpt_smr_max
    call param_get_keyword('boltz_dos_adpt_smr_max', found, r_value=boltz_dos_adpt_smr_max)
    if (boltz_dos_adpt_smr_max <= 0._dp) call io_error &
      ('Error: boltz_dos_adpt_smr_max must be greater than zero')

    boltz_dos_smr_fixed_en_width = smr_fixed_en_width
    call param_get_keyword('boltz_dos_smr_fixed_en_width', found, r_value=boltz_dos_smr_fixed_en_width)
    if (found .and. (boltz_dos_smr_fixed_en_width < 0._dp)) &
      call io_error('Error: boltz_dos_smr_fixed_en_width must be greater than or equal to zero')

    boltz_mu_min = -999._dp
    call param_get_keyword('boltz_mu_min', found, r_value=boltz_mu_min)
    if ((.not. found) .and. boltzwann) &
      call io_error('Error: BoltzWann required but no boltz_mu_min provided')
    boltz_mu_max = -999._dp
    call param_get_keyword('boltz_mu_max', found2, r_value=boltz_mu_max)
    if ((.not. found2) .and. boltzwann) &
      call io_error('Error: BoltzWann required but no boltz_mu_max provided')
    if (found .and. found2 .and. (boltz_mu_max < boltz_mu_min)) &
      call io_error('Error: boltz_mu_max must be greater than boltz_mu_min')
    boltz_mu_step = 0._dp
    call param_get_keyword('boltz_mu_step', found, r_value=boltz_mu_step)
    if ((.not. found) .and. boltzwann) &
      call io_error('Error: BoltzWann required but no boltz_mu_step provided')
    if (found .and. (boltz_mu_step <= 0._dp)) &
      call io_error('Error: boltz_mu_step must be greater than zero')

    boltz_temp_min = -999._dp
    call param_get_keyword('boltz_temp_min', found, r_value=boltz_temp_min)
    if ((.not. found) .and. boltzwann) &
      call io_error('Error: BoltzWann required but no boltz_temp_min provided')
    boltz_temp_max = -999._dp
    call param_get_keyword('boltz_temp_max', found2, r_value=boltz_temp_max)
    if ((.not. found2) .and. boltzwann) &
      call io_error('Error: BoltzWann required but no boltz_temp_max provided')
    if (found .and. found2 .and. (boltz_temp_max < boltz_temp_min)) &
      call io_error('Error: boltz_temp_max must be greater than boltz_temp_min')
    if (found .and. (boltz_temp_min <= 0._dp)) &
      call io_error('Error: boltz_temp_min must be greater than zero')
    boltz_temp_step = 0._dp
    call param_get_keyword('boltz_temp_step', found, r_value=boltz_temp_step)
    if ((.not. found) .and. boltzwann) &
      call io_error('Error: BoltzWann required but no boltz_temp_step provided')
    if (found .and. (boltz_temp_step <= 0._dp)) &
      call io_error('Error: boltz_temp_step must be greater than zero')

    ! The interpolation mesh is read later on

    ! By default, the energy step for the TDF is 1 meV
    boltz_tdf_energy_step = 0.001_dp
    call param_get_keyword('boltz_tdf_energy_step', found, r_value=boltz_tdf_energy_step)
    if (boltz_tdf_energy_step <= 0._dp) &
      call io_error('Error: boltz_tdf_energy_step must be greater than zero')

    ! For TDF: TDF smeared in a NON-adaptive way; value in eV, default = 0._dp
    ! (i.e., no smearing)
    boltz_TDF_smr_fixed_en_width = smr_fixed_en_width
    call param_get_keyword('boltz_tdf_smr_fixed_en_width', found, r_value=boltz_TDF_smr_fixed_en_width)
    if (found .and. (boltz_TDF_smr_fixed_en_width < 0._dp)) &
      call io_error('Error: boltz_TDF_smr_fixed_en_width must be greater than or equal to zero')

    ! By default: use the "global" smearing index
    boltz_TDF_smr_index = smr_index
    call param_get_keyword('boltz_tdf_smr_type', found, c_value=ctmp)
    if (found) boltz_TDF_smr_index = get_smearing_index(ctmp, 'boltz_tdf_smr_type')

    ! By default: use the "global" smearing index
    boltz_dos_smr_index = smr_index
    call param_get_keyword('boltz_dos_smr_type', found, c_value=ctmp)
    if (found) boltz_dos_smr_index = get_smearing_index(ctmp, 'boltz_dos_smr_type')

    ! By default: use the "global" smearing index
    dos_smr_index = smr_index
    call param_get_keyword('dos_smr_type', found, c_value=ctmp)
    if (found) dos_smr_index = get_smearing_index(ctmp, 'dos_smr_type')

    ! By default: use the "global" smearing index
    kubo_smr_index = smr_index
    call param_get_keyword('kubo_smr_type', found, c_value=ctmp)
    if (found) kubo_smr_index = get_smearing_index(ctmp, 'kubo_smr_type')

    ! By default: use the "global" smearing index
    gyrotropic_smr_index = smr_index
    call param_get_keyword('gyrotropic_smr_type', found, c_value=ctmp)
    if (found) gyrotropic_smr_index = get_smearing_index(ctmp, 'gyrotropic_smr_type')

    ! By default: 10 fs relaxation time
    boltz_relax_time = 10._dp
    call param_get_keyword('boltz_relax_time', found, r_value=boltz_relax_time)

    boltz_bandshift = .false.
    call param_get_keyword('boltz_bandshift', found, l_value=boltz_bandshift)
    boltz_bandshift = boltz_bandshift .and. boltzwann

    boltz_bandshift_firstband = 0
    call param_get_keyword('boltz_bandshift_firstband', found, i_value=boltz_bandshift_firstband)
    if (boltz_bandshift .and. (.not. found)) &
      call io_error('Error: boltz_bandshift required but no boltz_bandshift_firstband provided')
    boltz_bandshift_energyshift = 0._dp
    call param_get_keyword('boltz_bandshift_energyshift', found, r_value=boltz_bandshift_energyshift)
    if (boltz_bandshift .and. (.not. found)) &
      call io_error('Error: boltz_bandshift required but no boltz_bandshift_energyshift provided')
    ! [gp-end, Apr 12, 2012]

    !%%%%%%%%%%%%%%%%
    !  Other Stuff
    !%%%%%%%%%%%%%%%%

    ! aam: vdW
    write_vdw_data = .false.
    call param_get_keyword('write_vdw_data', found, l_value=write_vdw_data)
    if (write_vdw_data) then
      if ((.not. gamma_only) .or. (num_kpts .ne. 1)) &
        call io_error('Error: write_vdw_data may only be used with a single k-point at Gamma')
    endif
    if (write_vdw_data .and. disentanglement .and. num_valence_bands .le. 0) &
      call io_error('If writing vdw data and disentangling then num_valence_bands must be defined')

    if (frozen_states) then
      dos_energy_max = dis_froz_max + 0.6667_dp
    elseif (allocated(eigval)) then
      dos_energy_max = maxval(eigval) + 0.6667_dp
    else
      dos_energy_max = dis_win_max + 0.6667_dp
    end if
    call param_get_keyword('dos_energy_max', found, r_value=dos_energy_max)

    if (allocated(eigval)) then
      dos_energy_min = minval(eigval) - 0.6667_dp
    else
      dos_energy_min = dis_win_min - 0.6667_dp
    end if
    call param_get_keyword('dos_energy_min', found, r_value=dos_energy_min)

    kubo_freq_min = 0.0_dp
    gyrotropic_freq_min = kubo_freq_min
    call param_get_keyword('kubo_freq_min', found, r_value=kubo_freq_min)
    !
    if (frozen_states) then
      kubo_freq_max = dis_froz_max - fermi_energy_list(1) + 0.6667_dp
    elseif (allocated(eigval)) then
      kubo_freq_max = maxval(eigval) - minval(eigval) + 0.6667_dp
    else
      kubo_freq_max = dis_win_max - dis_win_min + 0.6667_dp
    end if
    gyrotropic_freq_max = kubo_freq_max
    call param_get_keyword('kubo_freq_max', found, r_value=kubo_freq_max)

    !
    kubo_freq_step = 0.01_dp
    call param_get_keyword('kubo_freq_step', found, r_value=kubo_freq_step)
    if (found .and. kubo_freq_step < 0.0_dp) call io_error( &
      'Error: kubo_freq_step must be positive')
    !
    kubo_nfreq = nint((kubo_freq_max - kubo_freq_min)/kubo_freq_step) + 1
    if (kubo_nfreq <= 1) kubo_nfreq = 2
    kubo_freq_step = (kubo_freq_max - kubo_freq_min)/(kubo_nfreq - 1)
    !
    if (allocated(kubo_freq_list)) deallocate (kubo_freq_list)
    allocate (kubo_freq_list(kubo_nfreq), stat=ierr)
    if (ierr /= 0) &
      call io_error('Error allocating kubo_freq_list in param_read')
    do i = 1, kubo_nfreq
      kubo_freq_list(i) = kubo_freq_min &
                          + (i - 1)*(kubo_freq_max - kubo_freq_min)/(kubo_nfreq - 1)
    enddo
    !
    ! TODO: Alternatively, read list of (complex) frequencies; kubo_nfreq is
    !       the length of the list

    gyrotropic_freq_step = 0.01_dp
    call param_get_keyword('gyrotropic_freq_min', found, r_value=gyrotropic_freq_min)
    call param_get_keyword('gyrotropic_freq_max', found, r_value=gyrotropic_freq_max)
    call param_get_keyword('gyrotropic_freq_step', found, r_value=gyrotropic_freq_step)
    gyrotropic_nfreq = nint((gyrotropic_freq_max - gyrotropic_freq_min)/gyrotropic_freq_step) + 1
    if (gyrotropic_nfreq <= 1) gyrotropic_nfreq = 2
    gyrotropic_freq_step = (gyrotropic_freq_max - gyrotropic_freq_min)/(gyrotropic_nfreq - 1)
    if (allocated(gyrotropic_freq_list)) deallocate (gyrotropic_freq_list)
    allocate (gyrotropic_freq_list(gyrotropic_nfreq), stat=ierr)
    if (ierr /= 0) &
      call io_error('Error allocating gyrotropic_freq_list in param_read')
    do i = 1, gyrotropic_nfreq
      gyrotropic_freq_list(i) = gyrotropic_freq_min &
                                + (i - 1)*(gyrotropic_freq_max - gyrotropic_freq_min)/(gyrotropic_nfreq - 1) &
                                + cmplx_i*gyrotropic_smr_fixed_en_width
    enddo

    if (frozen_states) then
      kubo_eigval_max = dis_froz_max + 0.6667_dp
    elseif (allocated(eigval)) then
      kubo_eigval_max = maxval(eigval) + 0.6667_dp
    else
      kubo_eigval_max = dis_win_max + 0.6667_dp
    end if
    gyrotropic_eigval_max = kubo_eigval_max

    call param_get_keyword('kubo_eigval_max', found, r_value=kubo_eigval_max)
    call param_get_keyword('gyrotropic_eigval_max', found, r_value=gyrotropic_eigval_max)

    automatic_translation = .true.
    translation_centre_frac = 0.0_dp
    call param_get_keyword_vector('translation_centre_frac', found, 3, r_value=rv_temp)
    if (found) then
      translation_centre_frac = rv_temp
      automatic_translation = .false.
    endif

    sc_eta = 0.04
    call param_get_keyword('sc_eta', found, r_value=sc_eta)

    sc_w_thr = 5.0d0
    call param_get_keyword('sc_w_thr', found, r_value=sc_w_thr)

    use_bloch_phases = .false.
    call param_get_keyword('use_bloch_phases', found, l_value=use_bloch_phases)
    if (disentanglement .and. use_bloch_phases) &
      call io_error('Error: Cannot use bloch phases for disentanglement')

    search_shells = 36
    call param_get_keyword('search_shells', found, i_value=search_shells)
    if (search_shells < 0) call io_error('Error: search_shells must be positive')

    kmesh_tol = 0.000001_dp
    call param_get_keyword('kmesh_tol', found, r_value=kmesh_tol)
    if (kmesh_tol < 0.0_dp) call io_error('Error: kmesh_tol must be positive')

    num_shells = 0
    call param_get_range_vector('shell_list', found, num_shells, lcount=.true.)
    if (found) then
      if (num_shells < 0 .or. num_shells > max_shells) &
        call io_error('Error: number of shell in shell_list must be between zero and six')
      if (allocated(shell_list)) deallocate (shell_list)
      allocate (shell_list(num_shells), stat=ierr)
      if (ierr /= 0) call io_error('Error allocating shell_list in param_read')
      call param_get_range_vector('shell_list', found, num_shells, .false., shell_list)
      if (any(shell_list < 1)) &
        call io_error('Error: shell_list must contain positive numbers')
    else
      if (allocated(shell_list)) deallocate (shell_list)
      allocate (shell_list(max_shells), stat=ierr)
      if (ierr /= 0) call io_error('Error allocating shell_list in param_read')
    end if

    call param_get_keyword('num_shells', found, i_value=itmp)
    if (found .and. (itmp /= num_shells)) &
      call io_error('Error: Found obsolete keyword num_shells. Its value does not agree with shell_list')

    ! If .true., does not perform the check of B1 of
    ! Marzari, Vanderbild, PRB 56, 12847 (1997)
    ! in kmesh.F90
    ! mainly needed for the interaction with Z2PACK
    ! By default: .false. (perform the tests)
    skip_B1_tests = .false.
    call param_get_keyword('skip_b1_tests', found, l_value=skip_B1_tests)

    call param_get_keyword_block('unit_cell_cart', found, 3, 3, r_value=real_lattice_tmp)
    if (found .and. library) write (stdout, '(a)') ' Ignoring <unit_cell_cart> in input file'
    if (.not. library) then
      real_lattice = transpose(real_lattice_tmp)
      if (.not. found) call io_error('Error: Did not find the cell information in the input file')
    end if

    if (.not. library) &
      call utility_recip_lattice(real_lattice, recip_lattice, cell_volume)
    call utility_metric(real_lattice, recip_lattice, real_metric, recip_metric)

    if (.not. effective_model) allocate (kpt_cart(3, num_kpts), stat=ierr)
    if (ierr /= 0) call io_error('Error allocating kpt_cart in param_read')
    if (.not. library .and. .not. effective_model) then
      allocate (kpt_latt(3, num_kpts), stat=ierr)
      if (ierr /= 0) call io_error('Error allocating kpt_latt in param_read')
    end if

    call param_get_keyword_block('kpoints', found, num_kpts, 3, r_value=kpt_cart)
    if (found .and. library) write (stdout, '(a)') ' Ignoring <kpoints> in input file'
    if (.not. library .and. .not. effective_model) then
      kpt_latt = kpt_cart
      if (.not. found) call io_error('Error: Did not find the kpoint information in the input file')
    end if

    ! Calculate the kpoints in cartesian coordinates
    if (.not. effective_model) then
      do nkp = 1, num_kpts
        kpt_cart(:, nkp) = matmul(kpt_latt(:, nkp), recip_lattice(:, :))
      end do
    endif

    ! get the nnkpts block -- this is allowed only in postproc-setup mode
    call param_get_block_length('nnkpts', explicit_nnkpts, rows)
    if (explicit_nnkpts) then
      nntot = rows/num_kpts
      if (modulo(rows, num_kpts) /= 0) then
        call io_error('The number of rows in nnkpts must be a multiple of num_kpts')
      end if
      if (allocated(nnkpts_block)) deallocate (nnkpts_block)
      allocate (nnkpts_block(5, rows), stat=ierr)
      if (ierr /= 0) call io_error('Error allocating nnkpts_block in param_read')
      call param_get_keyword_block('nnkpts', found, rows, 5, i_value=nnkpts_block)
      ! check that postproc_setup is true
      if (.not. postproc_setup) &
        call io_error('Input parameter nnkpts_block is allowed only if postproc_setup = .true.')
      ! assign the values in nnkpts_block to nnlist and nncell
      ! this keeps track of how many neighbours have been seen for each k-point
      if (allocated(nnkpts_idx)) deallocate (nnkpts_idx)
      allocate (nnkpts_idx(num_kpts), stat=ierr)
      if (ierr /= 0) call io_error('Error allocating nnkpts_idx in param_read')
      nnkpts_idx = 1
      ! allocating "global" nnlist & nncell
      ! These are deallocated in kmesh_dealloc
      if (allocated(nnlist)) deallocate (nnlist)
      allocate (nnlist(num_kpts, nntot), stat=ierr)
      if (ierr /= 0) call io_error('Error allocating nnlist in param_read')
      if (allocated(nncell)) deallocate (nncell)
      allocate (nncell(3, num_kpts, nntot), stat=ierr)
      if (ierr /= 0) call io_error('Error allocating nncell in param_read')
      do i = 1, num_kpts*nntot
        k = nnkpts_block(1, i)
        nnlist(k, nnkpts_idx(k)) = nnkpts_block(2, i)
        nncell(:, k, nnkpts_idx(k)) = nnkpts_block(3:, i)
        nnkpts_idx(k) = nnkpts_idx(k) + 1
      end do
      ! check that all k-points have the same number of neighbours
      if (any(nnkpts_idx /= (/(nntot + 1, i=1, num_kpts)/))) then
        call io_error('Inconsistent number of nearest neighbours.')
      end if
      deallocate (nnkpts_idx, stat=ierr)
      if (ierr /= 0) call io_error('Error deallocating nnkpts_idx in param_read')
      deallocate (nnkpts_block, stat=ierr)
      if (ierr /= 0) call io_error('Error deallocating nnkpts_block in param_read')
    end if

    !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!
    ! k meshes                                                                                 !
    !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!
    ! [GP-begin, Apr13, 2012]
    ! Global interpolation k-mesh; this is overridden by "local" meshes of a given submodule
    ! This bit of code must appear *before* all other codes for the local interpolation meshes,
    ! BUT *after* having calculated the reciprocal-space vectors.
    global_kmesh_set = .false.
    kmesh_spacing = -1._dp
    kmesh = 0
    call param_get_keyword('kmesh_spacing', found, r_value=kmesh_spacing)
    if (found) then
      if (kmesh_spacing .le. 0._dp) &
        call io_error('Error: kmesh_spacing must be greater than zero')
      global_kmesh_set = .true.

      call internal_set_kmesh(kmesh_spacing, recip_lattice, kmesh)
    end if
    call param_get_vector_length('kmesh', found, length=i)
    if (found) then
      if (global_kmesh_set) &
        call io_error('Error: cannot set both kmesh and kmesh_spacing')
      if (i .eq. 1) then
        global_kmesh_set = .true.
        call param_get_keyword_vector('kmesh', found, 1, i_value=kmesh)
        kmesh(2) = kmesh(1)
        kmesh(3) = kmesh(1)
      elseif (i .eq. 3) then
        global_kmesh_set = .true.
        call param_get_keyword_vector('kmesh', found, 3, i_value=kmesh)
      else
        call io_error('Error: kmesh must be provided as either one integer or a vector of three integers')
      end if
      if (any(kmesh <= 0)) &
        call io_error('Error: kmesh elements must be greater than zero')
    end if
    ! [GP-end]

    ! To be called after having read the global flag
    call get_module_kmesh(moduleprefix='boltz', &
                          should_be_defined=boltzwann, &
                          module_kmesh=boltz_kmesh, &
                          module_kmesh_spacing=boltz_kmesh_spacing)

    call get_module_kmesh(moduleprefix='berry', &
                          should_be_defined=berry, &
                          module_kmesh=berry_kmesh, &
                          module_kmesh_spacing=berry_kmesh_spacing)

    call get_module_kmesh(moduleprefix='gyrotropic', &
                          should_be_defined=gyrotropic, &
                          module_kmesh=gyrotropic_kmesh, &
                          module_kmesh_spacing=gyrotropic_kmesh_spacing)

    call get_module_kmesh(moduleprefix='spin', &
                          should_be_defined=spin_moment, &
                          module_kmesh=spin_kmesh, &
                          module_kmesh_spacing=spin_kmesh_spacing)

    call get_module_kmesh(moduleprefix='dos', &
                          should_be_defined=dos, &
                          module_kmesh=dos_kmesh, &
                          module_kmesh_spacing=dos_kmesh_spacing)

    ! Atoms
    if (.not. library) num_atoms = 0
    call param_get_block_length('atoms_frac', found, i_temp)
    if (found .and. library) write (stdout, '(a)') ' Ignoring <atoms_frac> in input file'
    call param_get_block_length('atoms_cart', found2, i_temp2, lunits)
    if (found2 .and. library) write (stdout, '(a)') ' Ignoring <atoms_cart> in input file'
    if (.not. library) then
      if (found .and. found2) call io_error('Error: Cannot specify both atoms_frac and atoms_cart')
      if (found .and. i_temp > 0) then
        lunits = .false.
        num_atoms = i_temp
      elseif (found2 .and. i_temp2 > 0) then
        num_atoms = i_temp2
        if (lunits) num_atoms = num_atoms - 1
      end if
      if (num_atoms > 0) then
        call param_get_atoms(lunits)
      end if
    endif

    ! Projections
    auto_projections = .false.
    call param_get_keyword('auto_projections', found, l_value=auto_projections)
    num_proj = 0
    call param_get_block_length('projections', found, i_temp)
    ! check to see that there are no unrecognised keywords
    if (found) then
      if (auto_projections) call io_error('Error: Cannot specify both auto_projections and projections block')
      lhasproj = .true.
      call param_get_projections(num_proj, lcount=.true.)
    else
      if (guiding_centres .and. .not. (gamma_only .and. use_bloch_phases)) &
        call io_error('param_read: Guiding centres requested, but no projection block found')
      lhasproj = .false.
      num_proj = num_wann
    end if

    lselproj = .false.
    num_select_projections = 0
    call param_get_range_vector('select_projections', found, num_select_projections, lcount=.true.)
    if (found) then
      if (num_select_projections < 1) call io_error('Error: problem reading select_projections')
      if (allocated(select_projections)) deallocate (select_projections)
      allocate (select_projections(num_select_projections), stat=ierr)
      if (ierr /= 0) call io_error('Error allocating select_projections in param_read')
      call param_get_range_vector('select_projections', found, num_select_projections, .false., select_projections)
      if (any(select_projections < 1)) &
        call io_error('Error: select_projections must contain positive numbers')
      if (num_select_projections < num_wann) &
        call io_error('Error: too few projections selected')
      if (num_select_projections > num_wann) &
        call io_error('Error: too many projections selected')
      if (.not. lhasproj) &
        call io_error('Error: select_projections cannot be used without defining the projections')
      if (maxval(select_projections(:)) > num_proj) &
        call io_error('Error: select_projections contains a number greater than num_proj')
      lselproj = .true.
    end if

    if (allocated(proj2wann_map)) deallocate (proj2wann_map)
    allocate (proj2wann_map(num_proj), stat=ierr)
    if (ierr /= 0) call io_error('Error allocating proj2wann_map in param_read')
    proj2wann_map = -1

    if (lselproj) then
      do i = 1, num_proj
        do j = 1, num_wann
          if (select_projections(j) == i) proj2wann_map(i) = j
        enddo
      enddo
    else
      do i = 1, num_wann
        proj2wann_map(i) = i
      enddo
    endif

    if (lhasproj) call param_get_projections(num_proj, lcount=.false.)

    ! Constrained centres
    call param_get_block_length('slwf_centres', found, i_temp)
    if (found) then
      if (slwf_constrain) then
        ! Allocate array for constrained centres
        call param_get_centre_constraints
      else
        write (stdout, '(a)') ' slwf_constrain set to false. Ignoring <slwf_centres> block '
      end if
      ! Check that either projections or constrained centres are specified if slwf_constrain=.true.
    elseif (.not. found) then
      if (slwf_constrain) then
        if (.not. allocated(proj_site)) then
          call io_error('Error: slwf_constrain = true, but neither &
               & <slwf_centre> block  nor &
               & <projection_block> are specified.')
        else
          ! Allocate array for constrained centres
          call param_get_centre_constraints
        end if
      end if
    end if
    ! Warning
    if (slwf_constrain .and. allocated(proj_site) .and. .not. found) &
         & write (stdout, '(a)') ' Warning: No <slwf_centres> block found, but slwf_constrain set to true. &
           & Desired centres for SLWF same as projection centres.'

302 continue

    if (any(len_trim(in_data(:)) > 0)) then
      write (stdout, '(1x,a)') 'The following section of file '//trim(seedname)//'.win contained unrecognised keywords'
      write (stdout, *)
      do loop = 1, num_lines
        if (len_trim(in_data(loop)) > 0) then
          write (stdout, '(1x,a)') trim(in_data(loop))
        end if
      end do
      write (stdout, *)
      call io_error('Unrecognised keyword(s) in input file, see also output file')
    end if

    if (transport .and. tran_read_ht) goto 303

    ! For aesthetic purposes, convert some things to uppercase
    call param_uppercase()

303 continue

    deallocate (in_data, stat=ierr)
    if (ierr /= 0) call io_error('Error deallocating in_data in param_read')

    if (transport .and. tran_read_ht) return

    ! =============================== !
    ! Some checks and initialisations !
    ! =============================== !

!    if (restart.ne.' ') disentanglement=.false.

    if (disentanglement) then
      if (allocated(ndimwin)) deallocate (ndimwin)
      allocate (ndimwin(num_kpts), stat=ierr)
      if (ierr /= 0) call io_error('Error allocating ndimwin in param_read')
      if (allocated(lwindow)) deallocate (lwindow)
      allocate (lwindow(num_bands, num_kpts), stat=ierr)
      if (ierr /= 0) call io_error('Error allocating lwindow in param_read')
    endif

!    if ( wannier_plot .and. (index(wannier_plot_format,'cub').ne.0) ) then
!       cosa(1)=dot_product(real_lattice(1,:),real_lattice(2,:))
!       cosa(2)=dot_product(real_lattice(1,:),real_lattice(3,:))
!       cosa(3)=dot_product(real_lattice(2,:),real_lattice(3,:))
!       cosa = abs(cosa)
!       if (any(cosa.gt.eps6)) &
!            call io_error('Error: plotting in cube format requires orthogonal lattice vectors')
!    endif

    ! Initialise
    omega_total = -999.0_dp
    omega_tilde = -999.0_dp
    omega_invariant = -999.0_dp
    have_disentangled = .false.

    if (allocated(wannier_centres)) deallocate (wannier_centres)
    allocate (wannier_centres(3, num_wann), stat=ierr)
    if (ierr /= 0) call io_error('Error allocating wannier_centres in param_read')
    wannier_centres = 0.0_dp
    if (allocated(wannier_spreads)) deallocate (wannier_spreads)
    allocate (wannier_spreads(num_wann), stat=ierr)
    if (ierr /= 0) call io_error('Error in allocating wannier_spreads in param_read')
    wannier_spreads = 0.0_dp

    return

105 call io_error('Error: Problem opening eigenvalue file '//trim(seedname)//'.eig')
106 call io_error('Error: Problem reading eigenvalue file '//trim(seedname)//'.eig')

  end subroutine param_read