Source code for schrodinger.application.matsci.qexsd.qespresso.documents

# -*- coding: utf-8 -*-
#
# Copyright (c), 2015-2016, Quantum Espresso Foundation and SISSA (Scuola
# Internazionale Superiore di Studi Avanzati). All rights reserved.
# This file is distributed under the terms of the MIT License. See the
# file 'LICENSE' in the root directory of the present distribution, or
# http://opensource.org/licenses/MIT.
# Authors: Davide Brunato
#
import logging
import os.path

from .converters import NebInputConverter
from .converters import PhononInputConverter
from .converters import PwInputConverter
from .converters import TD_spctInConverter
from .converters import TdInputConverter
from .exceptions import ConfigError
from .xsdtypes import XmlDocument
from .xsdtypes import etree_node_to_dict
from .xsdtypes.etree import etree_iter_path

logger = logging.getLogger('qespresso')


[docs]class QeDocument(XmlDocument): """ Abstract class for XML schema based configurations. """
[docs] def __init__(self, xsd_file, input_builder): super(QeDocument, self).__init__(xsd_file) self.input_builder = input_builder self.default_namespace = self.schema.target_namespace qe_nslist = list( map(self.namespaces.get, ['qes', 'neb', 'qes_ph', 'qes_lr', 'qes_spectrum'])) if self.default_namespace not in qe_nslist: raise NotImplementedError( "Converter not implemented for this schema {}".format( self.default_namespace))
[docs] def read_qe_input(self, filename): """ Map from a Fortran input to XML old parameters to correspondent parameter in XML schema. :param filename: :return: """ return self
[docs] def write_qe_input(self, filename): """ Write the XML configuration to a Fortran input. :param filename: :return: """ with open(filename, mode='w+') as f: f.write(self.get_qe_input())
[docs] def get_input_path(self): raise NotImplementedError( "This is an abstract implementation, use a subclass!")
[docs] def get_qe_input(self, use_defaults=True): if self._document is None: raise ConfigError("Configuration not loaded!") qe_input = self.input_builder(xml_file=self._config_file) schema = self.schema input_path = self.get_input_path() input_root = self.find(input_path) # Extract values from input's subtree of the XML document for elem, path in etree_iter_path(input_root, path=input_path): rel_path = path.replace(input_path, '.') node_dict = etree_node_to_dict(elem, schema, root_path=path, use_defaults=use_defaults) logger.debug("Add input for node '{0}' with dict '{1}'".format( elem.tag, node_dict)) # Convert attributes for attr_name, value in elem.attrib.items(): logger.debug("Convert attribute '%s' of element '%s'" % (attr_name, path)) path_key = '%s/%s' % (rel_path, attr_name) if path_key not in qe_input: logger.debug("Attribute's path '%s' not in converter!" % path_key) continue qe_input.set_path(path_key, elem.tag, node_dict) logger.debug("Convert element '%s'" % path) path_key = '%s/_text' % rel_path if schema.get_attributes( path) else rel_path if path_key not in qe_input: logger.debug("Element's path '%s' not in converter!" % path_key) continue qe_input.set_path(path_key, elem.tag, node_dict) if use_defaults: # Add defaults for elements not included in input XML subtree for path in filter( lambda x: x.startswith(input_path) and self.find(x) is None, schema.elements): rel_path = path.replace(input_path, '.') tag = rel_path.rsplit('/', 1)[-1] xsd_attributes = schema.get_attributes(path) defaults_dict = {} defaults_path_keys = [] try: # Add default values for attributes for attr_name, xsd_attribute in xsd_attributes.items(): default_value = xsd_attribute.get_default() if default_value is not None: path_key = '%s/%s' % (rel_path, attr_name) xsd_type = xsd_attribute.xsd_type value = xsd_type.decode(default_value) defaults_dict[attr_name] = value defaults_path_keys.append(path_key) except AttributeError: pass default_value = schema.get_element_default(path) if default_value is not None: path_key = '%s/_text' % rel_path if xsd_attributes else rel_path xsd_type = schema.get_element_type(path) value = xsd_type.decode(default_value) defaults_dict[path_key.rsplit("/")[-1]] = value defaults_path_keys.append(path_key) for path_key in defaults_path_keys: qe_input.set_path(path_key, tag, defaults_dict) return qe_input.get_qe_input()
[docs] def load_fortran_input(self, filename): if self._document is not None: raise ConfigError("Configuration not loaded!") # fortran_input = self.input_builder() return None
[docs]class PwDocument(QeDocument): """ Class to manage PW XML documents. """
[docs] def __init__(self): self._input_tag = 'input' super(PwDocument, self).__init__(xsd_file='%s/scheme/qes.xsd' % os.path.dirname(os.path.abspath(__file__)), input_builder=PwInputConverter)
[docs] def get_input_path(self): return './input'
[docs]class PhononDocument(QeDocument): """ Class to manage Phonon XML documents. """
[docs] def __init__(self): self._input_tag = 'input' super(PhononDocument, self).__init__(xsd_file='%s/scheme/ph_temp.xsd' % os.path.dirname(os.path.abspath(__file__)), input_builder=PhononInputConverter)
[docs] def get_input_path(self): return './inputPH'
[docs] def get_qe_input(self, use_defaults=False): """ overrides get_qe_input calling super get_qe_input with use_defaults set to False. :param use_defaults: :return: the input as obtained from its input builder """ return super(PhononDocument, self).get_qe_input(use_defaults=use_defaults)
[docs]class NebDocument(QeDocument): """ Class to manage NEB XML documents. """
[docs] def __init__(self): self._input_tag = 'input' super(NebDocument, self).__init__(xsd_file='%s/scheme/qes_neb_temp.xsd' % os.path.dirname(os.path.abspath(__file__)), input_builder=NebInputConverter)
[docs] def get_input_path(self): return './input'
[docs]class TdDocument(QeDocument): """ Class to manage TDDFPT """
[docs] def __init__(self): self._input_tag = 'input' super(TdDocument, self).__init__(xsd_file='%s/scheme/tddfpt.xsd' % os.path.dirname(os.path.abspath(__file__)), input_builder=TdInputConverter)
[docs] def get_input_path(self): return '.'
[docs]class SpectrumDocument(QeDocument): """ Class to manage turbo-spectrum inputs """
[docs] def __init__(self): self._input_tag = 'input' super(SpectrumDocument, self).__init__(xsd_file='%s/scheme/qes_spectrum.xsd' % os.path.dirname(os.path.abspath(__file__)), input_builder=TD_spctInConverter)
[docs] def get_input_path(self): return '.'