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