Esempio n. 1
0
    def test_xyz(self):
        op = SymmOp([[1, -1, 0, 0], [0, -1, 0, 0], [0, 0, -1, 0], [0, 0, 0,
                                                                   1]])
        s = op.as_xyz_string()
        self.assertEqual(s, 'x-y, -y, -z')
        self.assertEqual(op, SymmOp.from_xyz_string(s))

        op2 = SymmOp([[0, -1, 0, 0.5], [1, 0, 0, 0.5], [0, 0, 1, 0.5 + 1e-7],
                      [0, 0, 0, 1]])
        s2 = op2.as_xyz_string()
        self.assertEqual(s2, '-y+1/2, x+1/2, z+1/2')
        self.assertEqual(op2, SymmOp.from_xyz_string(s2))

        op2 = SymmOp([[3, -2, -1, 0.5], [-1, 0, 0, 12. / 13],
                      [0, 0, 1, 0.5 + 1e-7], [0, 0, 0, 1]])
        s2 = op2.as_xyz_string()
        self.assertEqual(s2, '3x-2y-z+1/2, -x+12/13, z+1/2')
        self.assertEqual(op2, SymmOp.from_xyz_string(s2))

        op3 = SymmOp.from_xyz_string('3x - 2y - z+1 /2 , -x+12/ 13, z+1/2')
        self.assertEqual(op2, op3)

        # Ensure strings can be read in any order
        op4 = SymmOp.from_xyz_string('1 /2 + 3X - 2y - z , 12/ 13-x, z+1/2')
        op5 = SymmOp.from_xyz_string('+1 /2 + 3x - 2y - z , 12/ 13-x, +1/2+z')
        self.assertEqual(op4, op3)
        self.assertEqual(op4, op5)
        self.assertEqual(op3, op5)

        self.assertRaises(ValueError, self.op.as_xyz_string)

        o = SymmOp.from_xyz_string('0.5+x, 0.25+y, 0.75+z')
        self.assertArrayAlmostEqual(o.translation_vector, [0.5, 0.25, 0.75])
        o = SymmOp.from_xyz_string('x + 0.5, y + 0.25, z + 0.75')
        self.assertArrayAlmostEqual(o.translation_vector, [0.5, 0.25, 0.75])
Esempio n. 2
0
def site_symm(point, gen_pos, tol=1e-3, lattice=Euclidean_lattice):
    '''
    Given gen_pos (a list of SymmOps), return the list of symmetry operations
    leaving a point (coordinate or SymmOp) invariant.
    '''
    #Convert point into a SymmOp
    if type(point) != SymmOp:
        point = SymmOp.from_rotation_and_translation([[0,0,0],[0,0,0],[0,0,0]], point)
    symmetry = []
    for op in gen_pos:
        is_symmetry = True
        #Calculate the effect of applying op to point
        difference = SymmOp(point.affine_matrix - (op*point).affine_matrix)
        #Check that the rotation matrix is unaltered by op
        if not np.allclose(difference.rotation_matrix, np.zeros((3,3)), rtol = 1e-3, atol = 1e-3):
            is_symmetry = False
        #Check that the displacement is less than tol
        displacement = difference.translation_vector
        if distance(displacement, lattice) > tol:
            is_symmetry = False
        if is_symmetry:
            '''The actual site symmetry's translation vector may vary from op by
            a factor of +1 or -1 (especially when op contains +-1/2).
            We record this to distinguish between special Wyckoff positions.
            As an example, consider the point (-x+1/2,-x,x+1/2) in position 16c
            of space group Ia-3(206). The site symmetry includes the operations
            (-z+1,x-1/2,-y+1/2) and (y+1/2,-z+1/2,-x+1). These operations are
            not listed in the general position, but correspond to the operations
            (-z,x+1/2,-y+1/2) and (y+1/2,-z+1/2,-x), respectively, just shifted
            by (+1,-1,0) and (0,0,+1), respectively.
            '''
            el = SymmOp.from_rotation_and_translation(op.rotation_matrix, op.translation_vector + np.round(displacement))
            symmetry.append(el)
    return symmetry
Esempio n. 3
0
def get_inverse(op):
    """
    Given a SymmOp object, returns its inverse.

    Args:
        op: a Symmop object

    Returns:
        the inverse
    """
    matrix = op.affine_matrix.copy()
    # fill the matrix if it is ill conditioned
    # experimental
    if np.linalg.matrix_rank(matrix) < 4:
        for row in range(3):
            # fixed value
            if np.sum(matrix[row, :3]**2) < 1e-3:
                matrix[row, row] = 1
                matrix[row, 3] = 0

        if np.linalg.matrix_rank(matrix) == 3:
            # [-3x/2, -x/2, 1/4]
            # [0, x, 1/4]
            for rows in [[0, 1, 2], [1, 2, 0], [0, 2, 1]]:
                #m = (matrix[rows,:])[:,rows]
                #print(rows, m)
                if np.linalg.matrix_rank(matrix[rows[:2], :3]) != 2:
                    break
            id0, id1, id2 = rows[0], rows[1], rows[2]
            if matrix[id0, id1] == 0:
                matrix[id0, id1], matrix[id0, id0] = matrix[id0,
                                                            id0], matrix[id0,
                                                                         id1]
                if np.linalg.matrix_rank(matrix) == 3:
                    matrix[id0, id1], matrix[id0,
                                             id2] = matrix[id0,
                                                           id2], matrix[id0,
                                                                        id1]
            else:
                matrix[id1, id0], matrix[id1, id1] = matrix[id1,
                                                            id1], matrix[id1,
                                                                         id0]
                if np.linalg.matrix_rank(matrix) == 3:
                    matrix[id1, id0], matrix[id1,
                                             id2] = matrix[id1,
                                                           id2], matrix[id1,
                                                                        id0]

        elif np.linalg.matrix_rank(matrix) == 2:
            # -3x/2, -x/2, -x+1/4
            if np.sum(matrix[:, 0]**2) > 1e-3:
                matrix[1, 0], matrix[1, 1] = matrix[1, 1], matrix[1, 0]
                matrix[2, 0], matrix[2, 2] = matrix[2, 2], matrix[2, 0]
            elif np.sum(matrix[:, 1]**2) > 1e-3:
                matrix[0, 1], matrix[0, 0] = matrix[0, 0], matrix[0, 1]
                matrix[2, 1], matrix[2, 2] = matrix[2, 2], matrix[2, 1]
            else:
                matrix[0, 2], matrix[0, 0] = matrix[0, 0], matrix[0, 2]
                matrix[1, 2], matrix[1, 1] = matrix[1, 1], matrix[1, 2]
    return SymmOp(np.linalg.inv(matrix))
