示例#1
0
    def _generate_film_structure():
        """Return a `StructureData` representing bulk silicon."""
        from aiida.orm import StructureData
        from aiida_fleur.common.constants import BOHR_A
        a = 7.497 * BOHR_A
        cell = [[0.7071068 * a, 0.0, 0.0], [0.0, 1.0 * a, 0.0],
                [0.0, 0.0, 0.7071068 * a]]
        structure = StructureData(cell=cell)
        structure.append_atom(position=(0., 0., -1.99285 * BOHR_A),
                              symbols='Fe')
        structure.append_atom(position=(0.5 * 0.7071068 * a, 0.5 * a, 0.0),
                              symbols='Pt')
        structure.append_atom(position=(0., 0., 1.99285 * BOHR_A),
                              symbols='Fe')
        structure.pbc = (True, True, False)

        return structure
示例#2
0
    def get_results_relax(self):
        """
        Generates results of the workchain.
        Creates a new structure data node which is an
        optimized structure.
        """

        if self.ctx.wf_dict.get('relaxation_type', 'atoms') is None:
            input_scf = AttributeDict(
                self.exposed_inputs(FleurScfWorkChain, namespace='scf'))
            if 'structure' in input_scf:
                structure = input_scf.structure
            elif 'fleurinp' in input_scf:
                structure = input_scf.fleurinp.get_structuredata_ncf()
            else:
                pass
            self.ctx.final_structure = structure
            self.ctx.total_energy_last = None  #total_energy
            self.ctx.total_energy_units = None  #total_energy_units
            self.ctx.final_cell = structure.cell
            self.ctx.final_atom_positions = None  #atom_positions
            self.ctx.atomtype_info = None

            return

        try:
            relax_out = self.ctx.scf_res.outputs.last_fleur_calc_output
        except NotExistent:
            return self.exit_codes.ERROR_NO_SCF_OUTPUT

        relax_out = relax_out.get_dict()

        try:
            cell = relax_out['relax_brav_vectors']
            atom_positions = relax_out['relax_atom_positions']
            film = relax_out['film']
            total_energy = relax_out['energy']
            total_energy_units = relax_out['energy_units']
            atomtype_info = relax_out['relax_atomtype_info']
        except KeyError:
            return self.exit_codes.ERROR_NO_RELAX_OUTPUT

        self.ctx.total_energy_last = total_energy
        self.ctx.total_energy_units = total_energy_units
        self.ctx.final_cell = cell
        self.ctx.final_atom_positions = atom_positions
        self.ctx.atomtype_info = atomtype_info

        if film == 'True':
            self.ctx.pbc = (True, True, False)
        else:
            self.ctx.pbc = (True, True, True)

        # we build the structure here, that way we can run an scf afterwards
        # construct it in a way which preserves the species information from the initial input structure
        if self.ctx.final_cell:
            np_cell = np.array(self.ctx.final_cell) * BOHR_A
            structure = StructureData(cell=np_cell.tolist())
            #self.report('############ {}'.format(atomtype_info))
            for i, atom in enumerate(self.ctx.final_atom_positions):
                species_name = atomtype_info[i][0]
                element = atomtype_info[i][1]
                np_pos = np.array(atom)
                pos_abs = np_pos @ np_cell
                if self.ctx.pbc == (True, True, True):
                    structure.append_atom(position=(pos_abs[0], pos_abs[1],
                                                    pos_abs[2]),
                                          symbols=element,
                                          name=species_name)
                else:  # assume z-direction is orthogonal to xy
                    structure.append_atom(position=(pos_abs[0], pos_abs[1],
                                                    atom[3] * BOHR_A),
                                          symbols=element,
                                          name=species_name)

            structure.pbc = self.ctx.pbc
            self.ctx.final_structure = structure
