Ejemplo n.º 1
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
Ejemplo n.º 2
0
def generate_inputcard_from_structure(parameters,
                                      structure,
                                      input_filename,
                                      parent_calc=None,
                                      shapes=None,
                                      isvoronoi=False,
                                      use_input_alat=False,
                                      vca_structure=False):
    """
    Takes information from parameter and structure data and writes input file 'input_filename'
    
    :param parameters: input parameters node containing KKR-related input parameter
    :param structure: input structure node containing lattice information
    :param input_filename: input filename, typically called 'inputcard'
    
    optional arguments
    :param parent_calc: input parent calculation node used to determine if EMIN 
                        parameter is automatically overwritten (from voronoi output)
                        or not
    :param shapes: input shapes array (set automatically by 
                   aiida_kkr.calculations.Kkrcaluation and shall not be overwritten)
    :param isvoronoi: tell whether or not the parameter set is for a voronoi calculation or kkr calculation (have different lists of mandatory keys)
    :param use_input_alat: True/False, determines whether the input alat value is taken or the new alat is computed from the Bravais vectors
    
    
    :note: assumes valid structure and parameters, i.e. for 2D case all necessary 
           information has to be given. This is checked with function 
           'check_2D_input' called in aiida_kkr.calculations.Kkrcaluation
    """

    from aiida.common.constants import elements as PeriodicTableElements
    from numpy import array
    from aiida_kkr.tools.kkr_params import kkrparams
    from aiida_kkr.tools.common_functions import get_Ang2aBohr, get_alat_from_bravais
    from aiida_kkr.calculations.voro import VoronoiCalculation

    #list of globally used constants
    a_to_bohr = get_Ang2aBohr()

    # Get the connection between coordination number and element symbol
    # maybe do in a differnt way

    _atomic_numbers = {
        data['symbol']: num
        for num, data in PeriodicTableElements.iteritems()
    }

    # KKR wants units in bohr
    bravais = array(structure.cell) * a_to_bohr
    alat_input = parameters.get_dict().get('ALATBASIS')
    if use_input_alat and alat_input is not None:
        alat = alat_input
    else:
        alat = get_alat_from_bravais(bravais, is3D=structure.pbc[2])
    bravais = bravais / alat

    sites = structure.sites
    naez = len(sites)
    positions = []
    charges = []
    weights = []  # for CPA
    isitelist = []  # counter sites array for CPA
    isite = 0
    for site in sites:
        pos = site.position
        #TODO maybe convert to rel pos and make sure that type is right for script (array or tuple)
        abspos = array(pos) * a_to_bohr / alat  # also in units of alat
        positions.append(abspos)
        isite += 1
        sitekind = structure.get_kind(site.kind_name)
        for ikind in range(len(sitekind.symbols)):
            site_symbol = sitekind.symbols[ikind]
            if sitekind.is_alloy():
                wght = sitekind.weights[ikind]
            else:
                wght = 1.
            if not sitekind.has_vacancies():
                zatom_tmp = _atomic_numbers[site_symbol]
            else:
                zatom_tmp = 0.0
            if vca_structure and ikind > 0 and not isvoronoi:
                # for VCA case take weighted average (only for KKR code, voronoi code uses zatom of first site for dummy calculation)
                zatom = zatom * wght_last + zatom_tmp * wght
                # also reset weight to 1
                wght = 1.
            else:
                zatom = zatom_tmp
                if vca_structure and isvoronoi:
                    wght = 1.

            wght_last = wght  # for VCA mode

            # make sure that for VCA only averaged position is written (or first for voronoi code)
            if ((vca_structure and ((len(sitekind.symbols) == 1) or
                                    (not isvoronoi and ikind == 1) or
                                    (isvoronoi and ikind == 0)))
                    or (not vca_structure)):
                charges.append(zatom)
                weights.append(wght)
                isitelist.append(isite)

    weights = array(weights)
    isitelist = array(isitelist)
    charges = array(charges)
    positions = array(positions)

    # workaround for voronoi calculation with Zatom=83 (Bi potential not there!)
    if isvoronoi:
        from numpy import where
        mask_replace_Bi_Pb = where(charges == 83)
        charges[mask_replace_Bi_Pb] = 82
        print('WARNING: Bi potential not available, using Pb instead!!!')

    ######################################
    # Prepare keywords for kkr from input structure

    # get parameter dictionary
    input_dict = parameters.get_dict()

    # remove special keys that are used for special cases but are not part of the KKR parameter set
    for key in _ignored_keys:
        if input_dict.get(key) is not None:
            print('WARNING: automatically removing value of key', key)
            input_dict.pop(key)

    # get rid of structure related inputs that are overwritten from structure input
    for key in [
            'BRAVAIS', 'ALATBASIS', 'NAEZ', '<ZATOM>', '<RBASIS>', 'CARTESIAN'
    ]:
        if input_dict.get(key) is not None:
            print('WARNING: automatically removing value of key', key)
            input_dict.pop(key)

    # automatically rescale RMAX, GMAX, RCLUSTZ, RCLUSTXY which are scaled with the lattice constant
    if alat_input is not None:
        if input_dict.get('RMAX') is not None:
            print('rescale RMAX', alat_input / alat)
            input_dict['RMAX'] = input_dict['RMAX'] * alat_input / alat
        if input_dict.get('GMAX') is not None:
            print('rescale GMAX', 1 / (alat_input / alat))
            input_dict['GMAX'] = input_dict['GMAX'] * 1 / (alat_input / alat)
        if input_dict.get('RCLUSTZ') is not None:
            print('rescale RCLUSTZ', alat_input / alat)
            input_dict['RCLUSTZ'] = input_dict['RCLUSTZ'] * alat_input / alat
        if input_dict.get('RCLUSTXY') is not None:
            print('rescale RCLUSTXY', alat_input / alat)
            input_dict['RCLUSTXY'] = input_dict['RCLUSTXY'] * alat_input / alat

    # empty kkrparams instance (contains formatting info etc.)
    if not isvoronoi:
        params = kkrparams()
    else:
        params = kkrparams(params_type='voronoi')

    # for KKR calculation set EMIN automatically from parent_calc (ausways in res.emin of voronoi and kkr)
    if ('EMIN' not in input_dict.keys()
            or input_dict['EMIN'] is None) and parent_calc is not None:
        print('Overwriting EMIN with value from parent calculation')
        if isinstance(parent_calc, VoronoiCalculation):
            emin = parent_calc.res.emin
        else:
            emin = parent_calc.res.energy_contour_group['emin']
        print('Setting emin:', emin, 'is emin None?', emin is None)
        params.set_value('EMIN', emin)

    # overwrite keywords with input parameter
    for key in input_dict.keys():
        params.set_value(key, input_dict[key], silent=True)

    # Write input to file (the parameters that are set here are not allowed to be modfied externally)
    params.set_multiple_values(BRAVAIS=bravais,
                               ALATBASIS=alat,
                               NAEZ=naez,
                               ZATOM=charges,
                               RBASIS=positions,
                               CARTESIAN=True)
    # for CPA case:
    if len(weights) > naez:
        natyp = len(weights)
        params.set_value('NATYP', natyp)
        params.set_value('<CPA-CONC>', weights)
        params.set_value('<SITE>', isitelist)
    else:
        natyp = naez

    # write shapes (extracted from voronoi parent automatically in kkr calculation plugin)
    if shapes is not None:
        params.set_value('<SHAPE>', shapes)

    # change input values of 2D input to new alat:
    rbl = params.get_value('<RBLEFT>')
    rbr = params.get_value('<RBRIGHT>')
    zper_l = params.get_value('ZPERIODL')
    zper_r = params.get_value('ZPERIODR')
    if rbl is not None:
        params.set_value('<RBLEFT>', array(rbl) * a_to_bohr / alat)
    if rbr is not None:
        params.set_value('<RBRIGHT>', array(rbr) * a_to_bohr / alat)
    if zper_l is not None:
        params.set_value('ZPERIODL', array(zper_l) * a_to_bohr / alat)
    if zper_r is not None:
        params.set_value('ZPERIODR', array(zper_r) * a_to_bohr / alat)

    # write inputfile
    params.fill_keywords_to_inputfile(output=input_filename)

    nspin = params.get_value('NSPIN')

    newsosol = False
    if 'NEWSOSOL' in params.get_value('RUNOPT'):
        newsosol = True

    return natyp, nspin, newsosol
