Ejemplo n.º 1
0
    def _get_output_nodes(self, output_path, bands_path):
        """
        Extracts output nodes from the standard output and standard error
        files. (And XML and JSON files)
        """
        from aiida.orm.data.array.trajectory import TrajectoryData
        import re

        result_list = []

        # Add errors
        successful = True
        if output_path is None:
            errors_list = ['WARNING: No aiida.out file...']
        else:
            successful, errors_list = self.get_errors_from_file(output_path)

        result_dict = {}
        result_dict["errors"] = errors_list

        # Add warnings
        warnings_list = self.get_warnings_from_file(output_path)
        result_dict["warnings"] = warnings_list

        # Add outuput data
        output_dict = self.get_output_from_file(output_path)
        result_dict.update(output_dict)

        # Add parser info dictionary
        parser_info = {}
        parser_version = 'aiida-0.11.0--plugin-0.11.5'
        parser_info['parser_info'] =\
            'AiiDA Vibra Parser V. {}'.format(parser_version)
        parser_info['parser_warnings'] = []
        parsed_dict = dict(result_dict.items() + parser_info.items())

        output_data = ParameterData(dict=parsed_dict)
        
        link_name = self.get_linkname_outparams()
        result_list.append((link_name,output_data))

        # Parse band-structure information if available
        if bands_path is not None:
             bands, coords = self.get_bands(bands_path)
             from aiida.orm.data.array.bands import BandsData
             arraybands = BandsData()
             arraybands.set_kpoints(self._calc.inp.bandskpoints.get_kpoints(cartesian=True))
             arraybands.set_bands(bands,units="eV")
             result_list.append((self.get_linkname_bandsarray(), arraybands))
             bandsparameters = ParameterData(dict={"kp_coordinates": coords})
             result_list.append((self.get_linkname_bandsparameters(), bandsparameters))

        return successful, result_list
Ejemplo n.º 2
0
    def _get_output_nodes(self, output_path, messages_path, xml_path,
                          json_path, bands_path):
        """
        Extracts output nodes from the standard output and standard error
        files. (And XML and JSON files)
        """
        from aiida.orm.data.array.trajectory import TrajectoryData
        import re

        parser_version = 'aiida-0.11.0--plugin-0.11.5'
        parser_info = {}
        parser_info['parser_info'] = 'AiiDA Siesta Parser V. {}'.format(
            parser_version)
        parser_info['parser_warnings'] = []

        result_list = []

        if xml_path is None:
            self.logger.error("Could not find a CML file to parse")
            # NOTE aiida.xml is not there?
            raise SiestaOutputParsingError(
                "Could not find a CML file to parse")

        # We get everything from the CML file

        xmldoc = get_parsed_xml_doc(xml_path)
        if xmldoc is None:
            self.logger.error("Malformed CML file: cannot parse")
            raise SiestaCMLParsingError("Malformed CML file: cannot parse")

        # These are examples of how we can access input items
        #
        # Structure (mandatory)
        #
        in_struc = self._calc.get_inputs_dict()['structure']
        #
        # Settings (optional)
        #
        try:
            in_settings = self._calc.get_inputs_dict()['settings']
        except KeyError:
            in_settings = None

        result_dict = get_dict_from_xml_doc(xmldoc)

        # Add timing information

        if json_path is None:
            self.logger.info("Could not find a time.json file to parse")
        else:
            from json_time import get_timing_info
            global_time, timing_decomp = get_timing_info(json_path)
            if global_time is None:
                self.logger.info("Cannot fully parse the time.json file")
            else:
                result_dict["global_time"] = global_time
                result_dict["timing_decomposition"] = timing_decomp

        # Add warnings
        successful = True
        if messages_path is None:
            # Perhaps using an old version of Siesta
            warnings_list = ['WARNING: No MESSAGES file...']
        else:
            successful, warnings_list = self.get_warnings_from_file(
                messages_path)

        result_dict["warnings"] = warnings_list

        # Add parser info dictionary
        parsed_dict = dict(result_dict.items() + parser_info.items())

        output_data = ParameterData(dict=parsed_dict)

        link_name = self.get_linkname_outparams()
        result_list.append((link_name, output_data))

        # If the structure has changed, save it
        if is_variable_geometry(xmldoc):
            # Get the input structure to copy its site names,
            # as the CML file traditionally contained only the
            # atomic symbols.
            #
            struc = get_last_structure(xmldoc, in_struc)
            result_list.append((self.get_linkname_outstructure(), struc))

        # Save forces and stress in an ArrayData object
        forces, stress = get_final_forces_and_stress(xmldoc)

        if forces is not None and stress is not None:
            from aiida.orm.data.array import ArrayData
            arraydata = ArrayData()
            arraydata.set_array('forces', np.array(forces))
            arraydata.set_array('stress', np.array(stress))
            result_list.append((self.get_linkname_outarray(), arraydata))

        # Parse band-structure information if available
        if bands_path is not None:
            bands, coords = self.get_bands(bands_path)
            from aiida.orm.data.array.bands import BandsData
            arraybands = BandsData()
            arraybands.set_kpoints(
                self._calc.inp.bandskpoints.get_kpoints(cartesian=True))
            arraybands.set_bands(bands, units="eV")
            result_list.append((self.get_linkname_bandsarray(), arraybands))
            bandsparameters = ParameterData(dict={"kp_coordinates": coords})
            result_list.append(
                (self.get_linkname_bandsparameters(), bandsparameters))

        return successful, result_list
