Statistiques
| Révision :

root / ase / calculators / turbomole.py @ 10

Historique | Voir | Annoter | Télécharger (5,14 ko)

1 1 tkerber
"""This module defines an ASE interface to Turbomole
2 1 tkerber
http://www.turbomole.com/
3 1 tkerber
"""
4 1 tkerber
import os, sys, string
5 1 tkerber
6 1 tkerber
from ase.units import Hartree, Bohr
7 1 tkerber
from ase.io.turbomole import write_turbomole
8 3 tkerber
from ase.calculators.general import Calculator
9 1 tkerber
10 1 tkerber
import numpy as np
11 1 tkerber
12 2 tkerber
class Turbomole(Calculator):
13 3 tkerber
    def __init__(self, label='turbomole', calculate_energy="dscf", calculate_forces="grad", post_HF = False):
14 1 tkerber
        self.label = label
15 1 tkerber
        self.converged = False
16 3 tkerber
17 3 tkerber
        # set calculators for energy and forces
18 3 tkerber
        self.calculate_energy = calculate_energy
19 3 tkerber
        self.calculate_forces = calculate_forces
20 1 tkerber
21 3 tkerber
        # turbomole has no stress
22 1 tkerber
        self.stress = np.empty((3, 3))
23 1 tkerber
24 3 tkerber
        # storage for energy and forces
25 3 tkerber
        self.e_total = None
26 3 tkerber
        self.forces = None
27 3 tkerber
        self.updated = False
28 3 tkerber
29 3 tkerber
        # atoms must be set
30 3 tkerber
        self.atoms = None
31 3 tkerber
32 3 tkerber
        # POST-HF method
33 3 tkerber
        self.post_HF  = post_HF
34 1 tkerber
35 1 tkerber
    def initialize(self, atoms):
36 1 tkerber
        self.numbers = atoms.get_atomic_numbers().copy()
37 1 tkerber
        self.species = []
38 1 tkerber
        for a, Z in enumerate(self.numbers):
39 1 tkerber
            self.species.append(Z)
40 1 tkerber
        self.converged = False
41 1 tkerber
42 3 tkerber
    def execute(self, command):
43 3 tkerber
        from subprocess import Popen, PIPE
44 3 tkerber
        try:
45 5 tkerber
            # the sub process gets started here
46 3 tkerber
            proc = Popen([command], shell=True, stderr=PIPE)
47 3 tkerber
            error = proc.communicate()[1]
48 8 tkerber
            # check the control file for "actual step" keyword
49 8 tkerber
            file = open("control")
50 8 tkerber
            data = file.read()
51 8 tkerber
            if "$actual step" in data:
52 8 tkerber
                raise OSError(error)
53 7 tkerber
            # print "TM command: ", command, "successfully executed"
54 3 tkerber
        except OSError, e:
55 5 tkerber
            print >>sys.stderr, "Execution failed: ", e
56 3 tkerber
            sys.exit(1)
57 3 tkerber
58 1 tkerber
    def get_potential_energy(self, atoms):
59 3 tkerber
        # update atoms
60 3 tkerber
        self.set_atoms(atoms)
61 3 tkerber
        # if update of energy is neccessary
62 3 tkerber
        if self.update_energy:
63 3 tkerber
            # calculate energy
64 3 tkerber
            self.execute(self.calculate_energy + " > ASE.TM.energy.out")
65 3 tkerber
            # check for convergence of dscf cycle
66 3 tkerber
            if os.path.isfile('dscf_problem'):
67 3 tkerber
                print 'Turbomole scf energy calculation did not converge'
68 3 tkerber
                raise RuntimeError, \
69 3 tkerber
                    'Please run Turbomole define and come thereafter back'
70 3 tkerber
            # read energy
71 3 tkerber
            self.read_energy()
72 3 tkerber
        else :
73 3 tkerber
            print "taking old values (E)"
74 3 tkerber
        self.update_energy = False
75 3 tkerber
        return self.e_total
76 1 tkerber
77 1 tkerber
    def get_forces(self, atoms):
78 3 tkerber
        # update atoms
79 3 tkerber
        self.set_atoms(atoms)