Esempio n. 4
0
 def test_to_from_dict(self):
     op = SymmOp([[3, -2, -1, 0.5], [-1, 0, 0, 12. / 13],
                  [0, 0, 1, 0.5 + 1e-7], [0, 0, 0, 1]])
     magop = MagSymmOp.from_symmop(op, -1)
     magop2 = MagSymmOp.from_dict(magop.as_dict())
     self.assertEqual(magop2.time_reversal, -1)
     self.assertEqual(magop2.as_xyzt_string(), '3x-2y-z+1/2, -x+12/13, z+1/2, -1')
Esempio n. 5
0
def generate_full_symmops(symmops, tol):
    """
    Recursive algorithm to permute through all possible combinations of the
    initially supplied symmetry operations to arrive at a complete set of
    operations mapping a single atom to all other equivalent atoms in the
    point group.  This assumes that the initial number already uniquely
    identifies all operations.

    Args:
        symmops ([SymmOp]): Initial set of symmetry operations.

    Returns:
        Full set of symmetry operations.
    """

    a = [o.affine_matrix for o in symmops]

    if len(symmops) > 300:
        logger.debug("Generation of symmetry operations in infinite loop.  " +
                     "Possible error in initial operations or tolerance too "
                     "low.")
    else:
        for op1, op2 in itertools.product(symmops, symmops):
            m = np.dot(op1.affine_matrix, op2.affine_matrix)
            d = np.abs(a - m) < tol
            if not np.any(np.all(np.all(d, axis=2), axis=1)):
                return generate_full_symmops(symmops + [SymmOp(m)], tol)

    return symmops
Esempio n. 6
0
 def symmetry_ops(self):
     """
     Full set of symmetry operations as matrices. Lazily initialized as
     generation sometimes takes a bit of time.
     """
     if self._symmetry_ops is None:
         self._symmetry_ops = [
             SymmOp(m) for m in self._generate_full_symmetry_ops()]
     return self._symmetry_ops
Esempio n. 7
0
    def test_xyz(self):
        op = SymmOp([[1, -1, 0, 0], [0, -1, 0, 0], [0, 0, -1, 0], [0, 0, 0, 1]])
        s = op.as_xyz_string()
        self.assertEqual(s, "x-y, -y, -z")
        self.assertEqual(op, SymmOp.from_xyz_string(s))

        op2 = SymmOp(
            [[0, -1, 0, 0.5], [1, 0, 0, 0.5], [0, 0, 1, 0.5 + 1e-7], [0, 0, 0, 1]]
        )
        s2 = op2.as_xyz_string()
        self.assertEqual(s2, "-y+1/2, x+1/2, z+1/2")
        self.assertEqual(op2, SymmOp.from_xyz_string(s2))

        op2 = SymmOp(
            [
                [3, -2, -1, 0.5],
                [-1, 0, 0, 12.0 / 13],
                [0, 0, 1, 0.5 + 1e-7],
                [0, 0, 0, 1],
            ]
        )
        s2 = op2.as_xyz_string()
        self.assertEqual(s2, "3x-2y-z+1/2, -x+12/13, z+1/2")
        self.assertEqual(op2, SymmOp.from_xyz_string(s2))

        op3 = SymmOp.from_xyz_string("3x - 2y - z+1 /2 , -x+12/ 13, z+1/2")
        self.assertEqual(op2, op3)

        # Ensure strings can be read in any order
        op4 = SymmOp.from_xyz_string("1 /2 + 3X - 2y - z , 12/ 13-x, z+1/2")
        op5 = SymmOp.from_xyz_string("+1 /2 + 3x - 2y - z , 12/ 13-x, +1/2+z")
        self.assertEqual(op4, op3)
        self.assertEqual(op4, op5)
        self.assertEqual(op3, op5)

        # TODO: assertWarns not in Python 2.x unittest
        # update PymatgenTest for unittest2?
        # self.assertWarns(UserWarning, self.op.as_xyz_string)

        o = SymmOp.from_xyz_string("0.5+x, 0.25+y, 0.75+z")
        self.assertArrayAlmostEqual(o.translation_vector, [0.5, 0.25, 0.75])
        o = SymmOp.from_xyz_string("x + 0.5, y + 0.25, z + 0.75")
        self.assertArrayAlmostEqual(o.translation_vector, [0.5, 0.25, 0.75])
