コード例 #1
0
ファイル: test_data.py プロジェクト: chrisjsewell/aiida_core
class TestVerdiDataArray(AiidaTestCase):
    """
    Testing verdi data array
    """
    @classmethod
    def setUpClass(cls):
        super(TestVerdiDataArray, cls).setUpClass()

    def setUp(self):
        self.a = ArrayData()
        self.a.set_array('test_array', np.array([0, 1, 3]))
        self.a.store()

        self.cli_runner = CliRunner()

    def test_arrayshowhelp(self):
        output = sp.check_output(['verdi', 'data', 'array', 'show', '--help'])
        self.assertIn('Usage:', output,
                      "Sub-command verdi data array show --help failed.")

    def test_arrayshow(self):
        # with captured_output() as (out, err):
        options = [str(self.a.id)]
        res = self.cli_runner.invoke(cmd_array.show,
                                     options,
                                     catch_exceptions=False)
        self.assertEquals(res.exit_code, 0, "The command did not finish "
                          "correctly")
コード例 #2
0
ファイル: gollum.py プロジェクト: garsua/aiida-gollu2
    def get_transport_data(self, nd_path):
        """
        Parses the open channels and transmission
        files to get ArrayData objects that can
        be stored in the database
        """

        import numpy as np
        from aiida.orm.data.array import ArrayData

        f = open(nd_path)
        lines = f.readlines()

        x = []
        y = []
        for line in lines:
            try:
                c1 = float(line.split()[0])
                x.append(c1)
                c2 = float(line.split()[1])
                y.append(c2)
            except:
                pass

        X = np.array(x, dtype=float)
        Y = np.array(y, dtype=float)

        arraydata = ArrayData()
        arraydata.set_array('X', X)
        arraydata.set_array('Y', Y)

        return arraydata
コード例 #3
0
    def parse_with_retrieved(self, retrieved):
        """
        Parses the datafolder, stores results.
        """

        # suppose at the start that the job is successful
        successful = True

        # select the folder object
        # Check that the retrieved folder is there
        try:
            out_folder = retrieved[self._calc._get_linkname_retrieved()]
        except KeyError:
            self.logger.error("No retrieved folder found")
            return False, ()

        # check what is inside the folder
        list_of_files = out_folder.get_folder_list()

        # OUTPUT file should exist
        if not self._calc._OUTPUT_FILE_NAME in list_of_files:
            successful = False
            self.logger.error("Output file not found")
            return successful, ()

        # Get file and do the parsing
        outfile = out_folder.get_abs_path(self._calc._OUTPUT_FILE_NAME)

        force_constants = parse_FORCE_CONSTANTS(outfile)

        # look at warnings
        warnings = []
        with open(out_folder.get_abs_path(self._calc._SCHED_ERROR_FILE)) as f:
            errors = f.read()
        if errors:
            warnings = [errors]

        # ====================== prepare the output node ======================

        # save the outputs
        new_nodes_list = []

        # save force constants into node
        try:
            array_data = ArrayData()
            array_data.set_array('force_constants', force_constants)

            new_nodes_list.append(('array_data', array_data))
        except KeyError:  # keys not found in json
            pass

        # add the dictionary with warnings
        new_nodes_list.append((self.get_linkname_outparams(),
                               ParameterData(dict={'warnings': warnings})))

        return successful, new_nodes_list
コード例 #4
0
def parse_kappa(filename):
    import numpy as np
    import h5py
    from aiida.orm.data.array import ArrayData

    kappa = ArrayData()

    f = h5py.File(filename, 'r')
    for item in f:
        array = np.array(f[item])
        kappa.set_array(item, array)
    f.close()

    return kappa
コード例 #5
0
    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)
コード例 #6
0
def create_supercells_with_displacements_using_phonopy(structure,
                                                       phonopy_input):
    """
    Create the supercells with the displacements to use the finite displacements methodology to calculate the
    force constants
    :param structure: Aiida StructureData Object
    :param phonopy_input: Aiida Parametersdata object containing a dictionary with the data needed to run phonopy:
            supercells matrix, primitive matrix and displacement distance.
    :return: dictionary of Aiida StructureData Objects containing the cells with displacements
    """
    from phonopy.structure.atoms import Atoms as PhonopyAtoms
    from phonopy import Phonopy
    import numpy as np

    # Generate phonopy phonon object
    bulk = PhonopyAtoms(symbols=[site.kind_name for site in structure.sites],
                        positions=[site.position for site in structure.sites],
                        cell=structure.cell)

    phonopy_input = phonopy_input.get_dict()
    phonon = Phonopy(bulk,
                     phonopy_input['supercell'],
                     primitive_matrix=phonopy_input['primitive'])

    phonon.generate_displacements(distance=phonopy_input['distance'])

    cells_with_disp = phonon.get_supercells_with_displacements()

    # Transform cells to StructureData and set them ready to return
    data_sets = phonon.get_displacement_dataset()
    data_sets_object = ArrayData()
    for i, first_atoms in enumerate(data_sets['first_atoms']):
        data_sets_array = np.array([
            first_atoms['direction'], first_atoms['number'],
            first_atoms['displacement']
        ])
        data_sets_object.set_array('data_sets_{}'.format(i), data_sets_array)

    disp_cells = {'data_sets': data_sets_object}
    for i, phonopy_supercell in enumerate(cells_with_disp):
        supercell = StructureData(cell=phonopy_supercell.get_cell())
        for symbol, position in zip(phonopy_supercell.get_chemical_symbols(),
                                    phonopy_supercell.get_positions()):
            supercell.append_atom(position=position, symbols=symbol)
        disp_cells["structure_{}".format(i)] = supercell

    return disp_cells
コード例 #7
0
def get_force_constants_from_phonopy(**kwargs):
    """
    Calculate the force constants using phonopy
    :param kwargs:
    :return:
    """

    from phonopy.structure.atoms import Atoms as PhonopyAtoms
    from phonopy import Phonopy
    import numpy as np
    # print 'function',kwargs

    structure = kwargs.pop('structure')
    phonopy_input = kwargs.pop('phonopy_input').get_dict()

    # Generate phonopy phonon object
    bulk = PhonopyAtoms(symbols=[site.kind_name for site in structure.sites],
                        positions=[site.position for site in structure.sites],
                        cell=structure.cell)

    phonon = Phonopy(bulk,
                     phonopy_input['supercell'],
                     primitive_matrix=phonopy_input['primitive'],
                     distance=phonopy_input['distance'])

    phonon.generate_displacements(distance=phonopy_input['distance'])

    # Build data_sets from forces of supercells with displacments

    data_sets = phonon.get_displacement_dataset()
    for i, first_atoms in enumerate(data_sets['first_atoms']):
        forces = kwargs.pop('forces_{}'.format(i)).get_array('forces')[0]
        first_atoms['forces'] = np.array(forces, dtype='double', order='c')

    # LOCAL calculation

    # Calculate and get force constants
    phonon.set_displacement_dataset(data_sets)
    phonon.produce_force_constants()

    force_constants = phonon.get_force_constants()

    array_data = ArrayData()
    array_data.set_array('force_constants', force_constants)

    return {'array_data': array_data}
コード例 #8
0
def create_forces_set(**kwargs):
    # Build data_sets from forces of supercells with displacments

    import numpy as np

    data_set = kwargs.pop('data_sets')

    force_sets = ArrayData()
    for i in data_set.get_arraynames():
        force_array = kwargs.pop(i.replace('data_sets',
                                           'forces')).get_array('forces')[0]
        data_set_array = np.array([
            data_set.get_array(i)[0],
            data_set.get_array(i)[1],
            data_set.get_array(i)[2], force_array
        ])
        force_sets.set_array(i, data_set_array)

    return {'force_sets': force_sets}
コード例 #9
0
 def _aiida_ndb_hf(self, data):
     """
     Save the data from ndb.HF_and_locXC  
     """
     pdata = ArrayData()
     pdata.set_array('Sx', numpy.array(data['Sx']))
     pdata.set_array('Vxc', numpy.array(data['Vxc']))
     return pdata
コード例 #10
0
def parse_thermal_properties(filename):
    import yaml
    temperature = []
    free_energy = []
    entropy = []
    cv = []

    with open(filename, 'r') as stream:
        thermal_properties = dict(yaml.load(stream))
        for tp in thermal_properties['thermal_properties']:
            temperature.append(tp['temperature'])
            entropy.append(tp['entropy'])
            free_energy.append(tp['free_energy'])
            cv.append(tp['heat_capacity'])

    tp_object = ArrayData()
    tp_object.set_array('temperature', np.array(temperature))
    tp_object.set_array('free_energy', np.array(free_energy))
    tp_object.set_array('entropy', np.array(entropy))
    tp_object.set_array('heat_capacity', np.array(cv))

    return tp_object
