Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Beam bending module. #11266

Closed
wants to merge 27 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
17c5bb0
Initiated PointLoad and DistributedLoad.
sampadsaha5 Jun 21, 2016
90a45f0
Added the Beam Class.
sampadsaha5 Jun 23, 2016
4334e92
Added the property in PointLoad.
sampadsaha5 Jun 24, 2016
396ed0d
Added the property in DLoad.
sampadsaha5 Jun 24, 2016
ed41724
Made the extisting attributes private in Dload.
sampadsaha5 Jun 24, 2016
dcae693
Added some tests to Beams.
sampadsaha5 Jun 28, 2016
c0735b9
Added Boundary Conditions to beam.
sampadsaha5 Jul 1, 2016
b3410ab
Merge branch 'master' into beam_bending
sampadsaha5 Jul 1, 2016
bbaf2dc
Added test and docstring for apply method.
sampadsaha5 Jul 2, 2016
297ca46
Rectified the mistake
sampadsaha5 Jul 2, 2016
cebf853
Replaced E with elastic_modulus.
sampadsaha5 Jul 4, 2016
e32ab05
Replaced I with second_moment.
sampadsaha5 Jul 4, 2016
28da1aa
Modified the docstring.
sampadsaha5 Jul 4, 2016
9743116
Replaced BoundaryConditions with boundary_conditions.
sampadsaha5 Jul 4, 2016
4a6ca30
Replaced shear with slope.
sampadsaha5 Jul 4, 2016
dba0ac4
Renamed the bcs method.
sampadsaha5 Jul 4, 2016
784dbeb
Added some dummy methods.
sampadsaha5 Jul 5, 2016
0226962
Added functionality to provide moment bcs explicitly.
sampadsaha5 Jul 5, 2016
7dc6f3f
Added functionality to provide slope bcs explicitly.
sampadsaha5 Jul 5, 2016
e297fda
apply_deflection_boundary_conditions.
sampadsaha5 Jul 5, 2016
9d742de
boundary_condition as a dict at init.
sampadsaha5 Jul 5, 2016
d5c83ae
Made apply_boundary_conditions more user friendly.
sampadsaha5 Jul 5, 2016
815294b
Added some tests and boundary_condition method.
sampadsaha5 Jul 5, 2016
53eedb2
Modified the strcture of DL.
sampadsaha5 Jul 6, 2016
dfc2c66
Updated the test.
sampadsaha5 Jul 6, 2016
0aca1cc
Relocated the module.
sampadsaha5 Jul 9, 2016
b3bfee5
Rectified the mistake.
sampadsaha5 Jul 10, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions sympy/physics/continuum_mechanics/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .beam import Beam, PointLoad, DistributedLoad
343 changes: 343 additions & 0 deletions sympy/physics/continuum_mechanics/beam.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,343 @@
"""
This module can be used to solve beam bending problems in mechanics.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"solve beam..." > "solve 2D beam bending problems with singularity functions"


"""

from __future__ import print_function, division

from sympy.printing import sstr
from sympy.physics.mechanics import Point
from sympy import sympify


class Beam(object):

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no space here

"""
A Beam is a structural element that is capable of withstanding load
primarily by resisting against bending.
Beams are characterized by their profile (Second moment of area),
their length, and their material.

Parameters
==========
length : Sympifyable
A SymPy expression representing the Beam's length.
elastic_modulus : Sympifyable
A SymPy expression representing the Beam's Modulus of Elasticity.
It is a measure of the stiffness of the Beam material.
second_moment : Sympifyable
A SymPy expression representing the Beam's Second moment of area.
It is a geometrical property of an area which reflects how its
points are distributed with regard to an arbitrary axis.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be "with respect to its neutral axis".


Examples
========
>>> from sympy.physics.continuum_mechanics.beam import Beam
>>> from sympy import Symbol
>>> E = Symbol('E')
>>> I = Symbol('I')
>>> Beam(1, E, I)
Beam(1, E, I)

"""

def __init__(self, length, elastic_modulus, second_moment):
self._length = length
self._elastic_modulus = elastic_modulus
self._second_moment = second_moment
self._boundary_conditions = {'deflection': [], 'moment': [], 'slope': []}

def __str__(self):
str_sol = 'Beam(%s, %s, %s)' % (sstr(self._length), sstr(self._elastic_modulus), sstr(self._second_moment))
return str_sol

__repr__ = __str__

@property
def length(self):
"""Length of the Beam."""
return self._length

@length.setter
def length(self, l):
self._length = sympify(l)

