Пример #1
0
    def test_get_mapping(self):
        sm = StructureMatcher(ltol=0.2,
                              stol=0.3,
                              angle_tol=5,
                              primitive_cell=False,
                              scale=True,
                              attempt_supercell=False,
                              allow_subset=True)
        l = Lattice.orthorhombic(1, 2, 3)
        s1 = Structure(l, ['Ag', 'Si', 'Si'],
                       [[.7, .4, .5], [0, 0, 0.1], [0, 0, 0.2]])
        s1.make_supercell([2, 1, 1])
        s2 = Structure(l, ['Si', 'Si', 'Ag'],
                       [[0, 0.1, -0.95], [0, 0.1, 0], [-.7, .5, .375]])

        shuffle = [2, 0, 1, 3, 5, 4]
        s1 = Structure.from_sites([s1[i] for i in shuffle])
        #test the mapping
        s2.make_supercell([2, 1, 1])
        #equal sizes
        for i, x in enumerate(sm.get_mapping(s1, s2)):
            self.assertEqual(s1[x].species_and_occu, s2[i].species_and_occu)

        del s1[0]
        #s1 is subset of s2
        for i, x in enumerate(sm.get_mapping(s2, s1)):
            self.assertEqual(s1[i].species_and_occu, s2[x].species_and_occu)
        #s2 is smaller than s1
        del s2[0]
        del s2[1]
        self.assertRaises(ValueError, sm.get_mapping, s2, s1)
Пример #2
0
    def test_get_mapping(self):
        sm = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5,
                              primitive_cell=False, scale=True,
                              attempt_supercell=False,
                              allow_subset = True)
        l = Lattice.orthorhombic(1, 2, 3)
        s1 = Structure(l, ['Ag', 'Si', 'Si'],
                       [[.7,.4,.5],[0,0,0.1],[0,0,0.2]])
        s1.make_supercell([2,1,1])
        s2 = Structure(l, ['Si', 'Si', 'Ag'],
                       [[0,0.1,-0.95],[0,0.1,0],[-.7,.5,.375]])

        shuffle = [2,0,1,3,5,4]
        s1 = Structure.from_sites([s1[i] for i in shuffle])
        #test the mapping
        s2.make_supercell([2,1,1])
        #equal sizes
        for i, x in enumerate(sm.get_mapping(s1, s2)):
            self.assertEqual(s1[x].species_and_occu,
                             s2[i].species_and_occu)

        del s1[0]
        #s1 is subset of s2
        for i, x in enumerate(sm.get_mapping(s2, s1)):
            self.assertEqual(s1[i].species_and_occu,
                             s2[x].species_and_occu)
        #s2 is smaller than s1
        del s2[0]
        del s2[1]
        self.assertRaises(ValueError, sm.get_mapping, s2, s1)
Пример #3
0
class observer_spinel(observer_base):
    def __init__(self, Asite_struct, Bspecie):
        super(observer_spinel, self).__init__()
        self.Asite_struct = Asite_struct
        self.Bspecie = Bspecie
        self.site_matcher = StructureMatcher(
            ltol=0.1,
            primitive_cell=False,
            allow_subset=True,
            comparator=FrameworkComparator(),
            ignored_species=["O"],
        )

    def DOI(self, calc_state):
        asites = self.site_matcher.get_mapping(calc_state.config.structure,
                                               self.Asite_struct)
        # print asites
        # print spinel_config.structure
        # print spinel_config.Asite_struct
        x = 0
        for i in asites:
            if calc_state.config.structure.species[i] == Element(self.Bspecie):
                x += 1
        x /= float(len(asites))
        return x

    def logfunc(self, calc_state):
        return calc_state.energy, self.DOI(calc_state)
