wien2k_parser.py 15.4 KB
Newer Older
1
from builtins import object
2
from wien2kparser import setup_paths
3
import numpy as np
Daria Tomecka's avatar
Daria Tomecka committed
4
from nomadcore.simple_parser import mainFunction, AncillaryParser, CachingLevel
5
6
from nomadcore.simple_parser import SimpleMatcher as SM
from nomadcore.local_meta_info import loadJsonFile, InfoKindEl
7
import os, sys, json, logging
8
from wien2kparser import wien2k_parser_struct, wien2k_parser_in0, wien2k_parser_in1c, wien2k_parser_in2c, wien2k_parser_in1,  wien2k_parser_in2
9

Daria Tomecka's avatar
Daria Tomecka committed
10
11

################################################################
Daria Tomecka's avatar
Daria Tomecka committed
12
# This is the parser for the main output file (.scf) of WIEN2k.
Daria Tomecka's avatar
Daria Tomecka committed
13
14
################################################################

Daria M. Tomecka's avatar
Daria M. Tomecka committed
15
# Copyright 2016-2018 Daria M. Tomecka, Fawzi Mohamed
Daria Tomecka's avatar
Daria Tomecka committed
16
17
18
19
20
21
22
23
24
25
26
27
28
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

Daria M. Tomecka's avatar
Daria M. Tomecka committed
29
30
31
32
__author__ = "Daria M. Tomecka"
__maintainer__ = "Daria M. Tomecka"
__email__ = "tomeckadm@gmail.com;"
__date__ = "15/05/2017"
Daria Tomecka's avatar
Daria Tomecka committed
33

Daria Tomecka's avatar
Daria Tomecka committed
34

35
36
37
38
39
40
41
42
class Wien2kContext(object):
    """context for wien2k 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"""
Daria Tomecka's avatar
Daria Tomecka committed
43
        self.metaInfoEnv = self.parser.parserBuilder.metaInfoEnv
44
45
46
47
        self.rootSecMethodIndex = None
        self.secMethodIndex = None
        self.secSystemIndex = None
        self.scfIterNr = 0
48
49
50
51
52
53
54
55

    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()

    def onClose_x_wien2k_header(self, backend, gIndex, section):
56
57
58
59
60
61
62
63
64
        version_check = section["x_wien2k_version"]
#        riprova = section["x_wien2k_release_date"][0]
#        print("prova=",prova," riprova=",riprova)
        if version_check:
            backend.addValue("program_version",
                             section["x_wien2k_version"][0] + " " +
                             section["x_wien2k_release_date"][0])
        else:
            backend.addValue("program_version", "Before_wien2k11")
65

Daria Tomecka's avatar
Daria Tomecka committed
66
    def onOpen_section_system(self, backend, gIndex, section):
Daria Tomecka's avatar
Daria Tomecka committed
67
        self.secSystemIndex = gIndex
Daria Tomecka's avatar
Daria Tomecka committed
68

69
70
71
72
73
74
75
76
77
78
79
80
81
82
    def onOpen_section_method(self, backend, gIndex, section):

        mainFile = self.parser.fIn.fIn.name
        fName = mainFile[:-4] + ".in0"
        if os.path.exists(fName):
            subSuperContext = wien2k_parser_in0.Wien2kIn0Context()
            subParser = AncillaryParser(
                fileDescription = wien2k_parser_in0.buildIn0Matchers(),
                parser = self.parser,
                cachingLevelForMetaName = wien2k_parser_in0.get_cachingLevelForMetaName(self.metaInfoEnv, CachingLevel.PreOpenedIgnore),
                superContext = subSuperContext)
            with open(fName) as fIn:
                subParser.parseFile(fIn)

83
84
85
86
87
88
89
90
91
92
93
94
95
96

        mainFile = self.parser.fIn.fIn.name
        fName = mainFile[:-4] + ".in1c"
        if os.path.exists(fName):
            subSuperContext = wien2k_parser_in1c.Wien2kIn1cContext()
            subParser = AncillaryParser(
                fileDescription = wien2k_parser_in1c.buildIn1cMatchers(),
                parser = self.parser,
                cachingLevelForMetaName = wien2k_parser_in1c.get_cachingLevelForMetaName(self.metaInfoEnv, CachingLevel.PreOpenedIgnore),
                superContext = subSuperContext)
            with open(fName) as fIn:
                subParser.parseFile(fIn)


