Example #1
0
    def _prepare_xsf(self, index=None):
        """
        Write the given trajectory to a string of format XSF (for XCrySDen). 
        """
        from aiida.common.constants import elements
        _atomic_numbers = {
            data['symbol']: num
            for num, data in elements.iteritems()
        }

        indices = range(self.numsteps)
        if index is not None:
            indices = [index]
        return_string = "ANIMSTEPS {}\nCRYSTAL\n".format(len(indices))
        for idx in indices:
            return_string += "PRIMVEC {}\n".format(idx + 1)
            structure = self.get_step_structure(index=idx)
            sites = structure.sites
            if structure.is_alloy() or structure.has_vacancies():
                raise NotImplementedError("XSF for alloys or systems with "
                                          "vacancies not implemented.")
            for cell_vector in structure.cell:
                return_string += " ".join(["%18.5f" % i for i in cell_vector])
                return_string += "\n"
            return_string += "PRIMCOORD {}\n".format(idx + 1)
            return_string += "%d 1\n" % len(sites)
            for site in sites:
                # I checked above that it is not an alloy, therefore I take the
                # first symbol
                return_string += "%s " % _atomic_numbers[structure.get_kind(
                    site.kind_name).symbols[0]]
                return_string += "%18.10f %18.10f %18.10f\n" % tuple(
                    site.position)
        return return_string
Example #2
0
def create_corehole_para(structure, kind, econfig, species_name='corehole', parameterData=None):
    """
    This methods sets of electron configurations for a kind
    or position given, make sure to break the symmetry for this position/kind
    beforehand, otherwise you will create several coreholes.

    param: structure: StructureData
    param: kind, a string with the kind_name (TODO: alternative the kind object)
    param: econfig, string, e.g. econfig = "[Kr] 5s2 4d10 4f13 | 5p6 5d5 6s2"
    ! THis is the new econfig therefore

    returns a parameterData node
    """

    from aiida.common.constants import elements as PeriodicTableElements

    _atomic_numbers = {data['symbol']: num for num,
                           data in PeriodicTableElements.iteritems()}
    #from aiida_fleur.tools.merge_parameter import merge_parameter

    kindo = structure.get_kind(kind)
    symbol = kindo.symbol
    head = kindo.name.rstrip('01223456789')
    #print(kindo)
    charge = _atomic_numbers[kindo.symbol]
    id = float("{}.{}".format(charge, kindo.name[len(head):]))
    #print('id {}'.format(id))

    # get kind symbol, get kind name,
    #&atom element="W" jri=921 lmax=8 rmt=2.52 dx=0.014 lo="5p" econfig="[Kr] 5s2 4d10 4f13 | 5p6 5d4 6s2" /
    #count = 0
    if parameterData:
        new_parameterd = parameterData.get_dict() # dict()otherwise parameterData is changed
        for key, val in new_parameterd.iteritems():
            if 'atom' in key:
                if val.get('element', None) == symbol:
                    # remember id is atomic number.some int
                    if (id and float(id) == float(val.get('id', -1))):
                        val.update({'econfig' : econfig})
                        #print 'here1'
                        break
                    elif not id:
                        #print 'here2'
                        val.update({'econfig' : econfig})
                    else:
                        pass
    else:
        if id:
            if species_name:
                new_parameterd = {'atom': {'element' : symbol, 'econfig' : econfig, 'id' : id, 'name' : species_name}}
            else:
                new_parameterd = {'atom': {'element' : symbol, 'econfig' : econfig, 'id' : id}}
        else:
            new_parameterd = {'atom': {'element' : symbol, 'econfig' : econfig}}

    new_parameter= ParameterData(dict=new_parameterd)
    #if parameterData:
    #    new_parameter = merge_parameter(parameterData, new_parameter)
    return new_parameter#structure
Example #3
0
    def _prepare_xsf(self, index=None):
        """
        Write the given trajectory to a string of format XSF (for XCrySDen).
        """
        from aiida.common.constants import elements
        _atomic_numbers = {
            data['symbol']: num
            for num, data in elements.iteritems()
        }

        indices = range(self.numsteps)
        if index is not None:
            indices = [index]
        return_string = "ANIMSTEPS {}\nCRYSTAL\n".format(len(indices))
        # Do the checks once and for all here:
        structure = self.get_step_structure(index=0)
        if structure.is_alloy() or structure.has_vacancies():
            raise NotImplementedError("XSF for alloys or systems with "
                                      "vacancies not implemented.")
        cells = self.get_cells()
        positions = self.get_positions()
        symbols = self.get_symbols()
        atomic_numbers_list = [_atomic_numbers[s] for s in symbols]
        nat = len(symbols)

        for idx in indices:
            return_string += "PRIMVEC {}\n".format(idx + 1)
            #~ structure = self.get_step_structure(index=idx)
            #~ sites = structure.sites
            #~ if structure.is_alloy() or structure.has_vacancies():
            #~ raise NotImplementedError("XSF for alloys or systems with "
            #~ "vacancies not implemented.")
            for cell_vector in cells[idx]:
                return_string += " ".join(
                    ["{:18.5f}".format(i) for i in cell_vector])
                return_string += "\n"
            return_string += "PRIMCOORD {}\n".format(idx + 1)
            return_string += "{} 1\n".format(nat)
            for atn, pos in zip(atomic_numbers_list, positions[idx]):
                try:
                    return_string += "{} {:18.10f} {:18.10f} {:18.10f}\n".format(
                        atn, pos[0], pos[1], pos[2])
                except:
                    print sym, pos
                    raise
        return return_string
def change_struc_imp_aux_wf(
        struc, imp_info):  # Note: works for single imp at center only!
    from aiida.common.constants import elements as PeriodicTableElements
    _atomic_numbers = {
        data['symbol']: num
        for num, data in PeriodicTableElements.iteritems()
    }

    new_struc = StructureData(cell=struc.cell)
    isite = 0
    for site in struc.sites:
        sname = site.kind_name
        kind = struc.get_kind(sname)
        pos = site.position
        zatom = _atomic_numbers[kind.get_symbols_string()]
        if isite == imp_info.get_dict().get('ilayer_center'):
            zatom = imp_info.get_dict().get('Zimp')[0]
        symbol = PeriodicTableElements.get(zatom).get('symbol')
        new_struc.append_atom(position=pos, symbols=symbol)
        isite += 1

    return new_struc