Ejemplo n.º 3
0
def find_neighbors(structure,
                   structure_array,
                   i,
                   radius,
                   clust_shape='spherical',
                   h=0.,
                   vector=[0., 0., 1.]):
    """
    Applies periodic boundary conditions and obtains the distances between the selected atom i in the cell and 
    all other atoms that lie within a cutoff radius r_cut. Afterwards an numpy array with all those atoms including 
    atom i (x_res) will be returned.
    
    :param structure: input parameter of the StructureData type containing the three bravais lattice cell vectors
    :param structure_array: input numpy structure array containing all the structure related data
    :param i: centered atom at which the origin lies (same one as in select_reference)
    :param radius: Specifies the radius of the cylinder or of the sphere, depending on clust_shape. 
                   Input in units of the lattice constant. 
    :param clust_shape: specifies the shape of the cluster that is used to determine the neighbors for the 'scoef' file.
                        Default value is 'spherical'. Other possible forms are 'cylindrical' ('h' and 'orient' 
                        needed), ... .
    :param h: needed for a cylindrical cluster shape. Specifies the height of the cylinder. Default=0. 
              Input in units of the lattice constant.
    :param vector: needed for a cylindrical cluster shape. Specifies the orientation vector of the cylinder. Default:
                   z-direction.
                  
    :return: array with all the atoms within the cutoff (x_res)
    
    :ToDo: - dynamical box construction (r_cut determines which values n1, n2, n3 have)
           - different cluster forms (spherical, cylinder, ...), add default parameters, better solution for 'orient'
    """

    #import packages
    from aiida_kkr.tools.common_functions import get_Ang2aBohr, get_alat_from_bravais
    import numpy as np
    import math

    #list of globally used constants
    a_to_bohr = get_Ang2aBohr()

    #conversion into units of the lattice constant
    bravais = np.array(structure.cell) * a_to_bohr
    alat = get_alat_from_bravais(bravais, is3D=structure.pbc[2])

    #obtain cutoff distance from radius and h
    dist_cut = max(radius, h)

    #initialize arrays and reference the system
    x = select_reference(structure_array, i)
    center = x[i]
    x_temp = np.array([x[i]])

    #calculate needed amount of boxes in all three directions
    #========================================================
    #spherical approach (same distance in all three directions)
    if clust_shape == 'spherical':
        box_1 = int(radius / (structure.cell_lengths[0] * a_to_bohr / alat) +
                    1)
        box_2 = int(radius / (structure.cell_lengths[1] * a_to_bohr / alat) +
                    1)
        box_3 = int(radius / (structure.cell_lengths[2] * a_to_bohr / alat) +
                    1)
    #cylindrical shape (different distances for the different directions)
    elif clust_shape == 'cylindrical':
        maxval = max(h / 2., radius)
        box_1 = int(maxval / (structure.cell_lengths[0] * a_to_bohr / alat) +
                    1)
        box_2 = int(maxval / (structure.cell_lengths[1] * a_to_bohr / alat) +
                    1)
        box_3 = int(maxval / (structure.cell_lengths[2] * a_to_bohr / alat) +
                    1)
    #================================================================================================================

    #create array of all the atoms in an expanded system
    box = max(box_1, box_2, box_3)
    for j in range(len(x)):
        for n in range(-box, box + 1):
            for m in range(-box, box + 1):
                for l in range(-box, box + 1):
                    x_temp = np.append(x_temp, [[
                        x[j][0] +
                        (n * structure.cell[0][0] + m * structure.cell[1][0] +
                         l * structure.cell[2][0]) * a_to_bohr / alat,
                        x[j][1] +
                        (n * structure.cell[0][1] + m * structure.cell[1][1] +
                         l * structure.cell[2][1]) * a_to_bohr / alat,
                        x[j][2] +
                        (n * structure.cell[0][2] + m * structure.cell[1][2] +
                         l * structure.cell[2][2]) * a_to_bohr / alat, x[j][3],
                        x[j][4], 0.
                    ]],
                                       axis=0)

    #x_temp now contains all the atoms and their positions regardless if they are bigger or smaller than the cutoff
    x_new = x_temp

    #calculate the distances between all the atoms and the center atom i
    for j in range(len(x_temp)):
        x_new[j][5] = get_distance(x_temp, 0, j)

    #initialize result array
    x_res = np.array([x[i]])

    #only take atoms into account whose distance to atom i is smaller than the cutoff radius
    #dist_cut = dist_cut
    if clust_shape == 'spherical':
        for j in range(len(x_temp)):
            if x_new[j][5] <= dist_cut and x_new[j][5] > 0.:
                x_res = np.append(x_res, [[
                    x_temp[j][0], x_temp[j][1], x_temp[j][2], x_temp[j][3],
                    x_temp[j][4], x_new[j][5]
                ]],
                                  axis=0)
    elif clust_shape == 'cylindrical':
        for j in range(len(x_temp)):
            #rotate system into help system that is aligned with the z-axis
            x_help = rotate_onto_z(structure, x_temp, vector)

            #calculate in plane distance and vertical distance
            vert_dist = np.absolute(x_help[j][2])
            inplane_dist = math.sqrt(x_help[j][0]**2 + x_help[j][1]**2)
            #print(vert_dist, inplane_dist)
            if vert_dist <= h / 2. and inplane_dist <= radius and x_new[j][
                    5] > 0.:
                x_res = np.append(x_res, [[
                    x_temp[j][0], x_temp[j][1], x_temp[j][2], x_temp[j][3],
                    x_temp[j][4], x_new[j][5]
                ]],
                                  axis=0)

    #return an unordered array of all the atoms which are within the cutoff distance with respect to atom i
    return x_res
