Skip to content

Commit

Permalink
Add delocalised coordinates parsers
Browse files Browse the repository at this point in the history
  • Loading branch information
oerc0122 committed Oct 9, 2024
1 parent f97ebc4 commit e5b36ed
Show file tree
Hide file tree
Showing 3 changed files with 147 additions and 13 deletions.
100 changes: 100 additions & 0 deletions castep_outputs/parsers/castep_file_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,14 @@
CellInfo,
CharTable,
ConstraintsReport,
DelocActiveSpace,
DelocInternalsTable,
DipoleTable,
ElasticProperties,
FinalConfig,
GeomTable,
InitialSpin,
InternalConstraints,
KPointsList,
KPointsSpec,
MDInfo,
Expand Down Expand Up @@ -1079,6 +1082,38 @@ def parse_castep_file(castep_file_in: TextIO,

curr_run["minimisation"].append(_process_geom_table(block))

# GeomOpt Deloc

elif block := Block.from_re(line, castep_file,
"INTERNAL CONSTRAINTS", REs.EMPTY, n_end=2):

if Filters.GEOM_OPT not in to_parse:
continue

curr_run["internal_constraints"] = _process_internal_constraints(block)

elif block := Block.from_re(line, castep_file,
"Message: Generating deloc", "Message: Generation of deloc"):

if Filters.GEOM_OPT not in to_parse:
continue

if "delocalised_internal" not in curr_run:
curr_run["delocalised_internal"] = {}

curr_run["delocalised_internal"].update(_process_deloc_table(block))

elif block := Block.from_re(line, castep_file,
"The size of active space", REs.EMPTY):

if Filters.GEOM_OPT not in to_parse:
continue

if "delocalised_internal" not in curr_run:
curr_run["delocalised_internal"] = {}

curr_run["delocalised_internal"].update(_process_deloc_act_space_table(block))

# TDDFT
elif block := Block.from_re(line, castep_file,
gen_table_re("TDDFT excitation energies", r"\+", post="TDDFT"),
Expand Down Expand Up @@ -2380,3 +2415,68 @@ def _process_elastic_properties(block: Block) -> ElasticProperties:
)

return accum


def _process_internal_constraints(block: TextIO) -> list[InternalConstraints]:

# Skip table headers
for _ in zip(range(3), block):
pass

accum = []
for line in block:
if not line.strip():
continue

_, type_, target, actual, *definitions = line.split()
if actual == "Satisfied":
target, actual = actual, target
else:
target = float(target)
actual = float(actual)

definitions = " ".join(definitions).split(")")
const = {val[0]: tuple(val[1:])
for definition in definitions
if definition and
(val := to_type(get_numbers(definition), int))}
assert type_ in ("Bond", "Angle", "Torsion")

elem: InternalConstraints = {"type": type_,
"target": target,
"actual": actual,
"constraints": const}
accum.append(elem)

return accum


def _process_deloc_table(block: TextIO) -> DelocInternalsTable:

accum: DelocInternalsTable = {"constraint_mapping": {}}
for line in block:
if line.startswith(" constraint"):
key, val = to_type(get_numbers(line), int)
accum["constraint_mapping"][key] = val
elif line.startswith("Total number of primitive"):
type_, val = line.split()[4:6]
type_ = "num_" + type_.strip(":")
val = int(val)

accum[type_] = val

return accum


def _process_deloc_act_space_table(block: TextIO) -> DelocActiveSpace:

accum = {}
for line in block:
if "active space" in line:
accum["active_space_size"] = to_type(get_numbers(line)[0], int)
if "degrees" in line:
accum["num_dof"] = to_type(get_numbers(line)[0], int)
if "primitive" in line:
accum["num_primitive_internals"] = to_type(get_numbers(line)[0], int)

return accum
40 changes: 27 additions & 13 deletions castep_outputs/test/test_castep_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -2720,10 +2720,29 @@ def test_get_deloc_info(self):
Message: Generation of delocalized internals is successful
""")
self.skipTest("Not implemented yet")
test_dict = parse_castep_file(test_text)[0]
pprint.pprint(test_dict)
self.assertEqual(test_dict, {})

self.assertEqual(test_dict, {'delocalised_internal':
{'constraint_mapping': {1: 15,
2: 43},
'num_angles': 48,
'num_bonds': 16,
'num_dihedrals': 144,
'num_internals': 208},
'internal_constraints': [
{'actual': 2.36,
'constraints': {4: (0, 0, 0),
5: (0, 0, -1)},
'target': 'Satisfied',
'type': 'Bond'},
{'actual': 109.47,
'constraints': {2: (1, 0, 0),
3: (0, 0, 0),
5: (0, 0, 0)},
'target': 'Satisfied',
'type': 'Angle'}
]
})

def test_get_deloc_step(self):
test_text = io.StringIO("""
Expand All @@ -2734,18 +2753,13 @@ def test_get_deloc_step(self):
There are : 24 degrees of freedom
There are : 67 primitive internals
INTERNAL CONSTRAINTS
# Type Target Actual Definition
1 Bond 2.360 Satisfied 4 ( 0 0 0) 5 ( 0 0-1)
2 Angle 109.47 Satisfied 3 ( 0 0 0) 5 ( 0 0 0) 2 ( 1 0 0)
""")
self.skipTest("Not implemented yet")

test_dict = parse_castep_file(test_text)[0]
pprint.pprint(test_dict)
self.assertEqual(test_dict, {})

self.assertEqual(test_dict, {'delocalised_internal': {'active_space_size': 19,
'num_dof': 24,
'num_primitive_internals': 67}})

def test_get_tss_structure(self):
test_text = io.StringIO("""
Expand Down
20 changes: 20 additions & 0 deletions castep_outputs/utilities/datatypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,26 @@ class GeomTable(TypedDict):
dr_max: GeomTableElem


class InternalConstraints(TypedDict):
type: Literal["Bond", "Angle", "Torsion"]
actual: float
target: Literal["Satisfied"] | float
constraints: dict[int, ThreeVector]


class DelocInternalsTable(TypedDict):
num_bonds: int
num_angles: int
num_dihedrals: int
num_internals: int
contraints: dict[int, int]


class DelocActiveSpace(TypedDict):
num_dof: int
num_primitive_internals: int
active_space_size: int

# Dipole

class DipoleTable(TypedDict):
Expand Down

0 comments on commit e5b36ed

Please sign in to comment.