Skip to content

Commit 0fcc136

Browse files
authored
Merge pull request #77 from WardLT/outcar_bugfix
Outcar bugfix
2 parents 1e95421 + d183c58 commit 0fcc136

File tree

3 files changed

+49
-42
lines changed

3 files changed

+49
-42
lines changed

dfttopif/parsers/base.py

-25
Original file line numberDiff line numberDiff line change
@@ -109,31 +109,6 @@ def get_result_functions(self):
109109
'Stresses': 'get_stresses'
110110
}
111111

112-
def _call_ase(self, func, directory):
113-
'''Make a call to an ASE function.
114-
115-
Note: I'm about to kill this function, once I'm done with the overhaul
116-
ASE assumes filenames, which we do not want
117-
118-
Handles changing directories
119-
120-
Returns: Result of ASE function
121-
'''
122-
# Change directories
123-
old_path = os.getcwd()
124-
os.chdir(directory)
125-
126-
# Call function
127-
try:
128-
res = func()
129-
except:
130-
os.chdir(old_path)
131-
raise
132-
133-
# Change back
134-
os.chdir(old_path)
135-
return res
136-
137112
def get_name(self):
138113
'''Get the name of this program'''
139114
raise NotImplementedError

dfttopif/parsers/vasp.py

+41-14
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
from .base import DFTParser, Value_if_true, InvalidIngesterException
44
import os
5-
from ase.calculators.vasp import Vasp
6-
from ase.io.vasp import read_vasp, read_vasp_out
5+
import re
6+
from ase.io.vasp import read_vasp_out
77
from pypif.obj import Value, FileReference
88
from dftparse.vasp.outcar_parser import OutcarParser
99
from dftparse.vasp.eigenval_parser import EigenvalParser
@@ -26,7 +26,7 @@ def _find_file(name):
2626
for f in self._files:
2727
if os.path.basename(f).upper().startswith(name):
2828
if my_file is not None:
29-
raise InvalidIngesterException('Found more than one %s file'.format(name))
29+
raise InvalidIngesterException('Found more than one {} file'.format(name))
3030
my_file = f
3131
return my_file
3232
self.outcar = _find_file('OUTCAR')
@@ -121,7 +121,6 @@ def get_xc_functional(self):
121121
if "TITEL" in line:
122122
words = line.split()
123123
return Value(scalars=[Scalar(value=words[2])])
124-
break
125124

126125
def get_pp_name(self):
127126
# Open up the OUTCAR
@@ -135,10 +134,7 @@ def get_pp_name(self):
135134
words = line.split()
136135
pp.append(words[3])
137136
return Value(vectors=[[Scalar(value=x) for x in pp]])
138-
139-
# Error handling: TITEL not found
140-
raise Exception('TITEL not found')
141-
137+
142138
def get_KPPRA(self):
143139
# Open up the OUTCAR
144140
with open(self.outcar) as fp:
@@ -167,15 +163,46 @@ def get_KPPRA(self):
167163
else:
168164
return Value(scalars=[Scalar(value=NI*NIRK)])
169165

170-
171-
# Error handling: NKPTS or NIONS not found
172-
raise Exception('NIONS, irredicuble or Coordinates not found')
173-
174166
def _is_converged(self):
175-
return self._call_ase(Vasp().read_convergence, os.path.dirname(self.outcar))
167+
# Follows the procedure used by qmpy, but without reading the whole file into memory
168+
# Source: https://github.com/wolverton-research-group/qmpy/blob/master/qmpy/analysis/vasp/calculation.py
169+
170+
with open(self.outcar) as fp:
171+
# Part 1: Determine the NELM
172+
nelm = None
173+
for line in fp:
174+
if line.startswith(" NELM ="):
175+
nelm = int(line.split()[2][:-1])
176+
break
177+
178+
# If we don't find it, tell the user
179+
if nelm is None:
180+
raise Exception('NELM not found. Cannot tell if this result is converged')
181+
182+
# Now, loop through the file. What we want to know is whether the last ionic
183+
# step of this file terminates because it converges or because we hit NELM
184+
re_iter = re.compile('([0-9]+)\( *([0-9]+)\)')
185+
converged = False
186+
for line in fp:
187+
# Count the ionic steps
188+
if 'Iteration' in line:
189+
ionic, electronic = map(int, re_iter.findall(line)[0])
190+
191+
# If the loop is finished, mark the number of electronic steps
192+
if 'aborting loop' in line:
193+
converged = electronic < nelm
194+
195+
return converged
176196

