示例#1
0
    def test_update_params_wf(self):
        from aiida_kkr.tools.common_workfunctions import update_params_wf
        from aiida_kkr.tools.kkr_params import kkrparams
        from aiida.orm import DataFactory
        ParameterData = DataFactory('parameter')

        k = kkrparams(LMAX=2)
        node1 = ParameterData(dict=k.values)
        node2 = ParameterData(
            dict={
                'nodename': 'my_changed_name',
                'nodedesc': 'My description text',
                'EMIN': -1,
                'RMAX': 10.
            })

        unode = update_params_wf(node1, node1)
        assert unode == node1

        unode = update_params_wf(node1, node2)

        d0 = node1.get_dict()
        for i in d0.keys():
            if d0[i] is None:
                d0.pop(i)

        d1 = unode.get_dict()
        for i in d1.keys():
            if d1[i] is None:
                d1.pop(i)

        l_identical, l_diff = [], []
        for i in d0.keys():
            if i in d1.keys():
                l_identical.append([i, d0[i], d1[i]])
            else:
                l_diff.append([0, i, d0[i]])
        for i in d1.keys():
            if i not in d0.keys():
                l_diff.append([1, i, d1[i]])

        assert l_identical == [[u'LMAX', 2, 2]]
        assert l_diff == [[1, u'RMAX', 10.0], [1, u'EMIN', -1.0]]
        return node1, node2, unode
示例#2
0
    def check_voro_out(self):
        """
        check outout of vorostart workflow and create input for rest of calculations (rmtcore setting etc.)
        """
        self.report('INFO: checking voronoi output')
        # get output of kkr_startpot
        out_wc = self.ctx.kkr_startpot
        try:
            res = out_wc.outputs.results_vorostart_wc
            voro_params = out_wc.outputs.last_params_voronoi
            smallest_voro_remote = out_wc.outputs.last_voronoi_remote
            smallest_voro_results = out_wc.outputs.last_voronoi_results
            vorostart_success = res.get_dict()['successful']
        except:
            vorostart_success = False

        if vorostart_success:
            rmt = []
            radii = smallest_voro_results.get_dict()['radii_atoms_group']
            for rad_iatom in radii:
                if 'rmt0' in list(rad_iatom.keys()):
                    rmt.append(rad_iatom['rmt0'])
            rmtcore_min = array(rmt) * smallest_voro_results.get_dict().get(
                'alat')  # needs to be mutiplied by alat in atomic units!
            self.report('INFO: extracted rmtcore_min ({})'.format(rmtcore_min))
        else:
            return self.exit_codes.ERROR_VOROSTART_NOT_SUCCESSFUL

        # update parameter node with rmtcore setting
        voro_params_with_rmtcore = kkrparams(**voro_params.get_dict())
        voro_params_with_rmtcore.set_value('<RMTCORE>', rmtcore_min)
        voro_params_with_rmtcore_dict = voro_params_with_rmtcore.get_dict()
        voro_params_with_rmtcore = update_params_wf(
            voro_params, Dict(dict=voro_params_with_rmtcore_dict))
        self.report(
            'INFO: updated kkr_parameters inlcuding RMTCORE setting (uuid={})'.
            format(voro_params_with_rmtcore.uuid))

        # store links to context
        self.ctx.params_kkr_run = voro_params_with_rmtcore
        self.ctx.smallest_voro_remote = smallest_voro_remote
示例#3
0
    def run_voronoi(self):
        """
        run voronoi calculation with parameters from input
        """
        # incerement iteration counter
        self.ctx.iter += 1

        # increase some parameters
        if self.ctx.iter > 1:
            # check if cluster size is actually the reason for failure
            if self.ctx.dos_check_fail_reason not in [
                    'EMIN too high', 'core state in contour',
                    'core state too close'
            ]:
                self.ctx.r_cls = self.ctx.r_cls * self.ctx.fac_clsincrease

        structure = self.inputs.structure
        self.ctx.formula = structure.get_formula()
        label = 'voronoi calculation step {}'.format(self.ctx.iter)
        description = '{} vornoi on {}'.format(self.ctx.description_wf,
                                               self.ctx.formula)

        voronoicode = self.inputs.voronoi

        # get valid KKR parameters
        if self.ctx.iter > 1:
            # take value from last run to continue
            params = self.ctx.last_params
            first_iter = False
        else:
            # used input or defaults in first iteration
            first_iter = True
            if 'calc_parameters' in self.inputs:
                params = self.inputs.calc_parameters
            else:
                kkrparams_default = kkrparams()
                para_version = self._kkr_default_params[1]
                for key, val in self._kkr_default_params[0].items():
                    kkrparams_default.set_value(key, val, silent=True)
                # create Dict node
                params = Dict(dict=kkrparams_default.get_dict())
                params.label = 'Defaults for KKR parameter node'
                params.description = 'defaults as defined in kkrparams of version {}'.format(
                    para_version)
            #  set last_params accordingly (used below for provenance tracking)
            self.ctx.last_params = params

        self.report("INFO: input params: {}".format(params.get_dict()))

        # check if RCLUSTZ is set and use setting from wf_parameters instead (calls update_params_wf to keep track of provenance)
        updated_params = False
        update_list = []
        kkr_para = kkrparams()
        for key, val in params.get_dict().items():
            kkr_para.set_value(key, val, silent=True)
        set_vals = kkr_para.get_set_values()
        set_vals = [keyvalpair[0] for keyvalpair in set_vals]
        default_values = kkrparams.get_KKRcalc_parameter_defaults()[0]
        if 'RCLUSTZ' in set_vals:
            rcls_input = params.get_dict()['RCLUSTZ']
            # set r_cls by default or from input in first iteration
            if self.ctx.r_cls < rcls_input and first_iter:
                self.ctx.r_cls = rcls_input
                updated_params = True
                update_list.append('RCLUSTZ')
            elif self.ctx.r_cls > rcls_input:
                # change rcls with iterations
                updated_params = True
                update_list.append('RCLUSTZ')
        else:
            updated_params = True
            update_list.append('RCLUSTZ')
        # in case of dos check verify that RMAX, GMAX are set and use setting from wf_parameters otherwise
        if 'RMAX' in set_vals:
            update_list.append('RMAX')
            rmax_input = params.get_dict()['RMAX']
        elif self.ctx.check_dos:  # add only if doscheck is done
            updated_params = True
            update_list.append('RMAX')
            rmax_input = kkrparams.default_values.get('RMAX')
        if 'GMAX' in set_vals:
            update_list.append('GMAX')
            gmax_input = params.get_dict()['GMAX']
        elif self.ctx.check_dos:  # add only if doscheck is done
            updated_params = True
            update_list.append('GMAX')
            gmax_input = kkrparams.default_values.get('GMAX')
        # check if any mandatory keys are not set and set them with the default values if missing in input parameters
        for key, value in default_values.items():
            if key not in update_list and key not in set_vals:
                self.report("INFO: setting {} to default value {}".format(
                    key, value))
                kkr_para.set_value(key, value)

        # check if Fermi lavel should be set with input value
        if self.ctx.ef_set is not None:
            update_list.append('ef_set')

        # check if emin should be changed:
        skip_voro = False
        if self.ctx.iter > 1:
            if (self.ctx.dos_check_fail_reason == 'EMIN too high' or
                    self.ctx.dos_check_fail_reason == 'core state too close'):
                # decrease emin  by self.ctx.delta_e
                emin_old = self.ctx.dos_params_dict['emin']
                eV2Ry = 1. / get_Ry2eV()
                emin_new = emin_old - self.ctx.delta_e * eV2Ry
                self.ctx.dos_params_dict['emin'] = emin_new
                updated_params = True
                update_list.append('EMIN')
                skip_voro = True

        # store updated nodes (also used via last_params in kkr_scf_wc)
        if updated_params:
            # set values that are updated
            if 'RCLUSTZ' in update_list:
                kkr_para.set_value('RCLUSTZ', self.ctx.r_cls)
                self.report("INFO: setting RCLUSTZ to {}".format(
                    self.ctx.r_cls))
            if 'EMIN' in update_list:
                kkr_para.set_value('EMIN', emin_new)
                self.report("INFO: setting EMIN to {}".format(emin_new))
            if 'RMAX' in update_list:
                kkr_para.set_value('RMAX', rmax_input)
                self.report(
                    "INFO: setting RMAX to {} (needed for DOS check with KKRcode)"
                    .format(rmax_input))
            if 'GMAX' in update_list:
                kkr_para.set_value('GMAX', gmax_input)
                self.report(
                    "INFO: setting GMAX to {} (needed for DOS check with KKRcode)"
                    .format(gmax_input))
            if 'ef_set' in update_list:
                kkr_para.set_value('EFSET', self.ctx.ef_set)
                self.report(
                    "INFO: setting Fermi level of stating potential to {}".
                    format(self.ctx.ef_set))

            updatenode = Dict(dict=kkr_para.get_dict())
            updatenode.description = 'changed values: {}'.format(update_list)
            if first_iter:
                updatenode.label = 'initial params from wf input'
                # used workfunction for provenance tracking if parameters have been changed
                params = update_params_wf(self.ctx.last_params, updatenode)
                self.ctx.last_params = params
            else:
                updatenode.label = 'updated params: {}'.format(update_list)
                # also keep track of last voronoi output if that has been used
                voro_out = self.ctx.voro_calc.outputs.output_parameters
                params = update_voro_input(self.ctx.last_params, updatenode,
                                           voro_out)
                self.ctx.last_params = params

        # run voronoi step
        if not skip_voro:
            options = {
                'queue_name': self.ctx.queue,
                'resources': self.ctx.resources,
                'max_wallclock_seconds': self.ctx.max_wallclock_seconds,
                'custom_scheduler_commands': self.ctx.custom_scheduler_commands
            }

            builder = get_inputs_voronoi(voronoicode,
                                         structure,
                                         options,
                                         label,
                                         description,
                                         params=params)
            if 'startpot_overwrite' in self.inputs:
                builder.potential_overwrite = self.inputs.startpot_overwrite
            self.report('INFO: run voronoi step {}'.format(self.ctx.iter))
            future = self.submit(builder)

            # return remote_voro (passed to dos calculation as input)
            return ToContext(voro_calc=future)
        else:
            self.report(
                "INFO: skipping voronoi calculation (do DOS run with different emin only)"
            )
