예제 #1
0
def test_coordinate_vars():
    """
    Tests the coordinate variables functionality with respect to
    reorientation of coordinate systems.
    """
    assert BaseScalar('Ax', 0, A) == A.x
    assert BaseScalar('Ay', 1, A) == A.y
    assert BaseScalar('Az', 2, A) == A.z
    assert BaseScalar('Ax', 0, A).__hash__() == A.x.__hash__()
    assert isinstance(A.x, BaseScalar) and \
           isinstance(A.y, BaseScalar) and \
           isinstance(A.z, BaseScalar)
    assert A.scalar_map(A) == {A.x: A.x, A.y: A.y, A.z: A.z}
    assert A.x.system == A
    B = A.orient_new('B', 'Axis', [q, A.k])
    assert B.scalar_map(A) == {B.z: A.z, B.y: -A.x*sin(q) + A.y*cos(q),
                                 B.x: A.x*cos(q) + A.y*sin(q)}
    assert A.scalar_map(B) == {A.x: B.x*cos(q) - B.y*sin(q),
                                 A.y: B.x*sin(q) + B.y*cos(q), A.z: B.z}
    assert express(B.x, A, variables=True) == A.x*cos(q) + A.y*sin(q)
    assert express(B.y, A, variables=True) == -A.x*sin(q) + A.y*cos(q)
    assert express(B.z, A, variables=True) == A.z
    assert express(B.x*B.y*B.z, A, variables=True) == \
           A.z*(-A.x*sin(q) + A.y*cos(q))*(A.x*cos(q) + A.y*sin(q))
    assert express(B.x*B.i + B.y*B.j + B.z*B.k, A) == \
           (B.x*cos(q) - B.y*sin(q))*A.i + (B.x*sin(q) + \
           B.y*cos(q))*A.j + B.z*A.k
    assert simplify(express(B.x*B.i + B.y*B.j + B.z*B.k, A, \
                            variables=True)) == \
           A.x*A.i + A.y*A.j + A.z*A.k
    assert express(A.x*A.i + A.y*A.j + A.z*A.k, B) == \
           (A.x*cos(q) + A.y*sin(q))*B.i + \
           (-A.x*sin(q) + A.y*cos(q))*B.j + A.z*B.k
    assert simplify(express(A.x*A.i + A.y*A.j + A.z*A.k, B, \
                            variables=True)) == \
           B.x*B.i + B.y*B.j + B.z*B.k
    N = B.orient_new('N', 'Axis', [-q, B.k])
    assert N.scalar_map(A) == \
           {N.x: A.x, N.z: A.z, N.y: A.y}
    C = A.orient_new('C', 'Axis', [q, A.i + A.j + A.k])
    mapping = A.scalar_map(C)
    assert mapping[A.x] == 2*C.x*cos(q)/3 + C.x/3 - \
           2*C.y*sin(q + pi/6)/3 + C.y/3 - 2*C.z*cos(q + pi/3)/3 + C.z/3
    assert mapping[A.y] == -2*C.x*cos(q + pi/3)/3 + \
           C.x/3 + 2*C.y*cos(q)/3 + C.y/3 - 2*C.z*sin(q + pi/6)/3 + C.z/3
    assert mapping[A.z] == -2*C.x*sin(q + pi/6)/3 + C.x/3 - \
           2*C.y*cos(q + pi/3)/3 + C.y/3 + 2*C.z*cos(q)/3 + C.z/3