Example #5
0
    def _prepare_for_submission(self, tempfolder, inputdict):
        """
        This is the routine to be called when you want to create
        the input files and related stuff with a plugin.

        :param tempfolder: a aiida.common.folders.Folder subclass where
                           the plugin should put all its files.
        :param inputdict: a dictionary with the input nodes, as they would
                be returned by get_inputdata_dict (without the Code!)
        """

        local_copy_list = []
        remote_copy_list = []

        # Process the settings dictionary first
        # Settings can be undefined, and defaults to an empty dictionary
        settings = inputdict.pop(self.get_linkname('settings'), None)
        if settings is None:
            settings_dict = {}
        else:
            if not isinstance(settings, ParameterData):
                raise InputValidationError(
                    "settings, if specified, must be of "
                    "type ParameterData")

            # Settings converted to UPPERCASE
            # Presumably to standardize the usage and avoid
            # ambiguities
            settings_dict = _uppercase_dict(settings.get_dict(),
                                            dict_name='settings')

        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 is not of type "
                                       "ParameterData")

        try:
            structure = inputdict.pop(self.get_linkname('structure'))
        except KeyError:
            raise InputValidationError("No structure specified for this "
                                       "calculation")
        if not isinstance(structure, StructureData):
            raise InputValidationError(
                "structure is not of type StructureData")

        bandskpoints = inputdict.pop(self.get_linkname('bandskpoints'), None)
        if bandskpoints is None:
            flagbands = False
        else:
            flagbands = True
            if not isinstance(bandskpoints, KpointsData):
                raise InputValidationError(
                    "kpoints for bands is not of type KpointsData")

        singlefile = inputdict.pop(self.get_linkname('singlefile'), None)
        if singlefile is not None:
            if not isinstance(singlefile, SinglefileData):
                raise InputValidationError("singlefile, if specified,"
                                           "must be of type SinglefileData")

        parent_calc_folder = inputdict.pop(self.get_linkname('parent_folder'),
                                           None)
        if parent_calc_folder is not None:
            if not isinstance(parent_calc_folder, RemoteData):
                raise InputValidationError("parent_calc_folder, if specified,"
                                           "must be of type RemoteData")

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

        # Here, there should be no more parameters...
        if inputdict:
            raise InputValidationError("The following input data nodes are "
                                       "unrecognized: {}".format(
                                           inputdict.keys()))

        ##############################
        # END OF INITIAL INPUT CHECK #
        ##############################

        #
        # There should be a warning for duplicated (canonicalized) keys
        # in the original dictionary in the script

        input_params = FDFDict(parameters.get_dict())

        # Look for blocked keywords and
        # add the proper values to the dictionary

        for blocked_key in self._aiida_blocked_keywords:
            canonical_blocked = FDFDict.translate_key(blocked_key)
            for key in input_params:
                if key == canonical_blocked:
                    raise InputValidationError(
                        "You cannot specify explicitly the '{}' flag in the "
                        "input parameters".format(
                            input_params.get_last_key(key)))

        input_params.update({'system-name': self._PREFIX})
        input_params.update({'system-label': self._PREFIX})

        input_params.update({'number-of-species': len(structure.kinds)})
        input_params.update({'number-of-atoms': len(structure.sites)})
        #
        # Regarding the lattice-constant parameter:
        # -- The variable "alat" is not typically kept anywhere, and
        # has already been used to define the vectors.
        # We need to specify that the units of these vectors are Ang...

        input_params.update({'lattice-constant': '1.0 Ang'})

        # Note that this  will break havoc with the band-k-points "pi/a"
        # option. The use of this option should be banned.

        # Note that the implicit coordinate convention of the Structure
        # class corresponds to the "Ang" convention in Siesta.
        # The "atomic-coordinates-format" keyword is blocked to ScaledCartesian,
        # which is given in terms of the lattice constant (1.0 Ang).
        input_params.update({'atomic-coordinates-format': 'ScaledCartesian'})

        # ============== Preparation of input data ===============
        #

        # ------------ CELL_PARAMETERS -----------
        cell_parameters_card = "%block lattice-vectors\n"
        for vector in structure.cell:
            cell_parameters_card += ("{0:18.10f} {1:18.10f} {2:18.10f}"
                                     "\n".format(*vector))
        cell_parameters_card += "%endblock lattice-vectors\n"

        # ------------- ATOMIC_SPECIES ------------
        # Only the species index and the mass are necessary

        # Dictionary to get the mass of a given element
        datmn = dict([(v['symbol'], v['mass'])
                      for k, v in elements.iteritems()])

        spind = {}
        spcount = 0
        for kind in structure.kinds:

            spcount += 1
            spind[kind.name] = spcount

        # ------------ ATOMIC_POSITIONS -----------
        atomic_positions_card_list = [
            "%block atomiccoordinatesandatomicspecies\n"
        ]
        countatm = 0
        for site in structure.sites:
            countatm += 1
            atomic_positions_card_list.append(
                "{0:18.10f} {1:18.10f} {2:18.10f} {3:4} {4:10} \n".format(
                    site.position[0], site.position[1], site.position[2],
                    spind[site.kind_name], datmn[kind.symbol]))
        atomic_positions_card = "".join(atomic_positions_card_list)
        del atomic_positions_card_list  # Free memory
        atomic_positions_card += "%endblock atomiccoordinatesandatomicspecies\n"

        # --------------- K-POINTS-FOR-BANDS ----------------!
        #This part is computed only if flagbands=True
        #Two possibility are supported in Siesta: BandLines ad BandPoints
        #At the moment the user can't choose directly one of the two options
        #BandsLine is set automatically if bandskpoints has labels,
        #BandsPoints if bandskpoints has no labels
        #BandLinesScale =pi/a is not supported at the moment because currently
        #a=1 always. BandLinesScale ReciprocalLatticeVectors is always set
        if flagbands:
            bandskpoints_card_list = [
                "BandLinesScale ReciprocalLatticeVectors\n"
            ]
            if bandskpoints.labels == None:
                bandskpoints_card_list.append("%block BandPoints\n")
                for s in bandskpoints.get_kpoints():
                    bandskpoints_card_list.append(
                        "{0:8.3f} {1:8.3f} {2:8.3f} \n".format(
                            s[0], s[1], s[2]))
                fbkpoints_card = "".join(bandskpoints_card_list)
                fbkpoints_card += "%endblock BandPoints\n"
            else:
                bandskpoints_card_list.append("%block BandLines\n")
                savs = []
                listforbands = bandskpoints.get_kpoints()
                for s, m in bandskpoints.labels:
                    savs.append(s)
                rawindex = 0
                for s, m in bandskpoints.labels:
                    rawindex = rawindex + 1
                    nkpnt, x, y, z, = listforbands[s]
                    if rawindex == 1:
                        bandskpoints_card_list.append(
                            "{0:2} {1:8.3f} {2:8.3f} {3:8.3f} {4:1}\n".format(
                                1, x, y, z, m))
                    else:
                        bandskpoints_card_list.append(
                            "{0:.0f} {1:8.3f} {2:8.3f} {3:8.3f} {4:1}\n".
                            format(nkpnt, x, y, z, m))
                fbkpoints_card = "".join(bandskpoints_card_list)
                fbkpoints_card += "%endblock BandLines\n"
            del bandskpoints_card_list

        # -------------ADDITIONAL FILES -----------
        # I create the subfolder that will contain additional Siesta files
        tempfolder.get_subfolder(self._SFILES_SUBFOLDER, create=True)
        # I create the subfolder with the output data
        tempfolder.get_subfolder(self._OUTPUT_SUBFOLDER, create=True)

        if singlefile is not None:
            lfile = singlefile.get_file_abs_path().split("path/", 1)[1]
            local_copy_list.append((singlefile.get_file_abs_path(),
                                    os.path.join(self._SFILES_SUBFOLDER,
                                                 lfile)))

        # ================ Namelists and cards ===================

        input_filename = tempfolder.get_abs_path(self._INPUT_FILE_NAME)

        with open(input_filename, 'w') as infile:
            # here print keys and values tp file

            for k, v in sorted(input_params.iteritems()):
                infile.write(get_input_data_text(k, v))
                # ,mapping=mapping_species))

            # Write previously generated cards now
            infile.write("#\n# -- Structural Info follows\n#\n")
            infile.write(cell_parameters_card)
            infile.write(atomic_positions_card)
            if flagbands:
                infile.write("#\n# -- Bandlines/Bandpoints Info follows\n#\n")
                infile.write(fbkpoints_card)

        # ------------------------------------- END of fdf file creation

        # The presence of a 'parent_calc_folder' input node signals
        # that we want to get something from there, as indicated in the
        # self._restart_copy_from attribute.
        # In Siesta's case, for now, it is just the density-matrix file
        #
        # It will be copied to the current calculation's working folder.

        if parent_calc_folder is not None:
            remote_copy_list.append(
                (parent_calc_folder.get_computer().uuid,
                 os.path.join(parent_calc_folder.get_remote_path(),
                              self._restart_copy_from), self._restart_copy_to))

        calcinfo = CalcInfo()

        calcinfo.uuid = self.uuid
        #
        # Empty command line by default
        # Why use 'pop' ?
        cmdline_params = settings_dict.pop('CMDLINE', [])

        # Comment this paragraph better, if applicable to Siesta
        #
        #we commented calcinfo.stin_name and added it here in cmdline_params
        #in this way the mpirun ... pw.x ... < aiida.in
        #is replaced by mpirun ... pw.x ... -in aiida.in
        # in the scheduler, _get_run_line, if cmdline_params is empty, it
        # simply uses < calcinfo.stin_name

        if cmdline_params:
            calcinfo.cmdline_params = list(cmdline_params)
        calcinfo.local_copy_list = local_copy_list
        calcinfo.remote_copy_list = remote_copy_list

        calcinfo.stdin_name = self._INPUT_FILE_NAME
        calcinfo.stdout_name = self._OUTPUT_FILE_NAME
        calcinfo.fc_name = self._FC_FILE_NAME

        #
        # Code information object
        #
        codeinfo = CodeInfo()
        codeinfo.cmdline_params = list(cmdline_params)
        codeinfo.stdin_name = self._INPUT_FILE_NAME
        codeinfo.stdout_name = self._OUTPUT_FILE_NAME
        codeinfo.fc_name = self._FC_FILE_NAME
        codeinfo.code_uuid = code.uuid
        calcinfo.codes_info = [codeinfo]

        # Retrieve by default: the output file, the xml file, and the
        # messages file.
        # If flagbands=True we also add the bands file to the retrieve list!
        # This is extremely important because the parser parses the bands
        # only if aiida.bands is in the retrieve list!!

        calcinfo.retrieve_list = []
        calcinfo.retrieve_list.append(self._OUTPUT_FILE_NAME)
        if flagbands:
            calcinfo.retrieve_list.append(self._BANDS_FILE_NAME)

        # Any other files specified in the settings dictionary
        settings_retrieve_list = settings_dict.pop('ADDITIONAL_RETRIEVE_LIST',
                                                   [])
        calcinfo.retrieve_list += settings_retrieve_list

        return calcinfo
