Statistiques
| Révision :

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)