Esempio n. 8
0
def get_inverse(op):
    """
    Given a SymmOp object, returns its inverse.

    Args:
        op: a Symmop object

    Returns:
        the inverse
    """
    return SymmOp(np.linalg.inv(op.affine_matrix))
Esempio n. 9
0
    def symmetry_ops(self) -> set[SymmOp]:
        """
        Full set of symmetry operations as matrices. Lazily initialized as
        generation sometimes takes a bit of time.
        """
        from pymatgen.core.operations import SymmOp

        if self._symmetry_ops is None:
            self._symmetry_ops = {
                SymmOp(m)
                for m in self._generate_full_symmetry_ops()
            }
        return self._symmetry_ops
Esempio n. 10
0
 def rotate(self, frac=False):
     R = rotate_matrix()
     arr1 = np.zeros(3)
     R = np.vstack((R, arr1))
     arr2 = np.array([0, 0, 0, 1])
     R = np.vstack((R.T, arr2))
     affine_matrix = R.T
     sym = SymmOp(affine_matrix)
     init_st = copy.copy(self.struct)
     if frac is True:
         init_st.apply_operation(sym, fractional=True)
     else:
         init_st.apply_operation(sym, fractional=False)
     self.rotate = init_st
Esempio n. 11
0
    def test_apply_operation(self):
        op = SymmOp.from_axis_angle_and_translation([0, 0, 1], 90)
        s = self.structure.copy()
        s.apply_operation(op)
        self.assertArrayAlmostEqual(
            s.lattice.matrix,
            [[0.000000, 3.840198, 0.000000], [-3.325710, 1.920099, 0.000000],
             [2.217138, -0.000000, 3.135509]], 5)

        op = SymmOp([[1, 1, 0, 0.5], [1, 0, 0, 0.5], [0, 0, 1, 0.5],
                     [0, 0, 0, 1]])
        s = self.structure.copy()
        s.apply_operation(op, fractional=True)
        self.assertArrayAlmostEqual(
            s.lattice.matrix,
            [[5.760297, 3.325710, 0.000000], [3.840198, 0.000000, 0.000000],
             [0.000000, -2.217138, 3.135509]], 5)
Esempio n. 12
0
    def _analyze(self):
        if len(self.centered_mol) == 1:
            self.sch_symbol = "Kh"
        else:
            inertia_tensor = np.zeros((3, 3))
            total_inertia = 0
            for site in self.mol:
                c = site.coords
                wt = site.species_and_occu.weight
                for i in range(3):
                    inertia_tensor[i, i] += wt * (c[(i + 1) % 3]**2 +
                                                  c[(i + 2) % 3]**2)
                for i, j in itertools.combinations(list(range(3)), 2):
                    inertia_tensor[i, j] += -wt * c[i] * c[j]
                    inertia_tensor[j, i] += -wt * c[j] * c[i]
                total_inertia += wt * np.dot(c, c)

            # Normalize the inertia tensor so that it does not scale with size
            # of the system.  This mitigates the problem of choosing a proper
            # comparison tolerance for the eigenvalues.
            inertia_tensor /= total_inertia
            eigvals, eigvecs = np.linalg.eig(inertia_tensor)
            self.principal_axes = eigvecs.T
            self.eigvals = eigvals
            v1, v2, v3 = eigvals
            eig_zero = abs(v1 * v2 * v3) < self.eig_tol**3
            eig_all_same = abs(v1 - v2) < self.eig_tol and abs(
                v1 - v3) < self.eig_tol
            eig_all_diff = abs(v1 - v2) > self.eig_tol and abs(
                v1 - v3) > self.eig_tol and abs(v2 - v3) > self.eig_tol

            self.rot_sym = []
            self.symmops = [SymmOp(np.eye(4))]

            if eig_zero:
                logger.debug("Linear molecule detected")
                self._proc_linear()
            elif eig_all_same:
                logger.debug("Spherical top molecule detected")
                self._proc_sph_top()
            elif eig_all_diff:
                logger.debug("Asymmetric top molecule detected")
                self._proc_asym_top()
            else:
                logger.debug("Symmetric top molecule detected")
                self._proc_sym_top()
Esempio n. 13
0
    def test_xyzt_string(self):

        xyzt_strings = [
            'x, y, z, +1', 'x, y, z, -1', '-y+1/2, x+1/2, x+1/2, +1'
        ]

        for xyzt_string in xyzt_strings:
            op = MagSymmOp.from_xyzt_string(xyzt_string)
            xyzt_string_out = op.as_xyzt_string()
            self.assertEqual(xyzt_string, xyzt_string_out)

        op = SymmOp([[3, -2, -1, 0.5], [-1, 0, 0, 12. / 13],
                     [0, 0, 1, 0.5 + 1e-7], [0, 0, 0, 1]])

        magop = MagSymmOp.from_symmop(op, -1)
        magop_str = magop.as_xyzt_string()
        self.assertEqual(magop.time_reversal, -1)
        self.assertEqual(magop_str, '3x-2y-z+1/2, -x+12/13, z+1/2, -1')