예제 #2
0
    def __new__(cls,
                name,
                location=None,
                rotation_matrix=None,
                parent=None,
                vector_names=None,
                variable_names=None):
        """
        The orientation/location parameters are necessary if this system
        is being defined at a certain orientation or location wrt another.

        Parameters
        ==========

        name : str
            The name of the new CoordSys3D instance.

        location : Vector
            The position vector of the new system's origin wrt the parent
            instance.

        rotation_matrix : SymPy ImmutableMatrix
            The rotation matrix of the new coordinate system with respect
            to the parent. In other words, the output of
            new_system.rotation_matrix(parent).

        parent : CoordSys3D
            The coordinate system wrt which the orientation/location
            (or both) is being defined.

        vector_names, variable_names : iterable(optional)
            Iterables of 3 strings each, with custom names for base
            vectors and base scalars of the new system respectively.
            Used for simple str printing.

        """

        name = str(name)
        Vector = sympy.vector.Vector
        BaseVector = sympy.vector.BaseVector
        Point = sympy.vector.Point
        if not isinstance(name, string_types):
            raise TypeError("name should be a string")

        # If orientation information has been provided, store
        # the rotation matrix accordingly
        if rotation_matrix is None:
            parent_orient = Matrix(eye(3))
        else:
            if not isinstance(rotation_matrix, Matrix):
                raise TypeError("rotation_matrix should be an Immutable" +
                                "Matrix instance")
            parent_orient = rotation_matrix

        # If location information is not given, adjust the default
        # location as Vector.zero
        if parent is not None:
            if not isinstance(parent, CoordSys3D):
                raise TypeError("parent should be a " + "CoordSys3D/None")
            if location is None:
                location = Vector.zero
            else:
                if not isinstance(location, Vector):
                    raise TypeError("location should be a Vector")
                # Check that location does not contain base
                # scalars
                for x in location.free_symbols:
                    if isinstance(x, BaseScalar):
                        raise ValueError("location should not contain" +
                                         " BaseScalars")
            origin = parent.origin.locate_new(name + '.origin', location)
        else:
            location = Vector.zero
            origin = Point(name + '.origin')

        # All systems that are defined as 'roots' are unequal, unless
        # they have the same name.
        # Systems defined at same orientation/position wrt the same
        # 'parent' are equal, irrespective of the name.
        # This is true even if the same orientation is provided via
        # different methods like Axis/Body/Space/Quaternion.
        # However, coincident systems may be seen as unequal if
        # positioned/oriented wrt different parents, even though
        # they may actually be 'coincident' wrt the root system.
        if parent is not None:
            obj = super(CoordSys3D, cls).__new__(cls, Symbol(name), location,
                                                 parent_orient, parent)
        else:
            obj = super(CoordSys3D, cls).__new__(cls, Symbol(name), location,
                                                 parent_orient)
        obj._name = name

        # Initialize the base vectors
        if vector_names is None:
            vector_names = (name + '.i', name + '.j', name + '.k')
            latex_vects = [(r'\mathbf{\hat{i}_{%s}}' % name),
                           (r'\mathbf{\hat{j}_{%s}}' % name),
                           (r'\mathbf{\hat{k}_{%s}}' % name)]
            pretty_vects = (name + '_i', name + '_j', name + '_k')
        else:
            _check_strings('vector_names', vector_names)
            vector_names = list(vector_names)
            latex_vects = [(r'\mathbf{\hat{%s}_{%s}}' % (x, name))
                           for x in vector_names]
            pretty_vects = [(name + '_' + x) for x in vector_names]

        obj._i = BaseVector(vector_names[0], 0, obj, pretty_vects[0],
                            latex_vects[0])
        obj._j = BaseVector(vector_names[1], 1, obj, pretty_vects[1],
                            latex_vects[1])
        obj._k = BaseVector(vector_names[2], 2, obj, pretty_vects[2],
                            latex_vects[2])

        # Initialize the base scalars
        if variable_names is None:
            variable_names = (name + '.x', name + '.y', name + '.z')
            latex_scalars = [(r"\mathbf{{x}_{%s}}" % name),
                             (r"\mathbf{{y}_{%s}}" % name),
                             (r"\mathbf{{z}_{%s}}" % name)]
            pretty_scalars = (name + '_x', name + '_y', name + '_z')
        else:
            _check_strings('variable_names', vector_names)
            variable_names = list(variable_names)
            latex_scalars = [(r"\mathbf{{%s}_{%s}}" % (x, name))
                             for x in variable_names]
            pretty_scalars = [(name + '_' + x) for x in variable_names]

        obj._x = BaseScalar(variable_names[0], 0, obj, pretty_scalars[0],
                            latex_scalars[0])
        obj._y = BaseScalar(variable_names[1], 1, obj, pretty_scalars[1],
                            latex_scalars[1])
        obj._z = BaseScalar(variable_names[2], 2, obj, pretty_scalars[2],
                            latex_scalars[2])

        obj._h1 = S.One
        obj._h2 = S.One
        obj._h3 = S.One

        obj._transformation_eqs = obj._x, obj._y, obj._y

        obj._inv_transformation_eqs = lambda x, y, z: (x, y, z)

        # Assign params
        obj._parent = parent
        if obj._parent is not None:
            obj._root = obj._parent._root
        else:
            obj._root = obj

        obj._parent_rotation_matrix = parent_orient
        obj._origin = origin

        # Return the instance
        return obj
