Statistiques
| Révision :

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)