Statistiques
| Révision :

root / ase / calculators / dftb.py @ 5

Historique | Voir | Annoter | Télécharger (18,46 ko)

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

3 1 tkerber
http://http://www.dftb-plus.info//
4 1 tkerber
http://www.dftb.org/
5 1 tkerber

6 1 tkerber
-Markus Kaukonen markus.kaukonen@iki.fi
7 1 tkerber
"""
8 1 tkerber
9 1 tkerber
10 1 tkerber
import numpy as np
11 1 tkerber
import os, string
12 1 tkerber
13 1 tkerber
#from ase.data import chemical_symbols
14 1 tkerber
from ase.units import Hartree, Bohr
15 1 tkerber
16 1 tkerber
17 1 tkerber
class Dftb:
18 1 tkerber
    """Class for doing DFTB+ calculations.
19 1 tkerber
    """
20 1 tkerber
    def __init__(self, label='dftb', write_dftb=False,
21 1 tkerber
                 charge=0.0, include_dispersion=False,
22 1 tkerber
                 do_spin_polarized=False,
23 1 tkerber
                 unpaired_electrons=0.0,
24 1 tkerber
                 fermi_temperature=0.0, scc=False):
25 1 tkerber
        """Construct DFTB-calculator object.
26 1 tkerber

27 1 tkerber

28 1 tkerber
        For example:
29 1 tkerber
        calc = Dftb(label='dftb',write_dftb=True,include_dispersion=True )
30 1 tkerber

31 1 tkerber
        Parameters
32 1 tkerber
        ==========
33 1 tkerber
        label: str
34 1 tkerber
            Prefix to use for filenames (label.txt, ...).
35 1 tkerber
            Default is 'dftb'.
36 1 tkerber
        write_dftb: boolean
37 1 tkerber
            True: a minimal input file (name of which is always 'dftb_in.hsd')
38 1 tkerber
            is written based on values given here.
39 1 tkerber
            False: input file for dftb+ is not written. User must have
40 1 tkerber
            generated file 'dftb_in.hsd' in the working directory.
41 1 tkerber
            Use write_dftb=False to use your own 'dftb_in.hsd'-file.
42 1 tkerber
        charge: float
43 1 tkerber
            Total charge of the system.
44 1 tkerber
        include_dispersion: boolean
45 1 tkerber
            True: Default dispersion parameters are written in the
46 1 tkerber
            file 'dftb_in.hsd' (requires that also write_dftb_input_file==True)
47 1 tkerber
            False: dispersion parameters are not written here.
48 1 tkerber
        do_spin_polarized: boolean
49 1 tkerber
            True: Spin polarized calculation
50 1 tkerber
            (requires that also write_dftb_input_file==True)
51 1 tkerber
            False: Spin unpolarized calculation
52 1 tkerber
        unpaired_electrons: float
53 1 tkerber
            Number of spin unpaired electrons in the system.
54 1 tkerber
            Relevant only if do_spin_polarized==True
55 1 tkerber
        fermi_temperature: float
56 1 tkerber
            Fermi temperature for electrons.
57 1 tkerber
        scc: boolean
58 1 tkerber
            True: Do charge self consistent dftb+
59 1 tkerber
            False: No SCC, charges on atoms are not iterated
60 1 tkerber

61 1 tkerber
        Input file for DFTB+ file is 'dftb_in.hsd'. Keywords in it are
62 1 tkerber
        written here or read from an existing file. The atom positions
63 1 tkerber
        in file 'dftb_in.hsd' are updated during ASE geometry
64 1 tkerber
        optimization.
