parser_elk.py 16.2 KB
Newer Older
1
2
from builtins import object
import setup_paths
3
import numpy as np
4
5
6
from nomadcore.simple_parser import mainFunction, AncillaryParser, CachingLevel
from nomadcore.simple_parser import SimpleMatcher as SM
from nomadcore.local_meta_info import loadJsonFile, InfoKindEl
Pardini, Lorenzo (lopa)'s avatar
Pardini, Lorenzo (lopa) committed
7
8
from nomadcore.unit_conversion import unit_conversion
import os, sys, json, logging
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

class ElkContext(object):
    """context for elk parser"""

    def __init__(self):
        self.parser = None

    def initialize_values(self):
        """allows to reset values if the same superContext is used to parse different files"""
        self.metaInfoEnv = self.parser.parserBuilder.metaInfoEnv

    def startedParsing(self, path, parser):
        """called when parsing starts"""
        self.parser = parser
        # allows to reset values if the same superContext is used to parse different files
        self.initialize_values()

26
27
28
29
30
31
32
    def onClose_x_elk_section_lattice_vectors(self, backend, gIndex, section):
      latticeX = section["x_elk_geometry_lattice_vector_x"]
      latticeY = section["x_elk_geometry_lattice_vector_y"]
      latticeZ = section["x_elk_geometry_lattice_vector_z"]
      cell = [[latticeX[0],latticeY[0],latticeZ[0]],
              [latticeX[1],latticeY[1],latticeZ[1]],
              [latticeX[2],latticeY[2],latticeZ[2]]]
33
#      print ("celll= ", cell)
34
35
36
37
38
39
40
41
42
43
44
      backend.addValue("simulation_cell", cell)

    def onClose_x_elk_section_reciprocal_lattice_vectors(self, backend, gIndex, section):
      recLatticeX = section["x_elk_geometry_reciprocal_lattice_vector_x"]
      recLatticeY = section["x_elk_geometry_reciprocal_lattice_vector_y"]
      recLatticeZ = section["x_elk_geometry_reciprocal_lattice_vector_z"]
      recCell = [[recLatticeX[0],recLatticeY[0],recLatticeZ[0]],
              [recLatticeX[1],recLatticeY[1],recLatticeZ[1]],
              [recLatticeX[2],recLatticeY[2],recLatticeZ[2]]]
      backend.addValue("x_elk_simulation_reciprocal_cell", recCell)

45
46
47
48
    def onClose_x_elk_section_xc(self, backend, gIndex, section):
      xcNr = section["x_elk_xc_functional"][0]
      xc_internal_map = {
        2: ['LDA_C_PZ', 'LDA_X_PZ'],
49
        3: ['LDA_C_PW', 'LDA_X_PZ'],
50
51
        4: ['LDA_C_XALPHA'],
        5: ['LDA_C_VBH'],
52
53
54
55
56
        20: ['GGA_C_PBE', 'GGA_X_PBE'],
        21: ['GGA_C_PBE', 'GGA_X_PBE_R'],
        22: ['GGA_C_PBE_SOL', 'GGA_X_PBE_SOL'],
        26: ['GGA_C_PBE', 'GGA_X_WC'],
        30: ['GGA_C_AM05', 'GGA_X_AM05']
57
58
59
60
61
62
        }
      for xcName in xc_internal_map[xcNr]:
        gi = backend.openSection("section_XC_functionals")
        backend.addValue("XC_functional_name", xcName)
        backend.closeSection("section_XC_functionals", gi)

Pardini, Lorenzo (lopa)'s avatar
Pardini, Lorenzo (lopa) committed
63
64
65
    def onClose_section_single_configuration_calculation(self, backend, gIndex, section):
      dirPath = os.path.dirname(self.parser.fIn.name)
      dosFile = os.path.join(dirPath, "TDOS.OUT")
