root / ase / calculators / turbomole.py @ 2
Historique | Voir | Annoter | Télécharger (6,99 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 | |
6 | 1 | tkerber | |
7 | 1 | tkerber | import os, sys, string |
8 | 1 | tkerber | |
9 | 1 | tkerber | from ase.data import chemical_symbols |
10 | 1 | tkerber | from ase.units import Hartree, Bohr |
11 | 1 | tkerber | from ase.io.turbomole import write_turbomole |
12 | 2 | tkerber | from general import Calculator |
13 | 1 | tkerber | |
14 | 1 | tkerber | import numpy as np |
15 | 1 | tkerber | |
16 | 2 | tkerber | class Turbomole(Calculator): |
17 | 1 | tkerber | """Class for doing Turbomole calculations.
|
18 | 1 | tkerber | """
|
19 | 1 | tkerber | def __init__(self, label='turbomole'): |
20 | 1 | tkerber | """Construct TURBOMOLE-calculator object.
|
21 | 1 | tkerber |
|
22 | 1 | tkerber | Parameters
|
23 | 1 | tkerber | ==========
|
24 | 1 | tkerber | label: str
|
25 | 1 | tkerber | Prefix to use for filenames (label.txt, ...).
|
26 | 1 | tkerber | Default is 'turbomole'.
|
27 | 1 | tkerber |
|
28 | 1 | tkerber | Examples
|
29 | 1 | tkerber | ========
|
30 | 1 | tkerber | This is poor man's version of ASE-Turbomole:
|
31 | 1 | tkerber |
|
32 | 1 | tkerber | First you do a normal turbomole preparation using turbomole's
|
33 | 1 | tkerber | define-program for the initial and final states.
|
34 | 1 | tkerber |
|
35 | 1 | tkerber | (for instance in subdirectories Initial and Final)
|
36 | 1 | tkerber |
|
37 | 1 | tkerber | Then relax the initial and final coordinates with desired constraints
|
38 | 1 | tkerber | using standard turbomole.
|
39 | 1 | tkerber |
|
40 | 1 | tkerber | Copy the relaxed initial and final coordinates
|
41 | 1 | tkerber | (initial.coord and final.coord)
|
42 | 1 | tkerber | and the turbomole related files (from the subdirectory Initial)
|
43 | 1 | tkerber | control, coord, alpha, beta, mos, basis, auxbasis etc to the directory
|
44 | 1 | tkerber | you do the diffusion run.
|
45 | 1 | tkerber |
|
46 | 1 | tkerber | For instance:
|
47 | 1 | tkerber | cd $My_Turbomole_diffusion_directory
|
48 | 1 | tkerber | cd Initial; cp control alpha beta mos basis auxbasis ../;
|
49 | 1 | tkerber | cp coord ../initial.coord;
|
50 | 1 | tkerber | cd ../;
|
51 | 1 | tkerber | cp Final/coord ./final.coord;
|
52 | 1 | tkerber | mkdir Gz ; cp * Gz ; gzip -r Gz
|
53 | 1 | tkerber |
|
54 | 1 | tkerber | from ase.io import read
|
55 | 1 | tkerber | from ase.calculators.turbomole import Turbomole
|
56 | 1 | tkerber | a = read('coord', index=-1, format='turbomole')
|
57 | 1 | tkerber | calc = Turbomole()
|
58 | 1 | tkerber | a.set_calculator(calc)
|
59 | 1 | tkerber | e = a.get_potential_energy()
|
60 | 1 | tkerber |
|
61 | 1 | tkerber | """
|
62 | 1 | tkerber | |
63 | 1 | tkerber | # get names of executables for turbomole energy and forces
|
64 | 1 | tkerber | # get the path
|
65 | 1 | tkerber | |
66 | 1 | tkerber | os.system('rm -f sysname.file; sysname > sysname.file')
|
67 | 1 | tkerber | f = open('sysname.file') |
68 | 1 | tkerber | architechture = f.readline()[:-1]
|
69 | 1 | tkerber | f.close() |
70 | 1 | tkerber | tmpath = os.environ['TURBODIR']
|
71 | 1 | tkerber | pre = tmpath + '/bin/' + architechture + '/' |
72 | 1 | tkerber | |
73 | 1 | tkerber | |
74 | 1 | tkerber | if os.path.isfile('control'): |
75 | 1 | tkerber | f = open('control') |
76 | 1 | tkerber | else:
|
77 | 1 | tkerber | print 'File control is missing' |
78 | 1 | tkerber | raise RuntimeError, \ |
79 | 1 | tkerber | 'Please run Turbomole define and come thereafter back'
|
80 | 1 | tkerber | lines = f.readlines() |
81 | 1 | tkerber | f.close() |
82 | 1 | tkerber | self.tm_program_energy=pre+'dscf' |
83 | 1 | tkerber | self.tm_program_forces=pre+'grad' |
84 | 1 | tkerber | for line in lines: |
85 | 1 | tkerber | if line.startswith('$ricore'): |
86 | 1 | tkerber | self.tm_program_energy=pre+'ridft' |
87 | 1 | tkerber | self.tm_program_forces=pre+'rdgrad' |
88 | 1 | tkerber | |
89 | 1 | tkerber | self.label = label
|
90 | 1 | tkerber | self.converged = False |
91 | 1 | tkerber | #clean up turbomole energy file
|
92 | 1 | tkerber | os.system('rm -f energy; touch energy')
|
93 | 1 | tkerber | |
94 | 1 | tkerber | #turbomole has no stress
|
95 | 1 | tkerber | self.stress = np.empty((3, 3)) |
96 | 1 | tkerber | |
97 | 1 | tkerber | |
98 | 1 | tkerber | def update(self, atoms): |
99 | 1 | tkerber | """Energy and forces are calculated when atoms have moved
|
100 | 1 | tkerber | by calling self.calculate
|
101 | 1 | tkerber | """
|
102 | 1 | tkerber | if (not self.converged or |
103 | 1 | tkerber | len(self.numbers) != len(atoms) or |
104 | 1 | tkerber | (self.numbers != atoms.get_atomic_numbers()).any()):
|
105 | 1 | tkerber | self.initialize(atoms)
|
106 | 1 | tkerber | self.calculate(atoms)
|
107 | 1 | tkerber | elif ((self.positions != atoms.get_positions()).any() or |
108 | 1 | tkerber | (self.pbc != atoms.get_pbc()).any() or |
109 | 1 | tkerber | (self.cell != atoms.get_cell()).any()):
|
110 | 1 | tkerber | self.calculate(atoms)
|
111 | 1 | tkerber | |
112 | 1 | tkerber | def initialize(self, atoms): |
113 | 1 | tkerber | self.numbers = atoms.get_atomic_numbers().copy()
|
114 | 1 | tkerber | self.species = []
|
115 | 1 | tkerber | for a, Z in enumerate(self.numbers): |
116 | 1 | tkerber | self.species.append(Z)
|
117 | 1 | tkerber | self.converged = False |
118 | 1 | tkerber | |
119 | 1 | tkerber | def get_potential_energy(self, atoms): |
120 | 1 | tkerber | self.update(atoms)
|
121 | 1 | tkerber | return self.etotal |
122 | 1 | tkerber | |
123 | 1 | tkerber | def get_forces(self, atoms): |
124 | 1 | tkerber | self.update(atoms)
|
125 | 1 | tkerber | return self.forces.copy() |
126 | 1 | tkerber | |
127 | 1 | tkerber | def get_stress(self, atoms): |
128 | 1 | tkerber | self.update(atoms)
|
129 | 1 | tkerber | return self.stress.copy() |
130 | 1 | tkerber | |
131 | 1 | tkerber | def calculate(self, atoms): |
132 | 1 | tkerber | """Total Turbomole energy is calculated (to file 'energy'
|
133 | 1 | tkerber | also forces are calculated (to file 'gradient')
|
134 | 1 | tkerber | """
|
135 | 1 | tkerber | self.positions = atoms.get_positions().copy()
|
136 | 1 | tkerber | self.cell = atoms.get_cell().copy()
|
137 | 1 | tkerber | self.pbc = atoms.get_pbc().copy()
|
138 | 1 | tkerber | |
139 | 1 | tkerber | #write current coordinates to file 'coord' for Turbomole
|
140 | 1 | tkerber | write_turbomole('coord', atoms)
|
141 | 1 | tkerber | |
142 | 1 | tkerber | |
143 | 1 | tkerber | #Turbomole energy calculation
|
144 | 1 | tkerber | os.system('rm -f output.energy.dummy; \
|
145 | 1 | tkerber | '+ self.tm_program_energy +'> output.energy.dummy') |
146 | 1 | tkerber | |
147 | 1 | tkerber | #check that the energy run converged
|
148 | 1 | tkerber | if os.path.isfile('dscf_problem'): |
149 | 1 | tkerber | print 'Turbomole scf energy calculation did not converge' |
150 | 1 | tkerber | print 'issue command t2x -c > last.xyz' |
151 | 1 | tkerber | print 'and check geometry last.xyz and job.xxx or statistics' |
152 | 1 | tkerber | raise RuntimeError, \ |
153 | 1 | tkerber | 'Please run Turbomole define and come thereafter back'
|
154 | 1 | tkerber | |
155 | 1 | tkerber | |
156 | 1 | tkerber | self.read_energy()
|
157 | 1 | tkerber | |
158 | 1 | tkerber | #Turbomole atomic forces calculation
|
159 | 1 | tkerber | #killing the previous gradient file because
|
160 | 1 | tkerber | #turbomole gradients are affected by the previous values
|
161 | 1 | tkerber | os.system('rm -f gradient; rm -f output.forces.dummy; \
|
162 | 1 | tkerber | '+ self.tm_program_forces +'> output.forces.dummy') |
163 | 1 | tkerber | |
164 | 1 | tkerber | self.read_forces(atoms)
|
165 | 1 | tkerber | |
166 | 1 | tkerber | self.converged = True |
167 | 1 | tkerber | |
168 | 1 | tkerber | |
169 | 1 | tkerber | def read_energy(self): |
170 | 1 | tkerber | """Read Energy from Turbomole energy file."""
|
171 | 1 | tkerber | text = open('energy', 'r').read().lower() |
172 | 1 | tkerber | lines = iter(text.split('\n')) |
173 | 1 | tkerber | |
174 | 1 | tkerber | # Energy:
|
175 | 1 | tkerber | for line in lines: |
176 | 1 | tkerber | if line.startswith('$end'): |
177 | 1 | tkerber | break
|
178 | 1 | tkerber | elif line.startswith('$'): |
179 | 1 | tkerber | pass
|
180 | 1 | tkerber | else:
|
181 | 1 | tkerber | #print 'LINE',line
|
182 | 1 | tkerber | energy_tmp = float(line.split()[1]) |
183 | 1 | tkerber | #print 'energy_tmp',energy_tmp
|
184 | 1 | tkerber | self.etotal = energy_tmp * Hartree
|
185 | 1 | tkerber | |
186 | 1 | tkerber | |
187 | 1 | tkerber | def read_forces(self,atoms): |
188 | 1 | tkerber | """Read Forces from Turbomole gradient file."""
|
189 | 1 | tkerber | |
190 | 1 | tkerber | file = open('gradient','r') |
191 | 1 | tkerber | line=file.readline()
|
192 | 1 | tkerber | line=file.readline()
|
193 | 1 | tkerber | tmpforces = np.array([[0, 0, 0]]) |
194 | 1 | tkerber | while line:
|
195 | 1 | tkerber | if 'cycle' in line: |
196 | 1 | tkerber | for i, dummy in enumerate(atoms): |
197 | 1 | tkerber | line=file.readline()
|
198 | 1 | tkerber | forces_tmp=[] |
199 | 1 | tkerber | for i, dummy in enumerate(atoms): |
200 | 1 | tkerber | line=file.readline()
|
201 | 1 | tkerber | line2=string.replace(line,'D','E') |
202 | 1 | tkerber | #tmp=np.append(forces_tmp,np.array\
|
203 | 1 | tkerber | # ([[float(f) for f in line2.split()[0:3]]]))
|
204 | 1 | tkerber | tmp=np.array\ |
205 | 1 | tkerber | ([[float(f) for f in line2.split()[0:3]]]) |
206 | 1 | tkerber | tmpforces=np.concatenate((tmpforces,tmp)) |
207 | 1 | tkerber | line=file.readline()
|
208 | 1 | tkerber | |
209 | 1 | tkerber | |
210 | 1 | tkerber | #note the '-' sign for turbomole, to get forces
|
211 | 1 | tkerber | self.forces = (-np.delete(tmpforces, np.s_[0:1], axis=0))*Hartree/Bohr |
212 | 1 | tkerber | |
213 | 1 | tkerber | #print 'forces', self.forces
|
214 | 1 | tkerber | |
215 | 1 | tkerber | def read(self): |
216 | 1 | tkerber | """Dummy stress for turbomole"""
|
217 | 1 | tkerber | self.stress = np.empty((3, 3)) |