Пример #1
0
 def test_mix(self):
     structures = []
     for fname in [
             "POSCAR.Li2O", "Li2O.cif", "Li2O2.cif", "LiFePO4.cif",
             "POSCAR.LiFePO4"
     ]:
         structures.append(read_structure(os.path.join(test_dir, fname)))
     sm = StructureMatcher(comparator=ElementComparator())
     groups = sm.group_structures(structures)
     for g in groups:
         formula = g[0].composition.reduced_formula
         if formula in ["Li2O", "LiFePO4"]:
             self.assertEqual(len(g), 2)
         else:
             self.assertEqual(len(g), 1)
Пример #2
0
    def test_cmp_fstruct(self):
        sm = StructureMatcher()

        s1 = np.array([[0.1, 0.2, 0.3], [0.4, 0.5, 0.6]])
        s2 = np.array([[0.11, 0.22, 0.33]])
        frac_tol = np.array([0.02, 0.03, 0.04])
        mask = np.array([[False, False]])
        mask2 = np.array([[True, False]])

        self.assertRaises(ValueError, sm._cmp_fstruct, s2, s1, frac_tol, mask.T)
        self.assertRaises(ValueError, sm._cmp_fstruct, s1, s2, frac_tol, mask.T)

        self.assertTrue(sm._cmp_fstruct(s1, s2, frac_tol, mask))
        self.assertFalse(sm._cmp_fstruct(s1, s2, frac_tol/2, mask))
        self.assertFalse(sm._cmp_fstruct(s1, s2, frac_tol, mask2))
Пример #3
0
    def test_electronegativity(self):
        sm = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5)

        s1 = read_structure(os.path.join(test_dir, "Na2Fe2PAsO4S4.cif"))
        s2 = read_structure(os.path.join(test_dir, "Na2Fe2PNO4Se4.cif"))
        self.assertEqual(
            sm.get_best_electronegativity_anonymous_mapping(s1, s2), {
                Element('S'): Element('Se'),
                Element('As'): Element('N'),
                Element('Fe'): Element('Fe'),
                Element('Na'): Element('Na'),
                Element('P'): Element('P'),
                Element('O'): Element('O'),
            })
        self.assertEqual(len(sm.get_all_anonymous_mappings(s1, s2)), 2)
Пример #4
0
    def _match_material(self, taskdoc):
        """
        Returns the material_id that has the same structure as this task as
         determined by the structure matcher. Returns None if no match.

        Args:
            taskdoc (dict): a JSON-like task document

        Returns:
            (int) matching material_id or None
        """
        formula = taskdoc["formula_reduced_abc"]

        if "parent_structure" in taskdoc:  # this is used to intentionally combine multiple data w/same formula but slightly different structure, e.g. from an ordering scheme
            t_struct = Structure.from_dict(
                taskdoc["parent_structure"]["structure"])
            q = {
                "formula_reduced_abc":
                formula,
                "parent_structure.spacegroup.number":
                taskdoc["parent_structure"]["spacegroup"]["number"]
            }
        else:
            sgnum = taskdoc["output"]["spacegroup"]["number"]
            t_struct = Structure.from_dict(taskdoc["output"]["structure"])
            q = {"formula_reduced_abc": formula, "sg_number": sgnum}

        for m in self._materials.find(q, {
                "parent_structure": 1,
                "structure": 1,
                "material_id": 1
        }):
            s_dict = m["parent_structure"][
                "structure"] if "parent_structure" in m else m["structure"]
            m_struct = Structure.from_dict(s_dict)
            sm = StructureMatcher(ltol=0.2,
                                  stol=0.3,
                                  angle_tol=5,
                                  primitive_cell=True,
                                  scale=True,
                                  attempt_supercell=False,
                                  allow_subset=False,
                                  comparator=ElementComparator())

            if sm.fit(m_struct, t_struct):
                return m["material_id"]

        return None
