Exemplo n.º 1
0
    def _find_mirror(self, axis):
        """
        Looks for mirror symmetry of specified type about axis.  Possible
        types are "h" or "vd".  Horizontal (h) mirrors are perpendicular to
        the axis while vertical (v) or diagonal (d) mirrors are parallel.  v
        mirrors has atoms lying on the mirror plane while d mirrors do
        not.
        """
        mirror_type = ""

        # First test whether the axis itself is the normal to a mirror plane.
        if self.is_valid_op(SymmOp.reflection(axis)):
            self.symmops.append(SymmOp.reflection(axis))
            mirror_type = "h"
        else:
            # Iterate through all pairs of atoms to find mirror
            for s1, s2 in itertools.combinations(self.centered_mol, 2):
                if s1.species_and_occu == s2.species_and_occu:
                    normal = s1.coords - s2.coords
                    if np.dot(normal, axis) < self.tol:
                        op = SymmOp.reflection(normal)
                        if self.is_valid_op(op):
                            self.symmops.append(op)
                            if len(self.rot_sym) > 1:
                                mirror_type = "d"
                                for v, r in self.rot_sym:
                                    if not np.linalg.norm(v - axis) < self.tol:
                                        if np.dot(v, normal) < self.tol:
                                            mirror_type = "v"
                                            break
                            else:
                                mirror_type = "v"
                            break

        return mirror_type
Exemplo n.º 2
0
def align_axis(structure, axis='c', direction=(0, 0, 1)):
    """
    Rotates a structure so that the specified axis is along
    the [001] direction. This is useful for adding vacuum, and
    in general for using vasp compiled with no z-axis relaxation.

    Args:
        structure (Structure): Pymatgen Structure object to rotate.
        axis: Axis to be rotated. Can be 'a', 'b', 'c', or a 1x3 vector.
        direction (vector): Final axis to be rotated to.
    Returns:
        structure. Rotated to align axis along direction.
    """

    if axis == 'a':
        axis = structure.lattice._matrix[0]
    elif axis == 'b':
        axis = structure.lattice._matrix[1]
    elif axis == 'c':
        axis = structure.lattice._matrix[2]
    proj_axis = np.cross(axis, direction)
    if not(proj_axis[0] == 0 and proj_axis[1] == 0):
        theta = (
            np.arccos(np.dot(axis, direction)
            / (np.linalg.norm(axis) * np.linalg.norm(direction)))
        )
        R = get_rotation_matrix(proj_axis, theta)
        rotation = SymmOp.from_rotation_and_translation(rotation_matrix=R)
        structure.apply_operation(rotation)
    if axis == 'c' and direction == (0, 0, 1):
        structure.lattice._matrix[2][2] = abs(structure.lattice._matrix[2][2])

    return structure
Exemplo n.º 3
0
 def from_spacegroup_number(sgnum):
     datadir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'sg_data')
     filename = str(sgnum).zfill(3) + "*"
     files = sorted(glob.glob(os.path.join(datadir, filename)))
     with open(files[0], "r") as fid:
         symmops = []
         rots = []
         lines = fid.readlines()
         sgname = lines[0].strip()
         for i in xrange(1, len(lines)):
             toks = re.split(",", lines[i].strip())
             if len(toks) == 3:
                 rot = np.zeros((3, 3))
                 trans = [0, 0, 0]
                 for j in xrange(3):
                     tok = toks[j]
                     m = re.search("([\+\-]*)([xyz])", tok)
                     if m:
                         factor = -1 if m.group(1) == "-" else 1
                         loc = ord(m.group(2)) - 120
                         rot[j, loc] = factor
                         tok = re.sub("([\+\-]*)([xyz])", "", tok)
                         if tok.strip() != '':
                             trans[j] = eval(tok)
                     rots.append(rot)
                 symmops.append(SymmOp.from_rotation_matrix_and_translation_vector(rot, trans))
         return Spacegroup(sgname, sgnum, symmops)
Exemplo n.º 4
0
def trilayer(doped = None):
    a = 5.43
    fcc = Lattice([[a/2,a/2,0],[a/2,0,a/2],[0,a/2,a/2]])
    trilayer = Structure(fcc,['Si']*2,[[0.00,0.00,0.00],[0.25,0.25,0.25]])
    
    # Make the cell cubic
    trilayer.make_supercell([[1,1,-1],[1,-1,1],[-1,1,1]])
    trilayer.make_supercell([[1,1,0],[1,-1,0],[0,0,4]])
    # Rotate the cell
    rt = 0.70710678118654746
    symmop = SymmOp.from_rotation_and_translation([[rt,rt,0],[rt,-rt,0],[0,0,1]])
    trilayer.apply_operation(symmop)
    
    if doped is not None:
        frac_coords = numpy.array([0.5,0.0,0.5])
        for i,atom in enumerate(trilayer):
            if numpy.linalg.norm(atom.frac_coords-frac_coords) < 0.001:
                trilayer.replace(i,doped,frac_coords)


    for z in [0.375,0.625]:
        for xy in [0.00,0.50]:
            trilayer.append('Mn',[xy,xy,z])

    return trilayer
Exemplo n.º 5
0
 def rotate(self, matrix, tol=1e-5):
     matrix = SquareTensor(matrix)
     if not matrix.is_rotation(tol):
         raise ValueError("Rotation matrix is not valid.")
     sop = SymmOp.from_rotation_and_translation(matrix,
                                                [0., 0., 0.])
     return self.transform(sop)
Exemplo n.º 6
0
    def test_structure_transform(self):
        # Test trivial case
        trivial = self.fit_r4.structure_transform(self.structure,
                                                  self.structure.copy())
        self.assertArrayAlmostEqual(trivial, self.fit_r4)

        # Test simple rotation
        rot_symm_op = SymmOp.from_axis_angle_and_translation([1, 1, 1], 55.5)
        rot_struct = self.structure.copy()
        rot_struct.apply_operation(rot_symm_op)
        rot_tensor = self.fit_r4.rotate(rot_symm_op.rotation_matrix)
        trans_tensor = self.fit_r4.structure_transform(self.structure, rot_struct)
        self.assertArrayAlmostEqual(rot_tensor, trans_tensor)

        # Test supercell
        bigcell = self.structure.copy()
        bigcell.make_supercell([2, 2, 3])
        trans_tensor = self.fit_r4.structure_transform(self.structure, bigcell)
        self.assertArrayAlmostEqual(self.fit_r4, trans_tensor)

        # Test rotated primitive to conventional for fcc structure
        sn = self.get_structure("Sn")
        sn_prim = SpacegroupAnalyzer(sn).get_primitive_standard_structure()
        sn_prim.apply_operation(rot_symm_op)
        rotated = self.fit_r4.rotate(rot_symm_op.rotation_matrix)
        transformed = self.fit_r4.structure_transform(sn, sn_prim)
        self.assertArrayAlmostEqual(rotated, transformed)
Exemplo n.º 7
0
    def test_fit(self):
        """
        Take two known matched structures
            1) Ensure match
            2) Ensure match after translation and rotations
            3) Ensure no-match after large site translation
            4) Ensure match after site shuffling
            """
        sm = StructureMatcher()

        self.assertTrue(sm.fit(self.struct_list[0], self.struct_list[1]))

        # Test rotational/translational invariance
        op = SymmOp.from_axis_angle_and_translation([0, 0, 1], 30, False,
                                                    np.array([0.4, 0.7, 0.9]))
        self.struct_list[1].apply_operation(op)
        self.assertTrue(sm.fit(self.struct_list[0], self.struct_list[1]))

        #Test failure under large atomic translation
        self.struct_list[1].translate_sites([0], [.4, .4, .2],
                                            frac_coords=True)
        self.assertFalse(sm.fit(self.struct_list[0], self.struct_list[1]))

        self.struct_list[1].translate_sites([0], [-.4, -.4, -.2],
                                            frac_coords=True)
        # random.shuffle(editor._sites)
        self.assertTrue(sm.fit(self.struct_list[0], self.struct_list[1]))
        #Test FrameworkComporator
        sm2 = StructureMatcher(comparator=FrameworkComparator())
        lfp = read_structure(os.path.join(test_dir, "LiFePO4.cif"))
        nfp = read_structure(os.path.join(test_dir, "NaFePO4.cif"))
        self.assertTrue(sm2.fit(lfp, nfp))
        self.assertFalse(sm.fit(lfp, nfp))

        #Test anonymous fit.
        self.assertEqual(sm.fit_anonymous(lfp, nfp),
                         {Composition("Li"): Composition("Na")})
        self.assertAlmostEqual(sm.get_minimax_rms_anonymous(lfp, nfp)[0],
                               0.096084154118549828)

        #Test partial occupancies.
        s1 = Structure([[3, 0, 0], [0, 3, 0], [0, 0, 3]],
                       [{"Fe": 0.5}, {"Fe": 0.5}, {"Fe": 0.5}, {"Fe": 0.5}],
                       [[0, 0, 0], [0.25, 0.25, 0.25],
                        [0.5, 0.5, 0.5], [0.75, 0.75, 0.75]])
        s2 = Structure([[3, 0, 0], [0, 3, 0], [0, 0, 3]],
                       [{"Fe": 0.25}, {"Fe": 0.5}, {"Fe": 0.5}, {"Fe": 0.75}],
                       [[0, 0, 0], [0.25, 0.25, 0.25],
                        [0.5, 0.5, 0.5], [0.75, 0.75, 0.75]])
        self.assertFalse(sm.fit(s1, s2))
        self.assertFalse(sm.fit(s2, s1))
        s2 = Structure([[3, 0, 0], [0, 3, 0], [0, 0, 3]],
                       [{"Fe": 0.25}, {"Fe": 0.25}, {"Fe": 0.25},
                        {"Fe": 0.25}],
                       [[0, 0, 0], [0.25, 0.25, 0.25],
                        [0.5, 0.5, 0.5], [0.75, 0.75, 0.75]])
        self.assertEqual(sm.fit_anonymous(s1, s2),
                         {Composition("Fe0.5"): Composition("Fe0.25")})

        self.assertAlmostEqual(sm.get_minimax_rms_anonymous(s1, s2)[0], 0)
