Exemple #1
0
def getInterstitials(ase_in,inter,spinpol):

	pmg_init	= AseAtomsAdaptor.get_structure(ase_in)
	pmg_init2 	= SpacegroupAnalyzer(pmg_init).get_conventional_standard_structure()
	
	interstitial = Interstitial(pmg_init2,None,covalent_radii) #accuracy=high breaks...
	os.system('cls' if os.name == 'nt' else 'clear')
	output = []
	for i,site in enumerate(interstitial.enumerate_defectsites()):
		coordination =  int(round(interstitial.get_defectsite_coordination_number(i)))
		mult 	= 0 # interstitial.get_defectsite_multiplicity(i) -- broken ???
		insert  = InsertSitesTransformation([inter],[site.coords],coords_are_cartesian=True)
		try:
			pmg_new = insert.apply_transformation(pmg_init2.copy())
			ase_new = AseAtomsAdaptor.get_atoms(pmg_new)

			if   coordination == 4: siteName='T'
			elif coordination == 6: siteName='O'
			else: siteName = '%d-fold'%coordination
			strname = '_%s-%s'%(inter,siteName)


			if spinpol: 
				new_magmoms = [3 if e in misc.magElems else 0 for e in ase_new.get_chemical_symbols()]
				ase_new.set_initial_magnetic_moments(new_magmoms)

			output.append((ase_new,strname))
		except ValueError: pass #ValueError: New site is too close to an existing site!



	return output
Exemple #2
0
def vac_intl(cellmax=2, mpid='', struct=None):
    """
    Vacancy and interstitial generator

    Args:
        cellmax: maximum cell size
        struct: Structure object
    Returns:
            def_str: defect structures
    """

    if struct == None:
        with MPRester() as mp:
            struct = mp.get_structure_by_material_id(mpid)
        if mpid == '':
            print("Provide structure")
    sg_mat = SpacegroupAnalyzer(struct)
    struct = sg_mat.get_conventional_standard_structure()
    def_str = []
    count = 0
    cell_arr = [cellmax, cellmax, cellmax]
    vac = Vacancy(struct, {}, {})
    for el in list(struct.symbol_set):

        scs = vac.make_supercells_with_defects(cell_arr, el)
        for i in range(len(scs)):
            if i == 0:
                pos = Poscar(scs[i])
                pos.comment = str('bulk') + str('.') + str('cellmax') + str(
                    cellmax)
                if count == 0:
                    def_str.append(pos)
                    count = count + 1
            else:
                pos = Poscar(scs[i])
                pos.comment = str('vac') + str('cellmax') + str(cellmax) + str(
                    '@') + str(vac.get_defectsite_multiplicity(i)) + str(
                        'Element') + str(el)
                if pos not in def_str:
                    def_str.append(pos)
    struct_valrad_eval = ValenceIonicRadiusEvaluator(struct)
    val = struct_valrad_eval.valences
    rad = struct_valrad_eval.radii
    struct_val = val
    struct_rad = rad
    intl = Interstitial(struct, val, rad)

    for el in struct.composition.elements:
        scs = intl.make_supercells_with_defects(cell_arr, el)
        for i in range(1, len(scs)):
            pos = Poscar(scs[i])
            pos.comment = str('intl') + str('cellmax') + str(cellmax) + str(
                '@') + str(intl.get_defectsite_coordination_number(
                    i - 1)) + str('Element') + str(el)
            if pos not in def_str:
                def_str.append(pos)
    print(len(def_str))
    return def_str