コード例 #11
0
ファイル: neb.py プロジェクト: asle85/aiida-core
    def parse_with_retrieved(self, retrieved):
        """
        Parses the calculation-output datafolder, and stores
        results.

        :param retrieved: a dictionary of retrieved nodes, where the keys
            are the link names of retrieved nodes, and the values are the
            nodes.
        """
        from aiida.common.exceptions import InvalidOperation
        from aiida.orm.data.array.trajectory import TrajectoryData
        from aiida.orm.data.array import ArrayData
        import os
        import numpy
        import copy

        successful = True

        # check if I'm not to overwrite anything
        #state = self._calc.get_state()
        #if state != calc_states.PARSING:
        #    raise InvalidOperation("Calculation not in {} state"
        #                           .format(calc_states.PARSING) )

        # look for eventual flags of the parser
        try:
            parser_opts = self._calc.inp.settings.get_dict()[
                self.get_parser_settings_key()]
        except (AttributeError, KeyError):
            parser_opts = {}

        # load the pw input dictionary
        pw_input_dict = self._calc.inp.pw_parameters.get_dict()

        # load the pw input dictionary
        neb_input_dict = self._calc.inp.neb_parameters.get_dict()

        # Check that the retrieved folder is there
        try:
            out_folder = retrieved[self._calc._get_linkname_retrieved()]
        except KeyError:
            self.logger.error("No retrieved folder found")
            successful = False
            return successful, ()

        # check what is inside the folder
        list_of_files = out_folder.get_folder_list()
        # at least the stdout should exist
        if not self._calc._OUTPUT_FILE_NAME in list_of_files:
            self.logger.error("Standard output not found")
            successful = False
            return successful, ()

        out_file = os.path.join(out_folder.get_abs_path('.'),
                                self._calc._OUTPUT_FILE_NAME)

        # First parse the Neb output
        neb_out_dict, iteration_data, raw_successful = parse_raw_output_neb(
            out_file, neb_input_dict)

        # if calculation was not considered failed already, use the new value
        successful = raw_successful if successful else successful

        # Retrieve the number of images
        try:
            num_images = neb_input_dict['num_of_images']
        except KeyError:
            try:
                num_images = neb_out_dict['num_of_images']
            except KeyError:
                self.logger.error(
                    "Impossible to understand the number of images")
                successful = False
                return successful, ()

        # Now parse the information from the single pw calculations for the different images
        image_data = {}
        positions = []
        cells = []
        for i in range(num_images):
            # look for xml and parse
            xml_file = os.path.join(out_folder.get_abs_path('.'),
                                    self._calc._PREFIX + '_{}'.format(i + 1),
                                    self._calc._PREFIX + '.save',
                                    self._calc._DATAFILE_XML_BASENAME)
            try:
                with open(xml_file, 'r') as f:
                    xml_lines = f.read()  # Note: read() and not readlines()
            except IOError:
                self.logger.error(
                    "No xml file found for image {} at {}".format(
                        i + 1, xml_file))
                successful = False
                return successful, ()
            xml_data, structure_dict, bands_data = parse_pw_xml_output(
                xml_lines)

            # convert the dictionary obtained from parsing the xml to an AiiDA StructureData
            structure_data = convert_qe2aiida_structure(structure_dict)

            # look for pw output and parse it
            pw_out_file = os.path.join(
                out_folder.get_abs_path('.'),
                self._calc._PREFIX + '_{}'.format(i + 1), 'PW.out')
            try:
                with open(pw_out_file, 'r') as f:
                    pw_out_lines = f.read()  # Note: read() and not readlines()
            except IOError:
                self.logger.error(
                    "No pw output file found for image {}".format(i + 1))
                successful = False
                return successful, ()

            pw_out_data, trajectory_data, critical_messages = parse_pw_text_output(
                pw_out_lines, xml_data, structure_dict, pw_input_dict)

            # I add in the out_data all the last elements of trajectory_data values.
            # Safe for some large arrays, that I will likely never query.
            skip_keys = [
                'forces', 'atomic_magnetic_moments', 'atomic_charges',
                'lattice_vectors_relax', 'atomic_positions_relax',
                'atomic_species_name'
            ]
            tmp_trajectory_data = copy.copy(trajectory_data)
            for x in tmp_trajectory_data.iteritems():
                if x[0] in skip_keys:
                    continue
                pw_out_data[x[0]] = x[1][-1]
                if len(x[1]) == 1:  # delete eventual keys that are not arrays
                    trajectory_data.pop(x[0])
            # As the k points are an array that is rather large, and again it's not something I'm going to parse likely
            # since it's an info mainly contained in the input file, I move it to the trajectory data
            for key in ['k_points', 'k_points_weights']:
                try:
                    trajectory_data[key] = xml_data.pop(key)
                except KeyError:
                    pass

            key = 'pw_output_image_{}'.format(i + 1)
            image_data[key] = dict(pw_out_data.items() + xml_data.items())

            positions.append([site.position for site in structure_data.sites])
            cells.append(structure_data.cell)

            # If a warning was already present in the NEB, add also PW warnings to the neb output data,
            # avoiding repetitions.
            if neb_out_dict['warnings']:
                for warning in pw_out_data['warnings']:
                    if warning not in neb_out_dict['warnings']:
                        neb_out_dict['warnings'].append(warning)

        # Symbols can be obtained simply from the last image
        symbols = [str(site.kind_name) for site in structure_data.sites]

        new_nodes_list = []

        # convert the dictionary into an AiiDA object
        output_params = ParameterData(dict=dict(neb_out_dict.items() +
                                                image_data.items()))

        # return it to the execmanager
        new_nodes_list.append((self.get_linkname_outparams(), output_params))

        # convert data on structure of images into a TrajectoryData
        traj = TrajectoryData()
        traj.set_trajectory(
            stepids=numpy.arange(1, num_images + 1),
            cells=numpy.array(cells),
            symbols=numpy.array(symbols),
            positions=numpy.array(positions),
        )

        # return it to the execmanager
        new_nodes_list.append((self.get_linkname_outtrajectory(), traj))

        if parser_opts.get('all_iterations', False):
            if iteration_data:
                from aiida.orm.data.array import ArrayData

                arraydata = ArrayData()
                for x in iteration_data.iteritems():
                    arraydata.set_array(x[0], numpy.array(x[1]))
                new_nodes_list.append(
                    (self.get_linkname_iterationarray(), arraydata))

        # Load the original and interpolated energy profile along the minimum-energy path (mep)
        try:
            mep_file = os.path.join(out_folder.get_abs_path('.'),
                                    self._calc._PREFIX + '.dat')
            mep = numpy.loadtxt(mep_file)
        except Exception:
            self.logger.warning(
                "Impossible to find the file with image energies "
                "versus reaction coordinate.")
            mep = numpy.array([[]])

        try:
            interp_mep_file = os.path.join(out_folder.get_abs_path('.'),
                                           self._calc._PREFIX + '.int')
            interp_mep = numpy.loadtxt(interp_mep_file)
        except Exception:
            self.logger.warning(
                "Impossible to find the file with the interpolation "
                "of image energies versus reaction coordinate.")
            interp_mep = numpy.array([[]])
        # Create an ArrayData with the energy profiles
        mep_arraydata = ArrayData()
        mep_arraydata.set_array('mep', mep)
        mep_arraydata.set_array('interpolated_mep', interp_mep)
        new_nodes_list.append((self.get_linkname_meparray(), mep_arraydata))

        return successful, new_nodes_list
コード例 #12
0
    def parse_with_retrieved(self, retrieved):
        """
        Parses the datafolder, stores results.
        """

        # suppose at the start that the job is successful
        successful = True

        # select the folder object
        # Check that the retrieved folder is there
        try:
            out_folder = retrieved[self._calc._get_linkname_retrieved()]
        except KeyError:
            self.logger.error("No retrieved folder found")
            return False, ()

        # check what is inside the folder
        list_of_files = out_folder.get_folder_list()

        # OUTPUT file should exist
        if not self._calc._OUTPUT_FILE_NAME in list_of_files:
            successful = False
            self.logger.error("Output file not found")
            return successful, ()

        # Get file and do the parsing
        outfile = out_folder.get_abs_path(self._calc._OUTPUT_FILE_NAME)
        ouput_trajectory = out_folder.get_abs_path(
            self._calc._OUTPUT_TRAJECTORY_FILE_NAME)

        output_data, cell, stress_tensor = read_log_file(outfile)
        positions, forces, symbols, cell2 = read_lammps_positions_and_forces(
            ouput_trajectory)

        # look at warnings
        warnings = []
        with open(out_folder.get_abs_path(self._calc._SCHED_ERROR_FILE)) as f:
            errors = f.read()
        if errors:
            warnings = [errors]

        # ====================== prepare the output node ======================

        # save the outputs
        new_nodes_list = []

        # save optimized structure into node
        structure = StructureData(cell=cell)

        for i, position in enumerate(positions[-1]):
            structure.append_atom(position=position.tolist(),
                                  symbols=symbols[i])

        new_nodes_list.append(('output_structure', structure))

        # save forces into node
        array_data = ArrayData()
        array_data.set_array('forces', forces)
        array_data.set_array('stress', stress_tensor)

        new_nodes_list.append(('output_array', array_data))

        # add the dictionary with warnings
        output_data.update({'warnings': warnings})

        parameters_data = ParameterData(dict=output_data)
        new_nodes_list.append((self.get_linkname_outparams(), parameters_data))

        # add the dictionary with warnings
        # new_nodes_list.append((self.get_linkname_outparams(), ParameterData(dict={'warnings': warnings})))

        return successful, new_nodes_list
