Example #1
0
def test_converter(transformation, frac_coords):
    converter = DerivativeMultiLatticeHash(transformation, frac_coords)

    index = converter.index
    num_sites = converter.num_sites

    all_factors = converter.get_all_factors()
    assert len({tuple(f) for f in all_factors}) == index

    all_lattice_points = converter.get_lattice_points()
    assert len({tuple(f) for f in all_lattice_points}) == index

    all_periodic_sites = converter.get_canonical_sites_list()
    assert len(set(all_periodic_sites)) == num_sites

    all_dsites = converter.get_distinct_derivative_sites_list()
    for dsite in all_dsites:
        csite, derivative_jimage = converter.hash_derivative_site(dsite, return_image=True)
        fcoords1 = converter.get_frac_coords(dsite)
        fcoords2 = (
            converter.displacement_set[dsite.site_index]
            + np.dot(converter.left_inv, csite.factor)
            + np.dot(converter.hnf, derivative_jimage)
        )
        assert np.allclose(fcoords1, fcoords2)

    for csite in all_periodic_sites:
        ind = converter.ravel_canonical_site(csite)
        csite2 = converter.unravel_to_canonical_site(ind)
        assert csite2 == csite
Example #2
0
def test_converter():
    list_transformations = [
        np.diag((2, 2, 2)),
        np.array([[-1, 1, 1], [1, -1, 1], [1, 1, -1]]),
        np.array([[-1, 1, 1], [1, -1, 1], [-1, -1, 1]]),  # negative determinat
    ]
    list_frac_coords = [
        np.array([[0, 0, 0]]),
        np.array([[0, 0, 0], [0.5, 0.5, 0.5]])
    ]

    for transformation in list_transformations:
        for frac_coords in list_frac_coords:
            converter = DerivativeMultiLatticeHash(transformation, frac_coords)

            index = converter.index
            num_sites = converter.num_sites

            all_factors = converter.get_all_factors()
            assert len(set([tuple((f)) for f in all_factors])) == index

            all_lattice_points = converter.get_lattice_points()
            assert len(set([tuple(f) for f in all_lattice_points])) == index

            all_periodic_sites = converter.get_canonical_sites_list()
            assert len(set(all_periodic_sites)) == num_sites

            all_dsites = converter.get_distinct_derivative_sites_list()
            for dsite in all_dsites:
                csite, derivative_jimage = converter.hash_derivative_site(
                    dsite, return_image=True)
                fcoords1 = converter.get_frac_coords(dsite)
                fcoords2 = (converter.displacement_set[dsite.site_index] +
                            np.dot(converter.left_inv, csite.factor) +
                            np.dot(converter.hnf, derivative_jimage))
                assert np.allclose(fcoords1, fcoords2)

            for csite in all_periodic_sites:
                ind = converter.ravel_canonical_site(csite)
                csite2 = converter.unravel_to_canonical_site(ind)
                assert csite2 == csite
Example #3
0
class DerivativeStructurePermutation:
    """
    Permutation Representation of space group of superlattice

    Parameters
    ----------
    hnf: array, (dim, dim)
        Hermite normal form(lower triangular)
    displacement_set: array, (num_site_parent, dim)
        fractinal coordinates in primitive cell of base structure
    rotations: array, (# of symmetry operations, dim, dim)
        rotations with primitive basis for base structure
    translations: array, (# of symmetry operations, dim)
        translations with primitive basis for base structure

    Attributes
    ----------
    dim : int
        dimention of lattice
    index: int
        # of parent multilattice in super lattice
    num_site: int
        # of sites in unit cell of superlattice
    """

    def __init__(
        self,
        hnf: np.ndarray,
        displacement_set: np.ndarray,
        rotations: np.ndarray,
        translations: np.ndarray,
    ):
        self.hnf = hnf
        self.num_sites_base = len(displacement_set)
        # TODO: check each site in displacement_set is in [0, 1)^dim
        self.displacement_set = displacement_set

        self.dhash = DerivativeMultiLatticeHash(self.hnf, self.displacement_set)

        self.rotations, self.translations = self._get_superlattice_invariant_subgroup(
            rotations, translations
        )

        self.list_dsites = self.dhash.get_distinct_derivative_sites_list()
        self.list_csites = self.dhash.get_canonical_sites_list()

        self._prm_t = self._get_translation_permutations()
        self.prm_rigid = self._get_rigid_permutations()

    @property
    def dim(self):
        return self.dhash.dim

    @property
    def index(self):
        return self.dhash.index

    @property
    def num_sites(self):
        return self.dhash.num_sites

    @property
    def prm_t(self):
        return self._prm_t

    def _get_superlattice_invariant_subgroup(
        self, rotations: np.ndarray, translations: np.ndarray
    ):
        valid_rotations = []
        valid_translations = []

        for R, tau in zip(rotations, translations):
            if not is_same_lattice(np.dot(R, self.hnf), self.hnf):
                continue

            valid_rotations.append(R)
            valid_translations.append(tau)

        assert len(rotations) % len(valid_rotations) == 0
        return np.array(valid_rotations), np.array(valid_translations)

    def _get_translation_permutations(self):
        list_permutations = []
        for add_factor in self.dhash.get_all_factors():
            new_list_csites = []
            for csite in self.list_csites:
                new_factor = self.dhash.modulus_factor(
                    np.array(csite.factor) + np.array(add_factor)
                )
                new_csite = CanonicalSite(csite.site_index, new_factor)
                new_list_csites.append(new_csite)

            # permutation represenation
            perm = [self.dhash.ravel_canonical_site(csite) for csite in new_list_csites]
            assert is_permutation(perm)
            list_permutations.append(perm)

        # assume list_permutations[0] is identity
        assert is_identity_permutation(list_permutations[0])

        return list_permutations

    def _get_rigid_permutations(self):
        identity = list(range(self.num_sites))
        list_permutations = [
            identity,
        ]

        for R, tau in zip(self.rotations, self.translations):
            new_list_csites = []
            for dsite in self.list_dsites:
                frac_coord = self.displacement_set[dsite.site_index] + np.array(dsite.jimage)
                acted_frac_coord = np.dot(R, frac_coord) + tau
                new_csite = self.dhash.hash_frac_coords(acted_frac_coord)
                assert new_csite is not None
                new_list_csites.append(new_csite)

            perm = [self.dhash.ravel_canonical_site(csite) for csite in new_list_csites]
            assert is_permutation(perm)
            if perm not in list_permutations:
                list_permutations.append(perm)

        # this set of permutations is not group!
        return list_permutations

    def get_symmetry_operation_permutations(self):
        """
        return permutation representation of the symmetry group of the supercell
        """
        list_permutations = []

        for p1 in self.prm_t:
            for p2 in self.prm_rigid:
                perm = product_permutations(p1, p2)
                assert perm not in list_permutations
                list_permutations.append(perm)

        # assume list_permutations[0] is identity
        assert is_identity_permutation(list_permutations[0])

        return list_permutations