"""Parsers provided by aiida_mlip. The parser is based on sp_parser.py."""from__future__importannotationsfrompathlibimportPathfromaiida.commonimportexceptionsfromaiida.engineimportExitCodefromaiida.ormimportDict,SinglefileDatafromaiida.orm.nodes.process.processimportProcessNodefromaiida.pluginsimportCalculationFactoryimportyamlfromaiida_mlip.parsers.base_parserimportBaseParserPhononCalc=CalculationFactory("mlip.ph")
[docs]classPhononParser(BaseParser):""" Parser class for parsing output of calculation-adapted to accommodate phonons. Parameters ---------- node : aiida.orm.nodes.process.process.ProcessNode ProcessNode of calculation. Methods ------- __init__(node: aiida.orm.nodes.process.process.ProcessNode) Initialize the PhononParser instance. parse(**kwargs: Any) -> int: Parse outputs, store results in the database. Returns ------- int An exit code. Raises ------ exceptions.ParsingError If the ProcessNode being passed was not produced by a PhononCalc. """
[docs]def__init__(self,node:ProcessNode):""" Check that the ProcessNode being passed was produced by a `PhononCalc`. Parameters ---------- node : aiida.orm.nodes.process.process.ProcessNode ProcessNode of calculation. """super().__init__(node)ifnotissubclass(node.process_class,PhononCalc):raiseexceptions.ParsingError("Can only parse `PhononCalc` calculations")
[docs]defparse(self,**kwargs)->int:""" Parse outputs, store results in the database. Parameters ---------- **kwargs : Any Any keyword arguments. Returns ------- int An exit code. """exit_code=super().parse(**kwargs)ifexit_code!=ExitCode(0):returnexit_codephonon_output=(self.node.inputs.out).valuenohdf5=(self.node.inputs.no_hdf5).valuedos=(self.node.inputs.dos).valuepdos=(self.node.inputs.pdos).valuebands=(self.node.inputs.bands).value# Check that folder content is as expectedfiles_retrieved=self.retrieved.list_object_names()files_expected={phonon_output}ifnotfiles_expected.issubset(files_retrieved):self.logger.error(f"Found files '{files_retrieved}', expected to find '{files_expected}'")returnself.exit_codes.ERROR_MISSING_OUTPUT_FILES# Add output file to the outputsself.logger.info(f"Parsing '{phonon_output}'")withself.retrieved.open(phonon_output,"rb")ashandle:self.out("phonon_output",SinglefileData(file=handle,filename=phonon_output))remote_workdir=Path(self.node.get_remote_workdir())phonon_path=remote_workdir/phonon_outputwithphonon_path.open()asf:content=yaml.safe_load(f)results_node=Dict(content)self.out("results_dict",results_node)# dosifdos:dos_path=remote_workdir/"aiida-dos.dat"try:filedata=self.retrieved.base.repository.get_object_content("aiida-dos.dat",mode="rb")exceptFileNotFoundError:self.logger.error("exception in filepath for the density of states")returnself.exit_codes.ERROR_MISSING_OUTPUTdos_path.write_bytes(filedata)results_node=SinglefileData(file=dos_path)self.out("dos",results_node)ifpdos:pdos_path=remote_workdir/"aiida-pdos.dat"try:filedata=self.retrieved.base.repository.get_object_content("aiida-pdos.dat",mode="rb")exceptFileNotFoundError:self.logger.info("exception in filepath for the partial density of states")returnself.exit_codes.ERROR_MISSING_OUTPUTpdos_path.write_bytes(filedata)results_node=SinglefileData(file=pdos_path)self.out("pdos",results_node)ifnotnohdf5:try:filedata=self.retrieved.base.repository.get_object_content("aiida-force_constants.hdf5",mode="rb")exceptFileNotFoundError:self.logger.info("exception in getting force constant filepath")returnself.exit_codes.ERROR_MISSING_OUTPUThdf5_path=remote_workdir/"aiida-force_constants.hdf5"hdf5_path.write_bytes(filedata)hdf5_node=SinglefileData(file=hdf5_path)self.out("force_constants",hdf5_node)# for band structure the required file is aiida-auto_bands.yml.xz# this needs to be changed for hdf5 once janus-core is updatedifbands:bnds_output="aiida-auto_bands.yml.xz"try:filedata=self.retrieved.base.repository.get_object_content(bnds_output,mode="rb")exceptFileNotFoundError:self.logger.info("exception in getting force constant filepath")returnself.exit_codes.ERROR_MISSING_OUTPUTbands_path=remote_workdir/bnds_outputbands_node=SinglefileData(file=bands_path)self.out("band_structure",bands_node)returnExitCode(0)