Exemplo n.º 8
0
    def test_find_all_mappings(self):
        m = np.array([[0.1, 0.2, 0.3], [-0.1, 0.2, 0.7], [0.6, 0.9, 0.2]])
        latt = Lattice(m)

        op = SymmOp.from_origin_axis_angle([0, 0, 0], [2, -1, 3], 40)
        rot = op.rotation_matrix
        scale = np.array([[0, 2, 0], [1, 1, 0], [0,0,1]])

        latt2 = Lattice(np.dot(rot, np.dot(scale, m).T).T)

        for (aligned_out, rot_out, scale_out) in latt.find_all_mappings(latt2):
            self.assertArrayAlmostEqual(np.inner(latt2.matrix, rot_out),
                                        aligned_out.matrix, 5)
            self.assertArrayAlmostEqual(np.dot(scale_out, latt.matrix),
                                        aligned_out.matrix)
            self.assertArrayAlmostEqual(aligned_out.lengths_and_angles, latt2.lengths_and_angles)
            self.assertFalse(np.allclose(aligned_out.lengths_and_angles,
                                         latt.lengths_and_angles))

        latt = Lattice.orthorhombic(9, 9, 5)
        self.assertEqual(len(list(latt.find_all_mappings(latt))), 16)

        #catch the singular matrix error
        latt = Lattice.from_lengths_and_angles([1,1,1], [10,10,10])
        for l, _, _ in latt.find_all_mappings(latt, ltol=0.05, atol=11):
            self.assertTrue(isinstance(l, Lattice))
Exemplo n.º 9
0
def parse_symmetry_operations(symmops_str_list):
    """
    Help method to parse the symmetry operations.

    Args:
        symmops_str_list:
            List of symmops strings of the form
            ['x, y, z', '-x, -y, z', '-y+1/2, x+1/2, z+1/2', ...]

    Returns:
        List of SymmOps
    """
    ops = []
    for op_str in symmops_str_list:
        rot_matrix = np.zeros((3, 3))
        trans = np.zeros(3)
        toks = op_str.strip().split(",")
        for i, tok in enumerate(toks):
            for m in re.finditer("([\+\-]*)\s*([x-z\d]+)/*(\d*)", tok):
                factor = -1 if m.group(1) == "-" else 1
                if m.group(2) in ("x", "y", "z"):
                    j = ord(m.group(2)) - 120
                    rot_matrix[i, j] = factor
                else:
                    num = float(m.group(2))
                    if m.group(3) != "":
                        num /= float(m.group(3))
                    trans[i] = factor * num
        op = SymmOp.from_rotation_and_translation(rot_matrix, trans)
        ops.append(op)
    return ops
Exemplo n.º 10
0
    def test_init(self):
        fitter = StructureFitter(self.b, self.a)
        self.assertTrue(fitter.mapping_op != None, "No fit found!")

        #Now to try with rotated structure
        op = SymmOp.from_axis_angle_and_translation([0, 0, 1], 30, False, np.array([0, 0, 1]))
        editor = StructureEditor(self.a)
        editor.apply_operation(op)
        fitter = StructureFitter(self.b, editor.modified_structure)

        self.assertTrue(fitter.mapping_op != None, "No fit found!")

        #test with a supercell
        mod = SupercellMaker(self.a, scaling_matrix=[[2, 0, 0], [0, 1, 0], [0, 0, 1]])
        a_super = mod.modified_structure
        fitter = StructureFitter(self.b, a_super)
        self.assertTrue(fitter.mapping_op != None, "No fit found!")

        # Test with a structure with a translated point

        editor = StructureEditor(self.a)
        site = self.a[0]
        editor.delete_site(0)
        trans = np.random.randint(0, 1000, 3)
        editor.insert_site(0, site.species_and_occu, site.frac_coords + trans, False, False)
        fitter = StructureFitter(self.b, editor.modified_structure)
        self.assertTrue(fitter.mapping_op != None, "No fit found for translation {}!".format(trans))

        parser = CifParser(os.path.join(test_dir, "FePO4a.cif"))
        a = parser.get_structures()[0]
        parser = CifParser(os.path.join(test_dir, "FePO4b.cif"))
        b = parser.get_structures()[0]
        fitter = StructureFitter(b, a)
        self.assertTrue(fitter.mapping_op != None, "No fit found!")
Exemplo n.º 11
0
 def test_apply_operation(self):
     op = SymmOp.from_axis_angle_and_translation([0, 0, 1], 90)
     self.structure.apply_operation(op)
     self.assertArrayAlmostEqual(
         self.structure.lattice.matrix,
         [[0.000000, 3.840198, 0.000000],
          [-3.325710, 1.920099, 0.000000],
          [2.217138, -0.000000, 3.135509]], 5)
Exemplo n.º 12
0
    def test_fit(self):
        """
        Take two known matched structures
            1) Ensure match
            2) Ensure match after translation and rotations
            3) Ensure no-match after large site translation
            4) Ensure match after site shuffling
            """
        sm = StructureMatcher()

        self.assertTrue(sm.fit(self.struct_list[0], self.struct_list[1]))

        # Test rotational/translational invariance
        op = SymmOp.from_axis_angle_and_translation([0, 0, 1], 30, False,
                                                    np.array([0.4, 0.7, 0.9]))
        self.struct_list[1].apply_operation(op)
        self.assertTrue(sm.fit(self.struct_list[0], self.struct_list[1]))

        #Test failure under large atomic translation
        self.struct_list[1].translate_sites([0], [.4, .4, .2],
                                            frac_coords=True)
        self.assertFalse(sm.fit(self.struct_list[0], self.struct_list[1]))

        self.struct_list[1].translate_sites([0], [-.4, -.4, -.2],
                                            frac_coords=True)
        # random.shuffle(editor._sites)
        self.assertTrue(sm.fit(self.struct_list[0], self.struct_list[1]))
        #Test FrameworkComporator
        sm2 = StructureMatcher(comparator=FrameworkComparator())
        lfp = self.get_structure("LiFePO4")
        nfp = self.get_structure("NaFePO4")
        self.assertTrue(sm2.fit(lfp, nfp))
        self.assertFalse(sm.fit(lfp, nfp))

        #Test anonymous fit.
        self.assertEqual(sm.fit_anonymous(lfp, nfp), True)
        self.assertAlmostEqual(sm.get_rms_anonymous(lfp, nfp)[0],
                               0.060895871160262717)

        #Test partial occupancies.
        s1 = Structure(Lattice.cubic(3),
                       [{"Fe": 0.5}, {"Fe": 0.5}, {"Fe": 0.5}, {"Fe": 0.5}],
                       [[0, 0, 0], [0.25, 0.25, 0.25],
                        [0.5, 0.5, 0.5], [0.75, 0.75, 0.75]])
        s2 = Structure(Lattice.cubic(3),
                       [{"Fe": 0.25}, {"Fe": 0.5}, {"Fe": 0.5}, {"Fe": 0.75}],
                       [[0, 0, 0], [0.25, 0.25, 0.25],
                        [0.5, 0.5, 0.5], [0.75, 0.75, 0.75]])
        self.assertFalse(sm.fit(s1, s2))
        self.assertFalse(sm.fit(s2, s1))
        s2 = Structure(Lattice.cubic(3),
                       [{"Mn": 0.5}, {"Mn": 0.5}, {"Mn": 0.5},
                        {"Mn": 0.5}],
                       [[0, 0, 0], [0.25, 0.25, 0.25],
                        [0.5, 0.5, 0.5], [0.75, 0.75, 0.75]])
        self.assertEqual(sm.fit_anonymous(s1, s2), True)

        self.assertAlmostEqual(sm.get_rms_anonymous(s1, s2)[0], 0)
Exemplo n.º 13
0
 def test_reflection(self):
     normal = np.random.rand(3)
     origin = np.random.rand(3)
     refl = SymmOp.reflection(normal, origin)
     point = np.random.rand(3)
     newcoord = refl.operate(point)
     # Distance to the plane should be negatives of each other.
     self.assertAlmostEqual(np.dot(newcoord - origin, normal),
                            -np.dot(point - origin, normal))
Exemplo n.º 14
0
    def __init__(self, axis, angle, angle_in_radians=False):
        """

        """
        self._axis = axis
        self._angle = angle
        self._angle_in_radians = angle_in_radians
        self._symmop = SymmOp.from_axis_angle_and_translation(
            self._axis, self._angle, self._angle_in_radians)
