Statistiques
| Révision :

root / ase / calculators / gaussian.py @ 16

Historique | Voir | Annoter | Télécharger (7,45 ko)

1 16 tkerber
"""
2 16 tkerber
This module is the Gaussian module for ASE,  based on the PyMD Gaussian Module by R. Bulo,
3 16 tkerber
implemented by T. Kerber
4 16 tkerber

5 16 tkerber
 @author:       Rosa Bulo
6 16 tkerber
 @organization: Vrije Universiteit Amsterdam
7 16 tkerber
 @contact:      bulo@few.vu.nl
8 16 tkerber

9 16 tkerber
Torsten Kerber,  ENS LYON: 2011,  07,  11
10 16 tkerber

11 16 tkerber
This work is supported by Award No. UK-C0017,  made by King Abdullah
12 16 tkerber
University of Science and Technology(KAUST)
13 16 tkerber
"""
14 16 tkerber
import os,  sys,  string
15 16 tkerber
16 16 tkerber
import numpy as np
17 16 tkerber
from ase.units import Hartree,  Bohr
18 16 tkerber
from ase.calculators.general import Calculator
19 16 tkerber
import os, sys, re, math, commands, subprocess, time
20 16 tkerber
21 16 tkerber
class Gaussian(Calculator):
22 16 tkerber
    """
23 16 tkerber
    Class for representing the settings of a ReaxffForceJob
24 16 tkerber

25 16 tkerber
    It contains the following variables:
26 16 tkerber

27 16 tkerber
    basis:
28 16 tkerber
        A string representing the basisset to be used
29 16 tkerber

30 16 tkerber
    functional:
31 16 tkerber
        A string representing the DFT functional or wavefunction
32 16 tkerber
        method to be used.
33 16 tkerber

34 16 tkerber
    """
35 16 tkerber
36 16 tkerber
    def __init__(self, functional='BP86', basis='TZVP', atoms=None, inputfile=None):
37 16 tkerber
        self.functional = functional
38 16 tkerber
        self.basis = basis
39 16 tkerber
        self.restartdata = None
40 16 tkerber
        self.forces = None
41 16 tkerber
        self.atoms_old = None
42 16 tkerber
        if inputfile != None:
43 16 tkerber
            self = self.get_settings(inputfile)
44 16 tkerber
        self.atoms = atoms
45 16 tkerber
46 16 tkerber
    def set_functional(self, functional):
47 16 tkerber
        self.functional = functional
48 16 tkerber
49 16 tkerber
    def set_basis(self, basis):
50 16 tkerber
        self.basis = basis
51 16 tkerber
52 16 tkerber
    def setup_job(self,  type='force'):
53 16 tkerber
        ForceJob.setup_job(self, type=type)
54 16 tkerber
55 16 tkerber
        os.chdir(self.dirname)
56 16 tkerber
        self.myfiles = GaussianFileManager()
57 16 tkerber
        # Add the restart restuls to the filemanager. The checksum will be empty('')
58 16 tkerber
        if self.restartdata != None:
59 16 tkerber
            self.r_m = GaussianResults(self.myfiles)
60 16 tkerber
            self.myfiles.add_results(self.r_m, dir=self.restartdata+'/')
61 16 tkerber
62 16 tkerber
        os.chdir(self.dir)
63 16 tkerber
64 16 tkerber
    def write_parfile(self, filename):
65 16 tkerber
        parfile = open(filename, 'w')
66 16 tkerber
        parfile.write(self.prm)
67 16 tkerber
        parfile.close()
68 16 tkerber
69 16 tkerber
    def write_moldata(self,  type='force'):
70 16 tkerber
        out = commands.getoutput('mkdir SETUP')
71 16 tkerber
        out = commands.getoutput('ls SETUP/coord.*').split()
72 16 tkerber
        pdb = False
73 16 tkerber
        psf = False
74 16 tkerber
        prm = False
75 16 tkerber
76 16 tkerber
        # Change labels variable if necessary
77 16 tkerber
        norderats = 0
78 16 tkerber
#        for el in self.labels:
79 16 tkerber
#            norderats += 1
80 16 tkerber
#            if norderats != self.atoms.pdb.get_number_of_atoms():
81 16 tkerber
#                self.labels = self.get_labels()
82 16 tkerber
83 16 tkerber
        self.write_input(type)