Exemple #3
0
    def get_interstitials(self):

        evaluator = ValenceIonicRadiusEvaluator(
            self.structure)  # computes site valence and ionic radii using bond valence analyser.
        # note this uses the sites, periodic table, bond valence, composition and local env packages! (as well as structure)
        radii = evaluator.radii
        valences = evaluator.valences

        #get the voronoi sites
        interstitial = Interstitial(self.structure, radii = radii, valences = valences,
                                         symmetry_flag = self.settings_obj.sym_dist)
        # this evaluates the structure and uses radii and valence to generate voronoi sites depending on whether vertex,
        # facecenter or edge center is selected.
        # note: not sure if hsould set oxi_state = False. By default it is true and it then uses ionic radii in the calculation,
        #  shouldnt really change centres? Returns and interstitial object. ._defect_sites returns the coordinates and labels of
        #  all intersittial sites which were found from the voronoi nodes/edges/faces/all depending on settings.
        # sym if False so we get all sites, including symmetry inequivalent sites!

        # structure the list of interstitial sites as a tuple with the voronoi radius in there
        interstitial_sites = [
            ([site._fcoords[0], site._fcoords[1], site._fcoords[2]], site.properties.get('voronoi_radius', None))
            for site in interstitial._defect_sites]  # this creates a list of tuples: [ (array of site location
        # fractional coordinates, Voronoi radius') ]

        # shift vornoi sites up if they were previously shifted down
        interstitial_sites = [([i[0][0] * self.structure.lattice.a - self.downwards_shifts[0][0],
                                     i[0][1] * self.structure.lattice.b - self.downwards_shifts[1][1],
                                     i[0][2] * self.structure.lattice.c - self.downwards_shifts[2][2]],
                                    i[1]) for i in
                                   interstitial_sites]  # shift it and convert to cart coords at the same time

        return interstitial_sites
    def apply_transformation(self, structure, return_ranked_list=False):
        """
        :param structure:
        :param return_ranked_list (Logical or integer): Use big enough
         number to return all defect structures
        :return:
            scs: Supercells with one interstitial defect in each structure.
        """
        if not return_ranked_list:
            raise ValueError("InterstitialTransformation has no single best "
                             "structure output. Must use return_ranked_list.")
        try:
            num_to_return = int(return_ranked_list)
        except ValueError:
            num_to_return = 1

        if self.radii:
            inter = Interstitial(structure, self.valences, self.radii)
        else:
            s = structure.copy()
            valrad_eval = ValenceIonicRadiusEvaluator(s)
            s = valrad_eval.structure
            val = valrad_eval.valences
            rad = valrad_eval.radii
            inter = Interstitial(s, val, rad, oxi_state=True)

        scs = inter.make_supercells_with_defects(self.supercell_dim,
                                                 self.inter_specie)

        #if num_to_return < len(scs)-1:
        #    raise ValueError("InterstitialTransformation has no ordering "
        #            "of best structures. Must increase return_ranked_list.")

        structures = []
        num_to_return = min(num_to_return, len(scs) - 1)
        for sc in scs[1:num_to_return + 1]:
            structures.append({'structure': sc})
        return structures
    def apply_transformation(self, structure, return_ranked_list=False):
        """
        :param structure:
        :param return_ranked_list (Logical or integer): Use big enough
         number to return all defect structures
        :return:
            scs: Supercells with one interstitial defect in each structure.
        """
        if not return_ranked_list:
            raise ValueError("InterstitialTransformation has no single best "
                    "structure output. Must use return_ranked_list.")
        try:
            num_to_return = int(return_ranked_list)
        except ValueError:
            num_to_return = 1

        if self.radii:
            inter = Interstitial(structure, self.valences, self.radii)
        else:
            s = structure.copy()
            valrad_eval = ValenceIonicRadiusEvaluator(s)
            s = valrad_eval.structure
            val = valrad_eval.valences
            rad = valrad_eval.radii
            inter = Interstitial(s,val,rad,oxi_state=True)

        scs = inter.make_supercells_with_defects(
            self.supercell_dim, self.inter_specie)

        #if num_to_return < len(scs)-1:
        #    raise ValueError("InterstitialTransformation has no ordering "
        #            "of best structures. Must increase return_ranked_list.")

        structures = []
        num_to_return = min(num_to_return,len(scs)-1)
        for sc in scs[1:num_to_return+1]:
            structures.append({'structure':sc})
        return structures