Exemplo n.º 15
0
 def _check_R2_axes_asym(self):
     """
     Test for 2-fold rotation along the principal axes. Used to handle
     asymetric top molecules.
     """
     for v in self.principal_axes:
         op = SymmOp.from_axis_angle_and_translation(v, 180)
         if self.is_valid_op(op):
             self.symmops.append(op)
             self.rot_sym.append((v, 2))
Exemplo n.º 16
0
    def test_find_mapping(self):
        m = np.array([[0.1, 0.2, 0.3], [-0.1, 0.2, 0.7], [0.6, 0.9, 0.2]])
        latt = Lattice(m)

        op = SymmOp.from_origin_axis_angle([0, 0, 0], [2, 3, 3], 35)
        rot = op.rotation_matrix
        scale = np.array([[1, 1, 0], [0, 1, 0], [0, 0, 1]])

        latt2 = Lattice(np.dot(rot, np.dot(scale, m).T).T)
        (aligned_out, rot_out, scale_out) = latt2.find_mapping(latt)
        self.assertAlmostEqual(abs(np.linalg.det(rot)), 1)

        rotated = SymmOp.from_rotation_and_translation(rot_out).operate_multi(latt.matrix)

        self.assertArrayAlmostEqual(rotated, aligned_out.matrix)
        self.assertArrayAlmostEqual(np.dot(scale_out, latt2.matrix), aligned_out.matrix)
        self.assertArrayAlmostEqual(aligned_out.lengths_and_angles, latt.lengths_and_angles)
        self.assertFalse(np.allclose(aligned_out.lengths_and_angles,
                                     latt2.lengths_and_angles))
Exemplo n.º 17
0
    def test_list_based_functions(self):
        # zeroed
        tc = TensorCollection([1e-4*Tensor(np.eye(3))]*4)
        for t in tc.zeroed():
            self.assertArrayEqual(t, np.zeros((3, 3)))
        for t in tc.zeroed(1e-5):
            self.assertArrayEqual(t, 1e-4*np.eye(3))
        self.list_based_function_check("zeroed", tc)
        self.list_based_function_check("zeroed", tc, tol=1e-5)

        # transform
        symm_op = SymmOp.from_axis_angle_and_translation([0, 0, 1], 30,
                                                         False, [0, 0, 1])
        self.list_based_function_check("transform", self.seq_tc, symm_op=symm_op)

        # symmetrized
        self.list_based_function_check("symmetrized", self.seq_tc)

        # rotation
        a = 3.14 * 42.5 / 180
        rotation = SquareTensor([[math.cos(a), 0, math.sin(a)], [0, 1, 0],
                                 [-math.sin(a), 0, math.cos(a)]])
        self.list_based_function_check("rotate", self.diff_rank, matrix=rotation)

        # is_symmetric
        self.assertFalse(self.seq_tc.is_symmetric())
        self.assertTrue(self.diff_rank.is_symmetric())

        # fit_to_structure
        self.list_based_function_check("fit_to_structure", self.diff_rank, self.struct)
        self.list_based_function_check("fit_to_structure", self.seq_tc, self.struct)

        # fit_to_structure
        self.list_based_function_check("fit_to_structure", self.diff_rank, self.struct)
        self.list_based_function_check("fit_to_structure", self.seq_tc, self.struct)

        # voigt
        self.list_based_function_check("voigt", self.diff_rank)

        # is_voigt_symmetric
        self.assertTrue(self.diff_rank.is_voigt_symmetric())
        self.assertFalse(self.seq_tc.is_voigt_symmetric())

        # Convert to ieee
        for entry in self.ieee_data[:2]:
            xtal = entry['xtal']
            tc = TensorCollection([entry['original_tensor']]*3)
            struct = entry['structure']
            self.list_based_function_check("convert_to_ieee", tc, struct)

        # from_voigt
        tc_input = [t for t in np.random.random((3, 6, 6))]
        tc = TensorCollection.from_voigt(tc_input)
        for t_input, t in zip(tc_input, tc):
            self.assertArrayAlmostEqual(Tensor.from_voigt(t_input), t)
Exemplo n.º 18
0
    def fit_with_mapper(self, mapper):
        coords = [[0.000000, 0.000000, 0.000000],
                  [0.000000, 0.000000, 1.089000],
                  [1.026719, 0.000000, -0.363000],
                  [-0.513360, -0.889165, -0.363000],
                  [-0.513360, 0.889165, -0.363000]]
        mol1 = Molecule(["C", "H", "H", "H", "H"], coords)
        op = SymmOp.from_origin_axis_angle([0, 0, 0], [0.1, 0.2, 0.3], 60)
        rotcoords = [op.operate(c) for c in coords]
        mol2 = Molecule(["C", "H", "H", "H", "H"], rotcoords)
        mm = MoleculeMatcher(mapper=mapper)
        self.assertTrue(mm.fit(mol1, mol2))

        mol1 = Molecule.from_file(os.path.join(test_dir, "benzene1.xyz"))
        mol2 = Molecule.from_file(os.path.join(test_dir, "benzene2.xyz"))
        self.assertTrue(mm.fit(mol1, mol2))

        mol1 = Molecule.from_file(os.path.join(test_dir, "benzene1.xyz"))
        mol2 = Molecule.from_file(os.path.join(test_dir, "t2.xyz"))
        self.assertFalse(mm.fit(mol1, mol2))

        mol1 = Molecule.from_file(os.path.join(test_dir, "c1.xyz"))
        mol2 = Molecule.from_file(os.path.join(test_dir, "c2.xyz"))
        self.assertTrue(mm.fit(mol1, mol2))

        mol1 = Molecule.from_file(os.path.join(test_dir, "t3.xyz"))
        mol2 = Molecule.from_file(os.path.join(test_dir, "t4.xyz"))
        self.assertTrue(mm.fit(mol1, mol2))

        mol1 = Molecule.from_file(os.path.join(test_dir, "j1.xyz"))
        mol2 = Molecule.from_file(os.path.join(test_dir, "j2.xyz"))
        self.assertTrue(mm.fit(mol1, mol2))

        mol1 = Molecule.from_file(os.path.join(test_dir, "ethene1.xyz"))
        mol2 = Molecule.from_file(os.path.join(test_dir, "ethene2.xyz"))
        self.assertTrue(mm.fit(mol1, mol2))

        mol1 = Molecule.from_file(os.path.join(test_dir, "toluene1.xyz"))
        mol2 = Molecule.from_file(os.path.join(test_dir, "toluene2.xyz"))
        self.assertTrue(mm.fit(mol1, mol2))

        mol1 = Molecule.from_file(os.path.join(test_dir, "cyclohexane1.xyz"))
        mol2 = Molecule.from_file(os.path.join(test_dir, "cyclohexane2.xyz"))
        self.assertTrue(mm.fit(mol1, mol2))

        mol1 = Molecule.from_file(os.path.join(test_dir, "oxygen1.xyz"))
        mol2 = Molecule.from_file(os.path.join(test_dir, "oxygen2.xyz"))
        self.assertTrue(mm.fit(mol1, mol2))

        mm = MoleculeMatcher(tolerance=0.001, mapper=mapper)
        mol1 = Molecule.from_file(os.path.join(test_dir, "t3.xyz"))
        mol2 = Molecule.from_file(os.path.join(test_dir, "t4.xyz"))
        self.assertFalse(mm.fit(mol1, mol2))
Exemplo n.º 19
0
    def __init__(self, int_symbol):
        """
        Initializes a Point Group from its international symbol.

        Args:
            int_symbol (str): International or Hermann-Mauguin Symbol.
        """
        self.symbol = int_symbol
        self.generators = [GENERATOR_MATRICES[c]
                           for c in POINT_GROUP_ENC[int_symbol]]
        self._symmetry_ops = set([SymmOp.from_rotation_and_translation(m)
                                  for m in self._generate_full_symmetry_ops()])
        self.order = len(self._symmetry_ops)
Exemplo n.º 20
0
    def __init__(self, int_symbol):
        """
        Initializes a Point Group from its international symbol.

        Args:
            int_symbol (str): International or Hermann-Mauguin Symbol.
        """
        self.symbol = int_symbol
        self.generators = [get_symm_data("generator_matrices")[c]
                           for c in get_symm_data("point_group_encoding")[int_symbol]]
        self._symmetry_ops = set([SymmOp.from_rotation_and_translation(m)
                                  for m in self._generate_full_symmetry_ops()])
        self.order = len(self._symmetry_ops)
Exemplo n.º 21
0
    def test_find_mapping(self):
        m = np.array([[0.1, 0.2, 0.3], [-0.1, 0.2, 0.7], [0.6, 0.9, 0.2]])
        latt = Lattice(m)

        op = SymmOp.from_origin_axis_angle([0, 0, 0], [2, 3, 3], 35)
        rot = op.rotation_matrix
        scale = np.array([[1, 1, 0], [0, 1, 0], [0, 0, 1]])

        latt2 = Lattice(np.dot(rot, np.dot(scale, m).T).T)
        (latt, rot, scale2) = latt2.find_mapping(latt)
        self.assertAlmostEqual(abs(np.linalg.det(rot)), 1)
        self.assertTrue(np.allclose(scale2, scale) or
                        np.allclose(scale2, -scale))