84 16 tkerber
85 16 tkerber
    def write_input(self, type):
86 16 tkerber
        input = self.get_input_block(type)
87 16 tkerber
        pyfile = open('ASE-gaussian.com', 'w')
88 16 tkerber
        pyfile.write(input)
89 16 tkerber
        pyfile.close()
90 16 tkerber
91 16 tkerber
    def get_inp(self,  filename):
92 16 tkerber
        input = None
93 16 tkerber
        lis = commands.getoutput('ls %s'%(filename)).split('\n')
94 16 tkerber
        if not re.search('ls:', lis[0]):
95 16 tkerber
            infile = open(filename)
96 16 tkerber
            input = infile.readlines()
97 16 tkerber
            infile.close()
98 16 tkerber
        return input
99 16 tkerber
100 16 tkerber
    def run(self, type='force'):
101 16 tkerber
        startrun = time.time()
102 16 tkerber
        # I have to write the input every timestep,  because that is where the coordinates are
103 16 tkerber
        # self.write_input(type)
104 16 tkerber
        self.write_moldata(type)
105 16 tkerber
106 16 tkerber
        # Make sure that restart data is copied to the current directory
107 16 tkerber
#        if self.r_m != None:
108 16 tkerber
#            self.r_m.files.copy_job_result_files(self.r_m.fileid)
109 16 tkerber
110 16 tkerber
        out = commands.getoutput('g09 ASE-gaussian.com')
111 16 tkerber
        endrun = time.time()
112 16 tkerber
        #print 'timings: ', endrun-startrun
113 16 tkerber
        # Write the output
114 16 tkerber
#        outputfile = open('ASE-gaussian.log')
115 16 tkerber
#        outfile = open('ASE-gaussian.out',  'w')
116 16 tkerber
#        for line in outputfile:
117 16 tkerber
#            outfile.write(line)
118 16 tkerber
#        outputfile.close()
119 16 tkerber
#        outfile.close()
120 16 tkerber
        # End write output
121 16 tkerber
        self.energy = self.read_energy()
122 16 tkerber
        if type == 'force':
123 16 tkerber
            self.forces = self.read_forces()
124 16 tkerber
        self.energy_zero = self.energy
125 16 tkerber
126 16 tkerber
        # Change the results object to the new results
127 16 tkerber
        input = self.get_input_block(type)
128 16 tkerber
129 16 tkerber
    def read_energy(self,  charges=True):
130 16 tkerber
        hartree2kcal = 627.5095
131 16 tkerber
132 16 tkerber
        outfile = open('ASE-gaussian.log')
133 16 tkerber
        lines = outfile.readlines()
134 16 tkerber
        outfile.close()
135 16 tkerber
136 16 tkerber
        chargelines = 0
137 16 tkerber
        if charges:
138 16 tkerber
            nats = len(self.atoms)
139 16 tkerber
            block = ''
140 16 tkerber
        for line in lines:
141 16 tkerber
            if re.search('SCF Done', line):
142 16 tkerber
                words = line.split()
143 16 tkerber
                energy = float(words[4]) * hartree2kcal
144 16 tkerber
            if charges:
145 16 tkerber
                if re.search(' Mulliken atomic charges:', line):
146 16 tkerber
                    chargelines += 1
147 16 tkerber
            if chargelines > 0 and chargelines <= nats+2:
148 16 tkerber
                chargelines += 1
149 16 tkerber
                block += line
150 16 tkerber
151 16 tkerber
        if charges:
152 16 tkerber
            chargefile = open('charge.out', 'a')
153 16 tkerber
            chargefile.write(block)
154 16 tkerber
            chargefile.close()
155 16 tkerber
156 16 tkerber
        return energy
157 16 tkerber
158 16 tkerber
    def read_forces(self):
159 16 tkerber
        factor = Hartree / Bohr
160 16 tkerber
        factor = 1.0
161 16 tkerber
162 16 tkerber
        outfile = open('ASE-gaussian.log')
163 16 tkerber
        lines = outfile.readlines()
164 16 tkerber
        outfile.close()
165 16 tkerber
166 16 tkerber
        outputforces = None
