From 71c08a9417e75d223c9387cd75ebcde407bf2d53 Mon Sep 17 00:00:00 2001 From: Sebastian Ehlert <28669218+awvwgk@users.noreply.github.com> Date: Mon, 1 Aug 2022 10:08:02 +0200 Subject: [PATCH 1/2] Add support for totalCharge and totalSpinMultiplicity in CJSON --- src/mctc/io/read/cjson.F90 | 15 ++++++++++----- src/mctc/io/write/cjson.f90 | 13 +++++++++++++ 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/mctc/io/read/cjson.F90 b/src/mctc/io/read/cjson.F90 index ff23cd40..0db802ef 100644 --- a/src/mctc/io/read/cjson.F90 +++ b/src/mctc/io/read/cjson.F90 @@ -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) @@ -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) @@ -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) diff --git a/src/mctc/io/write/cjson.f90 b/src/mctc/io/write/cjson.f90 index 1e5483eb..25de9f63 100644 --- a/src/mctc/io/write/cjson.f90 +++ b/src/mctc/io/write/cjson.f90 @@ -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 From 653b8647395dd2dabe07cce68d37efd46a1c702e Mon Sep 17 00:00:00 2001 From: Sebastian Ehlert <28669218+awvwgk@users.noreply.github.com> Date: Mon, 1 Aug 2022 11:08:15 +0200 Subject: [PATCH 2/2] Add additional tests --- test/test_read_cjson.f90 | 106 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 104 insertions(+), 2 deletions(-) diff --git a/test/test_read_cjson.f90 b/test/test_read_cjson.f90 index 972454d7..48c22832 100644 --- a/test/test_read_cjson.f90 +++ b/test/test_read_cjson.f90 @@ -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.), & @@ -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