Ejemplo n.º 4
0
    def test_read_slab(self):
        from numpy import array
        from aiida_kkr.tools.common_functions import get_Ang2aBohr
        p = kkrparams(params_type='kkr')

        # automatically read keywords from inpucard
        p.read_keywords_from_inputcard(
            inputcard='../tests/files/kkr/import_calc_old_style/inputcard')
        # convert some read-in stuff back from Ang. units to alat units
        rbl = p.get_value('<RBLEFT>')
        rbr = p.get_value('<RBRIGHT>')
        zper_l = p.get_value('ZPERIODL')
        zper_r = p.get_value('ZPERIODR')
        ang2alat = get_Ang2aBohr() / p.get_value('ALATBASIS')
        if rbl is not None: p.set_value('<RBLEFT>', array(rbl) * ang2alat)
        if rbr is not None: p.set_value('<RBRIGHT>', array(rbr) * ang2alat)
        if zper_l is not None:
            p.set_value('ZPERIODL', array(zper_l) * ang2alat)
        if zper_r is not None:
            p.set_value('ZPERIODR', array(zper_r) * ang2alat)

        # set parameters of expected values manually
        p0 = kkrparams(
            RUNOPT=['xigid-ef', 'LLOYD', 'ewald2d', 'NEWSOSOL', 'DOS'],
            TESTOPT=['ie', 'RMESH', 'clusters', 'MPIenerg', 'fullBZ', 'DOS'],
            LMAX=3,
            NSPIN=2,
            NATYP=80,
            NAEZ=80,
            CARTESIAN=True,
            ALATBASIS=20.156973053,
            BRAVAIS=[[0.38437499, 0., 0.], [0.19218749, -0.33287851, 0.],
                     [0.19218749, -0.11095950, 1.]],
            INTERFACE=True,
            NRIGHTHO=10,
            NLEFTHOS=10,
            NLBASIS=10,
            NRBASIS=10,
            ZPERIODL=[
                -1.92187500000000e-01, 1.10959504859881e-01,
                -1.00000000000000e+00
            ],
            ZPERIODR=[
                1.92187500000000e-01, -1.10959504859881e-01,
                1.00000000000000e+00
            ],
            RCLUSTZ=0.65,
            RCLUSTXY=0.65,
            EMIN=-1.2,
            EMAX=1.2,
            TEMPR=473.,
            NPOL=7,
            NPT1=7,
            NPT2=40,
            NPT3=6,
            KSHAPE=2,
            INS=1,
            ICST=2,
            KEXCOR=2,
            HFIELD=0,
            VCONST=0,
            NPAN_LOG=17,
            NPAN_EQ=7,
            NCHEB=12,
            R_LOG=0.8,
            BZDIVIDE=[40, 40, 1],
            NSTEPS=500,
            IMIX=5,
            STRMIX=0.02,
            FCM=20.,
            QBOUND=10**-7,
            BRYMIX=0.02,
            ITDBRY=30,
            LINIPOL=False,
            FILES=['potential', 'shapefun'],
            RMAX=15.,
            GMAX=900.)
        p0.set_value('<ZATOM>', [
            0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 52.0, 0.0, 51.0,
            0.0, 52.0, 0.0, 51.0, 0.0, 52.0, 0.0, 52.0, 0.0, 51.0, 0.0, 52.0,
            0.0, 51.0, 0.0, 52.0, 0.0, 52.0, 0.0, 51.0, 0.0, 52.0, 0.0, 51.0,
            0.0, 52.0, 0.0, 52.0, 0.0, 51.0, 0.0, 52.0, 0.0, 51.0, 0.0, 52.0,
            0.0, 52.0, 0.0, 51.0, 0.0, 52.0, 0.0, 51.0, 0.0, 52.0, 0.0, 52.0,
            0.0, 51.0, 0.0, 52.0, 0.0, 51.0, 0.0, 52.0, 0.0, 0.0, 0.0, 0.0,
            0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0
        ])
        p0.set_value('<SHAPE>', [
            1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2,
            3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4,
            5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6,
            7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
        ])
        p0.set_multiple_values(KAOEZR=[i for i in range(1, 11)],
                               KAOEZL=[i for i in range(1, 11)],
                               KVREL=1,
                               RMTREFL=[
                                   2.2671000, 2.2671000, 2.4948000, 2.3562000,
                                   2.3562000, 2.3562000, 2.4948000, 2.2671000,
                                   2.2671000, 2.5740000
                               ],
                               RMTREFR=[
                                   2.2671000, 2.2671000, 2.4948000, 2.3562000,
                                   2.3562000, 2.3562000, 2.4948000, 2.2671000,
                                   2.2671000, 2.5740000
                               ])
        p0.set_multiple_values(RMTREF=[
            2.2671000, 2.2671000, 2.4948000, 2.3562000, 2.3562000, 2.3562000,
            2.4948000, 2.2671000, 2.2671000, 2.5740000, 2.2671000, 2.2671000,
            2.4948000, 2.3562000, 2.3562000, 2.3562000, 2.4948000, 2.2671000,
            2.2671000, 2.5740000, 2.2671000, 2.2671000, 2.4948000, 2.3562000,
            2.3562000, 2.3562000, 2.4948000, 2.2671000, 2.2671000, 2.5740000,
            2.2671000, 2.2671000, 2.4948000, 2.3562000, 2.3562000, 2.3562000,
            2.4948000, 2.2671000, 2.2671000, 2.5740000, 2.2671000, 2.2671000,
            2.4948000, 2.3562000, 2.3562000, 2.3562000, 2.4948000, 2.2671000,
            2.2671000, 2.5740000, 2.2671000, 2.2671000, 2.4948000, 2.3562000,
            2.3562000, 2.3562000, 2.4948000, 2.2671000, 2.2671000, 2.5740000,
            2.2671000, 2.2671000, 2.4948000, 2.3562000, 2.3562000, 2.3562000,
            2.4948000, 2.2671000, 2.2671000, 2.5740000, 2.2671000, 2.2671000,
            2.4948000, 2.3562000, 2.3562000, 2.3562000, 2.4948000, 2.2671000,
            2.2671000, 2.5740000
        ])
        p0.set_multiple_values(
            RBLEFT=[[
                -1.92187500000000e-01, 1.10959504859881e-01,
                -1.00000000000000e+00
            ],
                    [
                        8.32667268468867e-17, 2.77555756156289e-17,
                        -9.49500000000000e-01
                    ],
                    [
                        1.92187500000000e-01, -1.10959504859881e-01,
                        -8.33000000000000e-01
                    ],
                    [
                        3.84375000000000e-01, -2.21919009719762e-01,
                        -7.16500000000000e-01
                    ],
                    [
                        8.32667268468867e-17, 0.00000000000000e+00,
                        -6.33000000000000e-01
                    ],
                    [
                        1.92187500000000e-01, -1.10959504859881e-01,
                        -5.49500000000000e-01
                    ],
                    [
                        3.84375000000000e-01, -2.21919009719762e-01,
                        -4.33000000000000e-01
                    ],
                    [
                        2.77555756156289e-17, 1.38777878078145e-17,
                        -3.16500000000000e-01
                    ],
                    [
                        1.92187500000000e-01, -1.10959504859881e-01,
                        -2.66000000000000e-01
                    ],
                    [
                        3.84375000000000e-01, -2.21919009719762e-01,
                        -1.33000000000000e-01
                    ]],
            RBRIGHT=[[
                1.53750000000000e+00, -8.87676038879049e-01,
                8.00000000000000e+00
            ],
                     [
                         1.72968750000000e+00, -9.98635543738930e-01,
                         8.05050000000000e+00
                     ],
                     [
                         1.92187500000000e+00, -1.10959504859881e+00,
                         8.16700000000000e+00
                     ],
                     [
                         2.11406250000000e+00, -1.22055455345869e+00,
                         8.28350000000000e+00
                     ],
                     [
                         1.72968750000000e+00, -9.98635543738930e-01,
                         8.36700000000000e+00
                     ],
                     [
                         1.92187500000000e+00, -1.10959504859881e+00,
                         8.45050000000000e+00
                     ],
                     [
                         2.11406250000000e+00, -1.22055455345869e+00,
                         8.56700000000000e+00
                     ],
                     [
                         1.72968750000000e+00, -9.98635543738930e-01,
                         8.68350000000000e+00
                     ],
                     [
                         1.92187500000000e+00, -1.10959504859881e+00,
                         8.73400000000000e+00
                     ],
                     [
                         2.11406250000000e+00, -1.22055455345869e+00,
                         8.86700000000000e+00
                     ]],
            RBASIS=[[0.0, 0.0, 0.0],
                    [0.1921875, -0.110959504859881, 0.0505000000000001],
                    [0.384375, -0.221919009719762, 0.167],
                    [0.5765625, -0.332878514579644, 0.2835],
                    [0.1921875, -0.110959504859881, 0.367],
                    [0.384375, -0.221919009719762, 0.4505],
                    [0.5765625, -0.332878514579644, 0.567],
                    [0.1921875, -0.110959504859881, 0.6835],
                    [0.384375, -0.221919009719762, 0.734],
                    [0.5765625, -0.332878514579644, 0.867],
                    [0.1921875, -0.110959504859881, 1.0],
                    [0.384375, -0.221919009719762, 1.0505],
                    [0.5765625, -0.332878514579643, 1.167],
                    [0.76875, -0.443838019439525, 1.2835],
                    [0.384375, -0.221919009719762, 1.367],
                    [0.5765625, -0.332878514579643, 1.4505],
                    [0.76875, -0.443838019439525, 1.567],
                    [0.384375, -0.221919009719762, 1.6835],
                    [0.5765625, -0.332878514579643, 1.734],
                    [0.76875, -0.443838019439525, 1.867],
                    [0.384375, -0.221919009719762, 2.0],
                    [0.5765625, -0.332878514579643, 2.0505],
                    [0.76875, -0.443838019439525, 2.167],
                    [0.9609375, -0.554797524299406, 2.2835],
                    [0.5765625, -0.332878514579643, 2.367],
                    [0.76875, -0.443838019439525, 2.4505],
                    [0.9609375, -0.554797524299406, 2.567],
                    [0.5765625, -0.332878514579643, 2.6835],
                    [0.76875, -0.443838019439525, 2.734],
                    [0.9609375, -0.554797524299406, 2.867],
                    [0.5765625, -0.332878514579643, 3.0],
                    [0.76875, -0.443838019439525, 3.0505],
                    [0.9609375, -0.554797524299406, 3.167],
                    [1.153125, -0.665757029159287, 3.2835],
                    [0.76875, -0.443838019439525, 3.367],
                    [0.9609375, -0.554797524299406, 3.4505],
                    [1.153125, -0.665757029159287, 3.567],
                    [0.76875, -0.443838019439525, 3.6835],
                    [0.9609375, -0.554797524299406, 3.734],
                    [1.153125, -0.665757029159287, 3.867],
                    [0.76875, -0.443838019439525, 4.0],
                    [0.9609375, -0.554797524299406, 4.0505],
                    [1.153125, -0.665757029159287, 4.167],
                    [1.3453125, -0.776716534019168, 4.2835],
                    [0.9609375, -0.554797524299406, 4.367],
                    [1.153125, -0.665757029159287, 4.4505],
                    [1.3453125, -0.776716534019168, 4.567],
                    [0.9609375, -0.554797524299406, 4.6835],
                    [1.153125, -0.665757029159287, 4.734],
                    [1.3453125, -0.776716534019168, 4.867],
                    [0.9609375, -0.554797524299406, 5.0],
                    [1.153125, -0.665757029159287, 5.0505],
                    [1.3453125, -0.776716534019168, 5.167],
                    [1.5375, -0.887676038879049, 5.2835],
                    [1.153125, -0.665757029159287, 5.367],
                    [1.3453125, -0.776716534019168, 5.4505],
                    [1.5375, -0.887676038879049, 5.567],
                    [1.153125, -0.665757029159287, 5.6835],
                    [1.3453125, -0.776716534019168, 5.734],
                    [1.5375, -0.887676038879049, 5.867],
                    [1.153125, -0.665757029159287, 6.0],
                    [1.3453125, -0.776716534019168, 6.0505],
                    [1.5375, -0.887676038879049, 6.167],
                    [1.7296875, -0.99863554373893, 6.2835],
                    [1.3453125, -0.776716534019168, 6.367],
                    [1.5375, -0.887676038879049, 6.4505],
                    [1.7296875, -0.99863554373893, 6.567],
                    [1.3453125, -0.776716534019168, 6.6835],
                    [1.5375, -0.887676038879049, 6.734],
                    [1.7296875, -0.99863554373893, 6.867],
                    [1.3453125, -0.776716534019168, 7.0],
                    [1.5375, -0.887676038879049, 7.0505],
                    [1.7296875, -0.99863554373893, 7.167],
                    [1.921875, -1.10959504859881, 7.2835],
                    [1.5375, -0.887676038879049, 7.367],
                    [1.7296875, -0.99863554373893, 7.4505],
                    [1.921875, -1.10959504859881, 7.567],
                    [1.5375, -0.887676038879049, 7.6835],
                    [1.7296875, -0.99863554373893, 7.734],
                    [1.921875, -1.10959504859881, 7.867]])

        # check all values
        check_full_dict(p, p0)
