Spaces:
Sleeping
Sleeping
File size: 5,406 Bytes
6a86ad5 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 |
from abc import ABC
from collections import namedtuple
from sympy.physics.mechanics.body_base import BodyBase
from sympy.physics.vector import Vector, ReferenceFrame, Point
__all__ = ['LoadBase', 'Force', 'Torque']
class LoadBase(ABC, namedtuple('LoadBase', ['location', 'vector'])):
"""Abstract base class for the various loading types."""
def __add__(self, other):
raise TypeError(f"unsupported operand type(s) for +: "
f"'{self.__class__.__name__}' and "
f"'{other.__class__.__name__}'")
def __mul__(self, other):
raise TypeError(f"unsupported operand type(s) for *: "
f"'{self.__class__.__name__}' and "
f"'{other.__class__.__name__}'")
__radd__ = __add__
__rmul__ = __mul__
class Force(LoadBase):
"""Force acting upon a point.
Explanation
===========
A force is a vector that is bound to a line of action. This class stores
both a point, which lies on the line of action, and the vector. A tuple can
also be used, with the location as the first entry and the vector as second
entry.
Examples
========
A force of magnitude 2 along N.x acting on a point Po can be created as
follows:
>>> from sympy.physics.mechanics import Point, ReferenceFrame, Force
>>> N = ReferenceFrame('N')
>>> Po = Point('Po')
>>> Force(Po, 2 * N.x)
(Po, 2*N.x)
If a body is supplied, then the center of mass of that body is used.
>>> from sympy.physics.mechanics import Particle
>>> P = Particle('P', point=Po)
>>> Force(P, 2 * N.x)
(Po, 2*N.x)
"""
def __new__(cls, point, force):
if isinstance(point, BodyBase):
point = point.masscenter
if not isinstance(point, Point):
raise TypeError('Force location should be a Point.')
if not isinstance(force, Vector):
raise TypeError('Force vector should be a Vector.')
return super().__new__(cls, point, force)
def __repr__(self):
return (f'{self.__class__.__name__}(point={self.point}, '
f'force={self.force})')
@property
def point(self):
return self.location
@property
def force(self):
return self.vector
class Torque(LoadBase):
"""Torque acting upon a frame.
Explanation
===========
A torque is a free vector that is acting on a reference frame, which is
associated with a rigid body. This class stores both the frame and the
vector. A tuple can also be used, with the location as the first item and
the vector as second item.
Examples
========
A torque of magnitude 2 about N.x acting on a frame N can be created as
follows:
>>> from sympy.physics.mechanics import ReferenceFrame, Torque
>>> N = ReferenceFrame('N')
>>> Torque(N, 2 * N.x)
(N, 2*N.x)
If a body is supplied, then the frame fixed to that body is used.
>>> from sympy.physics.mechanics import RigidBody
>>> rb = RigidBody('rb', frame=N)
>>> Torque(rb, 2 * N.x)
(N, 2*N.x)
"""
def __new__(cls, frame, torque):
if isinstance(frame, BodyBase):
frame = frame.frame
if not isinstance(frame, ReferenceFrame):
raise TypeError('Torque location should be a ReferenceFrame.')
if not isinstance(torque, Vector):
raise TypeError('Torque vector should be a Vector.')
return super().__new__(cls, frame, torque)
def __repr__(self):
return (f'{self.__class__.__name__}(frame={self.frame}, '
f'torque={self.torque})')
@property
def frame(self):
return self.location
@property
def torque(self):
return self.vector
def gravity(acceleration, *bodies):
"""
Returns a list of gravity forces given the acceleration
due to gravity and any number of particles or rigidbodies.
Example
=======
>>> from sympy.physics.mechanics import ReferenceFrame, Particle, RigidBody
>>> from sympy.physics.mechanics.loads import gravity
>>> from sympy import symbols
>>> N = ReferenceFrame('N')
>>> g = symbols('g')
>>> P = Particle('P')
>>> B = RigidBody('B')
>>> gravity(g*N.y, P, B)
[(P_masscenter, P_mass*g*N.y),
(B_masscenter, B_mass*g*N.y)]
"""
gravity_force = []
for body in bodies:
if not isinstance(body, BodyBase):
raise TypeError(f'{type(body)} is not a body type')
gravity_force.append(Force(body.masscenter, body.mass * acceleration))
return gravity_force
def _parse_load(load):
"""Helper function to parse loads and convert tuples to load objects."""
if isinstance(load, LoadBase):
return load
elif isinstance(load, tuple):
if len(load) != 2:
raise ValueError(f'Load {load} should have a length of 2.')
if isinstance(load[0], Point):
return Force(load[0], load[1])
elif isinstance(load[0], ReferenceFrame):
return Torque(load[0], load[1])
else:
raise ValueError(f'Load not recognized. The load location {load[0]}'
f' should either be a Point or a ReferenceFrame.')
raise TypeError(f'Load type {type(load)} not recognized as a load. It '
f'should be a Force, Torque or tuple.')
|