コード例 #13
0
ファイル: pw.py プロジェクト: unkcpz/aiida-quantumespresso
    def parse_with_retrieved(self, retrieved):
        """
        Parse the output nodes for a PwCalculations from a dictionary of retrieved nodes.
        Two nodes that are expected are the default 'retrieved' FolderData node which will
        store the retrieved files permanently in the repository. The second required node
        is the unstored FolderData node with the temporary retrieved files, which should
        be passed under the key 'retrieved_temporary_folder_key' of the Parser class.

        :param retrieved: a dictionary of retrieved nodes
        """
        import os

        successful = True

        # Load the input dictionary
        parameters = self._calc.inp.parameters.get_dict()

        # Look for optional settings input node and potential 'parser_options' dictionary within it
        try:
            settings = self._calc.inp.settings.get_dict()
            parser_opts = settings[self.get_parser_settings_key()]
        except (AttributeError, KeyError):
            settings = {}
            parser_opts = {}

        # Check that the retrieved folder is there
        try:
            out_folder = retrieved[self._calc._get_linkname_retrieved()]
        except KeyError:
            self.logger.error("No retrieved folder found")
            return False, ()

        # Verify that the retrieved_temporary_folder is within the arguments if temporary files were specified
        if self._calc._get_retrieve_temporary_list():
            try:
                temporary_folder = retrieved[
                    self.retrieved_temporary_folder_key]
                dir_with_bands = temporary_folder.get_abs_path('.')
            except KeyError:
                self.logger.error(
                    'the {} was not passed as an argument'.format(
                        self.retrieved_temporary_folder_key))
                return False, ()
        else:
            dir_with_bands = None

        list_of_files = out_folder.get_folder_list()

        # The stdout is required for parsing
        if self._calc._OUTPUT_FILE_NAME not in list_of_files:
            self.logger.error(
                "The standard output file '{}' was not found but is required".
                format(self._calc._OUTPUT_FILE_NAME))
            return False, ()

        # The xml file is required for parsing
        if self._calc._DATAFILE_XML_BASENAME not in list_of_files:
            self.logger.error(
                "The xml output file '{}' was not found but is required".
                format(self._calc._DATAFILE_XML_BASENAME))
            successful = False
            xml_file = None
        else:
            xml_file = os.path.join(out_folder.get_abs_path('.'),
                                    self._calc._DATAFILE_XML_BASENAME)

        out_file = os.path.join(out_folder.get_abs_path('.'),
                                self._calc._OUTPUT_FILE_NAME)

        # Call the raw parsing function
        parsing_args = [
            out_file, parameters, parser_opts, xml_file, dir_with_bands
        ]
        out_dict, trajectory_data, structure_data, bands_data, raw_successful = parse_raw_output(
            *parsing_args)

        # If calculation was not considered failed already, use the new value
        successful = raw_successful if successful else successful

        # If the parser option 'all_symmetries' is not set to True, we reduce the raw parsed symmetries to safe space
        all_symmetries = parser_opts.get('all_symmetries', False)

        if not all_symmetries:

            # In the standard output, each symmetry operation print two rotation matrices:
            #
            # * S_cryst^T: matrix in crystal coordinates, transposed
            # * S_cart: matrix in cartesian coordinates,
            #
            # The XML files only print one matrix:
            #
            # * S_cryst: matrix in crystal coordinates
            #
            # The raw parsed symmetry information from the XML is large and will load the database heavily if stored as
            # is for each calculation. Instead, we will map these dictionaries onto a static dictionary of rotation
            # matrices generated by the _get_qe_symmetry_list static method. This dictionary will return the rotation
            # matrices in cartesian coordinates, i.e. S_cart. In order to compare the raw matrices from the XML to these
            # static matrices we have to convert S_cryst into S_cart. We derive here how that is done:
            #
            #   S_cryst * v_cryst = v_cryst'
            #
            # where v_cryst' is the rotated vector v_cryst under S_cryst
            # We define `cell` where cell vectors are rows. Converting a vector from crystal to cartesian
            # coordinates is defined as:
            #
            #   cell^T * v_cryst = v_cart
            #
            # The inverse of this operation is defined as
            #
            #   v_cryst = cell^Tinv * v_cart
            #
            # Replacing the last equation into the first we find:
            #
            #   S_cryst * cell^Tinv * v_cart = cell^Tinv * v_cart'
            #
            # Multiply on the left with cell^T gives:
            #
            #   cell^T * S_cryst * cell^Tinv * v_cart = v_cart'
            #
            # which can be rewritten as:
            #
            #   S_cart * v_cart = v_cart'
            #
            # where:
            #
            #   S_cart = cell^T * S_cryst * cell^Tinv
            #
            # We compute here the transpose and its inverse of the structure cell basis, which is needed to transform
            # the parsed rotation matrices, which are in crystal coordinates, to cartesian coordinates, which are the
            # matrices that are returned by the _get_qe_symmetry_list staticmethod
            cell = structure_data['cell']['lattice_vectors']
            cell_T = numpy.transpose(cell)
            cell_Tinv = numpy.linalg.inv(cell_T)

            try:
                if 'symmetries' in out_dict.keys():
                    old_symmetries = out_dict['symmetries']
                    new_symmetries = []
                    for this_sym in old_symmetries:
                        name = this_sym['name'].strip()
                        for i, this in enumerate(self._possible_symmetries):
                            # Since we do an exact comparison we strip the string name from whitespace
                            # and as soon as it is matched, we break to prevent it from matching another
                            if name == this['name'].strip():
                                index = i
                                break
                        else:
                            index = None
                            self.logger.error(
                                'Symmetry {} not found'.format(name))

                        new_dict = {}
                        if index is not None:
                            # The raw parsed rotation matrix is in crystal coordinates, whereas the mapped rotation
                            # in self._possible_symmetries is in cartesian coordinates. To allow them to be compared
                            # to make sure we matched the correct rotation symmetry, we first convert the parsed matrix
                            # to cartesian coordinates. For explanation of the method, see comment above.
                            rotation_cryst = this_sym['rotation']
                            rotation_cart_new = self._possible_symmetries[
                                index]['matrix']
                            rotation_cart_old = numpy.dot(
                                cell_T, numpy.dot(rotation_cryst, cell_Tinv))

                            inversion = self._possible_symmetries[index][
                                'inversion']
                            if not are_matrices_equal(
                                    rotation_cart_old,
                                    rotation_cart_new,
                                    swap_sign_matrix_b=inversion):
                                self.logger.error(
                                    'Mapped rotation matrix {} does not match the original rotation {}'
                                    .format(rotation_cart_new,
                                            rotation_cart_old))
                                new_dict['all_symmetries'] = this_sym
                            else:
                                # Note: here I lose the information about equivalent ions and fractional_translation.
                                new_dict['t_rev'] = this_sym['t_rev']
                                new_dict['symmetry_number'] = index
                        else:
                            new_dict['all_symmetries'] = this_sym

                        new_symmetries.append(new_dict)

                    out_dict[
                        'symmetries'] = new_symmetries  # and overwrite the old one
            except KeyError:  # no symmetries were parsed (failed case, likely)
                self.logger.error("No symmetries were found in output")

        new_nodes_list = []

        # I eventually save the new structure. structure_data is unnecessary after this
        in_struc = self._calc.get_inputs_dict()['structure']
        type_calc = parameters['CONTROL']['calculation']
        struc = in_struc
        if type_calc in ['relax', 'vc-relax', 'md', 'vc-md']:
            if 'cell' in structure_data.keys():
                struc = convert_qe2aiida_structure(structure_data,
                                                   input_structure=in_struc)
                new_nodes_list.append(
                    (self.get_linkname_outstructure(), struc))

        k_points_list = trajectory_data.pop('k_points', None)
        k_points_weights_list = trajectory_data.pop('k_points_weights', None)

        if k_points_list is not None:

            # Build the kpoints object
            if out_dict['k_points_units'] not in ['2 pi / Angstrom']:
                raise QEOutputParsingError(
                    'Error in kpoints units (should be cartesian)')

            kpoints_from_output = KpointsData()
            kpoints_from_output.set_cell_from_structure(struc)
            kpoints_from_output.set_kpoints(k_points_list,
                                            cartesian=True,
                                            weights=k_points_weights_list)
            kpoints_from_input = self._calc.inp.kpoints

            if not bands_data:
                try:
                    kpoints_from_input.get_kpoints()
                except AttributeError:
                    new_nodes_list += [(self.get_linkname_out_kpoints(),
                                        kpoints_from_output)]

            # Converting bands into a BandsData object (including the kpoints)
            if bands_data:
                kpoints_for_bands = kpoints_from_output

                try:
                    kpoints_from_input.get_kpoints()
                    kpoints_for_bands.labels = kpoints_from_input.labels
                except (AttributeError, ValueError, TypeError):
                    # AttributeError: no list of kpoints in input
                    # ValueError: labels from input do not match the output
                    #      list of kpoints (some kpoints are missing)
                    # TypeError: labels are not set, so kpoints_from_input.labels=None
                    pass

                # Get the bands occupations and correct the occupations of QE:
                # If it computes only one component, it occupies it with half number of electrons
                try:
                    bands_data['occupations'][1]
                    the_occupations = bands_data['occupations']
                except IndexError:
                    the_occupations = 2. * numpy.array(
                        bands_data['occupations'][0])

                try:
                    bands_data['bands'][1]
                    bands_energies = bands_data['bands']
                except IndexError:
                    bands_energies = bands_data['bands'][0]

                the_bands_data = BandsData()
                the_bands_data.set_kpointsdata(kpoints_for_bands)
                the_bands_data.set_bands(bands_energies,
                                         units=bands_data['bands_units'],
                                         occupations=the_occupations)

                new_nodes_list += [('output_band', the_bands_data)]
                out_dict['linknames_band'] = ['output_band']

        # Separate the atomic_occupations dictionary in its own node if it is present
        atomic_occupations = out_dict.get('atomic_occupations', {})
        if atomic_occupations:
            out_dict.pop('atomic_occupations')
            atomic_occupations_node = ParameterData(dict=atomic_occupations)
            new_nodes_list.append(
                ('output_atomic_occupations', atomic_occupations_node))

        output_params = ParameterData(dict=out_dict)
        new_nodes_list.append((self.get_linkname_outparams(), output_params))

        if trajectory_data:
            from aiida.orm.data.array.trajectory import TrajectoryData
            from aiida.orm.data.array import ArrayData
            try:
                positions = numpy.array(
                    trajectory_data.pop('atomic_positions_relax'))
                try:
                    cells = numpy.array(
                        trajectory_data.pop('lattice_vectors_relax'))
                    # if KeyError, the MD was at fixed cell
                except KeyError:
                    cells = numpy.array([in_struc.cell] * len(positions))

                symbols = numpy.array(
                    [str(i.kind_name) for i in in_struc.sites])
                stepids = numpy.arange(
                    len(positions))  # a growing integer per step
                # I will insert time parsing when they fix their issues about time
                # printing (logic is broken if restart is on)

                traj = TrajectoryData()
                traj.set_trajectory(
                    stepids=stepids,
                    cells=cells,
                    symbols=symbols,
                    positions=positions,
                )
                for x in trajectory_data.iteritems():
                    traj.set_array(x[0], numpy.array(x[1]))
                new_nodes_list.append(
                    (self.get_linkname_outtrajectory(), traj))

            except KeyError:
                # forces, atomic charges and atomic mag. moments, in scf calculation (when outputed)
                arraydata = ArrayData()
                for x in trajectory_data.iteritems():
                    arraydata.set_array(x[0], numpy.array(x[1]))
                new_nodes_list.append(
                    (self.get_linkname_outarray(), arraydata))

        return successful, new_nodes_list
