chimie4psmn / database / import_vasp_calc @ 50
Historique | Voir | Annoter | Télécharger (11,49 ko)
1 |
#!/usr/bin/env python |
---|---|
2 |
# $Id$ |
3 |
import os, sys, argparse |
4 |
from ase import Atoms |
5 |
from ase.io import read |
6 |
from ase.db import connect |
7 |
from ase.calculators.vasp import Vasp |
8 |
from ase.constraints import FixAtoms |
9 |
from numpy.linalg import norm |
10 |
from bz2 import BZ2File |
11 |
from gzip import GzipFile |
12 |
from time import time |
13 |
import multiprocessing |
14 |
import traceback |
15 |
|
16 |
xc_dict = {'1':'LDA(HL)', |
17 |
'2':'LDA(CA/PZ)', |
18 |
'3':'LDA(WI)', |
19 |
'4':'GGA(PB)', |
20 |
'5':'GGA(PW86)', |
21 |
'6':'LM', |
22 |
'7':'PW91', |
23 |
'8':'PBE', |
24 |
'9':'RPBE', |
25 |
'10':'VWN', |
26 |
'11':'B3LYP(VWN3 correction)', |
27 |
'12':'B3LYP(VWN5 correction)', |
28 |
'13':'AM05', |
29 |
'14':'PBEsol', |
30 |
'17':'BEEF', |
31 |
'100':'CO'} |
32 |
def error(msg, *args): |
33 |
return multiprocessing.get_logger().error(msg, *args) |
34 |
|
35 |
class LogExceptions(object): |
36 |
def __init__(self, callable): |
37 |
self.__callable = callable |
38 |
|
39 |
def __call__(self, *args, **kwargs): |
40 |
try: |
41 |
result = self.__callable(*args, **kwargs) |
42 |
|
43 |
except Exception as e: |
44 |
# Here we add some debugging help. If multiprocessing's |
45 |
# debugging is on, it will arrange to log the traceback |
46 |
error(traceback.format_exc()) |
47 |
# Re-raise the original exception so the Pool worker can |
48 |
# clean up |
49 |
raise |
50 |
|
51 |
# It was fine, give a normal answer |
52 |
return result |
53 |
|
54 |
def import_vasp_calculations(path,db,include_dir=[],exclude_dir=[],use_poscar=False,user=os.environ['USER'], nproc=8,project='vasp'): |
55 |
#log = open('scan.log','w') |
56 |
_all = os.walk(os.path.abspath(path)) |
57 |
calculator=None |
58 |
read_all_dir = 0 |
59 |
filenames = [] |
60 |
if os.path.exists(db): |
61 |
con = connect(db) |
62 |
for row in con.select(code='VASP'): |
63 |
filenames.append(row.filename) |
64 |
else: |
65 |
con = connect(db) |
66 |
if len(include_dir) == 0: |
67 |
read_all_dir = 1 |
68 |
all_files = [] |
69 |
paths = [] |
70 |
t1 = time() |
71 |
for i,a in enumerate(_all): |
72 |
condition1 = (read_all_dir or a[0].split('/')[-1] in include_dir) |
73 |
#condition2 = not files[0].split('/')[-1] in exclude_dir |
74 |
condition3 = [ i for i, x in enumerate(exclude_dir) if x in a[0] ] |
75 |
_vasp_out = [i for i in range(len(a[2])) if ('OUTCAR' in a[2][i] and a[2][i][:6]=='OUTCAR')] |
76 |
if condition1 and not condition3: |
77 |
for f in _vasp_out: |
78 |
filetoread = a[2][f] |
79 |
path = a[0] |
80 |
if not filetoread in filenames: |
81 |
all_files.append(filetoread) |
82 |
paths.append(path) |
83 |
t2 = time() |
84 |
multiprocessing.log_to_stderr() |
85 |
print 'using '+str(nproc)+' threads' |
86 |
pool = multiprocessing.Pool(nproc) |
87 |
results = [] |
88 |
for filetoread,path in zip(all_files, paths): |
89 |
#result = pool.apply_async(LogExceptions(mp_worker), args=(con,files,use_poscar,filenames,xc_dict), callback=log_result) |
90 |
pool.apply_async(LogExceptions(mp_worker), args=(con,filetoread,path,use_poscar,filenames,xc_dict), callback=log_result) |
91 |
pool.close() |
92 |
pool.join() |
93 |
t3 = time() |
94 |
print 'total time used: ', t3-t2, ' seconds' |
95 |
|
96 |
def log_result(log): |
97 |
logfile = open('scan.log','a') |
98 |
print >> logfile, log |
99 |
|
100 |
def mp_worker(con, filetoread, path, use_poscar,filenames,xc_dict): |
101 |
try: |
102 |
t1 = time() |
103 |
filetoread = path +'/'+ filetoread |
104 |
Atoms = read(filetoread) |
105 |
t2 = time() |
106 |
print 'timing: ', t2-t1 |
107 |
if use_poscar: |
108 |
try: |
109 |
constraints = read(path+'/POSCAR').constraints |
110 |
except IOError: |
111 |
try: |
112 |
constraints = read(path+'/POSCAR.gz').constraints |
113 |
except IOError: |
114 |
try: |
115 |
constraints = read(path+'/POSCAR.bz2').constraints |
116 |
except IOError: |
117 |
constraints = None |
118 |
Atoms.set_constraint(constraints) |
119 |
print 'get constraint from poscar', filetoread |
120 |
if not constraints: |
121 |
Atoms0 = read(filetoread, index=0) |
122 |
pos0 = Atoms0.positions |
123 |
pos = Atoms.positions |
124 |
diff = pos - pos0 |
125 |
disp = norm(diff, axis=1) |
126 |
if disp.sum() > 0: |
127 |
print 'find constraint from outcar' |
128 |
mask = [_disp == 0 for _disp in disp] |
129 |
constraints = FixAtoms(mask=mask) |
130 |
Atoms.set_constraint(constraints) |
131 |
else: |
132 |
print 'no constraint' |
133 |
constraints = None |
134 |
#os.system('cp '+files[0]+'/'+files[2][f]+' OUTCAR') |
135 |
#calc = Vasp() |
136 |
#calc.atoms = Atoms |
137 |
#calc.sort = list(range(len(Atoms))) |
138 |
#calc.resort = list(range(len(Atoms))) |
139 |
#calc.read_outcar() |
140 |
#Atoms = calc.atoms |
141 |
#nbands = calc.get_number_of_bands() |
142 |
##xc = calc.get_xc_functional() |
143 |
#os.system('rm -f OUTCAR') |
144 |
|
145 |
#read version number, XC, ENCUT etc. |
146 |
if filetoread[-4:] == '.bz2': |
147 |
fobj = BZ2File(filetoread) |
148 |
elif filetoread[-3:] == '.gz': |
149 |
fobj = GzipFile(filetoread) |
150 |
else: |
151 |
fobj = open(filetoread) |
152 |
with fobj as outcar: |
153 |
version = outcar.readline() |
154 |
line = outcar.readline() |
155 |
read_para = 0 |
156 |
lsol = False |
157 |
ldipol = False |
158 |
while line != '': |
159 |
if line.startswith(' INCAR:'): |
160 |
line = outcar.readline().split() |
161 |
if line[1] == 'PAW_PBE': |
162 |
pot = 'PAW' |
163 |
else: |
164 |
pot = line[1] |
165 |
elif line.startswith(' exchange correlation table for LEXCH ='): |
166 |
xc_flag = line.split()[-1].upper() |
167 |
if xc_flag not in xc_dict.keys(): |
168 |
raise ValueError('Unknown xc-functional flag found in POTCAR,' |
169 |
' LEXCH=%s' % xc_flag) |
170 |
xc = xc_dict[xc_flag] |
171 |
elif line.startswith(' Dimension of arrays'): |
172 |
#if line.startswith(' Dimension of arrays'): |
173 |
read_para = 1 |
174 |
elif read_para: |
175 |
#if 'LEXCH' in line: |
176 |
# xc_flag = line.split()[2].upper() |
177 |
# if xc_flag not in xc_dict.keys(): |
178 |
# raise ValueError('Unknown xc-functional flag found in POTCAR,' |
179 |
# ' LEXCH=%s' % xc_flag) |
180 |
# xc = xc_dict[xc_flag] |
181 |
#elif 'NKPTS' in line: |
182 |
if 'NKPTS' in line: |
183 |
nkpts = int(line.split()[3]) |
184 |
elif 'ENCUT' in line: |
185 |
encut = float(line.split()[2]) |
186 |
elif 'ENAUG' in line: |
187 |
enaug = float(line.split()[2]) |
188 |
elif 'NBANDS' in line: |
189 |
nbands = int(line.split()[-1]) |
190 |
elif 'EDIFFG' in line: |
191 |
f_limit = -float(line.split()[2]) |
192 |
elif 'LSOL' in line: |
193 |
if line.split()[2] == 'T': |
194 |
lsol = True |
195 |
elif 'LDIPOL' in line: |
196 |
if line.split()[2] == 'T': |
197 |
ldipol = True |
198 |
elif '-'*104 in line: |
199 |
break |
200 |
line = outcar.readline() |
201 |
if constraints is not None: |
202 |
fmax = ((Atoms.get_forces()) ** 2).sum(1).max()**0.5 |
203 |
if fmax < f_limit: |
204 |
#print >> log, 'updating the database with minimized calculation from file: ', fmax, files[2][f] |
205 |
_log = 'archived_a: '+filetoread+' '+str(fmax) |
206 |
#if use_poscar: |
207 |
#print os.getenv('USER') |
208 |
#id = con.reserve(filename=filetoread) |
209 |
#con.write(Atoms,functional = xc,path=path,code='VASP',filename=filetoread, version=version, potential=pot, encut=encut, enaug=enaug, lsol=lsol, ldipol=ldipol, nkpts=nkpts, constraint=True) |
210 |
#del con[id] |
211 |
update_method = 1 |
212 |
#else: |
213 |
# con.write(Atoms,functional = xc,creator=creator,path=files[0],code='VASP',filename=filetoread, version=version, potential=pot, encut=encut, enaug=enaug, lsol=lsol, ldipol=ldipol, nkpts=nkpts, constraint=True) |
214 |
else: |
215 |
update_method = 0 |
216 |
#print >> log, 'not updating the database as fmax is too big for file: ', fmax, files[2][f] |
217 |
_log = 'skipped: '+filetoread+' '+str(fmax) |
218 |
else: |
219 |
#print >> log, 'updating the database with calculation', files[2][f] |
220 |
_log = 'archived_b: '+filetoread |
221 |
update_method = 2 |
222 |
#id = con.reserve(filename=filetoread) |
223 |
#con.write(Atoms,functional = xc,path=path,code='VASP',filename=filetoread, version=version, potential=pot, encut=encut, enaug=enaug, lsol=lsol, ldipol=ldipol, nkpts=nkpts, constraint=False) |
224 |
#del con[id] |
225 |
record = con.select(filename=filetoread) |
226 |
if update_method: |
227 |
try: |
228 |
id = con.reserve(filename=filetoread) |
229 |
con.write(Atoms,functional = xc,path=path,code='VASP',filename=filetoread, version=version, potential=pot, encut=encut, enaug=enaug, lsol=lsol, ldipol=ldipol, nkpts=nkpts, constraint=False) |
230 |
del con[id] |
231 |
record = con.select(filename=filetoread) |
232 |
id = next(record)['id'] |
233 |
con.update(id,user=user) |
234 |
con.update(id,calculator='vasp') |
235 |
except UnboundLocalError: |
236 |
print 'err:',filetoread |
237 |
return |
238 |
|
239 |
except (IndexError, ValueError): |
240 |
_log = 'failed: '+filetoread |
241 |
print _log |
242 |
#_log.flush() |
243 |
return |
244 |
|
245 |
if __name__ == '__main__': |
246 |
parser = argparse.ArgumentParser() |
247 |
parser.add_argument("path", help="The path under which the calculations will be scanned") |
248 |
parser.add_argument("-p", help="Use POSCAR in the same directory to determine the constraint", action="store_true") |
249 |
parser.add_argument("-i", "--include_dir",help="Directory to be included in the scanning") |
250 |
parser.add_argument("-e", "--exclude_dir",help="Directory to be excluded in the scanning") |
251 |
parser.add_argument("-d", help="Name of the database file to store the scanned calculations") |
252 |
parser.add_argument("-n", help="Number of processers") |
253 |
parser.add_argument("-u", help="The user who did the calculations") |
254 |
parser.add_argument("-j", help="Project name") |
255 |
args = parser.parse_args() |
256 |
nproc = multiprocessing.cpu_count() |
257 |
if args.path is None: |
258 |
path = '.' |
259 |
else: |
260 |
path = args.path |
261 |
if args.p: |
262 |
use_poscar = True |
263 |
else: |
264 |
use_poscar = False |
265 |
if args.include_dir is None: |
266 |
include_dir = [] |
267 |
else: |
268 |
include_dir = args.include_dir |
269 |
if args.exclude_dir is None: |
270 |
exclude_dir = [] |
271 |
else: |
272 |
exclude_dir = args.exclude_dir |
273 |
if args.d is None: |
274 |
db = 'vasp.db' |
275 |
else: |
276 |
db = args.d |
277 |
if args.n is None: |
278 |
nproc = nproc / 2 |
279 |
else: |
280 |
nproc = int(args.n) |
281 |
if args.u is None: |
282 |
user = os.environ['USER'] |
283 |
else: |
284 |
user = args.u |
285 |
if args.j is None: |
286 |
project = 'gaussian' |
287 |
else: |
288 |
project = args.j |
289 |
|
290 |
#import_vasp_calculations('/data/users/tjiang/rkerber', con) |
291 |
#import_vasp_calculations('.', con, include_dir=['<opt_dir>'], exclude_dir=['<to_exclude_dir1>', '<to_exclude_dir2>']) |
292 |
import_vasp_calculations(path, db, use_poscar=use_poscar, include_dir=include_dir, exclude_dir=exclude_dir, nproc=nproc, user=user) |