Exemplo n.º 22
0
 def get_symmetry_operations(self, cartesian=False):
     """
     Return symmetry operations as a list of SymmOp objects.
     By default returns fractional coord symmops.
     But cartesian can be returned too.
     """
     (rotation, translation) = self.get_symmetry()
     symmops = []
     for rot, trans in zip(rotation, translation):
         if cartesian:
             rot = np.dot(self._structure.lattice.md2c, np.dot(rot, self._structure.lattice.mc2d))
             trans = np.dot(self._structure.lattice.md2c, trans)
         symmops.append(SymmOp.from_rotation_matrix_and_translation_vector(rot, trans))
     return symmops
Exemplo n.º 23
0
    def rotate(self, matrix, tol=1e-3):
        """
        Applies a rotation directly, and tests input matrix to ensure a valid
        rotation.

        Args:
            matrix (3x3 array-like): rotation matrix to be applied to tensor
            tol (float): tolerance for testing rotation matrix validity
        """
        matrix = SquareTensor(matrix)
        if not matrix.is_rotation(tol):
            raise ValueError("Rotation matrix is not valid.")
        sop = SymmOp.from_rotation_and_translation(matrix, [0.0, 0.0, 0.0])
        return self.transform(sop)
Exemplo n.º 24
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)

        self.assertRaises(ValueError, self.op.as_xyz_string)
Exemplo n.º 25
0
    def _find_spherical_axes(self):
        """
        Looks for R5, R4, R3 and R2 axes in speherical top molecules.  Point
        group T molecules have only one unique 3-fold and one unique 2-fold
        axis. O molecules have one unique 4, 3 and 2-fold axes. I molecules
        have a unique 5-fold axis.
        """
        rot_present = defaultdict(bool)
        origin_site, dist_el_sites = cluster_sites(self.centered_mol, self.tol)
        test_set = min(dist_el_sites.values(), key=lambda s: len(s))
        coords = [s.coords for s in test_set]
        for c1, c2, c3 in itertools.combinations(coords, 3):
            for cc1, cc2 in itertools.combinations([c1, c2, c3], 2):
                if not rot_present[2]:
                    test_axis = cc1 + cc2
                    if np.linalg.norm(test_axis) > self.tol:
                        op = SymmOp.from_axis_angle_and_translation(test_axis,
                                                                    180)
                        rot_present[2] = self.is_valid_op(op)
                        if rot_present[2]:
                            self.symmops.append(op)
                            self.rot_sym.append((test_axis, 2))

            test_axis = np.cross(c2 - c1, c3 - c1)
            if np.linalg.norm(test_axis) > self.tol:
                for r in (3, 4, 5):
                    if not rot_present[r]:
                        op = SymmOp.from_axis_angle_and_translation(
                            test_axis, 360 / r)
                        rot_present[r] = self.is_valid_op(op)
                        if rot_present[r]:
                            self.symmops.append(op)
                            self.rot_sym.append((test_axis, r))
                            break
            if rot_present[2] and rot_present[3] and (
                        rot_present[4] or rot_present[5]):
                break
Exemplo n.º 26
0
def get_rot(slab):
    """
    Gets the transformation to rotate the z axis into the miller index
    """
    new_z = get_mi_vec(slab)
    a, b, c = slab.lattice.matrix
    new_x = a / np.linalg.norm(a)
    new_y = np.cross(new_z, new_x)
    x, y, z = np.eye(3)
    rot_matrix = np.array([np.dot(*el) for el in
                           itertools.product([x, y, z],
                                             [new_x, new_y, new_z])]).reshape(3, 3)
    rot_matrix = np.transpose(rot_matrix)
    sop = SymmOp.from_rotation_and_translation(rot_matrix)
    return sop
Exemplo n.º 27
0
 def _check_perpendicular_r2_axis(self, axis):
     """
     Checks for R2 axes perpendicular to unique axis.  For handling
     symmetric top molecules.
     """
     min_set = self._get_smallest_set_not_on_axis(axis)
     for s1, s2 in itertools.combinations(min_set, 2):
         test_axis = np.cross(s1.coords - s2.coords, axis)
         if np.linalg.norm(test_axis) > self.tol:
             op = SymmOp.from_axis_angle_and_translation(test_axis, 180)
             r2present = self.is_valid_op(op)
             if r2present:
                 self.symmops.append(op)
                 self.rot_sym.append((test_axis, 2))
                 return True
Exemplo n.º 28
0
 def _proc_cyclic(self):
     """
     Handles cyclic group molecules.
     """
     main_axis, rot = max(self.rot_sym, key=lambda v: v[1])
     self.sch_symbol = "C{}".format(rot)
     mirror_type = self._find_mirror(main_axis)
     if mirror_type == "h":
         self.sch_symbol += "h"
     elif mirror_type == "v":
         self.sch_symbol += "v"
     elif mirror_type == "":
         if self.is_valid_op(SymmOp.rotoreflection(main_axis,
                                                   angle=180 / rot)):
             self.sch_symbol = "S{}".format(2 * rot)
Exemplo n.º 29
0
 def __init__(self, axis, angle, angle_in_radians=False):
     """
     Args:
         axis:
             Axis of rotation, e.g., [1, 0, 0]
         angle:
             Angle to rotate
         angle_in_radians:
             Set to True if angle is supplied in radians. Else degrees are
             assumed.
     """
     self._axis = axis
     self._angle = angle
     self._angle_in_radians = angle_in_radians
     self._symmop = SymmOp.from_axis_angle_and_translation(self._axis, self._angle, self._angle_in_radians)
Exemplo n.º 30
0
    def _align_monomer(self, monomer, mon_vector, move_direction):
        """
        rotate the monomer so that it is aligned along the move direction

        Args:
            monomer (Molecule)
            mon_vector (numpy.array): molecule vector that starts from the
                start atom index to the end atom index
            move_direction (numpy.array): the direction of the polymer chain
                extension
        """
        axis = np.cross(mon_vector, move_direction)
        origin = monomer[self.start].coords
        angle = get_angle(mon_vector, move_direction)
        op = SymmOp.from_origin_axis_angle(origin, axis, angle)
        monomer.apply_operation(op)
Exemplo n.º 31
0
 def get_point_group_operations(self, cartesian=False):
     """
     Return symmetry operations as a list of SymmOp objects.
     By default returns fractional coord symmops.
     But cartesian can be returned too.
     """
     (rotation, translation) = self._get_symmetry()
     symmops = []
     mat = self._structure.lattice.matrix.T
     invmat = np.linalg.inv(mat)
     for rot, trans in zip(rotation, translation):
         if cartesian:
             rot = np.dot(mat, np.dot(rot, invmat))
         op = SymmOp.from_rotation_and_translation(rot, np.array([0, 0, 0]))
         symmops.append(op)
     return symmops
Exemplo n.º 32
0
 def __init__(self, axis, angle, angle_in_radians=False):
     """
     Args:
         axis:
             Axis of rotation, e.g., [1, 0, 0]
         angle:
             Angle to rotate
         angle_in_radians:
             Set to True if angle is supplied in radians. Else degrees are
             assumed.
     """
     self._axis = axis
     self._angle = angle
     self._angle_in_radians = angle_in_radians
     self._symmop = SymmOp.from_axis_angle_and_translation(
         self._axis, self._angle, self._angle_in_radians)
Exemplo n.º 33
0
def get_rot(slab):
    """
    Gets the transformation to rotate the z axis into the miller index
    """
    new_z = get_mi_vec(slab)
    a, b, c = slab.lattice.matrix
    new_x = a / np.linalg.norm(a)
    new_y = np.cross(new_z, new_x)
    x, y, z = np.eye(3)
    rot_matrix = np.array([
        np.dot(*el)
        for el in itertools.product([x, y, z], [new_x, new_y, new_z])
    ]).reshape(3, 3)
    rot_matrix = np.transpose(rot_matrix)
    sop = SymmOp.from_rotation_and_translation(rot_matrix)
    return sop
Exemplo n.º 34
0
    def _align_monomer(self, monomer, mon_vector, move_direction):
        """
        rotate the monomer so that it is aligned along the move direction

        Args:
            monomer (Molecule)
            mon_vector (numpy.array): molecule vector that starts from the
                start atom index to the end atom index
            move_direction (numpy.array): the direction of the polymer chain
                extension
        """
        axis = np.cross(mon_vector, move_direction)
        origin = monomer[self.start].coords
        angle = get_angle(mon_vector, move_direction)
        op = SymmOp.from_origin_axis_angle(origin, axis, angle)
        monomer.apply_operation(op)
Exemplo n.º 35
0
    def __init__(self, int_symbol):
        """
        Initializes a Point Group from its international symbol.

        Args:
            int_symbol (str): International or Hermann-Mauguin Symbol.
        """
        self.symbol = int_symbol
        self.generators = [
            GENERATOR_MATRICES[c] for c in POINT_GROUP_ENC[int_symbol]
        ]
        self.symmetry_ops = [
            SymmOp.from_rotation_and_translation(m)
            for m in self._generate_full_symmetry_ops()
        ]
        self.order = len(self.symmetry_ops)