Daria Tomecka's avatar
Daria Tomecka committed
97
98
99
100
101
102
103
104
105
106
107
108
        mainFile = self.parser.fIn.fIn.name
        fName = mainFile[:-4] + ".in2c"
        if os.path.exists(fName):
            subSuperContext = wien2k_parser_in2c.Wien2kIn2cContext()
            subParser = AncillaryParser(
                fileDescription = wien2k_parser_in2c.buildIn2cMatchers(),
                parser = self.parser,
                cachingLevelForMetaName = wien2k_parser_in2c.get_cachingLevelForMetaName(self.metaInfoEnv, CachingLevel.PreOpenedIgnore),
                superContext = subSuperContext)
            with open(fName) as fIn:
                subParser.parseFile(fIn)

109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
        mainFile = self.parser.fIn.fIn.name
        fName = mainFile[:-4] + ".in1"
        if os.path.exists(fName):
            subSuperContext = wien2k_parser_in1.Wien2kIn1Context()
            subParser = AncillaryParser(
                fileDescription = wien2k_parser_in1.buildIn1Matchers(),
                parser = self.parser,
                cachingLevelForMetaName = wien2k_parser_in1.get_cachingLevelForMetaName(self.metaInfoEnv, CachingLevel.PreOpenedIgnore),
                superContext = subSuperContext)
            with open(fName) as fIn:
                subParser.parseFile(fIn)


        mainFile = self.parser.fIn.fIn.name
        fName = mainFile[:-4] + ".in2"
        if os.path.exists(fName):
            subSuperContext = wien2k_parser_in2.Wien2kIn2Context()
            subParser = AncillaryParser(
                fileDescription = wien2k_parser_in2.buildIn2Matchers(),
                parser = self.parser,
                cachingLevelForMetaName = wien2k_parser_in2.get_cachingLevelForMetaName(self.metaInfoEnv, CachingLevel.PreOpenedIgnore),
                superContext = subSuperContext)
            with open(fName) as fIn:
                subParser.parseFile(fIn)
Daria Tomecka's avatar
Daria Tomecka committed
133

134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
        #if self.secMethodIndex is None:
        if self.rootSecMethodIndex is None:
            self.rootSecMethodIndex = gIndex
        self.secMethodIndex = gIndex
#        self.secMethodIndex["single_configuration_to_calculation_method_ref"] = gIndex


    def onClose_section_single_configuration_calculation(self, backend, gIndex, section):
       # write number of SCF iterations
        backend.addValue('number_of_scf_iterations', self.scfIterNr)
        # write the references to section_method and section_system
        backend.addValue('single_configuration_to_calculation_method_ref', self.secMethodIndex)
        backend.addValue('single_configuration_calculation_to_system_ref', self.secSystemIndex)


    def onClose_section_system(self, backend, gIndex, section):

        #backend.addValue("smearing_kind", x_fleur_smearing_kind)
Daria Tomecka's avatar
Daria Tomecka committed
152
153
        smearing_kind = section['x_wien2k_smearing_kind']
        if smearing_kind is not None:
154
155
156
157
        #    value = ''
            backend.addValue('x_wien2k_smearing_kind', value)


158
        smearing_width = section['x_wien2k_smearing_width']
Daria Tomecka's avatar
Daria Tomecka committed
159
        if smearing_width is not None:
160
        #    value = ''
161
            backend.addValue('x_wien2k_smearing_width', value)
162
163
164
165
166

        #   atom labels
        atom_labels = section['x_wien2k_atom_name']
        if atom_labels is not None:
           backend.addArrayValues('atom_labels', np.asarray(atom_labels))
167
168


169
170
171
172
173
174
175
176
177
178
        # atom force
        atom_force = []
        for i in ['x', 'y', 'z']:
            api = section['x_wien2k_for_' + i]
            if api is not None:
               atom_force.append(api)
        if atom_force:
            # need to transpose array since its shape is [number_of_atoms,3] in\the metadata
           backend.addArrayValues('atom_forces', np.transpose(np.asarray(atom_force)))