示例#4
0
    def _prepare_for_submission(self, tempfolder, inputdict):
        """
        Create input files.

            :param tempfolder: aiida.common.folders.Folder subclass where
                the plugin should put all its files.
            :param inputdict: dictionary of the input nodes as they would
                be returned by get_inputs_dict
        """

        has_parent = False
        local_copy_list = []
        # Check inputdict
        try:
            parameters = inputdict.pop(self.get_linkname('parameters'))
        except KeyError:
            raise InputValidationError(
                "No parameters specified for this calculation")
        if not isinstance(parameters, ParameterData):
            raise InputValidationError("parameters not of type ParameterData")

        try:
            imp_info = inputdict.pop(self.get_linkname('impurity_info'))
            found_imp_info = True
        except KeyError:
            imp_info = None
            found_imp_info = False
        if found_imp_info and not isinstance(imp_info, ParameterData):
            raise InputValidationError(
                "impurity_info not of type ParameterData")

        try:
            code = inputdict.pop(self.get_linkname('code'))
        except KeyError:
            raise InputValidationError(
                "No code specified for this calculation")

        # get qdos inputs
        try:
            kpath = inputdict.pop(self.get_linkname('kpoints'))
            found_kpath = True
        except KeyError:
            found_kpath = False

        try:
            parent_calc_folder = inputdict.pop(
                self.get_linkname('parent_folder'))
        except KeyError:
            raise InputValidationError(
                "Voronoi or previous KKR files needed for KKR calculation, "
                "you need to provide a Parent Folder/RemoteData node.")

        #TODO deal with data from folder data if calculation is continued on a different machine
        if not isinstance(parent_calc_folder, RemoteData):
            raise InputValidationError(
                "parent_calc_folder must be of type RemoteData")

        # extract parent calculation
        parent_calcs = parent_calc_folder.get_inputs(node_type=JobCalculation)
        n_parents = len(parent_calcs)
        if n_parents != 1:
            raise UniquenessError(
                "Input RemoteData is child of {} "
                "calculation{}, while it should have a single parent"
                "".format(n_parents, "" if n_parents == 0 else "s"))
            parent_calc = parent_calcs[0]
            has_parent = True
        if n_parents == 1:
            parent_calc = parent_calcs[0]
            has_parent = True

        # check if parent is either Voronoi or previous KKR calculation
        self._check_valid_parent(parent_calc)

        # extract parent input parameter dict for following check
        try:
            parent_inp_dict = parent_calc.inp.parameters.get_dict()
        except:
            self.logger.error(
                "Failed trying to find input parameter of parent {}".format(
                    parent_calc))
            raise InputValidationError(
                "No parameter node found of parent calculation.")

        # check if no keys are illegally overwritten (i.e. compare with keys in self._do_never_modify)
        for key in parameters.get_dict().keys():
            value = parameters.get_dict()[key]
            #self.logger.info("Checking {} {}".format(key, value))
            if not value is None:
                if key in self._do_never_modify:
                    oldvalue = parent_inp_dict[key]
                    if oldvalue is None and key in __kkr_default_params__:
                        oldvalue = __kkr_default_params__.get(key)
                    if value != oldvalue:
                        self.logger.error(
                            "You are trying to set keyword {} = {} but this is not allowed since the structure would be modified. Please use a suitable workfunction instead."
                            .format(key, value))
                        raise InputValidationError(
                            "You are trying to modify a keyword that is not allowed to be changed! (key={}, oldvalue={}, newvalue={})"
                            .format(key, oldvalue, value))

        #TODO check for remote folder (starting from folder data not implemented yet)
        # if voronoi calc check if folder from db given, or get folder from rep.
        # Parent calc does not has to be on the same computer.
        # so far we copy every thing from local computer ggf if kkr we want to copy remotely

        # get StructureData node from Parent if Voronoi
        structure = None
        self.logger.info(
            "KkrCalculation: Get structure node from voronoi parent")
        if isinstance(parent_calc, VoronoiCalculation):
            self.logger.info("KkrCalculation: Parent is Voronoi calculation")
            try:
                structure, voro_parent = VoronoiCalculation.find_parent_structure(
                    parent_calc)
            except:
                self.logger.error(
                    'KkrCalculation: Could not get structure from Voronoi parent.'
                )
                raise ValidationError("Cound not find structure node")
        elif isinstance(parent_calc, KkrCalculation):
            self.logger.info("KkrCalculation: Parent is KKR calculation")
            try:
                self.logger.info(
                    'KkrCalculation: extract structure from KKR parent')
                structure, voro_parent = VoronoiCalculation.find_parent_structure(
                    parent_calc)
            except:
                self.logger.error('Could not get structure from parent.')
                raise ValidationError(
                    'Cound not find structure node starting from parent {}'.
                    format(parent_calc))
        else:
            self.logger.error(
                "KkrCalculation: Parent is neither Voronoi nor KKR calculation!"
            )
            raise ValidationError('Cound not find structure node')

        if inputdict:
            self.logger.error(
                'KkrCalculation: Unknown inputs for structure lookup')
            raise ValidationError("Unknown inputs")

        # for VCA: check if input structure and parameter node define VCA structure
        vca_structure = vca_check(structure, parameters)

        ###################################

        # prepare scoef file if impurity_info was given
        write_scoef = False
        runopt = parameters.get_dict().get('RUNOPT', None)
        kkrflex_opt = False
        if runopt is not None:
            if 'KKRFLEX' in runopt:
                kkrflex_opt = True
        if kkrflex_opt:
            write_scoef = True
        elif found_imp_info:
            self.logger.info(
                'Found impurity_info in inputs of the calculation, automatically add runopt KKRFLEX'
            )
            write_scoef = True
            runopt = parameters.get_dict().get('RUNOPT', [])
            runopt.append('KKRFLEX')
            parameters = update_params_wf(
                parameters,
                ParameterData(
                    dict={
                        'RUNOPT': runopt,
                        'nodename': 'update_KKRFLEX',
                        'nodedesc': 'Update Parameter node with KKRFLEX runopt'
                    }))
        if found_imp_info and write_scoef:
            scoef_filename = os.path.join(tempfolder.get_abs_path(''),
                                          self._SCOEF)
            imp_info_dict = imp_info.get_dict()
            Rcut = imp_info_dict.get('Rcut', None)
            hcut = imp_info_dict.get('hcut', -1.)
            cylinder_orient = imp_info_dict.get('cylinder_orient',
                                                [0., 0., 1.])
            ilayer_center = imp_info_dict.get('ilayer_center', 0)
            for i in range(len(cylinder_orient)):
                try:
                    len(cylinder_orient[i])
                    vec_shape = False
                except TypeError:
                    vec_shape = True
            if ilayer_center > len(structure.sites) - 1:
                raise IndexError(
                    'Index of the reference site is out of range! Possible values: 0 to {}.'
                    .format(len(structure.sites) - 1))
            elif Rcut < 0:
                raise ValueError('Cutoff radius has to be positive!')
            elif vec_shape == False or len(cylinder_orient) != 3:
                raise TypeError(
                    'Input orientation vector ({}) has the wrong shape! It needs to be a 3D-vector!'
                    .format(cylinder_orient))
            else:
                print('Input parameters for make_scoef read in correctly!')
                make_scoef(structure, Rcut, scoef_filename, hcut,
                           cylinder_orient, ilayer_center)
        elif write_scoef:
            self.logger.info(
                'Need to write scoef file but no impurity_info given!')
            raise ValidationError(
                'Found RUNOPT KKRFLEX but no impurity_info in inputs')

        # Check for 2D case
        twoDimcheck, msg = check_2Dinput_consistency(structure, parameters)
        if not twoDimcheck:
            raise InputValidationError(msg)

        # set shapes array either from parent voronoi run or read from inputcard in kkrimporter calculation
        if parent_calc.get_parser_name() != 'kkr.kkrimporterparser':
            # get shapes array from voronoi parent
            shapes = voro_parent.res.shapes
        else:
            # extract shapes from input parameters node constructed by kkrimporter calculation
            shapes = voro_parent.inp.parameters.get_dict().get('<SHAPE>')

        #
        use_alat_input = parameters.get_dict().get('use_input_alat', False)

        # qdos option, ensure low T, E-contour, qdos run option and write qvec.dat file
        if found_kpath:
            # check qdos settings
            change_values = []
            runopt = parameters.get_dict().get('RUNOPT')
            if runopt is None: runopt = []
            runopt = [i.strip() for i in runopt]
            if 'qdos' not in runopt:
                runopt.append('qdos')
                change_values.append(['RUNOPT', runopt])
            tempr = parameters.get_dict().get('TEMPR')
            if tempr is None or tempr > 100.:
                change_values.append(['TEMPR', 50.])
            N1 = parameters.get_dict().get('TEMPR')
            if N1 is None or N1 > 0:
                change_values.append(['NPT1', 0])
            N2 = parameters.get_dict().get('NPT2')
            if N2 is None:
                change_values.append(['NPT2', 100])
            N3 = parameters.get_dict().get('NPT3')
            if N3 is None or N3 > 0.:
                change_values.append(['NPT3', 0])
            NPOL = parameters.get_dict().get('NPOL')
            if NPOL is None or NPOL > 0.:
                change_values.append(['NPOL', 0])
            if change_values != []:
                new_params = {
                    'nodename':
                    'changed_params_qdos',
                    'nodedesc':
                    'Changed parameters to mathc qdos mode. Changed values: {}'
                    .format(change_values)
                }
                for key, val in change_values:
                    new_params[key] = val
                new_params_node = ParameterData(dict=new_params)
                parameters = update_params_wf(parameters, new_params_node)
            # write qvec.dat file
            kpath_array = kpath.get_kpoints()
            # convert automatically to internal units
            if use_alat_input:
                alat = parameters.get_dict().get('ALATBASIS')
            else:
                alat = get_alat_from_bravais(
                    array(structure.cell),
                    is3D=structure.pbc[2]) * get_Ang2aBohr()
            kpath_array = kpath_array * (alat / 2. / pi)
            qvec = ['%i\n' % len(kpath_array)]
            qvec += [
                '%e %e %e\n' % (kpt[0], kpt[1], kpt[2]) for kpt in kpath_array
            ]
            qvecpath = tempfolder.get_abs_path(self._QVEC)
            with open(qvecpath, 'w') as file:
                file.writelines(qvec)

        # Prepare inputcard from Structure and input parameter data
        input_filename = tempfolder.get_abs_path(self._INPUT_FILE_NAME)
        natom, nspin, newsosol = generate_inputcard_from_structure(
            parameters,
            structure,
            input_filename,
            parent_calc,
            shapes=shapes,
            vca_structure=vca_structure,
            use_input_alat=use_alat_input)

        #################
        # Decide what files to copy based on settings to the code (e.g. KKRFLEX option needs scoef)
        if has_parent:
            # copy the right files #TODO check first if file, exists and throw
            # warning, now this will throw an error
            outfolderpath = parent_calc.out.retrieved.folder.abspath
            outfolderpath = os.path.join(outfolderpath, 'path')
            self.logger.info("out folder path {}".format(outfolderpath))

            copylist = []
            if isinstance(parent_calc, KkrCalculation):
                copylist = self._copy_filelist_kkr
                # TODO ggf copy remotely...

            if isinstance(parent_calc, VoronoiCalculation):
                copylist = [parent_calc._SHAPEFUN]
                # copy either overwrite potential or voronoi output potential
                # (voronoi caclualtion retreives only one of the two)
                if parent_calc._POTENTIAL_IN_OVERWRITE in os.listdir(
                        outfolderpath):
                    copylist.append(parent_calc._POTENTIAL_IN_OVERWRITE)
                else:
                    copylist.append(parent_calc._OUT_POTENTIAL_voronoi)

            #change copylist in case the calculation starts from an imported calculation
            if parent_calc.get_parser_name() == 'kkr.kkrimporterparser':
                copylist = []
                if not os.path.exists(
                        os.path.join(outfolderpath, self._OUT_POTENTIAL)):
                    copylist.append(self._POTENTIAL)
                else:
                    copylist.append(self._OUT_POTENTIAL)
                if os.path.exists(os.path.join(outfolderpath, self._SHAPEFUN)):
                    copylist.append(self._SHAPEFUN)

            # create local_copy_list from copylist and change some names automatically
            for file1 in copylist:
                filename = file1
                if (file1 == 'output.pot' or file1 == self._OUT_POTENTIAL
                        or (isinstance(parent_calc, VoronoiCalculation)
                            and file1 == parent_calc._POTENTIAL_IN_OVERWRITE)):
                    filename = self._POTENTIAL
                local_copy_list.append(
                    (os.path.join(outfolderpath,
                                  file1), os.path.join(filename)))

            # for set-ef option:
            ef_set = parameters.get_dict().get('ef_set', None)
            if ef_set is not None:
                print('local copy list before change: {}'.format(
                    local_copy_list))
                print(
                    "found 'ef_set' in parameters: change EF of potential to this value"
                )
                potcopy_info = [
                    i for i in local_copy_list if i[1] == self._POTENTIAL
                ][0]
                with open(potcopy_info[0]) as file:
                    # change potential and copy list
                    local_copy_list.remove(potcopy_info)
                    pot_new_name = tempfolder.get_abs_path(self._POTENTIAL +
                                                           '_new_ef')
                    local_copy_list.append((pot_new_name, self._POTENTIAL))

                    # change potential
                    txt = file.readlines()
                    potstart = []
                    for iline in range(len(txt)):
                        line = txt[iline]
                        if 'exc:' in line:
                            potstart.append(iline)
                    for ipotstart in potstart:
                        tmpline = txt[ipotstart + 3]
                        tmpline = tmpline.split()
                        newline = '%10.5f%20.14f%20.14f\n' % (float(
                            tmpline[0]), ef_set, float(tmpline[-1]))
                        txt[ipotstart + 3] = newline
                    # write new file
                    pot_new_ef = open(pot_new_name, 'w')
                    pot_new_ef.writelines(txt)
                    pot_new_ef.close()

            # TODO different copy lists, depending on the keywors input
            print('local copy list: {}'.format(local_copy_list))
            self.logger.info('local copy list: {}'.format(local_copy_list))

        # Prepare CalcInfo to be returned to aiida
        calcinfo = CalcInfo()
        calcinfo.uuid = self.uuid
        calcinfo.local_copy_list = local_copy_list
        calcinfo.remote_copy_list = []

        # TODO retrieve list needs some logic, retrieve certain files,
        # only if certain input keys are specified....
        calcinfo.retrieve_list = [
            self._DEFAULT_OUTPUT_FILE, self._INPUT_FILE_NAME, self._POTENTIAL,
            self._SHAPEFUN, self._SCOEF, self._NONCO_ANGLES_OUT,
            self._OUT_POTENTIAL, self._OUTPUT_0_INIT, self._OUTPUT_000,
            self._OUTPUT_2, self._OUT_TIMING_000
        ]

        # for special cases add files to retireve list:

        # 1. dos calculation, add *dos* files if NPOL==0
        retrieve_dos_files = False
        print('NPOL in parameter input:', parameters.get_dict()['NPOL'])
        if 'NPOL' in parameters.get_dict().keys():
            if parameters.get_dict()['NPOL'] == 0:
                retrieve_dos_files = True
        if 'TESTOPT' in parameters.get_dict().keys():
            testopts = parameters.get_dict()['TESTOPT']
            if testopts is not None:
                stripped_test_opts = [i.strip() for i in testopts]
                if 'DOS' in stripped_test_opts:
                    retrieve_dos_files = True
        if retrieve_dos_files:
            print('adding files for dos output', self._COMPLEXDOS,
                  self._DOS_ATOM, self._LMDOS)
            add_files = [self._COMPLEXDOS]
            for iatom in range(natom):
                add_files.append(self._DOS_ATOM % (iatom + 1))
                for ispin in range(nspin):
                    add_files.append(
                        (self._LMDOS % (iatom + 1, ispin + 1)).replace(
                            ' ', '0'))
            calcinfo.retrieve_list += add_files

        # 2. KKRFLEX calculation
        retrieve_kkrflex_files = False
        if 'RUNOPT' in parameters.get_dict().keys():
            runopts = parameters.get_dict()['RUNOPT']
            if runopts is not None:
                stripped_run_opts = [i.strip() for i in runopts]
                if 'KKRFLEX' in stripped_run_opts:
                    retrieve_kkrflex_files = True
        if retrieve_kkrflex_files:
            add_files = self._ALL_KKRFLEX_FILES
            print('adding files for KKRFLEX output', add_files)
            calcinfo.retrieve_list += add_files

        # 3. qdos claculation
        retrieve_qdos_files = False
        if 'RUNOPT' in parameters.get_dict().keys():
            runopts = parameters.get_dict()['RUNOPT']
            if runopts is not None:
                stripped_run_opts = [i.strip() for i in runopts]
                if 'qdos' in stripped_run_opts:
                    retrieve_qdos_files = True
        if retrieve_qdos_files:
            print('adding files for qdos output', self._QDOS_ATOM, self._QVEC)
            add_files = [self._QVEC]
            for iatom in range(natom):
                for ispin in range(nspin):
                    add_files.append(
                        (self._QDOS_ATOM % (iatom + 1, ispin + 1)).replace(
                            ' ', '0'))
            calcinfo.retrieve_list += add_files

        codeinfo = CodeInfo()
        codeinfo.cmdline_params = []
        codeinfo.code_uuid = code.uuid
        codeinfo.stdout_name = self._DEFAULT_OUTPUT_FILE
        calcinfo.codes_info = [codeinfo]

        return calcinfo
