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