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