65 1 tkerber
        """
66 1 tkerber
67 1 tkerber
68 1 tkerber
        if not(write_dftb):
69 1 tkerber
            if os.path.isfile('dftb_in.hsd'):
70 1 tkerber
                f = open('dftb_in.hsd')
71 1 tkerber
            else:
72 1 tkerber
                print 'Input file for DFTB+ dftb_in.hsd is missing'
73 1 tkerber
                raise RuntimeError, \
74 1 tkerber
                    'Provide it or set write_dftb=True '
75 1 tkerber
            #lines = f.readlines()
76 1 tkerber
            f.close()
77 1 tkerber
78 1 tkerber
        self.label = label
79 1 tkerber
        self.write_dftb = write_dftb
80 1 tkerber
        self.charge = charge
81 1 tkerber
        self.include_dispersion = include_dispersion
82 1 tkerber
        self.do_spin_polarized = do_spin_polarized
83 1 tkerber
        self.unpaired_electrons = unpaired_electrons
84 1 tkerber
        #if (do_spin_polarized):
85 1 tkerber
        #    print 'Sorry, generation of file "dftb_in.hsd" with spin '
86 1 tkerber
        #    print 'polarization is not inplemented for DFTB+'
87 1 tkerber
        #    print 'Set write_dftb=False and'
88 1 tkerber
        #    raise RuntimeError, \
89 1 tkerber
        #        'Generate file "dftb_in.hsd by hand"'
90 1 tkerber
91 1 tkerber
        self.etotal = 0.0
92 1 tkerber
        self.cell = None
93 1 tkerber
        self.fermi_temperature = fermi_temperature
94 1 tkerber
        self.scc = scc
95 1 tkerber
        self.converged = False
96 1 tkerber
97 1 tkerber
        #dftb has no stress
98 1 tkerber
        self.stress = np.empty((3, 3))
99 1 tkerber
100 1 tkerber
101 1 tkerber
    def update(self, atoms):
102 1 tkerber
        """Energy and forces are calculated when atoms have moved
103 1 tkerber
        by calling self.calculate
