Source code for aiida.tools.dbexporters.tcod_plugins.pw

# -*- coding: utf-8 -*-
###########################################################################
# Copyright (c), The AiiDA team. All rights reserved.                     #
# This file is part of the AiiDA code.                                    #
#                                                                         #
# The code is hosted on GitHub at https://github.com/aiidateam/aiida_core #
# For further information on the license, see the LICENSE.txt file        #
# For further information please visit http://www.aiida.net               #
###########################################################################
import re

from aiida.orm.data.upf import UpfData
from aiida.tools.dbexporters.tcod_plugins import BaseTcodtranslator


[docs]class PwTcodtranslator(BaseTcodtranslator): """ Quantum ESPRESSO's PW-specific input and output parameter translator to TCOD CIF dictionary tags. """ _plugin_type_string = "quantumespresso.pw.PwCalculation" _smearing_aliases = { 'gaussian': 'Gaussian', 'gauss': 'Gaussian', 'methfessel-paxton': 'Methfessel-Paxton', 'm-p': 'Methfessel-Paxton', 'mp': 'Methfessel-Paxton', 'marzari-vanderbilt': 'Marzari-Vanderbilt', 'cold': 'Marzari-Vanderbilt', 'm-v': 'Marzari-Vanderbilt', 'mv': 'Marzari-Vanderbilt', 'fermi-dirac': 'Marzari-Vanderbilt', 'f-d': 'Marzari-Vanderbilt', 'fd': 'Marzari-Vanderbilt', } _pseudopotential_types = [ 'NCPP', 'USPP', 'PAW' ] _upf_type_v2_regexp = re.compile( r""" \s* Pseudopotential type:\s*(?P<upf_type>.*) """, re.VERBOSE) @classmethod
[docs] def get_software_package(cls,calc,**kwargs): """ Returns the package or program name that was used to produce the structure. Only package or program name should be used, e.g. 'VASP', 'psi3', 'Abinit', etc. """ return 'Quantum ESPRESSO'
@classmethod def _get_pw_energy_value(cls,calc,energy_type,**kwargs): """ Returns the energy of defined type in eV. """ parameters = calc.out.output_parameters if energy_type not in parameters.attrs(): return None if energy_type + '_units' not in parameters.attrs(): raise ValueError("energy units for {} are " "unknown".format(energy_type)) if parameters.get_attr(energy_type + '_units') != 'eV': raise ValueError("energy units for {} are {} " "instead of eV -- unit " "conversion is not possible " "yet".format(energy_type, parameters.get_attr(energy_type + '_units'))) return parameters.get_attr(energy_type) @classmethod def _get_atom_site_residual_force_Cartesian(cls,calc,index,**kwargs): """ Returns an array with residual force components along the Cartesian axes. """ try: array = calc.out.output_array return [x[index] for x in array.get_array('forces').tolist()[-1]] except KeyError: return None @classmethod def _get_BZ_integration_grid(cls,calc,**kwargs): """ Returns an array with Brillouin zone point counts along each vector of reciprocal lattice. """ try: array,_ = calc.inp.kpoints.get_kpoints_mesh() return array except AttributeError: return None except KeyError: return None @classmethod def _get_BZ_integration_grid_shift(cls,calc,**kwargs): """ Returns an array with Brillouin zone point shifts along each vector of reciprocal lattice. """ try: _,array = calc.inp.kpoints.get_kpoints_mesh() return array except AttributeError: return None except KeyError: return None @classmethod def _get_raw_integration_smearing_method(cls,calc,**kwargs): """ Returns the smearing method name as string, as specified in the input parameters (if specified). If not 'smearing' is not specified, but 'occupations' == 'smearing', string with default value 'gaussian' is returned, as specified in http://www.quantum-espresso.org/wp-content/uploads/Doc/INPUT_PW.html """ parameters = calc.inp.parameters smearing = None try: smearing = parameters.get_dict()['SYSTEM']['smearing'] except KeyError: pass if smearing is None: try: if parameters.get_dict()['SYSTEM']['occupations'] == 'smearing': smearing = 'gaussian' except KeyError as e: pass return smearing @classmethod
[docs] def get_total_energy(cls,calc,**kwargs): """ Returns the total energy in eV. """ return cls._get_pw_energy_value(calc,'energy')
@classmethod
[docs] def get_one_electron_energy(cls,calc,**kwargs): """ Returns one electron energy in eV. """ return cls._get_pw_energy_value(calc,'energy_one_electron')
@classmethod
[docs] def get_exchange_correlation_energy(cls,calc,**kwargs): """ Returns exchange correlation (XC) energy in eV. """ return cls._get_pw_energy_value(calc,'energy_xc')
@classmethod
[docs] def get_ewald_energy(cls,calc,**kwargs): """ Returns Ewald energy in eV. """ return cls._get_pw_energy_value(calc,'energy_ewald')
@classmethod
[docs] def get_hartree_energy(cls,calc,**kwargs): """ Returns Hartree energy in eV. """ return cls._get_pw_energy_value(calc,'energy_hartree')
@classmethod
[docs] def get_fermi_energy(cls,calc,**kwargs): """ Returns Fermi energy in eV. """ return cls._get_pw_energy_value(calc,'fermi_energy')
@classmethod
[docs] def get_number_of_electrons(cls,calc,**kwargs): """ Returns the number of electrons. """ parameters = calc.out.output_parameters if 'number_of_electrons' not in parameters.attrs(): return None return parameters.get_attr('number_of_electrons')
@classmethod
[docs] def get_computation_wallclock_time(cls,calc,**kwargs): """ Returns the computation wallclock time in seconds. """ parameters = calc.out.output_parameters if 'wall_time_seconds' not in parameters.attrs(): return None return parameters.get_attr('wall_time_seconds')
@classmethod
[docs] def get_atom_site_residual_force_Cartesian_x(cls,calc,**kwargs): """ Returns a list of x components for Cartesian coordinates of residual force for atom. The list order MUST be the same as in the resulting structure. """ return cls._get_atom_site_residual_force_Cartesian(calc,0)
@classmethod
[docs] def get_atom_site_residual_force_Cartesian_y(cls,calc,**kwargs): """ Returns a list of y components for Cartesian coordinates of residual force for atom. The list order MUST be the same as in the resulting structure. """ return cls._get_atom_site_residual_force_Cartesian(calc,1)
@classmethod
[docs] def get_atom_site_residual_force_Cartesian_z(cls,calc,**kwargs): """ Returns a list of z components for Cartesian coordinates of residual force for atom. The list order MUST be the same as in the resulting structure. """ return cls._get_atom_site_residual_force_Cartesian(calc,2)
@classmethod
[docs] def get_BZ_integration_grid_X(cls,calc,**kwargs): """ Returns a number of points in the Brillouin zone along reciprocal lattice vector X. """ array = cls._get_BZ_integration_grid(calc,**kwargs) if array is not None: return array[0] else: return None
@classmethod
[docs] def get_BZ_integration_grid_Y(cls,calc,**kwargs): """ Returns a number of points in the Brillouin zone along reciprocal lattice vector Y. """ array = cls._get_BZ_integration_grid(calc,**kwargs) if array is not None: return array[1] else: return None
@classmethod
[docs] def get_BZ_integration_grid_Z(cls,calc,**kwargs): """ Returns a number of points in the Brillouin zone along reciprocal lattice vector Z. """ array = cls._get_BZ_integration_grid(calc,**kwargs) if array is not None: return array[2] else: return None
@classmethod
[docs] def get_BZ_integration_grid_shift_X(cls,calc,**kwargs): """ Returns the shift of the Brillouin zone points along reciprocal lattice vector X. """ array = cls._get_BZ_integration_grid_shift(calc,**kwargs) if array is not None: return array[0] else: return None
@classmethod
[docs] def get_BZ_integration_grid_shift_Y(cls,calc,**kwargs): """ Returns the shift of the Brillouin zone points along reciprocal lattice vector Y. """ array = cls._get_BZ_integration_grid_shift(calc,**kwargs) if array is not None: return array[1] else: return None
@classmethod
[docs] def get_BZ_integration_grid_shift_Z(cls,calc,**kwargs): """ Returns the shift of the Brillouin zone points along reciprocal lattice vector Z. """ array = cls._get_BZ_integration_grid_shift(calc,**kwargs) if array is not None: return array[2] else: return None
@classmethod
[docs] def get_integration_smearing_method(cls,calc,**kwargs): """ Returns the smearing method name as string. """ smearing = cls._get_raw_integration_smearing_method(calc,**kwargs) if smearing is None: return None elif smearing in cls._smearing_aliases: return cls._smearing_aliases[smearing] else: return 'other'
@classmethod
[docs] def get_integration_smearing_method_other(cls,calc,**kwargs): """ Returns the smearing method name as string if the name is different from specified in cif_dft.dic. """ smearing = cls._get_raw_integration_smearing_method(calc,**kwargs) if smearing is None or smearing in cls._smearing_aliases: return None else: return smearing
@classmethod
[docs] def get_integration_Methfessel_Paxton_order(cls,calc,**kwargs): """ Returns the order of Methfessel-Paxton approximation if used. """ if cls.get_integration_smearing_method(calc,**kwargs) == \ 'Methfessel-Paxton': return 1 else: return None
@classmethod
[docs] def get_kinetic_energy_cutoff_wavefunctions(cls,calc,**kwargs): """ Returns kinetic energy cutoff for wavefunctions in eV. """ from aiida.common.constants import ry_to_ev parameters = calc.inp.parameters ecutwfc = None try: ecutwfc = parameters.get_dict()['SYSTEM']['ecutwfc'] except KeyError: pass if ecutwfc is None: return None else: return ecutwfc * ry_to_ev
@classmethod
[docs] def get_kinetic_energy_cutoff_charge_density(cls,calc,**kwargs): """ Returns kinetic energy cutoff for charge density in eV. .. note :: by default returns 4 * ecutwfc, as indicated in http://www.quantum-espresso.org/wp-content/uploads/Doc/INPUT_PW.html """ from aiida.common.constants import ry_to_ev parameters = calc.inp.parameters try: return parameters.get_dict()['SYSTEM']['ecutrho'] * ry_to_ev except KeyError: pass ecutwfc = cls.get_kinetic_energy_cutoff_wavefunctions(calc) if ecutwfc is None: return None else: return 4 * ecutwfc
@classmethod
[docs] def get_kinetic_energy_cutoff_EEX(cls,calc,**kwargs): """ Returns kinetic energy cutoff for exact exchange (EEX) operator in eV. .. note :: by default returns ecutrho, as indicated in http://www.quantum-espresso.org/wp-content/uploads/Doc/INPUT_PW.html """ from aiida.common.constants import ry_to_ev parameters = calc.inp.parameters try: return parameters.get_dict()['SYSTEM']['ecutfock'] * ry_to_ev except KeyError: pass return cls.get_kinetic_energy_cutoff_charge_density(calc)
@classmethod def _get_raw_pseudopotential_type(cls,calc,**kwargs): """ """ from aiida.orm.data.upf import parse_upf types = {} for node in calc.get_inputs(): if not isinstance(node,UpfData): continue element = node.element parsed = parse_upf(node.get_file_abs_path()) if parsed['version'] != "2": types[element] = None continue upf_type = None with open(fname) as f: for line in f: match = _upf_type_v2_regexp.match(line.strip()) if match: upf_type = match.group('upf_type') break types[element] = upf_type return types @classmethod
[docs] def get_pseudopotential_atom_type(cls,calc,**kwargs): """ Returns a list of atom types. Each atom type MUST occur only once in this list. List MUST be sorted. """ raw_types = cls._get_raw_pseudopotential_type(calc,**kwargs) return sorted(raw_types)
@classmethod
[docs] def get_pseudopotential_type(cls,calc,**kwargs): """ Returns a list of pseudopotential types. List MUST be sorted by atom types. """ types = [] raw_types = cls._get_raw_pseudopotential_type(calc,**kwargs) for element in sorted(raw_types): if raw_types[element] is None or \ raw_types[element] in _pseudopotential_types: types.append(raw_types[element]) else: types.append('other') return types
@classmethod
[docs] def get_pseudopotential_type_other_name(cls,calc,**kwargs): """ Returns a list of other pseudopotential type names. List MUST be sorted by atom types. """ types = [] raw_types = cls._get_raw_pseudopotential_type(calc,**kwargs) for element in sorted(raw_types): if raw_types[element] is None or \ raw_types[element] in _pseudopotential_types: types.append(None) else: types.append(raw_types[element]) return types