Ejemplo n.º 5
0
def get_structure_data(structure):
    """
    Function to take data from AiiDA's StructureData type and store it into a single numpy array of the following form:
    a = [[x-Position 1st atom, y-Position 1st atom, z-Position 1st atom, index 1st atom, charge 1st atom, 0.],
         [x-Position 2nd atom, y-Position 2nd atom, z-Position 2nd atom, index 2nd atom, charge 1st atom, 0.],
         [..., ..., ..., ..., ..., ...],
         ...
         ]
    
    :param structure: input structure of the type StructureData
    
    :return: numpy array a[# of atoms in the unit cell][5] containing the structure related data (positions in units
             of the unit cell length)
    
    :note:   
    """

    #import packages
    from aiida.common.constants import elements as PeriodicTableElements
    from aiida_kkr.tools.common_functions import get_Ang2aBohr, get_alat_from_bravais
    import numpy as np

    #list of globally used constants
    a_to_bohr = get_Ang2aBohr()

    #get the connection between coordination number and element symbol
    _atomic_numbers = {
        data['symbol']: num
        for num, data in PeriodicTableElements.iteritems()
    }

    #convert units from Å to Bohr (KKR needs Bohr)
    bravais = np.array(structure.cell) * a_to_bohr
    alat = get_alat_from_bravais(bravais, is3D=structure.pbc[2])
    #bravais = bravais/alat

    #initialize the array that will be returned later (it will be a (# of atoms in the cell) x 6-matrix)
    a = np.zeros((len(structure.sites), 6))
    k = 0  #running index for filling up the array with data correctly
    charges = [
    ]  #will be needed to return the charge number for the different atoms later

    #loop to fill up the a-array with positions, index, charge and a 0. for every atom in the cell
    sites = structure.sites
    n = len(structure.sites) + 1  #needed to do the indexing of atoms
    m = len(structure.sites)  #needed to do the indexing of atoms
    for site in sites:
        for j in range(3):
            a[k][j] = site.position[j] * a_to_bohr / alat
        sitekind = structure.get_kind(site.kind_name)
        naez = n - m
        m = m - 1
        #convert the element symbol from StructureData to the charge number
        for ikind in range(len(sitekind.symbols)):
            site_symbol = sitekind.symbols[ikind]
            charges.append(_atomic_numbers[site_symbol])
        i = len(charges) - 1
        a[k][3] = int(naez)
        a[k][4] = float(charges[i])
        k = k + 1

    return a