80 3 tkerber
        # complete energy calculations
81 3 tkerber
        if self.update_energy:
82 3 tkerber
            self.get_potential_energy(atoms)
83 3 tkerber
        # if update of forces is neccessary
84 3 tkerber
        if self.update_forces:
85 3 tkerber
            # calculate forces
86 10 tkerber
            if self.calculate_forces is not None:
87 10 tkerber
                self.execute(self.calculate_forces + " > ASE.TM.forces.out")
88 3 tkerber
            # read forces
89 3 tkerber
            self.read_forces()
90 3 tkerber
        else :
91 3 tkerber
            print "taking old values (F)"
92 3 tkerber
        self.update_forces = False
93 1 tkerber
        return self.forces.copy()
94 1 tkerber
95 1 tkerber
    def get_stress(self, atoms):
96 5 tkerber
        return self.stress
97 3 tkerber
98 3 tkerber
    def set_atoms(self, atoms):
99 3 tkerber
        if self.atoms == atoms:
100 3 tkerber
            return
101 3 tkerber
        # performs an update of the atoms
102 3 tkerber
        super(Turbomole, self).set_atoms(atoms)
103 1 tkerber
        write_turbomole('coord', atoms)
104 3 tkerber
        # energy and forces must be re-calculated
105 3 tkerber
        self.update_energy = True
106 3 tkerber
        self.update_forces = True
107 1 tkerber
108 1 tkerber
    def read_energy(self):
109 1 tkerber
        """Read Energy from Turbomole energy file."""
110 1 tkerber
        text = open('energy', 'r').read().lower()
111 1 tkerber
        lines = iter(text.split('\n'))
112 1 tkerber
113 1 tkerber
        # Energy:
114 1 tkerber
        for line in lines:
115 1 tkerber
            if line.startswith('$end'):
116 1 tkerber
                break
117 1 tkerber
            elif line.startswith('$'):
118 1 tkerber
                pass
119 1 tkerber
            else:
120 3 tkerber
                # print 'LINE',line
121 1 tkerber
                energy_tmp = float(line.split()[1])
122 3 tkerber
                if self.post_HF:
123 3 tkerber
                    energy_tmp += float(line.split()[4])
124 5 tkerber
        # update energy units
125 3 tkerber
        self.e_total = energy_tmp * Hartree
126 3 tkerber
127 1 tkerber
128 3 tkerber
    def read_forces(self):
129 1 tkerber
        """Read Forces from Turbomole gradient file."""
130 1 tkerber
        file = open('gradient','r')
131 3 tkerber
        lines=file.readlines()
132 3 tkerber
        file.close()
133 1 tkerber
134 3 tkerber
        forces = np.array([[0, 0, 0]])
135 3 tkerber
136 3 tkerber
        nline = len(lines)
137 3 tkerber
        iline = -1
138 3 tkerber
139 3 tkerber
        for i in xrange(nline):
140 3 tkerber
            if 'cycle' in lines[i]:
141 3 tkerber
                iline = i
142 3 tkerber
143 3 tkerber
        if iline < 0:
144 3 tkerber
            print 'Gradients not found'
145 3 tkerber
            raise RuntimeError("Please check TURBOMOLE gradients")
146 1 tkerber
147 5 tkerber
        # next line
148 3 tkerber
        iline += len(self.atoms) + 1
149 5 tkerber
        # $end line
150 3 tkerber
        nline -= 1
151 5 tkerber
        # read gradients
152 3 tkerber
        for i in xrange(iline, nline):
153 3 tkerber
            line = string.replace(lines[i],'D','E')
154 3 tkerber
            #tmp=np.append(forces_tmp,np.array\
155 3 tkerber
            #      ([[float(f) for f in line.split()[0:3]]]))
156 3 tkerber
            tmp=np.array([[float(f) for f in line.split()[0:3]]])
157 3 tkerber
            forces=np.concatenate((forces,tmp))
158 3 tkerber
        #note the '-' sign for turbomole, to get forces
159 3 tkerber
        self.forces = (-np.delete(forces, np.s_[0:1], axis=0))*Hartree/Bohr