Esempio n. 14
0
    def split_k(self, wp1, wp2_lists):
        """
        split the generators in w1 to different w2s for k-subgroup
        """

        wp1_generators = [np.array(wp.as_dict()['matrix']) for wp in wp1]

        G1_orbits = []
        G2_orbits = []
        quadrant=deepcopy(self.inv_R[:3,3])
        quadrant[np.abs(quadrant)<1e-5]=0 #finds the orientation of the subgroup_basis
        for i in range(3):
            if quadrant[i]>=0:
                quadrant[i]=1
            else:
                quadrant[i]=-1


        all_g2_orbits = []
        translations = self.translation_generator()
        for translation in translations: #the translation generator provides all the possible ways to translate the starting positions, then they are shifted
            for gen in wp1_generators:#into the proper orientation
                orbit=np.matmul(self.inv_R,gen)
                orbit[np.abs(orbit)<1e-5]=0
                orbit[np.abs(orbit-1)<1e-5]=1
                orbit[np.abs(orbit+1)<1e-5]=-1
                for i in range(3):
                    if quadrant[i]==1:
                        orbit[i][3]+=translation[i]
                        orbit[i][3]=orbit[i][3]%1
                        if np.abs(orbit[i][3]-1)<1e-5:
                            orbit[i][3]=0
                    else:
                        orbit[i][3]+=(translation[i])%-1
                        orbit[i][3]=orbit[i][3]%-1
                        if np.abs(orbit[i][3])<1e-5:
                            orbit[i][3]=-1
                all_g2_orbits.append(orbit)




        for wp2 in wp2_lists:

            #final_G2=[]
            temp=np.array(deepcopy(all_g2_orbits))
            temp[np.abs(temp) <1e-5] =0
            temp=temp.tolist()

            for j, x in enumerate(temp):
                temp[j]=SymmOp(x)

            for orbit in temp:

                try_match=np.array([np.matmul(x.as_dict()['matrix'], orbit.as_dict()['matrix']) for x in wp2])
                try_match[np.abs(try_match) <1e-5]=0
                try_match[np.abs(try_match-1) <1e-5]=1
                try_match[np.abs(try_match+1) <1e-5]=-1

                for j in range(len(try_match)):
                    for k in range(3):
                        try_match[j][k][3]=try_match[j][k][3]%quadrant[k]
                        if try_match[j][k][3]==0 and quadrant[k]==-1:
                            try_match[j][k][3]=-1
                try_match=try_match.tolist()


                for j,x in enumerate(try_match):
                    try_match[j]=SymmOp(x)

                if np.any([try_match.count(x)>1 for x in try_match]):
                    continue

                try:
                    corresponding_positions=[temp.index(x) for x in try_match]
                except:
                    continue
                for index in sorted(corresponding_positions,reverse=True):
                    del all_g2_orbits[index]
                G2_orbits.append(try_match)
                break

        for position in G2_orbits:
            final_G1=[]
            for orbit in position:
                final_G1.append(SymmOp(np.matmul(self.R,orbit.as_dict()['matrix'])))
            G1_orbits.append(final_G1)


        if len(G1_orbits)!=len(wp2_lists):
            raise ValueError('inaccurate')
        else:
            return G1_orbits, G2_orbits