Pardini, Lorenzo (lopa)'s avatar
Pardini, Lorenzo (lopa) committed
66
      eigvalFile = os.path.join(dirPath, "EIGVAL.OUT")
Pardini, Lorenzo (lopa)'s avatar
Pardini, Lorenzo (lopa) committed
67
      if os.path.exists(dosFile):
Pardini, Lorenzo (lopa)'s avatar
Pardini, Lorenzo (lopa) committed
68
        dosGIndex=backend.openSection("section_dos")
Pardini, Lorenzo (lopa)'s avatar
Pardini, Lorenzo (lopa) committed
69
        with open(dosFile) as f:
Pardini, Lorenzo (lopa)'s avatar
Pardini, Lorenzo (lopa) committed
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
            dosE=[]
            dosV=[]
            fromH = unit_conversion.convert_unit_function("hartree", "J")
            while True:
                line = f.readline()
                if not line: break
                nrs = list(map(float,line.split()))
                if len(nrs) == 2:
                    dosV.append(nrs[1])
                    dosE.append(fromH(nrs[0]))
                elif len(nrs) != 0:
                    raise Exception("Found more than two values in dos file %s" % dosFile)
            backend.addArrayValues("dos_values", np.asarray(dosV))
            backend.addArrayValues("dos_energies", np.asarray(dosE))
        backend.closeSection("section_dos", dosGIndex)
Pardini, Lorenzo (lopa)'s avatar
Pardini, Lorenzo (lopa) committed
85
86
87
88
      if os.path.exists(eigvalFile):
        eigvalGIndex = backend.openSection("section_eigenvalues")
        with open(eigvalFile) as g:
            eigvalKpoint=[]
89
90
            eigvalVal=[]
            eigvalOcc=[]
Pardini, Lorenzo (lopa)'s avatar
Pardini, Lorenzo (lopa) committed
91
92
93
94
95
            fromH = unit_conversion.convert_unit_function("hartree", "J")
            while 1:
              s = g.readline()
              if not s: break
              s = s.strip()
96
97
98
              if len(s) < 20:
                continue
              elif len(s) > 50:
99
100
                eigvalVal.append([])
                eigvalOcc.append([])
Pardini, Lorenzo (lopa)'s avatar
Pardini, Lorenzo (lopa) committed
101
                eigvalKpoint.append(list(map(float, s.split()[1:4])))
102
103
104
105
106
107
              else:
                try: int(s[0])
                except ValueError:
                  continue
                else:
                  n, e, occ = s.split()
108
109
                  eigvalVal[-1].append(fromH(float(e)))
                  eigvalOcc[-1].append(float(occ))
Pardini, Lorenzo (lopa)'s avatar
Pardini, Lorenzo (lopa) committed
110
            backend.addArrayValues("eigenvalues_kpoints", np.asarray(eigvalKpoint))
111
            backend.addArrayValues("eigenvalues_values", np.asarray(eigvalVal))
Pardini, Lorenzo (lopa)'s avatar
Pardini, Lorenzo (lopa) committed
112
            backend.addArrayValues("eigenvalues_occupation", np.asarray(eigvalOcc))
Pardini, Lorenzo (lopa)'s avatar
Pardini, Lorenzo (lopa) committed
113
114
115

    def onClose_section_system(self, backend, gIndex, section):
      backend.addArrayValues('configuration_periodic_dimensions', np.asarray([True, True, True]))
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
      self.secSystemDescriptionIndex = gIndex

      atom_pos = []
      for i in ['x', 'y', 'z']:
         api = section['x_elk_geometry_atom_positions_' + i]
         if api is not None:
            atom_pos.append(api)
      if atom_pos:
         backend.addArrayValues('atom_positions', np.transpose(np.asarray(atom_pos)))
      atom_labels = section['x_elk_geometry_atom_labels']
      if atom_labels is not None:
         backend.addArrayValues('atom_labels', np.asarray(atom_labels))

    def onClose_section_scf_iteration(self, backend, gIndex, section):
      Etot = section["energy_total_scf_iteration"]