@property
def elastic_modulus(self):
"""Young's Modulus of the Beam. """
return self._elastic_modulus

@elastic_modulus.setter
def elastic_modulus(self, e):
self._elastic_modulus = sympify(e)

@property
def second_moment(self):
"""Second moment of area of the Beam. """
return self._second_moment

@second_moment.setter
def second_moment(self, i):
self._second_moment = sympify(i)

def apply_boundary_conditions(self, **bcs):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since there are only three kwargs it would be better if this was:

def apply_boundary_conditions(self, slope=None, deflection=None, moment=None)

This also begs the question why this is needed. If you use collections.defaultdict for list the user could simply do something like:

beam.boundary_conditions['moment'].append((3, 5))

"""
Takes the boundary conditions of the beam bending problem as input.
The boundary conditions should be passed as keyworded arguments.
It is suggested to use ``moment``, ``slope`` and ``deflection`` as the
keywords while providing the boundary conditions of the moment curve,
slope curve and the deflection curve respectively as inputs.

Outputs a dictionary.

Examples
========
>>> from sympy.physics.continuum_mechanics.beam import Beam
>>> from sympy import Symbol
>>> E = Symbol('E')
>>> I = Symbol('I')
>>> b = Beam(4, E, I)
>>> bcs = b.apply_boundary_conditions(moment = [(0, 4), (4, 0)], deflection = [(0, 2)], slope = [(0, 1)])
>>> bcs
{'deflection': [(0, 2)], 'moment': [(0, 4), (4, 0)], 'slope': [(0, 1)]}
>>> bcs['moment']
[(0, 4), (4, 0)]

"""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This docstring doesn't yet explain what [(0, 4), (4, 0)] is. This is a list of two tuples and the numbers must represent something. What do they represent?

for m_bcs in bcs['moment']:
self._boundary_conditions['moment'].append(m_bcs)
for s_bcs in bcs['slope']:
self._boundary_conditions['slope'].append(s_bcs)
for d_bcs in bcs['deflection']:
self._boundary_conditions['deflection'].append(d_bcs)
return self._boundary_conditions
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if they supply an incorrent keyword? Mispelling or something not relevant? You should provide an error if this happens.


def apply_moment_boundary_conditions(self, *m_bcs):
"""
Takes only the moment boundary conditions as input.

Examples
========
>>> from sympy.physics.continuum_mechanics.beam import Beam
>>> from sympy import Symbol
>>> E = Symbol('E')
>>> I = Symbol('I')
>>> b = Beam(4, E, I)
>>> bcs = b.apply_boundary_conditions(moment = [(0, 4), (4, 0)], deflection = [(0, 2)], slope = [(0, 1)])
>>> bcs
{'deflection': [(0, 2)], 'moment': [(0, 4), (4, 0)], 'slope': [(0, 1)]}
>>> b.apply_moment_boundary_conditions((4, 3), (5, 0))
[(0, 4), (4, 0), (4, 3), (5, 0)]

"""
for bcs in m_bcs:
self._boundary_conditions['moment'].append(bcs)
return self._boundary_conditions['moment']

def apply_slope_boundary_conditions(self, *s_bcs):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be:

apply_slope_boundary_conditions(self, location, value)

and apply only one at a time.

"""
Takes only the slope boundary conditions as input.

Examples
========
>>> from sympy.physics.continuum_mechanics.beam import Beam
>>> from sympy import Symbol
>>> E = Symbol('E')
>>> I = Symbol('I')
>>> b = Beam(4, E, I)
>>> bcs = b.apply_boundary_conditions(moment = [(0, 4), (4, 0)], deflection = [(0, 2)], slope = [(0, 1)])
>>> bcs
{'deflection': [(0, 2)], 'moment': [(0, 4), (4, 0)], 'slope': [(0, 1)]}
>>> b.apply_slope_boundary_conditions((4, 3), (5, 0))
[(0, 1), (4, 3), (5, 0)]

"""
for bcs in s_bcs:
self._boundary_conditions['slope'].append(bcs)
return self._boundary_conditions['slope']

def apply_deflection_boundary_conditions(self, *d_bcs):
"""
Takes only the slope boundary conditions as input.

Examples
========
>>> from sympy.physics.continuum_mechanics.beam import Beam
>>> from sympy import Symbol
>>> E = Symbol('E')
>>> I = Symbol('I')
>>> b = Beam(4, E, I)
>>> bcs = b.apply_boundary_conditions(moment = [(0, 4), (4, 0)], deflection = [(0, 2)], slope = [(0, 1)])
>>> bcs
{'deflection': [(0, 2)], 'moment': [(0, 4), (4, 0)], 'slope': [(0, 1)]}
>>> b.apply_deflection_boundary_conditions((4, 3), (5, 0))
[(0, 2), (4, 3), (5, 0)]

"""
for bcs in d_bcs:
self._boundary_conditions['deflection'].append(bcs)
return self._boundary_conditions['deflection']

