Statistiques
| Révision :

root / ase / calculators / elk.py @ 1

Historique | Voir | Annoter | Télécharger (4,99 ko)

1 1 tkerber
import os
2 1 tkerber
3 1 tkerber
import numpy as np
4 1 tkerber
5 1 tkerber
from ase.units import Bohr, Hartree
6 1 tkerber
7 1 tkerber
elk_parameters = {
8 1 tkerber
    'swidth': Hartree,
9 1 tkerber
    }
10 1 tkerber
11 1 tkerber
class ELK:
12 1 tkerber
    def __init__(self, dir='.', xc=None, kpts=None, tasks=[0], **kwargs):
13 1 tkerber
        for key, value in kwargs.items():
14 1 tkerber
            if key in elk_parameters:
15 1 tkerber
                kwargs[key] /= elk_parameters[key]
16 1 tkerber
17 1 tkerber
        if xc is not None:
18 1 tkerber
            if 'xctype' in kwargs:
19 1 tkerber
                raise ValueError("You can't use both 'xc' and 'xctype'!")
20 1 tkerber
            else:
21 1 tkerber
                kwargs['xctype'] = {'LDA': 3, # PW92
22 1 tkerber
                                    'PBE': 20,
23 1 tkerber
                                    'REVPBE': 21,
24 1 tkerber
                                    'PBESOL': 22,
25 1 tkerber
                                    'WC06': 26,
26 1 tkerber
                                    'AM05': 30}[xc.upper()]
27 1 tkerber
28 1 tkerber
        if kpts is not None:
29 1 tkerber
            if 'autokpt' in kwargs:
30 1 tkerber
                if kwargs['autokpt']:
31 1 tkerber
                    raise ValueError("You can't use both 'kpts' and 'autokpt'!")
32 1 tkerber
            if 'ngridk' in kwargs:
33 1 tkerber
                raise ValueError("You can't use both 'kpts' and 'ngridk'!")
34 1 tkerber
            if 'vkloff' in kwargs:
35 1 tkerber
                raise ValueError("You can't use both 'kpts' and 'vkloff'!")
36 1 tkerber
            else:
37 1 tkerber
                kwargs['ngridk'] = kpts
38 1 tkerber
                vkloff = []
39 1 tkerber
                for nk in kpts:
40 1 tkerber
                    if nk % 2 == 0:  # shift kpoint away from gamma point
41 1 tkerber
                        vkloff.append(0.5 / nk)
42 1 tkerber
                    else:
43 1 tkerber
                        vkloff.append(0)
44 1 tkerber
                kwargs['vkloff'] = vkloff
45 1 tkerber
46 1 tkerber
        kwargs['tasks'] = tasks
47 1 tkerber
48 1 tkerber
        self.parameters = kwargs
49 1 tkerber
50 1 tkerber
        self.dir = dir
51 1 tkerber
        self.energy = None
52 1 tkerber
53 1 tkerber
        self.converged = False
54 1 tkerber
55 1 tkerber
    def update(self, atoms):
56 1 tkerber
        if (not self.converged or
57 1 tkerber
            len(self.numbers) != len(atoms) or
58 1 tkerber
            (self.numbers != atoms.get_atomic_numbers()).any()):
59 1 tkerber
            self.initialize(atoms)
60 1 tkerber
            self.calculate(atoms)
61 1 tkerber
        elif ((self.positions != atoms.get_positions()).any() or
62 1 tkerber
              (self.pbc != atoms.get_pbc()).any() or
63 1 tkerber
              (self.cell != atoms.get_cell()).any()):
64 1 tkerber
            self.calculate(atoms)
65 1 tkerber
66 1 tkerber
    def initialize(self, atoms):
67 1 tkerber
        self.numbers = atoms.get_atomic_numbers().copy()
68 1 tkerber
        self.write(atoms)
69 1 tkerber
70 1 tkerber
    def get_potential_energy(self, atoms):
71 1 tkerber
        self.update(atoms)
72 1 tkerber
        return self.energy
73 1 tkerber
74 1 tkerber
    def get_forces(self, atoms):
75 1 tkerber
        self.update(atoms)
76 1 tkerber
        return self.forces.copy()
77 1 tkerber
78 1 tkerber
    def get_stress(self, atoms):