104 1 tkerber
        """
105 1 tkerber
        if (not self.converged or
106 1 tkerber
            len(self.typenumber) != len(atoms)):
107 1 tkerber
            self.initialize(atoms)
108 1 tkerber
            self.calculate(atoms)
109 1 tkerber
        elif ((self.positions != atoms.get_positions()).any() or
110 1 tkerber
              (self.pbc != atoms.get_pbc()).any() or
111 1 tkerber
              (self.cell != atoms.get_cell()).any()):
112 1 tkerber
            self.calculate(atoms)
113 1 tkerber
114 1 tkerber
    def initialize(self, atoms):
115 1 tkerber
        #from ase.io.dftb import read_dftb
116 1 tkerber
117 1 tkerber
        atomtypes = atoms.get_chemical_symbols()
118 1 tkerber
        self.allspecies = []
119 1 tkerber
        self.typenumber = []
120 1 tkerber
        self.max_angular_momentum = []
121 1 tkerber
        for species in (atomtypes):
122 1 tkerber
            if species not in self.allspecies:
123 1 tkerber
                self.allspecies.append(species)
124 1 tkerber
        for species in (atomtypes):
125 1 tkerber
            myindex = 1 + self.allspecies.index(species)
126 1 tkerber
            self.typenumber.append(myindex)
127 1 tkerber
        for i in self.allspecies:
128 1 tkerber
            if i == 'H':
129 1 tkerber
                self.max_angular_momentum.append('s')
130 1 tkerber
            elif i in ['C','N','O']:
131 1 tkerber
                self.max_angular_momentum.append('p')
132 1 tkerber
            elif i in ['Si','S','Fe','Ni']:
133 1 tkerber
                self.max_angular_momentum.append('d')
134 1 tkerber
            else:
135 1 tkerber
                print 'anglular momentum is not imlemented in ASE-DFTB+'
136 1 tkerber
                print 'for species '+i
137 1 tkerber
                raise RuntimeError('Use option write_dftb=False')
138 1 tkerber
        self.converged = False
139 1 tkerber
140 1 tkerber
        #write DFTB input file if desired
141 1 tkerber
        self.positions = atoms.get_positions().copy()
142 1 tkerber
        if self.write_dftb:
143 1 tkerber
            self.write_dftb_input_file(atoms)
144 1 tkerber
145 1 tkerber
146 1 tkerber
    def get_potential_energy(self, atoms):
147 1 tkerber
        self.update(atoms)
148 1 tkerber
        return self.etotal
149 1 tkerber
150 1 tkerber
    def get_forces(self, atoms):
151 1 tkerber
        self.update(atoms)
152 1 tkerber
        return self.forces.copy()
153 1 tkerber
154 1 tkerber
    def get_stress(self, atoms):
155 1 tkerber
        self.update(atoms)
156 1 tkerber
        return self.stress.copy()
157 1 tkerber
158 1 tkerber
    def calculate(self, atoms):
159 1 tkerber
        """Total DFTB energy is calculated (to file 'energy'
160 1 tkerber
        also forces are calculated (to file 'gradient')
161 1 tkerber
        """
162 1 tkerber
163 1 tkerber
        self.positions = atoms.get_positions().copy()
164 1 tkerber
        self.cell = atoms.get_cell().copy()
165 1 tkerber
        self.pbc = atoms.get_pbc().copy()
166 1 tkerber
167 1 tkerber
        if self.write_dftb:
168 1 tkerber
            self.write_dftb_input_file(atoms)
169 1 tkerber
        else:
170 1 tkerber
            #write current coordinates to file 'dftb_in.hsd' for DFTB+
171 1 tkerber
            self.change_atom_positions_dftb(atoms)
172 1 tkerber
173 1 tkerber
174 1 tkerber
        #DFTB energy&forces calculation
175 1 tkerber
        if (os.environ.has_key('DFTB_COMMAND') and
176 1 tkerber
            (os.environ.has_key('DFTB_PREFIX'))):
177 1 tkerber
            dftb = os.environ['DFTB_COMMAND']
178 1 tkerber
            exitcode = os.system(dftb+ '> dftb.output' )
179 1 tkerber
        elif not(os.environ.has_key('DFTB_COMMAND')):
180 1 tkerber
            raise RuntimeError('Please set DFTB_COMMAND environment variable')
181 1 tkerber
        elif not(os.environ.has_key('DFTB_PREFIX')):
182 1 tkerber
            print 'Path for DFTB+ slater koster files is missing'
183 1 tkerber
            raise RuntimeError('Please set DFTB_PREFIX environment variable')
184 1 tkerber
        else:
185 1 tkerber
            pass
186 1 tkerber
        if exitcode != 0:
187 1 tkerber
            raise RuntimeError('Dftb exited with exit code: %d.  ' % exitcode)
188 1 tkerber
189 1 tkerber
        self.read_energy()
190 1 tkerber
191 1 tkerber
        #DFTB atomic forces calculation, to be read in file detailed.out
192 1 tkerber
        #os.system(self.dftb_program_forces +'> output.forces.dummy')
193 1 tkerber
194 1 tkerber
        self.read_forces(atoms)
195 1 tkerber
196 1 tkerber
        self.converged = True
197 1 tkerber
198 1 tkerber
199 1 tkerber
    def read_energy(self):
200 1 tkerber
        """Read Energy from DFTB energy file."""
201 1 tkerber
        text = open('dftb.output', 'r').read().lower()
202 1 tkerber
        lines = iter(text.split('\n'))
203 1 tkerber
204 1 tkerber
        # Energy:
205 1 tkerber
        for line in lines:
206 1 tkerber
            if 'total energy' in line:
207 1 tkerber
                energy_tmp = float(line.split()[2])
208 1 tkerber
                #print 'energy_tmp', energy_tmp
209 1 tkerber
        self.etotal = energy_tmp * Hartree
210 1 tkerber
211 1 tkerber
212 1 tkerber
    def read_forces(self, atoms):
213 1 tkerber
        """Read Forces from DFTB+ detailed.out output file"""
214 1 tkerber
215 1 tkerber
        myfile = open('detailed.out','r')
216 1 tkerber
        line = myfile.readline()
217 1 tkerber
        line = myfile.readline()
218 1 tkerber
        tmpforces = np.array([[0, 0, 0]])
219 1 tkerber
        while line:
220 1 tkerber
            if 'Total Forces' in line:
221 1 tkerber
                for i, dummy in enumerate(atoms):
222 1 tkerber
                    line = myfile.readline()
223 1 tkerber
                    line2 = string.replace(line, 'D', 'E')
224 1 tkerber
                    tmp = np.array\
225 1 tkerber
                        ([[float(f) for f in line2.split()[0:3]]])
226 1 tkerber
                    tmpforces = np.concatenate((tmpforces, tmp))
227 1 tkerber
            line = myfile.readline()
228 1 tkerber
229 1 tkerber
230 1 tkerber
        self.forces = (np.delete(tmpforces, np.s_[0:1], axis=0))*Hartree/Bohr
231 1 tkerber
232 1 tkerber
        #print 'forces', self.forces
233 1 tkerber
234 1 tkerber
    def read(self):
235 1 tkerber
        """Dummy stress for dftb"""
236 1 tkerber
        self.stress = np.empty((3, 3))
237 1 tkerber
238 1 tkerber
    def write_dftb_input_file(self, atoms):
239 1 tkerber
        """Write input parameters to DFTB+ input file 'dftb_in.hsd'."""
240 1 tkerber
        import sys
241 1 tkerber
        fh = open('dftb_in.hsd', 'w')
242 1 tkerber
        # geometry
243 1 tkerber
        fh.write('Geometry = {\n')
244 1 tkerber
        fh.write('TypeNames = {')
245 1 tkerber
        for i in self.allspecies:
246 1 tkerber
            fh.write(' "'+i+'"')
247 1 tkerber
        fh.write(' }\n')
248 1 tkerber
        fh.write('TypesAndCoordinates [Angstrom] = {\n')
249 1 tkerber
        self.positions = atoms.get_positions().copy()
250 1 tkerber
        for i, pos in zip(self.typenumber, self.positions):
251 1 tkerber
            fh.write('%6d ' % (i))
252 1 tkerber
            fh.write('%20.14f %20.14f %20.14f' %  tuple(pos))
253 1 tkerber
            fh.write('\n')
254 1 tkerber
        fh.write(' }\n')
255 1 tkerber
256 1 tkerber
        #is it periodic and when is write also lattice vectors
257 1 tkerber
        periodic = atoms.get_pbc().any()
258 1 tkerber
        if periodic:
259 1 tkerber
            fh.write('Periodic = Yes\n')
260 1 tkerber
        else:
261 1 tkerber
            fh.write('Periodic = No\n')
262 1 tkerber
        if periodic:
263 1 tkerber
            cell = atoms.get_cell().copy()
264 1 tkerber
            fh.write('LatticeVectors [Angstrom] = {\n')
265 1 tkerber
            for v in cell:
266 1 tkerber
                fh.write('%20.14f %20.14f %20.14f \n' %  tuple(v))
267 1 tkerber
            fh.write('  }\n')
268 1 tkerber
269 1 tkerber
        #end of geometry session
270 1 tkerber
        fh.write('}\n')
271 1 tkerber
272 1 tkerber
        #zero step CG relaxation to get forces and energies
273 1 tkerber
        # these are dummies because ASE takes care of these things
274 1 tkerber
        fh.write('\n')
275 1 tkerber
        fh.write('Driver = ConjugateGradient {\n')
276 1 tkerber
        fh.write('MovedAtoms = Range { 1 -1 }\n')
277 1 tkerber
        fh.write('  MaxForceComponent = 1.0e-4\n')
278 1 tkerber
        fh.write('  MaxSteps = 0\n')
279 1 tkerber
        fh.write('  OutputPrefix = '+self.label+ '\n')
280 1 tkerber
        fh.write('}\n')
281 1 tkerber
282 1 tkerber
        #Hamiltonian
283 1 tkerber
        fh.write('\n')
284 1 tkerber
        fh.write('Hamiltonian = DFTB { # DFTB Hamiltonian\n')
285 1 tkerber
        if (self.scc):
286 1 tkerber
            fh.write('  SCC = Yes')
287 1 tkerber
            fh.write(' # Use self consistent charges\n')
288 1 tkerber
            fh.write('  SCCTolerance = 1.0e-5')
289 1 tkerber
            fh.write(' # Tolerance for charge consistence\n')
290 1 tkerber
            fh.write('  MaxSCCIterations = 1000')
291 1 tkerber
            fh.write(' # Nr. of maximal SCC iterations\n')
292 1 tkerber
            fh.write('  Mixer = Broyden {')
293 1 tkerber
            fh.write(' # Broyden mixer for charge mixing\n')
294 1 tkerber
            fh.write('    MixingParameter = 0.2')
295 1 tkerber
            fh.write(' # Mixing parameter\n')
296 1 tkerber
            fh.write('  }\n')
297 1 tkerber
        else:
298 1 tkerber
            fh.write('  SCC = No # NO self consistent charges\n')
299 1 tkerber
        fh.write('  SlaterKosterFiles = Type2FileNames {')
300 1 tkerber
        fh.write(' # File names from two atom type names\n')
301 1 tkerber
        sk_prefix = os.environ['DFTB_PREFIX']
302 1 tkerber
        fh.write('    Prefix = "'+sk_prefix+'"')
303 1 tkerber
        fh.write(' # Path as prefix\n')
304 1 tkerber
        fh.write('    Separator = "-"')
305 1 tkerber
        fh.write(' # Dash between type names\n')
306 1 tkerber
        fh.write('    Suffix = ".skf"')
307 1 tkerber
        fh.write(' # Suffix after second type name\n')
308 1 tkerber
        fh.write('  }\n')
309 1 tkerber
        fh.write('  MaxAngularMomentum = {')
310 1 tkerber
        fh.write(' # Maximal l-value of the various species\n')
311 1 tkerber
        for i, j in zip(self.allspecies, self.max_angular_momentum):
312 1 tkerber
            fh.write('   '+i+' = "'+j+'"\n')
313 1 tkerber
        fh.write('  }\n')
314 1 tkerber
        fh.write('  Charge = ')
315 1 tkerber
        fh.write('%10.6f' % (self.charge))
316 1 tkerber
        fh.write(' # System neutral\n')
317 1 tkerber
        if self.do_spin_polarized:
318 1 tkerber
            fh.write('  SpinPolarisation = Colinear {\n')
319 1 tkerber
            fh.write('  UnpairedElectrons = '+str(self.unpaired_electrons)+'\n')
320 1 tkerber
            fh.write('  } \n')
321 1 tkerber
            fh.write('  SpinConstants = {\n')
322 1 tkerber
            for i in self.allspecies:
323 1 tkerber
                if i == 'H':
324 1 tkerber
                    fh.write('   H={\n')
325 1 tkerber
                    fh.write('    # Wss\n')
326 1 tkerber
                    fh.write('    -0.072\n')
327 1 tkerber
                    fh.write('    }\n')
328 1 tkerber
                elif i == 'C':
329 1 tkerber
                    fh.write('   C={\n')
330 1 tkerber
                    fh.write('    # Wss Wsp Wps Wpp\n')
331 1 tkerber
                    fh.write('    -0.031 -0.025 -0.025 -0.023\n')
332 1 tkerber
                    fh.write('    }\n')
333 1 tkerber
                elif i == 'N':
334 1 tkerber
                    fh.write('   N={\n')
335 1 tkerber
                    fh.write('    # Wss Wsp Wps Wpp\n')
336 1 tkerber
                    fh.write('    -0.033 -0.027 -0.027 -0.026\n')
337 1 tkerber
                    fh.write('     }\n')
338 1 tkerber
                elif i == 'O':
339 1 tkerber
                    fh.write('   O={\n')
340 1 tkerber
                    fh.write('    # Wss Wsp Wps Wpp\n')
341 1 tkerber
                    fh.write('    -0.035 -0.030 -0.030 -0.028\n')
342 1 tkerber
                    fh.write('     }\n')
343 1 tkerber
                elif (i == 'Si' or i == 'SI'):
344 1 tkerber
                    fh.write('   Si={\n')
345 1 tkerber
                    fh.write('    # Wss Wsp Wsd Wps Wpp Wpd Wds Wdp Wdd\n')
346 1 tkerber
                    fh.write('    -0.020 -0.015 0.000 -0.015 -0.014 0.000 0.002 0.002 -0.032\n')
347 1 tkerber
                    fh.write('    }\n')
348 1 tkerber
                elif (i == 'S'):
349 1 tkerber
                    fh.write('   S={\n')
350 1 tkerber
                    fh.write('    # Wss Wsp Wsd Wps Wpp Wpd Wds Wdp Wdd\n')
351 1 tkerber
                    fh.write('    -0.021 -0.017 0.000 -0.017 -0.016 0.000 0.000 0.000 -0.080\n')
352 1 tkerber
                    fh.write('    }\n')
353 1 tkerber
                elif (i == 'Fe' or i == 'FE'):
354 1 tkerber
                    fh.write('   Fe={\n')
355 1 tkerber
                    fh.write('    # Wss Wsp Wsd Wps Wpp Wpd Wds Wdp Wdd\n')
356 1 tkerber
                    fh.write('    -0.016 -0.012 -0.003 -0.012 -0.029 -0.001 -0.003 -0.001 -0.015\n')
357 1 tkerber
                    fh.write('    }\n')
358 1 tkerber
                elif (i == 'Ni' or i == 'NI'):
359 1 tkerber
                    fh.write('   Ni={\n')
360 1 tkerber
                    fh.write('    # Wss Wsp Wsd Wps Wpp Wpd Wds Wdp Wdd\n')
361 1 tkerber
                    fh.write('    -0.016 -0.012 -0.003 -0.012 -0.022 -0.001 -0.003 -0.001 -0.018\n')
362 1 tkerber
                    fh.write('    }\n')
363 1 tkerber
                else:
364 1 tkerber
                    print 'Missing spin polarisation parameters for species'+i
365 1 tkerber
                    raise RuntimeError, \
366 1 tkerber
                        'Run spin unpolarised calculation'
367 1 tkerber
                fh.write('   }\n')
368 1 tkerber
        else:
369 1 tkerber
            fh.write('  SpinPolarisation = {}')
370 1 tkerber
            fh.write(' # No spin polarisation\n')
371 1 tkerber
        fh.write('  Filling = Fermi {\n')
372 1 tkerber
        fh.write('    Temperature [Kelvin] = ')
373 1 tkerber
        fh.write('%10.6f\n' % (self.fermi_temperature))
374 1 tkerber
        fh.write('  }\n')
375 1 tkerber
        if periodic:
376 1 tkerber
            fh.write('# gamma only\n')
377 1 tkerber
            fh.write('KPointsAndWeights = { \n')
378 1 tkerber
            fh.write('  0.000000    0.000000    0.000000       1.000000 \n')
379 1 tkerber
            fh.write('}\n')
380 1 tkerber
381 1 tkerber
        #Dispersion parameters
382 1 tkerber
        if (self.include_dispersion):
383 1 tkerber
            fh.write('Dispersion = SlaterKirkwood {\n')
384 1 tkerber
            fh.write(' PolarRadiusCharge = HybridDependentPol {\n')
385 1 tkerber
            fh.write('\n')
386 1 tkerber
            fh.write('  C={\n')
387 1 tkerber
            fh.write('    CovalentRadius [Angstrom] = 0.8\n')
388 1 tkerber
            fh.write('    HybridPolarisations [Angstrom^3,Angstrom,] = {\n')
389 1 tkerber
            fh.write('      1.382 1.382 1.382 1.064 1.064 1.064 3.8 3.8 3.8 3.8 3.8 3.8 2.5\n')
390 1 tkerber
            fh.write('    }\n')
391 1 tkerber
            fh.write('  }\n')
392 1 tkerber
            fh.write('\n')
393 1 tkerber
            fh.write('  N={\n')
394 1 tkerber
            fh.write('    CovalentRadius [Angstrom] = 0.8\n')
395 1 tkerber
            fh.write('    HybridPolarisations [Angstrom^3,Angstrom,] = {\n')
396 1 tkerber
            fh.write('      1.030 1.030 1.090 1.090 1.090 1.090 3.8 3.8 3.8 3.8 3.8 3.8 2.82\n')
397 1 tkerber
            fh.write('    }\n')
398 1 tkerber
            fh.write('  }\n')
399 1 tkerber
            fh.write('\n')
400 1 tkerber
            fh.write('  O={\n')
401 1 tkerber
            fh.write('    CovalentRadius [Angstrom] = 0.8\n')
402 1 tkerber
            fh.write('    HybridPolarisations [Angstrom^3,Angstrom,] = {\n')
403 1 tkerber
            fh.write('    # All polarisabilities and radii set the same\n')
404 1 tkerber
            fh.write('      0.560 0.560 0.000 0.000 0.000 0.000 3.8 3.8 3.8 3.8 3.8 3.8 3.15\n')
405 1 tkerber
            fh.write('    }\n')
406 1 tkerber
            fh.write('  }\n')
407 1 tkerber
            fh.write('\n')
408 1 tkerber
409 1 tkerber
410 1 tkerber
            fh.write('  H={\n')
411 1 tkerber
            fh.write('    CovalentRadius [Angstrom] = 0.4\n')
412 1 tkerber
            fh.write('    HybridPolarisations [Angstrom^3,Angstrom,] = {\n')
413 1 tkerber
            fh.write('    # Different polarisabilities depending on the hybridisation\n')
414 1 tkerber
            fh.write('      0.386 0.396 0.000 0.000 0.000 0.000 3.5 3.5 3.5 3.5 3.5 3.5 0.8\n')
415 1 tkerber
            fh.write('    }\n')
416 1 tkerber
            fh.write('  }\n')
417 1 tkerber
            fh.write('\n')
418 1 tkerber
419 1 tkerber
            fh.write('  P={\n')
420 1 tkerber
            fh.write('    CovalentRadius [Angstrom] = 0.9\n')
421 1 tkerber
            fh.write('    HybridPolarisations [Angstrom^3,Angstrom,] = {\n')
422 1 tkerber
            fh.write('    # Different polarisabilities depending on the hybridisation\n')
423 1 tkerber
            fh.write('      1.600 1.600 1.600 1.600 1.600 1.600 4.7 4.7 4.7 4.7 4.7 4.7 4.50\n')
424 1 tkerber
            fh.write('    }\n')
425 1 tkerber
            fh.write('  }\n')
426 1 tkerber
            fh.write('\n')
427 1 tkerber
428 1 tkerber
            fh.write('  S={\n')
429 1 tkerber
            fh.write('    CovalentRadius [Angstrom] = 0.9\n')
430 1 tkerber
            fh.write('    HybridPolarisations [Angstrom^3,Angstrom,] = {\n')
431 1 tkerber
            fh.write('    # Different polarisabilities depending on the hybridisation\n')
432 1 tkerber
            fh.write('      3.000 3.000 3.000 3.000 3.000 3.000 4.7 4.7 4.7 4.7 4.7 4.7 4.80\n')
433 1 tkerber
            fh.write('    }\n')
434 1 tkerber
            fh.write('  }\n')
435 1 tkerber
            fh.write(' }\n')
436 1 tkerber
            fh.write('}\n')
437 1 tkerber
        fh.write('}\n')
438 1 tkerber
        fh.write('Options = {}\n')
439 1 tkerber
        fh.write('ParserOptions = {\n')
440 1 tkerber
        fh.write('  ParserVersion = 3\n')
441 1 tkerber
        fh.write('}\n')
442 1 tkerber
443 1 tkerber
        fh.close()
444 1 tkerber
445 1 tkerber
    def change_atom_positions_dftb(self, atoms):
446 1 tkerber
        """Write coordinates in DFTB+ input file dftb_in.hsd
447 1 tkerber
        """
448 1 tkerber
449 1 tkerber
        filename = 'dftb_in.hsd'
450 1 tkerber
        if isinstance(filename, str):
451 1 tkerber
            myfile = open(filename)
452 1 tkerber
453 1 tkerber
        lines = myfile.readlines()
454 1 tkerber
455 1 tkerber
        if type(filename) == str:
456 1 tkerber
            myfile.close()
457 1 tkerber
458 1 tkerber
        if isinstance(filename, str):
459 1 tkerber
            myfile = open(filename, 'w')
460 1 tkerber
        else: # Assume it's a 'file-like object'
461 1 tkerber
            myfile = filename
462 1 tkerber
463 1 tkerber
        coord = atoms.get_positions()
464 1 tkerber
465 1 tkerber
        start_writing_coords = False
466 1 tkerber
        stop_writing_coords = False
467 1 tkerber
        i = 0
468 1 tkerber
        for line in lines:
469 1 tkerber
            if ('TypesAndCoordinates' in line):
470 1 tkerber
                start_writing_coords = True
471 1 tkerber
            if (start_writing_coords and not(stop_writing_coords)):
472 1 tkerber
                if ('}' in line):
473 1 tkerber
                    stop_writing_coords = True
474 1 tkerber
            if (start_writing_coords and not(stop_writing_coords)and
475 1 tkerber
                not ('TypesAndCoordinates' in line)):
476 1 tkerber
                atom_type_index = line.split()[0]
477 1 tkerber
                myfile.write('%6s  %20.14f  %20.14f  %20.14f\n'
478 1 tkerber
                        % (atom_type_index,coord[i][0],coord[i][1],coord[i][2]))
479 1 tkerber
                i = i + 1
480 1 tkerber
            else:
481 1 tkerber
                myfile.write(line)