Exemple #6
0
def inject_ions(structure, ion, atomic_fraction):
    """
    Adds ions to a percentage of interstitial sites into a structure
    that results in an at% less than or equal to the specified
    atomic_fraction. Starts by filling interstitial sites with the
    largest voronoi radius, and then works downward.

    Args:
        structure (Structure): Pymatgen Structure object to
            intercalate into.
        ion (str): name of atom to intercalate, e.g. 'Li', or 'Mg'.
        atomic_fraction (int): This fraction of the final intercalated
            structure will be intercalated atoms. Must be < 1.0.

    Returns:
        structure. Includes intercalated atoms.
    """

    specie = Element(ion)

    # If the structure isn't big enough to accomodate such a small
    # atomic fraction, multiply it in the x direction.
    n_ions = 1.
    while not n_ions / structure.num_sites <= atomic_fraction:
        structure.make_supercell([2, 1, 1])

    evaluator = ValenceIonicRadiusEvaluator(structure)
    interstitial = Interstitial(structure, radii=evaluator.radii,
                                valences=evaluator.valences)

    interstitial_sites = [
        (site._fcoords, site.properties.get('voronoi_radius', None))
        for site in interstitial._defect_sites]

    # Sort the interstitial sites by their voronoi radii.
    interstitial_sites.sort(key=operator.itemgetter(1))
    interstitial_sites.reverse()

    i = 0
    while n_ions / (structure.num_sites + 1) <= atomic_fraction:
        try:
            structure.append(species=specie, coords=interstitial_sites[i][0],
                             validate_proximity=True)
            n_ions += 1
            i += 1

            evaluator = ValenceIonicRadiusEvaluator(structure)
            interstitial = Interstitial(structure, radii=evaluator.radii,
                                        valences=evaluator.valences)

            interstitial_sites = [
                (site._fcoords, site.properties.get('voronoi_radius', None))
                for site in interstitial._defect_sites]

            # Sort the interstitial sites by their voronoi radii.
            interstitial_sites.sort(key=operator.itemgetter(1))
            interstitial_sites.reverse()

        except ValueError:
            i += 1

        except IndexError:
            raise ValueError('The atomic_fraction specified exceeds the '
                             'number of available interstitial sites in this '
                             'structure. Please choose a smaller '
                             'atomic_fraction.')

    return structure