Пример #5
0
    def get_framework_rms_plot(self,
                               plt=None,
                               granularity=200,
                               matching_s=None):
        """
        Get the plot of rms framework displacement vs time. Useful for checking
        for melting, especially if framework atoms can move via paddle-wheel
        or similar mechanism (which would show up in max framework displacement
        but doesn't constitute melting).

        Args:
            granularity (int): Number of structures to match
            matching_s (Structure): Optionally match to a disordered structure
                instead of the first structure in the analyzer. Required when
                a secondary mobile ion is present.
        """
        from pymatgen.util.plotting_utils import get_publication_quality_plot
        plt = get_publication_quality_plot(12, 8, plt=plt)
        step = (self.corrected_displacements.shape[1] - 1) // (granularity - 1)
        f = (matching_s or self.structure).copy()
        f.remove_species([self.specie])
        sm = StructureMatcher(primitive_cell=False,
                              stol=0.6,
                              comparator=OrderDisorderElementComparator(),
                              allow_subset=True)
        rms = []
        for s in self.get_drift_corrected_structures(step=step):
            s.remove_species([self.specie])
            d = sm.get_rms_dist(f, s)
            if d:
                rms.append(d)
            else:
                rms.append((1, 1))
        max_dt = (len(rms) - 1) * step * self.step_skip * self.time_step
        if max_dt > 100000:
            plot_dt = np.linspace(0, max_dt / 1000, len(rms))
            unit = 'ps'
        else:
            plot_dt = np.linspace(0, max_dt, len(rms))
            unit = 'fs'
        rms = np.array(rms)
        plt.plot(plot_dt, rms[:, 0], label='RMS')
        plt.plot(plot_dt, rms[:, 1], label='max')
        plt.legend(loc='best')
        plt.xlabel("Timestep ({})".format(unit))
        plt.ylabel("normalized distance")
        plt.tight_layout()
        return plt
Пример #6
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)
Пример #7
0
    def get_slabs(self, bonds=None, tol=0.1, max_broken_bonds=0):
        """
        This method returns a list of slabs that are generated using the list of
        shift values from the method, _calculate_possible_shifts(). Before the
        shifts are used to create the slabs however, if the user decides to take
        into account whether or not a termination will break any polyhedral
        structure (bonds != None), this method will filter out any shift values
        that do so.

        Args:
            bonds ({(specie1, specie2): max_bond_dist}: bonds are
                specified as a dict of tuples: float of specie1, specie2
                and the max bonding distance. For example, PO4 groups may be
                defined as {("P", "O"): 3}.
            tol (float): Threshold parameter in fcluster in order to check
                if two atoms are lying on the same plane. Default thresh set
                to 0.1 Angstrom in the direction of the surface normal.
            max_broken_bonds (int): Maximum number of allowable broken bonds
                for the slab. Use this to limit # of slabs (some structures
                may have a lot of slabs). Defaults to zero, which means no
                defined bonds must be broken.

        Returns:
            ([Slab]) List of all possible terminations of a particular surface.
            Slabs are sorted by the # of bonds broken.
        """
        c_ranges = set() if bonds is None else self._get_c_ranges(bonds)

        slabs = []
        for shift in self._calculate_possible_shifts(tol=tol):
            bonds_broken = 0
            for r in c_ranges:
                if r[0] <= shift <= r[1]:
                    bonds_broken += 1
            if bonds_broken <= max_broken_bonds:
                # For now, set the energy to be equal to no. of broken bonds
                # per unit cell.
                slab = self.get_slab(shift, tol=tol, energy=bonds_broken)
                slabs.append(slab)

        # Further filters out any surfaces made that might be the same
        m = StructureMatcher(ltol=tol,
                             stol=tol,
                             primitive_cell=False,
                             scale=False)
        slabs = [g[0] for g in m.group_structures(slabs)]
        return sorted(slabs, key=lambda s: s.energy)
