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