read_qcschema Subroutine

public subroutine read_qcschema(self, unit, error)

Arguments

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

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_qcschema(self, unit, error)

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

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

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

#if WITH_JSON
   type(json_core) :: json
   type(json_value), pointer :: root, val, child, array

   integer :: stat, schema_version, charge, multiplicity, ibond
   character(len=:), allocatable :: input, line, message, schema_name, comment
   character(len=symbol_length), allocatable :: sym(:)
   integer, allocatable :: bond(:, :), list(:)
   real(wp), allocatable, target :: geo(:)
   real(wp), pointer :: xyz(:, :)

   stat = 0
   input = ""
   do
      call getline(unit, line, stat)
      if (stat /= 0) exit
      input = input // line
   end do

   call json%deserialize(root, input)
   if (json%failed()) then
      call json%check_for_errors(error_msg=message)
      call fatal_error(error, message)
      call json%destroy(root)
      return
   end if
   val => root

   call json%get(val, "schema_version", schema_version, default=2)
   call json%get(val, "schema_name", schema_name, default="qcschema_molecule")

   if (schema_name /= "qcschema_molecule" .and. schema_name /= "qcschema_input" &
      & .or. json%failed()) then
      call fatal_error(error, "Invalid schema name '"//schema_name//"'")
      call json%destroy(root)
      return
   end if

   if (schema_name == "qcschema_input") then
      select case(schema_version)
      case(1)
         call json%get(val, "molecule", child)
      case default
         call fatal_error(error, "Unsupported schema version for 'qcschema_input'")
         call json%destroy(root)
         return
      end select
      call json%get(child, "schema_version", schema_version, default=2)
      call json%get(child, "schema_name", schema_name, default="qcschema_molecule")

      if (schema_name /= "qcschema_molecule" .or. json%failed()) then
         call fatal_error(error, "Invalid schema name '"//schema_name//"'")
         call json%destroy(root)
         return
      end if

      val => child
   end if

   select case(schema_version)
   case(1)
      call json%get(val, "molecule", child)
   case(2)
      child => val
   case default
      call fatal_error(error, "Unsupported schema version for 'qcschema_molecule'")
      call json%destroy(root)
      return
   end select

   call json%get(child, "symbols", sym)
   if (.not.allocated(sym) .or. json%failed()) then
      call fatal_error(error, "List of atomic symbols must be provided")
      call json%destroy(root)
      return
   end if
   call json%get(child, "geometry", geo)
   if (.not.allocated(geo) .or. json%failed()) then
      call fatal_error(error, "Cartesian coordinates must be provided")
      call json%destroy(root)
      return
   end if

   if (3*size(sym) /= size(geo)) then
      call fatal_error(error, "Number of symbols and coordinate triples must match")
      call json%destroy(root)
      return
   end if

   call json%get(child, "comment", comment, default="")
   call json%get(child, "molecular_charge", charge, default=0)
   call json%get(child, "molecular_multiplicity", multiplicity, default=1)

   if (json%failed()) then
      call json%check_for_errors(error_msg=message)
      call fatal_error(error, message)
      call json%destroy(root)
      return
   end if

   call json%get_child(child, "connectivity", array)
   if (associated(array)) then
      allocate(bond(3, json%count(array)))
      do ibond = 1, size(bond, 2)
         call json%get_child(array, ibond, child)
         call json%get(child, "", list)
         if (allocated(list)) then
            bond(:, ibond) = [list(1)+1, list(2)+1, list(3)]
         end if
      end do

      if (json%failed()) then
         call json%check_for_errors(error_msg=message)
         call fatal_error(error, message)
         call json%destroy(root)
         return
      end if
   end if

   xyz(1:3, 1:size(geo)/3) => geo
   call new(self, sym, xyz, charge=real(charge, wp), uhf=multiplicity-1)
   if (len(comment) > 0) self%comment = comment
   if (allocated(bond)) then
      self%nbd = size(bond, 2)
      call move_alloc(bond, self%bond)
   end if

   call json%destroy(root)
#else
   call fatal_error(error, "JSON support not enabled")
#endif
end subroutine read_qcschema