# Functioning of SymPy's Column module

The Column class implemented in PR #17122 enables the continuum mechanics module of SymPy to deal with column buckling related calculations. The Column module is currently able to calculate:

• The moment equation
• The deflection equation
• The slope equation

..for a column defined by a user.

### Below is an example usage of the Column Class:

``````# Column Class
>>> from sympy.physics.continuum_mechanics.column import Column
>>> from sympy import Symbol, symbols
>>> E, I, P = symbols('E, I, P', positive=True)

# defining an object of the Column class
>>> c = Column(3, E, I, 78000, top="pinned", bottom="pinned")

# checking the end-conditions
>>> c.end_conditions
{'bottom': 'pinned', 'top': 'pinned'}

# Specifying the boundary conditions of the column
>>> c.boundary_conditions
{'deflection': [(0, 0), (3, 0)], 'slope': [(0, 0)]}

# getting the moment equation
>>> c.moment()
78000*y(x)

# Calculating slope and deflection
>>> c.solve_slope_deflection()
>>> c.deflection()
C1*sin(20*sqrt(195)*x/(sqrt(E)*sqrt(I)))
>>> c.slope()
20*sqrt(195)*C1*cos(20*sqrt(195)*x/(sqrt(E)*sqrt(I)))/(sqrt(E)*sqrt(I))

pi**2*E*I/9
``````

# The Column class

The Column class is non-mutable, which means unlike the Beam class, a user cannot change the attributes of the class once they are defined along with the object definition. Therefore to change the attribute values one will have to define a new object.

## Reasons for creating a non-mutable class

• From a backward-compatibility perspective, it is always possible to adopt a different plan and add mutability later but not the other way around.
• Most things are immutable in SymPy which is useful for caching etc. Also, considering the Matrix module where allowing mutability has lead to many problems that are now impossible to fix without breaking backward compatibility.

# Working of the column class:

The governing equation for column buckling is:

E, I: Elastic modulus, Second moment of the column respectively

y: deflection

M: moment at a distance x from the bottom

If we determine the moment (or moment equation) of the column and place it in the above equation, we might be able to get the deflection by further solving the differential equation for y.

## Step-1: To determine the internal moment.

This is simply done by assuming deflection at any arbitrary cross-section at a distance x from the bottom to be y and then multiplying it by the load P. For eccentric load, another moment of magnitude P*e is added to the moment.

## Step-2:

This moment can then be substituted in the governing equation and the resulting differential equation can be solved using SymPy’s dsolve() for the deflection y.

# Applying different end-conditions

The above steps considers a simple example of a column pinned at both of its ends. But the end-condition of the column can vary, which will cause the moment equation to vary.

Currently, four basic end-conditions are implemented:

• Pinned-pinned
• Fixed-fixed
• Fixed-pinned
• One pinned-other free.

Depending on the supports the moment due to applied load would change as:

• Pinned-Pinned: no change in the moment

• Fixed-fixed: reaction moment M is included

• Fixed-pinned:

Here M is the restraint moment at B (which is fixed). To counter this, another moment is considered by applying a horizontal force F at point A.

• One pinned- other free:

# Solving for slope and critical load

Once we get the deflection equation we can solve for the slope by differentiating the deflection equation with respect to x. This is done by SymPy’s diff() function.

``````self._slope = self._deflection.diff(x)
``````

Critical load for single bow buckling condition can be easily determined by substituting the boundary conditions in the deflection equation and solving it for P i.e the load.

Note: Even if the user provides the applied load, during the entire calculation, we consider the load to be P. Whenever the moment(), slope(), deflection(), etc. methods are called the variable P is replaced with the user's value. This is done so that it is easier for us to calculate the critical load in the end.

``````defl_eqs = []
# taking last two bounndary conditions which are actually
# the initial boundary conditions.
for point, value in self._boundary_conditions['deflection'][-2:]:
defl_eqs.append(self._deflection.subs(x, point) - value)

# C1, C2 already solved, solve for P