Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
nomad-lab
parser-molcas
Commits
59e15aa7
Commit
59e15aa7
authored
Oct 14, 2016
by
Ask Hjorth Larsen
Browse files
parse basis type and eigenvalues/occupations
parent
b7cccee8
Changes
1
Hide whitespace changes
Inline
Side-by-side
parser/parser-molcas/main.py
View file @
59e15aa7
...
...
@@ -71,6 +71,8 @@ class MolcasContext(object):
self
.
last_line
=
None
self
.
current_module_name
=
None
self
.
section_refs
=
{}
self
.
basis_info
=
[]
self
.
buffered_lines
=
{}
def
onOpen_section_method
(
self
,
backend
,
gindex
,
section
):
self
.
section_refs
[
'method'
]
=
gindex
...
...
@@ -95,7 +97,84 @@ class MolcasContext(object):
backend
.
addValue
(
'single_configuration_calculation_to_system_ref'
,
self
.
section_refs
[
'system'
])
#print(self.buffered_lines.keys())
def
lines2arrays
(
name
):
elines
=
self
.
buffered_lines
.
pop
(
'energy_%s'
%
name
)
olines
=
self
.
buffered_lines
.
pop
(
'occupations_%s'
%
name
)
energies
=
[]
occupations
=
[]
assert
len
(
elines
)
==
len
(
olines
)
for
l1
,
l2
in
zip
(
elines
,
olines
):
energies
+=
l1
.
split
()[
1
:]
# Energy <numbers>
occupations
+=
l2
.
split
()[
2
:]
# Occ. No. <numbers>
assert
len
(
energies
)
==
len
(
occupations
)
energies
=
np
.
array
(
energies
).
astype
(
float
)
energies
=
convert_unit
(
energies
,
'hartree'
)
occupations
=
np
.
array
(
occupations
).
astype
(
float
)
# Sort by energy:
args
=
np
.
argsort
(
energies
)
energies
=
energies
[
args
]
occupations
=
occupations
[
args
]
return
energies
.
reshape
(
1
,
1
,
-
1
),
occupations
.
reshape
(
1
,
1
,
-
1
)
energies
=
None
try
:
energies
,
occupations
=
lines2arrays
(
'nospin'
)
nspins
=
1
nstates
=
energies
.
shape
[
-
1
]
except
KeyError
:
pass
try
:
ealpha
,
oalpha
=
lines2arrays
(
'alpha'
)
ebeta
,
obeta
=
lines2arrays
(
'beta'
)
except
KeyError
:
pass
else
:
# The spinup and spindown (alpha, beta)
# arrays can have different lengths
# so we must allocate arrays that are big enough
# and fill out with zeros or something else
assert
energies
is
None
nspins
=
2
nstates
=
max
(
ealpha
.
shape
[
-
1
],
ebeta
.
shape
[
-
1
])
energies
=
np
.
empty
((
nspins
,
1
,
nstates
))
# We will only fill out the values that we have.
# The rest will be nan:
energies
.
fill
(
np
.
nan
)
occupations
=
np
.
zeros
((
nspins
,
1
,
nstates
))
energies
[
0
,
:,
:
ealpha
.
shape
[
2
]]
=
ealpha
[
0
]
occupations
[
0
,
:,
:
ealpha
.
shape
[
2
]]
=
oalpha
[
0
]
energies
[
1
,
0
,
:
ebeta
.
shape
[
2
]]
=
ebeta
[
0
]
occupations
[
1
,
0
,
:
ebeta
.
shape
[
2
]]
=
obeta
[
0
]
if
energies
is
not
None
:
for
arr
in
[
energies
,
occupations
]:
assert
arr
.
shape
==
(
nspins
,
1
,
nstates
)
g
=
backend
.
openSection
(
'section_eigenvalues'
)
backend
.
addArrayValues
(
'eigenvalues_values'
,
energies
)
backend
.
addArrayValues
(
'eigenvalues_occupation'
,
occupations
)
backend
.
closeSection
(
'section_eigenvalues'
,
g
)
def
onClose_section_method
(
self
,
backend
,
gindex
,
section
):
for
line
in
self
.
basis_info
:
m
=
re
.
match
(
'\s*Basis set label:(.*?)\.(.*?)\s*$'
,
line
)
atomlabel
,
name
=
m
.
group
(
1
,
2
)
# The terrible syntax in molcas has a lot of dots everywhere.
# Replace sequences of dots with single dots to make things
# reasonable.
name
=
re
.
sub
(
r
'\.+'
,
'.'
,
name
).
strip
(
'.'
)
g
=
backend
.
openSection
(
'x_molcas_section_basis'
)
backend
.
addValue
(
'x_molcas_basis_atom_label'
,
atomlabel
)
backend
.
addValue
(
'x_molcas_basis_name'
,
name
)
backend
.
closeSection
(
'x_molcas_section_basis'
,
g
)
del
self
.
basis_info
[:]
#print('SECTION', section)
#methods = section['x_molcas_method']
xc
=
[]
...
...
@@ -163,6 +242,18 @@ class MolcasContext(object):
backend
.
addArrayValues
(
'atom_positions'
,
coords
)
backend
.
addArrayValues
(
'configuration_periodic_dimensions'
,
np
.
zeros
(
3
,
bool
))
def
adhoc_add_basis_set
(
self
,
parser
):
line
=
parser
.
fIn
.
readline
()
self
.
basis_info
.
append
(
line
)
def
adhoc_add_energies
(
self
,
parser
):
line
=
parser
.
fIn
.
readline
()
self
.
energies
.
append
(
line
)
def
adhoc_add_occupations
(
self
,
parser
):
line
=
parser
.
fIn
.
readline
()
self
.
occupations
.
append
(
line
)
# multi_sm copied from Siesta/GULP
def
multi_sm
(
self
,
name
,
startpattern
,
linepattern
,
endmatcher
=
None
,
conflict
=
'fail'
,
# 'fail', 'keep', 'overwrite'
...
...
@@ -343,10 +434,40 @@ def gateway_seward():
name
=
'gate/seward'
,
#r'\s*MOLCAS executing module (GATEWAY|SEWARD)', name='seward',
subMatchers
=
[
SM
(
r
'\s*Basis set label:(.*?)\s*$'
,
forwardMatch
=
True
,
repeats
=
True
,
adHoc
=
context
.
adhoc_add_basis_set
,
name
=
'basis'
),
get_system_sm
()
])
return
m
def
eigenvalue_line_matcher
(
pattern
,
spinname
):
class
AdHocLineAccumulator
:
def
__init__
(
self
,
var
):
self
.
var
=
var
def
__call__
(
self
,
parser
):
line
=
parser
.
fIn
.
readline
()
context
.
buffered_lines
.
setdefault
(
self
.
var
,
[]).
append
(
line
)
#print(context.buffered_lines)
#sdfkjsdfkj
m
=
SM
(
pattern
,
name
=
spinname
,
subMatchers
=
[
SM
(
r
'\s*Orbital'
,
repeats
=
True
,
subMatchers
=
[
SM
(
r
'\s*Energy\s*(.*)'
,
name
=
'energies'
,
adHoc
=
AdHocLineAccumulator
(
'energy_%s'
%
spinname
),
forwardMatch
=
True
),
SM
(
r
'\s*Occ\. No\.\s*(.*)'
,
name
=
'occ'
,
adHoc
=
AdHocLineAccumulator
(
'occupations_%s'
%
spinname
),
forwardMatch
=
True
)
])
])
return
m
def
scf_rasscf
():
m
=
SM
(
mod_pattern
(
r
'(:?ras)?scf'
),
name
=
'(ras)scf'
,
#r'(?:ras)?scf', r'\s*MOLCAS executing module (?:SCF|RASSCF)', name='scf',
...
...
@@ -358,10 +479,21 @@ def scf_rasscf():
SM
(
r
'\s*CI only, no orbital optimization'
,
sections
=
[
'section_method'
],
fixedStartValues
=
{
'x_molcas_method_name'
:
'RAS-CI'
}),
SM
(
r
'\s*Total SCF energy\s*(?P<energy_total__hartree>\S+)'
,
name
=
'E-tot'
,
sections
=
[
'section_single_configuration_calculation'
]),
SM
(
r
'\s*RASSCF root number\s*\d+\s*Total energy\s*=\s*(?P<energy_total__hartree>\S+)'
,
name
=
'E-ras'
,
sections
=
[
'section_single_configuration_calculation'
]),
SM
(
r
'\s*\*\s*Final Results\s*\*'
,
name
=
'finalresults'
,
sections
=
[
'section_single_configuration_calculation'
],
subMatchers
=
[
SM
(
r
'\s*Total \S+ energy\s*(?P<energy_total__hartree>\S+)'
,
name
=
'E-tot'
),
SM
(
r
'\s*RASSCF root number\s*\d+\s*Total energy\s*=\s*(?P<energy_total__hartree>\S+)'
,
name
=
'E-ras'
),
SM
(
r
'\s*Molecular orbitals:'
,
name
=
'mol-orb'
,
endReStr
=
r
'\s*Molecular Charges:'
,
subMatchers
=
[
eigenvalue_line_matcher
(
r
'\s*Title:\s*.*?\s*orbitals\s*$'
,
'nospin'
),
eigenvalue_line_matcher
(
r
'\s*Title:\s*.*?\s*orbitals\s*\(alpha\)'
,
'alpha'
),
eigenvalue_line_matcher
(
r
'\s*Title:\s*.*?\s*orbitals\s*\(beta\)'
,
'beta'
)
])
])
])
return
m
...
...
@@ -390,6 +522,14 @@ def molcas_main_loop_sm():
# Sometimes the damn thing starts without a proper header!! ARGH!
r
's*Specification of the internal coordinates according to the user-defined'
),
name
=
'slapaf'
,
# The slapaf module writes forces, but only for a symmetry-reduced set of atoms.
# Therefore they are not useful to parse. We could parse the set of symmetries probably
# and somehow make it possible to get the full set of Cartesian forces,
# but the operation would be very complicated.
#
# Let us consider parsing the reduced forces and
# symmetries the day that someone wants to implement
# this symmetry-unreduction (this will not happen).
subMatchers
=
[
SM
(
r
'\*\s*Energy Statistics for Geometry Optimization'
,
name
=
'opt-loop'
,
...
...
@@ -398,7 +538,12 @@ def molcas_main_loop_sm():
subMatchers
=
[
SM
(
r
'\s*\d+\s*\S+\s*'
,
name
=
'opt-iter'
,
repeats
=
True
,
forwardMatch
=
True
,
adHoc
=
context
.
adhoc_store_line
),
SM
(
r
'\s*$'
,
forwardMatch
=
True
,
adHoc
=
context
.
adhoc_pushback_last
,
name
=
'pushback'
),
SM
(
r
'\s*\d+\s*(?P<energy_total__hartree>\S+)\s*'
,
name
=
'opt-iter'
,
repeats
=
True
),
# Molcas is supposed to have spaces between the numbers, but with grdNorm/Max,
# it sometimes writes 0.051834-0.037589 in one. Thus we use -?[^\s-]+ to match such a number.
SM
(
r
'\s*\d+\s*(?P<energy_total__hartree>\S+)\s*'
r
'\S+\s*(?P<x_molcas_slapaf_grad_norm>-?[^\s-]+)\s*'
r
'(?P<x_molcas_slapaf_grad_max>\S+)'
,
name
=
'opt-iter'
,
repeats
=
True
),
]),
SM
(
r
'\s*\*\s*Nuclear coordinates for the next iteration / Bohr'
,
endReStr
=
r
'\s*$'
,
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment