Esempio n. 1
0
    def find_spherical_axes(self):
        """Looks for R5, R4, R3 and R2 axes in spherical 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 = {2: False, 3: False, 4: False, 5: False}
        test_set = self.find_possible_equivalent_positions()
        for c1, c2, c3 in itertools.combinations(test_set, 3):
            for cc1, cc2 in itertools.combinations([c1, c2, c3], 2):
                if not rot_present[2]:
                    test_axis = cc1 + cc2
                    if numpy.linalg.norm(test_axis) > self.tol:
                        op = rotation(axis=test_axis, order=2)
                        if is_valid_op(self.mol, op):
                            logger.debug("Found axis with order {0}".format(2))
                            rot_present[2] = True
                            self.symmops["C"] += [
                                (2, test_axis, op),
                            ]
                            self.nrot += 1

            test_axis = numpy.cross(c2 - c1, c3 - c1)
            if numpy.linalg.norm(test_axis) > self.tol:
                for order in (3, 4, 5):
                    if not rot_present[order]:
                        op = rotation(axis=test_axis, order=order)
                        if is_valid_op(self.mol, op):
                            logger.debug(
                                "Found axis with order {0}".format(order))
                            rot_present[order] = True
                            self.symmops["C"] += [
                                (order, test_axis, op),
                            ]
                            self.nrot += 1
                            break
            if (rot_present[2] & rot_present[3] &
                (rot_present[4] | rot_present[5])):
                break
        return
Esempio n. 2
0
 def has_perpendicular_C2(self, axis):
     """Checks for R2 axes perpendicular to unique axis.  For handling
     symmetric top molecules.
     """
     min_set = self.find_possible_equivalent_positions(axis=axis)
     found = False
     for s1, s2 in itertools.combinations(min_set, 2):
         test_axis = numpy.cross(s1 - s2, axis)
         if numpy.linalg.norm(test_axis) > self.tol:
             op = rotation(axis=test_axis, order=2)
             if is_valid_op(self.mol, op):
                 self.symmops["C"] += [(2, test_axis, op), ]
                 self.nrot += 1
                 found = True
     return found
Esempio n. 3
0
 def analyze_cyclic_groups(self):
     """Handles cyclic group molecules."""
     order, axis, op = max(self.symmops["C"], key=lambda v: v[0])
     self.schoenflies = "C{0}".format(order)
     mirror_type = self.find_reflection_plane(axis)
     if mirror_type == "h":
         self.schoenflies += "h"
     elif mirror_type == "v":
         self.schoenflies += "v"
     elif mirror_type is None:
         rotoref = reflection(axis).dot(
             rotation(axis=axis, order=2 * order))
         if is_valid_op(self.mol, rotoref):
             self.schoenflies = "S{0}".format(2 * order)
             self.symmops["S"] += [(order, axis, rotoref), ]
Esempio n. 4
0
 def detect_rotational_symmetry(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.find_possible_equivalent_positions(axis=axis)
     max_sym = len(min_set)
     for order in range(max_sym, 0, -1):
         if max_sym % order != 0:
             continue
         op = rotation(axis=axis, order=order)
         if is_valid_op(self.mol, op):
             logger.debug("Found axis with order {0}".format(order))
             self.symmops["C"] += [(order, axis, op), ]
             self.nrot += 1
             return order
     return 1
Esempio n. 5
0
 def analyze_asymmetric_top(self):
     """Handles assymetric top molecules, which cannot contain rotational
     symmetry larger than 2.
     """
     for axis in self.eigvecs:
         op = rotation(axis=axis, order=2)
         if is_valid_op(self.mol, op):
             self.symmops["C"] += [(2, axis, op), ]
             self.nrot += 1
     if self.nrot == 0:
         logger.debug("No rotation symmetries detected.")
         self.analyze_nonrotational_groups()
     elif self.nrot == 3:
         logger.debug("Dihedral group detected.")
         self.analyze_dihedral_groups()
     else:
         logger.debug("Cyclic group detected.")
         self.analyze_cyclic_groups()
Esempio n. 6
0
def get_symmetry_elements(mol,
                          max_order=8,
                          epsilon=0.1):
    """Return an array counting the found symmetries
    of the object, up to axes of order max_order.
    Enables fast comparison of compatibility between objects:
    if array1 - array2 > 0, that means object1 fits the slot2
    """
    if len(mol) == 1:
        logger.debug("Point-symmetry detected.")
        symmetries = numpy.array([0, 0, 0, 0, 0, 1])
        return symmetries
    if len(mol) == 2:
        logger.debug("Linear connectivity detected.")
        # simplest, linear case
        symmetries = numpy.array([1, 1, 0, 1, 1, 2])
        return symmetries
    mol.center(about=0)
    # ensure there is a sufficient distance between connections
    dist = mol.get_all_distances().mean()
    if dist < 10.0:
        alpha = 10.0 / dist
        mol.positions = mol.positions.dot(numpy.eye(3) * alpha)
    logger.debug("DIST {}".format(dist))
    axes = get_potential_axes(mol)
    # array for the operations:
    # size = (1inversion+rotationorders+rotinvorders+2planes+1multiplicity)
    symmetries = numpy.zeros(4 + 2 * max_order)
    # inversion
    inv = -1.0 * numpy.eye(3)
    has_inv = is_valid_op(mol, inv)
    symmetries[0] += int(has_inv)
    # rotations:
    principal_order = 1
    principal_axes = []
    for axis in axes:
        for order in range(2, max_order + 1):
            rot = rotation(axis, order)
            has_rot = is_valid_op(mol, rot)
            symmetries[order - 1] += int(has_rot)
            if has_rot:
                logger.debug("Detected: C{order}".format(order=order))
            # bookkeeping for the planes
            if has_rot and order > principal_order:
                principal_order = order
                principal_axes = [axis, ]
            elif has_rot and order == principal_order:
                principal_axes.append(axis)
    # planes
    for axis in axes:
        ref = reflection(axis)
        has_ref = is_valid_op(mol, ref)
        if has_ref:
            dots = [abs(axis.dot(max_axis))
                    for max_axis in principal_axes]
            if not dots:
                continue
            mindot = numpy.amin(dots)
            maxdot = numpy.amax(dots)
            if maxdot > 1.0 - epsilon:
                # sigma h
                symmetries[-2] += 1
                logger.debug("Detected: sigma h")
            elif mindot < epsilon:
                # sigma vd
                symmetries[-3] += 1
                logger.debug("Detected: sigma vd")
    # rotoreflections
    for axis in axes:
        ref = reflection(axis)
        for order in range(2, max_order + 1):
            rot = rotation(axis, order)
            rr = rot.dot(ref)
            has_rr = is_valid_op(mol, rr)
            symmetries[order + max_order - 2] += int(has_rr)
            if has_rr:
                logger.debug("Detected: S{order}".format(order=order))
    # multiplicity
    symmetries[-1] = len([x for x in mol if x.symbol == "X"])
    return numpy.array(symmetries, dtype=int)