Exemple #7
0
def main():
    jIDs = [x[0] for x in plotQuery(['jobid'], CONSTRAINTS)]

    question = "Going to add an %s interstitial to %d bulk objects.\n(y/n)--> " % (
        inter, len(jIDs))

    if raw_input(question).lower() in ['y', 'yes']:
        for j in jIDs:
            aseinitID = query1('aseid', 'jobid', j)
            aseinit = asedb.get_atoms(id=aseinitID)

            # Access information about previous Job / Atoms object
            jobinit = db2object(j)
            xc, pw, kptden = jobinit.xc, jobinit.pw, jobinit.kptden
            psp, xtol, strain = jobinit.psp, jobinit.xtol, jobinit.strain
            precalc, dftcode = jobinit.precalc, jobinit.dftcode
            nameinit = jobinit.name()
            structure = jobinit.structure()
            vacancies = jobinit.vacancies()

            # Create conventional PyMatGen Object
            pmg_init = AseAtomsAdaptor.get_structure(aseinit)
            pmg_init2 = SpacegroupAnalyzer(
                pmg_init).get_conventional_standard_structure()

            interstitial = Interstitial(
                pmg_init2, None, covalent_radii)  #accuracy=high breaks...
            os.system('cls' if os.name == 'nt' else 'clear')

            for i, site in enumerate(interstitial.enumerate_defectsites()):
                coordination = int(
                    round(interstitial.get_defectsite_coordination_number(i)))
                mult = 0  # interstitial.get_defectsite_multiplicity(i) -- broken ???
                insert = InsertSitesTransformation([inter], [site.coords],
                                                   coords_are_cartesian=True)
                pmg_new = insert.apply_transformation(pmg_init2.copy())
                ase_new = AseAtomsAdaptor.get_atoms(pmg_new)

                ase_new.set_calculator(EMT())
                emt = ase_new.get_potential_energy()

                if coordination == 4: siteName = 'T'
                elif coordination == 6: siteName = 'O'
                else: siteName = '%d-fold' % coordination

                question = ('site: %s\ncoordination: %s\nmultiplicity: %s' %
                            (site.coords, coordination, mult) +
                            '\ninitial ase id: %d \nxc: %s \npw: %d ' %
                            (aseinitID, xc, pw) +
                            '\nkptden: %f \npsp: %s\nxtol: %f\nstrain: %f' %
                            (kptden, psp, xtol, strain) +
                            '\nprecalc: %s \ndftcode: %s' %
                            (precalc, dftcode) +
                            '\n\nDoes this structure look good?\n(y/n)--> ')

                view(ase_new)
                if raw_input(question).lower() in ['y', 'yes']:
                    if checkForDuplicates(ase_new, structure, emt):

                        newquestion = 'What structure does this have?\n(leave blank for general triclinic case)\n--> '
                        structure = raw_input(newquestion)
                        if structure is '': structure = 'triclinic'

                        info = {
                            'name': nameinit + '_%s-%s' % (inter, siteName),
                            'emt':
                            emt  # EMT for relaxed structures useless, only relevant for deciding when to relax something
                            ,
                            'relaxed':
                            False  # Could always doing this be a problem?
                            ,
                            'comments': 'Generated from initializeHydride.py',
                            'parent': aseinitID,
                            'kind': 'bulk',
                            'structure': structure,
                            'interstitial': siteName
                        }
                        if vacancies is not None: info['vacancies'] = vacancies

                        newaseid = asedb.write(ase_new, key_value_pairs=info)

                        newjob = Job(None, 'bulkrelax', newaseid, None, None,
                                     xc, pw, kptden, psp, xtol, strain,
                                     2 if xc == 'mBEEF' else 1, precalc,
                                     dftcode, None, None, 'initialized')

                        insertObject(newjob)
    def __init__(
        self,
        settings_obj,
    ):
        self.settings_obj = settings_obj

        try:
            if self.settings_obj.poscar_path:
                self.structure = Structure.from_file(
                    self.settings_obj.poscar_path)
            else:
                self.structure = Structure.from_file('POSCAR')
        except FileNotFoundError as e:
            print(e)
            print(
                'The given filepath for the poscar did not find a poscar file, ensure POSCAR is at the end '
                'e.g. /POSCAR. if no filepath was given then no poscar was found in the current directory.'
            )

        self.no_ions = int(self.settings_obj.int_dens *
                           self.structure.num_sites)

        try:
            if self.settings_obj.locpot_path:
                self.vasp_pot, self.NGX, self.NGY, self.NGZ, self.lattice = md.read_vasp_density(
                    self.settings_obj.locpot_path)
            else:
                self.vasp_pot, self.NGX, self.NGY, self.NGZ, self.lattice = md.read_vasp_density(
                    'LOCPOT')
            self.grid_pot, self.electrons = md.density_2_grid(
                self.vasp_pot, self.NGX, self.NGY,
                self.NGZ)  # generate the grid of potentials

        except FileNotFoundError as e:
            print(e)
            print(
                'The given filepath for the locpot did not find a locpot file, ensure LOCPOT is at the end '
                'e.g. /LOCPOT. if no filepath was given then no locpot was found in the current directory.'
            )

        # then run as normal, once voronoi done and cells found, convert back and carry on
        if not self.check_orthog_lat():
            print('exiting prog')
            sys.exit()
        self.find_vacuums(
        )  #this changes structure to one without vacuum. copies the old structure as self.orig_struct

        self.evaluator = ValenceIonicRadiusEvaluator(
            self.structure
        )  #computes site valence and ionic radii using bond valence analyser.
        # note this uses the sites, periodic table, bond valence, composition and local env packages! (as well as structure)
        self.radii = self.evaluator.radii
        self.valences = self.evaluator.valences

        self.interstitial = Interstitial(
            self.structure,
            radii=self.radii,
            valences=self.valences,
            symmetry_flag=self.settings_obj.sym_dist)
        # this evaluates the structure and uses radii and valence to generate voronoi sites depending on whether vertex,
        # facecenter or edge center is selected.
        # note: not sur eif hsould set oxi_state = False. By default it is true and it then uses ionic radii in the calculation,
        #  shouldnt really change centres? Returns and interstitial object. ._defect_sites returns the coordinates and labels of
        #  all intersittial sites which were found from the voronoi nodes/edges/faces/all depending on settings.
        # sym if False so we get all sites, including symmetry inequivalent sites!

        print('\n')
        self.interstitial_sites = [
            ([site._fcoords[0], site._fcoords[1],
              site._fcoords[2]], site.properties.get('voronoi_radius', None))
            for site in self.interstitial._defect_sites
        ]  # this creates a list of tuples: [ (array of site location
        # fractional coordinates, Voronoi radius') ]
        #  replaced  with self.get_nearest_neighbour_dist(site)

        # shift vornoi up if shifted!
        self.interstitial_sites = [
            ([
                i[0][0] * self.structure.lattice.a -
                self.downwards_shifts[0][0],
                i[0][1] * self.structure.lattice.b -
                self.downwards_shifts[1][1],
                i[0][2] * self.structure.lattice.c -
                self.downwards_shifts[2][2]
            ], i[1]) for i in self.interstitial_sites
        ]  #shift it and convert to cart coords at the same time

        # go back to the original, unshifted structure
        self.shifted_structure = self.structure.copy()
        self.structure = self.orig_struct.copy()
        self.interstitial_sites = [([
            i[0][0] / self.structure.lattice.a,
            i[0][1] / self.structure.lattice.b,
            i[0][2] / self.structure.lattice.c
        ], i[1]) for i in self.interstitial_sites
                                   ]  # convert it back to fractional coords