Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ __pycache__/
.vscode/
build/
dist/
*.egg-info/
*.egg-info/
.idea/
Empty file.
70 changes: 70 additions & 0 deletions molextract/rules/orca/general.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import re
from molextract.rule import Rule


class ORCADipoleMoment(Rule):
"""
Parses every "DIPOLE MOMENT" block in an ORCA .out/.log file.

A block with no "State:" line is the ground state (state=0).
A block with "State: N" is that excited state.
"""
_HEADER_RE = re.compile(r"DIPOLE MOMENT")
_STATE_RE = re.compile(r"State\s*:\s*(\d+)")
_VECTOR_RE = re.compile(
r"Total Dipole Moment\s*:\s*([-\d.]+)\s+([-\d.]+)\s+([-\d.]+)")
_MAGNITUDE_RE = re.compile(r"Magnitude \(Debye\)\s*:\s*([-\d.]+)")

def __init__(self):
super().__init__(start_tag=r".*",
end_tag=r"ORCA TERMINATED NORMALLY",
check_only_beginning=False)
self._results = []

def process_lines(self, start_line):
state = 0
magnitude = None
x = y = z = None
in_block = False

for line in self:
# Find the dipole moment block
if self._HEADER_RE.search(line):
in_block = True
magnitude = None
x = y = z = None
state = 0
continue

if not in_block:
continue

# Get the state value
state_match = self._STATE_RE.search(line)
if state_match:
state = int(state_match.group(1))
continue

# Get the x,y,z total dipole moment vector (in a.u.)
vector_match = self._VECTOR_RE.search(line)
if vector_match:
x, y, z = (float(v) for v in vector_match.groups())
continue

# Get the magnitude in Debye
mag_match = self._MAGNITUDE_RE.search(line)
if mag_match:
magnitude = float(mag_match.group(1))
self._results.append({
"state": state,
"total": magnitude,
"x": x,
"y": y,
"z": z,
})
in_block = False

def reset(self):
tmp = self._results.copy()
self._results.clear()
return tmp
69 changes: 69 additions & 0 deletions test/orca_rules_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
from molextract.rules.orca import general
from molextract.parser import Parser

ORCA_LOG = """**************

-------------
DIPOLE MOMENT
-------------

Method : SCF
Type of density : Electron Density
Multiplicity : 1
Irrep : 0
Energy : -153.9592467839026426 Eh
Relativity type :
Basis : AO
X Y Z
Electronic contribution: 3.030774285 0.000000001 1.409400234
Nuclear contribution : -4.096753110 0.000000000 -1.551790077
-----------------------------------------
Total Dipole Moment : -1.065978825 0.000000001 -0.142389843
-----------------------------------------
Magnitude (a.u.) : 1.075446755
Magnitude (Debye) : 2.733568410


-------------
DIPOLE MOMENT
-------------

Method : TD-DFT/RPA
Type of density : Electron Density
Level : Relaxed density
State : 1
Multiplicity : 1
Irrep : 0
Energy : 0.0000000000000000 Eh
Relativity type :
Basis : AO
X Y Z
Electronic contribution: 3.386122984 -0.000000001 1.463710336
Nuclear contribution : -4.096753110 0.000000000 -1.551790077
-----------------------------------------
Total Dipole Moment : -0.710630126 -0.000000001 -0.088079741
-----------------------------------------
Magnitude (a.u.) : 0.716067886
Magnitude (Debye) : 1.820099920

ORCA TERMINATED NORMALLY
"""


def test_dipole_moment():
parser = Parser(general.ORCADipoleMoment())
data = parser.feed(ORCA_LOG)

ground_state = data[0]
assert ground_state['state'] == 0
assert ground_state['total'] == 2.733568410
assert ground_state['x'] == -1.065978825
assert ground_state['y'] == 0.000000001
assert ground_state['z'] == -0.142389843

excited_state = data[1]
assert excited_state['state'] == 1
assert excited_state['total'] == 1.820099920
assert excited_state['x'] == -0.710630126
assert excited_state['y'] == -0.000000001
assert excited_state['z'] == -0.088079741
Loading