Пример #8
0
def group_structures(structures,
                     ltol=0.2,
                     stol=0.3,
                     angle_tol=5,
                     symprec=0.1,
                     separate_mag_orderings=False):
    """
    Groups structures according to space group and structure matching

    Args:
        structures ([Structure]): list of structures to group
        ltol (float): StructureMatcher tuning parameter for matching tasks to materials
        stol (float): StructureMatcher tuning parameter for matching tasks to materials
        angle_tol (float): StructureMatcher tuning parameter for matching tasks to materials
        symprec (float): symmetry tolerance for space group finding
        separate_mag_orderings (bool): Separate magnetic orderings into different materials
    """

    sm = StructureMatcher(ltol=ltol,
                          stol=stol,
                          angle_tol=angle_tol,
                          primitive_cell=True,
                          scale=True,
                          attempt_supercell=False,
                          allow_subset=False,
                          comparator=ElementComparator())

    def get_sg(struc):
        # helper function to get spacegroup with a loose tolerance
        return struc.get_space_group_info(symprec=symprec)[1]

    def get_mag_ordering(struc):
        # helperd function to get a label of the magnetic ordering type
        return CollinearMagneticStructureAnalyzer(struc).ordering.value

    # First group by spacegroup number then by structure matching
    for sg, pregroup in groupby(sorted(structures, key=get_sg), key=get_sg):
        for group in sm.group_structures(list(pregroup)):

            # Match magnetic orderings here
            if separate_mag_orderings:
                for _, mag_group in groupby(sorted(group,
                                                   key=get_mag_ordering),
                                            key=get_mag_ordering):
                    yield list(mag_group)
            else:
                yield group
Пример #9
0
    def predict(self, structure, ref_structure, test_isostructural=True):
        """
        Given a structure, returns back the predicted volume.

        Args:
            structure (Structure): structure w/unknown volume
            ref_structure (Structure): A reference structure with a similar
                structure but different species.
            test_isostructural (bool): Whether to test that the two
                structures are isostructural. This algo works best for
                isostructural compounds. Defaults to True.

        Returns:
            a float value of the predicted volume
        """
        if not is_ox(structure):
            a = BVAnalyzer()
            structure = a.get_oxi_state_decorated_structure(structure)
        if not is_ox(ref_structure):
            a = BVAnalyzer()
            ref_structure = a.get_oxi_state_decorated_structure(ref_structure)

        if test_isostructural:
            m = StructureMatcher()
            mapping = m.get_best_electronegativity_anonymous_mapping(
                structure, ref_structure)
            if mapping is None:
                raise ValueError("Input structures do not match!")

        comp = structure.composition
        ref_comp = ref_structure.composition

        numerator = 0
        denominator = 0

        # Here, the 1/3 factor on the composition accounts for atomic
        # packing. We want the number per unit length.

        # TODO: AJ doesn't understand the (1/3). It would make sense to him
        # if you were doing atomic volume and not atomic radius
        for k, v in comp.items():
            numerator += k.ionic_radius * v**(1 / 3)
        for k, v in ref_comp.items():
            denominator += k.ionic_radius * v**(1 / 3)

        # The scaling factor is based on lengths. We apply a power of 3.
        return ref_structure.volume * (numerator / denominator)**3
Пример #10
0
 def __init__(
     self,
     abinitio_run,
     selective_dynamics=None,
     save_history=True,
     l_update_basestruct=False,
     check_ion_move=False,
     ion_move_tol=0.7,
 ):
     self.matcher = StructureMatcher(primitive_cell=False,
                                     allow_subset=False)
     self.abinitio_run = abinitio_run
     self.selective_dynamics = selective_dynamics
     self.save_history = save_history
     self.l_update_basestruct = l_update_basestruct
     self.check_ion_move = check_ion_move
     self.ion_move_tol = ion_move_tol
Пример #11
0
    def setUp(self):
        self.test_ents_MOF = loadfn(
            f'{dir_path}/full_path_files/Mn6O5F7_cat_migration.json')
        self.aeccar_MOF = Chgcar.from_file(
            f'{dir_path}/full_path_files/AECCAR_Mn6O5F7.vasp')
        self.cep = ComputedEntryPath(
            base_struct_entry=self.test_ents_MOF['ent_base'],
            migrating_specie='Li',
            single_cat_entries=self.test_ents_MOF['one_cation'],
            base_aeccar=self.aeccar_MOF)

        # structure matcher used for validation
        self.rough_sm = StructureMatcher(comparator=ElementComparator(),
                                         primitive_cell=False,
                                         ltol=0.5,
                                         stol=0.5,
                                         angle_tol=7)