79 1 tkerber
        self.update(atoms)
80 1 tkerber
        return self.stress.copy()
81 1 tkerber
82 1 tkerber
    def calculate(self, atoms):
83 1 tkerber
        self.positions = atoms.get_positions().copy()
84 1 tkerber
        self.cell = atoms.get_cell().copy()
85 1 tkerber
        self.pbc = atoms.get_pbc().copy()
86 1 tkerber
87 1 tkerber
        self.initialize(atoms)
88 1 tkerber
        assert os.system('cd %s; elk' % self.dir) == 0
89 1 tkerber
        self.read()
90 1 tkerber
91 1 tkerber
        self.converged = True
92 1 tkerber
93 1 tkerber
    def write(self, atoms):
94 1 tkerber
        if not os.path.isdir(self.dir):
95 1 tkerber
            os.mkdir(self.dir)
96 1 tkerber
        fd = open('%s/elk.in' % self.dir, 'w')
97 1 tkerber
        for key, value in self.parameters.items():
98 1 tkerber
            fd.write('%s\n' % key)
99 1 tkerber
            if isinstance(value, bool):
100 1 tkerber
                fd.write('.%s.\n\n' % ('false', 'true')[value])
101 1 tkerber
            elif isinstance(value, (int, float)):
102 1 tkerber
                fd.write('%s\n\n' % value)
103 1 tkerber
            else:
104 1 tkerber
                fd.write('%s\n\n' % ' '.join([str(x) for x in value]))
105 1 tkerber
106 1 tkerber
        fd.write('avec\n')
107 1 tkerber
        for vec in atoms.cell:
108 1 tkerber
            fd.write('%.14f %.14f %.14f\n' % tuple(vec / Bohr))
109 1 tkerber
        fd.write('\n')
110 1 tkerber
111 1 tkerber
        fd.write("sppath\n'%s'\n\n" % os.environ['ELK_SPECIES_PATH'])
112 1 tkerber
113 1 tkerber
        species = {}
114 1 tkerber
        symbols = []
115 1 tkerber
        for a, symbol in enumerate(atoms.get_chemical_symbols()):
116 1 tkerber
            if symbol in species:
117 1 tkerber
                species[symbol].append(a)
118 1 tkerber
            else:
119 1 tkerber
                species[symbol] = [a]
120 1 tkerber
                symbols.append(symbol)
121 1 tkerber
        fd.write('atoms\n%d\n' % len(species))
122 1 tkerber
        scaled = atoms.get_scaled_positions()
123 1 tkerber
        for symbol in symbols:
124 1 tkerber
            fd.write("'%s.in'\n" % symbol)
125 1 tkerber
            fd.write('%d\n' % len(species[symbol]))
126 1 tkerber
            for a in species[symbol]:
127 1 tkerber
                fd.write('%.14f %.14f %.14f 0.0 0.0 0.0\n' % tuple(scaled[a]))
128 1 tkerber
129 1 tkerber
    def read(self):
130 1 tkerber
        fd = open('%s/TOTENERGY.OUT' % self.dir, 'r')
131 1 tkerber
        self.energy = float(fd.readlines()[-1]) * Hartree
132 1 tkerber
        # Forces:
133 1 tkerber
        INFO_file = '%s/INFO.OUT' % self.dir
134 1 tkerber
        if os.path.isfile(INFO_file) or os.path.islink(INFO_file):
135 1 tkerber
            text = open(INFO_file).read().lower()
136 1 tkerber
            assert 'convergence targets achieved' in text
137 1 tkerber
            assert not 'reached self-consistent loops maximum' in text
138 1 tkerber
            lines = iter(text.split('\n'))
139 1 tkerber
            forces = []
140 1 tkerber
            atomnum = 0
141 1 tkerber
            for line in lines:
142 1 tkerber
                if line.rfind('total force') > -1:
143 1 tkerber
                    forces.append(np.array([float(f) for f in line.split(':')[1].split()]))
144 1 tkerber
                    atomnum =+ 1
145 1 tkerber
            self.forces = np.array(forces)
146 1 tkerber
        else:
147 1 tkerber
            raise RuntimeError
148 1 tkerber
        # Stress
149 1 tkerber
        self.stress = np.empty((3, 3))