Exemplo n.º 36
0
    def test_rotated_molecule(self):

        coords = [[0.000000, 0.000000, 0.000000],
                  [0.000000, 0.000000, 1.089000],
                  [1.026719, 0.000000, -0.363000],
                  [-0.513360, -0.889165, -0.363000],
                  [-0.513360, 0.889165, -0.363000]]

        op = SymmOp.from_origin_axis_angle([0, 0, 0], [0.1, 0.2, 0.3], 60)
        rotcoords = [op.operate(c) for c in coords]

        mol1 = Molecule(["C", "H", "H", "H", "H"], coords)
        mol2 = Molecule(["C", "H", "H", "H", "H"], rotcoords)

        mm = GeneticOrderMatcher(mol1, threshold=0.3)
        _, rmsd = mm.fit(mol2)[0]
        self.assertAlmostEqual(rmsd, 0., places=6)
Exemplo n.º 37
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()
Exemplo n.º 38
0
    def test_transform(self):
        # Rank 3
        tensor = TensorBase(np.arange(0, 27).reshape(3, 3, 3))
        symm_op = SymmOp.from_axis_angle_and_translation([0, 0, 1], 30,
                                                         False, [0, 0, 1])
        new_tensor = tensor.transform(symm_op)

        self.assertArrayAlmostEqual(new_tensor,
                                    [[[-0.871, -2.884, -1.928],
                                      [-2.152, -6.665, -4.196],
                                      [-1.026, -2.830, -1.572]],
                                     [[0.044, 1.531, 1.804],
                                      [4.263, 21.008, 17.928],
                                      [5.170, 23.026, 18.722]],
                                     [[1.679, 7.268, 5.821],
                                      [9.268, 38.321, 29.919],
                                      [8.285, 33.651, 26.000]]], 3)
Exemplo n.º 39
0
    def __init__(self, int_symbol):
        """
        Initializes a Point Group from its international symbol.

        Args:
            int_symbol (str): International or Hermann-Mauguin Symbol.
        """
        self.symbol = int_symbol
        self.generators = [
            _get_symm_data("generator_matrices")[c]
            for c in _get_symm_data("point_group_encoding")[int_symbol]
        ]
        self._symmetry_ops = {
            SymmOp.from_rotation_and_translation(m)
            for m in self._generate_full_symmetry_ops()
        }
        self.order = len(self._symmetry_ops)
Exemplo n.º 40
0
    def get_op(self, angle="random"):
        """
        Generate a SymmOp object consistent with the orientation's
        constraints. Allows for specification of an angle (possibly random) to
        rotate about the constraint axis.

        Args:
            angle: an angle to rotate about the constraint axis. If "random",
                chooses a random rotation angle. If self.degrees==2, chooses a
                random 3d rotation matrix to multiply by. If the original matrix
                is wanted, set angle=0, or call self.matrix

        Returns:
            pymatgen.core.structure. SymmOp object
        """
        #If "random", rotates by a random amount
        m = self.get_matrix(angle=angle)
        return SymmOp.from_rotation_and_translation(m,[0,0,0])
Exemplo n.º 41
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')
Exemplo n.º 42
0
 def _check_rot_sym(self, axis):
     """
     Determines the rotational symmetry about supplied axis.  Used only for
     symmetric top molecules which has possible rotational symmetry
     operations > 2.
     """
     min_set = self._get_smallest_set_not_on_axis(axis)
     max_sym = len(min_set)
     for i in range(max_sym, 0, -1):
         if max_sym % i != 0:
             continue
         op = SymmOp.from_axis_angle_and_translation(axis, 360 / i)
         rotvalid = self.is_valid_op(op)
         if rotvalid:
             self.symmops.append(op)
             self.rot_sym.append((axis, i))
             return i
     return 1
Exemplo n.º 43
0
def get_wyckoff_symmetry(sg):
    '''
    Returns a list of Wyckoff position site symmetry for a given space group.
    1st index: index of WP in sg (0 is the WP with largest multiplicity)
    2nd index: a point within the WP
    3rd index: a site symmetry SymmOp of the point
    '''
    symmetry_strings = eval(wyckoff_symmetry_df["0"][sg])
    symmetry = []
    #Loop over Wyckoff positions
    for x in symmetry_strings:
        symmetry.append([])
        #Loop over points in WP
        for y in x:
            symmetry[-1].append([])
            #Loop over
            for z in y:
                symmetry[-1][-1].append(SymmOp.from_xyz_string(z))
    return symmetry
Exemplo n.º 44
0
def project_point(point, op, lattice=Euclidean_lattice, PBC=[1,1,1]):
    """
    Given a 3-vector and a Wyckoff position operator, returns the projection of that
    point onto the axis, plane, or point.

    Args:
        point: a 3-vector (numeric list, tuple, or array)
        op: a SymmOp object representing a symmetry element within a symmetry group
        lattice: 3x3 matrix describing the unit cell vectors
        PBC: A periodic boundary condition list, where 1 means periodic, 0 means not periodic.
            Ex: [1,1,1] -> full 3d periodicity, [0,0,1] -> periodicity along the z axis

    Returns:
        a transformed 3-vector (numpy array)
    """
    if PBC == [0,0,0]:
        #Temporarily move the point in the opposite direction of the translation
        translation = op.translation_vector
        point -= translation
        new_vector = np.array([0.0,0.0,0.0])
        #Loop over basis vectors of the symmetry element
        for basis_vector in np.transpose(op.rotation_matrix):
            b = np.linalg.norm(basis_vector)
            if not np.isclose(b, 0):
                new_vector += basis_vector*(np.dot(point, basis_vector)/(b**2))
        new_vector += translation
        return new_vector
    else:
        #With PBC, the point could be projected onto multiple places on the symmetry element
        point = filtered_coords(point)
        #Generate translation vectors for the equivalent symmetry elements
        m = create_matrix(PBC=PBC)
        #Create new symmetry elements for each of the PBC vectors
        new_vectors = []
        distances = []
        for v in m:
            #Get the direct projection onto each of the new symmetry elements
            new_op = SymmOp.from_rotation_and_translation(op.rotation_matrix, op.translation_vector + v)
            new_vector = project_point(point, new_op, lattice=lattice, PBC=[0,0,0])
            new_vectors.append(new_vector)
            distances.append(distance(new_vector - point, lattice=lattice, PBC=[0,0,0]))
        i = np.argmin(distances)
        return filtered_coords(new_vectors[i], PBC=PBC)
Exemplo n.º 45
0
def get_shared_symmetry_operations(struc, pointops, tol=0.1):
    """
        Get all the point group operations shared by a pair of atomic sites
        in the form [[point operations of site index 1],[],...,[]]

        Args:
            struc: Pymatgen structure
            pointops: list of point group operations from get_site_symmetries method

        Return:
            list of lists of shared point operations for each pair of atomic sites
    """
    numsites = len(struc)
    sharedops = [[0 for x in range(numsites)] for y in range(numsites)]
    for site1 in range(numsites):
        for site2 in range(numsites):
            sharedops[site1][site2] = []
            for op1 in range(len(pointops[site1])):
                for op2 in range(len(pointops[site2])):
                    if np.allclose(
                            pointops[site1][op1].rotation_matrix,
                            pointops[site2][op2].rotation_matrix,
                    ):
                        sharedops[site1][site2].append(pointops[site1][op1])

    for site1 in range(len(sharedops)):
        for site2 in range(len(sharedops[site1])):
            uniqueops = []
            for ops in range(len(sharedops[site1][site2])):
                op = SymmOp.from_rotation_and_translation(
                    rotation_matrix=sharedops[site1][site2]
                    [ops].rotation_matrix,
                    translation_vec=(0, 0, 0),
                    tol=tol,
                )
                if op in uniqueops:
                    continue
                else:
                    uniqueops.append(op)
            sharedops[site1][site2] = uniqueops

    return sharedops
Exemplo n.º 46
0
    def get_symmetry_operations(self, cartesian=False):
        """
        Return symmetry operations as a list of SymmOp objects.
        By default returns fractional coord symmops.
        But cartesian can be returned too.

        Returns:
            ([SymmOp]): List of symmetry operations.
        """
        rotation, translation = self._get_symmetry()
        symmops = []
        mat = self._structure.lattice.matrix.T
        invmat = np.linalg.inv(mat)
        for rot, trans in zip(rotation, translation):
            if cartesian:
                rot = np.dot(mat, np.dot(rot, invmat))
                trans = np.dot(trans, self._structure.lattice.matrix)
            op = SymmOp.from_rotation_and_translation(rot, trans)
            symmops.append(op)
        return symmops
Exemplo n.º 47
0
 def transform_symmop(self, symmop):
     # type: (Union[SymmOp, MagSymmOp]) -> Union[SymmOp, MagSymmOp]
     """
     Takes a symmetry operation and transforms it.
     :param symmop: SymmOp or MagSymmOp
     :return: 
     """
     W = symmop.rotation_matrix
     w = symmop.translation_vector
     Q = np.linalg.inv(self.P)
     W_ = np.matmul(np.matmul(Q, W), self.P)
     I = np.identity(3)
     w_ = np.matmul(Q, (w + np.matmul(W - I, self.p)))
     if isinstance(symmop, MagSymmOp):
         return MagSymmOp.from_rotation_and_translation_and_time_reversal(rotation_matrix=W_,
                                                                          translation_vec=w_,
                                                                          time_reversal=symmop.time_reversal,
                                                                          tol=symmop.tol)
     elif isinstance(symmop, SymmOp):
         return SymmOp.from_rotation_and_translation(rotation_matrix=W_, translation_vec=w_, tol=symmop.tol)