예제 #3
0
def test_coordinate_vars():
    """
    Tests the coordinate variables functionality with respect to
    reorientation of coordinate systems.
    """
    A = CoordSys3D("A")
    # Note that the name given on the lhs is different from A.x._name
    assert BaseScalar(0, A, "A_x", r"\mathbf{{x}_{A}}") == A.x
    assert BaseScalar(1, A, "A_y", r"\mathbf{{y}_{A}}") == A.y
    assert BaseScalar(2, A, "A_z", r"\mathbf{{z}_{A}}") == A.z
    assert BaseScalar(0, A, "A_x",
                      r"\mathbf{{x}_{A}}").__hash__() == A.x.__hash__()
    assert (isinstance(A.x, BaseScalar) and isinstance(A.y, BaseScalar)
            and isinstance(A.z, BaseScalar))
    assert A.x * A.y == A.y * A.x
    assert A.scalar_map(A) == {A.x: A.x, A.y: A.y, A.z: A.z}
    assert A.x.system == A
    assert A.x.diff(A.x) == 1
    B = A.orient_new_axis("B", q, A.k)
    assert B.scalar_map(A) == {
        B.z: A.z,
        B.y: -A.x * sin(q) + A.y * cos(q),
        B.x: A.x * cos(q) + A.y * sin(q),
    }
    assert A.scalar_map(B) == {
        A.x: B.x * cos(q) - B.y * sin(q),
        A.y: B.x * sin(q) + B.y * cos(q),
        A.z: B.z,
    }
    assert express(B.x, A, variables=True) == A.x * cos(q) + A.y * sin(q)
    assert express(B.y, A, variables=True) == -A.x * sin(q) + A.y * cos(q)
    assert express(B.z, A, variables=True) == A.z
    assert expand(express(B.x * B.y * B.z, A, variables=True)) == expand(
        A.z * (-A.x * sin(q) + A.y * cos(q)) * (A.x * cos(q) + A.y * sin(q)))
    assert (express(B.x * B.i + B.y * B.j + B.z * B.k,
                    A) == (B.x * cos(q) - B.y * sin(q)) * A.i +
            (B.x * sin(q) + B.y * cos(q)) * A.j + B.z * A.k)
    assert (simplify(
        express(B.x * B.i + B.y * B.j + B.z * B.k, A,
                variables=True)) == A.x * A.i + A.y * A.j + A.z * A.k)
    assert (express(A.x * A.i + A.y * A.j + A.z * A.k,
                    B) == (A.x * cos(q) + A.y * sin(q)) * B.i +
            (-A.x * sin(q) + A.y * cos(q)) * B.j + A.z * B.k)
    assert (simplify(
        express(A.x * A.i + A.y * A.j + A.z * A.k, B,
                variables=True)) == B.x * B.i + B.y * B.j + B.z * B.k)
    N = B.orient_new_axis("N", -q, B.k)
    assert N.scalar_map(A) == {N.x: A.x, N.z: A.z, N.y: A.y}
    C = A.orient_new_axis("C", q, A.i + A.j + A.k)
    mapping = A.scalar_map(C)
    assert mapping[A.x].equals(C.x * (2 * cos(q) + 1) / 3 + C.y *
                               (-2 * sin(q + pi / 6) + 1) / 3 + C.z *
                               (-2 * cos(q + pi / 3) + 1) / 3)
    assert mapping[A.y].equals(C.x * (-2 * cos(q + pi / 3) + 1) / 3 + C.y *
                               (2 * cos(q) + 1) / 3 + C.z *
                               (-2 * sin(q + pi / 6) + 1) / 3)
    assert mapping[A.z].equals(C.x * (-2 * sin(q + pi / 6) + 1) / 3 + C.y *
                               (-2 * cos(q + pi / 3) + 1) / 3 + C.z *
                               (2 * cos(q) + 1) / 3)
    D = A.locate_new("D", a * A.i + b * A.j + c * A.k)
    assert D.scalar_map(A) == {D.z: A.z - c, D.x: A.x - a, D.y: A.y - b}
    E = A.orient_new_axis("E", a, A.k, a * A.i + b * A.j + c * A.k)
    assert A.scalar_map(E) == {
        A.z: E.z + c,
        A.x: E.x * cos(a) - E.y * sin(a) + a,
        A.y: E.x * sin(a) + E.y * cos(a) + b,
    }
    assert E.scalar_map(A) == {
        E.x: (A.x - a) * cos(a) + (A.y - b) * sin(a),
        E.y: (-A.x + a) * sin(a) + (A.y - b) * cos(a),
        E.z: A.z - c,
    }
    F = A.locate_new("F", Vector.zero)
    assert A.scalar_map(F) == {A.z: F.z, A.x: F.x, A.y: F.y}