示例#3
0
def test_x_and_bunchatom_input(
    aiida_profile,
    fixture_sandbox,
    generate_calc_job,
    fixture_code,
):
    """Test that plugin can deal (ignores) with other StructureData features

    Currently we assume atoms, deal with vacancies, i.e we leave them out
    ignore the x element. This is important for interoperability with kkr

    # TODO often we do natoms= len(n.sites), which would be false in the case of vacancies.
    """
    from aiida.orm import StructureData

    struc_Fe7Nb = StructureData()
    struc_Fe7Nb.cell = [[3.3168796764431, 0.0, 0.0],
                        [1.6584398382215, 2.3453881115923, 0.0],
                        [0.0, 0.0, 13.349076054836]]
    struc_Fe7Nb.pbc = (True, True, False)
    elements = ['X', 'X', 'X', 'Fe', 'Nb', 'Nb']
    positions = [[0.0, 0.0, 1.1726940557829],
                 [1.6584398382215, 0.0, 3.5180821673487],
                 [0.0, 0.0, 5.8634702789145],
                 [1.6584398382215, 0.0, 8.2088583904803],
                 [0.0, 0.0, 10.096376717551],
                 [1.6584398382215, 0.0, 12.46832205832]]
    for el, pos in zip(elements, positions):
        struc_Fe7Nb.append_atom(symbols=[el], position=pos)

    entry_point_name = 'fleur.inpgen'

    parameters = {}

    inputs = {
        'code': fixture_code(entry_point_name),
        'structure': struc_Fe7Nb,
        'metadata': {
            'options': {
                'resources': {
                    'num_machines': 1
                },
                'max_wallclock_seconds': int(100),
                'withmpi': False
            }
        }
    }

    calc_info = generate_calc_job(fixture_sandbox, entry_point_name, inputs)
    codes_info = calc_info.codes_info
    cmdline_params = ['+all', '-explicit', '-f', 'aiida.in']
    local_copy_list = []
    retrieve_list = [
        'inp.xml', 'out', 'shell.out', 'out.error', 'struct.xsf', 'aiida.in'
    ]
    retrieve_temporary_list = []

    # Check the attributes of the returned `CalcInfo`
    assert isinstance(calc_info, datastructures.CalcInfo)
    assert sorted(calc_info.retrieve_list) == sorted(retrieve_list)

    with fixture_sandbox.open('aiida.in') as handle:
        input_written = handle.read()

    print(input_written)
    assert '   3\n' in input_written  # test for natoms

    # Test not none of the vacany elements was written into the input file
    for line in input_written.split('\n'):
        assert 'X' not in line
        assert ' 0 ' not in line
示例#4
0
    def test_fleur_mae_FePt_film(self, run_with_cache, fleur_local_code,
                                 inpgen_local_code):
        """
        full example using mae workflow with FePt film structure as input.
        """
        from aiida.orm import Code, load_node, Dict, StructureData

        options = Dict(
            dict={
                'resources': {
                    'num_machines': 1,
                    'num_mpiprocs_per_machine': 1
                },
                'max_wallclock_seconds': 60 * 60,
                'queue_name': '',
                'custom_scheduler_commands': ''
            })

        wf_para_scf = {
            'fleur_runmax': 2,
            'itmax_per_run': 120,
            'density_converged': 0.4,
            'serial': False,
            'mode': 'density'
        }

        wf_para_scf = Dict(dict=wf_para_scf)

        wf_para = Dict(
            dict={
                'sqa_ref': [0.7, 0.7],
                'use_soc_ref': False,
                'sqas_theta': [0.0, 1.57079, 1.57079],
                'sqas_phi': [0.0, 0.0, 1.57079],
                'serial': False,
                'soc_off': [],
                'inpxml_changes': [],
            })

        bohr_a_0 = 0.52917721092  # A
        a = 7.497 * bohr_a_0
        cell = [[0.7071068 * a, 0.0, 0.0], [0.0, 1.0 * a, 0.0],
                [0.0, 0.0, 0.7071068 * a]]
        structure = StructureData(cell=cell)
        structure.append_atom(position=(0.0, 0.0, -1.99285 * bohr_a_0),
                              symbols='Fe',
                              name='Fe123')
        structure.append_atom(position=(0.5 * 0.7071068 * a, 0.5 * a, 0.0),
                              symbols='Pt')
        structure.append_atom(position=(0., 0., 2.65059 * bohr_a_0),
                              symbols='Pt')
        structure.pbc = (True, True, False)

        parameters = Dict(
            dict={
                'atom': {
                    'element': 'Pt',
                    'lmax': 6
                },
                'atom2': {
                    'element': 'Fe',
                    'lmax': 6,
                },
                'comp': {
                    'kmax': 3.2,
                },
                'kpt': {
                    'div1': 8,  #20,
                    'div2': 12,  #24,
                    'div3': 1
                }
            })

        FleurCode = fleur_local_code
        InpgenCode = inpgen_local_code

        inputs = {
            'scf': {
                'wf_parameters': wf_para_scf,
                'structure': structure,
                'calc_parameters': parameters,
                'options': options,
                'inpgen': InpgenCode,
                'fleur': FleurCode
            },
            'wf_parameters': wf_para,
            'fleur': FleurCode,
            'options': options
        }

        # now run calculation
        out, node = run_with_cache(inputs, process_class=FleurMaeWorkChain)

        print(out)
        print(node)

        assert node.is_finished_ok

        outpara = out.get('out', None)
        assert outpara is not None
        outpara = outpara.get_dict()
        print(outpara)

        # check output
        assert outpara.get('warnings') == []
        assert outpara.get('phi') == [0.0, 0.0, 1.57079]
        assert outpara.get('theta') == [0.1, 1.57079, 1.57079]
        assert outpara.get('is_it_force_theorem')
        assert outpara.get('maes') == [
            0.0039456509729923, 0.0026014085035566, 0.0
        ]