示例#5
0
    def set_params_dos(self):
        """
        take input parameter node and change to DOS contour according to input from wf_parameter input
        internally calls the update_params work function to keep track of provenance
        """
        params = self.ctx.input_params_KKR
        input_dict = params.get_dict()
        para_check = kkrparams()

        # step 1 try to fill keywords
        try:
            for key, val in input_dict.iteritems():
                para_check.set_value(key, val, silent=True)
        except:
            error = 'ERROR: calc_parameters given are not consistent! Hint: did you give an unknown keyword?'
            self.ctx.errors.append(error)
            self.control_end_wc(error)

        # step 2: check if all mandatory keys are there
        label = ''
        descr = ''
        missing_list = para_check.get_missing_keys(use_aiida=True)
        if missing_list != []:
            kkrdefaults = kkrparams.get_KKRcalc_parameter_defaults()[0]
            kkrdefaults_updated = []
            for key_default, val_default in kkrdefaults.items():
                if key_default in missing_list:
                    para_check.set_value(key_default,
                                         kkrdefaults.get(key_default),
                                         silent=True)
                    kkrdefaults_updated.append(key_default)
                    missing_list.remove(key_default)
            if len(missing_list) > 0:
                error = 'ERROR: calc_parameters misses keys: {}'.format(
                    missing_list)
                self.ctx.errors.append(error)
                self.control_end_wc(error)
            else:
                self.report(
                    'updated KKR parameter node with default values: {}'.
                    format(kkrdefaults_updated))
                label = 'add_defaults_'
                descr = 'added missing default keys, '

        # overwrite energy contour to DOS contour no matter what is in input parameter node.
        # Contour parameter given as input to workflow.
        econt_new = self.ctx.dos_params_dict
        # always overwrite NPOL, N1, N3, thus add these to econt_new
        econt_new['NPOL'] = 0
        econt_new['NPT1'] = 0
        econt_new['NPT3'] = 0
        try:
            for key, val in econt_new.iteritems():
                if key == 'kmesh':
                    key = 'BZDIVIDE'
                elif key == 'nepts':
                    key = 'NPT2'
                elif key == 'emin':
                    key = 'EMIN'
                elif key == 'emax':
                    key = 'EMAX'
                elif key == 'tempr':
                    key = 'TEMPR'
                # set params
                para_check.set_value(key, val, silent=True)
        except:
            error = 'ERROR: dos_params given in wf_params are not valid!'
            self.ctx.errors.append(error)
            self.control_end_wc(error)

        updatenode = ParameterData(dict=para_check.get_dict())
        updatenode.label = label + 'KKRparam_DOS'
        updatenode.description = descr + 'KKR parameter node extracted from parent parameters and wf_parameter input node.'

        paranode_dos = update_params_wf(self.ctx.input_params_KKR, updatenode)
        self.ctx.dos_kkrparams = paranode_dos
