root / ase / calculators / gaussian.py @ 20
Historique | Voir | Annoter | Télécharger (5,56 ko)
1 |
"""
|
---|---|
2 |
@author: Torsten Kerber and Paul Fleurat-Lessard
|
3 |
@organization: Ecole Normale Superieure de Lyon
|
4 |
@contact: Paul.Fleurat-Lessard@ens-lyon.fr
|
5 |
|
6 |
@data: June, 6, 2012
|
7 |
|
8 |
This work is supported by Award No. UK-C0017 made by King Abdullah University of Science and Technology(KAUST)
|
9 |
"""
|
10 |
import os, sys |
11 |
import numpy as np |
12 |
|
13 |
from ase.units import Hartree, Bohr |
14 |
from ase.calculators.general import Calculator |
15 |
|
16 |
str_keys = [ |
17 |
'functional', # functional |
18 |
'basis', # basis set |
19 |
'flags' # more options |
20 |
'memory', # RAM memory used |
21 |
'disk', # disk space available |
22 |
'filename', # name of the gaussian files |
23 |
'command' # command to run Gaussian |
24 |
] |
25 |
|
26 |
int_keys = [ |
27 |
'multiplicity', # multiplicity of the system |
28 |
'nproc', # number of processors |
29 |
] |
30 |
|
31 |
class Gaussian(Calculator): |
32 |
def __init__(self, atoms=None, **kwargs): |
33 |
self.set_standard()
|
34 |
|
35 |
self.set(**kwargs)
|
36 |
self.atoms = atoms
|
37 |
|
38 |
self.potential_energy = 0.0 |
39 |
self.forces = None |
40 |
|
41 |
self.new_calculation = True |
42 |
if atoms != None: |
43 |
self.forces = np.zeros((len(atoms), 3)) |
44 |
self.stress = None |
45 |
|
46 |
def set_standard(self): |
47 |
self.str_params = {}
|
48 |
self.int_params = {}
|
49 |
|
50 |
for key in str_keys: |
51 |
self.str_params['key'] = None |
52 |
|
53 |
for key in int_keys: |
54 |
self.int_params['key'] = None |
55 |
|
56 |
self.str_params['functional'] = "B3LYP" |
57 |
self.str_params['basis'] = '6-31G*' |
58 |
self.str_params['flags'] = ' Force ' |
59 |
self.str_params['memory'] = '60MW' |
60 |
self.str_params['disk'] = '16GB' |
61 |
|
62 |
self.str_params['command'] = 'g09' |
63 |
self.str_params['filename'] = 'ASE-gaussian' |
64 |
|
65 |
self.int_params['multiplicity'] = 1 |
66 |
self.int_params['nproc'] = 8 |
67 |
|
68 |
|
69 |
def set(self, **kwargs): |
70 |
for key in kwargs: |
71 |
if self.str_params.has_key(key): |
72 |
self.str_params[key] = kwargs[key]
|
73 |
if self.int_params.has_key(key): |
74 |
self.int_params[key] = kwargs[key]
|
75 |
|
76 |
|
77 |
def set_atoms(self, atoms): |
78 |
if self.atoms != atoms: |
79 |
self.atoms = atoms.copy()
|
80 |
self.new_calculation = True |
81 |
|
82 |
def write_file_line(self, file, line): |
83 |
file.write(line)
|
84 |
file.write('\n') |
85 |
|
86 |
def write_input(self): |
87 |
name = self.str_params['filename'] |
88 |
|
89 |
inputfile = open(name + '.com', 'w') |
90 |
self.write_file_line(inputfile, '%chk=' + name + '.chk') |
91 |
self.write_file_line(inputfile, '%mem=' + self.str_params['memory']) |
92 |
self.write_file_line(inputfile, '%nproc=' + ('%d' % self.int_params['nproc'])) |
93 |
self.write_file_line(inputfile, 'MaxDisk=' + self.str_params['disk']) |
94 |
|
95 |
line = '#' + self.str_params['functional'] + '/' + self.str_params['basis'] + ' ' + self.str_params['flags'] |
96 |
self.write_file_line(inputfile, line)
|
97 |
|
98 |
self.write_file_line(inputfile, '') |
99 |
self.write_file_line(inputfile, 'Gaussian job created by ASE (supported by King Abdullah University of Science and Technology ,KAUST)') |
100 |
self.write_file_line(inputfile, '') |
101 |
|
102 |
line = '%d %d' % (sum(self.atoms.get_charges()), self.int_params['multiplicity']) |
103 |
self.write_file_line(inputfile, line)
|
104 |
|
105 |
coords = self.atoms.get_positions()
|
106 |
for i, at in enumerate(self.atoms.get_chemical_symbols()): |
107 |
line = at |
108 |
coord = coords[i] |
109 |
line += ' %16.5f %16.5f %16.5f'%(coord[0], coord[1], coord[2]) |
110 |
self.write_file_line(inputfile, line)
|
111 |
|
112 |
if self.atoms.get_pbc().any(): |
113 |
cell = self.atoms.get_cell()
|
114 |
line = ''
|
115 |
for v in cell: |
116 |
line += 'TV %8.3f %8.3f %8.3f\n'%(v[0], v[1], v[2]) |
117 |
self.write_file_line(inputfile, line)
|
118 |
|
119 |
self.write_file_line(inputfile, '') |
120 |
|
121 |
def update(self, atoms): |
122 |
if (self.atoms is None or self.atoms.positions.shape != atoms.positions.shape): |
123 |
self.atoms = atoms.copy()
|
124 |
self.calculate(atoms)
|
125 |
|
126 |
def calculate(self, atoms): |
127 |
self.write_input()
|
128 |
line = self.str_params['command'] + ' ' + self.str_params['filename'] + '.com' |
129 |
exitcode = os.system(line) |
130 |
if exitcode != 0: |
131 |
raise RuntimeError('Gaussian exited with exit code: %d. ' % exitcode) |
132 |
self.read_output()
|
133 |
self.new_calculation = False |
134 |
|
135 |
def get_potential_energy(self, atoms=None, force_consistent=False): |
136 |
self.set_atoms(atoms)
|
137 |
if self.new_calculation: |
138 |
self.calculate(atoms)
|
139 |
return self.potential_energy |
140 |
|
141 |
def get_forces(self, atoms): |
142 |
self.set_atoms(atoms)
|
143 |
if self.new_calculation: |
144 |
self.calculate(atoms)
|
145 |
return self.forces |
146 |
|
147 |
def read_output(self): |
148 |
outfile = open(self.str_params['filename'] + '.log') |
149 |
lines = outfile.readlines() |
150 |
outfile.close() |
151 |
|
152 |
factor = Hartree |
153 |
for line in lines: |
154 |
if 'SCF Done' in line: |
155 |
line = line.split() |
156 |
self.potential_energy = float(line[4]) * factor |
157 |
|
158 |
factor = Hartree / Bohr |
159 |
nats = len(self.atoms) |
160 |
for iline, line in enumerate(lines): |
161 |
if 'Forces (Hartrees/Bohr)' in line: |
162 |
self.forces = np.zeros((nats, 3), float) |
163 |
for iat in range(nats): |
164 |
line = lines[iline+iat+3].split()
|
165 |
for idir, val in enumerate(line[2:5]): |
166 |
self.forces[iat, idir] = float(val) * factor |
167 |
break
|