コード例 #14
0
ファイル: test_data.py プロジェクト: chrisjsewell/aiida_core
    def setUp(self):
        self.a = ArrayData()
        self.a.set_array('test_array', np.array([0, 1, 3]))
        self.a.store()

        self.cli_runner = CliRunner()
コード例 #15
0
 def _aiida_array(self, data):
     arraydata = ArrayData()
     for ky in data.keys():
         arraydata.set_array(ky, data[ky])
     return arraydata
コード例 #16
0
def get_properties_from_phonopy(structure, phonopy_input, force_constants):
    """
    Calculate DOS and thermal properties using phonopy (locally)
    :param structure: Aiida StructureData Object
    :param phonopy_input: Aiida Parametersdata object containing a dictionary with the data needed to run phonopy:
            supercells matrix, primitive matrix and q-points mesh.
    :param force_constants:
    :return:
    """

    from phonopy.structure.atoms import Atoms as PhonopyAtoms
    from phonopy import Phonopy

    # Generate phonopy phonon object
    bulk = PhonopyAtoms(symbols=[site.kind_name for site in structure.sites],
                        positions=[site.position for site in structure.sites],
                        cell=structure.cell)

    phonopy_input = phonopy_input.get_dict()
    force_constants = force_constants.get_array('force_constants')

    phonon = Phonopy(bulk,
                     phonopy_input['supercell'],
                     primitive_matrix=phonopy_input['primitive'])

    phonon.set_force_constants(force_constants)

    #Normalization factor primitive to unit cell
    normalization_factor = phonon.unitcell.get_number_of_atoms(
    ) / phonon.primitive.get_number_of_atoms()

    phonon.set_mesh(phonopy_input['mesh'],
                    is_eigenvectors=True,
                    is_mesh_symmetry=False)
    phonon.set_total_DOS()
    phonon.set_partial_DOS()

    # get DOS (normalized to unit cell)
    total_dos = phonon.get_total_DOS() * normalization_factor
    partial_dos = phonon.get_partial_DOS() * normalization_factor

    # Stores DOS data in DB as a workflow result
    dos = ArrayData()
    dos.set_array('frequency', total_dos[0])
    dos.set_array('total_dos', total_dos[1])
    dos.set_array('partial_dos', partial_dos[1])

    #THERMAL PROPERTIES (per primtive cell)
    phonon.set_thermal_properties()
    t, free_energy, entropy, cv = phonon.get_thermal_properties()

    # Stores thermal properties (per unit cell) data in DB as a workflow result
    thermal_properties = ArrayData()
    thermal_properties.set_array('temperature', t)
    thermal_properties.set_array('free_energy',
                                 free_energy * normalization_factor)
    thermal_properties.set_array('entropy', entropy * normalization_factor)
    thermal_properties.set_array('cv', cv * normalization_factor)

    return {'thermal_properties': thermal_properties, 'dos': dos}
コード例 #17
0
ファイル: pw.py プロジェクト: asle85/aiida-core
    def parse_with_retrieved(self, retrieved):
        """
        Receives in input a dictionary of retrieved nodes.
        Does all the logic here.
        """
        from aiida.common.exceptions import InvalidOperation
        import os
        import glob

        successful = True

        # check if I'm not to overwrite anything
        #state = self._calc.get_state()
        #if state != calc_states.PARSING:
        #    raise InvalidOperation("Calculation not in {} state"
        #                           .format(calc_states.PARSING) )

        # look for eventual flags of the parser
        try:
            parser_opts = self._calc.inp.settings.get_dict()[
                self.get_parser_settings_key()]
        except (AttributeError, KeyError):
            parser_opts = {}

        # load the input dictionary
        # TODO: pass this input_dict to the parser. It might need it.
        input_dict = self._calc.inp.parameters.get_dict()

        # Check that the retrieved folder is there
        try:
            out_folder = retrieved[self._calc._get_linkname_retrieved()]
        except KeyError:
            self.logger.error("No retrieved folder found")
            return False, ()

        # check what is inside the folder
        list_of_files = out_folder.get_folder_list()
        # at least the stdout should exist
        if not self._calc._OUTPUT_FILE_NAME in list_of_files:
            self.logger.error("Standard output not found")
            successful = False
            return successful, ()
        # if there is something more, I note it down, so to call the raw parser
        # with the right options
        # look for xml
        has_xml = False
        if self._calc._DATAFILE_XML_BASENAME in list_of_files:
            has_xml = True
        # look for bands
        has_bands = False
        if glob.glob(os.path.join(out_folder.get_abs_path('.'), 'K*[0-9]')):
            # Note: assuming format of kpoints subfolder is K*[0-9]
            has_bands = True
            # TODO: maybe it can be more general than bands only?
        out_file = os.path.join(out_folder.get_abs_path('.'),
                                self._calc._OUTPUT_FILE_NAME)
        xml_file = os.path.join(out_folder.get_abs_path('.'),
                                self._calc._DATAFILE_XML_BASENAME)
        dir_with_bands = out_folder.get_abs_path('.')

        # call the raw parsing function
        parsing_args = [out_file, input_dict, parser_opts]
        if has_xml:
            parsing_args.append(xml_file)
        if has_bands:
            if not has_xml:
                self.logger.warning("Cannot parse bands if xml file not "
                                    "found")
            else:
                parsing_args.append(dir_with_bands)

        out_dict, trajectory_data, structure_data, bands_data, raw_successful = parse_raw_output(
            *parsing_args)

        # if calculation was not considered failed already, use the new value
        successful = raw_successful if successful else successful

        # The symmetry info has large arrays, that occupy most of the database.
        # turns out most of this is due to 64 matrices that are repeated over and over again.
        # therefore I map part of the results in a list of dictionaries wrote here once and for all
        # if the parser_opts has a key all_symmetries set to True, I don't reduce it
        all_symmetries = parser_opts.get('all_symmetries', False)
        if not all_symmetries:
            try:
                if 'symmetries' in out_dict.keys():
                    old_symmetries = out_dict['symmetries']
                    new_symmetries = []
                    for this_sym in old_symmetries:
                        name = this_sym['name']
                        index = None
                        for i, this in enumerate(self._possible_symmetries):
                            if name in this['name']:
                                index = i
                        if index is None:
                            self.logger.error(
                                "Symmetry {} not found".format(name))
                        new_dict = {}
                        # note: here I lose the information about equivalent
                        # ions and fractional_translation.
                        # They will be present with all_symmetries=True
                        new_dict['t_rev'] = this_sym['t_rev']
                        new_dict['symmetry_number'] = index
                        new_symmetries.append(new_dict)
                    out_dict[
                        'symmetries'] = new_symmetries  # and overwrite the old one
            except KeyError:  # no symmetries were parsed (failed case, likely)
                self.logger.error("No symmetries were found in output")

        new_nodes_list = []

        # I eventually save the new structure. structure_data is unnecessary after this
        in_struc = self._calc.get_inputs_dict()['structure']
        type_calc = input_dict['CONTROL']['calculation']
        struc = in_struc
        if type_calc in ['relax', 'vc-relax', 'md', 'vc-md']:
            if 'cell' in structure_data.keys():
                struc = convert_qe2aiida_structure(structure_data,
                                                   input_structure=in_struc)
                new_nodes_list.append(
                    (self.get_linkname_outstructure(), struc))

        k_points_list = trajectory_data.pop('k_points', None)
        k_points_weights_list = trajectory_data.pop('k_points_weights', None)

        if k_points_list is not None:

            # build the kpoints object
            if out_dict['k_points_units'] not in ['2 pi / Angstrom']:
                raise QEOutputParsingError(
                    'Error in kpoints units (should be cartesian)')
            # converting bands into a BandsData object (including the kpoints)

            kpoints_from_output = KpointsData()
            kpoints_from_output.set_cell_from_structure(struc)
            kpoints_from_output.set_kpoints(k_points_list,
                                            cartesian=True,
                                            weights=k_points_weights_list)
            kpoints_from_input = self._calc.inp.kpoints

            if not bands_data:
                try:
                    kpoints_from_input.get_kpoints()
                except AttributeError:
                    new_nodes_list += [(self.get_linkname_out_kpoints(),
                                        kpoints_from_output)]

            if bands_data:
                import numpy
                # converting bands into a BandsData object (including the kpoints)

                kpoints_for_bands = kpoints_from_output

                try:
                    kpoints_from_input.get_kpoints()
                    kpoints_for_bands.labels = kpoints_from_input.labels
                except (AttributeError, ValueError, TypeError):
                    # AttributeError: no list of kpoints in input
                    # ValueError: labels from input do not match the output
                    #      list of kpoints (some kpoints are missing)
                    # TypeError: labels are not set, so kpoints_from_input.labels=None
                    pass

                # get the bands occupations.
                # correct the occupations of QE: if it computes only one component,
                # it occupies it with half number of electrons
                try:
                    bands_data['occupations'][1]
                    the_occupations = bands_data['occupations']
                except IndexError:
                    the_occupations = 2. * numpy.array(
                        bands_data['occupations'][0])

                try:
                    bands_data['bands'][1]
                    bands_energies = bands_data['bands']
                except IndexError:
                    bands_energies = bands_data['bands'][0]

                the_bands_data = BandsData()
                the_bands_data.set_kpointsdata(kpoints_for_bands)
                the_bands_data.set_bands(bands_energies,
                                         units=bands_data['bands_units'],
                                         occupations=the_occupations)

                new_nodes_list += [('output_band', the_bands_data)]
                out_dict['linknames_band'] = ['output_band']

        # convert the dictionary into an AiiDA object
        output_params = ParameterData(dict=out_dict)
        # return it to the execmanager
        new_nodes_list.append((self.get_linkname_outparams(), output_params))

        if trajectory_data:
            import numpy
            from aiida.orm.data.array.trajectory import TrajectoryData
            from aiida.orm.data.array import ArrayData
            try:
                positions = numpy.array(
                    trajectory_data.pop('atomic_positions_relax'))
                try:
                    cells = numpy.array(
                        trajectory_data.pop('lattice_vectors_relax'))
                    # if KeyError, the MD was at fixed cell
                except KeyError:
                    cells = numpy.array([in_struc.cell] * len(positions))

                symbols = numpy.array(
                    [str(i.kind_name) for i in in_struc.sites])
                stepids = numpy.arange(
                    len(positions))  # a growing integer per step
                # I will insert time parsing when they fix their issues about time
                # printing (logic is broken if restart is on)

                traj = TrajectoryData()
                traj.set_trajectory(
                    stepids=stepids,
                    cells=cells,
                    symbols=symbols,
                    positions=positions,
                )
                for x in trajectory_data.iteritems():
                    traj.set_array(x[0], numpy.array(x[1]))
                # return it to the execmanager
                new_nodes_list.append(
                    (self.get_linkname_outtrajectory(), traj))

            except KeyError:
                # forces, atomic charges and atomic mag. moments, in scf
                # calculation (when outputed)
                arraydata = ArrayData()
                for x in trajectory_data.iteritems():
                    arraydata.set_array(x[0], numpy.array(x[1]))
                # return it to the execmanager
                new_nodes_list.append(
                    (self.get_linkname_outarray(), arraydata))

        return successful, new_nodes_list