Example #6
0
    def _prepare_for_submission(self, tempfolder, inputdict):
        """
        This is the routine to be called when you want to create
        the input files for a SPEX with the plug-in.

        :param tempfolder: a aiida.common.folders.Folder subclass where
                           the plugin should put all its files.
        :param inputdict: a dictionary with the input nodes, as they would
                be returned by get_inputdata_dict (without the Code!)
        """

        #from aiida.common.utils import get_unique_filename, get_suggestion
        #import re

        # 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()
        }

        possible_namelists = self._possible_namelists
        possible_params = self._possible_params
        local_copy_list = []
        remote_copy_list = []
        remote_symlink_list = []
        bulk = True
        film = False

        # convert these 'booleans' to the inpgen format.
        replacer_values_bool = [
            True, False, 'True', 'False', 't', 'T', 'F', 'f'
        ]
        # some keywords require a string " around them in the input file.
        string_replace = ['econfig', 'lo', 'element', 'name']

        # of some keys only the values are writen to the file, specify them here.
        val_only_namelist = ['soc', 'qss']

        # Scaling comes from the Structure
        # but we have to convert from Angstroem to a.u (bohr radii)
        scaling_factors = [1.0, 1.0, 1.0]  #
        scaling_lat = 1.  #/bohr_to_ang
        scaling_pos = 1. / bohr_to_ang  # Angstrom to atomic
        own_lattice = False  #not self._use_aiida_structure

        # The inpfile gen is run in serial TODO: How to do this by default?
        #self.set_withmpi(False)

        ##########################################
        ############# INPUT CHECK ################
        ##########################################

        # first check existence of structure and if 1D, 2D, 3D
        try:
            structure = inputdict.pop(self.get_linkname('structure'))
        except KeyError:
            raise InputValidationError("No structure specified for this"
                                       " calculation")
        if not isinstance(structure, StructureData):
            raise InputValidationError(
                "structure is not of type StructureData")

        pbc = structure.pbc
        if False in pbc:
            bulk = False
            film = True

        # check existence of parameters (optional)
        parameters = inputdict.pop(self.get_linkname('parameters'), None)
        if parameters is None:
            # use default
            parameters_dict = {}
        else:
            if not isinstance(parameters, ParameterData):
                raise InputValidationError(
                    "parameters, if specified, must be of "
                    "type ParameterData")
            parameters_dict = _lowercase_dict(parameters.get_dict(),
                                              dict_name='parameters')

        namelists_toprint = possible_namelists

        input_params = parameters_dict

        if 'title' in input_params.keys():
            self._inp_title = input_params.pop('title')

        #check input_parameters

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

        # check existence of settings (optional)
        settings = inputdict.pop(self.get_linkname('settings'), None)

        if settings is None:
            settings_dict = {}
        else:
            if not isinstance(settings, ParameterData):
                raise InputValidationError(
                    "settings, if specified, must be of "
                    "type ParameterData")
            else:
                settings_dict = settings.get_dict()

        #check for for allowed keys, ignor unknown keys but warn.
        for key in settings_dict.keys():
            if key not in self._settings_keys:
                #TODO warning
                self.logger.info("settings dict key {} for Fleur calculation"
                                 "not reconized, only {} are allowed."
                                 "".format(key, self._settings_keys))

        # Here, there should be no more parameters...
        if inputdict:
            raise InputValidationError("The following input data nodes are "
                                       "unrecognized: {}".format(
                                           inputdict.keys()))

        ##############################
        # END OF INITIAL INPUT CHECK #

        #
        #######################################################
        ######### PREPARE PARAMETERS FOR INPUT FILE ###########

        #### STRUCTURE_PARAMETERS ####

        scaling_factor_card = ""
        cell_parameters_card = ""

        if not own_lattice:
            cell = structure.cell
            for vector in cell:
                scaled = [a * scaling_pos
                          for a in vector]  #scaling_pos=1./bohr_to_ang
                cell_parameters_card += ("{0:18.10f} {1:18.10f} {2:18.10f}"
                                         "\n".format(scaled[0], scaled[1],
                                                     scaled[2]))
            scaling_factor_card += ("{0:18.10f} {1:18.10f} {2:18.10f}"
                                    "\n".format(scaling_factors[0],
                                                scaling_factors[1],
                                                scaling_factors[2]))

        #### ATOMIC_POSITIONS ####

        # TODO: be careful with units
        atomic_positions_card_list = [""]
        atomic_positions_card_listtmp = [""]
        # Fleur does not have any keyword before the atomic species.
        # first the number of atoms then the form nuclear charge, postion
        # Fleur hast the option of nuclear charge as floats,
        # allows the user to distinguish two atoms and break the symmetry.
        if not own_lattice:
            natoms = len(structure.sites)

            #for FLEUR true, general not, because you could put several
            # atoms on a site
            # TODO: test that only one atom at site?

            # TODO this feature might change in Fleur, do different. that in inpgen kind gets a name, which will also be the name in fleur inp.xml.
            # now user has to make kind_name = atom id.
            for site in structure.sites:
                kind_name = site.kind_name
                kind = structure.get_kind(kind_name)
                if kind.has_vacancies():
                    # then we do not at atoms with weights smaller one
                    if kind.weights[0] < 1.0:
                        natoms = natoms - 1
                        # Log message?
                        continue
                site_symbol = kind.symbols[
                    0]  # TODO: list I assume atoms therefore I just get the first one...
                atomic_number = _atomic_numbers[site_symbol]
                atomic_number_name = atomic_number
                if site_symbol != kind_name:  # This is an important fact, if usere renames it becomes a new species!
                    suc = True
                    try:
                        head = kind_name.rstrip('0123456789')
                        kind_namet = int(kind_name[len(head):])
                    except ValueError:
                        suc = False
                    if suc:
                        atomic_number_name = '{}.{}'.format(
                            atomic_number, kind_namet)
                # per default we use relative coordinates in Fleur
                # we have to scale back to atomic units from angstrom
                pos = site.position

                if bulk:
                    vector_rel = abs_to_rel(pos, cell)
                elif film:
                    vector_rel = abs_to_rel_f(pos, cell, structure.pbc)
                    vector_rel[2] = vector_rel[2] * scaling_pos
                atomic_positions_card_listtmp.append(
                    "    {0:3} {1:18.10f} {2:18.10f} {3:18.10f}"
                    "\n".format(atomic_number_name, vector_rel[0],
                                vector_rel[1], vector_rel[2]))
                #TODO check format
            # we write it later, since we do not know what natoms is before the loop...
            atomic_positions_card_list.append("    {0:3}\n".format(natoms))
            for card in atomic_positions_card_listtmp:
                atomic_positions_card_list.append(card)
        else:
            # TODO with own lattice atomic positions have to come from somewhere
            # else.... User input?
            raise InputValidationError("fleur lattice needs also the atom "
                                       " position as input,"
                                       " not implemented yet, sorry!")
        atomic_positions_card = "".join(atomic_positions_card_list)
        del atomic_positions_card_list  # Free memory

        #### Kpts ####

        # TODO: kpts

        #######################################
        #### WRITE ALL CARDS IN INPUT FILE ####

        input_filename = tempfolder.get_abs_path(self._INPUT_FILE_NAME)

        # TODO:
        with open(input_filename, 'w') as infile:

            #first write title
            infile.write("{0}\n".format(self._inp_title))

            #then write &input namelist
            infile.write("&{0}".format('input'))

            # namelist content; set to {} if not present, so that we leave an
            # empty namelist
            namelist = input_params.pop('input', {})
            for k, val in sorted(namelist.iteritems()):
                infile.write(get_input_data_text(k, val, False, mapping=None))
            infile.write("/\n")

            # Write lattice information now
            infile.write(cell_parameters_card)
            infile.write("{0:18.10f}\n".format(scaling_lat))
            infile.write(scaling_factor_card)
            infile.write("\n")

            # Write Atomic positons
            infile.write(atomic_positions_card)

            # Write namelists after atomic positions
            for namels_name in namelists_toprint:
                namelist = input_params.pop(namels_name, {})
                if namelist:
                    if 'atom' in namels_name:
                        namels_name = 'atom'
                    infile.write("&{0}\n".format(namels_name))
                    if namels_name in val_only_namelist:
                        for k, val in sorted(namelist.iteritems()):
                            infile.write(
                                get_input_data_text(k, val, True,
                                                    mapping=None))
                    else:
                        for k, val in sorted(namelist.iteritems()):
                            infile.write(
                                get_input_data_text(k,
                                                    val,
                                                    False,
                                                    mapping=None))
                    infile.write("/\n")
            #infile.write(kpoints_card)

        if input_params:
            raise InputValidationError(
                "input_params leftover: The following namelists are specified"
                " in input_params, but are "
                "not valid namelists for the current type of calculation: "
                "{}".format(",".join(input_params.keys())))

        calcinfo = CalcInfo()

        calcinfo.uuid = self.uuid

        calcinfo.local_copy_list = local_copy_list
        calcinfo.remote_copy_list = remote_copy_list
        calcinfo.remote_symlink_list = remote_symlink_list

        # Retrieve per default only out file and inp.xml file?
        retrieve_list = []

        # TODO: let the user specify?
        #settings_retrieve_list = settings_dict.pop(
        #                             'ADDITIONAL_RETRIEVE_LIST', [])
        retrieve_list.append(self._INPXML_FILE_NAME)
        retrieve_list.append(self._OUTPUT_FILE_NAME)
        retrieve_list.append(self._SHELLOUT_FILE_NAME)
        retrieve_list.append(self._ERROR_FILE_NAME)
        retrieve_list.append(self._INPUT_FILE_NAME)
        #calcinfo.retrieve_list += settings_retrieve_list
        #calcinfo.retrieve_list += self._internal_retrieve_list

        # user specific retrieve
        add_retrieve = settings_dict.get('additional_retrieve_list', [])
        #print('add_retrieve: {}'.format(add_retrieve))
        for file1 in add_retrieve:
            retrieve_list.append(file1)

        remove_retrieve = settings_dict.get('remove_from_retrieve_list', [])
        for file1 in remove_retrieve:
            if file1 in retrieve_list:
                retrieve_list.remove(file1)

        calcinfo.retrieve_list = []
        for file1 in retrieve_list:
            calcinfo.retrieve_list.append(file1)

        codeinfo = CodeInfo()
        cmdline_params = []

        # user specific commandline_options
        for command in settings_dict.get('cmdline', []):
            cmdline_params.append(command)
        codeinfo.cmdline_params = (list(cmdline_params))

        codeinfo.code_uuid = code.uuid
        codeinfo.stdin_name = self._INPUT_FILE_NAME
        codeinfo.stdout_name = self._SHELLOUT_FILE_NAME  # shell output will be piped in file
        codeinfo.stderr_name = self._ERROR_FILE_NAME  # std error too

        calcinfo.codes_info = [codeinfo]

        return calcinfo
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
Example #8
0
    def _prepare_for_submission(self, tempfolder, inputdict):
        """
        This is the routine to be called when you want to create
        the input files for the inpgen with the plug-in.

        :param tempfolder: a aiida.common.folders.Folder subclass where
                           the plugin should put all its files.
        :param inputdict: a dictionary with the input nodes, as they would
                be returned by get_inputdata_dict (without the Code!)
        """

        #from aiida.common.utils import get_unique_filename, get_suggestion
        #import re

        # 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()
        }

        possible_namelists = self._possible_namelists
        possible_params = self._possible_params
        local_copy_list = []
        remote_copy_list = []
        remote_symlink_list = []
        bulk = True
        film = False

        # convert these 'booleans' to the inpgen format.
        replacer_values_bool = [
            True, False, 'True', 'False', 't', 'T', 'F', 'f'
        ]
        # some keywords require a string " around them in the input file.
        string_replace = ['econfig', 'lo', 'element', 'name']

        # of some keys only the values are writen to the file, specify them here.
        val_only_namelist = ['soc', 'qss']

        # Scaling comes from the Structure
        # but we have to convert from Angstroem to a.u (bohr radii)
        scaling_factors = [1.0, 1.0, 1.0]  #
        scaling_lat = 1.  #/bohr_a
        scaling_pos = 1. / bohr_a  # Angstrom to atomic
        own_lattice = False  #not self._use_aiida_structure

        # The inpfile gen is run in serial TODO: How to do this by default?
        #self.set_withmpi(False)

        ##########################################
        ############# INPUT CHECK ################
        ##########################################

        # first check existence of structure and if 1D, 2D, 3D
        try:
            structure = inputdict.pop(self.get_linkname('structure'))
        except KeyError:
            raise InputValidationError("No structure specified for this"
                                       " calculation")
        if not isinstance(structure, StructureData):
            raise InputValidationError(
                "structure is not of type StructureData")

        pbc = structure.pbc
        if False in pbc:
            bulk = False
            film = True

        # check existence of parameters (optional)
        parameters = inputdict.pop(self.get_linkname('parameters'), None)
        if parameters is None:
            # use default
            parameters_dict = {}
        else:
            if not isinstance(parameters, ParameterData):
                raise InputValidationError(
                    "parameters, if specified, must be of "
                    "type ParameterData")
            parameters_dict = _lowercase_dict(parameters.get_dict(),
                                              dict_name='parameters')

        # we write always out rel coordinates, because thats the way FLEUR uses
        # them best. we have to convert them from abs, becauses thats how they
        #are stored in a Structure node. cartesian=F is default
        if 'input' in parameters_dict:
            parameters_dict['input']['cartesian'] = False
            if film:
                parameters_dict['input']['film'] = True
        else:
            if bulk:
                parameters_dict['input'] = {'cartesian': False}
            elif film:
                parameters_dict['input'] = {'cartesian': False, 'film': True}

        namelists_toprint = possible_namelists

        # check parameters keys TODO: values needed, or keep plug-in as stupid as possible?
        #if parameters_dict:# TODO remove, unnesseary now?
        input_params = parameters_dict
        #TODO:?make everything lowercase in the database, and change it to inpgen format?
        #_lowercase_dict(parameters.get_dict(),
        #dict_name='parameters')
        #input_params = {k: _lowercase_dict(val, dict_name=k)
        #                   for k, val in input_params.iteritems()}
        #input_params_keys = input_params.keys()

        if 'title' in input_params.keys():
            self._inp_title = input_params.pop('title')
        #TODO validate type of values of the input parameter keys ?

        #check input_parameters
        for namelist, paramdic in input_params.iteritems():
            if 'atom' in namelist:  # this namelist can be specified more often
                # special atom namelist needs to be set for writing,
                #  but insert it in the right spot!
                index = namelists_toprint.index('atom') + 1
                namelists_toprint.insert(index, namelist)
                namelist = 'atom'
            if namelist not in possible_namelists:
                raise InputValidationError(
                    "The namelist '{}' is not supported by the fleur"
                    " inputgenerator. Check on the fleur website or add '{}'"
                    "to _possible_namelists.".format(namelist, namelist))
            for para in paramdic.keys():
                if para not in possible_params[namelist]:
                    raise InputValidationError(
                        "The property '{}' is not supported by the "
                        "namelist '{}'. "
                        "Check the fleur website, or if it really is,"
                        " update _possible_params. ".format(para, namelist))
                if paramdic[para] in replacer_values_bool:
                    # because 1/1.0 == True, and 0/0.0 == False
                    # maybe change in convert_to_fortran that no error occurs
                    if isinstance(paramdic[para], (int, float)):
                        if isinstance(paramdic[para], bool):
                            paramdic[para] = convert_to_fortran_bool(
                                paramdic[para])
                    else:
                        paramdic[para] = convert_to_fortran_bool(
                            paramdic[para])

                if para in string_replace:
                    #TODO check if its in the parameter dict
                    #print para
                    paramdic[para] = convert_to_fortran_string(paramdic[para])
                    #print "{}".format(paramdic[para])
            #in fleur it is possible to give a lattice namelist
            if 'lattice' in input_params.keys():
                own_lattice = True
                structure = inputdict.pop(self.get_linkname('structure'), None)
                if structure is not None:  #two structures given?
                    #which one should be prepared? TODO: print warning or even error
                    if self._use_aiida_structure:
                        if not isinstance(structure, StructureData):
                            raise InputValidationError(
                                "structure is not of type"
                                " StructureData")
                        input_params.pop('lattice', {})
                        own_lattice = False
        '''
        # TODO allow only usual kpt meshes and use therefore Aiida kpointData
        if self._use_kpoints:
            try:
                kpoints = inputdict.pop(self.get_linkname('kpoints'))
            except KeyError:
                raise InputValidationError("No kpoints specified for this"
                                           " calculation")
            if not isinstance(kpoints, KpointsData):
                raise InputValidationError("kpoints is not of type KpointsData")
        '''

        #TODO I think the code should not be in the input dict. check local,
        # verus remote, codeinfos, one several codes..
        try:
            code = inputdict.pop(self.get_linkname('code'))
        except KeyError:
            raise InputValidationError("No code specified for this "
                                       "calculation")

        # check existence of settings (optional)
        settings = inputdict.pop(self.get_linkname('settings'), None)
        #print('settings: {}'.format(settings))
        if settings is None:
            settings_dict = {}
        else:
            if not isinstance(settings, ParameterData):
                raise InputValidationError(
                    "settings, if specified, must be of "
                    "type ParameterData")
            else:
                settings_dict = settings.get_dict()
        #check for for allowed keys, ignor unknown keys but warn.
        for key in settings_dict.keys():
            if key not in self._settings_keys:
                #TODO warrning
                self.logger.info("settings dict key {} for Fleur calculation"
                                 "not reconized, only {} are allowed."
                                 "".format(key, self._settings_keys))

        # Here, there should be no more parameters...
        if inputdict:
            raise InputValidationError("The following input data nodes are "
                                       "unrecognized: {}".format(
                                           inputdict.keys()))

        ##############################
        # END OF INITIAL INPUT CHECK #

        #######################################################
        ######### PREPARE PARAMETERS FOR INPUT FILE ###########

        #### STRUCTURE_PARAMETERS ####

        scaling_factor_card = ""
        cell_parameters_card = ""

        if not own_lattice:
            cell = structure.cell
            for vector in cell:
                scaled = [a * scaling_pos
                          for a in vector]  #scaling_pos=1./bohr_a
                cell_parameters_card += ("{0:18.10f} {1:18.10f} {2:18.10f}"
                                         "\n".format(scaled[0], scaled[1],
                                                     scaled[2]))
            scaling_factor_card += ("{0:18.10f} {1:18.10f} {2:18.10f}"
                                    "\n".format(scaling_factors[0],
                                                scaling_factors[1],
                                                scaling_factors[2]))

        #### ATOMIC_POSITIONS ####

        # TODO: be careful with units
        atomic_positions_card_list = [""]
        # Fleur does not have any keyword before the atomic species.
        # first the number of atoms then the form nuclear charge, postion
        # Fleur hast the option of nuclear charge as floats,
        # allows the user to distinguish two atoms and break the symmetry.
        if not own_lattice:
            natoms = len(structure.sites)
            #for FLEUR true, general not, because you could put several
            # atoms on a site
            # TODO: test that only one atom at site?
            atomic_positions_card_list.append("    {0:3}\n".format(natoms))

            # TODO this feature might change in Fleur, do different. that in inpgen kind gets a name, which will also be the name in fleur inp.xml.
            # now user has to make kind_name = atom id.
            for site in structure.sites:
                kind_name = site.kind_name
                site_symbol = structure.get_kind(kind_name).symbols[
                    0]  # TODO: list I assume atoms therefore I just get the first one...
                atomic_number = _atomic_numbers[site_symbol]
                atomic_number_name = atomic_number
                if site_symbol != kind_name:  # This is an important fact, if usere renames it becomes a new species!
                    suc = True
                    try:
                        head = kind_name.rstrip('0123456789')
                        kind_namet = int(kind_name[len(head):])
                    except ValueError:
                        suc = False
                    if suc:
                        atomic_number_name = '{}.{}'.format(
                            atomic_number, kind_namet)
                # per default we use relative coordinates in Fleur
                # we have to scale back to atomic units from angstrom
                pos = site.position
                #print 'pos {}'.format(pos)
                if bulk:
                    vector_rel = abs_to_rel(pos, cell)
                elif film:
                    vector_rel = abs_to_rel_f(pos, cell, structure.pbc)
                    vector_rel[2] = vector_rel[2] * scaling_pos
                atomic_positions_card_list.append(
                    "    {0:3} {1:18.10f} {2:18.10f} {3:18.10f}"
                    "\n".format(atomic_number_name, vector_rel[0],
                                vector_rel[1], vector_rel[2]))
                #print atomic_positions_card_list
                #TODO check format

        else:
            # TODO with own lattice atomic positions have to come from somewhere
            # else.... User input?
            raise InputValidationError("fleur lattice needs also the atom "
                                       " position as input,"
                                       " not implemented yet, sorry!")
        atomic_positions_card = "".join(atomic_positions_card_list)
        del atomic_positions_card_list  # Free memory

        #### Kpts ####

        # TODO: kpts
        #kpoints_card = ""#.join(kpoints_card_list)
        #del kpoints_card_list

        #######################################
        #### WRITE ALL CARDS IN INPUT FILE ####

        input_filename = tempfolder.get_abs_path(self._INPUT_FILE_NAME)

        with open(input_filename, 'w') as infile:

            #first write title
            infile.write("{0}\n".format(self._inp_title))

            #then write &input namelist
            infile.write("&{0}".format('input'))

            # namelist content; set to {} if not present, so that we leave an
            # empty namelist
            namelist = input_params.pop('input', {})
            for k, val in sorted(namelist.iteritems()):
                infile.write(get_input_data_text(k, val, False, mapping=None))
            infile.write("/\n")

            # Write lattice information now
            infile.write(cell_parameters_card)
            infile.write("{0:18.10f}\n".format(scaling_lat))
            infile.write(scaling_factor_card)
            infile.write("\n")

            # Write Atomic positons
            infile.write(atomic_positions_card)

            # Write namelists after atomic positions
            for namels_name in namelists_toprint:
                namelist = input_params.pop(namels_name, {})
                if namelist:
                    if 'atom' in namels_name:
                        namels_name = 'atom'
                    infile.write("&{0}\n".format(namels_name))
                    if namels_name in val_only_namelist:
                        for k, val in sorted(namelist.iteritems()):
                            infile.write(
                                get_input_data_text(k, val, True,
                                                    mapping=None))
                    else:
                        for k, val in sorted(namelist.iteritems()):
                            infile.write(
                                get_input_data_text(k,
                                                    val,
                                                    False,
                                                    mapping=None))
                    infile.write("/\n")
            #infile.write(kpoints_card)

        if input_params:
            raise InputValidationError(
                "input_params leftover: The following namelists are specified"
                " in input_params, but are "
                "not valid namelists for the current type of calculation: "
                "{}".format(",".join(input_params.keys())))

        calcinfo = CalcInfo()

        calcinfo.uuid = self.uuid

        calcinfo.local_copy_list = local_copy_list
        calcinfo.remote_copy_list = remote_copy_list
        calcinfo.remote_symlink_list = remote_symlink_list

        # Retrieve per default only out file and inp.xml file?
        retrieve_list = []

        # TODO: let the user specify?
        #settings_retrieve_list = settings_dict.pop(
        #                             'ADDITIONAL_RETRIEVE_LIST', [])
        retrieve_list.append(self._INPXML_FILE_NAME)
        retrieve_list.append(self._OUTPUT_FILE_NAME)
        retrieve_list.append(self._SHELLOUT_FILE_NAME)
        retrieve_list.append(self._ERROR_FILE_NAME)
        retrieve_list.append(self._STRUCT_FILE_NAME)
        retrieve_list.append(self._INPUT_FILE_NAME)
        #calcinfo.retrieve_list += settings_retrieve_list
        #calcinfo.retrieve_list += self._internal_retrieve_list

        # user specific retrieve
        add_retrieve = settings_dict.get('additional_retrieve_list', [])
        #print('add_retrieve: {}'.format(add_retrieve))
        for file1 in add_retrieve:
            retrieve_list.append(file1)

        remove_retrieve = settings_dict.get('remove_from_retrieve_list', [])
        for file1 in remove_retrieve:
            if file1 in retrieve_list:
                retrieve_list.remove(file1)

        calcinfo.retrieve_list = []
        for file1 in retrieve_list:
            calcinfo.retrieve_list.append(file1)

        codeinfo = CodeInfo()
        cmdline_params = ["-explicit"]  # TODO? let the user decide -econfig?

        # user specific commandline_options
        for command in settings_dict.get('cmdline', []):
            cmdline_params.append(command)
        codeinfo.cmdline_params = (list(cmdline_params))

        codeinfo.code_uuid = code.uuid
        codeinfo.stdin_name = self._INPUT_FILE_NAME
        codeinfo.stdout_name = self._SHELLOUT_FILE_NAME  # shell output will be piped in file
        codeinfo.stderr_name = self._ERROR_FILE_NAME  # std error too

        calcinfo.codes_info = [codeinfo]
        '''
        if settings_dict:
            try:
                Parserclass = self.get_parserclass()
                parser = Parserclass(self)
                parser_opts = parser.get_parser_settings_key()
                settings_dict.pop(parser_opts)
            except (KeyError, AttributeError): # the key parser_opts isn't
                                              # inside the dictionary
                raise InputValidationError(
                    "The following keys have been found in the settings "
                    "input node, but were not understood: {}"
                    "".format(",".join(settings_dict.keys())))
        '''
        return calcinfo