Exemplo n.º 48
0
    def test_inverse(self):
        coord0 = [0.35, 0.1, 0.4]
        coords = np.array([
            [0.350, 0.100, 0.400],
            [0.350, 0.100, 0.000],
            [0.350, 0.100, 0.000],
            [0.350, 0.000, 0.667],
            [0.350, 0.000, 0.250],
            [0.350, 0.350, 0.400],
            [0.350, 0.350, 0.500],
            [0.350, 0.350, 0.000],
            [0.350, 0.350, 0.350],
            [0.100, 0.100, 0.100],
            [0.400, 0.400, 0.400],
            [0.350, 0.000, 0.000],
            [0.000, 0.100, 0.400],
            [0.350, 0.000, 0.400],
        ])
        xyzs = [
            'x,y,z',
            'x,y,0',
            'y,x,0',
            'x,0,2/3',
            '0,x,1/4',
            'x,x,z',
            'x,-x,1/2',
            '2x,x,0',
            '-2x,-0.5x,-x+1/4',
            '-2y,-0.5y,-y+1/4',
            '-2z,-0.5z,-z+1/4',
            '0,0,x',
            '-y/2+1/2,-z,0',
            '-z,-x/2+1/2,0',
        ]

        for i, xyz in enumerate(xyzs):
            op = SymmOp.from_xyz_string(xyz)
            inv_op = get_inverse(op)
            coord1 = op.operate(coord0)
            coord2 = inv_op.operate(coord1)
            self.assertTrue(np.allclose(coord2, coords[i], rtol=1e-2))
Exemplo n.º 49
0
def get_symmops(structure, symprec):
    """
    Helper function to get the symmetry operations of the structure
    in the reciprocal lattice fractional coordinates.

    Args:
            structure (pymatgen.core.structure.Structure)
            symprec (number): symmetry precision for pymatgen SpacegroupAnalyzer
    """

    sga = SpacegroupAnalyzer(structure, symprec * max(structure.lattice.abc))
    symmops = sga.get_symmetry_operations(cartesian=True)
    lattice = structure.lattice.matrix
    invlattice = structure.lattice.inv_matrix
    newops = []
    for op in symmops:
        newrot = np.dot(lattice, op.rotation_matrix)
        newrot = np.dot(newrot, invlattice)
        newtrans = np.dot(op.translation_vector, invlattice)
        newops.append(SymmOp.from_rotation_and_translation(newrot, newtrans))
    return newops
Exemplo n.º 50
0
 def rotate_mols(self):
     """
     rotate the molecules wrt each other using the provided info
     """
     # rotate the molecules around an axis that is
     # perpendicular to the molecular axes
     if self.angle:
         for mol in range(len(self.mols)):
             for ind_key, rot in self.angle[str(mol)].items():
                 perp_vec = np.cross(self.mol_vecs[int(ind_key)],
                                     self.mol_vecs[mol])
                 # if the vectors are parllel,
                 # then perp_vec = (-y, x, 0)
                 if np.abs(np.dot(self.mol_vecs[int(ind_key)],
                                  self.mol_vecs[mol]) - \
                                           np.linalg.norm(self.mol_vecs[mol]) ** 2) < 1e-6:
                     perp_vec = np.array([-self.mol_vecs[mol][1],
                                          self.mol_vecs[mol][0], 0])
                     org_pt = self.vec_indices[mol][0]
                     op = SymmOp.from_origin_axis_angle(
                             self.mols[mol].cart_coords[org_pt],
                             axis=perp_vec, angle=rot)
                     self.mols[mol].apply_operation(op)
Exemplo n.º 51
0
    def get_point_group_operations(self, cartesian=False):
        """
        Return symmetry operations as a list of SymmOp objects.
        By default returns fractional coord symmops.
        But cartesian can be returned too.

        Args:
            cartesian (bool): Whether to return SymmOps as cartesian or
                direct coordinate operations.

        Returns:
            ([SymmOp]): List of point group symmetry operations.
        """
        rotation, translation = self._get_symmetry()
        symmops = []
        mat = self._structure.lattice.matrix.T
        invmat = np.linalg.inv(mat)
        for rot in rotation:
            if cartesian:
                rot = np.dot(mat, np.dot(rot, invmat))
            op = SymmOp.from_rotation_and_translation(rot, np.array([0, 0, 0]))
            symmops.append(op)
        return symmops
Exemplo n.º 52
0
    def test_find_all_mappings(self):
        m = np.array([[0.1, 0.2, 0.3], [-0.1, 0.2, 0.7], [0.6, 0.9, 0.2]])
        latt = Lattice(m)

        op = SymmOp.from_origin_axis_angle([0, 0, 0], [2, -1, 3], 40)
        rot = op.rotation_matrix
        scale = np.array([[0, 2, 0], [1, 1, 0], [0, 0, 1]])

        latt2 = Lattice(np.dot(rot, np.dot(scale, m).T).T)

        for (aligned_out, rot_out, scale_out) in latt.find_all_mappings(latt2):
            self.assertArrayAlmostEqual(np.inner(latt2.matrix, rot_out), aligned_out.matrix, 5)
            self.assertArrayAlmostEqual(np.dot(scale_out, latt.matrix), aligned_out.matrix)
            self.assertArrayAlmostEqual(aligned_out.parameters, latt2.parameters)
            self.assertFalse(np.allclose(aligned_out.parameters, latt.parameters))

        latt = Lattice.orthorhombic(9, 9, 5)
        self.assertEqual(len(list(latt.find_all_mappings(latt))), 16)

        # catch the singular matrix error
        latt = Lattice.from_parameters(1, 1, 1, 10, 10, 10)
        for l, _, _ in latt.find_all_mappings(latt, ltol=0.05, atol=11):
            self.assertTrue(isinstance(l, Lattice))
Exemplo n.º 53
0
    def test_find_all_mappings(self):
        m = np.array([[0.1, 0.2, 0.3], [-0.1, 0.2, 0.7], [0.6, 0.9, 0.2]])
        latt = Lattice(m)

        op = SymmOp.from_origin_axis_angle([0, 0, 0], [2, -1, 3], 40)
        rot = op.rotation_matrix
        scale = np.array([[0, 2, 0], [1, 1, 0], [0, 0, 1]])

        latt2 = Lattice(np.dot(rot, np.dot(scale, m).T).T)

        for (aligned_out, rot_out, scale_out) in latt.find_all_mappings(latt2):
            self.assertArrayAlmostEqual(np.inner(latt2.matrix, rot_out),
                                        aligned_out.matrix)
            self.assertArrayAlmostEqual(np.dot(scale_out, latt.matrix),
                                        aligned_out.matrix)
            self.assertArrayAlmostEqual(aligned_out.lengths_and_angles,
                                        latt2.lengths_and_angles)
            self.assertFalse(
                np.allclose(aligned_out.lengths_and_angles,
                            latt.lengths_and_angles))

        latt = Lattice.orthorhombic(9, 9, 5)
        self.assertEqual(len(list(latt.find_all_mappings(latt))), 16)
Exemplo n.º 54
0
def align_c_axis_along_001(structure):
    """
    Given a structure with a c-axis not along [001],
    returns the same structure rotated so that the c-axis is along
    the [001] direction. This is useful for vasp compiled with no
    z-axis relaxation.

    Args:
        structure (Structure): Pymatgen Structure object to rotate.

    Returns:
        structure. Rotated to align c-axis along [001].
    """

    c = structure.lattice._matrix[2]
    z = [0, 0, 1]
    axis = np.cross(c, z)
    if not(axis[0] == 0 and axis[1] == 0):
        theta = (np.arccos(np.dot(c, z) / (np.linalg.norm(c) * np.linalg.norm(z))))
        R = get_rotation_matrix(axis, theta)
        rotation = SymmOp.from_rotation_and_translation(rotation_matrix=R)
        structure.apply_operation(rotation)
    return structure
Exemplo n.º 55
0
def get_wyckoffs(sg, organized=False):
    '''
    Returns a list of Wyckoff positions for a given space group.
    1st index: index of WP in sg (0 is the WP with largest multiplicity)
    2nd index: a SymmOp object in the WP
    '''
    wyckoff_strings = eval(wyckoff_df["0"][sg])
    wyckoffs = []
    for x in wyckoff_strings:
        wyckoffs.append([])
        for y in x:
            wyckoffs[-1].append(SymmOp.from_xyz_string(y))
    if organized:
        wyckoffs_organized = [[]]  #2D Array of WP's organized by multiplicity
        old = len(wyckoffs[0])
        for wp in wyckoffs:
            mult = len(wp)
            if mult != old:
                wyckoffs_organized.append([])
                old = mult
            wyckoffs_organized[-1].append(wp)
        return wyckoffs_organized
    else:
        return wyckoffs
