def _parser_function(self): parser_warnings = {} # for compatibility try: errfile = self._params['SCHED_ERROR_FILE'] errfile = self._out_folder.get_abs_path(errfile) except KeyError: raise OutputParsingError( "{} expects the SCHED_ERROR_FILE to " "be provided as a parameter.".format( self.__class__.__name__) ) except OSError: raise OutputParsingError( "SCHED_ERROR_FILE ({}/{}) not found !".format( self._out_folder.get_abs_path(), self._params['SCHED_ERROR_FILE'] ) ) # === parse errors & warnings === # just a text blob --> no way to parse things more cleanly ?!! with open(errfile, 'r') as f: errors = f.read() # use if/else to make things more explicit if errors: errors = ParameterData(dict={'runtime_errors': errors}) else: errors = ParameterData(dict={'runtime_errors': None}) # return [('runtime_errors', errors), ('bad.key', errors)], parser_warnings # for debug return [('runtime_errors', errors)], parser_warnings
def __init__(self, calc): """Initialize the instance of RaspaParser.""" super(RaspaParser, self).__init__(calc) # check for valid input if not isinstance(calc, RaspaCalculation): raise OutputParsingError("Input calc must be a RaspaCalculation")
def _parser_function(self): """ Parses the vasprun.xml using the Pymatgen Vasprun function. """ vasp_param = {} # ParameterData parser_warnings = {} # return non-critical errors vspr = vasp.Vasprun(self._out_folder.get_abs_path('vasprun.xml'), exception_on_bad_xml=False) # vasp_param['final_energy'] = vspr.final_energy # This includes PV vasp_param['energy'] = vspr.ionic_steps[-1]['electronic_steps'][-1][ 'e_wo_entrp'] # Pure internal energy (U) as appear in OUTCAR # construct proper output format try: nodes_list = [] parameter_data = ParameterData(dict=vasp_param) nodes_list.append(('output_parameters', parameter_data)) except Exception, e: msg = ("Failed to create AiiDA data structures " "(ParameterData/ArrrayData) from parsed data, " "with error message:\n>> {}".format(e)) raise OutputParsingError(msg)
def _parser_function(self): """ Parses the XDATCAR using custom function. """ parser_warnings = {} # return non-critical errors timestep = self._calc.inp.incar.dict.NSW * 1e-3 # In picoseconds # extract data try: step_ids, positions, time, cells, symbols = read_VASP_XDATCAR( self._out_folder.get_abs_path('XDATCAR'), timestep) except: print('Error parsing XDATCAR') # construct proper trajectory data format trajectory_data = TrajectoryData() try: nodes_list = [] trajectory_data.set_trajectory(step_ids, cells, symbols, positions, times=time) nodes_list.append(('trajectory_data', trajectory_data)) except Exception, e: msg = ("Failed to create AiiDA data structures " "(ParameterData/ArrrayData) from parsed data, " "with error message:\n>> {}".format(e)) raise OutputParsingError(msg)
def _parser_function(self): """ Parses the vasprun.xml. """ # Get born charges and epsilon nodes_list = [] array_data = ArrayData() try: import xml.etree.cElementTree as ET tree = ET.parse(self._out_folder.get_abs_path('vasprun.xml')) root = tree.getroot() for elements in root.iter('varray'): if elements.attrib['name'] == 'epsilon': epsilon = [] for row in elements: epsilon.append(np.array(row.text.split(), dtype=float)) epsilon = np.array(epsilon) array_data.set_array('epsilon', epsilon) break for elements in root.iter('array'): try: if elements.attrib['name'] == 'born_charges': born_charges = [] for atom in elements[1:]: atom_array = [] for c in atom: atom_array.append( np.array(c.text.split(), dtype=float)) born_charges.append(atom_array) born_charges = np.array(born_charges) array_data.set_array('born_charges', born_charges) break except KeyError: pass except: pass # Use pymatgen vasp parser to get atomic forces and stress tensor vspr = Vasprun(self._out_folder.get_abs_path('vasprun.xml'), exception_on_bad_xml=False) # Get forces using pymatgen try: forces = np.array([vspr.ionic_steps[-1]['forces']]) array_data.set_array('forces', forces) except Exception, e: msg = ("Processing forces, " "with error Message:\n>> {}".format(e)) raise OutputParsingError(msg)
def __init__(self, calculation): from .calculations import Wannier90Calculation # check for valid input if not isinstance(calculation, Wannier90Calculation): raise OutputParsingError("Input must calc must be a " "Wannier90Calculation") super(Wannier90Parser, self).__init__(calculation)
def __init__(self,calculation): """ Initialize the instance of AseParser """ # check for valid input if not isinstance(calculation,AseCalculation): raise OutputParsingError("Input calculation must be a AseCalculation") self._calc = calculation
def __init__(self, calculation): """ Initialize Parser instance """ super(NetworkParser, self).__init__(calculation) # check for valid input if not isinstance(calculation, NetworkCalculation): raise OutputParsingError("Can only parse NetworkCalculation")
def __init__(self, calculation): # """ # Initialize Parser instance # """ super(ApeParser, self).__init__(calculation) # # # check for valid input if not isinstance(calculation, ApeCalculation): raise OutputParsingError("Can only parse ApeCalculation")
def __init__(self, calculation): ''' initializes with a Calculation object ''' super(VaspParser, self).__init__(calculation) if not isinstance(calculation, VaspCalculation): raise OutputParsingError( 'Input calculation must be a VaspCalculation') self._calc = calculation
def parse_chi(self, filepath): """ Parse the contents of the file {prefix}.chi.dat as written by a HpCalculation :param filepath: absolute filepath to the chi.dat output file :returns: dictionary with parsed contents """ try: with open(filepath, 'r') as handle: data = handle.readlines() except IOError as exception: raise OutputParsingError( "could not read the '{}' output file".format( os.path.basename(filepath))) result = {} blocks = { 'chi0': [None, None], 'chi1': [None, None], } for line_number, line in enumerate(data): if 'chi0' in line: blocks['chi0'][0] = line_number + 1 if 'chi1' in line: blocks['chi0'][1] = line_number blocks['chi1'][0] = line_number + 1 blocks['chi1'][1] = len(data) break if not all(sum(blocks.values(), [])): raise OutputParsingError( "could not determine beginning and end of all blocks in '{}'". format(os.path.basename(filepath))) for matrix_name in ('chi0', 'chi1'): matrix_block = blocks[matrix_name] matrix_data = data[matrix_block[0]:matrix_block[1]] matrix = numpy.matrix(self.parse_hubbard_matrix(matrix_data)) result[matrix_name] = matrix return result
def __init__(self, calculation): """ Initialize Parser instance """ super(RipsParser, self).__init__(calculation) # check for valid input if not isinstance(calculation, RipsDistanceMatrixCalculation): raise OutputParsingError( "Can only parse RipsDistanceMatrixCalculation")
def __init__(self,calculation): """ Initialize the instance of ShirleyParser """ # check for valid input if not isinstance(calculation,ShirleyCalculation): raise OutputParsingError("Input calculation must be a " "ShirleyCalculation") super(ShirleyParser, self).__init__(calculation) self._eps_re_array_linkname = 'array_eps_re' self._eps_im_array_linkname = 'array_eps_im'
def _parser_function(self): """ Parses CONTCAR/POSCAR file. :output_structure: name of the structure file; must be specified in parameters list. """ parser_warnings = {} # return non-critical errors nodes_list = [] try: ofile = self._params['OUTPUT_STRUCTURE'] out_structure = self._out_folder.get_abs_path(ofile) out_structure = vasp.Poscar.from_file(out_structure) out_structure = disassemble_poscar(out_structure) except KeyError: raise OutputParsingError( "Output structure file was not specified in params!") except OSError: raise OutputParsingError( "Output structure file ({}/{}) not found!".format( self.out_folder.get_abs_path(), ofile)) except Exception as e: raise OutputParsingError("Parsing of output structure failed! " "Error: {}".format(e)) # Small hack to change name of output structure node to be consistent with QE plugin out_structure['output_structure'] = out_structure.pop('structure') for item in out_structure: nodes_list.append((item, out_structure[item])) if not nodes_list: parser_warnings.setdefault( 'Returning empty node list.', 'Parsing of the output structure may have quietly failed!') if not parser_warnings: parser_warnings = None return nodes_list, parser_warnings
def __init__(self, calculation): """ Initialize Parser instance """ CryBasicCalculation = CalculationFactory('crystal17.basic') CryMainCalculation = CalculationFactory('crystal17.main') # check for valid input if not isinstance(calculation, (CryBasicCalculation, CryMainCalculation)): raise OutputParsingError( "Can only parse CryBasicCalculation or CryMainCalculation") super(CryBasicParser, self).__init__(calculation)
def _parse_stdout(self, out_folder, new_nodes_list): fn = self._calc._OUTPUT_FILE_NAME if fn not in out_folder.get_folder_list(): raise OutputParsingError("Cp2k output file not retrieved") result_dict = {'exceeded_walltime': False} abs_fn = out_folder.get_abs_path(fn) with open(abs_fn, "r") as f: for line in f.readlines(): if line.startswith(' ENERGY| '): result_dict['energy'] = float(line.split()[8]) result_dict['energy_units'] = "a.u." if 'The number of warnings for this run is' in line: result_dict['nwarnings'] = int(line.split()[-1]) if 'exceeded requested execution time' in line: result_dict['exceeded_walltime'] = True if 'nwarnings' not in result_dict: raise OutputParsingError("CP2K did not finish properly.") pair = ('output_parameters', ParameterData(dict=result_dict)) new_nodes_list.append(pair)
def _parser_function(self): """ Parses the vasprun.xml using the Pymatgen Vasprun function. """ vasp_param = {} # ParameterData vasp_array = {} # ArrayData parser_warnings = {} # return non-critical errors # parameter data keys _vasprun_keys = [ # directly accessible, by name # logical 'converged', 'converged_electronic', 'converged_ionic', 'dos_has_errors', 'is_spin', 'is_hubbard', # value 'efermi' ] _vasprun_special_keys = [ # can't be accessed directly # logical 'is_band_gap_direct', # value 'no_ionic_steps', 'final_energy', # returned as FloatWithUnit 'energy_units', 'free_energy', 'energy_wo_entropy', 'energy_T0', 'entropy_TS', 'no_electronic_steps', 'total_no_electronic_steps', 'band_gap', 'cbm', 'vbm', ] # array data keys # TODO # list --> array; see what exactly ArrayData supports # parsing output files try: vspr = vasp.Vasprun(self._out_folder.get_abs_path('vasprun.xml')) except Exception, e: msg = ("Parsing vasprun file in pymatgen failed, " "with error message:\n>> {}".format(e)) raise OutputParsingError(msg)
class Custom_vasprun_parserInstruction(BaseInstruction): _input_file_list_ = ['vasprun.xml', 'OUTCAR'] def _parser_function(self): """ Parses the vasprun.xml using the Pymatgen Vasprun function. """ vasp_param = {} # ParameterData parser_warnings = {} # return non-critical errors # extract data try: with open(self._out_folder.get_abs_path('OUTCAR'), 'r') as f: text = f.readlines() except: print('Error opening') try: vspr = vasp.Vasprun(self._out_folder.get_abs_path('vasprun.xml')) vasp_param['energy'] = vspr.final_energy # vasp_param['volume'] = vspr.final_structure.lattice.volume #Not here!, not necessary except Exception, e: msg = ("Parsing vasprun file in pymatgen failed, " "with error message:\n>> {}".format(e)) raise OutputParsingError(msg) # Get forces using phonopy functions try: force = vasp_phonopy._get_forces_vasprun_xml( vasp_phonopy._iterparse( self._out_folder.get_abs_path('vasprun.xml'), tag='varray')) vasp_param['atomic_force'] = force.tolist() except Exception, e: msg = ("Processing of extracted data failed, " "with error Message:\n>> {}".format(e)) raise OutputParsingError(msg)
def __init__(self, calculation): """Initialize the instance of YamboParser""" from aiida.common import aiidalogger self._logger = aiidalogger.getChild('parser').getChild( self.__class__.__name__) # check for valid input if not isinstance(calculation, YamboCalculation): raise OutputParsingError( "Input calculation must be a YamboCalculation") self._calc = calculation self._eels_array_linkname = 'array_eels' self._eps_array_linkname = 'array_eps' self._alpha_array_linkname = 'array_alpha' self._qp_array_linkname = 'array_qp' self._ndb_linkname = 'array_ndb' self._ndb_QP_linkname = 'array_ndb_QP' self._ndb_HF_linkname = 'array_ndb_HFlocXC' self._lifetime_bands_linkname = 'bands_lifetime' self._quasiparticle_bands_linkname = 'bands_quasiparticle' self._parameter_linkname = 'output_parameters' super(YamboParser, self).__init__(calculation)
def _parser_function(self): """ Parses the vasprun.xml using the Pymatgen Vasprun function. """ vasp_param = {} # ParameterData parser_warnings = {} # return non-critical errors # extract data try: with open(self._out_folder.get_abs_path('OUTCAR'), 'r') as f: text = f.readlines() except: print('Error opening') try: vspr = vasp.Vasprun(self._out_folder.get_abs_path('vasprun.xml')) vasp_param['energy'] = vspr.final_energy # vasp_param['volume'] = vspr.final_structure.lattice.volume #Not here!, not necessary except Exception, e: msg = ("Parsing vasprun file in pymatgen failed, " "with error message:\n>> {}".format(e)) raise OutputParsingError(msg)
def create_inputs(inpath, outpath): """ create ``crystal17.main`` input nodes from an existing run NB: none of the nodes are stored, also existing basis will be retrieved if availiable :param inpath: path to .d12 file :param outpath: path to .out file :return: dictionary of inputs, with keys 'structure', 'parameters', 'settings', 'structure', 'basis' """ from aiida.orm import DataFactory, CalculationFactory calc_cls = CalculationFactory('crystal17.main') basis_cls = DataFactory('crystal17.basisset') struct_cls = DataFactory('structure') structsettings_cls = DataFactory('crystal17.structsettings') inputs = {} with open(inpath) as f: d12content = f.read() output_dict, basis_sets, atom_props = extract_data(d12content) cryparse = CrystalOutputPlugin() if not os.path.exists(outpath): raise OutputParsingError( "The raw data file does not exist: {}".format(outpath)) with open(outpath) as f: try: data = cryparse.read_file(f, log_warnings=False) except IOError as err: raise OutputParsingError( "Error in CRYSTAL 17 run output: {}".format(err)) # we retrieve the initial primitive geometry and symmetry atoms = _create_atoms(data) # convert fragment (i.e. unfixed) to fixed if "fragment" in atom_props: frag = atom_props.pop("fragment") atom_props["fixed"] = [ i + 1 for i in range(atoms.get_number_of_atoms()) if i + 1 not in frag ] atoms.set_tags(_create_tags(atom_props, atoms)) structure = struct_cls(ase=atoms) inputs['structure'] = structure settings_dict = {"kinds": {}} for key, vals in atom_props.items(): settings_dict["kinds"][key] = [ structure.sites[i - 1].kind_name for i in vals ] settings_dict["operations"] = data["initial"]["primitive_symmops"] # TODO retrieve centering code, crystal system and spacegroup settings_dict["space_group"] = 1 settings_dict["crystal_type"] = 1 settings_dict["centring_code"] = 1 settings = structsettings_cls(data=settings_dict) parameters = calc_cls.prepare_and_validate(output_dict, structure, settings) inputs['parameters'] = parameters inputs['settings'] = settings inputs["basis"] = {} for bset in basis_sets: bfile = tempfile.NamedTemporaryFile(delete=False) try: with open(bfile.name, "w") as f: f.write(bset) bdata, _ = basis_cls.get_or_create( bfile.name, use_first=False, store_basis=False) # TODO report if bases created or retrieved finally: os.remove(bfile.name) inputs["basis"][bdata.element] = bdata return inputs
def parse_hubbard(self, filepath): """ Parse the contents of the file {prefix}.Hubbard_U.dat as written by a HpCalculation :param filepath: absolute filepath to the Hubbard_U.dat output file :returns: dictionary with parsed contents """ try: with open(filepath, 'r') as handle: data = handle.readlines() except IOError as exception: raise OutputParsingError( "could not read the '{}' output file".format( os.path.basename(filepath))) result = {'hubbard_U': {'sites': []}} blocks = { 'chi0': [None, None], 'chi1': [None, None], 'chi0_inv': [None, None], 'chi1_inv': [None, None], 'hubbard': [None, None], } for line_number, line in enumerate(data): if 'site n.' in line: parsed = False subline_number = line_number + 1 while not parsed: subline = data[subline_number].strip() if subline: subline_number += 1 subdata = subline.split() result['hubbard_U']['sites'].append({ 'index': subdata[0], 'type': subdata[1], 'kind': subdata[2], 'spin': subdata[3], 'new_type': subdata[4], 'new_kind': subdata[5], 'value': subdata[6], }) else: parsed = True if 'chi0 matrix' in line: blocks['chi0'][0] = line_number + 1 if 'chi1 matrix' in line: blocks['chi0'][1] = line_number blocks['chi1'][0] = line_number + 1 if 'chi0^{-1} matrix' in line: blocks['chi1'][1] = line_number blocks['chi0_inv'][0] = line_number + 1 if 'chi1^{-1} matrix' in line: blocks['chi0_inv'][1] = line_number blocks['chi1_inv'][0] = line_number + 1 if 'Hubbard matrix' in line: blocks['chi1_inv'][1] = line_number blocks['hubbard'][0] = line_number + 1 blocks['hubbard'][1] = len(data) break if not all(sum(blocks.values(), [])): raise OutputParsingError( "could not determine beginning and end of all matrix blocks in '{}'" .format(os.path.basename(filepath))) for matrix_name in ('chi0', 'chi1', 'chi0_inv', 'chi1_inv', 'hubbard'): matrix_block = blocks[matrix_name] matrix_data = data[matrix_block[0]:matrix_block[1]] matrix = self.parse_hubbard_matrix(matrix_data) if len(set(matrix.shape)) != 1: raise OutputParsingError( "the matrix '{}' in '{}'' is not square but has shape {}". format(matrix_name, os.path.basename(filepath), matrix.shape)) result[matrix_name] = matrix return result
try: forces = np.array([vspr.ionic_steps[-1]['forces']]) array_data.set_array('forces', forces) except Exception, e: msg = ("Processing forces, " "with error Message:\n>> {}".format(e)) raise OutputParsingError(msg) try: stress = np.array(vspr.ionic_steps[-1]['stress']) array_data.set_array('stress', stress) except Exception, e: msg = ("Processing stress, " "with error Message:\n>> {}".format(e)) raise OutputParsingError(msg) try: nodes_list.append(('output_array', array_data)) except Exception, e: msg = ("Failed to create AiiDA data structures " "(ParameterData/ArrrayData) from parsed data, " "with error message:\n>> {}".format(e)) raise OutputParsingError(msg) parser_warnings = None return nodes_list, parser_warnings
def _parse_stdout(self, out_folder, new_nodes_list): fn = None fs = out_folder.get_folder_list() for f in fs: if f.endswith('.data'): fn = f if fn is None: raise OutputParsingError( "Calculation did not produce an output file. Please make sure that it run " "correctly") res_per_component = [] component_names = [] inp_params = self._calc.inp.parameters.get_dict() ncomponents = len(inp_params['Component']) for i in range(ncomponents): res_per_component.append({}) component_names.append(inp_params['Component'][i]['MoleculeName']) # self.logger.info("list of components: {}".format(component_names)) output_abs_path = out_folder.get_abs_path(fn) result_dict = {'exceeded_walltime': False} framework_density = re.compile("Framework Density:") num_of_molec = re.compile("Number of molecules:$") with open(output_abs_path, "r") as f: # 1st parsing part icomponent = 0 res_cmp = res_per_component[0] for line in f: # TODO maybe change for parse_line? if "WARNING" in line: self.logger.warning(line) if "Conversion factor molecules/unit cell -> mol/kg:" in line: res_cmp['conversion_factor_molec_uc_to_mol_kg'] = float( line.split()[6]) res_cmp[ 'conversion_factor_molec_uc_to_mol_kg_unit'] = "(mol/kg)/(molec/uc)" if "Conversion factor molecules/unit cell -> gr/gr:" in line: res_cmp['conversion_factor_molec_uc_to_gr_gr'] = float( line.split()[6]) res_cmp[ 'conversion_factor_molec_uc_to_gr_gr_unit'] = "(gr/gr)/(molec/uc)" if "Conversion factor molecules/unit cell -> cm^3 STP/gr:" in line: res_cmp['conversion_factor_molec_uc_to_cm3stp_gr'] = float( line.split()[7]) res_cmp[ 'conversion_factor_molec_uc_to_cm3stp_gr_unit'] = "(cm^3_STP/gr)/(molec/uc)" if "Conversion factor molecules/unit cell -> cm^3 STP/cm^3:" in line: res_cmp[ 'conversion_factor_molec_uc_to_cm3stp_cm3'] = float( line.split()[7]) res_cmp[ 'conversion_factor_molec_uc_to_cm3stp_cm3_unit'] = "(cm^3_STP/cm^3)/(molec/uc)" if "MolFraction:" in line: res_cmp['mol_fraction'] = float(line.split()[1]) res_cmp['mol_fraction_unit'] = "-" if "Partial pressure:" in line: res_cmp['partial_pressure'] = float(line.split()[2]) res_cmp['partial_pressure_unit'] = "Pa" if "Partial fugacity:" in line: res_cmp['partial_fugacity'] = float(line.split()[2]) res_cmp['partial_fugacity_unit'] = "Pa" icomponent += 1 if icomponent < ncomponents: res_cmp = res_per_component[icomponent] else: break # end of the 1st parsing part # 2nd parsing part for line in f: for parse in block1_list: if parse[0].match(line): parse_block1(f, result_dict, parse[1], *parse[2]) for i, cmpnt in enumerate(component_names): # I assume here that properties per component are present right in the next line. The order of # properties per molecule is the same as the order of molecules in the input file. So if component # name was not found in the next line, I break the loop immidiately as there is no reason to # continue it line = next(f) if cmpnt in line: parse_block1(f, res_per_component[i], parse[1], *parse[2]) else: break continue # no need to perform further checks, propperty has been found already for parse in energy_block_list: if parse[0].match(line): parse_block_energy(f, result_dict, prop=parse[1]) continue # no need to perform further checks, propperty has been found already if framework_density.match(line) is not None: result_dict['framework_density'] = line.split()[2] result_dict['framework_density_units'] = line.split( )[3].translate(None, '[](){}') elif num_of_molec.match(line) is not None: break # this stops the cycle # end of the 2nd parsing part # 3rd parsing part icomponent = 0 for line in f: # TODO: change for parse_line? if 'Average loading absolute [molecules/unit cell]' in line: res_per_component[icomponent][ 'loading_absolute_average'] = float(line.split()[5]) res_per_component[icomponent][ 'loading_absolute_dev'] = float(line.split()[7]) res_per_component[icomponent][ 'loading_absolute_units'] = 'molecules/unit cell' elif 'Average loading excess [molecules/unit cell]' in line: res_per_component[icomponent][ 'loading_excess_average'] = float(line.split()[5]) res_per_component[icomponent][ 'loading_excess_dev'] = float(line.split()[7]) res_per_component[icomponent][ 'loading_excess_units'] = 'molecules/unit cell' icomponent += 1 if icomponent >= ncomponents: break # end of the 3rd parsing part # 4th parsing part for line in f: for to_parse in lines_with_component_list: if to_parse[0].search(line): parse_lines_with_component(res_per_component, component_names, line, to_parse[1]) # end of the 4th parsing part pair = (self.get_linkname_outparams(), ParameterData(dict=result_dict)) new_nodes_list.append(pair) for i, item in enumerate(res_per_component): pair = ('component_' + str(i), ParameterData(dict=item)) new_nodes_list.append(pair)
def _parse_stdout(self, out_folder, new_nodes_list): fn = None fs = out_folder.get_folder_list() for f in fs: if f.endswith('.data'): fn = f if fn is None: raise OutputParsingError( "Calculation did not produce an output" " file. Please make sure that it run correctly") res_per_component = [] component_names = [] inp_params = self._calc.inp.parameters.get_dict() ncomponents = len(inp_params['Component']) for i in range(ncomponents): res_per_component.append({}) component_names.append(inp_params['Component'][i]['MoleculeName']) # self.logger.info("list of components: {}".format(component_names)) abs_fn = out_folder.get_abs_path(fn) with open(abs_fn, "r") as f: # Parse the "Adsorbate properties" section if ncomponents > 0: icomponent = 0 for line in f: if "MolFraction:" in line: res_per_component[icomponent]['mol_fraction'] = float( line.split()[1]) res_per_component[icomponent][ 'mol_fraction_unit'] = "-" if "Conversion factor molecules/unit cell -> mol/kg:" in line: res_per_component[icomponent][ 'conversion_factor_molec_uc_to_mol_kg'] = float( line.split()[6]) res_per_component[icomponent][ 'conversion_factor_molec_uc_to_mol_kg_unit'] = "(mol/kg)/(molec/uc)" if "Conversion factor molecules/unit cell -> gr/gr:" in line: res_per_component[icomponent][ 'conversion_factor_molec_uc_to_gr_gr'] = float( line.split()[6]) res_per_component[icomponent][ 'conversion_factor_molec_uc_to_gr_gr_unit'] = "(gr/gr)/(molec/uc)" if "Conversion factor molecules/unit cell -> cm^3 STP/gr:" in line: res_per_component[icomponent][ 'conversion_factor_molec_uc_to_cm3stp_gr'] = float( line.split()[7]) res_per_component[icomponent][ 'conversion_factor_molec_uc_to_cm3stp_gr_unit'] = "(cm^3_STP/gr)/(molec/uc)" if "Conversion factor molecules/unit cell -> cm^3 STP/cm^3:" in line: res_per_component[icomponent][ 'conversion_factor_molec_uc_to_cm3stp_cm3'] = float( line.split()[7]) res_per_component[icomponent][ 'conversion_factor_molec_uc_to_cm3stp_cm3_unit'] = "(cm^3_STP/cm^3)/(molec/uc)" if "Partial pressure:" in line: res_per_component[icomponent][ 'partial_pressure'] = float(line.split()[2]) res_per_component[icomponent][ 'partial_pressure_unit'] = "Pa" if "Partial fugacity:" in line: res_per_component[icomponent][ 'partial_fugacity'] = float(line.split()[2]) res_per_component[icomponent][ 'partial_fugacity_unit'] = "Pa" icomponent += 1 if icomponent == ncomponents: break # Jump to the "Results" section (if not present: exceeded_walltime=True) result_dict = {'exceeded_walltime': True} for line in f: if 'Finishing simulation' in line: result_dict['exceeded_walltime'] = False break # Parse the "System results" section for line in f: if 'Enthalpy of adsorption:' in line: for line in f: if 'Average' in line: result_dict[ 'enthalpy_of_adsorption_units'] = 'KJ/MOL' result_dict[ 'enthalpy_of_adsorption_average'] = float( line.split()[1]) * KELVIN_TO_KJ_PER_MOL result_dict['enthalpy_of_adsorption_dev'] = float( line.split()[3]) * KELVIN_TO_KJ_PER_MOL break break for line in f: if 'Average Adsorbate-Adsorbate energy:' in line: for line in f: if 'Average' in line: result_dict['ads_ads_total_energy_unit'] = 'KJ/MOL' result_dict['ads_ads_wdv_energy_unit'] = 'KJ/MOL' result_dict[ 'ads_ads_coulomb_energy_unit'] = 'KJ/MOL' result_dict[ 'ads_ads_total_energy_average'] = float( line.split()[1]) * KELVIN_TO_KJ_PER_MOL result_dict['ads_ads_wdv_energy_average'] = float( line.split()[5]) * KELVIN_TO_KJ_PER_MOL result_dict[ 'ads_ads_coulomb_energy_average'] = float( line.split()[7]) * KELVIN_TO_KJ_PER_MOL if '+/-' in line: result_dict['ads_ads_total_energy_dev'] = float( line.split()[1]) * KELVIN_TO_KJ_PER_MOL result_dict['ads_ads_wdv_energy_dev'] = float( line.split()[3]) * KELVIN_TO_KJ_PER_MOL result_dict['ads_ads_coulomb_energy_dev'] = float( line.split()[5]) * KELVIN_TO_KJ_PER_MOL break break for line in f: if 'Average Host-Adsorbate energy:' in line: for line in f: if 'Average' in line: result_dict[ 'host_ads_total_energy_unit'] = 'KJ/MOL' result_dict['host_ads_wdv_energy_unit'] = 'KJ/MOL' result_dict[ 'host_ads_coulomb_energy_unit'] = 'KJ/MOL' result_dict[ 'host_ads_total_energy_average'] = float( line.split()[1]) * KELVIN_TO_KJ_PER_MOL result_dict['host_ads_wdv_energy_average'] = float( line.split()[5]) * KELVIN_TO_KJ_PER_MOL result_dict[ 'host_ads_coulomb_energy_average'] = float( line.split()[7]) * KELVIN_TO_KJ_PER_MOL if '+/-' in line: result_dict['host_ads_total_energy_dev'] = float( line.split()[1]) * KELVIN_TO_KJ_PER_MOL result_dict['host_ads_wdv_energy_dev'] = float( line.split()[3]) * KELVIN_TO_KJ_PER_MOL result_dict['host_ads_coulomb_energy_dev'] = float( line.split()[5]) * KELVIN_TO_KJ_PER_MOL break break # Jump to the "Adsorbate results" section for line in f: if 'Number of molecules:' in line: break # Parse the "Adsorbate results" section if ncomponents > 0: icomponent = 0 for line in f: if 'Average loading absolute [molecules/unit cell]' in line: res_per_component[icomponent][ 'loading_absolute_average'] = float( line.split()[5]) res_per_component[icomponent][ 'loading_absolute_dev'] = float(line.split()[7]) res_per_component[icomponent][ 'loading_absolute_units'] = 'molec/uc' if 'Average loading excess [molecules/unit cell]' in line: res_per_component[icomponent][ 'loading_excess_average'] = float(line.split()[5]) res_per_component[icomponent][ 'loading_excess_dev'] = float(line.split()[7]) res_per_component[icomponent][ 'loading_excess_units'] = 'molec/uc' icomponent += 1 if icomponent == ncomponents: break for line in f: if 'Average Henry coefficient:' in line: for line in f: for icomponent in range(len(component_names)): if component_names[icomponent] in line: res_per_component[icomponent][ 'average_henry_coefficient_units'] = 'mol/kg/Pa' res_per_component[icomponent][ 'average_henry_coefficient'] = float( line.split()[4]) res_per_component[icomponent][ 'average_henry_coefficient_dev'] = float( line.split()[6]) if 'Average adsorption energy' in line: break break #End of the Raspa file pair = (self.get_linkname_outparams(), ParameterData(dict=result_dict)) new_nodes_list.append(pair) for i, item in enumerate(res_per_component): pair = ('component_' + str(i), ParameterData(dict=item)) new_nodes_list.append(pair)
def parse_mainout(abs_path, parser_class, init_struct=None, init_settings=None): """ parse the main output file and create the required output nodes :param abs_path: absolute path of stdout file :param parser_class: a string denoting the parser class :param init_struct: input structure :param init_settings: input structure settings :return psuccess: a boolean that is False in case of failed calculations :return output_nodes: containing "paramaters" and (optionally) "structure" and "settings" """ from aiida.orm import DataFactory psuccess = True param_data = {"parser_warnings": []} output_nodes = {} cryparse = CrystalOutputPlugin() if not os.path.exists(abs_path): raise OutputParsingError( "The raw data file does not exist: {}".format(abs_path)) with open(abs_path) as f: try: data = cryparse.read_file(f, log_warnings=False) except IOError as err: param_data["parser_warnings"].append( "Error in CRYSTAL 17 run output: {}".format(err)) output_nodes["parameters"] = DataFactory("parameter")( dict=param_data) return False, output_nodes # data contains the top-level keys: # "warnings" (list), "errors" (list), "meta" (dict), "creator" (dict), # "initial" (None or dict), "optimisation" (None or dict), "final" (dict) # "mulliken" (optional dict) # TODO could also read .gui file for definitive final (primitive) geometry, with symmetries # TODO could also read .SCFLOG, to get scf output for each opt step # TODO could also read files in .optstory folder, to get (primitive) geometries (+ symmetries) for each opt step # Note the above files are only available for optimisation runs perrors = data["errors"] pwarnings = data["warnings"] if perrors: psuccess = False param_data["errors"] = perrors # aiida-quantumespresso only has warnings, so we group errors and warnings for compatibility param_data["warnings"] = perrors + pwarnings # get meta data meta_data = data.pop("meta") if "elapsed_time" in meta_data: h, m, s = meta_data["elapsed_time"].split(':') param_data["wall_time_seconds"] = int(h) * 3600 + int(m) * 60 + int(s) # get initial data initial_data = data.pop("initial") initial_data = {} if not initial_data else initial_data for name, val in initial_data.get("calculation", {}).items(): param_data["calculation_{}".format(name)] = val init_scf_data = initial_data.get("scf", []) param_data["scf_iterations"] = len(init_scf_data) # TODO create TrajectoryData from init_scf_data data # optimisation trajectory data opt_data = data.pop("optimisation") if opt_data: param_data["opt_iterations"] = len( opt_data) + 1 # the first optimisation step is the initial scf # TODO create TrajectoryData from optimisation data final_data = data.pop("final") # TODO read separate energy contributions energy = final_data["energy"]["total_corrected"] param_data["energy"] = energy["magnitude"] param_data["energy_units"] = energy["units"] # TODO read from .gui file and check consistency of final cell/symmops structure = _extract_structure(final_data["primitive_cell"], init_struct, param_data) if opt_data or not init_struct: output_nodes["structure"] = structure ssuccess = _extract_symmetry(final_data, init_settings, output_nodes, param_data) psuccess = False if not ssuccess else psuccess _extract_mulliken(data, param_data) # add the version and class of parser param_data["parser_version"] = str(pkg_version) param_data["parser_class"] = str(parser_class) param_data["ejplugins_version"] = str(ejplugins.__version__) output_nodes["parameters"] = DataFactory("parameter")(dict=param_data) # if array_dict: # arraydata = DataFactory("array")() # for name, array in array_dict.items(): # arraydata.set_array(name, np.array(array)) # else: # arraydata = None return psuccess, output_nodes
class Default_vasprun_parserInstruction(BaseInstruction): _input_file_list_ = ['vasprun.xml'] def _parser_function(self): """ Parses the vasprun.xml using the Pymatgen Vasprun function. """ vasp_param = {} # ParameterData vasp_array = {} # ArrayData parser_warnings = {} # return non-critical errors # parameter data keys _vasprun_keys = [ # directly accessible, by name # logical 'converged', 'converged_electronic', 'converged_ionic', 'dos_has_errors', 'is_spin', 'is_hubbard', # value 'efermi' ] _vasprun_special_keys = [ # can't be accessed directly # logical 'is_band_gap_direct', # value 'no_ionic_steps', 'final_energy', # returned as FloatWithUnit 'energy_units', 'free_energy', 'energy_wo_entropy', 'energy_T0', 'entropy_TS', 'no_electronic_steps', 'total_no_electronic_steps', 'band_gap', 'cbm', 'vbm', ] # array data keys # TODO # list --> array; see what exactly ArrayData supports # parsing output files try: vspr = vasp.Vasprun(self._out_folder.get_abs_path('vasprun.xml')) except Exception, e: msg = ("Parsing vasprun file in pymatgen failed, " "with error message:\n>> {}".format(e)) raise OutputParsingError(msg) # extract data try: for k in _vasprun_keys: vasp_param[k] = getattr(vspr, k) # acessing special keys manually band_gap, cbm, vbm, is_direct = tuple( vspr.eigenvalue_band_properties) vasp_param['band_gap'] = band_gap vasp_param['cbm'] = cbm vasp_param['vbm'] = vbm vasp_param['is_band_gap_direct'] = is_direct vasp_param['no_ionic_steps'] = len(vspr.ionic_steps) last_ionic = vspr.ionic_steps[-1] vasp_param['free_energy'] = last_ionic['e_fr_energy'] vasp_param['energy_wo_entropy'] = last_ionic[ 'e_wo_entrp'] # CHECK: looks like a bug in pymatgen !!! vasp_param['energy_T0'] = last_ionic['e_0_energy'] vasp_param['entropy_TS'] = (last_ionic['e_fr_energy'] - last_ionic['e_wo_entrp']) vasp_param['no_electronic_steps'] = len( last_ionic['electronic_steps']) vasp_param['total_no_electronic_steps'] = 0 for step in vspr.ionic_steps: vasp_param['total_no_electronic_steps'] += len( step['electronic_steps']) final_en = vspr.final_energy vasp_param['final_energy'] = final_en.real vasp_param['energy_units'] = str(final_en.unit) except Exception, e: msg = ("Processing of extracted data failed, " "with error message:\n>> {}".format(e)) raise OutputParsingError(msg)