示例#6
0
    def run_voroaux(self):
        """
        Perform a voronoi calculation for every impurity charge using the structure
        from the converged KKR host calculation
        """
        # TODO: generalize to multiple impurities

        # collect inputs
        vorocode = self.inputs.voronoi
        kkrcode = self.inputs.kkr
        imp_info = self.inputs.impurity_info
        voro_params = self.ctx.voro_params_dict
        if self.ctx.do_gf_calc:
            self.report('INFO: get converged host remote from inputs to extract structure for Voronoi calculation')
            converged_host_remote = self.inputs.remote_data_host
        else:
            self.report('INFO: get converged host remote from GF_host_calc and graph to extract structure for Voronoi calculation')
            remote_data_gf_node = load_node(self.inputs.remote_data_gf.pk)
            GF_host_calc = remote_data_gf_node.get_incoming(link_label_filter=u'remote_folder').first().node
            converged_host_remote = GF_host_calc.inputs.parent_folder

        # get previous kkr parameters following remote_folder->calc->parameters links
        prev_kkrparams = converged_host_remote.get_incoming(link_label_filter='remote_folder').first().node.get_incoming(link_label_filter='parameters').first().node
        calc_params = prev_kkrparams

        # set Fermi level for auxiliary impurity potential correctly (extract from EF that is used in impurity calc)
        set_efermi = self.get_ef_from_parent()
        self.report('INFO: set Fermi level in jellium starting potential to {}'.format(set_efermi))
        # change voronoi parameters
        updatenode = Dict(dict={'ef_set': set_efermi, 'add_direct': True})
        updatenode.label = 'Added Fermi energy'
        voro_params = update_params_wf(voro_params, updatenode)

        # add or overwrite some parameters (e.g. things that are only used by voronoi)
        calc_params_dict = calc_params.get_dict()
        # add some voronoi specific parameters automatically if found (RMTREF should also set RMTCORE to the same value)
        if '<RMTREF>' in calc_params_dict.keys():
            self.report('INFO: add rmtcore to voro params')
            self.ctx.change_voro_params['<RMTCORE>'] = calc_params_dict['<RMTREF>']
            self.report(self.ctx.change_voro_params)
        changed_params = False
        for key, val in self.ctx.change_voro_params.items():
            if key in ['RUNOPT', 'TESTOPT']:
                opt_old = calc_params_dict.get(key, [])
                if type(val)!=list: val = [val]
                val = opt_old + val
            calc_params_dict[key] = val
            changed_params = True
        if changed_params:
            updatenode = Dict(dict=calc_params_dict)
            updatenode.label = 'Changed params for voroaux: {}'.format(self.ctx.change_voro_params.keys())
            updatenode.description = 'Overwritten voronoi input parameter from kkr_imp_wc input.'
            calc_params = update_params_wf(calc_params, updatenode)

        # find host structure
        structure_host, voro_calc = VoronoiCalculation.find_parent_structure(converged_host_remote)

        # for every impurity, generate a structure and launch the voronoi workflow
        # to get the auxiliary impurity startpotentials
        self.ctx.voro_calcs = {}
        inter_struc = change_struc_imp_aux_wf(structure_host, imp_info)
        sub_label = 'voroaux calc for Zimp: {} in host-struc'.format(imp_info.get_dict().get('Zimp'))
        sub_description = 'Auxiliary voronoi calculation for an impurity with charge '
        sub_description += '{} in the host structure from pid: {}'.format(imp_info.get_dict().get('Zimp'), converged_host_remote.pk)

        builder = kkr_startpot_wc.get_builder()
        builder.metadata.label = sub_label
        builder.metadata.description = sub_description
        builder.structure = inter_struc
        builder.voronoi = vorocode
        builder.kkr = kkrcode
        builder.wf_parameters = voro_params
        builder.calc_parameters = calc_params
        builder.options = Dict(dict=self.ctx.options_params_dict_voronoi)
        future = self.submit(builder)


        tmp_calcname = 'voro_aux_{}'.format(1)
        self.ctx.voro_calcs[tmp_calcname] = future
        self.report('INFO: running voro aux (Zimp= {}, pid: {})'.format(imp_info.get_dict().get('Zimp'), future.pk))

        return ToContext(last_voro_calc=future)