Пример #12
0
    def add_if_belongs(self, cand_snl):

        # no need to compare if different formulas or spacegroups
        if cand_snl.snlgroup_key != self.canonical_snl.snlgroup_key:
            return False

        # no need to compare if one is ordered, the other disordered
        if not (cand_snl.structure.is_ordered
                == self.canonical_structure.is_ordered):
            return False

        # filter out large C-Ce structures
        comp = cand_snl.structure.composition
        elsyms = sorted(set([e.symbol for e in comp.elements]))
        chemsys = '-'.join(elsyms)
        if (cand_snl.structure.num_sites > 1500
                or self.canonical_structure.num_sites > 1500
            ) and chemsys == 'C-Ce':
            print 'SKIPPING LARGE C-Ce'
            return False

        # make sure the structure is not already in all_structures
        if cand_snl.snl_id in self.all_snl_ids:
            print 'WARNING: add_if_belongs() has detected that you are trying to add the same SNL id twice!'
            return False

        #try a structure fit to the canonical structure

        # use default Structure Matcher params from April 24, 2013, as suggested by Shyue
        # we are using the ElementComparator() because this is how we want to group results
        sm = StructureMatcher(ltol=0.2,
                              stol=0.3,
                              angle_tol=5,
                              primitive_cell=True,
                              scale=True,
                              attempt_supercell=False,
                              comparator=ElementComparator())

        if not sm.fit(cand_snl.structure, self.canonical_structure):
            return False

        # everything checks out, add to the group
        self.all_snl_ids.append(cand_snl.snl_id)
        self.updated_at = datetime.datetime.utcnow()

        return True
Пример #13
0
    def _match_material(self, doc, ltol=0.2, stol=0.3, angle_tol=5):
        """
        Returns the material_id that has the same structure as this doc as
         determined by the structure matcher. Returns None if no match.

        Args:
            doc (dict): a JSON-like document
            ltol (float): StructureMatcher tuning parameter
            stol (float): StructureMatcher tuning parameter
            angle_tol (float): StructureMatcher tuning parameter

        Returns:
            (int) matching material_id or None
        """
        formula = doc["formula_reduced_abc"]
        sgnum = doc["spacegroup"]["number"]

        for m in self._materials.find(
            {
                "formula_reduced_abc": formula,
                "sg_number": sgnum
            },
            {
                "structure": 1,
                "material_id": 1
            },
        ):

            m_struct = Structure.from_dict(m["structure"])
            t_struct = Structure.from_dict(doc["structure"])

            sm = StructureMatcher(
                ltol=ltol,
                stol=stol,
                angle_tol=angle_tol,
                primitive_cell=True,
                scale=True,
                attempt_supercell=False,
                allow_subset=False,
                comparator=ElementComparator(),
            )

            if sm.fit(m_struct, t_struct):
                return m["material_id"]

        return None