예제 #4
0
    def __new__(cls,
                name,
                transformation=None,
                parent=None,
                location=None,
                rotation_matrix=None,
                vector_names=None,
                variable_names=None):
        """
        The orientation/location parameters are necessary if this system
        is being defined at a certain orientation or location wrt another.

        Parameters
        ==========

        name : str
            The name of the new CoordSys3D instance.

        transformation : Lambda, Tuple, str
            Transformation defined by transformation equations or chosen
            from predefined ones.

        location : Vector
            The position vector of the new system's origin wrt the parent
            instance.

        rotation_matrix : SymPy ImmutableMatrix
            The rotation matrix of the new coordinate system with respect
            to the parent. In other words, the output of
            new_system.rotation_matrix(parent).

        parent : CoordSys3D
            The coordinate system wrt which the orientation/location
            (or both) is being defined.

        vector_names, variable_names : iterable(optional)
            Iterables of 3 strings each, with custom names for base
            vectors and base scalars of the new system respectively.
            Used for simple str printing.

        """

        name = str(name)
        Vector = sympy.vector.Vector
        BaseVector = sympy.vector.BaseVector
        Point = sympy.vector.Point

        if not isinstance(name, string_types):
            raise TypeError("name should be a string")

        if transformation is not None:
            if (location is not None) or (rotation_matrix is not None):
                raise ValueError("specify either `transformation` or "
                                 "`location`/`rotation_matrix`")
            if isinstance(transformation, (Tuple, tuple, list)):
                if isinstance(transformation[0], MatrixBase):
                    rotation_matrix = transformation[0]
                    location = transformation[1]
                else:
                    transformation = Lambda(transformation[0],
                                            transformation[1])
            elif isinstance(transformation, Callable):
                x1, x2, x3 = symbols('x1 x2 x3', cls=Dummy)
                transformation = Lambda((x1, x2, x3),
                                        transformation(x1, x2, x3))
            elif isinstance(transformation, string_types):
                transformation = Symbol(transformation)
            elif isinstance(transformation, (Symbol, Lambda)):
                pass
            else:
                raise TypeError("transformation: "
                                "wrong type {0}".format(type(transformation)))

        # If orientation information has been provided, store
        # the rotation matrix accordingly
        if rotation_matrix is None:
            rotation_matrix = ImmutableDenseMatrix(eye(3))
        else:
            if not isinstance(rotation_matrix, MatrixBase):
                raise TypeError("rotation_matrix should be an Immutable" +
                                "Matrix instance")
            rotation_matrix = rotation_matrix.as_immutable()

        # If location information is not given, adjust the default
        # location as Vector.zero
        if parent is not None:
            if not isinstance(parent, CoordSys3D):
                raise TypeError("parent should be a " + "CoordSys3D/None")
            if location is None:
                location = Vector.zero
            else:
                if not isinstance(location, Vector):
                    raise TypeError("location should be a Vector")
                # Check that location does not contain base
                # scalars
                for x in location.free_symbols:
                    if isinstance(x, BaseScalar):
                        raise ValueError("location should not contain" +
                                         " BaseScalars")
            origin = parent.origin.locate_new(name + '.origin', location)
        else:
            location = Vector.zero
            origin = Point(name + '.origin')

        if transformation is None:
            transformation = Tuple(rotation_matrix, location)

        if isinstance(transformation, Tuple):
            lambda_transformation = CoordSys3D._compose_rotation_and_translation(
                transformation[0], transformation[1], parent)
            r, l = transformation
            l = l._projections
            lambda_lame = CoordSys3D._get_lame_coeff('cartesian')
            lambda_inverse = lambda x, y, z: r.inv() * Matrix(
                [x - l[0], y - l[1], z - l[2]])
        elif isinstance(transformation, Symbol):
            trname = transformation.name
            lambda_transformation = CoordSys3D._get_transformation_lambdas(
                trname)
            if parent is not None:
                if parent.lame_coefficients() != (S.One, S.One, S.One):
                    raise ValueError('Parent for pre-defined coordinate '
                                     'system should be Cartesian.')
            lambda_lame = CoordSys3D._get_lame_coeff(trname)
            lambda_inverse = CoordSys3D._set_inv_trans_equations(trname)
        elif isinstance(transformation, Lambda):
            if not CoordSys3D._check_orthogonality(transformation):
                raise ValueError("The transformation equation does not "
                                 "create orthogonal coordinate system")
            lambda_transformation = transformation
            lambda_lame = CoordSys3D._calculate_lame_coeff(
                lambda_transformation)
            lambda_inverse = None
        else:
            lambda_transformation = lambda x, y, z: transformation(x, y, z)
            lambda_lame = CoordSys3D._get_lame_coeff(transformation)
            lambda_inverse = None

        if variable_names is None:
            if isinstance(transformation, Lambda):
                variable_names = ["x1", "x2", "x3"]
            elif isinstance(transformation, Symbol):
                if transformation.name == 'spherical':
                    variable_names = ["r", "theta", "phi"]
                elif transformation.name == 'cylindrical':
                    variable_names = ["r", "theta", "z"]
                else:
                    variable_names = ["x", "y", "z"]
            else:
                variable_names = ["x", "y", "z"]
        if vector_names is None:
            vector_names = ["i", "j", "k"]

        # All systems that are defined as 'roots' are unequal, unless
        # they have the same name.
        # Systems defined at same orientation/position wrt the same
        # 'parent' are equal, irrespective of the name.
        # This is true even if the same orientation is provided via
        # different methods like Axis/Body/Space/Quaternion.
        # However, coincident systems may be seen as unequal if
        # positioned/oriented wrt different parents, even though
        # they may actually be 'coincident' wrt the root system.
        if parent is not None:
            obj = super(CoordSys3D, cls).__new__(cls, Symbol(name),
                                                 transformation, parent)
        else:
            obj = super(CoordSys3D, cls).__new__(cls, Symbol(name),
                                                 transformation)
        obj._name = name
        # Initialize the base vectors

        _check_strings('vector_names', vector_names)
        vector_names = list(vector_names)
        latex_vects = [(r'\mathbf{\hat{%s}_{%s}}' % (x, name))
                       for x in vector_names]
        pretty_vects = ['%s_%s' % (x, name) for x in vector_names]

        obj._vector_names = vector_names

        v1 = BaseVector(0, obj, pretty_vects[0], latex_vects[0])
        v2 = BaseVector(1, obj, pretty_vects[1], latex_vects[1])
        v3 = BaseVector(2, obj, pretty_vects[2], latex_vects[2])

        obj._base_vectors = (v1, v2, v3)

        # Initialize the base scalars

        _check_strings('variable_names', vector_names)
        variable_names = list(variable_names)
        latex_scalars = [(r"\mathbf{{%s}_{%s}}" % (x, name))
                         for x in variable_names]
        pretty_scalars = ['%s_%s' % (x, name) for x in variable_names]

        obj._variable_names = variable_names
        obj._vector_names = vector_names

        x1 = BaseScalar(0, obj, pretty_scalars[0], latex_scalars[0])
        x2 = BaseScalar(1, obj, pretty_scalars[1], latex_scalars[1])
        x3 = BaseScalar(2, obj, pretty_scalars[2], latex_scalars[2])

        obj._base_scalars = (x1, x2, x3)

        obj._transformation = transformation
        obj._transformation_lambda = lambda_transformation
        obj._lame_coefficients = lambda_lame(x1, x2, x3)
        obj._transformation_from_parent_lambda = lambda_inverse

        setattr(obj, variable_names[0], x1)
        setattr(obj, variable_names[1], x2)
        setattr(obj, variable_names[2], x3)

        setattr(obj, vector_names[0], v1)
        setattr(obj, vector_names[1], v2)
        setattr(obj, vector_names[2], v3)

        # Assign params
        obj._parent = parent
        if obj._parent is not None:
            obj._root = obj._parent._root
        else:
            obj._root = obj

        obj._parent_rotation_matrix = rotation_matrix
        obj._origin = origin

        # Return the instance
        return obj