Exemplo n.º 56
0
 def cover_surface(self, site_indices):
     """
     puts the ligand molecule on the given list of site indices
     """
     num_atoms = len(self.ligand)
     normal = self.normal
     # get a vector that points from one atom in the botton plane
     # to one atom on the top plane. This is required to make sure
     # that the surface normal points outwards from the surface on
     #  to which we want to adsorb the ligand
     vec_vac = self.cart_coords[self.top_atoms[0]] - \
         self.cart_coords[self.bottom_atoms[0]]
     # mov_vec = the vector along which the ligand will be displaced
     mov_vec = normal * self.displacement
     angle = get_angle(vec_vac, self.normal)
     # flip the orientation of normal if it is not pointing in
     # the right direction.
     if (angle > 90):
         normal_frac = self.lattice.get_fractional_coords(normal)
         normal_frac[2] = -normal_frac[2]
         normal = self.lattice.get_cartesian_coords(normal_frac)
         mov_vec = normal * self.displacement
     # get the index corresponding to the given atomic species in
     # the ligand that will bond with the surface on which the
     # ligand will be adsorbed
     adatom_index = self.get_index(self.adatom_on_lig)
     adsorbed_ligands_coords = []
     # set the ligand coordinates for each adsorption site on
     # the surface
     for sindex in site_indices:
         # align the ligand wrt the site on the surface to which
         # it will be adsorbed
         origin = self.cart_coords[sindex]
         self.ligand.translate_sites(
             list(range(num_atoms)),
             origin - self.ligand[adatom_index].coords)
         # displace the ligand by the given amount in the direction
         # normal to surface
         self.ligand.translate_sites(list(range(num_atoms)), mov_vec)
         # vector pointing from the adatom_on_lig to the
         # ligand center of mass
         vec_adatom_cm = self.ligand.center_of_mass - \
             self.ligand[adatom_index].coords
         # rotate the ligand with respect to a vector that is
         # normal to the vec_adatom_cm and the normal to the surface
         # so that the ligand center of mass is aligned along the
         # outward normal to the surface
         origin = self.ligand[adatom_index].coords
         angle = get_angle(vec_adatom_cm, normal)
         if 1 < abs(angle % 180) < 179:
             # For angles which are not 0 or 180,
             # perform a rotation about the origin along an axis
             # perpendicular to both bonds to align bonds.
             axis = np.cross(vec_adatom_cm, normal)
             op = SymmOp.from_origin_axis_angle(origin, axis, angle)
             self.ligand.apply_operation(op)
         elif abs(abs(angle) - 180) < 1:
             # We have a 180 degree angle.
             # Simply do an inversion about the origin
             for i in range(len(self.ligand)):
                 self.ligand[i] = (self.ligand[i].species_and_occu, origin -
                                   (self.ligand[i].coords - origin))
         # x - y - shifts
         x = self.x_shift
         y = self.y_shift
         rot = self.rot
         if x:
             self.ligand.translate_sites(list(range(num_atoms)),
                                         np.array([x, 0, 0]))
         if y:
             self.ligand.translate_sites(list(range(num_atoms)),
                                         np.array([0, y, 0]))
         if rot:
             self.ligand.apply_operation(
                 SymmOp.from_axis_angle_and_translation(
                     (1, 0, 0),
                     rot[0],
                     angle_in_radians=False,
                     translation_vec=(0, 0, 0)))
             self.ligand.apply_operation(
                 SymmOp.from_axis_angle_and_translation(
                     (0, 1, 0),
                     rot[1],
                     angle_in_radians=False,
                     translation_vec=(0, 0, 0)))
             self.ligand.apply_operation(
                 SymmOp.from_axis_angle_and_translation(
                     (0, 0, 1),
                     rot[2],
                     angle_in_radians=False,
                     translation_vec=(0, 0, 0)))
         # 3d numpy array
         adsorbed_ligands_coords.append(self.ligand.cart_coords)
         # extend the slab structure with the adsorbant atoms
     adsorbed_ligands_coords = np.array(adsorbed_ligands_coords)
     for j in range(len(site_indices)):
         [
             self.append(self.ligand.species_and_occu[i],
                         adsorbed_ligands_coords[j, i, :],
                         coords_are_cartesian=True)
             for i in range(num_atoms)
         ]
Exemplo n.º 57
0
    def __init__(self, int_symbol):
        """
        Initializes a Space Group from its full or abbreviated international
        symbol. Only standard settings are supported.

        Args:
            int_symbol (str): Full International (e.g., "P2/m2/m2/m") or
                Hermann-Mauguin Symbol ("Pmmm") or abbreviated symbol. The
                notation is a LaTeX-like string, with screw axes being
                represented by an underscore. For example, "P6_3/mmc".
                Alternative settings can be access by adding a ":identifier".
                For example, the hexagonal setting  for rhombohedral cells can be
                accessed by adding a ":H", e.g., "R-3m:H". To find out all
                possible settings for a spacegroup, use the get_settings
                classmethod. Alternative origin choices can be indicated by a
                translation vector, e.g., 'Fm-3m(a-1/4,b-1/4,c-1/4)'.
        """

        int_symbol = re.sub(r" ", "", int_symbol)
        if int_symbol in SpaceGroup.abbrev_sg_mapping:
            int_symbol = SpaceGroup.abbrev_sg_mapping[int_symbol]
        elif int_symbol in SpaceGroup.full_sg_mapping:
            int_symbol = SpaceGroup.full_sg_mapping[int_symbol]

        for spg in SpaceGroup.SYMM_OPS:
            if int_symbol in [spg["hermann_mauguin"], spg["universal_h_m"]]:
                ops = [SymmOp.from_xyz_string(s) for s in spg["symops"]]
                self.symbol = re.sub(r":", "",
                                     re.sub(r" ", "", spg["universal_h_m"]))
                if int_symbol in SpaceGroup.sgencoding:
                    self.full_symbol = SpaceGroup.sgencoding[int_symbol][
                        "full_symbol"]
                    self.point_group = SpaceGroup.sgencoding[int_symbol][
                        "point_group"]
                else:
                    self.full_symbol = re.sub(r" ", "", spg["universal_h_m"])
                    self.point_group = spg["schoenflies"]
                self.int_number = spg["number"]
                self.order = len(ops)
                self._symmetry_ops = ops
                break
        else:
            if int_symbol not in SpaceGroup.sgencoding:
                raise ValueError("Bad international symbol %s" % int_symbol)

            data = SpaceGroup.sgencoding[int_symbol]

            self.symbol = int_symbol
            # TODO: Support different origin choices.
            enc = list(data["enc"])
            inversion = int(enc.pop(0))
            ngen = int(enc.pop(0))
            symm_ops = [np.eye(4)]
            if inversion:
                symm_ops.append(
                    np.array([[-1, 0, 0, 0], [0, -1, 0, 0], [0, 0, -1, 0],
                              [0, 0, 0, 1]]))
            for i in range(ngen):
                m = np.eye(4)
                m[:3, :3] = SpaceGroup.gen_matrices[enc.pop(0)]
                m[0, 3] = SpaceGroup.translations[enc.pop(0)]
                m[1, 3] = SpaceGroup.translations[enc.pop(0)]
                m[2, 3] = SpaceGroup.translations[enc.pop(0)]
                symm_ops.append(m)
            self.generators = symm_ops
            self.full_symbol = data["full_symbol"]
            self.point_group = data["point_group"]
            self.int_number = data["int_number"]
            self.order = data["order"]

            self._symmetry_ops = None
Exemplo n.º 58
0
    def test_fit(self):
        """
        Take two known matched structures
            1) Ensure match
            2) Ensure match after translation and rotations
            3) Ensure no-match after large site translation
            4) Ensure match after site shuffling
            """
        sm = StructureMatcher()

        self.assertTrue(sm.fit(self.struct_list[0], self.struct_list[1]))

        # Test rotational/translational invariance
        op = SymmOp.from_axis_angle_and_translation([0, 0, 1], 30, False,
                                                    np.array([0.4, 0.7, 0.9]))
        self.struct_list[1].apply_operation(op)
        self.assertTrue(sm.fit(self.struct_list[0], self.struct_list[1]))

        #Test failure under large atomic translation
        self.struct_list[1].translate_sites([0], [.4, .4, .2],
                                            frac_coords=True)
        self.assertFalse(sm.fit(self.struct_list[0], self.struct_list[1]))

        self.struct_list[1].translate_sites([0], [-.4, -.4, -.2],
                                            frac_coords=True)
        # random.shuffle(editor._sites)
        self.assertTrue(sm.fit(self.struct_list[0], self.struct_list[1]))
        #Test FrameworkComporator
        sm2 = StructureMatcher(comparator=FrameworkComparator())
        lfp = self.get_structure("LiFePO4")
        nfp = self.get_structure("NaFePO4")
        self.assertTrue(sm2.fit(lfp, nfp))
        self.assertFalse(sm.fit(lfp, nfp))

        #Test anonymous fit.
        self.assertEqual(sm.fit_anonymous(lfp, nfp), True)
        self.assertAlmostEqual(
            sm.get_rms_anonymous(lfp, nfp)[0], 0.060895871160262717)

        #Test partial occupancies.
        s1 = Structure(Lattice.cubic(3), [{
            "Fe": 0.5
        }, {
            "Fe": 0.5
        }, {
            "Fe": 0.5
        }, {
            "Fe": 0.5
        }], [[0, 0, 0], [0.25, 0.25, 0.25], [0.5, 0.5, 0.5],
             [0.75, 0.75, 0.75]])
        s2 = Structure(Lattice.cubic(3), [{
            "Fe": 0.25
        }, {
            "Fe": 0.5
        }, {
            "Fe": 0.5
        }, {
            "Fe": 0.75
        }], [[0, 0, 0], [0.25, 0.25, 0.25], [0.5, 0.5, 0.5],
             [0.75, 0.75, 0.75]])
        self.assertFalse(sm.fit(s1, s2))
        self.assertFalse(sm.fit(s2, s1))
        s2 = Structure(Lattice.cubic(3), [{
            "Mn": 0.5
        }, {
            "Mn": 0.5
        }, {
            "Mn": 0.5
        }, {
            "Mn": 0.5
        }], [[0, 0, 0], [0.25, 0.25, 0.25], [0.5, 0.5, 0.5],
             [0.75, 0.75, 0.75]])
        self.assertEqual(sm.fit_anonymous(s1, s2), True)

        self.assertAlmostEqual(sm.get_rms_anonymous(s1, s2)[0], 0)
