Statistiques
| Révision :

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)