Skip to content

Commit a54a7ab

Browse files
authored
Merge pull request #90 from haidi-ustc/devel
support fhi-amis
2 parents b56f202 + 639d101 commit a54a7ab

15 files changed

+3785
-1
lines changed

dpdata/fhi_aims/__init__.py

Whitespace-only changes.

dpdata/fhi_aims/output.py

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
import numpy as np
2+
import re
3+
4+
latt_patt="\|\s+([0-9]{1,}[.][0-9]*)\s+([0-9]{1,}[.][0-9]*)\s+([0-9]{1,}[.][0-9]*)"
5+
pos_patt_first="\|\s+[0-9]{1,}[:]\s\w+\s(\w+)(\s.*[-]?[0-9]{1,}[.][0-9]*)(\s+[-]?[0-9]{1,}[.][0-9]*)(\s+[-]?[0-9]{1,}[.][0-9]*)"
6+
pos_patt_other="\s+[a][t][o][m]\s+([-]?[0-9]{1,}[.][0-9]*)\s+([-]?[0-9]{1,}[.][0-9]*)\s+([-]?[0-9]{1,}[.][0-9]*)\s+(\w{1,2})"
7+
force_patt="\|\s+[0-9]{1,}\s+([-]?[0-9]{1,}[.][0-9]*[E][+-][0-9]{1,})\s+([-]?[0-9]{1,}[.][0-9]*[E][+-][0-9]{1,})\s+([-]?[0-9]{1,}[.][0-9]*[E][+-][0-9]{1,})"
8+
eng_patt="Total energy uncorrected.*([-]?[0-9]{1,}[.][0-9]*[E][+-][0-9]{1,})\s+eV"
9+
#atom_numb_patt="Number of atoms.*([0-9]{1,})"
10+
11+
def get_info (lines, type_idx_zero = False) :
12+
13+
atom_types = []
14+
atom_names = []
15+
cell = []
16+
atom_numbs = None
17+
_atom_names = []
18+
19+
contents="\n".join(lines)
20+
#cell
21+
#_tmp=re.findall(latt_patt,contents)
22+
#for ii in _tmp:
23+
# vect=[float(kk) for kk in ii]
24+
# cell.append(vect)
25+
#------------------
26+
for ln,l in enumerate(lines):
27+
if l.startswith(' | Unit cell'):
28+
break
29+
_tmp=lines[ln+1:ln+4]
30+
for ii in _tmp:
31+
v_str=ii.split('|')[1].split()
32+
vect=[float(kk) for kk in v_str]
33+
cell.append(vect)
34+
# print(cell)
35+
#atom name
36+
_tmp=re.findall(pos_patt_first,contents)
37+
for ii in _tmp:
38+
_atom_names.append(ii[0])
39+
atom_names=[]
40+
for ii in _atom_names:
41+
if not ii in atom_names:
42+
atom_names.append(ii)
43+
#atom number
44+
#_atom_numb_patt=re.compile(atom_numb_patt)
45+
atom_numbs =[_atom_names.count(ii) for ii in atom_names]
46+
assert(atom_numbs is not None), "cannot find ion type info in aims output"
47+
48+
for idx,ii in enumerate(atom_numbs) :
49+
for jj in range(ii) :
50+
if type_idx_zero :
51+
atom_types.append(idx)
52+
else :
53+
atom_types.append(idx+1)
54+
55+
return [cell, atom_numbs, atom_names, atom_types ]
56+
57+
58+
def get_fhi_aims_block(fp) :
59+
blk = []
60+
for ii in fp :
61+
if not ii :
62+
return blk
63+
blk.append(ii.rstrip('\n'))
64+
if 'Begin self-consistency loop: Re-initialization' in ii:
65+
return blk
66+
return blk
67+
68+
def get_frames (fname, md=True, begin = 0, step = 1) :
69+
fp = open(fname)
70+
blk = get_fhi_aims_block(fp)
71+
ret = get_info(blk, type_idx_zero = True)
72+
73+
cell, atom_numbs, atom_names, atom_types =ret[0],ret[1],ret[2],ret[3]
74+
ntot = sum(atom_numbs)
75+
76+
all_coords = []
77+
all_cells = []
78+
all_energies = []
79+
all_forces = []
80+
all_virials = []
81+
82+
cc = 0
83+
while len(blk) > 0 :
84+
# with open(str(cc),'w') as f:
85+
# f.write('\n'.join(blk))
86+
if cc >= begin and (cc - begin) % step == 0 :
87+
if cc==0:
88+
coord, _cell, energy, force, virial, is_converge = analyze_block(blk, first_blk=True, md=md)
89+
else:
90+
coord, _cell, energy, force, virial, is_converge = analyze_block(blk, first_blk=False)
91+
if is_converge :
92+
if len(coord) == 0:
93+
break
94+
all_coords.append(coord)
95+
96+
if _cell:
97+
all_cells.append(_cell)
98+
else:
99+
all_cells.append(cell)
100+
101+
all_energies.append(energy)
102+
all_forces.append(force)
103+
if virial is not None :
104+
all_virials.append(virial)
105+
blk = get_fhi_aims_block(fp)
106+
cc += 1
107+
108+
if len(all_virials) == 0 :
109+
all_virials = None
110+
else :
111+
all_virials = np.array(all_virials)
112+
fp.close()
113+
return atom_names, atom_numbs, np.array(atom_types), np.array(all_cells), np.array(all_coords), np.array(all_energies), np.array(all_forces), all_virials
114+
115+
116+
def analyze_block(lines, first_blk=False, md=True) :
117+
coord = []
118+
cell = []
119+
energy = None
120+
force = []
121+
virial = None
122+
atom_names=[]
123+
_atom_names=[]
124+
125+
contents="\n".join(lines)
126+
try:
127+
natom=int(re.findall("Number of atoms.*([0-9]{1,})",lines)[0])
128+
except:
129+
natom=0
130+
131+
if first_blk:
132+
133+
if md:
134+
_tmp=re.findall(pos_patt_other,contents)[:]
135+
for ii in _tmp[slice(int(len(_tmp)/2),len(_tmp))]:
136+
coord.append([float(kk) for kk in ii[:-1]])
137+
else:
138+
_tmp=re.findall(pos_patt_first,contents)
139+
for ii in _tmp:
140+
coord.append([float(kk) for kk in ii[1:]])
141+
else:
142+
_tmp=re.findall(pos_patt_other,contents)
143+
for ii in _tmp:
144+
coord.append([float(kk) for kk in ii[:-1]])
145+
146+
_tmp=re.findall(force_patt,contents)
147+
for ii in _tmp:
148+
force.append([float(kk) for kk in ii])
149+
150+
if "Self-consistency cycle converged" in contents:
151+
is_converge=True
152+
else:
153+
is_converge=False
154+
155+
try:
156+
_eng_patt=re.compile(eng_patt)
157+
energy=float(_eng_patt.search(contents).group().split()[-2])
158+
except:
159+
energy=None
160+
161+
if not energy:
162+
is_converge = False
163+
164+
if energy:
165+
assert((force is not None) and len(coord) > 0 )
166+
167+
return coord, cell, energy, force, virial, is_converge
168+
169+
if __name__=='__main__':
170+
import sys
171+
ret=get_frames (sys.argv[1], begin = 0, step = 1)
172+
print(ret)

