From 01427529696c8dc6cb6e8393875704f2983a768d Mon Sep 17 00:00:00 2001 From: temok-mx <temok.mx@gmail.com> Date: Tue, 5 Nov 2019 11:19:08 +0100 Subject: [PATCH] Updated all VASPs incars as in VASPs wiki --- vaspparser/parser_vasprun.py | 145 +++++++++++++++++++++++------------ 1 file changed, 97 insertions(+), 48 deletions(-) diff --git a/vaspparser/parser_vasprun.py b/vaspparser/parser_vasprun.py index 813b351..d3f7c78 100644 --- a/vaspparser/parser_vasprun.py +++ b/vaspparser/parser_vasprun.py @@ -38,6 +38,7 @@ eV2J = convert_unit_function("eV", "J") eV2JV = np.vectorize(eV2J) + def crystal_structure_from_cell(cell, eps=1e-4): """Return the crystal structure as a string calculated from the cell. """ @@ -71,6 +72,11 @@ def crystal_structure_from_cell(cell, eps=1e-4): else: raise ValueError('Cannot find crystal structure') +vasp_to_metainfo_type_mapping = { + 'string': ['C'], + 'int': ['i'], + 'logical': ['b', 'C'], + 'float': ['f']} special_points = { 'cubic': {'Γ': [0, 0, 0], @@ -215,10 +221,9 @@ def toBool(value): backend.pwarn("Unexpected value for boolean field: %s" % (value)) return None - metaTypeTransformers = { 'C': lambda x: x.strip(), - 'i': lambda x: int(x.strip()), + 'i': lambda x: int(float(x.strip())), 'f': lambda x: float(x.strip()), 'b': toBool, } @@ -263,8 +268,12 @@ def getVector(el, transform=float, field="v"): class VasprunContext(object): - def __init__(self, logger=None): + + def __init__(self, logger=None): + if logger is None: + logger = logging.getLogger(__name__) self.logger = logger + self.parser = None self.bands = None self.kpoints = None @@ -279,12 +288,8 @@ class VasprunContext(object): self.eFermi = None self.cell = None self.angstrom_cell = None - - self.unknown_incar_params = [] - - if self.logger is None: - logger = logging.getLogger(__name__) - + self.unknown_incars = {} + sectionMap = { "modeling": ["section_run", "section_method"], "structure": ["section_system"], @@ -329,11 +334,17 @@ class VasprunContext(object): dft_plus_u = False ibrion = None nsw = 0 - for el in element: - if (el.tag != "i"): - backend.pwarn("unexpected tag %s %s %r in incar" % - (el.tag, el.attrib, el.text)) - else: + for el in element: + if el.tag == "v": + name = el.attrib.get("name", None) + meta = metaEnv['x_vasp_incar_' + name] + if not meta: + backend.pwarn("Unknown INCAR parameter (not registered in the meta data): %s %s %r" % ( + el.tag, el.attrib, el.text)) + #- - + vector_val = np.asarray(getVector(el)) + backend.addArrayValues(meta.get('name'), vector_val) + elif el.tag == "i": name = el.attrib.get("name", None) meta = metaEnv['x_vasp_incar_' + name] valType = el.attrib.get("type") @@ -392,6 +403,9 @@ class VasprunContext(object): ibrion = int(el.text.strip()) elif name == "NSW": nsw = int(el.text.strip()) + else: + backend.pwarn("unexpected tag %s %s %r in incar" % + (el.tag, el.attrib, el.text)) if ibrion is None: ibrion = -1 if nsw == 0 or nsw == 1 else 0 if nsw == 0: @@ -406,22 +420,27 @@ class VasprunContext(object): backend = parser.backend self.bands = None self.kpoints = None - self.weights = None - for el in element: + self.weights = None + for el in element: if el.tag == "generation": - param = el.attrib.get("param", None) - if param: + param = el.attrib.get("param", None) # eg. listgenerated, Monkhorst-Pack, Gamma + if param: backend.addValue( "x_vasp_k_points_generation_method", param) if param == "listgenerated": + # This implies a path on k-space, potentially a bandstructure calculation + # Save k-path info into a dictionary self.bands = { "divisions": g(el, "i/[@name='divisions']", None), "points": getVector(el) } - elif param == "Monkhorst-Pack": + + elif param in ["Monkhorst-Pack", "Gamma"]: + # This implies a (2D|3D) mesh on k-space, i.e., not a badstructure calculation + # Hence, do nothing: k-points will be stored in the `varray` if-block pass else: - backend.pwarn("unknown k point generation method") + backend.pwarn("Unknown k point generation method '%s'" %(param)) elif el.tag == "varray": name = el.attrib.get("name", None) if name == "kpointlist": @@ -434,7 +453,7 @@ class VasprunContext(object): else: backend.pwarn("Unknown array %s in kpoints" % name) else: - backend.pwarn("Unknown tag %s in kpoints" % el.tag) + backend.pwarn("Unknown tag %s in kpoints" % el.tag) def onEnd_structure(self, parser, event, element, pathStr): backend = parser.backend @@ -627,6 +646,7 @@ class VasprunContext(object): def onEnd_modeling(self, parser, event, element, pathStr): backend = parser.backend + backend.addValue("x_vasp_unknown_incars", self.unknown_incars) if self.ibrion is None or self.ibrion == -1: return samplingGIndex = backend.openSection("section_sampling_method") @@ -641,6 +661,7 @@ class VasprunContext(object): backend.addArrayValues( "frame_sequence_local_frames_ref", np.asarray(self.singleConfCalcs)) backend.closeSection("section_frame_sequence", frameSequenceGIndex) + def onEnd_calculation(self, parser, event, element, pathStr): eConv = eV2J @@ -792,47 +813,76 @@ class VasprunContext(object): backend.pwarn("unexpected tag %s in atominfo" % el.tag) self.labels = np.asarray(labels2) if labels2 else np.asarray(labels) - def incarOutTag(self, el): + def incarOutTag(self, el): backend = self.parser.backend metaEnv = self.parser.backend.metaInfoEnv() if (el.tag != "i"): backend.pwarn("unexpected tag %s %s %r in incar" % (el.tag, el.attrib, el.text)) else: - name = el.attrib.get("name", None) + name = el.attrib.get("name", None) + valType = el.attrib.get("type") meta = metaEnv['x_vasp_incarOut_' + name] - valType = el.attrib.get("type") - if not meta: - self.unknown_incar_params.append((el.tag, el.attrib, el.text)) + + + if not meta: + # Unknown_Incars_Begin: storage into a dictionary + if not valType: + # On vasp's xml files, valType *could* be absent if incar value is float + valType = 'float' + + # map vasp's datatype to nomad's datatype [b, f, i, C, D, R] + nomad_dtypeStr = vasp_to_metainfo_type_mapping[valType][0] + + converter = metaTypeTransformers.get(nomad_dtypeStr) + text_value = el.text.strip() # text representation of incar value + try: + pyvalue = converter(text_value) # python data type + except Exception: + pyvalue = text_value + + # save (name, pyvalue) into a dict + self.unknown_incars[name] = pyvalue + # Unknown_Incars_end else: - if valType: - expectedMetaType = { - 'string': ['C'], - 'int': ['i'], - 'logical': ['b', 'C'] - }.get(valType) - if not expectedMetaType: - backend.pwarn("Unknown value type %s encountered in INCAR out: %s %s %r" % ( - valType, el.tag, el.attrib, el.text)) - elif not meta.get('dtypeStr') in expectedMetaType: - backend.pwarn("type mismatch between meta data %s and INCAR type %s for %s %s %r" % ( - meta.get('dtypeStr'), valType, el.tag, el.attrib, el.text)) - try: - shape = meta.get("shape", None) - dtypeStr = meta.get("dtypeStr", None) - converter = metaTypeTransformers.get(dtypeStr) + if not valType: + valType = 'float' + + vasp_metainfo_type = vasp_to_metainfo_type_mapping.get(valType)[0] + metainfo_type = meta.get('dtypeStr') + if not vasp_metainfo_type: + backend.pwarn("Unknown value type %s encountered in INCAR out: %s %s %r" % ( + valType, el.tag, el.attrib, el.text)) + + elif metainfo_type != vasp_metainfo_type: + if (metainfo_type == 'C' and vasp_metainfo_type == 'b'): + pass + elif (metainfo_type == 'i' and vasp_metainfo_type == 'f'): + pass + else: + backend.pwarn("Data type mismatch: %s. Vasp_type: %s, metainfo_type: %s " % + (name, vasp_metainfo_type, metainfo_type)) + try: + shape = meta.get("shape", None) + converter = metaTypeTransformers.get(metainfo_type) if not converter: backend.pwarn( - "could not find converter for dtypeStr %s when handling meta info %s" % (dtypeStr, meta)) + "could not find converter for dtypeStr %s when handling meta info %s" % + (metainfo_type, meta )) elif shape: vals = re.split("\s+", el.text.strip()) backend.addValue( meta["name"], [converter(x) for x in vals]) else: + # If-block to handle incars without value + if el.text == None: + el.text = '' backend.addValue(meta["name"], converter(el.text)) - except: + + except: backend.pwarn("Exception trying to handle incarOut %s: %s" % ( name, traceback.format_exc())) + if name == 'ENMAX' or name == 'PREC': if name == 'ENMAX': self.enmax = converter(el.text) @@ -862,6 +912,7 @@ class VasprunContext(object): "section_XC_functionals") elif name == "ISPIN": self.ispin = int(el.text.strip()) + def separatorScan(self, element, backend, depth=0): for separators in element: @@ -901,6 +952,8 @@ class VasprunContext(object): "mapping_section_method_basis_set_cell_associated", self.waveCut) backend.closeNonOverlappingSection("section_method_basis_set") except AttributeError: + import traceback + traceback.print_exc() backend.pwarn( "Missing ENMAX for calculating plane wave basis cut off ") except AttributeError: @@ -1132,10 +1185,6 @@ class XmlParser(object): parserErrors=["exception: %s" % sys.exc_info()[1]] ) else: - if len(self.superContext.unknown_incar_params) > 0: - example = self.superContext.unknown_incar_params[0] - backend.pwarn("Unknown INCAR out parameters (not registered in the meta data), e.g. %s %s %r" % example) - backend.finishedParsingSession( parserStatus="ParseSuccess", parserErrors=None -- GitLab