示例#7
0
    def prepare_for_submission(self, tempfolder):
        """
        Create input files.

            :param tempfolder: aiida.common.folders.Folder subclass where
                the plugin should put all its files.
            :param inputdict: dictionary of the input nodes as they would
                be returned by get_inputs_dict
        """

        has_parent = False
        local_copy_list = []

        # get mandatory input nodes
        parameters = self.inputs.parameters
        code = self.inputs.code
        parent_calc_folder = self.inputs.parent_folder

        # now check for optional nodes

        # for GF writeout
        if 'impurity_info' in self.inputs:
            imp_info = self.inputs.impurity_info
            found_imp_info = True
        else:
            imp_info = None
            found_imp_info = False

        # for qdos funcitonality
        if 'kpoints' in self.inputs:
            kpath = self.inputs.kpoints
            found_kpath = True
        else:
            found_kpath = False

        # extract parent calculation
        parent_calcs = parent_calc_folder.get_incoming(node_class=CalcJobNode)
        n_parents = len(parent_calcs.all_link_labels())
        if n_parents != 1:
            raise UniquenessError(
                "Input RemoteData is child of {} "
                "calculation{}, while it should have a single parent"
                "".format(n_parents, "" if n_parents == 0 else "s"))
            # TODO change to exit code
        if n_parents == 1:
            parent_calc = parent_calcs.first().node
            has_parent = True

        # check if parent is either Voronoi or previous KKR calculation
        #self._check_valid_parent(parent_calc)

        # extract parent input parameter dict for following check
        try:
            parent_inp_dict = parent_calc.inputs.parameters.get_dict()
        except:
            self.logger.error(
                "Failed trying to find input parameter of parent {}".format(
                    parent_calc))
            raise InputValidationError(
                "No parameter node found of parent calculation.")

        # check if no keys are illegally overwritten (i.e. compare with keys in self._do_never_modify)
        for key in list(parameters.get_dict().keys()):
            value = parameters.get_dict()[key]
            #self.logger.info("Checking {} {}".format(key, value))
            if not value is None:
                if key in self._do_never_modify:
                    oldvalue = parent_inp_dict[key]
                    if oldvalue is None and key in __kkr_default_params__:
                        oldvalue = __kkr_default_params__.get(key)
                    if value == oldvalue:
                        values_eqivalent = True
                    else:
                        values_eqivalent = False
                        # check if values match up to certain numerical accuracy
                        if type(value) == float:
                            if abs(value - oldvalue) < self._eps:
                                values_eqivalent = True
                        elif type(value) == list or type(value) == ndarray:
                            tmp_value, tmp_oldvalue = array(value).reshape(
                                -1), array(oldvalue).reshape(-1)
                            values_eqivalent_tmp = []
                            for ival in range(len(tmp_value)):
                                if abs(tmp_value[ival] -
                                       tmp_oldvalue[ival]) < self._eps:
                                    values_eqivalent_tmp.append(True)
                                else:
                                    values_eqivalent_tmp.append(False)
                            if all(values_eqivalent_tmp) and len(value) == len(
                                    oldvalue):
                                values_eqivalent = True
                    if not values_eqivalent:
                        self.logger.error(
                            "You are trying to set keyword {} = {} but this is not allowed since the structure would be modified. Please use a suitable workfunction instead."
                            .format(key, value))
                        raise InputValidationError(
                            "You are trying to modify a keyword that is not allowed to be changed! (key={}, oldvalue={}, newvalue={})"
                            .format(key, oldvalue, value))

        #TODO check for remote folder (starting from folder data not implemented yet)
        # if voronoi calc check if folder from db given, or get folder from rep.
        # Parent calc does not has to be on the same computer.
        # so far we copy every thing from local computer ggf if kkr we want to copy remotely

        # get StructureData node from Parent if Voronoi
        structure = None
        self.logger.info(
            "KkrCalculation: Get structure node from voronoi parent")
        try:
            structure, voro_parent = VoronoiCalculation.find_parent_structure(
                parent_calc)
        except:
            self.logger.error(
                'KkrCalculation: Could not get structure from Voronoi parent ({}).'
                .format(parent_calc))
            raise ValidationError(
                "Cound not find structure node from parent {}".format(
                    parent_calc))

        # for VCA: check if input structure and parameter node define VCA structure
        vca_structure = vca_check(structure, parameters)

        ###################################

        # check whether or not the alat from the input parameters are used (this enters as a scaling factor for some parameters)
        use_alat_input = parameters.get_dict().get('use_input_alat', False)

        # prepare scoef file if impurity_info was given
        write_scoef = False
        runopt = parameters.get_dict().get('RUNOPT', None)
        kkrflex_opt = False
        if runopt is not None:
            if 'KKRFLEX' in runopt:
                kkrflex_opt = True
        if kkrflex_opt:
            write_scoef = True
        elif found_imp_info:
            self.logger.info(
                'Found impurity_info in inputs of the calculation, automatically add runopt KKRFLEX'
            )
            write_scoef = True
            runopt = parameters.get_dict().get('RUNOPT', [])
            runopt.append('KKRFLEX')
            parameters = update_params_wf(
                parameters,
                Dict(
                    dict={
                        'RUNOPT': runopt,
                        'nodename': 'update_KKRFLEX',
                        'nodedesc': 'Update Parameter node with KKRFLEX runopt'
                    }))
        if found_imp_info and write_scoef:
            imp_info_dict = imp_info.get_dict()
            Rcut = imp_info_dict.get('Rcut', None)
            hcut = imp_info_dict.get('hcut', -1.)
            cylinder_orient = imp_info_dict.get('cylinder_orient',
                                                [0., 0., 1.])
            ilayer_center = imp_info_dict.get('ilayer_center', 0)
            for i in range(len(cylinder_orient)):
                try:
                    len(cylinder_orient[i])
                    vec_shape = False
                except TypeError:
                    vec_shape = True
            if ilayer_center > len(structure.sites) - 1:
                raise IndexError(
                    'Index of the reference site is out of range! Possible values: 0 to {}.'
                    .format(len(structure.sites) - 1))
            elif Rcut < 0:
                raise ValueError('Cutoff radius has to be positive!')
            elif vec_shape == False or len(cylinder_orient) != 3:
                raise TypeError(
                    'Input orientation vector ({}) has the wrong shape! It needs to be a 3D-vector!'
                    .format(cylinder_orient))
            else:
                print('Input parameters for make_scoef read in correctly!')
                with tempfolder.open(self._SCOEF, 'w') as scoef_file:
                    if use_alat_input:
                        alat_input = parameters.get_dict().get(
                            'ALATBASIS', None) / get_Ang2aBohr()
                        self.logger.info('alat_input is ' + str(alat_input))
                    else:
                        self.logger.info('alat_input is None')
                        alat_input = None
                    make_scoef(structure, Rcut, scoef_file, hcut,
                               cylinder_orient, ilayer_center, alat_input)
        elif write_scoef:
            self.logger.info(
                'Need to write scoef file but no impurity_info given!')
            raise ValidationError(
                'Found RUNOPT KKRFLEX but no impurity_info in inputs')

        # Check for 2D case
        twoDimcheck, msg = check_2Dinput_consistency(structure, parameters)
        if not twoDimcheck:
            raise InputValidationError(msg)

        # set shapes array either from parent voronoi run or read from inputcard in kkrimporter calculation
        if parent_calc.process_label == 'VoronoiCalculation' or parent_calc.process_label == 'KkrCalculation':
            # get shapes array from voronoi parent
            shapes = voro_parent.outputs.output_parameters.get_dict().get(
                'shapes')
        else:
            # extract shapes from input parameters node constructed by kkrimporter calculation
            shapes = voro_parent.inputs.parameters.get_dict().get('<SHAPE>')
        self.logger.info('Extracted shapes: {}'.format(shapes))

        # qdos option, ensure low T, E-contour, qdos run option and write qvec.dat file
        if found_kpath:
            # check qdos settings
            change_values = []
            runopt = parameters.get_dict().get('RUNOPT')
            if runopt is None: runopt = []
            runopt = [i.strip() for i in runopt]
            if 'qdos' not in runopt:
                runopt.append('qdos')
                change_values.append(['RUNOPT', runopt])
            tempr = parameters.get_dict().get('TEMPR')
            if tempr is None or tempr > 100.:
                change_values.append(['TEMPR', 50.])
            N1 = parameters.get_dict().get('NPT1')
            if N1 is None or N1 > 0:
                change_values.append(['NPT1', 0])
            N2 = parameters.get_dict().get('NPT2')
            if N2 is None:
                change_values.append(['NPT2', 100])
            N3 = parameters.get_dict().get('NPT3')
            if N3 is None or N3 > 0.:
                change_values.append(['NPT3', 0])
            NPOL = parameters.get_dict().get('NPOL')
            if NPOL is None or NPOL > 0.:
                change_values.append(['NPOL', 0])
            if change_values != []:
                new_params = {}
                #{'nodename': 'changed_params_qdos', 'nodedesc': 'Changed parameters to mathc qdos mode. Changed values: {}'.format(change_values)}
                for key, val in parameters.get_dict().items():
                    new_params[key] = val
                for key, val in change_values:
                    new_params[key] = val
                new_params_node = Dict(dict=new_params)
                #parameters = update_params_wf(parameters, new_params_node)
                parameters = new_params_node
            # write qvec.dat file
            kpath_array = kpath.get_kpoints(cartesian=True)
            # convert automatically to internal units
            alat = get_alat_from_bravais(
                array(
                    structure.cell), is3D=structure.pbc[2]) * get_Ang2aBohr()
            if use_alat_input:
                alat_input = parameters.get_dict().get('ALATBASIS')
            else:
                alat_input = alat
            kpath_array = kpath_array * (
                alat_input / alat) / get_Ang2aBohr() / (2 * pi / alat)
            # now write file
            qvec = ['%i\n' % len(kpath_array)]
            qvec += [
                '%e %e %e\n' % (kpt[0], kpt[1], kpt[2]) for kpt in kpath_array
            ]
            with tempfolder.open(self._QVEC, 'w') as qvecfile:
                qvecfile.writelines(qvec)

        # Prepare inputcard from Structure and input parameter data
        with tempfolder.open(self._INPUT_FILE_NAME, u'w') as input_file:
            natom, nspin, newsosol, warnings_write_inputcard = generate_inputcard_from_structure(
                parameters,
                structure,
                input_file,
                parent_calc,
                shapes=shapes,
                vca_structure=vca_structure,
                use_input_alat=use_alat_input)

        #################
        # Decide what files to copy based on settings to the code (e.g. KKRFLEX option needs scoef)
        if has_parent:
            # copy the right files #TODO check first if file, exists and throw
            # warning, now this will throw an error
            outfolder = parent_calc.outputs.retrieved

            copylist = []
            if parent_calc.process_class == KkrCalculation:
                copylist = [self._OUT_POTENTIAL]
                # TODO ggf copy remotely from remote node if present ...

            elif parent_calc.process_class == VoronoiCalculation:
                copylist = [parent_calc.process_class._SHAPEFUN]
                # copy either overwrite potential or voronoi output potential
                # (voronoi caclualtion retreives only one of the two)
                if parent_calc.process_class._POTENTIAL_IN_OVERWRITE in outfolder.list_object_names(
                ):
                    copylist.append(
                        parent_calc.process_class._POTENTIAL_IN_OVERWRITE)
                else:
                    copylist.append(
                        parent_calc.process_class._OUT_POTENTIAL_voronoi)

            #change copylist in case the calculation starts from an imported calculation
            else:  #if parent_calc.process_class == KkrImporterCalculation:
                if self._OUT_POTENTIAL in outfolder.list_object_names():
                    copylist.append(self._OUT_POTENTIAL)
                else:
                    copylist.append(self._POTENTIAL)
                if self._SHAPEFUN in outfolder.list_object_names():
                    copylist.append(self._SHAPEFUN)

            # create local_copy_list from copylist and change some names automatically
            for file1 in copylist:
                # deal with special case that file is written to another name
                if (file1 == 'output.pot' or file1 == self._OUT_POTENTIAL or
                    (parent_calc.process_class == VoronoiCalculation and file1
                     == parent_calc.process_class._POTENTIAL_IN_OVERWRITE)):
                    filename = self._POTENTIAL
                else:
                    filename = file1
                # now add to copy list
                local_copy_list.append((outfolder.uuid, file1, filename))

                # add shapefun file from voronoi parent if needed
                if self._SHAPEFUN not in copylist:
                    try:
                        struc, voro_parent = VoronoiCalculation.find_parent_structure(
                            parent_calc)
                    except ValueError:
                        return self.exit_codes.ERROR_NO_SHAPEFUN_FOUND
                    # copy shapefun from retrieved of voro calc
                    voro_retrieved = voro_parent.outputs.retrieved
                    local_copy_list.append(
                        (voro_retrieved.uuid, VoronoiCalculation._SHAPEFUN,
                         self._SHAPEFUN))

            # for set-ef option:
            ef_set = parameters.get_dict().get('ef_set', None)
            if ef_set is not None:
                print('local copy list before change: {}'.format(
                    local_copy_list))
                print(
                    "found 'ef_set' in parameters: change EF of potential to this value"
                )
                potcopy_info = [
                    i for i in local_copy_list if i[2] == self._POTENTIAL
                ][0]
                with load_node(potcopy_info[0]).open(
                        potcopy_info[1]) as potfile:
                    # remove previous output potential from copy list
                    local_copy_list.remove(potcopy_info)
                    # create potential here by readin in old potential and overwriting with changed Fermi energy
                    with tempfolder.open(self._POTENTIAL, 'w') as pot_new_ef:
                        # change potential
                        txt = potfile.readlines()
                        potstart = []
                        for iline in range(len(txt)):
                            line = txt[iline]
                            if 'exc:' in line:
                                potstart.append(iline)
                        for ipotstart in potstart:
                            tmpline = txt[ipotstart + 3]
                            tmpline = tmpline.split()
                            newline = '%10.5f%20.14f%20.14f\n' % (float(
                                tmpline[0]), ef_set, float(tmpline[-1]))
                            txt[ipotstart + 3] = newline
                        # write new file
                        pot_new_ef.writelines(txt)
                    # now this directory contains the updated potential file, thus it is not needed to put it in the local copy list anymore

            # TODO different copy lists, depending on the keywors input
            print('local copy list: {}'.format(local_copy_list))
            self.logger.info('local copy list: {}'.format(local_copy_list))

        # Prepare CalcInfo to be returned to aiida
        calcinfo = CalcInfo()
        calcinfo.uuid = self.uuid
        calcinfo.local_copy_list = local_copy_list
        calcinfo.remote_copy_list = []

        # TODO retrieve list needs some logic, retrieve certain files,
        # only if certain input keys are specified....
        calcinfo.retrieve_list = [
            self._DEFAULT_OUTPUT_FILE, self._INPUT_FILE_NAME, self._SCOEF,
            self._NONCO_ANGLES_OUT, self._OUT_POTENTIAL, self._OUTPUT_0_INIT,
            self._OUTPUT_000, self._OUTPUT_2, self._OUT_TIMING_000
        ]

        # for special cases add files to retireve list:

        # 1. dos calculation, add *dos* files if NPOL==0
        retrieve_dos_files = False
        print('NPOL in parameter input:', parameters.get_dict()['NPOL'])
        if 'NPOL' in list(parameters.get_dict().keys()):
            if parameters.get_dict()['NPOL'] == 0:
                retrieve_dos_files = True
        if 'TESTOPT' in list(parameters.get_dict().keys()):
            testopts = parameters.get_dict()['TESTOPT']
            if testopts is not None:
                stripped_test_opts = [i.strip() for i in testopts]
                if 'DOS' in stripped_test_opts:
                    retrieve_dos_files = True
        if retrieve_dos_files:
            print('adding files for dos output', self._COMPLEXDOS,
                  self._DOS_ATOM, self._LMDOS)
            add_files = [self._COMPLEXDOS]
            for iatom in range(natom):
                add_files.append(self._DOS_ATOM % (iatom + 1))
                for ispin in range(nspin):
                    add_files.append(
                        (self._LMDOS % (iatom + 1, ispin + 1)).replace(
                            ' ', '0'))
            calcinfo.retrieve_list += add_files

        # 2. KKRFLEX calculation
        retrieve_kkrflex_files = False
        if 'RUNOPT' in list(parameters.get_dict().keys()):
            runopts = parameters.get_dict()['RUNOPT']
            if runopts is not None:
                stripped_run_opts = [i.strip() for i in runopts]
                if 'KKRFLEX' in stripped_run_opts:
                    retrieve_kkrflex_files = True
        if retrieve_kkrflex_files:
            add_files = self._ALL_KKRFLEX_FILES
            print('adding files for KKRFLEX output', add_files)
            calcinfo.retrieve_list += add_files

        # 3. qdos claculation
        retrieve_qdos_files = False
        if 'RUNOPT' in list(parameters.get_dict().keys()):
            runopts = parameters.get_dict()['RUNOPT']
            if runopts is not None:
                stripped_run_opts = [i.strip() for i in runopts]
                if 'qdos' in stripped_run_opts:
                    retrieve_qdos_files = True
        if retrieve_qdos_files:
            print('adding files for qdos output', self._QDOS_ATOM, self._QVEC)
            add_files = [self._QVEC]
            for iatom in range(natom):
                for ispin in range(nspin):
                    add_files.append(
                        (self._QDOS_ATOM % (iatom + 1, ispin + 1)).replace(
                            ' ', '0'))
                # retrieve also qdos_sx,y,z files if written out
                add_files.append(
                    (self._QDOS_SX % (iatom + 1)).replace(' ', '0'))
                add_files.append(
                    (self._QDOS_SY % (iatom + 1)).replace(' ', '0'))
                add_files.append(
                    (self._QDOS_SZ % (iatom + 1)).replace(' ', '0'))
            calcinfo.retrieve_list += add_files

        # 4. Jij calculation
        retrieve_Jij_files = False
        if 'RUNOPT' in list(parameters.get_dict().keys()):
            runopts = parameters.get_dict()['RUNOPT']
            if runopts is not None:
                stripped_run_opts = [i.strip() for i in runopts]
                if 'XCPL' in stripped_run_opts:
                    retrieve_Jij_files = True
        if retrieve_Jij_files:
            add_files = [self._SHELLS_DAT] + [
                self._Jij_ATOM % iatom for iatom in range(1, natom + 1)
            ]
            print('adding files for Jij output', add_files)
            calcinfo.retrieve_list += add_files

        codeinfo = CodeInfo()
        codeinfo.cmdline_params = []
        codeinfo.code_uuid = code.uuid
        codeinfo.stdout_name = self._DEFAULT_OUTPUT_FILE
        calcinfo.codes_info = [codeinfo]

        return calcinfo