예제 #5
0
def test_coordinate_vars():
    """
    Tests the coordinate variables functionality with respect to
    reorientation of coordinate systems.
    """
    A = CoordSys3D('A')
    # Note that the name given on the lhs is different from A.x._name
    assert BaseScalar('A.x', 0, A, 'A_x', r'\mathbf{{x}_{A}}') == A.x
    assert BaseScalar('A.y', 1, A, 'A_y', r'\mathbf{{y}_{A}}') == A.y
    assert BaseScalar('A.z', 2, A, 'A_z', r'\mathbf{{z}_{A}}') == A.z
    assert BaseScalar('A.x', 0, A, 'A_x',
                      r'\mathbf{{x}_{A}}').__hash__() == A.x.__hash__()
    assert isinstance(A.x, BaseScalar) and \
           isinstance(A.y, BaseScalar) and \
           isinstance(A.z, BaseScalar)
    assert A.x * A.y == A.y * A.x
    assert A.scalar_map(A) == {A.x: A.x, A.y: A.y, A.z: A.z}
    assert A.x.system == A
    assert A.x.diff(A.x) == 1
    B = A.orient_new_axis('B', q, A.k)
    assert B.scalar_map(A) == {
        B.z: A.z,
        B.y: -A.x * sin(q) + A.y * cos(q),
        B.x: A.x * cos(q) + A.y * sin(q)
    }
    assert A.scalar_map(B) == {
        A.x: B.x * cos(q) - B.y * sin(q),
        A.y: B.x * sin(q) + B.y * cos(q),
        A.z: B.z
    }
    assert express(B.x, A, variables=True) == A.x * cos(q) + A.y * sin(q)
    assert express(B.y, A, variables=True) == -A.x * sin(q) + A.y * cos(q)
    assert express(B.z, A, variables=True) == A.z
    assert expand(express(B.x*B.y*B.z, A, variables=True)) == \
           expand(A.z*(-A.x*sin(q) + A.y*cos(q))*(A.x*cos(q) + A.y*sin(q)))
    assert express(B.x*B.i + B.y*B.j + B.z*B.k, A) == \
           (B.x*cos(q) - B.y*sin(q))*A.i + (B.x*sin(q) + \
           B.y*cos(q))*A.j + B.z*A.k
    assert simplify(express(B.x*B.i + B.y*B.j + B.z*B.k, A, \
                            variables=True)) == \
           A.x*A.i + A.y*A.j + A.z*A.k
    assert express(A.x*A.i + A.y*A.j + A.z*A.k, B) == \
           (A.x*cos(q) + A.y*sin(q))*B.i + \
           (-A.x*sin(q) + A.y*cos(q))*B.j + A.z*B.k
    assert simplify(express(A.x*A.i + A.y*A.j + A.z*A.k, B, \
                            variables=True)) == \
           B.x*B.i + B.y*B.j + B.z*B.k
    N = B.orient_new_axis('N', -q, B.k)
    assert N.scalar_map(A) == \
           {N.x: A.x, N.z: A.z, N.y: A.y}
    C = A.orient_new_axis('C', q, A.i + A.j + A.k)
    mapping = A.scalar_map(C)
    assert mapping[A.x].equals(C.x * (2 * cos(q) + 1) / 3 + C.y *
                               (-2 * sin(q + pi / 6) + 1) / 3 + C.z *
                               (-2 * cos(q + pi / 3) + 1) / 3)
    assert mapping[A.y].equals(C.x * (-2 * cos(q + pi / 3) + 1) / 3 + C.y *
                               (2 * cos(q) + 1) / 3 + C.z *
                               (-2 * sin(q + pi / 6) + 1) / 3)
    assert mapping[A.z].equals(C.x * (-2 * sin(q + pi / 6) + 1) / 3 + C.y *
                               (-2 * cos(q + pi / 3) + 1) / 3 + C.z *
                               (2 * cos(q) + 1) / 3)
    D = A.locate_new('D', a * A.i + b * A.j + c * A.k)
    assert D.scalar_map(A) == {D.z: A.z - c, D.x: A.x - a, D.y: A.y - b}
    E = A.orient_new_axis('E', a, A.k, a * A.i + b * A.j + c * A.k)
    assert A.scalar_map(E) == {
        A.z: E.z + c,
        A.x: E.x * cos(a) - E.y * sin(a) + a,
        A.y: E.x * sin(a) + E.y * cos(a) + b
    }
    assert E.scalar_map(A) == {
        E.x: (A.x - a) * cos(a) + (A.y - b) * sin(a),
        E.y: (-A.x + a) * sin(a) + (A.y - b) * cos(a),
        E.z: A.z - c
    }
    F = A.locate_new('F', Vector.zero)
    assert A.scalar_map(F) == {A.z: F.z, A.x: F.x, A.y: F.y}