167 16 tkerber
        forces = None
168 16 tkerber
        nats = len(self.atoms)
169 16 tkerber
170 16 tkerber
        for iline, line in enumerate(lines):
171 16 tkerber
            if re.search('Forces \(Ha', line):
172 16 tkerber
                forces = np.zeros((nats,  3),  float)
173 16 tkerber
                for iat in range(nats):
174 16 tkerber
                    forceline = lines[iline+iat+3]
175 16 tkerber
                    words = forceline.split()
176 16 tkerber
                    for idir,  word in enumerate(words[2:5]):
177 16 tkerber
                        forces[iat,  idir] = float(word) * factor
178 16 tkerber
                break
179 16 tkerber
        return forces
180 16 tkerber
181 16 tkerber
    def get_input_block(self, type):
182 16 tkerber
        block = ''
183 16 tkerber
        block += '%chk=ASE-gaussian.chk\n'
184 16 tkerber
        block += '%Mem=256MB\n'
185 16 tkerber
        block += '%nproc=32\n'
186 16 tkerber
        block += 'MaxDisk=16gb\n'
187 16 tkerber
188 16 tkerber
        block += '#'
189 16 tkerber
        block += '%s'%(self.functional)
190 16 tkerber
        block += '/'
191 16 tkerber
        block += '%s'%(self.basis)
192 16 tkerber
193 16 tkerber
        if type == 'force':
194 16 tkerber
            block += 'Force '
195 16 tkerber
#        if self.r_m != None:
196 16 tkerber
#            block += 'Guess=Read'
197 16 tkerber
198 16 tkerber
        block += '\n\nGaussian job\n\n'
199 16 tkerber
200 16 tkerber
        charge = sum(self.atoms.get_charges())
201 16 tkerber
        block += '%i '%(charge)
202 16 tkerber
        block += '%i '%(1)
203 16 tkerber
        block += '\n'
204 16 tkerber
205 16 tkerber
        coords = self.atoms.get_positions()
206 16 tkerber
        for i, at in enumerate(self.atoms.get_chemical_symbols()):
207 16 tkerber
            block += ' %2s'%(at)
208 16 tkerber
            coord = coords[i]
209 16 tkerber
            block += '  %16.5f %16.5f %16.5f'%(coord[0], coord[1], coord[2])
210 16 tkerber
            block += '\n'
211 16 tkerber
212 16 tkerber
        if self.atoms.get_pbc().any():
213 16 tkerber
            cell = self.atoms.get_cell()
214 16 tkerber
215 16 tkerber
            for v in cell:
216 16 tkerber
                block += 'TV %8.3f %8.3f %8.3f\n'%(v[0], v[1], v[2])
217 16 tkerber
        block += '\n'
218 16 tkerber
219 16 tkerber
        return block
220 16 tkerber
221 16 tkerber
222 16 tkerber
    def get_settings(self,  filename=None):
223 16 tkerber
        settings = GaussianSettings()
224 16 tkerber
225 16 tkerber
        if filename != None or filename == '':
226 16 tkerber
            input = self.get_inp(filename)
227 16 tkerber
        else:
228 16 tkerber
            settings.set_functional("")
229 16 tkerber
            return settings
230 16 tkerber
231 16 tkerber
        if input == None:
232 16 tkerber
            settings.set_functional("")
233 16 tkerber
            return settings
234 16 tkerber
235 16 tkerber
        for i, line in enumerate(input):
236 16 tkerber
            if len(line.strip()) == 0:
237 16 tkerber
                continue
238 16 tkerber
            if line[0] == '#':
239 16 tkerber
                keyline = i
240 16 tkerber
                words = line[1:].split()
241 16 tkerber
            else:
242 16 tkerber
                settings.functional = words[0].split('/')[0]
243 16 tkerber
                settings.basis = words[0].split('/')[1]
244 16 tkerber
            break
245 16 tkerber
            return settings
246 16 tkerber
247 16 tkerber
    def update(self,  atoms):
248 16 tkerber
        if self.atoms_old != atoms:
249 16 tkerber
            self.atoms = atoms.copy()
250 16 tkerber
            self.atoms_old = atoms.copy()
251 16 tkerber
            self.run()