Пример #14
0
    def test_get_mask(self):
        sm = StructureMatcher(comparator=ElementComparator())
        l = Lattice.cubic(1)
        s1 = Structure(l, ['Mg', 'Cu', 'Ag', 'Cu'], [[0] * 3] * 4)
        s2 = Structure(l, ['Cu', 'Cu', 'Ag'], [[0] * 3] * 3)

        result = [[True, False, True, False], [True, False, True, False],
                  [True, True, False, True]]
        m, inds, i = sm._get_mask(s1, s2, 1, True)
        self.assertTrue(np.all(m == result))
        self.assertTrue(i == 2)
        self.assertEqual(inds, [2])

        #test supercell with match
        result = [[1, 1, 0, 0, 1, 1, 0, 0], [1, 1, 0, 0, 1, 1, 0, 0],
                  [1, 1, 1, 1, 0, 0, 1, 1]]
        m, inds, i = sm._get_mask(s1, s2, 2, True)
        self.assertTrue(np.all(m == result))
        self.assertTrue(i == 2)
        self.assertTrue(np.allclose(inds, np.array([4])))

        #test supercell without match
        result = [[1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 1, 1], [1, 1, 1, 1, 0, 0],
                  [0, 0, 0, 0, 1, 1]]
        m, inds, i = sm._get_mask(s2, s1, 2, True)
        self.assertTrue(np.all(m == result))
        self.assertTrue(i == 0)
        self.assertTrue(np.allclose(inds, np.array([])))

        #test s2_supercell
        result = [[1, 1, 1], [1, 1, 1], [0, 0, 1], [0, 0, 1], [1, 1, 0],
                  [1, 1, 0], [0, 0, 1], [0, 0, 1]]
        m, inds, i = sm._get_mask(s2, s1, 2, False)
        self.assertTrue(np.all(m == result))
        self.assertTrue(i == 0)
        self.assertTrue(np.allclose(inds, np.array([])))

        #test for multiple translation indices
        s1 = Structure(l, ['Cu', 'Ag', 'Cu', 'Ag', 'Ag'], [[0] * 3] * 5)
        s2 = Structure(l, ['Ag', 'Cu', 'Ag'], [[0] * 3] * 3)
        result = [[1, 0, 1, 0, 0], [0, 1, 0, 1, 1], [1, 0, 1, 0, 0]]
        m, inds, i = sm._get_mask(s1, s2, 1, True)

        self.assertTrue(np.all(m == result))
        self.assertTrue(i == 1)
        self.assertTrue(np.allclose(inds, [0, 2]))
Пример #15
0
    def test_find_match2(self):
        sm = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5,
                              primitive_cell=True, scale=True,
                              attempt_supercell=False)
        l = Lattice.orthorhombic(1, 2, 3)
        s1 = Structure(l, ['Si', 'Si'], [[0,0,0.1],[0,0,0.2]])
        s2 = Structure(l, ['Si', 'Si'], [[0,0.1,0],[0,0.1,-0.95]])
        match = sm._find_match(s1, s2, break_on_match = False,
                               use_rms = True, niggli = False)
        scale_matrix = np.round(np.dot(match[2].matrix,
                                       s2.lattice.inv_matrix)).astype('int')
        s2.make_supercell(scale_matrix)
        fc = s2.frac_coords + match[3]
        fc -= np.round(fc)

        self.assertAlmostEqual(np.sum(fc), 0.3)
        self.assertAlmostEqual(np.sum(fc[:,:2]), 0)
Пример #16
0
    def test_get_lattices(self):
        sm = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5,
                              primitive_cell=True, scale=True,
                              attempt_supercell=False)
        l1 = Lattice.from_lengths_and_angles([1, 2.1, 1.9] , [90, 89, 91])
        l2 = Lattice.from_lengths_and_angles([1.1, 2, 2] , [89, 91, 90])
        s1 = Structure(l1, [], [])
        s2 = Structure(l2, [], [])

        lattices = list(sm._get_lattices(s = s1, target_s = s2))
        self.assertEqual(len(lattices), 16)

        l3 = Lattice.from_lengths_and_angles([1.1, 2, 20] , [89, 91, 90])
        s3 = Structure(l3, [], [])

        lattices = list(sm._get_lattices(s = s1, target_s = s3))
        self.assertEqual(len(lattices), 0)
Пример #17
0
def _perform_grouping(args):
    (
        entries_json,
        hosts_json,
        ltol,
        stol,
        angle_tol,
        primitive_cell,
        scale,
        comparator,
        groups,
    ) = args

    entries = json.loads(entries_json, cls=MontyDecoder)
    hosts = json.loads(hosts_json, cls=MontyDecoder)
    unmatched = list(zip(entries, hosts))
    while len(unmatched) > 0:
        ref_host = unmatched[0][1]
        logger.info(
            f"Reference tid = {unmatched[0][0].entry_id}, formula = {ref_host.formula}"
        )
        ref_formula = ref_host.composition.reduced_formula
        logger.info(f"Reference host = {ref_formula}")
        matches = [unmatched[0]]
        for i in range(1, len(unmatched)):
            test_host = unmatched[i][1]
            logger.info(
                f"Testing tid = {unmatched[i][0].entry_id}, formula = {test_host.formula}"
            )
            test_formula = test_host.composition.reduced_formula
            logger.info(f"Test host = {test_formula}")
            m = StructureMatcher(
                ltol=ltol,
                stol=stol,
                angle_tol=angle_tol,
                primitive_cell=primitive_cell,
                scale=scale,
                comparator=comparator,
            )
            if m.fit(ref_host, test_host):
                logger.info("Fit found")
                matches.append(unmatched[i])
        groups.append(json.dumps([m[0] for m in matches], cls=MontyEncoder))
        unmatched = list(filter(lambda x: x not in matches, unmatched))
        logger.info(f"{len(unmatched)} unmatched remaining")
