chimie4psmn / database / import_gaussian_calc @ 46
Historique | Voir | Annoter | Télécharger (5,41 ko)
1 |
#!/usr/bin/env python |
---|---|
2 |
# $Id$ |
3 |
import os, sys, argparse |
4 |
from ase import Atoms |
5 |
from ase.io.gaussian import read_gaussian_out |
6 |
from ase.db import connect |
7 |
from ase.calculators.gaussian import Gaussian |
8 |
from ase.calculators.emt import EMT |
9 |
from ase.constraints import FixAtoms |
10 |
from numpy.linalg import norm |
11 |
from bz2 import BZ2File |
12 |
from gzip import GzipFile |
13 |
from time import time |
14 |
import multiprocessing |
15 |
import traceback |
16 |
|
17 |
def error(msg, *args): |
18 |
return multiprocessing.get_logger().error(msg, *args) |
19 |
|
20 |
class LogExceptions(object): |
21 |
def __init__(self, callable): |
22 |
self.__callable = callable |
23 |
|
24 |
def __call__(self, *args, **kwargs): |
25 |
try: |
26 |
result = self.__callable(*args, **kwargs) |
27 |
|
28 |
except Exception as e: |
29 |
# Here we add some debugging help. If multiprocessing's |
30 |
# debugging is on, it will arrange to log the traceback |
31 |
error(traceback.format_exc()) |
32 |
# Re-raise the original exception so the Pool worker can |
33 |
# clean up |
34 |
raise |
35 |
|
36 |
# It was fine, give a normal answer |
37 |
return result |
38 |
|
39 |
def import_gaussian_calculations(path,db,include_dir=[],exclude_dir=[],use_input=False,project='gaussian',user=os.environ['USER'], nproc=8): |
40 |
#log = open('scan.log','w') |
41 |
_all = os.walk(os.path.abspath(path)) |
42 |
calculator=None |
43 |
xc_dict = {'8': 'PBE', '91': 'PW91', 'CA': 'LDA'} |
44 |
read_all_dir = 0 |
45 |
filenames = [] |
46 |
if os.path.exists(db): |
47 |
con = connect(db) |
48 |
for row in con.select(project='test'): |
49 |
filenames.append(row.filename) |
50 |
else: |
51 |
con = connect(db) |
52 |
if len(include_dir) == 0: |
53 |
read_all_dir = 1 |
54 |
all_files = [] |
55 |
paths = [] |
56 |
t1 = time() |
57 |
for i,a in enumerate(_all): |
58 |
condition1 = (read_all_dir or a[0].split('/')[-1] in include_dir) |
59 |
#condition2 = not files[0].split('/')[-1] in exclude_dir |
60 |
condition3 = [ i for i, x in enumerate(exclude_dir) if x in a[0] ] |
61 |
_gass_out = [i for i in range(len(a[2])) if ('.log' in a[2][i])] |
62 |
if condition1 and not condition3: |
63 |
for f in _gass_out: |
64 |
path = a[0] |
65 |
filetoread = path +'/'+ a[2][f] |
66 |
if not filetoread in filenames: |
67 |
all_files.append(filetoread) |
68 |
paths.append(path) |
69 |
t2 = time() |
70 |
multiprocessing.log_to_stderr() |
71 |
print 'using '+str(nproc)+' threads' |
72 |
pool = multiprocessing.Pool(nproc) |
73 |
for filetoread,path in zip(all_files, paths): |
74 |
#def callback(result, func=LogExceptions(mp_worker)): |
75 |
# results[func] = result |
76 |
result = pool.apply_async(LogExceptions(mp_worker), args=(con,files,use_input,filenames,xc_dict), callback=log_result) |
77 |
pool.close() |
78 |
pool.join() |
79 |
t3 = time() |
80 |
con = connect(db) |
81 |
print 'total time used: ', t3-t2, ' seconds' |
82 |
|
83 |
def log_result(log): |
84 |
logfile = open('scan.log','a') |
85 |
print >> logfile, log |
86 |
return log |
87 |
|
88 |
def mp_worker(con, filetoread, path, use_input,filenames, user, project): |
89 |
try: |
90 |
t1 = time() |
91 |
Atoms, data = read_gaussian_out(filetoread,quantity='all') |
92 |
t2 = time() |
93 |
print 'timing: ', t2-t1 |
94 |
|
95 |
_log = 'archived_a: '+filetoread |
96 |
id = con.reserve(filename=filetoread) |
97 |
con.write(Atoms,functional = data['Method'],charge=data['Charge'],basis_set=data['Basis_set'],path=path,filename=filetoread, version=data['Version'],project='test') |
98 |
del con[id] |
99 |
record = con.select(filename=filetoread) |
100 |
#================================== |
101 |
#This part will only exist temporarily, it is for importing other people's calculation |
102 |
#For update the user and calculator keys, tjiang's hacked copy of ase is needed, |
103 |
#as these two are reserved keys that are not allowed to be updated manually |
104 |
id = next(record)['id'] |
105 |
con.update(id,user='edumont') |
106 |
#================================== |
107 |
con.update(id,calculator='gaussian') |
108 |
print _log |
109 |
except (IndexError, ValueError): |
110 |
_log = 'failed: '+filetoread |
111 |
print _log |
112 |
##_log.flush() |
113 |
return |
114 |
|
115 |
if __name__ == '__main__': |
116 |
parser = argparse.ArgumentParser() |
117 |
parser.add_argument("path", help="The path under which the calculations will be scanned") |
118 |
parser.add_argument("-p", help="Use input in the same directory to determine the constraint", action="store_true") |
119 |
parser.add_argument("-i", "--include_dir",help="Directory to be included in the scanning") |
120 |
parser.add_argument("-e", "--exclude_dir",help="Directory to be excluded in the scanning") |
121 |
parser.add_argument("-d", help="Name of the database file to store the scanned calculations") |
122 |
parser.add_argument("-n", help="Number of processers") |
123 |
parser.add_argument("-j", help="Project name") |
124 |
args = parser.parse_args() |
125 |
if args.path is None: |
126 |
path = '.' |
127 |
else: |
128 |
path = args.path |
129 |
if args.p: |
130 |
use_input = True |
131 |
else: |
132 |
use_input = False |
133 |
if args.include_dir is None: |
134 |
include_dir = [] |
135 |
else: |
136 |
include_dir = args.include_dir |
137 |
if args.exclude_dir is None: |
138 |
exclude_dir = [] |
139 |
else: |
140 |
exclude_dir = args.exclude_dir |
141 |
if args.d is None: |
142 |
db = 'gaussian.db' |
143 |
else: |
144 |
db = args.d |
145 |
if args.n is None: |
146 |
nproc = 8 |
147 |
else: |
148 |
nproc = int(args.n) |
149 |
if args.j is None: |
150 |
project = 'gaussian' |
151 |
else: |
152 |
project = int(args.j) |
153 |
|
154 |
import_gaussian_calculations(path, db, use_input=use_input, include_dir=include_dir, exclude_dir=exclude_dir, project=project, nproc=nproc) |