Statistiques
| Révision :

root / ase / calculators / turbomole.py @ 3

Historique | Voir | Annoter | Télécharger (6,27 ko)

1 1 tkerber
"""This module defines an ASE interface to Turbomole
2 1 tkerber

3 1 tkerber
http://www.turbomole.com/
4 1 tkerber
"""
5 1 tkerber
import os, sys, string
6 1 tkerber
7 1 tkerber
from ase.units import Hartree, Bohr
8 1 tkerber
from ase.io.turbomole import write_turbomole
9 3 tkerber
from ase.calculators.general import Calculator
10 1 tkerber
11 1 tkerber
import numpy as np
12 1 tkerber
13 2 tkerber
class Turbomole(Calculator):
14 1 tkerber
    """Class for doing Turbomole calculations.
15 1 tkerber
    """
16 3 tkerber
    def __init__(self, label='turbomole', calculate_energy="dscf", calculate_forces="grad", post_HF = False):
17 1 tkerber
        """Construct TURBOMOLE-calculator object.
18 1 tkerber

19 1 tkerber
        Parameters
20 1 tkerber
        ==========
21 1 tkerber
        label: str
22 1 tkerber
            Prefix to use for filenames (label.txt, ...).
23 1 tkerber
            Default is 'turbomole'.
24 1 tkerber

25 1 tkerber
        Examples
26 1 tkerber
        ========
27 1 tkerber
        This is poor man's version of ASE-Turbomole:
28 1 tkerber

29 1 tkerber
        First you do a normal turbomole preparation using turbomole's
30 1 tkerber
        define-program for the initial and final states.
31 1 tkerber

32 1 tkerber
        (for instance in subdirectories Initial and Final)
33 1 tkerber

34 1 tkerber
        Then relax the initial and final coordinates with desired constraints
35 1 tkerber
        using standard turbomole.
36 1 tkerber

37 1 tkerber
        Copy the relaxed initial and final coordinates
38 1 tkerber
        (initial.coord and final.coord)
39 1 tkerber
        and the turbomole related files (from the subdirectory Initial)
40 1 tkerber
        control, coord, alpha, beta, mos, basis, auxbasis etc to the directory
41 1 tkerber
        you do the diffusion run.
42 1 tkerber

43 1 tkerber
        For instance:
44 1 tkerber
        cd $My_Turbomole_diffusion_directory
45 1 tkerber
        cd Initial; cp control alpha beta mos basis auxbasis ../;
46 1 tkerber
        cp coord ../initial.coord;
47 1 tkerber
        cd ../;
48 1 tkerber
        cp Final/coord ./final.coord;
49 1 tkerber
        mkdir Gz ; cp * Gz ; gzip -r Gz
50 1 tkerber

51 1 tkerber
        from ase.io import read
52 1 tkerber
        from ase.calculators.turbomole import Turbomole
53 1 tkerber
        a = read('coord', index=-1, format='turbomole')
54 1 tkerber
        calc = Turbomole()
55 1 tkerber
        a.set_calculator(calc)
56 1 tkerber
        e = a.get_potential_energy()
57 1 tkerber

58 1 tkerber
        """
59 3 tkerber
60 1 tkerber
        self.label = label
61 1 tkerber
        self.converged = False
62 3 tkerber
63 3 tkerber
        # set calculators for energy and forces
64 3 tkerber
        self.calculate_energy = calculate_energy
65 3 tkerber
        self.calculate_forces = calculate_forces
66 1 tkerber
67 3 tkerber
        # turbomole has no stress
68 1 tkerber
        self.stress = np.empty((3, 3))
69 1 tkerber
70 3 tkerber
        # storage for energy and forces
71 3 tkerber
        self.e_total = None
72 3 tkerber
        self.forces = None
73 3 tkerber
        self.updated = False
74 3 tkerber
75 3 tkerber
        # atoms must be set
76 3 tkerber
        self.atoms = None
77 3 tkerber
78 3 tkerber
        # POST-HF method
79 3 tkerber
        self.post_HF  = post_HF
80 1 tkerber
81 1 tkerber
    def initialize(self, atoms):
82 1 tkerber
        self.numbers = atoms.get_atomic_numbers().copy()
83 1 tkerber
        self.species = []
84 1 tkerber
        for a, Z in enumerate(self.numbers):
85 1 tkerber
            self.species.append(Z)
86 1 tkerber
        self.converged = False
87 1 tkerber
88 3 tkerber
    def execute(self, command):
89 3 tkerber
        from subprocess import Popen, PIPE
90 3 tkerber
        try:
91 3 tkerber
            proc = Popen([command], shell=True, stderr=PIPE)
92 3 tkerber
            error = proc.communicate()[1]
93 3 tkerber
            if "abnormally" in error:
94 3 tkerber
                raise OSError(error)
95 3 tkerber
            print "TM command: ", command, "successfully executed"
96 3 tkerber
        except OSError, e:
97 3 tkerber
            print >>sys.stderr, "Execution failed:", e
98 3 tkerber
            sys.exit(1)