Пример #18
0
    def relaxed_structure_match(self, i, j):
        """
        Check if the relaxed structures of two interstitials match

        Args:
            i: Symmetrically distinct interstitial index
            j: Symmetrically distinct interstitial index

        .. note::

            Index 0 corresponds to bulk.
        """
        if not self._relax_structs:
            self.relax()
        sm = StructureMatcher()
        struct1 = self._relax_structs[i]
        struct2 = self._relax_structs[j]
        return sm.fit(struct1, struct2)
Пример #19
0
    def test_electronegativity(self):
        sm = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5)

        s1 = Structure.from_file(os.path.join(test_dir, "Na2Fe2PAsO4S4.json"))
        s2 = Structure.from_file(os.path.join(test_dir, "Na2Fe2PNO4Se4.json"))
        self.assertEqual(sm.get_best_electronegativity_anonymous_mapping(s1, s2),
                    {Element('S'): Element('Se'),
                     Element('As'): Element('N'),
                     Element('Fe'): Element('Fe'),
                     Element('Na'): Element('Na'),
                     Element('P'): Element('P'),
                     Element('O'): Element('O'),})
        self.assertEqual(len(sm.get_all_anonymous_mappings(s1, s2)), 2)

        # test include_dist
        dists = {Element('N'): 0, Element('P'): 0.0010725064}
        for mapping, d in sm.get_all_anonymous_mappings(s1, s2, include_dist=True):
            self.assertAlmostEqual(dists[mapping[Element('As')]], d)
Пример #20
0
    def test_get_s2_like_s1(self):
        sm = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5,
                              primitive_cell=False, scale=True,
                              attempt_supercell=True)
        l = Lattice.orthorhombic(1, 2, 3)
        s1 = Structure(l, ['Si', 'Si', 'Ag'],
                       [[0,0,0.1],[0,0,0.2],[.7,.4,.5]])
        s1.make_supercell([2,1,1])
        s2 = Structure(l, ['Si', 'Si', 'Ag'],
                       [[0,0.1,0],[0,0.1,-0.95],[-.7,.5,.375]])
        result = sm.get_s2_like_s1(s1, s2)

        self.assertEqual(len(find_in_coord_list_pbc(result.frac_coords,
                                                    [0.35,0.4,0.5])), 1)
        self.assertEqual(len(find_in_coord_list_pbc(result.frac_coords,
                                                    [0,0,0.125])), 1)
        self.assertEqual(len(find_in_coord_list_pbc(result.frac_coords,
                                                    [0,0,0.175])), 1)
Пример #21
0
    def test_occupancy_comparator(self):

        lp = Lattice.orthorhombic(10, 20, 30)
        pcoords = [[0, 0, 0],
                   [0.5, 0.5, 0.5]]
        s1 = Structure(lp, [{'Na': 0.6, 'K': 0.4}, 'Cl'], pcoords)
        s2 = Structure(lp, [{'Xa': 0.4, 'Xb': 0.6}, 'Cl'], pcoords)
        s3 = Structure(lp, [{'Xa': 0.5, 'Xb': 0.5}, 'Cl'], pcoords)

        sm_sites = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5,
                                    primitive_cell=False, scale=True,
                                    attempt_supercell=True,
                                    allow_subset=True,
                                    supercell_size='num_sites',
                                    comparator=OccupancyComparator())

        self.assertTrue(sm_sites.fit(s1, s2))
        self.assertFalse(sm_sites.fit(s1, s3))