131
      backend.addValue("energy_total", Etot[-1])
Pardini, Lorenzo (lopa)'s avatar
Pardini, Lorenzo (lopa) committed
132

133
# description of the input
134
135
136
137
138
139
mainFileDescription = \
    SM(name = "root matcher",
       startReStr = "",
       weak = True,
       subMatchers = [
         SM(name = "header",
140
         startReStr = r"\s*\|\s*Elk version\s*(?P<program_version>[-a-zA-Z0-9\.]+)\s*started\s*",
141
142
143
144
         fixedStartValues={'program_name': 'elk', 'program_basis_set_type': '(L)APW+lo' },
            sections = ["section_run", "section_method"],
         subMatchers = [
           SM(name = 'input',
145
146
              startReStr = r"\|\sGround-state run starting from atomic densities\s\|\s",
              endReStr = r"\|\sDensity and potential initialised from atomic data\s",
147
148
              sections = ['section_system'],
              subMatchers = [
149
150
151
152
153
154
155
156
157
158
159
160
                SM(startReStr = r"\s*Lattice vectors :",
                sections = ["x_elk_section_lattice_vectors"],
                subMatchers = [

    SM(startReStr = r"\s*(?P<x_elk_geometry_lattice_vector_x__bohr>[-+0-9.]+)\s+(?P<x_elk_geometry_lattice_vector_y__bohr>[-+0-9.]+)\s+(?P<x_elk_geometry_lattice_vector_z__bohr>[-+0-9.]+)", repeats = True)
                ]),
                SM(startReStr = r"Reciprocal lattice vectors :",
                sections = ["x_elk_section_reciprocal_lattice_vectors"],
                subMatchers = [

    SM(startReStr = r"\s*(?P<x_elk_geometry_reciprocal_lattice_vector_x__bohr_1>[-+0-9.]+)\s+(?P<x_elk_geometry_reciprocal_lattice_vector_y__bohr_1>[-+0-9.]+)\s+(?P<x_elk_geometry_reciprocal_lattice_vector_z__bohr_1>[-+0-9.]+)", repeats = True)
                ]),
161
    SM(r"\s*Unit cell volume\s*:\s*(?P<x_elk_unit_cell_volume__bohr3>[-0-9.]+)"),
Pardini, Lorenzo (lopa)'s avatar
Pardini, Lorenzo (lopa) committed
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
    SM(r"\s*Brillouin zone volume\s*:\s*(?P<x_elk_brillouin_zone_volume__bohr_3>[-0-9.]+)"),
    SM(r"\s*Species\s*:\s*[0-9]\s*\((?P<x_elk_geometry_atom_labels>[-a-zA-Z0-9]+)\)", repeats = True,
       subMatchers = [
    SM(r"\s*muffin-tin radius\s*:\s*(?P<x_elk_muffin_tin_radius__bohr>[-0-9.]+)"),
    SM(r"\s*number of radial points in muffin-tin\s*:\s*(?P<x_elk_muffin_tin_points>[-0-9.]+)"),
    SM(startReStr = r"\s*atomic positions\s*\(lattice\)\, magnetic fields \(Cartesian\)\s*:\s*",
      subMatchers = [
        SM(r"\s*(?P<x_elk_geometry_atom_number>[+0-9]+)\s*:\s*(?P<x_elk_geometry_atom_positions_x__bohr>[-+0-9.]+)\s*(?P<x_elk_geometry_atom_positions_y__bohr>[-+0-9.]+)\s*(?P<x_elk_geometry_atom_positions_z__bohr>[-+0-9.]+)", repeats = True)
      ])
    ]),
    SM(r"\s*k-point grid\s*:\s*(?P<x_elk_number_kpoint_x>[-0-9.]+)\s+(?P<x_elk_number_kpoint_y>[-0-9.]+)\s+(?P<x_elk_number_kpoint_z>[-0-9.]+)"),
    SM(r"\s*k-point offset\s*:\s*(?P<x_elk_kpoint_offset_x>[-0-9.]+)\s+(?P<x_elk_kpoint_offset_y>[-0-9.]+)\s+(?P<x_elk_kpoint_offset_z>[-0-9.]+)"),
    SM(r"\s*Total number of k-points\s*:\s*(?P<x_elk_number_kpoints>[-0-9.]+)"),
    SM(r"\s*Muffin-tin radius times maximum \|G\+k\|\s*:\s*(?P<x_elk_rgkmax__bohr>[-0-9.]+)"),
    SM(r"\s*Maximum \|G\+k\| for APW functions\s*:\s*(?P<x_elk_gkmax__bohr_1>[-0-9.]+)"),
    SM(r"\s*Maximum \|G\| for potential and density\s*:\s*(?P<x_elk_gmaxvr__bohr_1>[-0-9.]+)"),
    SM(r"\s*G-vector grid sizes\s*:\s*(?P<x_elk_gvector_size_x>[-0-9.]+)\s+(?P<x_elk_gvector_size_y>[-0-9.]+)\s+(?P<x_elk_gvector_size_z>[-0-9.]+)"),
    SM(r"\s*Number of G-vectors\s*:\s*(?P<x_elk_gvector_total>[-0-9.]+)"),
    SM(startReStr = r"\s*Maximum angular momentum used for\s*",
        subMatchers = [
          SM(r"\s*APW functions\s*:\s*(?P<x_elk_lmaxapw>[-0-9.]+)")
        ]),
184
185
186
187
188
189
190
191
192
193
    SM(r"\s*Total nuclear charge\s*:\s*(?P<x_elk_nuclear_charge>[-0-9.]+)"),
    SM(r"\s*Total core charge\s*:\s*(?P<x_elk_core_charge>[-0-9.]+)"),
    SM(r"\s*Total valence charge\s*:\s*(?P<x_elk_valence_charge>[-0-9.]+)"),
    SM(r"\s*Total electronic charge\s*:\s*(?P<x_elk_electronic_charge>[-0-9.]+)"),
    SM(r"\s*Effective Wigner radius, r_s\s*:\s*(?P<x_elk_wigner_radius>[-0-9.]+)"),
    SM(r"\s*Number of empty states\s*:\s*(?P<x_elk_empty_states>[-0-9.]+)"),
    SM(r"\s*Total number of valence states\s*:\s*(?P<x_elk_valence_states>[-0-9.]+)"),
    SM(r"\s*Total number of core states\s*:\s*(?P<x_elk_core_states>[-0-9.]+)"),
    SM(r"\s*Total number of local-orbitals\s*:\s*(?P<x_elk_lo>[-0-9.]+)"),
    SM(r"\s*Smearing width\s*:\s*(?P<x_elk_smearing_width__hartree>[-0-9.]+)"),
194
195
    SM(startReStr = r"\s*Exchange-correlation functional\s*:\s*(?P<x_elk_xc_functional>[-0-9.]+)",
       sections = ['x_elk_section_xc'])
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
           ]),
            SM(name = "single configuration iteration",
              startReStr = r"\|\s*Self-consistent loop started\s*\|",
              sections = ["section_single_configuration_calculation"],
              repeats = True,
              subMatchers = [
                SM(name = "scfi totE",
                 startReStr =r"\|\s*Loop number\s*:",
                  sections = ["section_scf_iteration"],
                  repeats = True,
                  subMatchers = [
                   SM(r"\s*Fermi\s*:\s*(?P<x_elk_fermi_energy_scf_iteration__hartree>[-0-9.]+)"),
                   SM(r"\s*sum of eigenvalues\s*:\s*(?P<energy_sum_eigenvalues_scf_iteration__hartree>[-0-9.]+)"),
                   SM(r"\s*electron kinetic\s*:\s*(?P<electronic_kinetic_energy_scf_iteration__hartree>[-0-9.]+)"),
                   SM(r"\s*core electron kinetic\s*:\s*(?P<x_elk_core_electron_kinetic_energy_scf_iteration__hartree>[-0-9.]+)"),
                   SM(r"\s*Coulomb\s*:\s*(?P<x_elk_coulomb_energy_scf_iteration__hartree>[-0-9.]+)"),
                   SM(r"\s*Coulomb potential\s*:\s*(?P<x_elk_coulomb_potential_energy_scf_iteration__hartree>[-0-9.]+)"),
                   SM(r"\s*nuclear-nuclear\s*:\s*(?P<x_elk_nuclear_nuclear_energy_scf_iteration__hartree>[-0-9.]+)"),
                   SM(r"\s*electron-nuclear\s*:\s*(?P<x_elk_electron_nuclear_energy_scf_iteration__hartree>[-0-9.]+)"),
                   SM(r"\s*Hartree\s*:\s*(?P<x_elk_hartree_energy_scf_iteration__hartree>[-0-9.]+)"),
                   SM(r"\s*Madelung\s*:\s*(?P<x_elk_madelung_energy_scf_iteration__hartree>[-0-9.]+)"),
                   SM(r"\s*xc potential\s*:\s*(?P<energy_XC_potential_scf_iteration__hartree>[-0-9.]+)"),
                   SM(r"\s*exchange\s*:\s*(?P<x_elk_exchange_energy_scf_iteration__hartree>[-0-9.]+)"),
                   SM(r"\s*correlation\s*:\s*(?P<x_elk_correlation_energy_scf_iteration__hartree>[-0-9.]+)"),
                   SM(r"\s*electron entropic\s*:\s*(?P<x_elk_electron_entropic_energy_scf_iteration__hartree>[-0-9.]+)"),
                   SM(r"\s*total energy\s*:\s*(?P<energy_total_scf_iteration__hartree>[-0-9.]+)"),
                   SM(r"\s*Density of states at Fermi energy\s*:\s*(?P<x_elk_dos_fermi_scf_iteration__hartree_1>[-0-9.]+)"),
                   SM(r"\s*Estimated indirect band gap\s*:\s*(?P<x_elk_indirect_gap_scf_iteration__hartree>[-0-9.]+)"),
                   SM(r"\s*Estimated direct band gap\s*:\s*(?P<x_elk_direct_gap_scf_iteration__hartree>[-0-9.]+)"),
                   SM(r"\s*core\s*:\s*(?P<x_elk_core_charge_scf_iteration>[-0-9.]+)"),
                   SM(r"\s*valence\s*:\s*(?P<x_elk_valence_charge_scf_iteration>[-0-9.]+)"),
                   SM(r"\s*interstitial\s*:\s*(?P<x_elk_interstitial_charge_scf_iteration>[-0-9.]+)"),
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
                  ]) #,
#                SM(name="final_quantities",
#                  startReStr = r"\sConvergence targets achieved\s*\+",
#                  endReStr = r"\| Self-consistent loop stopped\s*\|\+",
#                   subMatchers = [
#                   SM(r"\s*Fermi\s*:\s*(?P<x_elk_fermi_energy__hartree>[-0-9.]+)"),
#                   SM(r"\s*sum of eigenvalues\s*:\s*(?P<energy_sum_eigenvalues__hartree>[-0-9.]+)"),
#                   SM(r"\s*electron kinetic\s*:\s*(?P<electronic_kinetic_energy__hartree>[-0-9.]+)"),
#                   SM(r"\s*core electron kinetic\s*:\s*(?P<x_elk_core_electron_kinetic_energy__hartree>[-0-9.]+)"),
#                   SM(r"\s*Coulomb\s*:\s*(?P<x_elk_coulomb_energy__hartree>[-0-9.]+)"),
#                   SM(r"\s*Coulomb potential\s*:\s*(?P<x_elk_coulomb_potential_energy__hartree>[-0-9.]+)"),
#                   SM(r"\s*nuclear-nuclear\s*:\s*(?P<x_elk_nuclear_nuclear_energy__hartree>[-0-9.]+)"),
#                   SM(r"\s*electron-nuclear\s*:\s*(?P<x_elk_electron_nuclear_energy__hartree>[-0-9.]+)"),
#                   SM(r"\s*Hartree\s*:\s*(?P<x_elk_hartree_energy__hartree>[-0-9.]+)"),
#                   SM(r"\s*Madelung\s*:\s*(?P<x_elk_madelung_energy__hartree>[-0-9.]+)"),
#                   SM(r"\s*xc potential\s*:\s*(?P<energy_XC_potential__hartree>[-0-9.]+)"),
#                   SM(r"\s*exchange\s*:\s*(?P<x_elk_exchange_energy__hartree>[-0-9.]+)"),
#                   SM(r"\s*correlation\s*:\s*(?P<x_elk_correlation_energy__hartree>[-0-9.]+)"),
#                   SM(r"\s*electron entropic\s*:\s*(?P<x_elk_electron_entropic_energy__hartree>[-0-9.]+)"),
#                   SM(r"\s*total energy\s*:\s*(?P<energy_total__hartree>[-0-9.]+)"),
#                   SM(r"\s*Density of states at Fermi energy\s*:\s*(?P<x_elk_dos_fermi__hartree_1>[-0-9.]+)"),
#                   SM(r"\s*Estimated indirect band gap\s*:\s*(?P<x_elk_indirect_gap__hartree>[-0-9.]+)"),
#                   SM(r"\s*Estimated direct band gap\s*:\s*(?P<x_elk_direct_gap__hartree>[-0-9.]+)"),
#                   SM(r"\s*core\s*:\s*(?P<x_elk_core_charge_final>[-0-9.]+)"),
#                   SM(r"\s*valence\s*:\s*(?P<x_elk_valence_charge_final>[-0-9.]+)"),
#                   SM(r"\s*interstitial\s*:\s*(?P<x_elk_interstitial_charge_final>[-0-9.]+)")
#                   ])
255
256
               ]
            )
257
          ])
258
259
260
261
262
263
264
265
266
    ])

