# Source code for sympy.physics.mechanics.body

from sympy.core.backend import Symbol
from sympy.physics.mechanics import (RigidBody, Particle, ReferenceFrame,
inertia)
from sympy.physics.vector import Point, Vector

__all__ = ['Body']

[docs]class Body(RigidBody, Particle):
"""
Body is a common representation of either a RigidBody or a Particle SymPy
object depending on what is passed in during initialization. If a mass is
passed in and central_inertia is left as None, the Particle object is
created. Otherwise a RigidBody object will be created.

The attributes that Body possesses will be the same as a Particle instance
or a Rigid Body instance depending on which was created. Additional
attributes are listed below.

Attributes
==========

name : string
The body's name
masscenter : Point
The point which represents the center of mass of the rigid body
frame : ReferenceFrame
The reference frame which the body is fixed in
mass : Sympifyable
The body's mass
The body's inertia around its center of mass. This attribute is specific
to the rigid body form of Body and is left undefined for the Particle
form
This list contains information on the different loads acting on the
Body. Forces are listed as a (point, vector) tuple and torques are
listed as (reference frame, vector) tuples.

Parameters
==========

name : String
Defines the name of the body. It is used as the base for defining
body specific properties.
masscenter : Point, optional
A point that represents the center of mass of the body or particle.
If no point is given, a point is generated.
mass : Sympifyable, optional
A Sympifyable object which represents the mass of the body. If no
mass is passed, one is generated.
frame : ReferenceFrame, optional
The ReferenceFrame that represents the reference frame of the body.
If no frame is given, a frame is generated.
Central inertia dyadic of the body. If none is passed while creating
RigidBody, a default inertia is generated.

Examples
========

Default behaviour. This results in the creation of a RigidBody object for
which the mass, mass center, frame and inertia attributes are given default
values. ::

>>> from sympy.physics.mechanics import Body
>>> body = Body('name_of_body')

This next example demonstrates the code required to specify all of the
values of the Body object. Note this will also create a RigidBody version of
the Body object. ::

>>> from sympy import Symbol
>>> from sympy.physics.mechanics import ReferenceFrame, Point, inertia
>>> from sympy.physics.mechanics import Body
>>> mass = Symbol('mass')
>>> masscenter = Point('masscenter')
>>> frame = ReferenceFrame('frame')
>>> ixx = Symbol('ixx')
>>> body_inertia = inertia(frame, ixx, 0, 0)
>>> body = Body('name_of_body', masscenter, mass, frame, body_inertia)

The minimal code required to create a Particle version of the Body object
involves simply passing in a name and a mass. ::

>>> from sympy import Symbol
>>> from sympy.physics.mechanics import Body
>>> mass = Symbol('mass')
>>> body = Body('name_of_body', mass=mass)

The Particle version of the Body object can also receive a masscenter point
and a reference frame, just not an inertia.
"""

def __init__(self, name, masscenter=None, mass=None, frame=None,
central_inertia=None):

self.name = name

if frame is None:
frame = ReferenceFrame(name + '_frame')

if masscenter is None:
masscenter = Point(name + '_masscenter')

if central_inertia is None and mass is None:
ixx = Symbol(name + '_ixx')
iyy = Symbol(name + '_iyy')
izz = Symbol(name + '_izz')
izx = Symbol(name + '_izx')
ixy = Symbol(name + '_ixy')
iyz = Symbol(name + '_iyz')
_inertia = (inertia(frame, ixx, iyy, izz, ixy, iyz, izx),
masscenter)
else:
_inertia = (central_inertia, masscenter)

if mass is None:
_mass = Symbol(name + '_mass')
else:
_mass = mass

masscenter.set_vel(frame, 0)

# If user passes masscenter and mass then a particle is created
# otherwise a rigidbody. As a result a body may or may not have inertia.
if central_inertia is None and mass is not None:
self.frame = frame
self.masscenter = masscenter
Particle.__init__(self, name, masscenter, _mass)
else:
RigidBody.__init__(self, name, masscenter, frame, _mass, _inertia)

[docs]    def apply_force(self, vec, point=None):
"""
Adds a force to a point (center of mass by default) on the body.

Parameters
==========

vec: Vector
Defines the force vector. Can be any vector w.r.t any frame or
combinations of frames.
point: Point, optional
Defines the point on which the force is applied. Default is the
Body's center of mass.

Example
=======

The first example applies a gravitational force in the x direction of
Body's frame to the body's center of mass. ::

>>> from sympy import Symbol
>>> from sympy.physics.mechanics import Body
>>> body = Body('body')
>>> g = Symbol('g')
>>> body.apply_force(body.mass * g * body.frame.x)

To apply force to any other point than center of mass, pass that point
as well. This example applies a gravitational force to a point a distance
l from the body's center of mass in the y direction. The force is again
applied in the x direction. ::

>>> from sympy import Symbol
>>> from sympy.physics.mechanics import Body
>>> body = Body('body')
>>> g = Symbol('g')
>>> l = Symbol('l')
>>> point = body.masscenter.locatenew('force_point', l *
...                                   body.frame.y)
>>> body.apply_force(body.mass * g * body.frame.x, point)

"""

if not isinstance(point, Point):
if point is None:
point = self.masscenter  # masscenter
else:
raise TypeError("A Point must be supplied to apply force to.")
if not isinstance(vec, Vector):
raise TypeError("A Vector must be supplied to apply force.")

[docs]    def apply_torque(self, vec):
"""
Adds a torque to the body.

Parameters
==========

vec: Vector
Defines the torque vector. Can be any vector w.r.t any frame or
combinations of frame.

Example
=======

This example adds a simple torque around the body's z axis. ::

>>> from sympy import Symbol
>>> from sympy.physics.mechanics import Body
>>> body = Body('body')
>>> T = Symbol('T')
>>> body.apply_torque(T * body.frame.z)
"""

if not isinstance(vec, Vector):
raise TypeError("A Vector must be supplied to add torque.")