Example #9
0
    def _prepare_for_submission(self, tempfolder, inputdict):
        """
        This is the routine to be called when you want to create
        the input files and related stuff with a plugin.

        :param tempfolder: a aiida.common.folders.Folder subclass where
                           the plugin should put all its files.
        :param inputdict: a dictionary with the input nodes, as they would
                be returned by get_inputdata_dict (without the Code!)
        """

        local_copy_list = []
        remote_copy_list = []

        # Process the settings dictionary first
        # Settings can be undefined, and defaults to an empty dictionary
        settings = inputdict.pop(self.get_linkname('settings'), None)
        if settings is None:
            settings_dict = {}
        else:
            if not isinstance(settings, ParameterData):
                raise InputValidationError(
                    "settings, if specified, must be of "
                    "type ParameterData")

            # Settings converted to UPPERCASE
            # Presumably to standardize the usage and avoid
            # ambiguities
            settings_dict = _uppercase_dict(settings.get_dict(),
                                            dict_name='settings')

        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 is not of type "
                                       "ParameterData")

        # Basis can be undefined, and defaults to an empty dictionary,
        # Siesta will use default parameters
        basis = inputdict.pop(self.get_linkname('basis'), None)
        if basis is None:
            input_basis = {}
        else:
            if not isinstance(basis, ParameterData):
                raise InputValidationError("basis not of type ParameterData")