179
180
181
182
183
184
185
186
187
188
189
190
        mainFile = self.parser.fIn.fIn.name
        fName = mainFile[:-4] + ".struct"
        if os.path.exists(fName):
            structSuperContext = wien2k_parser_struct.Wien2kStructContext()
            structParser = AncillaryParser(
                fileDescription = wien2k_parser_struct.buildStructureMatchers(),
                parser = self.parser,
                cachingLevelForMetaName = wien2k_parser_struct.get_cachingLevelForMetaName(self.metaInfoEnv, CachingLevel.PreOpenedIgnore),
                superContext = structSuperContext)

            with open(fName) as fIn:
                structParser.parseFile(fIn)
191
192
193
194
195



    def onClose_section_scf_iteration(self, backend, gIndex, section):
        #Trigger called when section_scf_iteration is closed.
196

197
198
199
        # count number of SCF iterations
        self.scfIterNr += 1

200
201
202
203
204
# description of the input
mainFileDescription = SM(
    name = 'root',
    weak = True,
    startReStr = "",
205
    sections   = ['section_run','x_wien2k_header'],
206
    subMatchers = [
207
        SM(r"\s*:LABEL[0-9]+: using WIEN2k_(?P<x_wien2k_version>[0-9.]+) \(Release (?P<x_wien2k_release_date>[0-9/.]+)\) in "),
208
        SM(name = 'newRun',
209
210
211
212
#           subMatchers=[
#           SM(r"\s*:LABEL[0-9]+: using WIEN2k_(?P<x_wien2k_version>[0-9.]+) \(Release (?P<x_wien2k_release_date>[0-9/.]+)\) in ")
#           ],
           startReStr = r"\s*:ITE[0-9]+:\s*[0-9]+.\s*ITERATION",
213
214
215
           repeats = True,
           required = True,
           forwardMatch = True,
216
217
           sections   = ['section_method', 'section_system', 'section_single_configuration_calculation'],
           fixedStartValues={'program_name': 'WIEN2k', 'program_basis_set_type': '(L)APW+lo' }, #, 'program_version': 'Before WIEN2k_11'},
218
           subMatchers = [
219
220
221
222
               SM(
                  name = "scf iteration",
                  startReStr = r"\s*:ITE(?P<x_wien2k_iteration_number>[0-9]+):\s*[0-9]*. ITERATION",
                  sections=["section_scf_iteration"],
Daria Tomecka's avatar
Daria Tomecka committed
223
                  repeats = True,
224
                  subMatchers=[
225
                      SM(r":NATO\s*:\s*(?P<x_wien2k_nr_of_independent_atoms>[0-9]+)\s*INDEPENDENT AND\s*(?P<x_wien2k_total_atoms>[0-9]+)\s*TOTAL ATOMS IN UNITCELL"),
Daria Tomecka's avatar
Daria Tomecka committed
226
227
                      SM(r"\s*SUBSTANCE: (?P<x_wien2k_system_name>.*)"),
                      SM(r":POT\s*:\s*POTENTIAL OPTION\s*(?P<x_wien2k_potential_option>[0-9]+)"),
228
                      SM(r":LAT\s*:\s*LATTICE CONSTANTS=\s*(?P<x_wien2k_lattice_const_a>[0-9.]+)\s*(?P<x_wien2k_lattice_const_b>[0-9.]+)\s*(?P<x_wien2k_lattice_const_c>[0-9.]+)"),
229
                      SM(r":VOL\s*:\s*UNIT CELL VOLUME\s*=\s*(?P<x_wien2k_unit_cell_volume_bohr3>[0-9.]+)"),
230
                      SM(r":RKM  : MATRIX SIZE (?P<x_wien2k_matrix_size>[0-9]+)\s*LOs:\s*(?P<x_wien2k_LOs>[0-9.]+)\s*RKM=\s*(?P<x_wien2k_rkm>[0-9.]+)\s*WEIGHT=\s*[0-9.]*\s*\w*:"),
231
                      SM(r":KPT\s*:\s*NUMBER\s*OF\s*K-POINTS:\s*(?P<x_wien2k_nr_kpts>[-+0-9.]+)"),
Daria Tomecka's avatar
Daria Tomecka committed
232
                      #SM(r":GMA\s*:\s*POTENTIAL\sAND\sCHARGE\sCUT-OFF\s*(?P<x_wien2k_cutoff>[0-9.]+)\s*Ry\*\*[0-9.]+"),
233
                      SM(r":GMA\s*:\s*POTENTIAL\sAND\sCHARGE\sCUT-OFF\s*(?P<x_wien2k_cutoff>[0-9.]+)\s*Ry\W\W[0-9.]+"),
Daria Tomecka's avatar
Daria Tomecka committed
234
                      SM(r":GAP\s*:\s*(?P<x_wien2k_ene_gap__rydberg>[-+0-9.]+)\s*Ry\s*=\s*(?P<x_wien2k_ene_gap_eV>[-+0-9.]+)\s*eV\s*.*"),
235
                      SM(r":NOE\s*:\s*NUMBER\sOF\sELECTRONS\s*=\s*(?P<x_wien2k_noe>[0-9.]+)"),
Daria Tomecka's avatar
Daria Tomecka committed
236
                      SM(r":FER\s*:\s(\w*\s*)*-\s\w*\W\w*\WM\W*=\s*(?P<x_wien2k_fermi_ene__rydberg>[-+0-9.]+)"),
237
                      SM(r":GMA\s*:\s*POTENTIAL\sAND\sCHARGE\sCUT-OFF\s*[0-9.]+\s*Ry\W\W[0-9.]+"),
238
239
                      SM(r":CHA(?P<x_wien2k_atom_nr>[-+0-9]+):\s*TOTAL\s*\w*\s*CHARGE INSIDE SPHERE\s*(?P<x_wien2k_sphere_nr>[-+0-9]+)\s*=\s*(?P<x_wien2k_tot_val_charge_sphere>[0-9.]+)",repeats = True),
                      SM(r":CHA\s*:\s*TOTAL\s*\w*\s*CHARGE INSIDE\s*\w*\s*CELL\s=\s*(?P<x_wien2k_tot_val_charge_cell>[-+0-9.]+)"),
240
241
                      SM(r":MMTOT: TOTAL MAGNETIC MOMENT IN CELL =\s*(?P<x_wien2k_mmtot>[-+0-9.]+)"),
                      SM(r":MMINT: MAGNETIC MOMENT IN INTERSTITIAL =\s*(?P<x_wien2k_mmint>[-+0-9.]+)"),
242
                      SM(r":MMI001: MAGNETIC MOMENT IN SPHERE 1 =\s*(?P<x_wien2k_mmi001>[-+0-9.]+)"),
243
                      SM(r":RTO(?P<x_wien2k_atom_nr>[-+0-9]+)\s*:\s*[0-9]+\s*(?P<x_wien2k_density_at_nucleus_valence>[-+0-9.]+)\s*(?P<x_wien2k_density_at_nucleus_semicore>[-+0-9.]+)\s*(?P<x_wien2k_density_at_nucleus_core>[-+0-9.]+)\s*(?P<x_wien2k_density_at_nucleus_tot>[0-9.]+)",repeats = True),
244
245
                      SM(r":NTO\s*:\s*\sTOTAL\s*INTERSTITIAL\s*CHARGE=\s*(?P<x_wien2k_tot_int_charge_nm>[-+0-9.]+)"),
                      SM(r":NTO(?P<x_wien2k_atom_nr>[-+0-9]+)[0-9]*:\s*\sTOTAL\s*CHARGE\s*IN\s*SPHERE\s*(?P<x_wien2k_sphere_nr>[-+0-9]+)\s*=\s*(?P<x_wien2k_tot_charge_in_sphere_nm>[-+0-9.]+)",repeats = True),
246
                      SM(r":DTO(?P<x_wien2k_atom_nr>[-+0-9]+)[0-9]*:\sTOTAL\s*DIFFERENCE\s*CHARGE\W*\w*\s*IN\s*SPHERE\s*(?P<x_wien2k_sphere_nr>[-+0-9]+)\s*=\s*(?P<x_wien2k_tot_diff_charge>[-+0-9.]+)", repeats = True),
Daria Tomecka's avatar
Daria Tomecka committed
247
                      SM(r":DIS\s*:\s*CHARGE\sDISTANCE\s*\W*[0-9.]+\sfor\satom\s*[0-9]*\sspin\s[0-9]*\W\s*(?P<x_wien2k_charge_distance>[0-9.]+)"),
248
249
                      SM(r":CTO\s*:\s*\sTOTAL\s*INTERSTITIAL\s*CHARGE=\s*(?P<x_wien2k_tot_int_charge>[-+0-9.]+)"),
                      SM(r":CTO(?P<x_wien2k_atom_nr>[-+0-9]+)[0-9]*:\s*\sTOTAL\s*CHARGE\s*IN\s*SPHERE\s*(?P<x_wien2k_sphere_nr>[-+0-9]+)\s*=\s*(?P<x_wien2k_tot_charge_in_sphere>[-+0-9.]+)",repeats = True),
250
#                      SM(r":NEC(?P<x_wien2k_necnr>[-+0-9]+)\s*:\s*NUCLEAR AND ELECTRONIC CHARGE\s*(?P<x_wien2k_nuclear_charge>[-+0-9.]+)\s*(?P<x_wien2k_electronic_charge>[0-9.]+)",repeats = True),
Daria Tomecka's avatar
Daria Tomecka committed
251
                      SM(r":ENE\s*:\s*\W*\w*\W*\s*TOTAL\s*ENERGY\s*IN\s*Ry\s*=\s*(?P<x_wien2k_energy_total__rydberg>[-+0-9.]+)"),
252
                      SM(r":FOR[0-9]*:\s*(?P<x_wien2k_atom_nr>[0-9]+).ATOM\s*(?P<x_wien2k_for_abs>[0-9.]+)\s*(?P<x_wien2k_for_x>[-++0-9.]+)\s*(?P<x_wien2k_for_y>[-+0-9.]+)\s*(?P<x_wien2k_for_z>[-+0-9.]+)\s*partial\sforces", repeats = True),
Daria Tomecka's avatar
Daria Tomecka committed
253
                      SM(r":FGL[0-9]*:\s*(?P<x_wien2k_atom_nr>[0-9]+).ATOM\s*(?P<x_wien2k_for_x_gl>[-+0-9.]+)\s*(?P<x_wien2k_for_y_gl>[-+0-9.]+)\s*(?P<x_wien2k_for_z_gl>[-+0-9.]+)\s*partial\sforces", repeats = True)
254
                  ]
255
              )
256
257
           ]
       )
258
259
    ])