Пример #4
0
    def test_rms_vs_minimax(self):
        # This tests that structures with adjusted RMS less than stol, but minimax
        # greater than stol are treated properly
        sm = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5, primitive_cell=False)
        l = Lattice.orthorhombic(1, 2, 12)

        sp = ["Si", "Si", "Al"]
        s1 = Structure(l, sp, [[0.5, 0, 0], [0, 0, 0], [0, 0, 0.5]])
        s2 = Structure(l, sp, [[0.5, 0, 0], [0, 0, 0], [0, 0, 0.6]])

        self.assertArrayAlmostEqual(sm.get_rms_dist(s1, s2), (0.32 ** 0.5 / 2, 0.4))

        self.assertEqual(sm.fit(s1, s2), False)
        self.assertEqual(sm.fit_anonymous(s1, s2), False)
        self.assertEqual(sm.get_mapping(s1, s2), None)
Пример #5
0
    def test_rms_vs_minimax(self):
        # This tests that structures with adjusted RMS less than stol, but minimax
        # greater than stol are treated properly
        # stol=0.3 gives exactly an ftol of 0.1 on the c axis
        sm = StructureMatcher(ltol=0.2, stol=0.301, angle_tol=1, primitive_cell=False)
        l = Lattice.orthorhombic(1, 2, 12)

        sp = ["Si", "Si", "Al"]
        s1 = Structure(l, sp, [[0.5, 0, 0], [0, 0, 0], [0, 0, 0.5]])
        s2 = Structure(l, sp, [[0.5, 0, 0], [0, 0, 0], [0, 0, 0.6]])
        self.assertArrayAlmostEqual(sm.get_rms_dist(s1, s2),
                                    (0.32 ** 0.5 / 2, 0.4))

        self.assertEqual(sm.fit(s1, s2), False)
        self.assertEqual(sm.fit_anonymous(s1, s2), False)
        self.assertEqual(sm.get_mapping(s1, s2), None)
Пример #6
0
    def occu_from_structure(self, structure, return_mapping=False):
        """
        Calculates the correlation vector. Structure must be on this supercell
        """
        #calculate mapping to supercell
        sm_no_sc = StructureMatcher(primitive_cell=False,
                                    attempt_supercell=False,
                                    allow_subset=True,
                                    comparator=OrderDisorderElementComparator(),
                                    supercell_size=self.cluster_expansion.supercell_size,
                                    scale=True,
                                    ltol=self.cluster_expansion.ltol,
                                    stol=self.cluster_expansion.stol,
                                    angle_tol=self.cluster_expansion.angle_tol)

        #print('sc:\n',self.supercell_matrix,\
        #      '\nstr:\n',self.cluster_expansion.supercell_matrix_from_structure(structure))
        mapping = sm_no_sc.get_mapping(self.supercell, structure)

        if mapping is None:
            raise ValueError('Structure cannot be mapped to this supercell. Structure:{}\nSupercell:{}'.format(structure,self.supercell))

        mapping = mapping.tolist()
        #cs.supercell[mapping] = structure
        occu = np.zeros(len(self.supercell), dtype=np.int)
        for i, bit in enumerate(self.bits):
            # print('i=',i)
            # print('bit=', bit)
            #rather than starting with all vacancies and looping
            #only over mapping, explicitly loop over everything to
            #catch vacancies on improper sites
            if i in mapping:
                sp = str(structure[mapping.index(i)].specie)
            else:
                sp = 'Vacancy'
            occu[i] = bit.index(sp)
        if not return_mapping:
            return occu
        else:
            return occu, mapping
