Statistiques
| Révision :

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