Skip to content

Commit c22dbf0

Browse files
committed
Removed reliance on files being named OUTCAR
Removed use of ase's VASP Calculator, which has the filenames hardcoded (and that is OK for ase, as the job of this class is to run VASP)
1 parent 11776cd commit c22dbf0

File tree

1 file changed

+41
-14
lines changed

1 file changed

+41
-14
lines changed

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

0 commit comments

Comments
 (0)