The Column class implemented in PR #17122 enables the continuum mechanics module of SymPy to deal with column buckling related calculations. The Column module can calculate the moment equation, deflection equation, slope equation and the critical load for a column defined by a user.

Example use-case of Column class:

```>>> from sympy.physics.continuum_mechanics.column import Column
>>> from sympy import Symbol, symbols
>>> E, I, P = symbols('E, I, P', positive=True)
>>> c = Column(3, E, I, 78000, top="pinned", bottom="pinned")
>>> c.end_conditions
{'bottom': 'pinned', 'top': 'pinned'}
>>> c.boundary_conditions
{'deflection': [(0, 0), (3, 0)], 'slope': [(0, 0)]}
>>> c.moment()
78000*y(x)
>>> 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. Matrix is an example where allowing mutability has lead to many problems that are now impossible to fix without breaking backwards compatibility.

## Working of the column class:

The governing equation for column buckling is:

If we determine the the moment equation of the column ,on which the buckling load is applied, 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 as y and then multiplying this by the load P and 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 to vary.

Currently four basic supports 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 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 the 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 users 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