Source code for aiida_quantumespresso.calculations.xspectra

# -*- coding: utf-8 -*-
"""Classes and methods for running xspectra.x with AiiDA."""

import os

from aiida import orm
from aiida.common import exceptions
from aiida.orm import Dict, SinglefileData, XyData
from aiida.plugins import DataFactory

from aiida_quantumespresso.calculations.namelists import NamelistsCalculation

[docs]KpointsData = DataFactory('core.array.kpoints')
[docs]class XspectraCalculation(NamelistsCalculation): """CalcJob implementation for the xspectra.x code of Quantum ESPRESSO."""
[docs] _Plotcore_FILENAME = 'stdout'
[docs] _Spectrum_FILENAME = 'xanes.dat'
[docs] _XSPECTRA_SAVE_FILE = 'xanes.sav'
[docs] _XSPECTRA_GAMMA_FILE = 'gamma.dat'
[docs] _default_namelists = ['INPUT_XSPECTRA', 'PLOT', 'PSEUDOS', 'CUT_OCC']
[docs] _blocked_keywords = [('INPUT_XSPECTRA', 'outdir', NamelistsCalculation._OUTPUT_SUBFOLDER), ('INPUT_XSPECTRA', 'prefix', NamelistsCalculation._PREFIX), ('INPUT_XSPECTRA', 'x_save_file', _XSPECTRA_SAVE_FILE), ('PLOT', 'gamma_file', _XSPECTRA_GAMMA_FILE), ('PSEUDOS', 'filecore', _Plotcore_FILENAME)]
[docs] _internal_retrieve_list = [_Spectrum_FILENAME]
[docs] _retrieve_singlefile_list = []
[docs] _retrieve_temporary_list = []
[docs] _default_parser = 'quantumespresso.xspectra'
@classmethod
[docs] def define(cls, spec): """Define the process specification.""" super().define(spec) spec.input('parent_folder', valid_type=orm.RemoteData, required=True) spec.input( 'core_wfc_data', valid_type=SinglefileData, required=True, help='Core wavefunction data, generated by the upf2plotcore.sh utility' ) spec.input( 'kpoints', valid_type=KpointsData, required=True, help='The K-point sampling to be used for the XSpectra calculation' ) spec.input( 'gamma_file', valid_type=SinglefileData, required=False, help='An optional file containing the data for the broadening function used when' ' `gamma_mode=file`' ) spec.output('output_parameters', valid_type=Dict) spec.output('spectra', valid_type=XyData) spec.default_output_node = 'output_parameters' spec.exit_code( 313, 'ERROR_OUTPUT_ABSORBING_SPECIES_WRONG', message='xiabs was set incorrectly, check and ensure that the index value correctly refers ' 'to the atomic species containing the core-hole (where the index starts from 1).' ) spec.exit_code( 314, 'ERROR_OUTPUT_ABSORBING_SPECIES_ZERO', message='xiabs was either set to 0 or less, or was greater than ntyp.' ) spec.exit_code( 400, 'ERROR_OUT_OF_WALLTIME', message='The time limit set for the calculation was exceeded, and the job wrote a save file ' 'before exiting.' ) spec.exit_code( 330, 'ERROR_READING_SPECTRUM_FILE', message='The xspectra output file could not be read from the retrieved folder.' ) spec.exit_code( 331, 'ERROR_READING_SPECTRUM_FILE_DATA', message='The spectrum data file could not be read using NumPy genfromtxt' )
[docs] def generate_input_file(self, parameters): # pylint: disable=arguments-differ """Add kpoint handling to the inherited method. This checks that the offset for the mesh is in a valid format, converts the offset from AiiDA format to QE format, and adds the kpoint mesh input to the end of the file. Essentially this copies the method used in prepare_for_submission from the BasePwCpInputGenerator class. """ file_content = super().generate_input_file(parameters) kpmesh, offset = self.inputs.kpoints.get_kpoints_mesh() if any(i not in [0, 0.5] for i in offset): raise exceptions.InputValidationError('offset list must only be made of 0 or 0.5 floats') xs_offset = [0 if i == 0. else 1 for i in offset] kpoint_string = f'{kpmesh[0]} {kpmesh[1]} {kpmesh[2]} {xs_offset[0]} {xs_offset[1]} {xs_offset[2]}' file_content += f'\n{kpoint_string}' return file_content
[docs] def prepare_for_submission(self, folder): """Override the inherited method to add the core wavefunction data file to the local_copy_list.""" calcinfo = super().prepare_for_submission(folder) # append the core wavefunction data node to the copy list core_file = self.inputs.core_wfc_data core_file_info = (core_file.uuid, core_file.filename, core_file.filename) calcinfo.local_copy_list.append(core_file_info) # if included as an input, append the gamma file node to the copy list if 'gamma_file' in self.inputs: gamma_file = self.inputs.gamma_file gamma_file_info = (gamma_file.uuid, gamma_file.filename, gamma_file.filename) calcinfo.local_copy_list.append(gamma_file_info) # Check if the parent folder is an XspectraCalculation type, if so we then copy the # save file to enable calculation restarts and re-plots. parent_folder = self.inputs.parent_folder parent_calc = parent_folder.creator if parent_calc.process_type == 'aiida.calculations:quantumespresso.xspectra': calcinfo.remote_copy_list.append(( parent_folder.computer.uuid, os.path.join(parent_folder.get_remote_path(), self._XSPECTRA_SAVE_FILE), '.' )) return calcinfo