Statistiques
| Révision :

root / ase / calculators / turbomole.py @ 16

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

1 1 tkerber
"""
2 13 tkerber
This module is the EMBED module for ASE
3 13 tkerber
implemented by T. Kerber
4 13 tkerber

5 13 tkerber
Torsten Kerber, ENS LYON: 2011, 07, 11
6 13 tkerber

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