示例#8
0
    def set_params_dos(self):
        """
        take input parameter node and change to DOS contour according to input from wf_parameter input
        internally calls the update_params work function to keep track of provenance
        """
        params = self.ctx.input_params_KKR
        input_dict = params.get_dict()
        para_check = kkrparams()

        # step 1 try to fill keywords
        try:
            for key, val in input_dict.items():
                para_check.set_value(key, val, silent=True)
        except:
            return self.exit_codes.ERROR_CALC_PARAMETERS_INVALID

        # step 2: check if all mandatory keys are there
        label = ''
        descr = ''
        missing_list = para_check.get_missing_keys(use_aiida=True)
        if missing_list != []:
            kkrdefaults = kkrparams.get_KKRcalc_parameter_defaults()[0]
            kkrdefaults_updated = []
            for key_default, val_default in list(kkrdefaults.items()):
                if key_default in missing_list:
                    para_check.set_value(key_default,
                                         kkrdefaults.get(key_default),
                                         silent=True)
                    kkrdefaults_updated.append(key_default)
                    missing_list.remove(key_default)
            if len(missing_list) > 0:
                self.report('ERROR: calc_parameters misses keys: {}'.format(
                    missing_list))
                return self.exit_codes.ERROR_CALC_PARAMETERS_INCOMPLETE
            else:
                self.report(
                    'updated KKR parameter node with default values: {}'.
                    format(kkrdefaults_updated))
                label = 'add_defaults_'
                descr = 'added missing default keys, '

        # overwrite energy contour to DOS contour no matter what is in input parameter node.
        # Contour parameter given as input to workflow.
        econt_new = self.ctx.dos_params_dict
        # always overwrite NPOL, N1, N3, thus add these to econt_new
        econt_new['NPOL'] = 0
        econt_new['NPT1'] = 0
        econt_new['NPT3'] = 0
        try:
            for key, val in econt_new.items():
                if key == 'kmesh':
                    key = 'BZDIVIDE'
                elif key == 'nepts':
                    key = 'NPT2'
                    # add IEMXD which has to be big enough
                    print('setting IEMXD', val)
                    para_check.set_value('IEMXD', val, silent=True)
                elif key == 'emin':
                    key = 'EMIN'
                elif key == 'emax':
                    key = 'EMAX'
                elif key == 'tempr':
                    key = 'TEMPR'
                # set params
                para_check.set_value(key, val, silent=True)
        except:
            return self.exit_codes.ERROR_DOS_PARAMS_INVALID

        updatenode = Dict(dict=para_check.get_dict())
        updatenode.label = label + 'KKRparam_DOS'
        updatenode.description = descr + 'KKR parameter node extracted from parent parameters and wf_parameter input node.'

        paranode_dos = update_params_wf(self.ctx.input_params_KKR, updatenode)
        self.ctx.dos_kkrparams = paranode_dos