#            input_basis=FDFDict(basis.get_dict())
            input_basis = basis.get_dict()

        try:
            structure = inputdict.pop(self.get_linkname('structure'))
        except KeyError:
            raise InputValidationError("No structure specified for this "
                                       "calculation")
        if not isinstance(structure, StructureData):
            raise InputValidationError(
                "structure is not of type StructureData")

        # k-points
        # It is now possible to elide the kpoints node.
        #
        # Note also that a *different* set of k-points is needed if a band
        # calculation is carried out. This should be specified somehow in
        # the 'settings' dictionary (see QE example...)

        kpoints = inputdict.pop(self.get_linkname('kpoints'), None)
        if kpoints is None:
            # Do nothing. Assume it is a gamma-point calculation
            pass
        else:
            if not isinstance(kpoints, KpointsData):
                raise InputValidationError("kpoints, if specified, must be of "
                                           "type KpointsData")

        bandskpoints = inputdict.pop(self.get_linkname('bandskpoints'), None)
        if bandskpoints is None:
            flagbands = False
        else:
            flagbands = True
            if not isinstance(bandskpoints, KpointsData):
                raise InputValidationError(
                    "kpoints for bands is not of type KpointsData")

        pseudos = {}
        # I create here a dictionary that associates each kind name to a pseudo
        for link in inputdict.keys():
            if link.startswith(self._get_linkname_pseudo_prefix()):
                kindstring = link[len(self._get_linkname_pseudo_prefix()):]
                kinds = kindstring.split('_')
                the_pseudo = inputdict.pop(link)
                if not isinstance(the_pseudo, PsfData):
                    raise InputValidationError("Pseudo for kind(s) {} is not "
                                               " of type PsfData".format(
                                                   ",".join(kinds)))
                #
                # Note that we can associate the same pseudo object to different
                # atom kinds
                #
                for kind in kinds:
                    pseudos[kind] = the_pseudo

        parent_calc_folder = inputdict.pop(self.get_linkname('parent_folder'),
                                           None)
        if parent_calc_folder is not None:
            if not isinstance(parent_calc_folder, RemoteData):
                raise InputValidationError("parent_calc_folder, if specified,"
                                           "must be of type RemoteData")

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

        # Here, there should be no more parameters...
        if inputdict:
            raise InputValidationError("The following input data nodes are "
                                       "unrecognized: {}".format(
                                           inputdict.keys()))

        # Check structure, get species, check peudos
        kindnames = [k.name for k in structure.kinds]
        if set(kindnames) != set(pseudos.keys()):
            err_msg = ("Mismatch between the defined pseudos and the list of "
                       "kinds of the structure. Pseudos: {}; kinds: {}".format(
                           ",".join(pseudos.keys()),
                           ",".join(list(kindnames))))
            raise InputValidationError(err_msg)

        ##############################
        # END OF INITIAL INPUT CHECK #
        ##############################

        #
        # There should be a warning for duplicated (canonicalized) keys
        # in the original dictionary in the script

        input_params = FDFDict(parameters.get_dict())

        # Look for blocked keywords and
        # add the proper values to the dictionary

        for blocked_key in self._aiida_blocked_keywords:
            canonical_blocked = FDFDict.translate_key(blocked_key)
            for key in input_params:
                if key == canonical_blocked:
                    raise InputValidationError(
                        "You cannot specify explicitly the '{}' flag in the "
                        "input parameters".format(
                            input_params.get_last_key(key)))

        input_params.update({'system-name': self._PREFIX})
        input_params.update({'system-label': self._PREFIX})
        input_params.update({'use-tree-timer': 'T'})
        input_params.update({'xml-write': 'T'})

        input_params.update({'number-of-species': len(structure.kinds)})
        input_params.update({'number-of-atoms': len(structure.sites)})
        #
        # Regarding the lattice-constant parameter:
        # -- The variable "alat" is not typically kept anywhere, and
        # has already been used to define the vectors.
        # We need to specify that the units of these vectors are Ang...

        input_params.update({'lattice-constant': '1.0 Ang'})

        # Note that this  will break havoc with the band-k-points "pi/a"
        # option. The use of this option should be banned.

        # Note that the implicit coordinate convention of the Structure
        # class corresponds to the "Ang" convention in Siesta.
        # That is why the "atomic-coordinates-format" keyword is blocked
        # and reset.
        input_params.update({'atomic-coordinates-format': 'Ang'})

        # ============== Preparation of input data ===============
        #

        # ------------ CELL_PARAMETERS -----------
        cell_parameters_card = "%block lattice-vectors\n"
        for vector in structure.cell:
            cell_parameters_card += ("{0:18.10f} {1:18.10f} {2:18.10f}"
                                     "\n".format(*vector))
        cell_parameters_card += "%endblock lattice-vectors\n"

        # ------------- ATOMIC_SPECIES ------------
        # I create the subfolder that will contain the pseudopotentials
        tempfolder.get_subfolder(self._PSEUDO_SUBFOLDER, create=True)
        # I create the subfolder with the output data
        tempfolder.get_subfolder(self._OUTPUT_SUBFOLDER, create=True)

        atomic_species_card_list = []

        # Dictionary to get the atomic number of a given element
        datmn = dict([(v['symbol'], k) for k, v in elements.iteritems()])

        spind = {}
        spcount = 0
        for kind in structure.kinds:

            ps = pseudos[kind.name]

            # I add this pseudo file to the list of files to copy,
            # with the appropiate name
            local_copy_list.append((ps.get_file_abs_path(),
                                    os.path.join(self._PSEUDO_SUBFOLDER,
                                                 kind.name + ".psf")))
            spcount += 1
            spind[kind.name] = spcount
            atomic_species_card_list.append("{0:5} {1:5} {2:5}\n".format(
                spind[kind.name], datmn[kind.symbol], kind.name.rjust(6)))

        atomic_species_card_list = (["%block chemicalspecieslabel\n"] +
                                    list(atomic_species_card_list))
        atomic_species_card = "".join(atomic_species_card_list)
        atomic_species_card += "%endblock chemicalspecieslabel\n"
        # Free memory
        del atomic_species_card_list

        # ------------ ATOMIC_POSITIONS -----------
        atomic_positions_card_list = [
            "%block atomiccoordinatesandatomicspecies\n"
        ]
        countatm = 0
        for site in structure.sites:
            countatm += 1
            atomic_positions_card_list.append(
                "{0:18.10f} {1:18.10f} {2:18.10f} {3:4} {4:6} {5:6}\n".format(
                    site.position[0], site.position[1], site.position[2],
                    spind[site.kind_name], site.kind_name.rjust(6), countatm))
        atomic_positions_card = "".join(atomic_positions_card_list)
        del atomic_positions_card_list  # Free memory
        atomic_positions_card += "%endblock atomiccoordinatesandatomicspecies\n"

        # --------------- K-POINTS ----------------
        if kpoints is not None:
            #
            # Get a mesh for sampling
            # NOTE that there is not yet support for the 'kgrid-cutoff'
            # option in Siesta.
            #
            try:
                mesh, offset = kpoints.get_kpoints_mesh()
                has_mesh = True
            except AttributeError:
                raise InputValidationError("K-point sampling for scf "
                                           "must be given in mesh form")

            kpoints_card_list = ["%block kgrid_monkhorst_pack\n"]
            #
            # This will fail if has_mesh is False (for the case of a list),
            # since in that case 'offset' is undefined.
            #
            kpoints_card_list.append("{0:6} {1:6} {2:6} {3:18.10f}\n".format(
                mesh[0], 0, 0, offset[0]))
            kpoints_card_list.append("{0:6} {1:6} {2:6} {3:18.10f}\n".format(
                0, mesh[1], 0, offset[1]))
            kpoints_card_list.append("{0:6} {1:6} {2:6} {3:18.10f}\n".format(
                0, 0, mesh[2], offset[2]))

            kpoints_card = "".join(kpoints_card_list)
            kpoints_card += "%endblock kgrid_monkhorst_pack\n"
            del kpoints_card_list

        # --------------- K-POINTS-FOR-BANDS ----------------!
        #This part is computed only if flagbands=True
        #Two possibility are supported in Siesta: BandLines ad BandPoints
        #At the moment the user can't choose directly one of the two options
        #BandsLine is set automatically if bandskpoints has labels,
        #BandsPoints if bandskpoints has no labels
        #BandLinesScale =pi/a is not supported at the moment because currently
        #a=1 always. BandLinesScale ReciprocalLatticeVectors is always set
        if flagbands:
            bandskpoints_card_list = [
                "BandLinesScale ReciprocalLatticeVectors\n"
            ]
            if bandskpoints.labels == None:
                bandskpoints_card_list.append("%block BandPoints\n")
                for s in bandskpoints.get_kpoints():
                    bandskpoints_card_list.append(
                        "{0:8.3f} {1:8.3f} {2:8.3f} \n".format(
                            s[0], s[1], s[2]))
                fbkpoints_card = "".join(bandskpoints_card_list)
                fbkpoints_card += "%endblock BandPoints\n"
            else:
                bandskpoints_card_list.append("%block BandLines\n")
                savs = []
                listforbands = bandskpoints.get_kpoints()
                for s, m in bandskpoints.labels:
                    savs.append(s)
                rawindex = 0
                for s, m in bandskpoints.labels:
                    rawindex = rawindex + 1
                    x, y, z = listforbands[s]
                    if rawindex == 1:
                        bandskpoints_card_list.append(
                            "{0:3} {1:8.3f} {2:8.3f} {3:8.3f} {4:1} \n".format(
                                1, x, y, z, m))
                    else:
                        bandskpoints_card_list.append(
                            "{0:3} {1:8.3f} {2:8.3f} {3:8.3f} {4:1} \n".format(
                                s - savs[rawindex - 2], x, y, z, m))
                fbkpoints_card = "".join(bandskpoints_card_list)
                fbkpoints_card += "%endblock BandLines\n"
            del bandskpoints_card_list

        # ================ Namelists and cards ===================

        input_filename = tempfolder.get_abs_path(self._INPUT_FILE_NAME)

        with open(input_filename, 'w') as infile:
            # here print keys and values tp file

            for k, v in sorted(input_params.iteritems()):
                infile.write(get_input_data_text(k, v))
                # ,mapping=mapping_species))

            # Basis set info is processed just like the general
            # parameters section. Some discipline is needed to
            # put any basis-related parameters (including blocks)
            # in the basis dictionary in the input script.
            #
            if basis is not None:
                infile.write("#\n# -- Basis Set Info follows\n#\n")
                for k, v in input_basis.iteritems():
                    infile.write(get_input_data_text(k, v))

            # Write previously generated cards now
            infile.write("#\n# -- Structural Info follows\n#\n")
            infile.write(atomic_species_card)
            infile.write(cell_parameters_card)
            infile.write(atomic_positions_card)
            if kpoints is not None:
                infile.write("#\n# -- K-points Info follows\n#\n")
                infile.write(kpoints_card)
            if flagbands:
                infile.write("#\n# -- Bandlines/Bandpoints Info follows\n#\n")
                infile.write(fbkpoints_card)

            # Write max wall-clock time
            infile.write("#\n# -- Max wall-clock time block\n#\n")
            infile.write("max.walltime {}".format(
                self.get_max_wallclock_seconds()))

        # ------------------------------------- END of fdf file creation

        # operations for restart

        # The presence of a 'parent_calc_folder' input node signals
        # that we want to get something from there, as indicated in the
        # self._restart_copy_from attribute.
        # In Siesta's case, for now, it is just the density-matrix file
        #
        # It will be copied to the current calculation's working folder.

        if parent_calc_folder is not None:
            remote_copy_list.append(
                (parent_calc_folder.get_computer().uuid,
                 os.path.join(parent_calc_folder.get_remote_path(),
                              self._restart_copy_from), self._restart_copy_to))

        calcinfo = CalcInfo()

        calcinfo.uuid = self.uuid
        #
        # Empty command line by default
        # Why use 'pop' ?
        cmdline_params = settings_dict.pop('CMDLINE', [])

        # Comment this paragraph better, if applicable to Siesta
        #
        #we commented calcinfo.stin_name and added it here in cmdline_params
        #in this way the mpirun ... pw.x ... < aiida.in
        #is replaced by mpirun ... pw.x ... -in aiida.in
        # in the scheduler, _get_run_line, if cmdline_params is empty, it
        # simply uses < calcinfo.stin_name

        if cmdline_params:
            calcinfo.cmdline_params = list(cmdline_params)
        calcinfo.local_copy_list = local_copy_list
        calcinfo.remote_copy_list = remote_copy_list

        calcinfo.stdin_name = self._INPUT_FILE_NAME
        calcinfo.stdout_name = self._OUTPUT_FILE_NAME
        calcinfo.xml_name = self._XML_FILE_NAME
        calcinfo.json_name = self._JSON_FILE_NAME
        calcinfo.messages_name = self._MESSAGES_FILE_NAME

        #
        # Code information object
        #
        codeinfo = CodeInfo()
        codeinfo.cmdline_params = list(cmdline_params)
        codeinfo.stdin_name = self._INPUT_FILE_NAME
        codeinfo.stdout_name = self._OUTPUT_FILE_NAME
        codeinfo.xml_name = self._XML_FILE_NAME
        codeinfo.json_name = self._JSON_FILE_NAME
        codeinfo.messages_name = self._MESSAGES_FILE_NAME
        codeinfo.code_uuid = code.uuid
        calcinfo.codes_info = [codeinfo]

        # Retrieve by default: the output file, the xml file, and the
        # messages file.
        # If flagbands=True we also add the bands file to the retrieve list!
        # This is extremely important because the parser parses the bands
        # only if aiida.bands is in the retrieve list!!

        calcinfo.retrieve_list = []
        calcinfo.retrieve_list.append(self._OUTPUT_FILE_NAME)
        calcinfo.retrieve_list.append(self._XML_FILE_NAME)
        calcinfo.retrieve_list.append(self._JSON_FILE_NAME)
        calcinfo.retrieve_list.append(self._MESSAGES_FILE_NAME)
        if flagbands:
            calcinfo.retrieve_list.append(self._BANDS_FILE_NAME)

        # Any other files specified in the settings dictionary
        settings_retrieve_list = settings_dict.pop('ADDITIONAL_RETRIEVE_LIST',
                                                   [])
        calcinfo.retrieve_list += settings_retrieve_list

        return calcinfo
