Axial Loading
Axial loading is the simplest form of structural loading — forces applied along the axis of a member. Despite its simplicity, understanding axial loading deeply prepares you for more complex problems.
Deformation Under Axial Load
For a prismatic bar (uniform cross-section) under axial load:
$$\delta = \frac{PL}{AE}$$
Sponsored
Harshal got placed at Fiat Chrysler as Design Engineer
Watch his video testimonial on how the program helped him
Where:
- $\delta$ = Elongation or shortening (m)
- $P$ = Axial force (N)
- $L$ = Length (m)
- $A$ = Cross-sectional area (m²)
- $E$ = Young's modulus (Pa)
import numpy as np
def axial_deformation(P_kN, L_mm, A_mm2, E_GPa):
"""
Calculate axial deformation of a prismatic bar.
Parameters:
-----------
P_kN : float - Axial force in kN (positive = tension)
L_mm : float - Length in mm
A_mm2 : float - Cross-sectional area in mm²
E_GPa : float - Young's modulus in GPa
Returns:
--------
float : Deformation in mm
"""
# Convert to consistent units (N, mm, MPa)
P = P_kN * 1e3 # N
L = L_mm # mm
A = A_mm2 # mm²
E = E_GPa * 1e3 # MPa (= N/mm²)
delta = (P * L) / (A * E)
return delta
# Example: Steel rod
delta = axial_deformation(P_kN=50, L_mm=2000, A_mm2=500, E_GPa=200)
print(f"Elongation: {delta:.4f} mm")
Bars with Multiple Segments
When a bar has different cross-sections or materials, calculate deformation for each segment:
$$\delta_{total} = \sum_{i} \frac{P_i L_i}{A_i E_i}$$
Sponsored
Master CATIA, NX, LS-DYNA, HyperMesh, ANSYS
The exact tools used by Mahindra, Bosch & TATA ELXSI
def multi_segment_bar(segments):
"""
Analyze a bar with multiple segments.
Parameters:
-----------
segments : list of dicts
Each dict: {'P_kN', 'L_mm', 'A_mm2', 'E_GPa', 'name'}
Returns:
--------
dict with total deformation and segment details
"""
results = []
total_delta = 0
for seg in segments:
delta = axial_deformation(
seg['P_kN'], seg['L_mm'], seg['A_mm2'], seg['E_GPa']
)
stress = (seg['P_kN'] * 1e3) / seg['A_mm2'] # MPa
results.append({
'name': seg.get('name', 'Segment'),
'delta_mm': delta,
'stress_MPa': stress
})
total_delta += delta
return {
'segments': results,
'total_delta_mm': total_delta
}
# Example: Stepped shaft
segments = [
{'name': 'AB (Steel)', 'P_kN': 100, 'L_mm': 500, 'A_mm2': 800, 'E_GPa': 200},
{'name': 'BC (Steel)', 'P_kN': 60, 'L_mm': 400, 'A_mm2': 500, 'E_GPa': 200},
{'name': 'CD (Aluminum)', 'P_kN': 60, 'L_mm': 300, 'A_mm2': 500, 'E_GPa': 70}
]
result = multi_segment_bar(segments)
print("Multi-Segment Bar Analysis:")
print("-" * 50)
for seg in result['segments']:
print(f"{seg['name']}:")
print(f" Stress: {seg['stress_MPa']:.2f} MPa")
print(f" Deformation: {seg['delta_mm']:.4f} mm")
print("-" * 50)
print(f"Total deformation: {result['total_delta_mm']:.4f} mm")
Statically Indeterminate Systems
When a structure has more supports than needed for equilibrium, it's statically indeterminate. We need both equilibrium AND compatibility equations.
Example: Bar Fixed at Both Ends
def bar_fixed_both_ends(P_kN, a_mm, L_mm, A_mm2, E_GPa):
"""
Bar fixed at both ends with point load P at distance 'a' from left.
P
↓
|========|========|
A a ↑ b B
(L-a)
Reactions: RA at A, RB at B
"""
L = L_mm
a = a_mm
b = L - a
P = P_kN
# Compatibility: delta_total = 0
# delta_AC - delta_CB = 0 (considering directions)
# From equilibrium: RA + RB = P
# From compatibility: RA*a/(AE) = RB*b/(AE)
# Solving: RA*a = RB*b and RA + RB = P
RB = P * a / L
RA = P * b / L
# Stresses
stress_AC = RA * 1e3 / A_mm2 # MPa
stress_CB = RB * 1e3 / A_mm2 # MPa
print(f"Bar Fixed at Both Ends")
print(f"Load P = {P_kN} kN at distance a = {a_mm} mm from A")
print(f"Total length L = {L_mm} mm")
print("-" * 40)
print(f"Reaction at A (RA): {RA:.2f} kN")
print(f"Reaction at B (RB): {RB:.2f} kN")
print(f"Stress in AC: {stress_AC:.2f} MPa (Compression)")
print(f"Stress in CB: {stress_CB:.2f} MPa (Tension)")
return {'RA': RA, 'RB': RB, 'stress_AC': stress_AC, 'stress_CB': stress_CB}
# Example
bar_fixed_both_ends(
P_kN=100,
a_mm=400,
L_mm=1000,
A_mm2=500,
E_GPa=200
)
Thermal Stress
When temperature changes, materials expand or contract:
$$\delta_T = \alpha \cdot \Delta T \cdot L$$
Sponsored
Abhishek landed his dream job at TATA ELXSI
From learning simulations to working at an industry leader
Where:
- $\alpha$ = Coefficient of thermal expansion (1/°C)
- $\Delta T$ = Temperature change (°C)
- $L$ = Original length
If free to expand → no stress, only strain
If constrained → thermal stress develops
| Material | α (×10⁻⁶ /°C) |
|---|
| Steel | 12 |
| Aluminum | 23 |
| Copper | 17 |
| Concrete | 10 |
| Brass | 19 |
def thermal_stress_analysis(
L_mm, A_mm2, E_GPa, alpha_per_C, delta_T, constraint='fixed'
):
"""
Analyze thermal stress in a bar.
Parameters:
-----------
L_mm : float - Original length in mm
A_mm2 : float - Cross-sectional area in mm²
E_GPa : float - Young's modulus in GPa
alpha_per_C : float - Thermal expansion coefficient (1/°C)
delta_T : float - Temperature change in °C
constraint : str - 'free', 'fixed', or 'partial'
Returns:
--------
dict with thermal expansion, stress, and strain
"""
E = E_GPa * 1e3 # MPa
# Free thermal expansion
delta_free = alpha_per_C * delta_T * L_mm
if constraint == 'free':
# No constraint - free expansion, no stress
return {
'thermal_strain': alpha_per_C * delta_T,
'thermal_expansion_mm': delta_free,
'mechanical_strain': 0,
'stress_MPa': 0,
'net_deformation_mm': delta_free
}
elif constraint == 'fixed':
# Fully constrained - no expansion allowed
# Mechanical strain must cancel thermal strain
thermal_strain = alpha_per_C * delta_T
mechanical_strain = -thermal_strain # Constrained
stress = E * mechanical_strain # Will be compressive if heating
return {
'thermal_strain': thermal_strain,
'thermal_expansion_mm': delta_free,
'mechanical_strain': mechanical_strain,
'stress_MPa': stress,
'net_deformation_mm': 0
}
# Example: Steel bar heated while fixed at both ends
print("Case 1: Free to expand")
result_free = thermal_stress_analysis(
L_mm=1000, A_mm2=500, E_GPa=200,
alpha_per_C=12e-6, delta_T=100, constraint='free'
)
print(f" Thermal expansion: {result_free['thermal_expansion_mm']:.3f} mm")
print(f" Stress: {result_free['stress_MPa']:.1f} MPa")
print("\nCase 2: Fixed at both ends")
result_fixed = thermal_stress_analysis(
L_mm=1000, A_mm2=500, E_GPa=200,
alpha_per_C=12e-6, delta_T=100, constraint='fixed'
)
print(f" Would-be expansion: {result_fixed['thermal_expansion_mm']:.3f} mm")
print(f" Actual deformation: {result_fixed['net_deformation_mm']:.3f} mm")
print(f" Thermal stress: {result_fixed['stress_MPa']:.1f} MPa (Compressive)")
Composite Bars (Parallel)
When two materials are bonded together and loaded:
def composite_bar_parallel(materials, total_load_kN, L_mm):
"""
Analyze composite bar with materials in parallel.
Both materials have same strain but different stresses.
Parameters:
-----------
materials : list of dicts
Each: {'name', 'A_mm2', 'E_GPa'}
total_load_kN : float - Total applied load
L_mm : float - Length of bar
"""
# Calculate equivalent stiffness
sum_AE = sum(m['A_mm2'] * m['E_GPa'] * 1e3 for m in materials)
# Common strain
P = total_load_kN * 1e3 # N
# P = sum(stress_i * A_i) = sum(E_i * strain * A_i) = strain * sum(AE)
strain = P / sum_AE
# Deformation
delta = strain * L_mm
print(f"Composite Bar Analysis (Parallel)")
print(f"Total load: {total_load_kN} kN, Length: {L_mm} mm")
print("-" * 50)
print(f"Common strain: {strain:.6f} ({strain*100:.4f}%)")
print(f"Total deformation: {delta:.4f} mm")
print("\nLoad sharing:")
for m in materials:
E = m['E_GPa'] * 1e3 # MPa
stress = E * strain
load = stress * m['A_mm2'] / 1e3 # kN
print(f" {m['name']}:")
print(f" Stress: {stress:.2f} MPa")
print(f" Load carried: {load:.2f} kN ({load/total_load_kN*100:.1f}%)")
return {'strain': strain, 'delta_mm': delta}
# Example: Steel rod inside aluminum tube
materials = [
{'name': 'Steel core', 'A_mm2': 500, 'E_GPa': 200},
{'name': 'Aluminum sleeve', 'A_mm2': 800, 'E_GPa': 70}
]
composite_bar_parallel(materials, total_load_kN=150, L_mm=500)
Visualization: Stress Distribution
import numpy as np
import matplotlib.pyplot as plt
def visualize_stepped_shaft():
"""Visualize stress distribution in a stepped shaft."""
# Shaft geometry (lengths in mm, forces in kN)
segments = [
{'L': 200, 'd': 40, 'P': 80}, # Section 1
{'L': 300, 'd': 30, 'P': 80}, # Section 2
{'L': 150, 'd': 50, 'P': 50}, # Section 3 (load reduced)
]
fig, axes = plt.subplots(2, 1, figsize=(12, 8), height_ratios=[1, 1.5])
# Calculate stresses and positions
x_positions = []
stresses = []
x = 0
for seg in segments:
A = np.pi * (seg['d'] / 2) ** 2
sigma = seg['P'] * 1e3 / A # MPa
x_positions.extend([x, x + seg['L']])
stresses.extend([sigma, sigma])
x += seg['L']
# Plot 1: Shaft geometry (side view)
ax1 = axes[0]
x = 0
for i, seg in enumerate(segments):
rect = plt.Rectangle(
(x, -seg['d']/2), seg['L'], seg['d'],
facecolor=plt.cm.Blues(0.3 + 0.2*i),
edgecolor='black', linewidth=2
)
ax1.add_patch(rect)
# Dimension
ax1.annotate(
f"Ø{seg['d']}",
xy=(x + seg['L']/2, 0),
fontsize=10, ha='center'
)
x += seg['L']
# Force arrows
ax1.annotate('', xy=(0, 0), xytext=(-40, 0),
arrowprops=dict(arrowstyle='->', lw=2, color='red'))
ax1.text(-50, 10, f"P₁={segments[0]['P']}kN", fontsize=10, color='red')
ax1.set_xlim(-60, 700)
ax1.set_ylim(-40, 40)
ax1.set_aspect('equal')
ax1.set_title('Stepped Shaft Geometry', fontsize=12)
ax1.axis('off')
# Plot 2: Stress distribution
ax2 = axes[1]
ax2.fill_between(x_positions, 0, stresses, alpha=0.3, color='blue')
ax2.plot(x_positions, stresses, 'b-', linewidth=2)
ax2.set_xlabel('Position along shaft (mm)', fontsize=11)
ax2.set_ylabel('Stress (MPa)', fontsize=11)
ax2.set_title('Axial Stress Distribution', fontsize=12)
ax2.grid(True, alpha=0.3)
ax2.set_xlim(0, 650)
plt.tight_layout()
plt.show()
visualize_stepped_shaft()
Key Takeaways
- Basic deformation formula: $\delta = PL/(AE)$
- Multiple segments: Sum deformations, watch force directions
- Statically indeterminate: Use equilibrium + compatibility
- Thermal stress: $\sigma_T = E \cdot \alpha \cdot \Delta T$ (when constrained)
- Composite bars: Same strain, different stresses
Next lesson: We'll explore stress transformation and the powerful Mohr's Circle visualization.