Пример #7
0
class config:
    """This class defines the config with lattice gas mapping"""
    def __init__(
        self,
        base_structure,
        defect_sublattices,
        num_defects,
        cellsize=[1, 1, 1],
        perf_structure=None,
    ):
        try:
            num_defect_sublat = len(defect_sublattices)
        except TypeError:
            num_defect_sublat = 1
            defect_sublattices = [defect_sublattices]
            num_defects = [num_defects]
        self.matcher_base = StructureMatcher(primitive_cell=False,
                                             allow_subset=True)
        self.matcher_frame = StructureMatcher(
            stol=0.4,
            primitive_cell=False,
            allow_subset=True,
            comparator=FrameworkComparator(),
        )

        self.calc_history = []
        self.cellsize = cellsize
        self.base_structure = base_structure
        if self.base_structure.num_sites == 0:
            # we need at least one site for make_supercell
            self.base_structure.append("H", np.array([0, 0, 0]))
            self.base_structure.make_supercell(
                [cellsize[0], cellsize[1], cellsize[2]])
            self.base_structure.remove_sites(
                range(self.base_structure.num_sites))
        else:
            self.base_structure.make_supercell(
                [cellsize[0], cellsize[1], cellsize[2]])
        if perf_structure:
            self.perf_structure = perf_structure
            self.perf_structure.make_supercell(
                [cellsize[0], cellsize[1], cellsize[2]])
        self.supercell = self.base_structure.lattice.matrix
        self.n_sublat = num_defect_sublat
        invSuper = np.linalg.inv(self.supercell)

        # add supercell information to defect_sites
        num_sites = 0
        ntot_defects = 0
        sublat_id = 0
        for defect_sublattice in defect_sublattices:
            site_centers = defect_sublattice.site_centers
            defect_sublattice.site_centers_sc = np.zeros(
                (np.prod(cellsize) * site_centers.shape[0], 3), dtype=float)
            idx = 0
            for i in range(cellsize[0]):
                for j in range(cellsize[1]):
                    for k in range(cellsize[2]):
                        for l in range(site_centers.shape[0]):
                            defect_sublattice.site_centers_sc[
                                idx] = site_centers[l] + np.array([i, j, k])
                            idx += 1
            defect_sublattice.site_centers_sc /= np.array(cellsize)
            num_sites += len(defect_sublattice.site_centers_sc)

            # change cartesian coordinates to fractional
            for group in defect_sublattice.groups:
                for i in range(group.orientations):
                    for j in range(group.natoms):
                        group.coords[i][j] = np.dot(group.coords[i][j],
                                                    invSuper)

            # fill the lattice gas representation list
            latgas_rep = []
            for group in num_defects[sublat_id].keys():
                latgas_rep.extend(
                    [[group, 0] for i in range(num_defects[sublat_id][group])])
                ntot_defects += num_defects[sublat_id][group]
            defect_sublattice.latgas_rep = latgas_rep

            sublat_id += 1

        self.defect_sublattices = defect_sublattices

        assert num_sites == ntot_defects
        self.set_latgas()

    def set_latgas(self, defect_sublattices=False):
        if defect_sublattices:
            self.defect_sublattices = defect_sublattices
        assert len(self.defect_sublattices) == self.n_sublat

        self.structure = copy.deepcopy(self.base_structure)
        for defect_sublattice in self.defect_sublattices:
            latgas_rep = defect_sublattice.latgas_rep
            assert len(latgas_rep) == len(defect_sublattice.site_centers_sc)
            for isite in range(len(latgas_rep)):
                grp_name = latgas_rep[isite][0]
                orr = latgas_rep[isite][1]
                group = defect_sublattice.group_dict[grp_name]
                for j in range(group.natoms):
                    self.structure.append(
                        group.species[j], group.coords[orr][j] +
                        defect_sublattice.site_centers_sc[isite]
                        # properties={"velocities":[0,0,0]}
                    )

    def shuffle(self):
        for defect_sublattice in self.defect_sublattices:
            latgas_rep = defect_sublattice.latgas_rep
            rand.shuffle(latgas_rep)
            for site in latgas_rep:
                group = defect_sublattice.group_dict[site[0]]
                norr = group.orientations
                site[1] = rand.randrange(norr)
            # print(latgas_rep)
        self.set_latgas()

    def count(self, group_name, orientation):
        num_grp = []

        for defect_sublattice in self.defect_sublattices:
            num_grp.append(
                defect_sublattice.latgas_rep.count([group_name, orientation]))
        return num_grp

    def update_basestruct(self):
        basesites = self.matcher_base.get_mapping(self.structure,
                                                  self.base_structure)
        idx = 0
        for i in basesites:
            self.base_structure[idx] = self.structure[i]
            idx += 1

    def defect_sublattice_structure(self, sublat_id):
        assert sublat_id < self.n_sublat
        sublattice_structure = self.structure.copy()
        base_sites = self.matcher_base.get_mapping(self.structure,
                                                   self.base_structure)
        sublattice_structure.remove_sites(base_sites)
        return sublattice_structure

    @property
    def vacancy_structure(self):
        filledsites = self.matcher_frame.get_mapping(self.perf_structure,
                                                     self.structure)
        # print(self.perf_structure)
        # print(self.structure)
        # print(filledsites)
        vac_structure = self.perf_structure.copy()
        vac_structure.remove_sites(filledsites)
        return vac_structure
