"""Parsers for the specific usage of aiida-lsmo workchains."""
import io
import os
from aiida.common import OutputParsingError, NotExistent
from aiida.engine import ExitCode
from aiida.orm import Dict, BandsData
from aiida.plugins import ParserFactory
from aiida_cp2k.parsers import Cp2kBaseParser
from .parser_functions import parse_cp2k_output_bsse, parse_cp2k_output_advanced
[docs]class Cp2kBsseParser(Cp2kBaseParser): # pylint: disable=too-few-public-methods
"""Advanced AiiDA parser class for a BSSE calculation in CP2K."""
[docs] def _parse_stdout(self):
"""BSSE CP2K output file parser"""
fname = self.node.get_attribute('output_filename')
if fname not in self.retrieved.list_object_names():
return self.exit_codes.ERROR_OUTPUT_STDOUT_MISSING
try:
output_string = self.retrieved.get_object_content(fname)
except IOError:
return self.exit_codes.ERROR_OUTPUT_STDOUT_READ
result_dict = parse_cp2k_output_bsse(output_string)
# nwarnings is the last thing to be printed in the CP2K output file:
# if it is not there, CP2K didn't finish properly
if 'nwarnings' not in result_dict:
raise OutputParsingError("CP2K did not finish properly.")
self.out("output_parameters", Dict(dict=result_dict))
return None
[docs]class Cp2kAdvancedParser(Cp2kBaseParser): # pylint: disable=too-few-public-methods
"""Advanced AiiDA parser class for the output of CP2K."""
[docs] def _parse_stdout(self):
"""Advanced CP2K output file parser"""
fname = self.node.get_attribute('output_filename')
if fname not in self.retrieved.list_object_names():
return self.exit_codes.ERROR_OUTPUT_STDOUT_MISSING
try:
output_string = self.retrieved.get_object_content(fname)
except IOError:
return self.exit_codes.ERROR_OUTPUT_STDOUT_READ
result_dict = parse_cp2k_output_advanced(output_string)
# nwarnings is the last thing to be printed in th eCP2K output file:
# if it is not there, CP2K didn't finish properly
if 'nwarnings' not in result_dict:
raise OutputParsingError("CP2K did not finish properly.")
# Compute the bandgap for Spin1 and Spin2 if eigen was parsed (works also with smearing!)
if 'eigen_spin1_au' in result_dict:
if result_dict['dft_type'] == "RKS":
result_dict['eigen_spin2_au'] = result_dict['eigen_spin1_au']
lumo_spin1_idx = result_dict['init_nel_spin1']
lumo_spin2_idx = result_dict['init_nel_spin2']
if (lumo_spin1_idx > len(result_dict['eigen_spin1_au'])-1) or \
(lumo_spin2_idx > len(result_dict['eigen_spin2_au'])-1):
#electrons jumped from spin1 to spin2 (or opposite): assume last eigen is lumo
lumo_spin1_idx = len(result_dict['eigen_spin1_au']) - 1
lumo_spin2_idx = len(result_dict['eigen_spin2_au']) - 1
homo_spin1 = result_dict['eigen_spin1_au'][lumo_spin1_idx - 1]
homo_spin2 = result_dict['eigen_spin2_au'][lumo_spin2_idx - 1]
lumo_spin1 = result_dict['eigen_spin1_au'][lumo_spin1_idx]
lumo_spin2 = result_dict['eigen_spin2_au'][lumo_spin2_idx]
result_dict['bandgap_spin1_au'] = lumo_spin1 - homo_spin1
result_dict['bandgap_spin2_au'] = lumo_spin2 - homo_spin2
if "kpoint_data" in result_dict:
bnds = BandsData()
bnds.set_kpoints(result_dict["kpoint_data"]["kpoints"])
bnds.labels = result_dict["kpoint_data"]["labels"]
bnds.set_bands(
result_dict["kpoint_data"]["bands"],
units=result_dict["kpoint_data"]["bands_unit"],
)
self.out("output_bands", bnds)
del result_dict["kpoint_data"]
self.out("output_parameters", Dict(dict=result_dict))
return None