コード例 #18
0
    def parse_with_retrieved(self, retrieved):
        """
        Receives in input a dictionary of retrieved nodes.
        Does all the logic here.
        """
        from aiida.common.exceptions import InvalidOperation
        import os
        import glob

        successful = True

        # check if I'm not to overwrite anything
        #state = self._calc.get_state()
        #if state != calc_states.PARSING:
        #    raise InvalidOperation("Calculation not in {} state"
        #                           .format(calc_states.PARSING) )

        # retrieve the input parameter
        calc_input = self._calc.inp.parameters

        # look for eventual flags of the parser
        try:
            parser_opts = self._calc.inp.settings.get_dict()[
                self.get_parser_settings_key()]
        except (AttributeError, KeyError):
            parser_opts = {}

        # load the input dictionary
        # TODO: pass this input_dict to the parser. It might need it.
        input_dict = self._calc.inp.parameters.get_dict()

        # Check that the retrieved folder is there
        try:
            out_folder = retrieved[self._calc._get_linkname_retrieved()]
        except KeyError:
            self.logger.error("No retrieved folder found")
            return False, ()

        # check what is inside the folder
        list_of_files = out_folder.get_folder_list()
        # at least the stdout should exist
        if not self._calc._OUTPUT_FILE_NAME in list_of_files:
            self.logger.error("Standard output not found")
            successful = False
            return successful, ()
        # if there is something more, I note it down, so to call the raw parser
        # with the right options
        # look for xml
        has_xml = False
        if self._calc._DATAFILE_XML_BASENAME in list_of_files:
            has_xml = True
        # look for bands
        has_bands = False
        if glob.glob(os.path.join(out_folder.get_abs_path('.'), 'K*[0-9]')):
            # Note: assuming format of kpoints subfolder is K*[0-9]
            has_bands = True
            # TODO: maybe it can be more general than bands only?
        out_file = os.path.join(out_folder.get_abs_path('.'),
                                self._calc._OUTPUT_FILE_NAME)
        xml_file = os.path.join(out_folder.get_abs_path('.'),
                                self._calc._DATAFILE_XML_BASENAME)
        dir_with_bands = out_folder.get_abs_path('.')

        # call the raw parsing function
        parsing_args = [out_file, input_dict, parser_opts]
        if has_xml:
            parsing_args.append(xml_file)
        if has_bands:
            if not has_xml:
                self.logger.warning("Cannot parse bands if xml file not "
                                    "found")
            else:
                parsing_args.append(dir_with_bands)

        out_dict, trajectory_data, structure_data, raw_successful = parse_raw_output(
            *parsing_args)

        # if calculation was not considered failed already, use the new value
        successful = raw_successful if successful else successful

        new_nodes_list = []

        # I eventually save the new structure. structure_data is unnecessary after this
        in_struc = self._calc.get_inputs_dict()['structure']
        type_calc = input_dict['CONTROL']['calculation']
        struc = in_struc
        if type_calc in ['relax', 'vc-relax', 'md', 'vc-md']:
            if 'cell' in structure_data.keys():
                struc = convert_qe2aiida_structure(structure_data,
                                                   input_structure=in_struc)
                new_nodes_list.append(
                    (self.get_linkname_outstructure(), struc))

        k_points_list = trajectory_data.pop('k_points', None)
        k_points_weights_list = trajectory_data.pop('k_points_weights', None)

        if k_points_list is not None:

            # build the kpoints object
            if out_dict['k_points_units'] not in ['2 pi / Angstrom']:
                raise QEOutputParsingError(
                    'Error in kpoints units (should be cartesian)')
            # converting bands into a BandsData object (including the kpoints)

            kpoints_from_output = KpointsData()
            kpoints_from_output.set_cell_from_structure(struc)
            kpoints_from_output.set_kpoints(k_points_list,
                                            cartesian=True,
                                            weights=k_points_weights_list)
            kpoints_from_input = self._calc.inp.kpoints
            try:
                kpoints_from_input.get_kpoints()
            except AttributeError:
                new_nodes_list += [(self.get_linkname_out_kpoints(),
                                    kpoints_from_output)]

        # convert the dictionary into an AiiDA object
        output_params = ParameterData(dict=out_dict)
        # return it to the execmanager
        new_nodes_list.append((self.get_linkname_outparams(), output_params))

        if trajectory_data:
            import numpy
            from aiida.orm.data.array.trajectory import TrajectoryData
            from aiida.orm.data.array import ArrayData

            try:
                positions = numpy.array(
                    trajectory_data.pop('atomic_positions_relax'))
                try:
                    cells = numpy.array(
                        trajectory_data.pop('lattice_vectors_relax'))
                    # if KeyError, the MD was at fixed cell
                except KeyError:
                    cells = numpy.array([in_struc.cell] * len(positions))

                symbols = numpy.array(
                    [str(i.kind_name) for i in in_struc.sites])
                stepids = numpy.arange(
                    len(positions))  # a growing integer per step
                # I will insert time parsing when they fix their issues about time
                # printing (logic is broken if restart is on)

                traj = TrajectoryData()
                traj.set_trajectory(
                    stepids=stepids,
                    cells=cells,
                    symbols=symbols,
                    positions=positions,
                )
                for x in trajectory_data.iteritems():
                    traj.set_array(x[0], numpy.array(x[1]))
                # return it to the execmanager
                new_nodes_list.append(
                    (self.get_linkname_outtrajectory(), traj))

            except KeyError:  # forces in scf calculation (when outputed)
                arraydata = ArrayData()
                for x in trajectory_data.iteritems():
                    arraydata.set_array(x[0], numpy.array(x[1]))
                # return it to the execmanager
                new_nodes_list.append(
                    (self.get_linkname_outarray(), arraydata))

        return successful, new_nodes_list