Пример #8
0
    for site in Vacsites:
        structure.pop(site)

    structure_Osite = structure.copy()
    structure_Osite.remove_species(["Pt", "Zr"])

    matcher_site = StructureMatcher(
        ltol=ltol,
        primitive_cell=False,
        allow_subset=True,
        comparator=FrameworkComparator(),
        ignored_species=["Pt"],
    )

    # Figure out where the vacancies are by comparing with base_structure
    filled_sites = matcher_site.get_mapping(base_Osite, structure_Osite)

    print(filled_sites)

    vac_struct = base_Osite.copy()
    vac_struct.remove_sites(filled_sites)
    print(vac_struct)
    # assert len(vac_struct) == 10

    # choose one vacancy and one O atom randomly and flip
    vac_flip = rand.choice(vac_struct)
    Osites = structure.indices_from_symbol("O")
    O_flip = rand.choice(Osites)

    del structure[O_flip]
    print(vac_flip.frac_coords)
Пример #9
0
class config:
    """This class defines the config with lattice gas mapping"""
    def __init__(
        self,
        base_structure,
        defect_sublattices,
        num_defects,
        cellsize=[1, 1, 1],
        perfect_structure=None,
    ):
        """

        Parameters
        ----------
        base_structure : pymatgen.Structure
            Structure of base sites (unsampled sites)
        defect_sublattices : defect_sublattice
            Structure of defects (sampled sites)
        num_defects : dict
            {group name: number of defects}
        cellsize : list, optional
            Cell size, by default [1, 1, 1]
        perfect_structure : pymatgen.Structure, optional
            Strucure of all sites (union of base and defect), by default None
        """
        try:
            num_defect_sublat = len(defect_sublattices)
        except TypeError:
            num_defect_sublat = 1
            defect_sublattices = [defect_sublattices]
            num_defects = [num_defects]
        self.matcher_base = StructureMatcher(primitive_cell=False,
                                             allow_subset=True)
        self.matcher_frame = StructureMatcher(
            stol=0.4,
            primitive_cell=False,
            allow_subset=True,
            comparator=FrameworkComparator(),
        )

        self.calc_history = []
        self.cellsize = cellsize
        self.base_structure = base_structure
        if self.base_structure.num_sites == 0:
            # we need at least one site for make_supercell
            self.base_structure.append("H", np.array([0, 0, 0]))
            self.base_structure.make_supercell(
                [cellsize[0], cellsize[1], cellsize[2]])
            self.base_structure.remove_sites(
                range(self.base_structure.num_sites))
        else:
            self.base_structure.make_supercell(
                [cellsize[0], cellsize[1], cellsize[2]])
        if perfect_structure:
            self.perfect_structure = perfect_structure
            self.perfect_structure.make_supercell(
                [cellsize[0], cellsize[1], cellsize[2]])
        self.supercell = self.base_structure.lattice.matrix
        self.n_sublat = num_defect_sublat
        invSuper = np.linalg.inv(self.supercell)

        # add supercell information to defect_sites
        num_sites = 0
        ntot_defects = 0
        sublat_id = 0
        for defect_sublattice in defect_sublattices:
            site_centers = defect_sublattice.site_centers
            defect_sublattice.site_centers_sc = np.zeros(
                (np.prod(cellsize) * site_centers.shape[0], 3), dtype=float)
            idx = 0
            for (idx, (i, j, k, l)) in enumerate(
                    product(
                        range(cellsize[0]),
                        range(cellsize[1]),
                        range(cellsize[2]),
                        range(site_centers.shape[0]),
                    )):
                defect_sublattice.site_centers_sc[
                    idx] = site_centers[l] + np.array([i, j, k])
                idx += 1
            defect_sublattice.site_centers_sc /= np.array(cellsize)
            num_sites += len(defect_sublattice.site_centers_sc)

            # change cartesian coordinates to fractional
            for group in defect_sublattice.groups:
                for i in range(group.orientations):
                    for j in range(group.natoms):
                        group.coords[i][j] = np.dot(group.coords[i][j],
                                                    invSuper)

            # fill the lattice gas representation list
            latgas_rep = []
            for group in num_defects[sublat_id].keys():
                latgas_rep.extend(
                    [[group, 0] for i in range(num_defects[sublat_id][group])])
                ntot_defects += num_defects[sublat_id][group]
            defect_sublattice.latgas_rep = latgas_rep

            sublat_id += 1

        self.defect_sublattices = defect_sublattices

        assert num_sites == ntot_defects
        self.set_latgas()

    def set_latgas(self, defect_sublattices=False):
        """

        Parameters
        ----------
        defect_sublattices: pymatgen.Structure
        """
        if defect_sublattices:
            self.defect_sublattices = defect_sublattices
        assert len(self.defect_sublattices) == self.n_sublat

        self.structure = copy.deepcopy(self.base_structure)
        for defect_sublattice in self.defect_sublattices:
            latgas_rep = defect_sublattice.latgas_rep
            assert len(latgas_rep) == len(defect_sublattice.site_centers_sc)
            for isite in range(len(latgas_rep)):
                grp_name = latgas_rep[isite][0]
                orr = latgas_rep[isite][1]
                group = defect_sublattice.group_dict[grp_name]
                for j in range(group.natoms):
                    self.structure.append(
                        group.species[j],
                        group.coords[orr][j] +
                        defect_sublattice.site_centers_sc[isite],
                        properties={
                            "seldyn": group.relaxations[j, :],
                            "magnetization": group.magnetizations[j],
                        },
                    )

    def shuffle(self):
        for defect_sublattice in self.defect_sublattices:
            latgas_rep = defect_sublattice.latgas_rep
            rand.shuffle(latgas_rep)
            for site in latgas_rep:
                group = defect_sublattice.group_dict[site[0]]
                norr = group.orientations
                site[1] = rand.randint(norr)
        self.set_latgas()

    def count(self, group_name, orientation):
        """

        Parameters
        ----------
        group_name: str
            The name of the group
        orientation:

        Returns
        -------

        """
        num_grp = []

        for defect_sublattice in self.defect_sublattices:
            num_grp.append(
                defect_sublattice.latgas_rep.count([group_name, orientation]))
        return num_grp

    def update_basestruct(self):
        basesites = self.matcher_base.get_mapping(self.structure,
                                                  self.base_structure)
        idx = 0
        for i in basesites:
            self.base_structure[idx] = self.structure[i]
            idx += 1

    def defect_sublattice_structure(self, sublat_id):
        """

        Parameters
        ----------
        sublat_id: int
            index of sublattice

        Returns
        -------
        sublattice_structure: pymatgen.Structure
            sublattice structure object

        """
        assert sublat_id < self.n_sublat
        sublattice_structure = self.structure.copy()
        base_sites = self.matcher_base.get_mapping(self.structure,
                                                   self.base_structure)
        sublattice_structure.remove_sites(base_sites)
        return sublattice_structure

    @property
    def vacancy_structure(self):
        filledsites = self.matcher_frame.get_mapping(self.perfect_structure,
                                                     self.structure)
        vac_structure = self.perfect_structure.copy()
        vac_structure.remove_sites(filledsites)
        return vac_structure