dpdata/system.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from dpdata.cp2k.output import Cp2kSystems
2222
import dpdata.pwmat.movement
2323
import dpdata.pwmat.atomconfig
24+
import dpdata.fhi_aims.output
2425
from copy import deepcopy
2526
from monty.json import MSONable
2627
from monty.serialization import loadfn,dumpfn
@@ -1030,6 +1031,34 @@ def from_cp2k_aimd_output(self, file_dir):
10301031
l = LabeledSystem(data=info_dict)
10311032
self.append(l)
10321033

1034+
@register_from_funcs.register_funcs('fhi_aims/md')
1035+
def from_fhi_aims_output(self, file_name, md=True, begin=0, step =1):
1036+
self.data['atom_names'], \
1037+
self.data['atom_numbs'], \
1038+
self.data['atom_types'], \
1039+
self.data['cells'], \
1040+
self.data['coords'], \
1041+
self.data['energies'], \
1042+
self.data['forces'], \
1043+
tmp_virial, \
1044+
= dpdata.fhi_aims.output.get_frames(file_name, md = md, begin = begin, step = step)
1045+
if tmp_virial is not None :
1046+
self.data['virials'] = tmp_virial
1047+
1048+
@register_from_funcs.register_funcs('fhi_aims/scf')
1049+
def from_fhi_aims_output(self, file_name ):
1050+
self.data['atom_names'], \
1051+
self.data['atom_numbs'], \
1052+
self.data['atom_types'], \
1053+
self.data['cells'], \
1054+
self.data['coords'], \
1055+
self.data['energies'], \
1056+
self.data['forces'], \
1057+
tmp_virial, \
1058+
= dpdata.fhi_aims.output.get_frames(file_name, md = False, begin = 0, step = 1)
1059+
if tmp_virial is not None :
1060+
self.data['virials'] = tmp_virial
1061+
10331062
@register_from_funcs.register_funcs('xml')
10341063
@register_from_funcs.register_funcs('vasp/xml')
10351064
def from_vasp_xml(self, file_name, begin = 0, step = 1) :

setup.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,19 @@
2424
long_description=readme,
2525
long_description_content_type="text/markdown",
2626
url="https://github.com/deepmodeling/dpdata",
27-
packages=['dpdata', 'dpdata/vasp', 'dpdata/lammps', 'dpdata/md', 'dpdata/deepmd', 'dpdata/qe', 'dpdata/siesta', 'dpdata/gaussian', 'dpdata/cp2k','dpdata/xyz','dpdata/pwmat', 'dpdata/amber'],
27+
packages=['dpdata',
28+
'dpdata/vasp',
29+
'dpdata/lammps',
30+
'dpdata/md',
31+
'dpdata/deepmd',
32+
'dpdata/qe',
33+
'dpdata/siesta',
34+
'dpdata/gaussian',
35+
'dpdata/cp2k',
36+
'dpdata/xyz',
37+
'dpdata/pwmat',
38+
'dpdata/amber',
39+
'dpdata/fhi_aims'],
2840
package_data={'dpdata':['*.json']},
2941
classifiers=[
3042
"Programming Language :: Python :: 3.6",

0 commit comments

Comments
 (0)