コード例 #19
0
def execute(args):
    """
    The main execution of the script, which will run some preliminary checks on the command
    line arguments before passing them to the workchain and running it
    """
    try:
        code = Code.get_from_string(args.codename)
    except NotExistent as exception:
        print "Execution failed: could not retrieve the code '{}'".format(
            args.codename)
        print "Exception report: {}".format(exception)
        return

    try:
        vibra_code = Code.get_from_string(args.vibra_codename)
    except NotExistent as exception:
        print "Execution failed: could not retrieve the code '{}'".format(
            args.stm_codename)
        print "Exception report: {}".format(exception)
        return

    protocol = Str(args.protocol)

    # Structure. Bulk silicon

    SuperCell_1 = 1
    SuperCell_2 = 1
    SuperCell_3 = 1
    scnumbers = np.array([SuperCell_1, SuperCell_2, SuperCell_3])
    scarray = ArrayData()
    scarray.set_array('sca', scnumbers)

    alat = 5.43  # Angstrom. Not passed to the fdf file (only for internal use)
    cell = [[
        0.,
        alat / 2,
        alat / 2,
    ], [
        alat / 2,
        0.,
        alat / 2,
    ], [
        alat / 2,
        alat / 2,
        0.,
    ]]
    pf = alat * 0.125
    na = 2
    x0 = [[pf, pf, pf], [-pf, -pf, -pf]]

    s1 = StructureData(cell=cell)
    for i in range(na):
        s1.append_atom(position=(x0[i][0], x0[i][1], x0[i][2]), symbols=['Si'])

    bandskpoints = KpointsData()
    kpp = [(1, 1., 1., 1.), (15, 0., 0.5, 0.5), (25, 0., 0., 0.),
           (20, 0.5, 0.5, 0.5), (20, 0., 0.5, 0.5), (15, 0.25, 0.5, 0.75),
           (20, 0.5, 0.5, 0.5)]
    lpp = [[0, '\Gamma'], [1, 'X'], [2, '\Gamma'], [3, 'L'], [4, 'X'],
           [5, 'W'], [6, 'L']]
    bandskpoints.set_cell(s1.cell, s1.pbc)
    bandskpoints.set_kpoints(kpp, labels=lpp)

    if args.structure > 0:
        structure = load_node(args.structure)
    else:
        structure = s1

    run(SiestaVibraWorkChain,
        code=code,
        vibra_code=vibra_code,
        scarray=scarray,
        structure=structure,
        protocol=protocol,
        bandskpoints=bandskpoints)
コード例 #20
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
コード例 #21
0
    def parse_from_calc(self):
        """
        Parses the datafolder, stores results.
        This parser for this simple code does simply store in the DB a node
        representing the file of forces in real space
        """
        from aiida.common.exceptions import InvalidOperation
        from aiida.common import aiidalogger
        from aiida.djsite.utils import get_dblogger_extra

        import ase, ase.io

        parserlogger = aiidalogger.getChild('aseparser')
        logger_extra = get_dblogger_extra(self._calc)

        # suppose at the start that the job is successful
        successful = True

        # check that calculation is in the right state
        state = self._calc.get_state()
        if state != calc_states.PARSING:
            raise InvalidOperation("Calculation not in {} state".format(
                calc_states.PARSING))

        # select the folder object
        out_folder = self._calc.get_retrieved_node()

        # check what is inside the folder
        list_of_files = out_folder.get_folder_list()

        # at least the stdout should exist
        if not self._calc._OUTPUT_FILE_NAME in list_of_files:
            successful = False
            parserlogger.error("Standard output not found", extra=logger_extra)
            return successful, ()

        # output structure
        has_out_atoms = True if self._calc._output_aseatoms in list_of_files else False
        if has_out_atoms:
            out_atoms = ase.io.read(
                out_folder.get_abs_path(self._calc._output_aseatoms))
            out_structure = StructureData().set_ase(out_atoms)

        # load the results dictionary
        json_outfile = out_folder.get_abs_path(self._calc._OUTPUT_FILE_NAME)
        with open(json_outfile, 'r') as f:
            json_params = json.load(f)

        # extract arrays from json_params
        dictionary_array = {}
        for k, v in list(json_params.iteritems()):
            if isinstance(v, (list, tuple)):
                dictionary_array[k] = json_params.pop(k)

        # look at warnings
        warnings = []
        with open(out_folder.get_abs_path(self._calc._SCHED_ERROR_FILE)) as f:
            errors = f.read()
        if errors:
            warnings = [errors]
        json_params['warnings'] = warnings

        # save the outputs
        new_nodes_list = []

        # save the arrays
        if dictionary_array:
            array_data = ArrayData()
            for k, v in dictionary_array.iteritems():
                array_data.set_array(k, numpy.array(v))
            new_nodes_list.append((self._outarray_name, array_data))

        # save the parameters
        if json_params:
            parameter_data = ParameterData(dict=json_params)
            new_nodes_list.append((self._outdict_name, parameter_data))

        if has_out_atoms:
            structure_data = StructureData()
            new_nodes_list.append((self._outstruc_name, structure_data))

        return successful, new_nodes_list
コード例 #22
0
 def _sigma_c(self, ndbqp, ndbhf):
     """
     Calculate S_c if missing from  information parsed from the  ndb.*
      Sc = 1/Z[ E-Eo] -S_x + Vxc
     """
     Eo = numpy.array(ndbqp['E-Eo'])
     Z = numpy.array(ndbqp['Z'])
     E_minus_Eo = numpy.array(ndbqp['E-Eo'])
     Sx = numpy.array(ndbhf['Sx'])
     Vxc = numpy.array(ndbhf['Vxc'])
     try:
         Sc = numpy.array(ndbqp['So'])
     except KeyError:
         Sc = 1 / Z * E_minus_Eo - Sx + Vxc
     pdata = ArrayData()
     pdata.set_array('Eo', Eo)
     pdata.set_array('E_minus_Eo', E_minus_Eo)
     pdata.set_array('Z', Z)
     pdata.set_array('Sx', Sx)
     pdata.set_array('Sc', Sc)
     pdata.set_array('Vxc', Vxc)
     pdata.set_array('qp_table', numpy.array(ndbqp['qp_table']))
     return pdata
コード例 #23
0
    def get_stm_data(self, plot_path):
        """
        Parses the STM plot file to get an Array object with
        X, Y, and Z arrays in the 'meshgrid'
        setting, as in the example code:

        import numpy as np
        xlist = np.linspace(-3.0, 3.0, 3)
        ylist = np.linspace(-3.0, 3.0, 4)
        X, Y = np.meshgrid(xlist, ylist)
        Z = np.sqrt(X**2 + Y**2)

        X:
        [[-3.  0.  3.]
        [-3.  0.  3.]
        [-3.  0.  3.]
        [-3.  0.  3.]]

        Y:
        [[-3. -3. -3.]
        [-1. -1. -1.]
        [ 1.  1.  1.]
        [ 3.  3.  3.]]

        Z:
        [[ 4.24264069  3.          4.24264069]
        [ 3.16227766  1.          3.16227766]
        [ 3.16227766  1.          3.16227766]
        [ 4.24264069  3.          4.24264069]]

        These can then be used in matplotlib to get a contour plot.
        """

        import numpy as np
        from itertools import groupby

        from aiida.common.exceptions import InputValidationError
        from aiida.common.exceptions import ValidationError

        file = open(plot_path, "r")  # aiida.CH.STM or aiida.CC.STM...
        data = file.read().split('\n')
        data = [i.split() for i in data]

        # The data in the file is organized in "lines" parallel to the Y axes
        # (that is, for constant X) separated by blank lines.
        # In the following we use the 'groupby' function to get at the individual
        # blocks one by one, and set the appropriate arrays.

        # I am not sure about the mechanics of groupby,
        # so repeat
        xx = []
        yy = []
        zz = []
        #
        # Function to separate the blocks
        h = lambda x: len(x) == 0
        #
        for k, g in groupby(data, h):
            if not k:
                xx.append([i[0] for i in g])
        for k, g in groupby(data, h):
            if not k:
                yy.append([i[1] for i in g])
        for k, g in groupby(data, h):
            if not k:
                zz.append([i[2] for i in g])

        # Now, transpose, since x runs fastest in our fortran code,
        # the opposite convention of the meshgrid paradigm.

        X = np.array(xx, dtype=float).transpose()
        Y = np.array(yy, dtype=float).transpose()
        Z = np.array(zz, dtype=float).transpose()

        from aiida.orm.data.array import ArrayData

        arraydata = ArrayData()
        arraydata.set_array('X', np.array(X))
        arraydata.set_array('Y', np.array(Y))
        arraydata.set_array('Z', np.array(Z))

        return arraydata
コード例 #24
0
ファイル: siesta.py プロジェクト: garsua/aiida_siesta_plugin
    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