Ejemplo n.º 3
0
 def _aiida_bands_data(self, data, cell, kpoints_dict):
     if not data:
         return False
     kpt_idx = sorted(data.keys())  #  list of kpoint indices
     try:
         k_list = [kpoints_dict[i]
                   for i in kpt_idx]  # list of k-point triplet
     except KeyError:
         # kpoint triplets are not present (true  for .qp and so on, can not use BandsData)
         # We use the internal Yambo Format  [ [Eo_1, Eo_2,... ], ...[So_1,So_2,] ]
         #                                  QP_TABLE  [[ib_1,ik_1,isp_1]      ,[ib_n,ik_n,isp_n]]
         # Each entry in DATA has corresponding legend in QP_TABLE that defines its details
         # like   ib= Band index,  ik= kpoint index,  isp= spin polarization index.
         #  Eo_1 =>  at ib_1, ik_1 isp_1.
         pdata = ArrayData()
         QP_TABLE = []
         ORD = []
         Eo = []
         E_minus_Eo = []
         So = []
         Z = []
         for ky in data.keys():  # kp == kpoint index as a string  1,2,..
             for ind in range(len(data[ky]['Band'])):
                 try:
                     Eo.append(data[ky]['Eo'][ind])
                 except KeyError:
                     pass
                 try:
                     E_minus_Eo.append(data[ky]['E-Eo'][ind])
                 except KeyError:
                     pass
                 try:
                     So.append(data[ky]['Sc|Eo'][ind])
                 except KeyError:
                     pass
                 try:
                     Z.append(data[ky]['Z'][ind])
                 except KeyError:
                     pass
                 ik = int(ky)
                 ib = data[ky]['Band'][ind]
                 isp = 0
                 if 'Spin_Pol' in data[ky].keys():
                     isp = data[ky]['Spin_Pol'][ind]
                 QP_TABLE.append([ik, ib, isp])
         pdata.set_array('Eo', numpy.array(Eo))
         pdata.set_array('E_minus_Eo', numpy.array(E_minus_Eo))
         pdata.set_array('So', numpy.array(So))
         pdata.set_array('Z', numpy.array(Z))
         pdata.set_array('qp_table', numpy.array(QP_TABLE))
         return pdata
     quasiparticle_bands = BandsData()
     quasiparticle_bands.set_cell(cell)
     quasiparticle_bands.set_kpoints(k_list, cartesian=True)
     # labels will come from any of the keys in the nested  kp_point data,
     # there is a uniform set of observables for each k-point, ie Band, Eo, ...
     # ***FIXME BUG does not seem to handle spin polarizes at all when constructing bandsdata***
     bands_labels = [
         legend for legend in sorted(data[data.keys()[0]].keys())
     ]
     append_list = [[] for i in bands_labels]
     for kp in kpt_idx:
         for i in range(len(bands_labels)):
             append_list[i].append(data[kp][bands_labels[i]])
     generalised_bands = [numpy.array(it) for it in append_list]
     quasiparticle_bands.set_bands(bands=generalised_bands,
                                   units='eV',
                                   labels=bands_labels)
     return quasiparticle_bands