Esempio n. 15
0
    def split_t(self, wp1, wp2_lists, quadrant=None):
        """
        split the generators in w1 to different w2s
        """
        if self.counter == 0:
            self.proper_wp1 = []
            [
                self.proper_wp1.append(np.array(x.as_dict()['matrix']))
                for x in wp1
            ]
            self.original_tau_list = [x[:3, 3] for x in self.proper_wp1]
            for k, x in enumerate(self.original_tau_list):
                for j in range(3):
                    self.original_tau_list[k][
                        j] = self.original_tau_list[k][j] % 1
                self.original_tau_list[k] = self.original_tau_list[k].round(4)
            for k, x in enumerate(self.proper_wp1):
                self.proper_wp1[k][:3, 3] = self.original_tau_list[k]
                self.proper_wp1[k] = SymmOp(self.proper_wp1[k])

        wp1_generators_visited = []
        wp1_generators = [np.array(wp.as_dict()['matrix']) for wp in wp1]

        G1_orbits = []
        G2_orbits = []
        factor = max([1, np.linalg.det(self.R)])

        if quadrant is None:
            quadrant = deepcopy(self.inv_R[:3, 3])
            quadrant[np.abs(quadrant) < 1e-5] = 0
            for i in range(3):
                if quadrant[i] >= 0:
                    quadrant[i] = 1
                else:
                    quadrant[i] = -1
        for wp2 in wp2_lists:

            for l, gen in enumerate(wp1_generators):

                good_generator = False

                trans_generator = np.matmul(self.inv_R, gen)
                trans_generator[np.abs(trans_generator) < 1e-5] = 0

                for i in range(3):
                    trans_generator[i][3] = trans_generator[i][3] % quadrant[i]
                    if trans_generator[i][3] == 0 and quadrant[i] == -1:
                        trans_generator[i][3] = -1

                g1_orbits = []
                g2_orbits = []
                strs = []

                for i, wp in enumerate(wp2):

                    new_basis_orbit = np.matmul(wp.as_dict()['matrix'],
                                                trans_generator)
                    new_basis_orbit[np.abs(new_basis_orbit) < 1e-5] = 0
                    for j in range(3):
                        new_basis_orbit[j,
                                        3] = new_basis_orbit[j,
                                                             3] % quadrant[j]
                        if new_basis_orbit[j, 3] == 0 and quadrant[j] == -1:
                            new_basis_orbit[j, 3] = -1

                    old_basis_orbit = np.matmul(self.R, new_basis_orbit)
                    old_basis_orbit[np.abs(old_basis_orbit) < 1e-5] = 0
                    old_basis_orbit[np.abs(old_basis_orbit - 1) < 1e-5] = 1
                    old_basis_orbit[np.abs(old_basis_orbit + 1) < 1e-5] = -1
                    tmp = deepcopy(old_basis_orbit)
                    tmp[3, :] = [0, 0, 0, 1]
                    if i == 0:
                        truth = True
                        if self.counter != 0:

                            tau = tmp[:3, 3]
                            for j in range(3):
                                tau[j] = tau[j] % 1
                            tau = tau.round(4)
                            temporary = deepcopy(tmp)
                            temporary[:3, 3] = tau
                            temporary = SymmOp(temporary)
                            truth = any(
                                [temporary == x for x in self.proper_wp1])
                        if not in_lists(tmp,
                                        wp1_generators_visited) and in_lists(
                                            tmp, wp1_generators) and truth:

                            good_generator = True

                        else:
                            break
                    # to consider PBC
                    g1_orbits.append(old_basis_orbit)
                    if self.counter >= 1 and in_lists(new_basis_orbit,
                                                      g2_orbits):
                        good_generator = False
                        break
                    g2_orbits.append(new_basis_orbit)

                if good_generator:

                    temp = []

                    for gen in g1_orbits:
                        if not in_lists(gen, temp, PBC=False):
                            temp.append(gen)
                    if int(len(temp) * factor) >= len(wp2):

                        wp1_generators_visited.extend(temp)
                        g1_orbits = [SymmOp(orbit) for orbit in g1_orbits]
                        g2_orbits = [SymmOp(orbit) for orbit in g2_orbits]

                        G1_orbits.append(g1_orbits)
                        G2_orbits.append(g2_orbits)

                        break
            try:
                self.check_orbits(g1_orbits, wp1, wp2, wp2_lists)
            except:
                if self.counter != 0:
                    quadrants = [[1, 1, 1], [1, 1, -1], [1, -1, 1],
                                 [1, -1, -1], [-1, 1, 1], [-1, 1, -1],
                                 [-1, -1, 1], [-1, -1, -1]]
                    quadrant = quadrants[self.counter - 1]
                wp1_generators = wp1_generators[:self.current_wp1_size]
                wp2_translations = []
                for wp2 in wp2_lists:
                    wp = [np.array(x.as_dict()['matrix']) for x in wp2]
                    rot = [x[:3, :3] for x in wp]
                    tau = [x[:3, 3] for x in wp]
                    translations = [
                        np.array(tau[i]) for i, x in enumerate(rot)
                        if np.array_equal(x, rot[0])
                    ]
                    translations = [x - translations[0] for x in translations]
                    wp2_translations.append(translations)
                new_wp1 = []
                for translation_set in wp2_translations:
                    for translation in translation_set:
                        for gen in wp1_generators:
                            orbit = np.matmul(self.inv_R, gen)
                            orbit[np.abs(orbit) < 1e-5] = 0
                            orbit[np.abs(orbit - 1) < 1e-5] = 1
                            orbit[np.abs(orbit + 1) < 1e-5] = -1

                            for i in range(3):
                                if quadrant[i] == 1:
                                    orbit[i][3] += (translation[i]) % 1
                                    orbit[i][3] = orbit[i][3] % 1
                                else:

                                    orbit[i][3] += (translation[i]) % -1
                                    orbit[np.abs(orbit) < 1e-5] = 0
                                    orbit[np.abs(orbit - 1) < 1e-5] = 1
                                    orbit[np.abs(orbit + 1) < 1e-5] = -1
                                    if orbit[i][3] == 0:
                                        orbit[i][3] = -1
                                    elif orbit[i][3] != -1:
                                        orbit[i][3] = orbit[i][3] % -1
                            orbit = np.matmul(self.R, orbit)
                            orbit[np.abs(orbit) < 1e-5] = 0
                            orbit[np.abs(orbit - 1) < 1e-5] = 1
                            orbit[np.abs(orbit + 1) < 1e-5] = -1
                            orbit = SymmOp(orbit)

                            if orbit not in new_wp1:
                                new_wp1.append(orbit)
                self.counter += 1
                if self.counter == 5:
                    self.valid_split = False
                    self.error = True
                    return None, None
                return self.split_t(new_wp1, wp2_lists, quadrant=quadrant)
        return G1_orbits, G2_orbits