示例#5
0
    def get_structuredata_ncf(self):
        """
        This routine returns an AiiDA Structure Data type produced from the ``inp.xml``
        file. not a calcfunction

        :param self: a FleurinpData instance to be parsed into a StructureData
        :returns: StructureData node, or None
        """
        from aiida.orm import StructureData
        from aiida_fleur.tools.StructureData_util import rel_to_abs, rel_to_abs_f

        # StructureData = DataFactory(‘structure’)
        # Disclaimer: this routine needs some xpath expressions. these are hardcoded here,
        # therefore maintainance might be needed, if you want to circumvent this, you have
        # to get all the paths from somewhere.

        #######
        # all hardcoded xpaths used and attributes names:
        bravaismatrix_bulk_xpath = '/fleurInput/cell/bulkLattice/bravaisMatrix/'
        bravaismatrix_film_xpath = '/fleurInput/cell/filmLattice/bravaisMatrix/'
        species_xpath = '/fleurInput/atomSpecies/species'
        all_atom_groups_xpath = '/fleurInput/atomGroups/atomGroup'

        species_attrib_name = 'name'
        species_attrib_element = 'element'

        row1_tag_name = 'row-1'
        row2_tag_name = 'row-2'
        row3_tag_name = 'row-3'

        atom_group_attrib_species = 'species'
        atom_group_tag_abspos = 'absPos'
        atom_group_tag_relpos = 'relPos'
        atom_group_tag_filmpos = 'filmPos'
        ########

        if 'inp.xml' not in self.files:
            print(
                'cannot get a StructureData because fleurinpdata has no inp.xml file yet'
            )
            # TODO what to do in this case?
            return None

        # read in inpxml

        if self._schema_file_path:  # Schema there, parse with schema
            xmlschema_doc = etree.parse(self._schema_file_path)
            xmlschema = etree.XMLSchema(xmlschema_doc)
            parser = etree.XMLParser(attribute_defaults=True, encoding='utf-8')
            with self.open(path='inp.xml', mode='r') as inpxmlfile:
                tree = etree.parse(inpxmlfile, parser)
            tree.xinclude()
            # remove comments from inp.xml
            comments = tree.xpath('//comment()')
            for c in comments:
                p = c.getparent()
                p.remove(c)
            if not xmlschema.validate(tree):
                raise ValueError(
                    'Input file is not validated against the schema.')
        else:  # schema not there, parse without
            print('parsing inp.xml without XMLSchema')
            with self.open(path='inp.xml', mode='r') as inpxmlfile:
                tree = etree.parse(inpxmlfile)
            tree.xinclude()
            # remove comments from inp.xml
            comments = tree.xpath('//comment()')
            for c in comments:
                p = c.getparent()
                p.remove(c)
        root = tree.getroot()

        # Fleur uses atomic units, convert to Angstrom
        # get cell matrix from inp.xml
        row1 = root.xpath(bravaismatrix_bulk_xpath +
                          row1_tag_name)  # [0].text.split()
        cell = None

        if row1:  # bulk calculation
            row1 = row1[0].text.split()
            row2 = root.xpath(bravaismatrix_bulk_xpath +
                              row2_tag_name)[0].text.split()
            row3 = root.xpath(bravaismatrix_bulk_xpath +
                              row3_tag_name)[0].text.split()
            # TODO? allow math?
            for i, cor in enumerate(row1):
                row1[i] = float(cor) * BOHR_A
            for i, cor in enumerate(row2):
                row2[i] = float(cor) * BOHR_A
            for i, cor in enumerate(row3):
                row3[i] = float(cor) * BOHR_A

            cell = [row1, row2, row3]
            # create new structure Node
            struc = StructureData(cell=cell)
            struc.pbc = [True, True, True]

        elif root.xpath(bravaismatrix_film_xpath + row1_tag_name):
            # film calculation
            row1 = root.xpath(bravaismatrix_film_xpath +
                              row1_tag_name)[0].text.split()
            row2 = root.xpath(bravaismatrix_film_xpath +
                              row2_tag_name)[0].text.split()
            row3 = root.xpath(bravaismatrix_film_xpath +
                              row3_tag_name)[0].text.split()
            for i, cor in enumerate(row1):
                row1[i] = float(cor) * BOHR_A
            for i, cor in enumerate(row2):
                row2[i] = float(cor) * BOHR_A
            for i, cor in enumerate(row3):
                row3[i] = float(cor) * BOHR_A
            # row3 = [0, 0, 0]#? TODO:what has it to be in this case?
            cell = [row1, row2, row3]
            struc = StructureData(cell=cell)
            struc.pbc = [True, True, False]

        if cell is None:
            print('Could not extract Bravias matrix out of inp.xml. Is the '
                  'Bravias matrix explicitly given? i.e Latnam definition '
                  'not supported.')
            return None

        # get species for atom kinds
        #species = root.xpath(species_xpath)
        species_name = root.xpath(species_xpath + '/@' + species_attrib_name)
        species_element = root.xpath(species_xpath + '/@' +
                                     species_attrib_element)
        # alternativ: loop over species and species.get(species_attrib_name)

        # save species info in a dict
        species_dict = {}
        for i, spec in enumerate(species_name):
            species_dict[spec] = {species_attrib_element: species_element[i]}

        # Now we have to get all atomgroups, look what their species is and
        # their positions are.
        # Then we append them to the new structureData

        all_atom_groups = root.xpath(all_atom_groups_xpath)

        for atom_group in all_atom_groups:
            current_species = atom_group.get(atom_group_attrib_species)

            group_atom_positions_abs = atom_group.xpath(atom_group_tag_abspos)
            group_atom_positions_rel = atom_group.xpath(atom_group_tag_relpos)
            group_atom_positions_film = atom_group.xpath(
                atom_group_tag_filmpos)

            if group_atom_positions_abs:  # we have absolute positions
                for atom in group_atom_positions_abs:
                    postion_a = atom.text.split()
                    # allow for math *, /
                    for i, pos in enumerate(postion_a):
                        if '/' in pos:
                            temppos = pos.split('/')
                            postion_a[i] = float(temppos[0]) / float(
                                temppos[1])
                        elif '*' in pos:
                            temppos = pos.split('*')
                            postion_a[i] = float(temppos[0]) * float(
                                temppos[1])
                        else:
                            postion_a[i] = float(pos)
                        postion_a[i] = postion_a[i] * BOHR_A
                    # append atom to StructureData
                    struc.append_atom(position=postion_a,
                                      symbols=species_dict[current_species]
                                      [species_attrib_element])

            elif group_atom_positions_rel:  # we have relative positions
                # TODO: check if film or 1D calc, because this is not allowed! I guess
                for atom in group_atom_positions_rel:
                    postion_r = atom.text.split()
                    # allow for math * /
                    for i, pos in enumerate(postion_r):
                        if '/' in pos:
                            temppos = pos.split('/')
                            postion_r[i] = float(temppos[0]) / float(
                                temppos[1])
                        elif '*' in pos:
                            temppos = pos.split('*')
                            postion_r[i] = float(temppos[0]) * float(
                                temppos[1])
                        else:
                            postion_r[i] = float(pos)

                    # now transform to absolute Positions
                    new_abs_pos = rel_to_abs(postion_r, cell)

                    # append atom to StructureData
                    struc.append_atom(position=new_abs_pos,
                                      symbols=species_dict[current_species]
                                      [species_attrib_element])

            elif group_atom_positions_film:  # Do we support mixture always, or only in film case?
                # either support or throw error
                for atom in group_atom_positions_film:
                    # film pos are rel rel abs, therefore only transform first two coordinates
                    postion_f = atom.text.split()
                    # allow for math * /
                    for i, pos in enumerate(postion_f):
                        if '/' in pos:
                            temppos = pos.split('/')
                            postion_f[i] = float(temppos[0]) / float(
                                temppos[1])
                        elif '*' in postion_f[i]:
                            temppos = pos.split('*')
                            postion_f[i] = float(temppos[0]) * float(
                                temppos[1])
                        else:
                            postion_f[i] = float(pos)
                    # now transform to absolute Positions
                    postion_f[2] = postion_f[2] * BOHR_A
                    new_abs_pos = rel_to_abs_f(postion_f, cell)
                    # append atom to StructureData
                    struc.append_atom(position=new_abs_pos,
                                      symbols=species_dict[current_species]
                                      [species_attrib_element])
            else:
                # TODO throw error
                print('I should never get here, 1D not supported yet, '
                      'I only know relPos, absPos, filmPos')
                # TODO throw error
        # TODO DATA-DATA links are not wanted, you might want to use a cf instead
        #struc.add_link_from(self, label='self.structure', link_type=LinkType.CREATE)
        # label='self.structure'
        # return {label : struc}
        return struc