99 3 tkerber
100 1 tkerber
    def get_potential_energy(self, atoms):
101 3 tkerber
        # update atoms
102 3 tkerber
        self.set_atoms(atoms)
103 3 tkerber
        # if update of energy is neccessary
104 3 tkerber
        if self.update_energy:
105 3 tkerber
            # calculate energy
106 3 tkerber
            self.execute(self.calculate_energy + " > ASE.TM.energy.out")
107 3 tkerber
            # check for convergence of dscf cycle
108 3 tkerber
            if os.path.isfile('dscf_problem'):
109 3 tkerber
                print 'Turbomole scf energy calculation did not converge'
110 3 tkerber
                raise RuntimeError, \
111 3 tkerber
                    'Please run Turbomole define and come thereafter back'
112 3 tkerber
            # read energy
113 3 tkerber
            self.read_energy()
114 3 tkerber
        else :
115 3 tkerber
            print "taking old values (E)"
116 3 tkerber
        self.update_energy = False
117 3 tkerber
        return self.e_total
118 1 tkerber
119 1 tkerber
    def get_forces(self, atoms):
120 3 tkerber
        # update atoms
121 3 tkerber
        self.set_atoms(atoms)
122 3 tkerber
        # complete energy calculations
123 3 tkerber
        if self.update_energy:
124 3 tkerber
            self.get_potential_energy(atoms)
125 3 tkerber
        # if update of forces is neccessary
126 3 tkerber
        if self.update_forces:
127 3 tkerber
            # calculate forces
128 3 tkerber
            self.execute(self.calculate_forces + " > ASE.TM.forces.out")
129 3 tkerber
            # read forces
130 3 tkerber
            self.read_forces()
131 3 tkerber
        else :
132 3 tkerber
            print "taking old values (F)"
133 3 tkerber
        self.update_forces = False
134 1 tkerber
        return self.forces.copy()
135 1 tkerber
136 1 tkerber
    def get_stress(self, atoms):
137 1 tkerber
        return self.stress.copy()
138 3 tkerber
139 3 tkerber
    def set_atoms(self, atoms):
140 3 tkerber
        if self.atoms == atoms:
141 3 tkerber
            return
142 3 tkerber
        # performs an update of the atoms
143 3 tkerber
        super(Turbomole, self).set_atoms(atoms)
144 1 tkerber
        write_turbomole('coord', atoms)
145 3 tkerber
        # energy and forces must be re-calculated
146 3 tkerber
        self.update_energy = True
147 3 tkerber
        self.update_forces = True
148 1 tkerber
149 1 tkerber
    def read_energy(self):
150 1 tkerber
        """Read Energy from Turbomole energy file."""
151 1 tkerber
        text = open('energy', 'r').read().lower()
152 1 tkerber
        lines = iter(text.split('\n'))
153 1 tkerber
154 1 tkerber
        # Energy:
155 1 tkerber
        for line in lines:
156 1 tkerber
            if line.startswith('$end'):
157 1 tkerber
                break
158 1 tkerber
            elif line.startswith('$'):
159 1 tkerber
                pass
160 1 tkerber
            else:
161 3 tkerber
                # print 'LINE',line
162 1 tkerber
                energy_tmp = float(line.split()[1])
163 3 tkerber
                if self.post_HF:
164 3 tkerber
                    energy_tmp += float(line.split()[4])
165 3 tkerber
        self.e_total = energy_tmp * Hartree
166 3 tkerber
167 1 tkerber
168 3 tkerber
    def read_forces(self):
169 1 tkerber
        """Read Forces from Turbomole gradient file."""
170 1 tkerber
        file = open('gradient','r')
171 3 tkerber
        lines=file.readlines()
172 3 tkerber
        file.close()
173 1 tkerber
174 3 tkerber
        forces = np.array([[0, 0, 0]])
175 3 tkerber
176 3 tkerber
        nline = len(lines)
177 3 tkerber
        iline = -1
178 3 tkerber
179 3 tkerber
        for i in xrange(nline):
180 3 tkerber
            if 'cycle' in lines[i]:
181 3 tkerber
                iline = i
182 3 tkerber
183 3 tkerber
        if iline < 0:
184 3 tkerber
            print 'Gradients not found'
185 3 tkerber
            raise RuntimeError("Please check TURBOMOLE gradients")
186 1 tkerber
187 3 tkerber
        iline += len(self.atoms) + 1
188 3 tkerber
        nline -= 1
189 3 tkerber
        for i in xrange(iline, nline):
190 3 tkerber
            line = string.replace(lines[i],'D','E')
191 3 tkerber
            #tmp=np.append(forces_tmp,np.array\
192 3 tkerber
            #      ([[float(f) for f in line.split()[0:3]]]))
193 3 tkerber
            tmp=np.array([[float(f) for f in line.split()[0:3]]])
194 3 tkerber
            forces=np.concatenate((forces,tmp))
195 3 tkerber
        #note the '-' sign for turbomole, to get forces
196 3 tkerber
        self.forces = (-np.delete(forces, np.s_[0:1], axis=0))*Hartree/Bohr