Exemplo n.º 1
0
    def external_basis(self):
        """The basis for small displacements in the external degrees of freedom.

           The basis is expressed in mass-weighted Cartesian coordinates.
           The three translations are along the x, y, and z-axis. The three
           rotations are about an axis parallel to the x, y, and z-axis
           through the center of mass.
           The returned result depends on the periodicity of the system:

           * When the system is periodic, only the translation external degrees
             are included. The result is an array with shape (3,3N)
           * When the system is not periodic, the rotational external
             degrees are also included. The result is an array with shape (6,3N). The
             first three rows correspond to translation, the latter three rows
             correspond to rotation.
        """
        center = (self.coordinates*self.masses3.reshape((-1,3))).sum(0)/self.mass  # center of mass
        result = transrot_basis(self.coordinates - center, not self.periodic)
        result *= np.sqrt(self.masses3) # transform basis to mass weighted coordinates

        return result
Exemplo n.º 2
0
    def external_basis(self):
        """The basis for small displacements in the external degrees of freedom.

           The basis is expressed in mass-weighted Cartesian coordinates.
           The three translations are along the x, y, and z-axis. The three
           rotations are about an axis parallel to the x, y, and z-axis
           through the center of mass.
           The returned result depends on the periodicity of the system:

           * When the system is periodic, only the translation external degrees
             are included. The result is an array with shape (3,3N)
           * When the system is not periodic, the rotational external
             degrees are also included. The result is an array with shape (6,3N). The
             first three rows correspond to translation, the latter three rows
             correspond to rotation.
        """
        center = (self.coordinates*self.masses3.reshape((-1,3))).sum(0)/self.mass  # center of mass
        result = transrot_basis(self.coordinates - center, not self.periodic)
        result *= np.sqrt(self.masses3) # transform basis to mass weighted coordinates

        return result
Exemplo n.º 3
0
def compute_moments(coordinates, masses3, center, axis, indexes):
    """Computes the absolute and the relative moment of an internal rotor

       Arguments:
        | ``coordinates`` -- The coordinates of all atoms, float numpy array
                             with shape (N,3).
        | ``masses3`` -- The diagonal of the mass matrix, each mass is repeated
                         three tines, float numpy array with shape 3N.
        | ``center`` -- A point on the rotation axis. Float numpy array with
                        shape 3.
        | ``axis`` -- A unit vector with the direction of the rotation axis.
                      Float numpy array with shape 3.
        | ``indexes`` -- The indexes of the atoms that belong to the rotor.

       The implementation is based on the transformation of the mass-matrix to
       the internal rotation coordinate. The derivative of the internal
       coordinate towards cartesian coordinates represents a small displacement
       of the atoms. This displacement is constrained to show no external
       linear or rotational moment.
    """
    # the derivative of the cartesian coordinates towards the rotation
    # angle of the top:
    rot_tangent = numpy.zeros((len(coordinates)*3), float)
    for i in indexes:
        rot_tangent[3*i:3*i+3] = numpy.cross(coordinates[i]-center, axis)
    # transform this to a derivative without global linear or angular
    # momentum. This is done by projecting on the basis of external degrees
    # of freedom in mass-weighted coordinates, and subsequently subtracting
    # that projection from the original tangent
    basis = transrot_basis(coordinates)
    A = numpy.dot(basis*masses3, basis.transpose())
    B = numpy.dot(basis*masses3, rot_tangent)
    alphas = numpy.linalg.solve(A,B)
    rot_tangent_relative = rot_tangent - numpy.dot(alphas, basis)
    return (
        (rot_tangent**2*masses3).sum(),
        (rot_tangent_relative**2*masses3).sum()
    )
Exemplo n.º 4
0
def compute_moments(coordinates, masses3, center, axis, indexes):
    """Computes the absolute and the relative moment of an internal rotor

       Arguments:
        | ``coordinates`` -- The coordinates of all atoms, float numpy array
                             with shape (N,3).
        | ``masses3`` -- The diagonal of the mass matrix, each mass is repeated
                         three tines, float numpy array with shape 3N.
        | ``center`` -- A point on the rotation axis. Float numpy array with
                        shape 3.
        | ``axis`` -- A unit vector with the direction of the rotation axis.
                      Float numpy array with shape 3.
        | ``indexes`` -- The indexes of the atoms that belong to the rotor.

       The implementation is based on the transformation of the mass-matrix to
       the internal rotation coordinate. The derivative of the internal
       coordinate towards cartesian coordinates represents a small displacement
       of the atoms. This displacement is constrained to show no external
       linear or rotational moment.
    """
    # the derivative of the cartesian coordinates towards the rotation
    # angle of the top:
    rot_tangent = np.zeros((len(coordinates) * 3), float)
    for i in indexes:
        rot_tangent[3 * i:3 * i + 3] = np.cross(coordinates[i] - center, axis)
    # transform this to a derivative without global linear or angular
    # momentum. This is done by projecting on the basis of external degrees
    # of freedom in mass-weighted coordinates, and subsequently subtracting
    # that projection from the original tangent
    basis = transrot_basis(coordinates)
    A = np.dot(basis * masses3, basis.transpose())
    B = np.dot(basis * masses3, rot_tangent)
    alphas = np.linalg.solve(A, B)
    rot_tangent_relative = rot_tangent - np.dot(alphas, basis)
    return ((rot_tangent**2 * masses3).sum(),
            (rot_tangent_relative**2 * masses3).sum())