Пример #22
0
    def test_ignore_species(self):
        s1 = Structure.from_file(os.path.join(test_dir, "LiFePO4.cif"))
        s2 = Structure.from_file(os.path.join(test_dir, "POSCAR"))
        m = StructureMatcher(ignored_species=["Li"], primitive_cell=False,
                             attempt_supercell=True)
        self.assertTrue(m.fit(s1, s2))
        self.assertTrue(m.fit_anonymous(s1, s2))
        groups = m.group_structures([s1, s2])
        self.assertEqual(len(groups), 1)
        s2.make_supercell((2, 1, 1))
        ss1 = m.get_s2_like_s1(s2, s1, include_ignored_species=True)
        self.assertAlmostEqual(ss1.lattice.a, 20.820740000000001)
        self.assertEqual(ss1.composition.reduced_formula, "LiFePO4")

        self.assertEqual({
            k.symbol: v.symbol for k, v in
            m.get_best_electronegativity_anonymous_mapping(s1, s2).items()},
            {"Fe": "Fe", "P": "P", "O": "O"})
Пример #23
0
    def test_find_match2(self):
        sm = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5,
                              primitive_cell=True, scale=True,
                              attempt_supercell=False)
        l = Lattice.orthorhombic(1, 2, 3)
        s1 = Structure(l, ['Si', 'Si'], [[0, 0, 0.1], [0, 0, 0.2]])
        s2 = Structure(l, ['Si', 'Si'], [[0, 0.1, 0], [0, 0.1, -0.95]])

        s1, s2, fu, s1_supercell = sm._preprocess(s1, s2, False)

        match = sm._strict_match(s1, s2, fu, s1_supercell=False,
                                 use_rms=True, break_on_match=False)
        scale_matrix = match[2]
        s2.make_supercell(scale_matrix)
        s2.translate_sites(range(len(s2)), match[3])

        self.assertAlmostEqual(np.sum(s2.frac_coords) % 1, 0.3)
        self.assertAlmostEqual(np.sum(s2.frac_coords[:, :2]) % 1, 0)
Пример #24
0
def mpid_and_link(symmetrizer: StructureSymmetrizer):

    reduced_formula = symmetrizer.structure.composition.reduced_formula
    criteria = {"reduced_cell_formula": reduced_formula,
                "spacegroup.number": symmetrizer.sg_number}
    properties = ["task_id", "structure"]
    with MPRester() as m:
        for doc in m.query(criteria, properties):
            sm = StructureMatcher()
            if sm.fit(doc["structure"], symmetrizer.structure):
                mpid = doc["task_id"]
                break
        else:
            return H4("None")

    return dcc.Link(f'mp-id {mpid}',
                    href=f'https://materialsproject.org/materials/{mpid}/',
                    style={'font-weight': 'bold', "font-size": "20px"})
Пример #25
0
def test_basic_structure(kind, index):
    base_structure = get_lattice(kind)
    num_type = 2
    species = ["Cu", "Au"]

    se = StructureEnumerator(
        base_structure,
        index,
        num_type,
        species,
        color_exchange=True,
        remove_superperiodic=True,
    )
    list_ds = se.generate()

    stm = StructureMatcher(ltol=1e-4, stol=1e-4)
    grouped = stm.group_structures(list_ds)
    assert len(grouped) == len(list_ds)
Пример #26
0
def test__EnumerateDistinctFacets():
    '''
    We take all the facets that the task are distinct/unique, then actually
    make slabs out of them and compare all the slabs to see if they are
    identical. Note that this tests only if we get repeats. It does not
    test if we missed anything.

    WARNING:  This test uses `run_task_locally`, which has a chance of
    actually submitting a FireWork to production. To avoid this, you must try
    to make sure that you have all of the gas calculations in the unit testing
    atoms collection.  If you copy/paste this test into somewhere else, make
    sure that you use `run_task_locally` appropriately.
    '''
    mpid = 'mp-2'
    max_miller = 2
    task = _EnumerateDistinctFacets(mpid=mpid, max_miller=max_miller)

    # Run the task to get the facets, and also get the bulk structure so we can
    # actually make slabs to check
    try:
        run_task_locally(task)
        distinct_millers = get_task_output(task)
        with open(task.input().path, 'rb') as file_handle:
            bulk_doc = pickle.load(file_handle)
        bulk_atoms = make_atoms_from_doc(bulk_doc)

        # Make all the slabs that the task said are distinct
        all_slabs = []
        for miller in distinct_millers:
            slabs = make_slabs_from_bulk_atoms(
                bulk_atoms,
                miller,
                SLAB_SETTINGS['slab_generator_settings'],
                SLAB_SETTINGS['get_slab_settings'],
            )
            all_slabs.extend(slabs)

        # Check that the slabs are actually different
        matcher = StructureMatcher()
        for slabs_to_compare in combinations(all_slabs, 2):
            assert not matcher.fit(*slabs_to_compare)

    finally:
        clean_up_tasks()
