Statistiques
| Révision :

root / ase / calculators / exciting.py @ 13

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

1 1 tkerber
import os
2 1 tkerber
import numpy as np
3 1 tkerber
from ase.units import Bohr, Hartree
4 1 tkerber
5 1 tkerber
6 1 tkerber
class Exciting:
7 1 tkerber
    """exciting calculator object."""
8 1 tkerber
9 1 tkerber
    def __init__(self, dir='.', template=None, speciespath=None,
10 1 tkerber
                 bin='excitingser', kpts=(1, 1, 1), **kwargs):
11 1 tkerber
        """Exciting calculator object constructor
12 1 tkerber

13 1 tkerber
        Parameters
14 1 tkerber
        ----------
15 1 tkerber
        dir: string
16 1 tkerber
            directory in which to excecute exciting
17 1 tkerber
        template: string
18 1 tkerber
            Path to XSLT templat if it schould be used
19 1 tkerber
            default: none
20 1 tkerber
        bin: string
21 1 tkerber
            Path or executable name of exciting
22 1 tkerber
            default: ``excitingser``
23 1 tkerber
        kpts: integer list length 3
24 1 tkerber
            Number of kpoints
25 1 tkerber
        kwargs: dictionary like
26 1 tkerber
            list of key value pairs to be converted into groundstate attributes
27 1 tkerber

28 1 tkerber
        """
29 1 tkerber
        self.dir = dir
30 1 tkerber
        self.energy = None
31 1 tkerber
        self.template = template
32 1 tkerber
        if speciespath is None:
33 1 tkerber
            self.speciespath = os.environ.get('EXCITING_SPECIES_PATH', './')
34 1 tkerber
        self.converged = False
35 1 tkerber
        self.excitingbinary = bin
36 1 tkerber
        self.groundstate_attributes = kwargs
37 1 tkerber
        if not 'ngridk' in kwargs.keys():
38 1 tkerber
            self.groundstate_attributes['ngridk'] = ' '.join(map(str, kpts))
39 1 tkerber
40 1 tkerber
    def update(self, atoms):
41 1 tkerber
        if (not self.converged or
42 1 tkerber
            len(self.numbers) != len(atoms) or
43 1 tkerber
            (self.numbers != atoms.get_atomic_numbers()).any()):
44 1 tkerber
            self.initialize(atoms)
45 1 tkerber
            self.calculate(atoms)
46 1 tkerber
        elif ((self.positions != atoms.get_positions()).any() or
47 1 tkerber
              (self.pbc != atoms.get_pbc()).any() or
48 1 tkerber
              (self.cell != atoms.get_cell()).any()):
49 1 tkerber
            self.calculate(atoms)
50 1 tkerber
51 1 tkerber
    def initialize(self, atoms):
52 1 tkerber
        self.numbers = atoms.get_atomic_numbers().copy()
53 1 tkerber
        self.write(atoms)
54 1 tkerber
55 1 tkerber
    def get_potential_energy(self, atoms):
56 1 tkerber
        self.update(atoms)
57 1 tkerber
        return self.energy
58 1 tkerber
59 1 tkerber
    def get_forces(self, atoms):
60 1 tkerber
        self.update(atoms)
61 1 tkerber
        return self.forces.copy()
62 1 tkerber
63 1 tkerber
    def get_stress(self, atoms):
64 1 tkerber
        self.update(atoms)
65 1 tkerber
        return self.stress.copy()
66 1 tkerber
67 1 tkerber
    def calculate(self, atoms):
68 1 tkerber
        self.positions = atoms.get_positions().copy()
69 1 tkerber
        self.cell = atoms.get_cell().copy()
70 1 tkerber
        self.pbc = atoms.get_pbc().copy()
71 1 tkerber
72 1 tkerber
        self.initialize(atoms)
73 1 tkerber
        syscall = ('cd %(dir)s; %(bin)s;' %
74 1 tkerber
                   {'dir': self.dir, 'bin': self.excitingbinary})
75 1 tkerber
        print syscall
76 1 tkerber
        assert os.system(syscall ) == 0
77 1 tkerber
        self.read()
78 1 tkerber
79 1 tkerber
    def write(self, atoms):
80 1 tkerber
        from lxml import etree as ET
81 1 tkerber
        from ase.io.exciting import  atoms2etree
82 1 tkerber
        if not os.path.isdir(self.dir):
83 1 tkerber
            os.mkdir(self.dir)
84 1 tkerber
        root = atoms2etree(atoms)
85 1 tkerber
        root.find('structure').attrib['speciespath'] = self.speciespath
86 1 tkerber
        root.find('structure').attrib['autormt'] = 'false'
87 1 tkerber
        groundstate = ET.SubElement(root, 'groundstate', tforce='true')
88 1 tkerber
        for key, value in self.groundstate_attributes.items():
89 1 tkerber
            groundstate.attrib[key] = str(value)
90 1 tkerber
        if self.template:
91 1 tkerber
            xslf = open(self.template, 'r')
92 1 tkerber
            xslt_doc = ET.parse(xslf)
93 1 tkerber
            transform = ET.XSLT(xslt_doc)
94 1 tkerber
            result = transform(root)
95 1 tkerber
            fd = open('%s/input.xml' % self.dir, 'w')
96 1 tkerber
            fd.write(ET.tostring(result, method='xml', pretty_print=True,
97 1 tkerber
                                 xml_declaration=True, encoding='UTF-8'))
98 1 tkerber
            fd.close()
99 1 tkerber
        else:
100 1 tkerber
            fd = open('%s/input.xml' % self.dir, 'w')
101 1 tkerber
            fd.write(ET.tostring(root, method='xml', pretty_print=True,
102 1 tkerber
                                 xml_declaration=True, encoding='UTF-8'))
103 1 tkerber
            fd.close()
104 1 tkerber
105 1 tkerber
    def read(self):
106 1 tkerber
        """ reads Total energy and forces from info.xml
107 1 tkerber
        """
108 1 tkerber
        from lxml import etree as ET
109 1 tkerber
        INFO_file = '%s/info.xml' % self.dir
110 1 tkerber
111 1 tkerber
        try:
112 1 tkerber
            fd = open(INFO_file)
113 1 tkerber
        except IOError:
114 1 tkerber
            print "file doesn't exist"
115 1 tkerber
        info = ET.parse(fd)
116 1 tkerber
        self.energy = float(info.xpath('//@totalEnergy')[-1]) * Hartree
117 1 tkerber
        forces = []
118 1 tkerber
        forcesnodes = info.xpath(
119 1 tkerber
            '//structure[last()]/species/atom/forces/totalforce/@*')
120 1 tkerber
        for force in forcesnodes:
121 1 tkerber
            forces.append(np.array(float(force)))
122 1 tkerber
        self.forces = np.reshape(forces, (-1, 3))
123 1 tkerber
124 1 tkerber
        if str(info.xpath('//groundstate/@status')[0]) == 'finished':
125 1 tkerber
            self.converged = True
126 1 tkerber
        else:
127 1 tkerber
            raise RuntimeError('calculation did not finish correctly')
128 1 tkerber
129 1 tkerber
        # Stress
130 1 tkerber
        self.stress = np.empty((3, 3))