Ejemplo n.º 4
0
def spin_dependent_subparcer(out_info_dict):
    """
    This find the projection and bands arrays from the out_file and
    out_info_dict. Used to handle the different possible spin-cases in
    a convenient manner.

    :param out_info_dict: contains various technical internals useful in parsing
    :return: ProjectionData, BandsData parsed from out_file
    """

    out_file = out_info_dict["out_file"]
    spin_down = out_info_dict["spin_down"]
    od = out_info_dict #using a shorter name for convenience
    #   regular expressions needed for later parsing
    WaveFraction1_re = re.compile(r"\=(.*?)\*")  # state composition 1
    WaveFractionremain_re = re.compile(r"\+(.*?)\*")  # state comp 2
    FunctionId_re = re.compile(r"\#(.*?)\]")  # state identity
    # primes arrays for the later parsing
    num_wfc = len(od["wfc_lines"])
    bands = np.zeros([od["k_states"], od["num_bands"]])
    projection_arrays = np.zeros([od["k_states"], od["num_bands"], num_wfc])

    try:
        for i in range(od["k_states"]):
            if spin_down:
                i += od["k_states"]
            # grabs band energy
            for j in range (i*od["num_bands"],(i+1)*od["num_bands"],1):
                out_ind = od["e_lines"][j]
                val = out_file[out_ind].split()[4]
                bands[i%od["k_states"]][j%od["num_bands"]] = val
                #subloop grabs pdos
                wave_fraction = []
                wave_id = []
                for k in range(od["e_lines"][j]+1,od["psi_lines"][j],1):
                    out_line = out_file[k]
                    wave_fraction += WaveFraction1_re.findall(out_line)
                    wave_fraction += WaveFractionremain_re.findall(out_line)
                    wave_id += FunctionId_re.findall(out_line)
                if len(wave_id) != len(wave_fraction):
                    raise IndexError
                for l in range (len(wave_id)):
                    wave_id[l] = int(wave_id[l])
                    wave_fraction[l] = float(wave_fraction[l])
                    #sets relevant values in pdos_array
                    projection_arrays[i%od["k_states"]][
                        j%od["num_bands"]][wave_id[l]-1] = wave_fraction[l]
    except IndexError:
        raise QEOutputParsingError("the standard out file does not "
                                   "comply with the official "
                                   "documentation.")

    bands_data = BandsData()
    try:
    # Attempts to retrive the kpoints from the parent calc
        parent_calc = out_info_dict["parent_calc"]
        parent_kpoints = parent_calc.get_inputs_dict()['kpoints']
        if len(od['k_vect']) != len(parent_kpoints.get_kpoints()):
            raise AttributeError
        bands_data.set_kpointsdata(parent_kpoints)
    except AttributeError:
        bands_data.set_kpoints(od['k_vect'].astype(float))

    bands_data.set_bands(bands, units='eV')

    orbitals = out_info_dict["orbitals"]
    if len(orbitals) != np.shape(projection_arrays[0,0,:])[0]:
        raise QEOutputParsingError("There was an internal parsing error, "
                                   " the projection array shape does not agree"
                                   " with the number of orbitals")
    projection_data = ProjectionData()
    projection_data.set_reference_bandsdata(bands_data)
    projections = [projection_arrays[:,:,i] for i in range(len(orbitals))]

    # Do the bands_check manually here
    for projection in projections:
        if np.shape(projection) !=  np.shape(bands):
            raise AttributeError("Projections not the same shape as the bands")


    #insert here some logic to assign pdos to the orbitals
    pdos_arrays = spin_dependent_pdos_subparcer(out_info_dict)
    energy_arrays = [out_info_dict["energy"]]*len(orbitals)
    projection_data.set_projectiondata(orbitals,
                                       list_of_projections=projections,
                                       list_of_energy=energy_arrays,
                                       list_of_pdos=pdos_arrays,
                                       bands_check=False)
    # pdos=pdos_arrays
    return bands_data,  projection_data