コード例 #25
0
ファイル: pw.py プロジェクト: zhubonan/aiida-quantumespresso
    def parse_with_retrieved(self, retrieved):
        """
        Parse the output nodes for a PwCalculations from a dictionary of retrieved nodes.
        Two nodes that are expected are the default 'retrieved' FolderData node which will
        store the retrieved files permanently in the repository. The second required node
        is the unstored FolderData node with the temporary retrieved files, which should
        be passed under the key 'retrieved_temporary_folder_key' of the Parser class.

        :param retrieved: a dictionary of retrieved nodes
        """
        import os
        import numpy

        successful = True

        # Load the input dictionary
        parameters = self._calc.inp.parameters.get_dict()

        # Look for optional settings input node and potential 'parser_options' dictionary within it
        try:
            settings = self._calc.inp.settings.get_dict()
            parser_opts = settings[self.get_parser_settings_key()]
        except (AttributeError, KeyError):
            settings = {}
            parser_opts = {}

        # Check that the retrieved folder is there
        try:
            out_folder = retrieved[self._calc._get_linkname_retrieved()]
        except KeyError:
            self.logger.error("No retrieved folder found")
            return False, ()

        # Verify that the retrieved_temporary_folder is within the arguments if temporary files were specified
        if self._calc._get_retrieve_temporary_list():
            try:
                temporary_folder = retrieved[self.retrieved_temporary_folder_key]
                dir_with_bands = temporary_folder.get_abs_path('.')
            except KeyError:
                self.logger.error('the {} was not passed as an argument'.format(self.retrieved_temporary_folder_key))
                return False, ()
        else:
            dir_with_bands = None

        list_of_files = out_folder.get_folder_list()

        # The stdout is required for parsing
        if not self._calc._OUTPUT_FILE_NAME in list_of_files:
            self.logger.error("The standard output file '{}' was not found but is required".format(self._calc._OUTPUT_FILE_NAME))
            return False, ()

        # The xml file is required for parsing
        if not self._calc._DATAFILE_XML_BASENAME in list_of_files:
            self.logger.error("The xml output file '{}' was not found but is required".format(self._calc._DATAFILE_XML_BASENAME))
            successful = False
            xml_file = None
        else:
            xml_file = os.path.join(out_folder.get_abs_path('.'), self._calc._DATAFILE_XML_BASENAME)

        out_file = os.path.join(out_folder.get_abs_path('.'), self._calc._OUTPUT_FILE_NAME)

        # Call the raw parsing function
        parsing_args = [out_file, parameters, parser_opts, xml_file, dir_with_bands]
        out_dict, trajectory_data, structure_data, bands_data, raw_successful = parse_raw_output(*parsing_args)

        # If calculation was not considered failed already, use the new value
        successful = raw_successful if successful else successful

        # The symmetry info has large arrays, that occupy most of the database.
        # turns out most of this is due to 64 matrices that are repeated over and over again.
        # therefore I map part of the results in a list of dictionaries wrote here once and for all
        # if the parser_opts has a key all_symmetries set to True, I don't reduce it
        all_symmetries = parser_opts.get('all_symmetries', False)
        if not all_symmetries:
            try:
                if 'symmetries' in out_dict.keys():
                    old_symmetries = out_dict['symmetries']
                    new_symmetries = []
                    for this_sym in old_symmetries:
                        name = this_sym['name']
                        index = None
                        for i,this in enumerate(self._possible_symmetries):
                            if name in this['name']:
                                index = i
                        if index is None:
                            self.logger.error("Symmetry {} not found".format(name))
                        new_dict = {}
                        # note: here I lose the information about equivalent
                        # ions and fractional_translation.
                        # They will be present with all_symmetries=True
                        new_dict['t_rev'] = this_sym['t_rev']
                        new_dict['symmetry_number'] = index
                        new_symmetries.append(new_dict)
                    out_dict['symmetries'] = new_symmetries # and overwrite the old one
            except KeyError: # no symmetries were parsed (failed case, likely)
                self.logger.error("No symmetries were found in output")

        new_nodes_list = []

        # I eventually save the new structure. structure_data is unnecessary after this
        in_struc = self._calc.get_inputs_dict()['structure']
        type_calc = parameters['CONTROL']['calculation']
        struc = in_struc
        if type_calc in ['relax', 'vc-relax', 'md', 'vc-md']:
            if 'cell' in structure_data.keys():
                struc = convert_qe2aiida_structure(structure_data, input_structure=in_struc)
                new_nodes_list.append((self.get_linkname_outstructure(), struc))

        k_points_list = trajectory_data.pop('k_points', None)
        k_points_weights_list = trajectory_data.pop('k_points_weights', None)

        if k_points_list is not None:

            # Build the kpoints object
            if out_dict['k_points_units'] not in ['2 pi / Angstrom']:
                raise QEOutputParsingError('Error in kpoints units (should be cartesian)')

            kpoints_from_output = KpointsData()
            kpoints_from_output.set_cell_from_structure(struc)
            kpoints_from_output.set_kpoints(k_points_list, cartesian=True, weights=k_points_weights_list)
            kpoints_from_input = self._calc.inp.kpoints

            if not bands_data:
                try:
                    kpoints_from_input.get_kpoints()
                except AttributeError:
                    new_nodes_list += [(self.get_linkname_out_kpoints(), kpoints_from_output)]

            # Converting bands into a BandsData object (including the kpoints)
            if bands_data:
                kpoints_for_bands = kpoints_from_output

                try:
                    kpoints_from_input.get_kpoints()
                    kpoints_for_bands.labels = kpoints_from_input.labels
                except (AttributeError, ValueError, TypeError):
                    # AttributeError: no list of kpoints in input
                    # ValueError: labels from input do not match the output
                    #      list of kpoints (some kpoints are missing)
                    # TypeError: labels are not set, so kpoints_from_input.labels=None
                    pass

                # Get the bands occupations and correct the occupations of QE:
                # If it computes only one component, it occupies it with half number of electrons
                try:
                    bands_data['occupations'][1]
                    the_occupations = bands_data['occupations']
                except IndexError:
                    the_occupations = 2.*numpy.array(bands_data['occupations'][0])

                try:
                    bands_data['bands'][1]
                    bands_energies = bands_data['bands']
                except IndexError:
                    bands_energies = bands_data['bands'][0]

                the_bands_data = BandsData()
                the_bands_data.set_kpointsdata(kpoints_for_bands)
                the_bands_data.set_bands(bands_energies,
                                         units = bands_data['bands_units'],
                                         occupations = the_occupations)

                new_nodes_list += [('output_band', the_bands_data)]
                out_dict['linknames_band'] = ['output_band']

        # Separate the atomic_occupations dictionary in its own node if it is present
        atomic_occupations = out_dict.get('atomic_occupations', {})
        if atomic_occupations:
            out_dict.pop('atomic_occupations')
            atomic_occupations_node = ParameterData(dict=atomic_occupations)
            new_nodes_list.append(('output_atomic_occupations', atomic_occupations_node))

        output_params = ParameterData(dict=out_dict)
        new_nodes_list.append((self.get_linkname_outparams(), output_params))

        if trajectory_data:
            from aiida.orm.data.array.trajectory import TrajectoryData
            from aiida.orm.data.array import ArrayData
            try:
                positions = numpy.array( trajectory_data.pop('atomic_positions_relax'))
                try:
                    cells = numpy.array( trajectory_data.pop('lattice_vectors_relax'))
                    # if KeyError, the MD was at fixed cell
                except KeyError:
                    cells = numpy.array([in_struc.cell] * len(positions))

                symbols = numpy.array([str(i.kind_name) for i in in_struc.sites])
                stepids = numpy.arange(len(positions)) # a growing integer per step
                # I will insert time parsing when they fix their issues about time
                # printing (logic is broken if restart is on)

                traj = TrajectoryData()
                traj.set_trajectory(
                    stepids = stepids,
                    cells = cells,
                    symbols = symbols,
                    positions = positions,
                )
                for x in trajectory_data.iteritems():
                    traj.set_array(x[0],numpy.array(x[1]))
                new_nodes_list.append((self.get_linkname_outtrajectory(),traj))

            except KeyError:
                # forces, atomic charges and atomic mag. moments, in scf calculation (when outputed)
                arraydata = ArrayData()
                for x in trajectory_data.iteritems():
                    arraydata.set_array(x[0],numpy.array(x[1]))
                new_nodes_list.append((self.get_linkname_outarray(),arraydata))

        return successful, new_nodes_list
コード例 #26
0
 def _aiida_ndb_qp(self, data):
     """
     Save the data from ndb.QP to the db
     """
     pdata = ArrayData()
     pdata.set_array('Eo', numpy.array(data['Eo']))
     pdata.set_array('E_minus_Eo', numpy.array(data['E-Eo']))
     pdata.set_array('Z', numpy.array(data['Z']))
     pdata.set_array('qp_table', numpy.array(data['qp_table']))
     try:
         pdata.set_array('So', numpy.array(data['So']))
     except KeyError:
         pass
     return pdata