示例#9
0
    def set_params_flex(self):
        """
        Take input parameter node and change to input from wf_parameter and options
        """

        self.report('INFO: setting parameters ...')

        params = self.ctx.input_params_KKR
        input_dict = params.get_dict()
        para_check = kkrparams()

        # step 1: try to fill keywords
        try:
            for key, val in input_dict.items():
                para_check.set_value(key, val, silent=True)
        except:
            return self.exit_codes.ERROR_INVALID_CALC_PARAMETERS

        # step 2: check if all mandatory keys are there
        label = ''
        descr = ''
        missing_list = para_check.get_missing_keys(use_aiida=True)
        if missing_list != []:
            kkrdefaults = kkrparams.get_KKRcalc_parameter_defaults()[0]
            kkrdefaults_updated = []
            for key_default, val_default in list(kkrdefaults.items()):
                if key_default in missing_list:
                    para_check.set_value(key_default,
                                         kkrdefaults.get(key_default),
                                         silent=True)
                    kkrdefaults_updated.append(key_default)
                    missing_list.remove(key_default)
            if len(missing_list) > 0:
                self.report('ERROR: calc_parameters misses keys: {}'.format(
                    missing_list))
                return self.exit_codes.ERROR_CALC_PARAMETERS_INCOMPLETE

            else:
                self.report(
                    'updated KKR parameter node with default values: {}'.
                    format(kkrdefaults_updated))
                label = 'add_defaults_'
                descr = 'added missing default keys, '

        # updatedict contains all things that will be updated with update_params_wf later on
        updatedict = {}

        runopt = para_check.get_dict().get('RUNOPT', None)
        if runopt == None:
            runopt = []

        # overwrite some parameters of the KKR calculation by hand before setting mandatory keys
        if "params_kkr_overwrite" in self.inputs:
            for key, val in self.inputs.params_kkr_overwrite.get_dict().items(
            ):
                if key != runopt:
                    updatedict[key] = val
                else:
                    runopt = val
                self.report(
                    'INFO: overwriting KKR parameter: {} with {} from params_kkr_overwrite input node'
                    .format(key, val))

        runopt = [i.strip() for i in runopt]
        if 'KKRFLEX' not in runopt:
            runopt.append('KKRFLEX')

        updatedict['RUNOPT'] = runopt

        self.report('INFO: RUNOPT set to: {}'.format(runopt))

        if 'wf_parameters' in self.inputs:
            if self.ctx.dos_run:
                for key, val in {
                        'EMIN': self.ctx.dos_params_dict['emin'],
                        'EMAX': self.ctx.dos_params_dict['emax'],
                        'NPT2': self.ctx.dos_params_dict['nepts'],
                        'NPOL': 0,
                        'NPT1': 0,
                        'NPT3': 0,
                        'BZDIVIDE': self.ctx.dos_params_dict['kmesh'],
                        'IEMXD': self.ctx.dos_params_dict['nepts'],
                        'TEMPR': self.ctx.dos_params_dict['tempr']
                }.items():
                    updatedict[key] = val
            elif self.ctx.ef_shift != 0:
                # extract old Fermi energy in Ry
                remote_data_parent = self.inputs.remote_data
                parent_calc = remote_data_parent.get_incoming(
                    link_label_filter='remote_folder').first().node
                ef_old = parent_calc.outputs.output_parameters.get_dict().get(
                    'fermi_energy')
                # get Fermi energy shift in eV
                ef_shift = self.ctx.ef_shift  #set new E_F in eV
                # calculate new Fermi energy in Ry
                ef_new = (ef_old + ef_shift / get_Ry2eV())
                self.report(
                    'INFO: ef_old + ef_shift = ef_new: {} eV + {} eV = {} eV'.
                    format(ef_old * get_Ry2eV(), ef_shift,
                           ef_new * get_Ry2eV()))
                updatedict['ef_set'] = ef_new

        #construct the final param node containing all of the params
        updatenode = Dict(dict=updatedict)
        updatenode.label = label + 'KKRparam_flex'
        updatenode.description = descr + 'KKR parameter node extracted from parent parameters and wf_parameter and options input node.'
        paranode_flex = update_params_wf(self.ctx.input_params_KKR, updatenode)
        self.ctx.flex_kkrparams = paranode_flex
        self.ctx.flex_runopt = runopt

        self.report('INFO: Updated params= {}'.format(
            paranode_flex.get_dict()))