예제 #1
0
def test_fleurinp_modifier_set_kpointsdata(create_fleurinp):
    """Test if setting a kpoints list to a fleurinp data node works"""
    from aiida.orm import KpointsData

    fleurinp_tmp = create_fleurinp(inpxmlfilefolder)
    fleurinp_tmp.store()  # needed?
    struc = fleurinp_tmp.get_structuredata_ncf()

    kps = KpointsData()
    kps.set_cell(struc.cell)
    kps.pbc = struc.pbc
    kpoints_pos = [[0.0, 0.0, 0.0], [0.0, 0.5, 0.0], [0.5, 0.0, 0.0], [0.5, 0.0, 0.5], [0.5, 0.5, 0.5], [1.0, 1.0, 1.0]]
    kpoints_weight = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0]
    # Fleur renormalizes
    kps.set_kpoints(kpoints_pos, cartesian=False, weights=kpoints_weight)

    kps.store()  # needed, because node has to be loaded...
    #print(fleurinp_tmp)
    fm = FleurinpModifier(fleurinp_tmp)
    fm.set_kpointsdata(kps)

    fm.show(validate=True, display=False)
    fm.freeze()

    # check if kpoint node is input into modification
    # uuid of node show also work
    fm = FleurinpModifier(fleurinp_tmp)
    fm.set_kpointsdata(kps.uuid)
    fm.freeze()
예제 #2
0
    def change_fleurinp(self):
        """
        create a new fleurinp from the old with certain parameters
        """
        # TODO allow change of kpoint mesh?, tria?
        wf_dict = self.ctx.wf_dict

        if self.ctx.scf_needed:
            try:
                fleurin = self.ctx.scf.outputs.fleurinp
            except NotExistent:
                error = 'Fleurinp generated in the SCF calculation is not found.'
                self.control_end_wc(error)
                return self.exit_codes.ERROR_SCF_CALCULATION_FAILED
        else:
            if 'fleurinp' not in self.inputs:
                fleurin = get_fleurinp_from_remote_data(self.inputs.remote)
            else:
                fleurin = self.inputs.fleurinp

        # how can the user say he want to use the given kpoint mesh, ZZ nkpts : False/0
        fleurmode = FleurinpModifier(fleurin)

        fchanges = wf_dict.get('inpxml_changes', [])
        # apply further user dependend changes
        if fchanges:
            try:
                fleurmode.add_task_list(fchanges)
            except (ValueError, TypeError) as exc:
                error = (
                    'ERROR: Changing the inp.xml file failed. Tried to apply inpxml_changes'
                    f', which failed with {exc}. I abort, good luck next time!'
                )
                self.control_end_wc(error)
                return self.exit_codes.ERROR_CHANGING_FLEURINPUT_FAILED

        kpath = wf_dict['kpath']
        explicit = wf_dict['kpoints_explicit']
        distance = wf_dict['kpoints_distance']
        nkpts = wf_dict['kpoints_number']
        listname = wf_dict['klistname']

        if explicit is not None:
            try:
                fleurmode.set_kpointlist(**explicit)
            except (ValueError, TypeError) as exc:
                error = (
                    'ERROR: Changing the inp.xml file failed. Tried to apply kpoints_explicit'
                    f', which failed with {exc}. I abort, good luck next time!'
                )
                self.control_end_wc(error)
                return self.exit_codes.ERROR_CHANGING_FLEURINPUT_FAILED

        if listname is None:
            if wf_dict.get('mode') == 'band':
                listname = 'path-2'

        if nkpts is None and distance is None:
            nkpts = 500

        if 'kpoints' in self.inputs:
            fleurmode.set_kpointsdata(self.inputs.kpoints, switch=True)

        if kpath == 'auto':
            if fleurin.inp_version >= '0.32' and listname is not None:
                fleurmode.switch_kpointset(listname)
        elif isinstance(kpath, dict):
            if fleurin.inp_version < '0.32':
                if distance is not None:
                    raise ValueError(
                        'set_kpath only supports specifying the number of points for the kpoints'
                    )
                fleurmode.set_kpath(kpath, nkpts)
            else:
                raise ValueError(
                    'set_kpath is only supported for inputs up to Max4')
        elif kpath == 'seek':
            #Use aiida functionality
            struc = fleurin.get_structuredata()

            if distance is not None:
                output = get_explicit_kpoints_path(struc,
                                                   reference_distance=distance)
            else:
                output = get_explicit_kpoints_path(struc)
            primitive_struc = output['primitive_structure']

            #check if primitive_structure and input structure are identical:
            maxdiff_cell = sum(
                abs(np.array(primitive_struc.cell) -
                    np.array(struc.cell))).max()

            if maxdiff_cell > 3e-9:
                self.report(f'Error in cell : {maxdiff_cell}')
                self.report(
                    'WARNING: The structure data from the fleurinp is not the primitive structure type, which is mandatory in some cases'
                )

            output['explicit_kpoints'].store()

            fleurmode.set_kpointsdata(output['explicit_kpoints'], switch=True)

        elif kpath == 'skip':
            return
        else:
            #Use ase
            struc = fleurin.get_structuredata()

            path = bandpath(kpath,
                            cell=struc.cell,
                            npoints=nkpts,
                            density=distance)

            special_points = path.special_points

            labels = []
            for label, special_kpoint in special_points.items():
                for index, kpoint in enumerate(path.kpts):
                    if sum(abs(np.array(special_kpoint) -
                               np.array(kpoint))).max() < 1e-12:
                        labels.append((index, label))
            labels = sorted(labels, key=lambda x: x[0])

            kpts = KpointsData()
            kpts.set_cell(struc.cell)
            kpts.pbc = struc.pbc
            weights = np.ones(len(path.kpts)) / len(path.kpts)
            kpts.set_kpoints(kpoints=path.kpts,
                             cartesian=False,
                             weights=weights,
                             labels=labels)

            kpts.store()
            fleurmode.set_kpointsdata(kpts, switch=True)

        sigma = wf_dict['sigma']
        emin = wf_dict['emin']
        emax = wf_dict['emax']

        if fleurin.inp_version < '0.32':
            if wf_dict.get('mode') == 'dos':
                fleurmode.set_inpchanges({'ndir': -1})

        if wf_dict.get('mode') == 'dos':
            change_dict = {
                'dos': True,
                'minEnergy': emin,
                'maxEnergy': emax,
                'sigma': sigma
            }
        else:
            change_dict = {
                'band': True,
                'minEnergy': emin,
                'maxEnergy': emax,
                'sigma': sigma
            }
        fleurmode.set_inpchanges(change_dict)

        try:
            fleurmode.show(display=False, validate=True)
        except etree.DocumentInvalid:
            error = (
                'ERROR: input, user wanted inp.xml changes did not validate')
            self.control_end_wc(error)
            return self.exit_codes.ERROR_INVALID_INPUT_FILE
        except ValueError as exc:
            error = (
                'ERROR: input, user wanted inp.xml changes could not be applied.'
                f'The following error was raised {exc}')
            self.control_end_wc(error)
            return self.exit_codes.ERROR_CHANGING_FLEURINPUT_FAILED

        fleurinp_new = fleurmode.freeze()
        self.ctx.fleurinp_banddos = fleurinp_new