parserInfo = {
  "name": "Elk"
}

metaInfoPath = os.path.normpath(os.path.join(os.path.dirname(os.path.abspath(__file__)),"../../../../nomad-meta-info/meta_info/nomad_meta_info/elk.nomadmetainfo.json"))
metaInfoEnv, warnings = loadJsonFile(filePath = metaInfoPath, dependencyLoader = None, extraArgsHandling = InfoKindEl.ADD_EXTRA_ARGS, uri = None)

267
268
269
270
271
272
273
274
275
276
277
cachingLevelForMetaName = {
                            "x_elk_geometry_lattice_vector_x":CachingLevel.Cache,
                            "x_elk_geometry_lattice_vector_y":CachingLevel.Cache,
                            "x_elk_geometry_lattice_vector_z":CachingLevel.Cache,
                            "x_elk_section_lattice_vectors": CachingLevel.Ignore,
                            "x_elk_geometry_reciprocal_lattice_vector_x":CachingLevel.Cache,
                            "x_elk_geometry_reciprocal_lattice_vector_y":CachingLevel.Cache,
                            "x_elk_geometry_reciprocal_lattice_vector_z":CachingLevel.Cache,
                            "x_elk_section_reciprocal_lattice_vectors": CachingLevel.Ignore
                          }

278
279
280
if __name__ == "__main__":
    superContext = ElkContext()
    mainFunction(mainFileDescription, metaInfoEnv, parserInfo, superContext = superContext)