Esempio n. 16
0
    def k_split2(self, wp1, wp2_lists):
        """
        split the generators in w1 to different w2
        """
        def add_g2_orbits(orbit, translations):

            new_g2 = []
            for translation in translations:
                pos = deepcopy(orbit)
                pos[np.abs(pos) < 1e-5] = 0

                for p in range(3):
                    if pos[p][3] >= 0:
                        pos[p][3] += translation[p]
                        pos[p][3] = pos[p][3] % 1
                    else:
                        pos[p][3] += (translation[p]) % -1
                        if pos[p][3] != -1:
                            pos[p][3] = pos[p][3] % -1

                new_g2.append(pos)
            return new_g2

        wp1_generators = [np.array(wp.as_dict()['matrix']) for wp in wp1]

        G1_orbits = []
        G2_orbits = []

        all_g2_orbits = []
        translations = self.translation_generator()

        for translation in translations:
            for gen in wp1_generators:
                orbit = np.matmul(self.inv_R, gen)
                orbit[np.abs(orbit) < 1e-5] = 0
                for i in range(3):
                    if orbit[i][3] >= 0.:
                        orbit[i][3] += translation[i]
                        orbit[i][3] = orbit[i][3] % 1
                    else:
                        orbit[i][3] += (translation[i]) % -1
                        if orbit[i][3] != -1:
                            orbit[i][3] = orbit[i][3] % -1
                all_g2_orbits.append(orbit)

        for i in range(len(wp2_lists)):
            match = False
            ite = 0
            while not match:
                final_G2 = []
                temp = np.array(deepcopy(all_g2_orbits))
                for j in range(len(temp)):
                    temp[j][:3, 3] = temp[j][:3, 3] % 1
                temp = temp.round(3).tolist()
                for orbit in temp:
                    try_match = np.array([
                        np.matmul(x.as_dict()['matrix'], orbit)
                        for x in wp2_lists[i]
                    ])
                    for j in range(len(try_match)):
                        try_match[j][:3, 3] = try_match[j][:3, 3] % 1

                    try_match = try_match.round(3).tolist()
                    corresponding_positions = []
                    duplicates = []
                    for x in try_match:
                        if x not in duplicates:
                            duplicates.append(x)
                    if len(duplicates) != len(try_match):
                        continue

                    try:
                        corresponding_positions = [
                            temp.index(x) for x in try_match
                        ]
                        for index in sorted(corresponding_positions,
                                            reverse=True):
                            final_G2.append(all_g2_orbits[index])
                            del all_g2_orbits[index]

                        G2_orbits.append(final_G2)
                        match = True
                        break
                    except:
                        continue
                if len(corresponding_positions) == 0:

                    trial = all_g2_orbits[0]
                    quadrant = [0, 0, 0]
                    for f in range(3):
                        if trial[f][3] < 0.:
                            quadrant[f] = -1
                        else:
                            quadrant[f] = 1
                    try_match = np.array([
                        np.matmul(x.as_dict()['matrix'], trial)
                        for x in wp2_lists[i]
                    ])

                    for j in range(len(try_match)):
                        for k in range(3):
                            if try_match[j][k][3] >= 1:
                                try_match[j][k][3] = try_match[j][k][3] % 1

                    temp_try_match = deepcopy(try_match)

                    for j in range(len(try_match)):
                        try_match[j][:3, 3] = try_match[j][:3, 3] % 1
                    try_match = try_match.round(3).tolist()
                    temp = np.array(deepcopy(all_g2_orbits))
                    for j in range(len(temp)):
                        temp[j][:3, 3] = temp[j][:3, 3] % 1
                    temp = temp.round(3).tolist()

                    necessary_orbits = [x for x in try_match if x not in temp]
                    necessary_index = [
                        try_match.index(x) for x in necessary_orbits
                    ]
                    trial_orbit = temp_try_match[choice(necessary_index)]

                    for f in range(3):
                        trial_orbit[f][3] = trial_orbit[f][3] % (quadrant[f])

                    all_g2_orbits.extend(
                        add_g2_orbits(trial_orbit, translations))
                    ite += 1

        for position in G2_orbits:
            final_G1 = []
            for orbit in position:
                final_G1.append(SymmOp(np.matmul(self.R, orbit).round(3)))
            G1_orbits.append(final_G1)

        for i, position in enumerate(G2_orbits):
            for j, orbit in enumerate(position):
                G2_orbits[i][j] = SymmOp(orbit)

        return G1_orbits, G2_orbits