def boundary_conditions(self):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@property?

"""
Returns a dictionary of boundary conditions applied on the beam.
"""
return self._boundary_conditions

def apply_loads(self, *loads):
"""
Takes PointLoad and DistributedLoad as input. This method would apply
the loads, that are passed as arguments, to the beam object. Internally
this method would represent the PointLoads and DistributedLoads using
Singularity Functions.

Examples
========

"""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs code.



class PointLoad(object):
"""A Point Load.
Copy link
Member

@moorepants moorepants Jul 13, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A load (force or moment) applied at a point.


A load applied to a single, specific point. It is also known as a
concentrated load.

Parameters
==========
location : Point
The specific point of the applied load.
value : Sympifyable
A SymPy expression representing the value of the applied load.

Examples
========
>>> from sympy.physics.continuum_mechanics.beam import PointLoad
>>> from sympy.physics.mechanics import Point
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this should be tied to Point in mechanics. I don't think it should be tied to a Point object at all. We also have a geometry module with 2d points which would be more appropriate. But I don't see why this overhead is needed at all

>>> p = Point('4')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't even how Point works!

>>> PointLoad(location = p, value = -4)
PointLoad(4, -4, Load)

A Moment can be defined just by passing moment=True as an argument.

>>> PointLoad(location = p, value = -4, moment=True)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think this API is better than:

MomentPointLoad()

and

ForcePointLoad()

Or PointForce() PointMoment()

PointLoad(4, -4, Moment)

"""

def __init__(self, location, value, moment=False):
self._location = location
self._value = value
self._moment = moment

def __str__(self):
if self.moment:
str_sol = 'PointLoad(%s, %s, %s)' % (sstr(self.location), sstr(self.value), sstr('Moment'))
return str_sol
str_sol = 'PointLoad(%s, %s, %s)' % (sstr(self.location), sstr(self.value), sstr('Load'))
return str_sol

__repr__ = __str__

@property
def location(self):
"""Location of the applied Point Load."""
return self._location

@location.setter
def location(self, l):
if not isinstance(l, Point):
raise TypeError("PointLoad location attribute must be a Point object.")
self._location = l

@property
def value(self):
"""Value of the applied Point Load. """
return self._value

@value.setter
def value(self, v):
self._value = sympify(v)

@property
def moment(self):
"""Stores whether a Point Load is a load or a couple. """
return self._moment

@moment.setter
def moment(self, m):
if not isinstance(m, bool):
raise TypeError("PointLoad moment attribute must be a bool object.")
self._moment = m


class DistributedLoad(object):

"""A Distributed Load.

A load applied across a length instead of at one point.

Parameters
==========
start : Point
The starting point of the applied load.
order : Sympifyable
The order of the applied load.
value : Sympifyable
A SymPy expression representing the value of the applied load.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd order them as: value, start, order

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd order them as: value, start, order.


Examples
========
>>> from sympy.physics.continuum_mechanics.beam import DistributedLoad
>>> from sympy.physics.mechanics import Point
>>> from sympy import Symbol
>>> a = Point('4')
>>> b = 2
>>> DistributedLoad(start = a, order = b, value = 2)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you going to support start and end with this where it creates two distributed loads, one that makes a composite of two?

DistributedLoad(4, 2, 2)

"""

def __init__(self, start, order, value):

if isinstance(start, Point):
self._start = start
else:
raise TypeError("DistributedLoad start attribute must be a Point object.")
self._order = order
self._value = value

def __str__(self):
str_sol = 'DistributedLoad(%s, %s, %s)' % (sstr(self.start), sstr(self.order), sstr(self.value))
return str_sol

__repr__ = __str__

@property
def start(self):
"""The starting point of the applied load."""
return self._start

@start.setter
def start(self, s):
if not isinstance(s, Point):
raise TypeError("DistributedLoad start attribute must be a Point object.")
self._start = s

@property
def order(self):
"""The order of the applied load."""
return self._order

@order.setter
def order(self, o):
self._order = sympify(o)

@property
def value(self):
"""The value of the applied load."""
return self._value

@value.setter
def value(self, v):
self._value = sympify(v)
Empty file.
Loading