read_qchem Subroutine

public subroutine read_qchem(mol, unit, error)

Arguments

Type IntentOptional Attributes Name
type(structure_type), intent(out) :: mol

Instance of the molecular structure data

integer, intent(in) :: unit

File handle

type(error_type), intent(out), allocatable :: error

Error handling


Source Code

subroutine read_qchem(mol, unit, error)

   !> Instance of the molecular structure data
   type(structure_type), intent(out) :: mol

   !> File handle
   integer, intent(in) :: unit

   !> Error handling
   type(error_type), allocatable, intent(out) :: error

   integer :: stat, pos, lnum, izp, iat
   integer :: charge, multiplicity
   type(token_type) :: token
   character(len=:), allocatable :: line
   real(wp) :: x, y, z
   character(len=symbol_length), allocatable :: sym(:)
   real(wp), allocatable :: xyz(:, :), abc(:, :), lattice(:, :)
   logical :: is_frac, periodic(3)

   iat = 0
   lnum = 0
   stat = 0

   do while(stat == 0)
      call next_line(unit, line, pos, lnum, stat)
      if (stat /= 0) exit

      call next_token(line, pos, token)
      if (token%first > len(line)) cycle
      if (to_lower(line(token%first:token%last)) == '$molecule') exit
   end do

   if (stat /= 0) then
      call io_error(error, "No atoms found", &
         & line, token_type(0, 0), filename(unit), lnum+1, "expected molecule block")
      return
   end if

   call next_line(unit, line, pos, lnum, stat)
   if (stat == 0) &
      call read_next_token(line, pos, token, charge, stat)
   if (stat == 0) &
      call read_next_token(line, pos, token, multiplicity, stat)
   if (stat /= 0) then
      call io_error(error, "Failed to read charge and multiplicity", &
         & line, token, filename(unit), lnum, "expected integer value")
      return
   end if

   allocate(sym(initial_size), source=repeat(' ', symbol_length))
   allocate(xyz(3, initial_size), source=0.0_wp)

   do while(stat == 0)
      call next_line(unit, line, pos, lnum, stat)
      if (stat /= 0) exit

      call next_token(line, pos, token)
      if (to_lower(line(token%first:token%last)) == '$end') exit

      if (iat >= size(sym)) call resize(sym)
      if (iat >= size(xyz, 2)) call resize(xyz)
      iat = iat + 1

      token%last = min(token%last, token%first + symbol_length - 1)
      sym(iat) = line(token%first:token%last)
      if (to_number(sym(iat)) == 0) then
         call read_token(line, token, izp, stat)
         sym(iat) = to_symbol(izp)
      end if
      if (stat /= 0) then
         call io_error(error, "Cannot map symbol to atomic number", &
            & line, token, filename(unit), lnum, "unknown element")
         return
      end if

      call read_next_token(line, pos, token, x, stat)
      if (stat == 0) &
         call read_next_token(line, pos, token, y, stat)
      if (stat == 0) &
         call read_next_token(line, pos, token, z, stat)
      if (stat /= 0) then
         call io_error(error, "Cannot read coordinates", &
            & line, token, filename(unit), lnum, "expected real value")
         return
      end if

      xyz(:, iat) = [x, y, z] * aatoau
   end do

   if (stat /= 0) then
      call io_error(error, "Failed to read molecule block", &
         & line, token_type(0, 0), filename(unit), lnum, "unexpected end of input")
      return
   end if

   call new(mol, sym(:iat), xyz, charge=real(charge, wp), uhf=multiplicity-1)
end subroutine read_qchem