コード例 #27
0
    def test_pw_translation(self):
        from aiida.tools.dbexporters.tcod \
            import translate_calculation_specific_values
        # from aiida.tools.dbexporters.tcod_plugins.pw \
        #     import PwTcodtranslator as PWT
        # from aiida.tools.dbexporters.tcod_plugins.cp \
        #     import CpTcodtranslator as CPT
        from aiida.orm.code import Code
        from aiida.orm.data.array import ArrayData
        from aiida.orm.data.array.kpoints import KpointsData
        from aiida.orm.data.parameter import ParameterData
        import numpy
        from aiida.common.pluginloader import get_plugin
        PWT = get_plugin('tools.dbexporters.tcod_plugins',
                         'quantumespresso.pw')
        CPT = get_plugin('tools.dbexporters.tcod_plugins',
                         'quantumespresso.cp')

        code = Code()
        code._set_attr('remote_exec_path', '/test')

        kpoints = KpointsData()
        kpoints.set_kpoints_mesh([2, 3, 4], offset=[0.25, 0.5, 0.75])

        def empty_list():
            return []

        calc = FakeObject({
            "inp": {
                "parameters": ParameterData(dict={}),
                "kpoints": kpoints,
                "code": code
            },
            "out": {
                "output_parameters": ParameterData(dict={})
            },
            "get_inputs": empty_list
        })

        res = translate_calculation_specific_values(calc, PWT)
        self.assertEquals(
            res, {
                '_dft_BZ_integration_grid_X': 2,
                '_dft_BZ_integration_grid_Y': 3,
                '_dft_BZ_integration_grid_Z': 4,
                '_dft_BZ_integration_grid_shift_X': 0.25,
                '_dft_BZ_integration_grid_shift_Y': 0.5,
                '_dft_BZ_integration_grid_shift_Z': 0.75,
                '_dft_pseudopotential_atom_type': [],
                '_dft_pseudopotential_type': [],
                '_dft_pseudopotential_type_other_name': [],
                '_tcod_software_package': 'Quantum ESPRESSO',
                '_tcod_software_executable_path': '/test',
            })

        calc = FakeObject({
            "inp": {
                "parameters":
                ParameterData(dict={
                    'SYSTEM': {
                        'ecutwfc': 40,
                        'occupations': 'smearing'
                    }
                })
            },
            "out": {
                "output_parameters":
                ParameterData(dict={
                    'number_of_electrons': 10,
                })
            },
            "get_inputs": empty_list
        })
        res = translate_calculation_specific_values(calc, PWT)
        self.assertEquals(
            res, {
                '_dft_cell_valence_electrons': 10,
                '_tcod_software_package': 'Quantum ESPRESSO',
                '_dft_BZ_integration_smearing_method': 'Gaussian',
                '_dft_pseudopotential_atom_type': [],
                '_dft_pseudopotential_type': [],
                '_dft_pseudopotential_type_other_name': [],
                '_dft_kinetic_energy_cutoff_EEX': 2176.910676048,
                '_dft_kinetic_energy_cutoff_charge_density': 2176.910676048,
                '_dft_kinetic_energy_cutoff_wavefunctions': 544.227669012,
            })

        calc = FakeObject({
            "inp": {
                "parameters": ParameterData(dict={})
            },
            "out": {
                "output_parameters": ParameterData(dict={
                    'energy_xc': 5,
                })
            },
            "get_inputs": empty_list
        })
        with self.assertRaises(ValueError):
            translate_calculation_specific_values(calc, PWT)

        calc = FakeObject({
            "inp": {
                "parameters": ParameterData(dict={})
            },
            "out": {
                "output_parameters":
                ParameterData(dict={
                    'energy_xc': 5,
                    'energy_xc_units': 'meV'
                })
            },
            "get_inputs": empty_list
        })
        with self.assertRaises(ValueError):
            translate_calculation_specific_values(calc, PWT)

        energies = {
            'energy': -3701.7004199449257,
            'energy_one_electron': -984.0078459766,
            'energy_xc': -706.6986753641559,
            'energy_ewald': -2822.6335103043157,
            'energy_hartree': 811.6396117001462,
            'fermi_energy': 10.25208617898623,
        }
        dct = energies
        for key in energies.keys():
            dct["{}_units".format(key)] = 'eV'
        calc = FakeObject({
            "inp": {
                "parameters":
                ParameterData(dict={'SYSTEM': {
                    'smearing': 'mp'
                }})
            },
            "out": {
                "output_parameters": ParameterData(dict=dct)
            },
            "get_inputs": empty_list
        })
        res = translate_calculation_specific_values(calc, PWT)
        self.assertEquals(
            res, {
                '_tcod_total_energy': energies['energy'],
                '_dft_1e_energy': energies['energy_one_electron'],
                '_dft_correlation_energy': energies['energy_xc'],
                '_dft_ewald_energy': energies['energy_ewald'],
                '_dft_hartree_energy': energies['energy_hartree'],
                '_dft_fermi_energy': energies['fermi_energy'],
                '_tcod_software_package': 'Quantum ESPRESSO',
                '_dft_BZ_integration_smearing_method': 'Methfessel-Paxton',
                '_dft_BZ_integration_MP_order': 1,
                '_dft_pseudopotential_atom_type': [],
                '_dft_pseudopotential_type': [],
                '_dft_pseudopotential_type_other_name': [],
            })
        dct = energies
        dct['number_of_electrons'] = 10
        for key in energies.keys():
            dct["{}_units".format(key)] = 'eV'
        calc = FakeObject({
            "inp": {
                "parameters":
                ParameterData(dict={'SYSTEM': {
                    'smearing': 'unknown-method'
                }})
            },
            "out": {
                "output_parameters": ParameterData(dict=dct)
            },
            "get_inputs": empty_list
        })
        res = translate_calculation_specific_values(calc, CPT)
        self.assertEquals(
            res, {
                '_dft_cell_valence_electrons': 10,
                '_tcod_software_package': 'Quantum ESPRESSO'
            })

        ad = ArrayData()
        ad.set_array("forces", numpy.array([[[1, 2, 3], [4, 5, 6]]]))
        calc = FakeObject({
            "inp": {
                "parameters":
                ParameterData(dict={'SYSTEM': {
                    'smearing': 'unknown-method'
                }})
            },
            "out": {
                "output_parameters": ParameterData(dict={}),
                "output_array": ad
            },
            "get_inputs": empty_list
        })
        res = translate_calculation_specific_values(calc, PWT)
        self.assertEquals(
            res,
            {
                '_tcod_software_package': 'Quantum ESPRESSO',
                '_dft_BZ_integration_smearing_method': 'other',
                '_dft_BZ_integration_smearing_method_other': 'unknown-method',
                '_dft_pseudopotential_atom_type': [],
                '_dft_pseudopotential_type': [],
                '_dft_pseudopotential_type_other_name': [],
                ## Residual forces are no longer produced, as they should
                ## be in the same CIF loop with coordinates -- to be
                ## implemented later, since it's not yet clear how.
                # '_tcod_atom_site_resid_force_Cartn_x': [1,4],
                # '_tcod_atom_site_resid_force_Cartn_y': [2,5],
                # '_tcod_atom_site_resid_force_Cartn_z': [3,6],
            })
コード例 #28
0
    def parse_with_retrieved(self, retrieved):
        """
        Parse the results of retrieved nodes

        :param retrieved: dictionary of retrieved nodes
        """
        is_success = True
        output_nodes = []

        try:
            output_folder = retrieved[
                self.calculation._get_linkname_retrieved()]
        except KeyError:
            self.logger.error('no retrieved folder found')
            return False, ()

        # Verify the standard output file is present, parse it and attach as output parameters
        try:
            filepath_stdout = output_folder.get_abs_path(
                self.calculation.output_file_name)
        except OSError as exception:
            self.logger.error(
                "expected output file '{}' was not found".format(filepath))
            return False, ()

        is_success, dict_stdout = self.parse_stdout(filepath_stdout)
        output_nodes.append(
            (self.get_linkname_outparams(), ParameterData(dict=dict_stdout)))

        # The final chi and hubbard files are only written by a serial or post-processing calculation
        complete_calculation = True

        # We cannot use get_abs_path of the output_folder, since that will check for file existence and will throw
        output_path = output_folder.get_abs_path('.')
        filepath_chi = os.path.join(output_path,
                                    self.calculation.output_file_name_chi)
        filepath_hubbard = os.path.join(
            output_path, self.calculation.output_file_name_hubbard)
        filepath_hubbard_file = os.path.join(
            output_path, self.calculation.output_file_name_hubbard_file)

        for filepath in [filepath_chi, filepath_hubbard]:
            if not os.path.isfile(filepath):
                complete_calculation = False
                self.logger.info(
                    "output file '{}' was not found, assuming partial calculation"
                    .format(filepath))

        if os.path.isfile(filepath_hubbard_file):
            output_hubbard_file = SinglefileData(file=filepath_hubbard_file)
            output_nodes.append(
                (self.get_linkname_hubbard_file(), output_hubbard_file))

        if complete_calculation:
            dict_hubbard = self.parse_hubbard(filepath_hubbard)
            dict_chi = self.parse_chi(filepath_chi)

            output_matrices = ArrayData()
            output_matrices.set_array('chi0', dict_hubbard['chi0'])
            output_matrices.set_array('chi1', dict_hubbard['chi1'])
            output_matrices.set_array('chi0_inv', dict_hubbard['chi0_inv'])
            output_matrices.set_array('chi1_inv', dict_hubbard['chi1_inv'])
            output_matrices.set_array('hubbard', dict_hubbard['hubbard'])

            output_chi = ArrayData()
            output_chi.set_array('chi0', dict_chi['chi0'])
            output_chi.set_array('chi1', dict_chi['chi1'])

            output_hubbard = ParameterData(dict=dict_hubbard['hubbard_U'])

            output_nodes.append(
                (self.get_linkname_matrices(), output_matrices))
            output_nodes.append((self.get_linkname_hubbard(), output_hubbard))
            output_nodes.append((self.get_linkname_chi(), output_chi))

        return is_success, output_nodes