예제 #6
0
def test_coordinate_vars():
    """
    Tests the coordinate variables functionality with respect to
    reorientation of coordinate systems.
    """
    A = CoordSysCartesian('A')
    assert BaseScalar('Ax', 0, A, ' ', ' ') == A.x
    assert BaseScalar('Ay', 1, A, ' ', ' ') == A.y
    assert BaseScalar('Az', 2, A, ' ', ' ') == A.z
    assert BaseScalar('Ax', 0, A, ' ', ' ').__hash__() == A.x.__hash__()
    assert isinstance(A.x, BaseScalar) and \
           isinstance(A.y, BaseScalar) and \
           isinstance(A.z, BaseScalar)
    assert A.scalar_map(A) == {A.x: A.x, A.y: A.y, A.z: A.z}
    assert A.x.system == A
    B = A.orient_new_axis('B', q, A.k)
    assert B.scalar_map(A) == {
        B.z: A.z,
        B.y: -A.x * sin(q) + A.y * cos(q),
        B.x: A.x * cos(q) + A.y * sin(q)
    }
    assert A.scalar_map(B) == {
        A.x: B.x * cos(q) - B.y * sin(q),
        A.y: B.x * sin(q) + B.y * cos(q),
        A.z: B.z
    }
    assert express(B.x, A, variables=True) == A.x * cos(q) + A.y * sin(q)
    assert express(B.y, A, variables=True) == -A.x * sin(q) + A.y * cos(q)
    assert express(B.z, A, variables=True) == A.z
    assert express(B.x*B.y*B.z, A, variables=True) == \
           A.z*(-A.x*sin(q) + A.y*cos(q))*(A.x*cos(q) + A.y*sin(q))
    assert express(B.x*B.i + B.y*B.j + B.z*B.k, A) == \
           (B.x*cos(q) - B.y*sin(q))*A.i + (B.x*sin(q) + \
           B.y*cos(q))*A.j + B.z*A.k
    assert simplify(express(B.x*B.i + B.y*B.j + B.z*B.k, A, \
                            variables=True)) == \
           A.x*A.i + A.y*A.j + A.z*A.k
    assert express(A.x*A.i + A.y*A.j + A.z*A.k, B) == \
           (A.x*cos(q) + A.y*sin(q))*B.i + \
           (-A.x*sin(q) + A.y*cos(q))*B.j + A.z*B.k
    assert simplify(express(A.x*A.i + A.y*A.j + A.z*A.k, B, \
                            variables=True)) == \
           B.x*B.i + B.y*B.j + B.z*B.k
    N = B.orient_new_axis('N', -q, B.k)
    assert N.scalar_map(A) == \
           {N.x: A.x, N.z: A.z, N.y: A.y}
    C = A.orient_new_axis('C', q, A.i + A.j + A.k)
    mapping = A.scalar_map(C)
    assert mapping[A.x] == 2*C.x*cos(q)/3 + C.x/3 - \
           2*C.y*sin(q + pi/6)/3 + C.y/3 - 2*C.z*cos(q + pi/3)/3 + C.z/3
    assert mapping[A.y] == -2*C.x*cos(q + pi/3)/3 + \
           C.x/3 + 2*C.y*cos(q)/3 + C.y/3 - 2*C.z*sin(q + pi/6)/3 + C.z/3
    assert mapping[A.z] == -2*C.x*sin(q + pi/6)/3 + C.x/3 - \
           2*C.y*cos(q + pi/3)/3 + C.y/3 + 2*C.z*cos(q)/3 + C.z/3
    D = A.locate_new('D', a * A.i + b * A.j + c * A.k)
    assert D.scalar_map(A) == {D.z: A.z - c, D.x: A.x - a, D.y: A.y - b}
    E = A.orient_new_axis('E', a, A.k, a * A.i + b * A.j + c * A.k)
    assert A.scalar_map(E) == {
        A.z: E.z + c,
        A.x: E.x * cos(a) - E.y * sin(a) + a,
        A.y: E.x * sin(a) + E.y * cos(a) + b
    }
    assert E.scalar_map(A) == {
        E.x: (A.x - a) * cos(a) + (A.y - b) * sin(a),
        E.y: (-A.x + a) * sin(a) + (A.y - b) * cos(a),
        E.z: A.z - c
    }
    F = A.locate_new('F', Vector.zero)
    assert A.scalar_map(F) == {A.z: F.z, A.x: F.x, A.y: F.y}