Example #10
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
Example #11
0
def break_symmetry(structure,
                   atoms=['all'],
                   site=[],
                   pos=[],
                   new_kinds_names={},
                   parameterData=None):
    """
    This routine introduces different 'kind objects' in a structure
    and names them that inpgen will make different species/atomgroups out of them.
    If nothing specified breaks ALL symmetry (i.e. every atom gets their own kind)

    params: StructureData
    params: atoms: python list of symbols, exp: ['W', 'Be']. This would make for
                   all Be and W atoms their own kinds.
    params: site: python list of integers, exp: [1, 4, 8]. This would create for
                  atom 1, 4 and 8 their own kinds.
    params: pos: python list of tuples of 3, exp [(0.0, 0.0, -1.837927), ...].
                 This will create a new kind for the atom at that position.
                 Be carefull the number given has to match EXACTLY the position
                 in the structure.

    return: StructureData, a AiiDA crystal structure with new kind specification.
    """
    # TODO proper input checks?
    from aiida.common.constants import elements as PeriodicTableElements

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

    #get all atoms, get the symbol of the atom
    #if wanted make individual kind for that atom
    #kind names will be atomsymbol+number
    #create new structure with new kinds and atoms
    #Param = DataFactory('parameter')
    symbol_count = {
    }  # Counts the atom symbol occurence to set id's and kind names right
    replace = []  # all atoms symbols ('W') to be replaced
    replace_siteN = []  # all site integers to be replaced
    replace_pos = []  #all the atom positions to be replaced
    new_parameterd = None
    struc = is_structure(structure)
    if not struc:
        print 'Error, no structure given'
        # throw error?

    cell = struc.cell
    pbc = struc.pbc
    sites = struc.sites
    #natoms = len(sites)
    new_structure = DataFactory('structure')(cell=cell, pbc=pbc)

    for sym in atoms:
        replace.append(sym)
    for position in pos:
        replace_pos.append(position)
    for atom in site:
        replace_siteN.append(atom)

    if parameterData:
        para = parameterData.get_dict()
        new_parameterd = dict(para)
    else:
        new_parameterd = {}

    for i, site in enumerate(sites):
        kind_name = site.kind_name
        pos = site.position
        kind = struc.get_kind(kind_name)
        symbol = kind.symbol
        replace_kind = False

        if symbol in replace or 'all' in replace:
            replace_kind = True
        if pos in replace_pos:
            replace_kind = True
        if i in replace_siteN:
            replace_kind = True

        if replace_kind:
            if symbol in symbol_count:
                symbol_count[symbol] = symbol_count[symbol] + 1
                symbol_new_kinds_names = new_kinds_names.get(symbol, [])
                print(symbol_new_kinds_names)
                if symbol_new_kinds_names and ((len(symbol_new_kinds_names))
                                               == symbol_count[symbol]):
                    newkindname = symbol_new_kinds_names[symbol_count[symbol] -
                                                         1]
                else:
                    newkindname = '{}{}'.format(symbol, symbol_count[symbol])
            else:
                symbol_count[symbol] = 1
                symbol_new_kinds_names = new_kinds_names.get(symbol, [])
                #print(symbol_new_kinds_names)
                if symbol_new_kinds_names and ((len(symbol_new_kinds_names))
                                               == symbol_count[symbol]):
                    newkindname = symbol_new_kinds_names[symbol_count[symbol] -
                                                         1]
                else:
                    newkindname = '{}{}'.format(symbol, symbol_count[symbol])
            #print(newkindname)
            new_kind = Kind(name=newkindname, symbols=symbol)
            new_structure.append_kind(new_kind)

            # now we have to add an atom list to parameterData with the corresponding id.
            if parameterData:
                id_a = symbol_count[
                    symbol]  #'{}.{}'.format(charge, symbol_count[symbol])
                #print 'id: {}'.format(id)
                for key, val in para.iteritems():
                    if 'atom' in key:
                        if val.get('element', None) == symbol:
                            if id_a and id_a == val.get('id', None):
                                break  # we assume the user is smart and provides a para node,
                                # which incooperates the symmetry breaking already
                            elif id_a:  # != 1: # copy parameter of symbol and add id
                                val_new = dict(val)
                                # getting the charge over element might be risky
                                charge = _atomic_numbers.get(
                                    (val.get('element')))
                                idp = '{}.{}'.format(charge,
                                                     symbol_count[symbol])
                                idp = float("{0:.2f}".format(float(idp)))
                                # dot cannot be stored in AiiDA dict...
                                val_new.update({u'id': idp})
                                atomlistname = 'atom{}'.format(id_a)
                                i = 0
                                while new_parameterd.get(atomlistname, {}):
                                    i = i + 1
                                    atomlistname = 'atom{}'.format(id_a + i)

                                symbol_new_kinds_names = new_kinds_names.get(
                                    symbol, [])
                                #print(symbol_new_kinds_names)
                                if symbol_new_kinds_names and (
                                    (len(symbol_new_kinds_names))
                                        == symbol_count[symbol]):
                                    species_name = symbol_new_kinds_names[
                                        symbol_count[symbol] - 1]
                                val_new.update({u'name': species_name})

                                new_parameterd[atomlistname] = val_new
            else:
                pass
                #TODO write basic parameter data node
        else:
            newkindname = kind_name
            if not kind_name in new_structure.get_kind_names():
                new_structure.append_kind(kind)
        new_structure.append_site(Site(kind_name=newkindname, position=pos))

    #print 'natoms: {}, nkinds: {}'.format(natoms, len(new_structure.get_kind_names()))

    if parameterData:
        para_new = ParameterData(dict=new_parameterd)
    else:
        para_new = None

    new_structure.label = structure.label
    new_structure.description = structure.description + 'more kinds, less sym'

    return new_structure, para_new