177197
def get_total_energy(self):
178-
return Property(scalars=[Scalar(value=self._call_ase(Vasp().read_energy, os.path.dirname(self.outcar))[0])], units='eV')
198+
with open(self.outcar) as fp:
199+
last_energy = None
200+
for line in fp:
201+
if line.startswith(' free energy TOTEN'):
202+
last_energy = float(line.split()[4])
203+
if last_energy is None:
204+
return None
205+
return Property(scalars=[Scalar(value=last_energy)], units='eV')
179206

180207
def get_version_number(self):
181208
# Open up the OUTCAR

tests/parsers/test_vasp.py

+8-3
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ def test_perov(self):
2727

2828
# Test the density
2929
self.assertEqual("g/(cm^3)", parser.get_density().units)
30-
self.assertAlmostEqual(6.7238121, parser.get_density().scalars[0].value)
30+
self.assertAlmostEqual(6.7238121, parser.get_density().scalars[0].value, places=6)
3131

3232
# Test the cutoff energy
3333
res = parser.get_cutoff_energy()
@@ -121,8 +121,7 @@ def _evaluate_AlNi(self, parser):
121121
self.assertEquals([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.034779999999999998, 0.058860000000000003, 0.087639999999999996, 0.097239999999999993, 0.11268, 0.12908, 0.13766, 0.14779999999999999, 0.15936, 0.17232, 0.17985999999999999, 0.18837999999999999, 0.19753999999999999, 0.20760000000000001, 0.21779999999999999, 0.22600000000000001, 0.23419999999999999, 0.2422, 0.25080000000000002, 0.26000000000000001, 0.27000000000000002, 0.27900000000000003, 0.28699999999999998, 0.29499999999999998, 0.3044, 0.31419999999999998, 0.32419999999999999, 0.33460000000000001, 0.3448, 0.35659999999999997, 0.36940000000000001, 0.38340000000000002, 0.39860000000000001, 0.41520000000000001, 0.43580000000000002, 0.45839999999999997, 0.46700000000000003, 0.47920000000000001, 0.49320000000000003, 0.50960000000000005, 0.53200000000000003, 0.5534, 0.56879999999999997, 0.6048, 0.63600000000000001, 0.65880000000000005, 0.71020000000000005, 0.75839999999999996, 0.65300000000000002, 0.623, 0.61660000000000004, 0.62480000000000002, 0.63859999999999995, 0.66200000000000003, 0.7016, 0.76400000000000001, 0.82920000000000005, 0.96719999999999995, 1.7285999999999999, 2.1680000000000001, 1.8826000000000001, 1.599, 1.4379999999999999, 1.5680000000000001, 2.4300000000000002, 2.4079999999999999, 3.5880000000000001, 2.9319999999999999, 2.742, 1.9369000000000001, 0.71629999999999994, 3.5699999999999998, 4.3099999999999996, 3.242, 4.4660000000000002, 8.8300000000000001, 5.7919999999999998, 5.1760000000000002, 4.0540000000000003, 2.8900000000000001, 0.88260000000000005, 0.7258, 0.62339999999999995, 0.52700000000000002, 0.35659999999999997, 0.4929, 0.65859999999999996, 2.6619999999999999, 1.5973999999999999, 1.3284, 1.1026, 0.9264, 0.83499999999999996, 0.7722, 0.7046, 0.6482, 0.60140000000000005, 0.5484, 0.51039999999999996, 0.47660000000000002, 0.44700000000000001, 0.41199999999999998, 0.38600000000000001, 0.35539999999999999, 0.2994, 0.26019999999999999, 0.26479999999999998, 0.309, 0.35599999999999998, 0.3886, 0.44440000000000002, 0.5766, 0.6976, 0.73719999999999997, 0.80220000000000002, 0.8226, 0.89459999999999995, 0.86519999999999997, 0.82620000000000005, 0.78720000000000001, 0.77880000000000005, 0.83579999999999999, 0.74099999999999999, 0.73340000000000005, 0.7944, 0.73919999999999997, 0.73199999999999998, 0.74119999999999997, 0.69840000000000002, 0.73860000000000003, 0.71079999999999999, 0.70199999999999996, 0.77439999999999998, 0.74460000000000004, 0.79279999999999995, 0.89900000000000002, 0.82720000000000005, 0.81620000000000004, 0.85199999999999998, 0.85819999999999996, 0.876, 0.87819999999999998, 0.89100000000000001, 0.89880000000000004, 0.874, 0.85399999999999998, 0.85719999999999996, 0.8518, 0.84819999999999995, 0.83499999999999996, 0.8206, 0.80500000000000005, 0.78900000000000003, 0.77400000000000002, 0.75880000000000003, 0.753, 0.75580000000000003, 0.75080000000000002, 0.73280000000000001, 0.71079999999999999, 0.69040000000000001, 0.65900000000000003, 0.66139999999999999, 0.67700000000000005, 0.70620000000000005, 0.74180000000000001, 0.79459999999999997, 0.878, 0.98299999999999998, 1.0628, 1.1044, 1.0998000000000001, 1.0371999999999999, 0.92179999999999995, 0.85260000000000002, 0.80100000000000005, 0.75239999999999996, 0.70079999999999998, 0.66920000000000002, 0.65180000000000005, 0.64159999999999995, 0.63300000000000001, 0.62760000000000005, 0.62780000000000002, 0.64059999999999995, 0.66620000000000001, 0.6784, 0.68300000000000005, 0.67479999999999996, 0.6804, 0.755, 0.7802, 0.80659999999999998, 0.82120000000000004, 0.83640000000000003, 0.85660000000000003, 0.90500000000000003, 0.90880000000000005, 0.88019999999999998, 0.86419999999999997, 0.84719999999999995, 0.82740000000000002, 0.80020000000000002, 0.75800000000000001, 0.69979999999999998, 0.71360000000000001, 0.90400000000000003, 0.9768, 1.123, 1.2014, 0.93259999999999998, 0.81240000000000001, 0.71319999999999995, 0.65780000000000005, 0.65639999999999998, 0.6472, 0.62829999999999997, 0.63440000000000007, 0.6885, 0.76059999999999994, 0.83579999999999999, 0.93270000000000008, 1.0291000000000001, 1.0882000000000001, 1.0954000000000002, 1.0880999999999998, 1.0526, 0.98049999999999993, 0.86430000000000007, 0.8085, 0.41639999999999999, 0.29980000000000001, 0.24840000000000001, 0.1825, 0.13319999999999999, 0.091359999999999997, 0.065560000000000007, 0.048509999999999998, 0.039219999999999998, 0.030629999999999998, 0.02239, 0.016642000000000001, 0.015498000000000001, 0.01456, 0.013663, 0.012806999999999999, 0.011991, 0.011218000000000001, 0.010484, 0.009777000000000001, 0.0090940000000000014, 0.0084370000000000001, 0.0079260000000000008, 0.0081139999999999997, 0.0071549999999999999, 0.0062389999999999998, 0.0053679999999999995, 0.0045409999999999999, 0.0037580000000000001, 0.003019, 0.00232, 0.0016800999999999999, 0.0011435, 0.00070980000000000001, 0.0003791, 0.00015118999999999999, 2.6239999999999999e-05, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
122122
list(map(lambda x: x.value, dos.scalars)))
123123
self.assertEquals('number of states per unit cell', dos.units)
124-
125-
124+
126125
def test_SOC(self):
127126
# Parse the results
128127
parser = self.get_parser('heusler_static_SOC')
@@ -233,6 +232,12 @@ def test_filename_robustness(self):
233232
res = parser.get_cutoff_energy()
234233
self.assertEquals(400, res.scalars[0].value)
235234
self.assertEquals('eV', res.units)
235+
236+
# Test whether it is converged
237+
self.assertTrue(parser.is_converged().scalars[0].value)
238+
239+
# Test total energy
240+
self.assertAlmostEqual(-39.85550532, parser.get_total_energy().scalars[0].value)
236241
finally:
237242
delete_example('perov_relax_U')
238243

0 commit comments

Comments
 (0)