예제 #7
0
    def __new__(cls,
                name,
                vector_names=None,
                variable_names=None,
                location=None,
                rot_type=None,
                rot_amounts=None,
                rot_order='',
                parent=None):
        """
        The orientation/location parameters are necessary if this system
        is being defined at a certain orientation or location wrt another.

        For more information on the orientation parameters, please refer
        to the docs of orient_new method.

        Parameters
        ==========

        name : str
            The name of the new CoordSysCartesian instance.

        vector_names, variable_names : tuples/lists(optional)
            Tuples/Lists of 3 strings each, with custom names for base
            vectors and base scalars of the new system respectively.

        location : Vector
            The position vector of the new system's origin wrt the parent
            instance.

        rot_type : str ('Axis'/'Body'/'Quaternion'/'Space')
            The type of orientation matrix that is being created.

        rot_amounts : list OR value
            The quantities that the orientation matrix will be
            defined by.

        rot_order : str (Look at the docs of orient_new for more details)
            If applicable, the order of a series of rotations.

        parent : CoordSysCartesian
            The coordinate system wrt which the orientation/location
            (or both) is being defined.

        docstring of orient_new
        =======================

        """

        if not isinstance(name, string_types):
            raise TypeError("name should be a string")

        #If orientation information has been provided, calculate
        #the DCM accordingly
        from sympy.vector.vector import BaseVector, Vector
        if rot_type is not None:
            for i, v in enumerate(rot_amounts):
                if not isinstance(v, Vector):
                    rot_amounts[i] = sympify(v)
            rot_type = rot_type.upper()
            if rot_type == 'AXIS':
                parent_orient = _orient_axis(list(rot_amounts), rot_order,
                                             parent)
            elif rot_type == 'QUATERNION':
                parent_orient = _orient_quaternion(list(rot_amounts),
                                                   rot_order)
            elif rot_type == 'BODY':
                parent_orient = _orient_body(list(rot_amounts), rot_order)
            elif rot_type == 'SPACE':
                parent_orient = _orient_space(list(rot_amounts), rot_order)
            else:
                raise NotImplementedError('Rotation not implemented')
        else:
            if not (rot_amounts == None and rot_order == ''):
                raise ValueError("No rotation type provided")
            parent_orient = Matrix(eye(3))

        #If location information is not given, adjust the default
        #location as Vector.zero
        from sympy.vector.point import Point
        if parent is not None:
            if not isinstance(parent, CoordSysCartesian):
                raise TypeError("parent should be a " +
                                "CoordSysCartesian/None")
            if location is None:
                location = Vector.zero
            origin = parent.origin.locate_new(name + '.origin', location)
            arg_parent = parent
            arg_self = Symbol('default')
        else:
            origin = Point(name + '.origin')
            arg_parent = Symbol('default')
            arg_self = Symbol(name)

        #All systems that are defined as 'roots' are unequal, unless
        #they have the same name.
        #Systems defined at same orientation/position wrt the same
        #'parent' are equal, irrespective of the name.
        #This is true even if the same orientation is provided via
        #different methods like Axis/Body/Space/Quaternion.
        #However, coincident systems may be seen as unequal if
        #positioned/oriented wrt different parents, even though
        #they may actually be 'coincident' wrt the root system.
        obj = super(CoordSysCartesian,
                    cls).__new__(cls, arg_self, parent_orient, origin,
                                 arg_parent)
        obj._name = name

        #Initialize the base vectors
        if vector_names is None:
            vector_names = (name + '.i', name + '.j', name + '.k')
        obj._i = BaseVector(vector_names[0], 0, obj)
        obj._j = BaseVector(vector_names[1], 1, obj)
        obj._k = BaseVector(vector_names[2], 2, obj)

        #Initialize the base scalars
        if variable_names is None:
            variable_names = (name + '.x', name + '.y', name + '.z')
        obj._x = BaseScalar(variable_names[0], 0, obj)
        obj._y = BaseScalar(variable_names[1], 1, obj)
        obj._z = BaseScalar(variable_names[2], 2, obj)

        #Assign a Del operator instance
        from sympy.vector.deloperator import Del
        obj._del = Del(obj)

        #Assign params
        obj._parent = parent
        if obj._parent is not None:
            obj._root = obj._parent._root
        else:
            obj._root = obj

        obj._parent_rotation_matrix = parent_orient.T
        obj._origin = origin

        #Return the instance
        return obj