Exemplo n.º 59
0
    def generate_doc(self, dir_name, vasprun_files, outcar_files):
        """
        Adapted from matgendb.creator.generate_doc
        """
        try:
            # basic properties, incl. calcs_reversed and run_stats
            fullpath = os.path.abspath(dir_name)
            d = {k: v for k, v in self.additional_fields.items()}
            d["schema"] = {"code": "atomate", "version": VaspDrone.__version__}
            d["dir_name"] = fullpath
            d["calcs_reversed"] = [self.process_vasprun(dir_name, taskname, filename)
                                   for taskname, filename in vasprun_files.items()]
            outcar_data = [Outcar(os.path.join(dir_name, filename)).as_dict()
                           for taskname, filename in outcar_files.items()]
            run_stats = {}
            for i, d_calc in enumerate(d["calcs_reversed"]):
                run_stats[d_calc["task"]["name"]] = outcar_data[i].pop("run_stats")
                if d_calc.get("output"):
                    d_calc["output"].update({"outcar": outcar_data[i]})
                else:
                    d_calc["output"] = {"outcar": outcar_data[i]}
            try:
                overall_run_stats = {}
                for key in ["Total CPU time used (sec)", "User time (sec)", "System time (sec)",
                            "Elapsed time (sec)"]:
                    overall_run_stats[key] = sum([v[key] for v in run_stats.values()])
                run_stats["overall"] = overall_run_stats
            except:
                logger.error("Bad run stats for {}.".format(fullpath))
            d["run_stats"] = run_stats

            # reverse the calculations data order so newest calc is first
            d["calcs_reversed"].reverse()

            # set root formula/composition keys based on initial and final calcs
            d_calc_init = d["calcs_reversed"][-1]
            d_calc_final = d["calcs_reversed"][0]
            d["chemsys"] = "-".join(sorted(d_calc_final["elements"]))
            comp = Composition(d_calc_final["composition_unit_cell"])
            d["formula_anonymous"] = comp.anonymized_formula
            d["formula_reduced_abc"] = comp.reduced_composition.alphabetical_formula
            for root_key in ["completed_at", "nsites", "composition_unit_cell",
                             "composition_reduced", "formula_pretty", "elements", "nelements"]:
                d[root_key] = d_calc_final[root_key]

            # store the input key based on initial calc
            # store any overrides to the exchange correlation functional
            xc = d_calc_init["input"]["incar"].get("GGA")
            if xc:
                xc = xc.upper()
            p = d_calc_init["input"]["potcar_type"][0].split("_")
            pot_type = p[0]
            functional = "lda" if len(pot_type) == 1 else "_".join(p[1:])
            d["input"] = {"structure": d_calc_init["input"]["structure"],
                          "is_hubbard": d_calc_init.pop("is_hubbard"),
                          "hubbards": d_calc_init.pop("hubbards"),
                          "is_lasph": d_calc_init["input"]["incar"].get("LASPH", False),
                          "potcar_spec": d_calc_init["input"].get("potcar_spec"),
                          "xc_override": xc,
                          "pseudo_potential": {"functional": functional.lower(),
                                               "pot_type": pot_type.lower(),
                                               "labels": d_calc_init["input"]["potcar"]},
                          "parameters": d_calc_init["input"]["parameters"],
                          "incar": d_calc_init["input"]["incar"]
                          }

            # store the output key based on final calc
            d["output"] = {
                "structure": d_calc_final["output"]["structure"],
                "density": d_calc_final.pop("density"),
                "energy": d_calc_final["output"]["energy"],
                "energy_per_atom": d_calc_final["output"]["energy_per_atom"],
                "forces": d_calc_final["output"]["ionic_steps"][-1].get("forces"),
                "stress": d_calc_final["output"]["ionic_steps"][-1].get("stress")}

            # patch calculated magnetic moments into final structure
            if len(d_calc_final["output"]["outcar"]["magnetization"]) != 0:
                magmoms = [m["tot"] for m in d_calc_final["output"]["outcar"]["magnetization"]]
                s = Structure.from_dict(d["output"]["structure"])
                s.add_site_property('magmom', magmoms)
                d["output"]["structure"] = s.as_dict()

            calc = d["calcs_reversed"][0]

            try:
                d["output"].update({"bandgap": calc["output"]["bandgap"],
                                    "cbm": calc["output"]["cbm"],
                                    "vbm": calc["output"]["vbm"],
                                    "is_gap_direct": calc["output"]["is_gap_direct"],
                                    "is_metal": calc["output"]["is_metal"]})
                if not calc["output"]["is_gap_direct"]:
                    d["output"]["direct_gap"] = calc["output"]["direct_gap"]
                if "transition" in calc["output"]:
                    d["output"]["transition"] = calc["output"]["transition"]

            except Exception:
                if self.bandstructure_mode is True:
                    import traceback
                    logger.error(traceback.format_exc())
                    logger.error("Error in " + os.path.abspath(dir_name) + ".\n" + traceback.format_exc())
                    raise

            sg = SpacegroupAnalyzer(Structure.from_dict(d_calc_final["output"]["structure"]), 0.1)
            if not sg.get_symmetry_dataset():
                sg = SpacegroupAnalyzer(Structure.from_dict(d_calc_final["output"]["structure"]),
                                        1e-3, 1)
            d["output"]["spacegroup"] = {
                "source": "spglib",
                "symbol": sg.get_space_group_symbol(),
                "number": sg.get_space_group_number(),
                "point_group": sg.get_point_group_symbol(),
                "crystal_system": sg.get_crystal_system(),
                "hall": sg.get_hall()}
            if d["input"]["parameters"].get("LEPSILON"):
                for k in ['epsilon_static', 'epsilon_static_wolfe', 'epsilon_ionic']:
                    d["output"][k] = d_calc_final["output"][k]
                if SymmOp.inversion() not in sg.get_symmetry_operations():
                    for k in ["piezo_ionic_tensor", "piezo_tensor"]:
                        d["output"][k] = d_calc_final["output"]["outcar"][k]

            d["state"] = "successful" if d_calc["has_vasp_completed"] else "unsuccessful"

            self.set_analysis(d)

            d["last_updated"] = datetime.datetime.today()
            return d

        except Exception:
            import traceback
            logger.error(traceback.format_exc())
            logger.error("Error in " + os.path.abspath(dir_name) + ".\n" + traceback.format_exc())
            raise
Exemplo n.º 60
0
    def test_list_based_functions(self):
        # zeroed
        tc = TensorCollection([1e-4 * Tensor(np.eye(3))] * 4)
        for t in tc.zeroed():
            self.assertArrayEqual(t, np.zeros((3, 3)))
        for t in tc.zeroed(1e-5):
            self.assertArrayEqual(t, 1e-4 * np.eye(3))
        self.list_based_function_check("zeroed", tc)
        self.list_based_function_check("zeroed", tc, tol=1e-5)

        # transform
        symm_op = SymmOp.from_axis_angle_and_translation([0, 0, 1], 30, False,
                                                         [0, 0, 1])
        self.list_based_function_check("transform",
                                       self.seq_tc,
                                       symm_op=symm_op)

        # symmetrized
        self.list_based_function_check("symmetrized", self.seq_tc)

        # rotation
        a = 3.14 * 42.5 / 180
        rotation = SquareTensor([[math.cos(a), 0, math.sin(a)], [0, 1, 0],
                                 [-math.sin(a), 0,
                                  math.cos(a)]])
        self.list_based_function_check("rotate",
                                       self.diff_rank,
                                       matrix=rotation)

        # is_symmetric
        self.assertFalse(self.seq_tc.is_symmetric())
        self.assertTrue(self.diff_rank.is_symmetric())

        # fit_to_structure
        self.list_based_function_check("fit_to_structure", self.diff_rank,
                                       self.struct)
        self.list_based_function_check("fit_to_structure", self.seq_tc,
                                       self.struct)

        # fit_to_structure
        self.list_based_function_check("fit_to_structure", self.diff_rank,
                                       self.struct)
        self.list_based_function_check("fit_to_structure", self.seq_tc,
                                       self.struct)

        # voigt
        self.list_based_function_check("voigt", self.diff_rank)

        # is_voigt_symmetric
        self.assertTrue(self.diff_rank.is_voigt_symmetric())
        self.assertFalse(self.seq_tc.is_voigt_symmetric())

        # Convert to ieee
        for entry in self.ieee_data[:2]:
            xtal = entry['xtal']
            tc = TensorCollection([entry['original_tensor']] * 3)
            struct = Structure.from_dict(entry['structure'])
            self.list_based_function_check("convert_to_ieee", tc, struct)

        # from_voigt
        tc_input = [t for t in np.random.random((3, 6, 6))]
        tc = TensorCollection.from_voigt(tc_input)
        for t_input, t in zip(tc_input, tc):
            self.assertArrayAlmostEqual(Tensor.from_voigt(t_input), t)