260
261
262
263
264
265
266

# which values to cache or forward (mapping meta name -> CachingLevel)

cachingLevelForMetaName = {

    "XC_functional_name": CachingLevel.ForwardAndCache,
    "energy_total": CachingLevel.ForwardAndCache
267

268
269
 }

270
271
272
# loading metadata from nomad-meta-info/meta_info/nomad_meta_info/fhi_aims.nomadmetainfo.json

parserInfo = {
Daria Tomecka's avatar
Daria Tomecka committed
273
274
  "name": "Wien2k",
  "version": "1.0"
275
276
277
278
279
}

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

280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
class Wien2kParser:
    """ A proper class envolop for running this parser from within python. """
    def __init__(self, backend, **kwargs):
        self.backend_factory = backend

    logging.warn('something is wrong')
    logger = logging.getLogger(__name__)
    logger.warn(...)

    def parse(self, mainfile):
        from unittest.mock import patch
        # _logging.getLogger('nomadcore').setLevel(_logging.WARNING)
        backend = self.backend_factory(metaInfoEnv)
        with patch.object(sys, 'argv', ['<exe>', '--uri', 'nmd://uri', mainfile]):
            mainFunction(
                mainFileDescription,
                metaInfoEnv,
                parserInfo,
                superContext=Wien2kContext(),
                superBackend=backend)

        return backend


    def setup_logger(self, new_logger):
        if hasattr(new_logger, 'bind'):
            # tell tests about received logger
            new_logger.debug('received logger')


310
311
312
if __name__ == "__main__":
    superContext = Wien2kContext()
    mainFunction(mainFileDescription, metaInfoEnv, parserInfo, superContext = superContext)