Skip to content

Commit

Permalink
Add support for totalCharge and totalSpinMultiplicity in CJSON (#51)
Browse files Browse the repository at this point in the history
  • Loading branch information
awvwgk authored Aug 1, 2022
1 parent abfbff1 commit 8fd9e43
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 7 deletions.
15 changes: 10 additions & 5 deletions src/mctc/io/read/cjson.F90
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ subroutine read_cjson(self, unit, error)
type(json_value), pointer :: root, val, child, array

logical :: cartesian, found
integer :: stat, schema_version, charge, ibond
integer :: stat, schema_version, charge, multiplicity, ibond
character(len=:), allocatable :: input, line, message, comment
integer, allocatable :: num(:), bond(:, :), list(:), order(:)
real(wp) :: cellpar(6)
Expand Down Expand Up @@ -156,9 +156,14 @@ subroutine read_cjson(self, unit, error)
end if

call json%get(val, "name", comment, default="")
call json%get(val, "atoms.formalCharges", list, found=found)
charge = 0
if (allocated(list)) charge = sum(list)
call json%get(val, "properties.totalCharge", charge, found=found)
if (.not.found) then
call json%get(val, "atoms.formalCharges", list, found=found)
charge = 0
if (allocated(list)) charge = sum(list)
end if
call json%get(val, "properties.totalSpinMultiplicity", multiplicity, found=found)
if (.not.found) multiplicity = 1

if (json%failed()) then
call json%check_for_errors(error_msg=message)
Expand All @@ -172,7 +177,7 @@ subroutine read_cjson(self, unit, error)
if (.not.cartesian) then
xyz(:, :) = matmul(lattice, xyz(:, :))
end if
call new(self, num, xyz, lattice=lattice, charge=real(charge, wp))
call new(self, num, xyz, lattice=lattice, charge=real(charge, wp), uhf=multiplicity - 1)
if (len(comment) > 0) self%comment = comment
if (allocated(bond)) then
self%nbd = size(bond, 2)
Expand Down
13 changes: 13 additions & 0 deletions src/mctc/io/write/cjson.f90
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,19 @@ pure function json_string(mol, indent) result(string)
if (present(indent)) string = string // nl // indent
string = string // "}"

string = string // ","
if (present(indent)) string = string // nl // indent
string = string // json_key("properties", indent) // "{"
if (present(indent)) string = string // nl // repeat(indent, 2)
string = string // json_key("totalCharge", indent) // json_value(nint(mol%charge))
if (mol%uhf > 0) then
string = string // ","
if (present(indent)) string = string // nl // repeat(indent, 2)
string = string // json_key("totalSpinMultiplicity", indent) // json_value(mol%uhf + 1)
end if
if (present(indent)) string = string // nl // indent
string = string // "}"

if (allocated(mol%bond)) then
string = string // ","
if (present(indent)) string = string // nl // indent
Expand Down
106 changes: 104 additions & 2 deletions test/test_read_cjson.f90
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ subroutine collect_read_cjson(testsuite)
& new_unittest("valid1-cjson", test_valid1_cjson, should_fail=.not.with_json), &
& new_unittest("valid2-cjson", test_valid2_cjson, should_fail=.not.with_json), &
& new_unittest("valid3-cjson", test_valid3_cjson, should_fail=.not.with_json), &
& new_unittest("valid4-cjson", test_valid3_cjson, should_fail=.not.with_json), &
& new_unittest("valid4-cjson", test_valid4_cjson, should_fail=.not.with_json), &
& new_unittest("valid5-cjson", test_valid5_cjson, should_fail=.not.with_json), &
& new_unittest("valid6-cjson", test_valid6_cjson, should_fail=.not.with_json), &
& new_unittest("invalid1-cjson", test_invalid1_cjson, should_fail=.true.), &
& new_unittest("invalid2-cjson", test_invalid2_cjson, should_fail=.true.), &
& new_unittest("invalid3-cjson", test_invalid3_cjson, should_fail=.true.), &
Expand Down Expand Up @@ -332,12 +334,112 @@ subroutine test_valid4_cjson(error)
if (allocated(error)) return
call check(error, struc%nid, 4, "Number of species does not match")
if (allocated(error)) return
call check(error, struc%nbd, 23, "Number of bonds does not match")
call check(error, struc%nbd, 25, "Number of bonds does not match")
if (allocated(error)) return

end subroutine test_valid4_cjson


subroutine test_valid5_cjson(error)

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

type(structure_type) :: struc
integer :: unit

open(status='scratch', newunit=unit)
write(unit, '(a)') &
'{', &
' "chemicalJson": 1,', &
' "atoms": {', &
' "elements": {', &
' "number": [', &
' 8,', &
' 1', &
' ]', &
' },', &
' "coords": {', &
' "3d": [', &
' 1.2358341722502633E+00,', &
' -9.1774253284895344E-02,', &
' -6.7936144993384059E-02,', &
' 1.5475582000473165E+00,', &
' 5.7192830956765273E-01,', &
' 5.5691301045614838E-01', &
' ]', &
' },', &
' "formalCharges": [ -1, 0 ]', &
' }', &
'}'
rewind(unit)

call read_cjson(struc, unit, error)
close(unit)
if (allocated(error)) return
call check(error, struc%nat, 2, "Number of atoms does not match")
if (allocated(error)) return
call check(error, struc%nid, 2, "Number of species does not match")
if (allocated(error)) return
call check(error, nint(struc%charge), -1, "Total charge does not match")
if (allocated(error)) return

end subroutine test_valid5_cjson


subroutine test_valid6_cjson(error)

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

type(structure_type) :: struc
integer :: unit

open(status='scratch', newunit=unit)
write(unit, '(a)') &
'{', &
' "chemicalJson": 1,', &
' "atoms": {', &
' "elements": {', &
' "number": [', &
' 7,', &
' 7,', &
' 7', &
' ]', &
' },', &
' "coords": {', &
' "3d": [', &
' 3.6361808414857721E-01,', &
' 1.9287266130863627E+00,', &
' -1.7850498831821635E+00,', &
' 8.2217629145179161E-01,', &
' 2.4066501990670561E+00,', &
' -2.7896663819784173E+00,', &
' -9.4568423260748616E-02,', &
' 1.4516946870018026E+00,', &
' -7.7682289506097102E-01', &
' ]', &
' }', &
' },', &
' "properties": {', &
' "totalCharge": -1', &
' }', &
'}'
rewind(unit)

call read_cjson(struc, unit, error)
close(unit)
if (allocated(error)) return
call check(error, struc%nat, 3, "Number of atoms does not match")
if (allocated(error)) return
call check(error, struc%nid, 1, "Number of species does not match")
if (allocated(error)) return
call check(error, nint(struc%charge), -1, "Total charge does not match")
if (allocated(error)) return

end subroutine test_valid6_cjson


subroutine test_invalid1_cjson(error)

!> Error handling
Expand Down

0 comments on commit 8fd9e43

Please sign in to comment.