Esempio n. 17
0
    def split_t(self, wp1, wp2_lists, quadrant=None):
        """
        split the generators in w1 to different w2s for t-subgroup
        """
        if self.counter==0:
            self.proper_wp1=[]
            [self.proper_wp1.append(np.array(x.as_dict()['matrix'])) for x in wp1]
            self.original_tau_list=[x[:3,3] for x in self.proper_wp1]
            for k,x in enumerate(self.original_tau_list):
                for j in range(3):
                    self.original_tau_list[k][j]=self.original_tau_list[k][j]%1
                self.original_tau_list[k]=self.original_tau_list[k].round(4)
            for k,x in enumerate(self.proper_wp1):
                self.proper_wp1[k][:3,3]=self.original_tau_list[k]
                self.proper_wp1[k]=SymmOp(self.proper_wp1[k])

        wp1_generators_visited = []
        wp1_generators = [np.array(wp.as_dict()['matrix']) for wp in wp1]

        if np.all([wp2_lists[0]==x for x in wp2_lists]) and len(wp2_lists)==2:
            w1=deepcopy(wp1_generators[1])
            w2=deepcopy(wp1_generators[2])
            wp1_generators[1]=w2
            wp1_generators[2]=w1

        G1_orbits = []
        G2_orbits = []
        factor = max([1,np.linalg.det(self.R)])

        if quadrant is None:
            quadrant=deepcopy(self.inv_R[:3,3])
            quadrant[np.abs(quadrant)<1e-5]=0
            for i in range(3):
                if quadrant[i]>=0:
                    quadrant[i]=1
                else:
                    quadrant[i]=-1
        for wp2 in wp2_lists:
            # [print(SymmOp(np.matmul(self.inv_R,x)).as_xyz_string()) for x in wp1_generators]
            for gen in wp1_generators:

                good_generator = False
                # inv=np.linalg.inv(self.R[:3,:3])
                # t=self.R[:3,3]
                # trans_generator=np.zeros([4,4])
                # trans_generator[:3,3]=gen[:3,3]-t
                # trans_generator[:3,:3]=np.matmul(inv,gen[:3,:3])
                #
                # print("My new one",SymmOp(trans_generator).as_xyz_string())


                trans_generator = np.matmul(self.inv_R, gen)
                trans_generator[np.abs(trans_generator)<1e-5]=0

                for i in range(3):
                    trans_generator[i][3]=trans_generator[i][3]%quadrant[i]
                    if trans_generator[i][3]==0 and quadrant[i]==-1:
                        trans_generator[i][3]=-1
                g1_orbits = []
                g2_orbits = []

                for i, wp in enumerate(wp2):

                    new_basis_orbit = np.matmul(wp.as_dict()['matrix'], trans_generator)
                    new_basis_orbit[np.abs(new_basis_orbit)<1e-5]=0
                    for j in range(3):
                        new_basis_orbit[j,3]=new_basis_orbit[j,3]%quadrant[j]
                        if new_basis_orbit[j,3]==0 and quadrant[j]==-1:
                            new_basis_orbit[j,3]=-1


                    old_basis_orbit = np.matmul(self.R, new_basis_orbit)
                    old_basis_orbit[np.abs(old_basis_orbit)<1e-5]=0
                    old_basis_orbit[np.abs(old_basis_orbit-1)<1e-5]=1
                    old_basis_orbit[np.abs(old_basis_orbit+1)<1e-5]=-1
                    tmp = deepcopy(old_basis_orbit)
                    tmp[3,:] = [0, 0, 0, 1]
                    # print('tracking wp2 orbit',i,'newbasisorbit',SymmOp(new_basis_orbit).as_xyz_string(),'oldbasisorbit',SymmOp(old_basis_orbit).as_xyz_string(), 'chosenwyckoff',wp.as_xyz_string())
                    # print('transgenerator',SymmOp(trans_generator).as_xyz_string())
                    if i==0:
                        truth=True
                        if self.counter!=0:

                            tau=tmp[:3,3]
                            for j in range(3):
                                tau[j]=tau[j]%1
                            tau=tau.round(4)
                            temporary=deepcopy(tmp)
                            temporary[:3,3]=tau
                            temporary=SymmOp(temporary)
                            truth=any([temporary==x for x in self.proper_wp1])
                        # print('current state')
                        # print('wp1generated')
                        # [print(SymmOp(x).as_xyz_string()) for x in wp1_generators_visited]
                        # print('not in wp1 visited',not in_lists(tmp, wp1_generators_visited))
                        # print('in wp1 generators',in_lists(tmp, wp1_generators))
                        if not in_lists(tmp, wp1_generators_visited) and in_lists(tmp, wp1_generators) and truth:

                            good_generator = True

                        else:
                            break
                    # to consider PBC
                    # print(SymmOp(old_basis_orbit).as_xyz_string(),'   ',SymmOp(new_basis_orbit).as_xyz_string(),'    ',wp.as_xyz_string())
                    g1_orbits.append(old_basis_orbit)
                    if self.counter>=1 and in_lists(new_basis_orbit,g2_orbits):
                        good_generator=False
                        break
                    g2_orbits.append(new_basis_orbit)


                if good_generator:

                    temp=[]

                    for gen in g1_orbits:
                        if not in_lists(gen, temp, PBC=False):
                            temp.append(gen)
                    if int(len(temp)*factor) >= len(wp2):

                        wp1_generators_visited.extend(temp)
                        g1_orbits = [SymmOp(orbit) for orbit in g1_orbits]
                        g2_orbits = [SymmOp(orbit) for orbit in g2_orbits]
                        # print('G1=')
                        # [print(x.as_xyz_string()) for x in g1_orbits]
                        # print('G2=')
                        # [print(x.as_xyz_string()) for x in g2_orbits]
                        G1_orbits.append(g1_orbits)
                        G2_orbits.append(g2_orbits)

                        break
            try:
                self.check_orbits(g1_orbits, wp2, wp2_lists)
            except:
                if self.counter!=0:
                    quadrants=[[1,1,1],[1,1,-1],[1,-1,1],[1,-1,-1],[-1,1,1],[-1,1,-1],[-1,-1,1],[-1,-1,-1]]
                    quadrant=quadrants[self.counter-1]
                wp1_generators=wp1_generators[:self.current_wp1_size]
                wp2_translations=[]
                for wp2 in wp2_lists:
                    wp=[np.array(x.as_dict()['matrix']) for x in wp2]
                    rot=[x[:3,:3] for x in wp]
                    tau=[x[:3,3] for x in wp]
                    translations=[np.array(tau[i]) for i,x in enumerate(rot) if np.array_equal(x,rot[0])]
                    translations=[x-translations[0] for x in translations]
                    wp2_translations.append(translations)
                new_wp1=[]
                for translation_set in wp2_translations:
                    for translation in translation_set:
                        for gen in wp1_generators:
                            orbit=np.matmul(self.inv_R,gen)
                            orbit[np.abs(orbit)<1e-5]=0
                            orbit[np.abs(orbit-1)<1e-5]=1
                            orbit[np.abs(orbit+1)<1e-5]=-1

                            for i in range(3):
                                if quadrant[i]==1:
                                    orbit[i][3]+=(translation[i])%1
                                    orbit[i][3]=orbit[i][3]%1
                                else:

                                    orbit[i][3]+=(translation[i])%-1
                                    orbit[np.abs(orbit)<1e-5]=0
                                    orbit[np.abs(orbit-1)<1e-5]=1
                                    orbit[np.abs(orbit+1)<1e-5]=-1
                                    if orbit[i][3]==0:
                                        orbit[i][3]=-1
                                    elif orbit[i][3]!=-1:
                                        orbit[i][3]=orbit[i][3]%-1
                            orbit=np.matmul(self.R,orbit)
                            orbit[np.abs(orbit)<1e-5]=0
                            orbit[np.abs(orbit-1)<1e-5]=1
                            orbit[np.abs(orbit+1)<1e-5]=-1
                            orbit=SymmOp(orbit)

                            if orbit not in new_wp1:
                                new_wp1.append(orbit)
                self.counter += 1
                if self.counter == 5:
                    self.valid_split = False
                    self.error = True
                    return None, None
                return self.split_t(new_wp1, wp2_lists, quadrant=quadrant)
        return G1_orbits, G2_orbits