Пример #27
0
    def __init__(self, structure_matcher=StructureMatcher(
                 comparator=ElementComparator()), symprec=None):
        """
        Remove duplicate structures based on the structure matcher
        and symmetry (if symprec is given).

        Args:
            structure_matcher: Provides a structure matcher to be used for
                structure comparison.
            symprec: The precision in the symmetry finder algorithm if None (
                default value), no symmetry check is performed and only the
                structure matcher is used. A recommended value is 1e-5.
        """
        self.symprec = symprec
        self.structure_list = defaultdict(list)
        if isinstance(structure_matcher, dict):
            self.structure_matcher = StructureMatcher.from_dict(structure_matcher)
        else:
            self.structure_matcher = structure_matcher
Пример #28
0
    def relaxed_structure_match(self, i, j):
        """
        Check if the relaxed structures of two interstitials match

        Args:
            i: Symmetrically distinct interstitial index
            j: Symmetrically distinct interstitial index

        .. note::

            To use relaxed bulk structure pass -1.
            -ve index will not work as expected
        """
        if not self._relax_struct:
            self._relax_analysis()
        sm = StructureMatcher()
        struct1 = self._relax_struct[i + 1]
        struct2 = self._relax_struct[j + 1]
        return sm.fit(struct1, struct2)
Пример #29
0
    def test_get_supercells(self):
        sm = StructureMatcher(comparator=ElementComparator())
        l = Lattice.cubic(1)
        l2 = Lattice.cubic(0.5)
        s1 = Structure(l, ['Mg', 'Cu', 'Ag', 'Cu'], [[0] * 3] * 4)
        s2 = Structure(l2, ['Cu', 'Cu', 'Ag'], [[0] * 3] * 3)
        scs = list(sm._get_supercells(s1, s2, 8, False))
        for x in scs:
            self.assertAlmostEqual(abs(np.linalg.det(x[3])), 8)
            self.assertEqual(len(x[0]), 4)
            self.assertEqual(len(x[1]), 24)
        self.assertEqual(len(scs), 48)

        scs = list(sm._get_supercells(s2, s1, 8, True))
        for x in scs:
            self.assertAlmostEqual(abs(np.linalg.det(x[3])), 8)
            self.assertEqual(len(x[0]), 24)
            self.assertEqual(len(x[1]), 4)
        self.assertEqual(len(scs), 48)
Пример #30
0
    def test_get_s2_large_s2(self):
        sm = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5,
                              primitive_cell=False, scale=False,
                              attempt_supercell=True, allow_subset=False,
                              supercell_size='volume')

        l = Lattice.orthorhombic(1, 2, 3)
        s1 = Structure(l, ['Ag', 'Si', 'Si'],
                       [[.7, .4, .5], [0, 0, 0.1], [0, 0, 0.2]])

        l2 = Lattice.orthorhombic(1.01, 2.01, 3.01)
        s2 = Structure(l2, ['Si', 'Si', 'Ag'],
                       [[0, 0.1, -0.95], [0, 0.1, 0], [-.7, .5, .375]])
        s2.make_supercell([[0, -1, 0], [1, 0, 0], [0, 0, 1]])

        result = sm.get_s2_like_s1(s1, s2)

        for x, y in zip(s1, result):
            self.assertLess(x.distance(y), 0.08)