Esempio n. 18
0
    def split_t(self, wp1, wp2_lists):
        """
        split the generators in w1 to different w2s
        """
        #print(wp1)
        # wyckoff objects
        wp1_generators_visited = []
        wp1_generators = [np.array(wp.as_dict()['matrix']) for wp in wp1]

        # convert them to numpy array
        for generator in wp1_generators:
            generator = np.array(generator)

        G1_orbits = []
        G2_orbits = []
        factor = max([1, np.linalg.det(self.R)])

        for wp2 in wp2_lists:
            #print(wp2)
            #import sys; sys.exit()
            # try all generators here
            for gen in wp1_generators:
                good_generator = False
                #QZ: temporary solution, Needs to be fixed later
                if gen[0, 3] == 1 / 4 and gen[1, 3] == 3 / 4:
                    gen[0, 3] -= 1
                trans_generator = np.matmul(self.inv_R, gen)
                #print(trans_generator)

                g1_orbits = []
                g2_orbits = []
                strs = []
                for i, wp in enumerate(wp2):
                    new_basis_orbit = np.matmul(wp.as_dict()['matrix'],
                                                trans_generator)
                    #print(wp.as_dict()['matrix'])
                    #print(new_basis_orbit)
                    #import sys; sys.exit()
                    old_basis_orbit = np.matmul(self.R,
                                                new_basis_orbit).round(3)
                    #old_basis_orbit[3,:] = [0, 0, 0, 1]
                    tmp = deepcopy(old_basis_orbit)
                    tmp[3, :] = [0, 0, 0, 1]
                    if i == 0:
                        #print("wp1", SymmOp(gen).as_xyz_string(), in_lists(tmp, wp1_generators_visited), in_lists(tmp, wp1_generators))
                        #print("sgb", SymmOp(new_basis_orbit).as_xyz_string())
                        #print("gb", SymmOp(tmp).as_xyz_string())
                        #for w in wp1_generators:
                        #    print(SymmOp(w).as_xyz_string())
                        if not in_lists(tmp,
                                        wp1_generators_visited) and in_lists(
                                            tmp, wp1_generators):
                            #if in_lists(tmp, wp1_generators):
                            good_generator = True
                            #print("good_gener")
                        else:
                            break
                    # to consider PBC
                    g1_orbits.append(old_basis_orbit)
                    g2_orbits.append(new_basis_orbit)
                #print(g1_orbits)
                if good_generator:
                    temp = []
                    # remove duplicates due to peridoic boundary conditions
                    for gen in g1_orbits:
                        if not in_lists(gen, temp):
                            temp.append(gen)
                    if int(len(temp) * factor) >= len(wp2):
                        wp1_generators_visited.extend(temp)
                        g1_orbits = [SymmOp(orbit) for orbit in g1_orbits]
                        g2_orbits = [SymmOp(orbit) for orbit in g2_orbits]
                        G1_orbits.append(g1_orbits)
                        G2_orbits.append(g2_orbits)
                        #print("adding unique generators", len(g1_orbits), len(wp2), int(len(temp)*factor))
                        break
            #print("EEEEEE", len(g1_orbits), len(wp2))
            self.check_orbits(g1_orbits, wp1, wp2, wp2_lists)

        return G1_orbits, G2_orbits
Esempio n. 19
0
    def split_k(self, wp1, wp2_lists):
        """
        split the generators in w1 to different w2s
        """
        wp1_generators = [np.array(wp.as_dict()['matrix']) for wp in wp1]

        G1_orbits = []
        G2_orbits = []
        #         factor = max([1, np.linalg.det(self.R)])

        all_g2_orbits = []
        translations = self.translation_generator()
        for translation in translations:
            for gen in wp1_generators:
                orbit = np.matmul(self.inv_R, gen)
                for i in range(3):
                    if orbit[i][3] >= 0:
                        orbit[i][3] += translation[i]
                        orbit[i][3] = orbit[i][3] % 1
                    else:
                        orbit[i][3] -= translation[i]
                        orbit[i][3] = orbit[i][3] % -1
                all_g2_orbits.append(orbit)

        #########################################################################
        for i in range(len(wp2_lists)):
            final_G2 = []
            temp = np.array(deepcopy(all_g2_orbits))
            for j in range(len(temp)):
                temp[j][:3, 3] = temp[j][:3, 3] % 1
            temp = temp.round(3).tolist()

            for orbit in temp:
                try_match = np.array([
                    np.matmul(x.as_dict()['matrix'], orbit)
                    for x in wp2_lists[i]
                ])
                for j in range(len(try_match)):
                    try_match[j][:3, 3] = try_match[j][:3, 3] % 1

                try_match = try_match.round(3).tolist()

                try:
                    corresponding_positions = [
                        temp.index(x) for x in try_match
                    ]
                except:
                    continue
                for index in sorted(corresponding_positions, reverse=True):
                    final_G2.append(all_g2_orbits[index])
                    del all_g2_orbits[index]
                G2_orbits.append(final_G2)
                break

        for position in G2_orbits:
            final_G1 = []
            for orbit in position:
                final_G1.append(SymmOp(np.matmul(self.R, orbit).round(3)))
            G1_orbits.append(final_G1)

        for i, position in enumerate(G2_orbits):
            for j, orbit in enumerate(position):
                G2_orbits[i][j] = SymmOp(orbit)

        return G1_orbits, G2_orbits