Combined Loading | Strength of Materials with Python | Skill-Lync Resources

50% OFF - Ends Soon!

Lesson 9 of 13 30 min

Combined Loading

Real engineering components rarely experience only one type of loading. A drive shaft might experience bending, torsion, and axial force simultaneously. Understanding combined loading is essential for safe design.

Superposition Principle

For linear elastic materials, stresses from different loads can be added:

$$\sigma_{total} = \sigma_{axial} + \sigma_{bending}$$

Sponsored

70% of India's auto industry trusts Skill-Lync

For training their engineers in CAD, CAE & simulation

Learn More

$$\tau_{total} = \tau_{torsion} + \tau_{shear}$$

Common Combined Loading Cases

import numpy as np
import matplotlib.pyplot as plt

class CombinedLoading:
    """Analyze combined loading on structural members."""

    @staticmethod
    def axial_bending(P_kN, M_kNm, A_mm2, I_mm4, c_mm, position='top'):
        """
        Combined axial load and bending.

        Parameters:
        -----------
        P_kN : float - Axial force (positive = tension)
        M_kNm : float - Bending moment (positive = tension at bottom)
        A_mm2 : float - Cross-sectional area
        I_mm4 : float - Moment of inertia
        c_mm : float - Distance to extreme fiber
        position : str - 'top' or 'bottom'
        """
        # Convert units
        P = P_kN * 1e3      # N
        M = M_kNm * 1e6     # N·mm

        # Individual stresses
        sigma_axial = P / A_mm2  # MPa

        if position == 'top':
            sigma_bending = -M * c_mm / I_mm4  # Compression at top for positive M
        else:
            sigma_bending = M * c_mm / I_mm4   # Tension at bottom for positive M

        # Combined stress
        sigma_total = sigma_axial + sigma_bending

        return {
            'sigma_axial': sigma_axial,
            'sigma_bending': sigma_bending,
            'sigma_total': sigma_total,
            'position': position
        }

    @staticmethod
    def bending_torsion(M_kNm, T_kNm, I_mm4, J_mm4, c_mm):
        """
        Combined bending and torsion (common for shafts).

        Returns principal stresses using Mohr's circle.
        """
        M = M_kNm * 1e6     # N·mm
        T = T_kNm * 1e6     # N·mm

        # Bending stress at extreme fiber
        sigma_b = M * c_mm / I_mm4  # MPa

        # Torsional shear stress at surface
        tau = T * c_mm / J_mm4  # MPa

        # At surface: σx = σb, σy = 0, τxy = τ
        # Principal stresses
        sigma_avg = sigma_b / 2
        R = np.sqrt(sigma_avg**2 + tau**2)

        sigma_1 = sigma_avg + R
        sigma_2 = sigma_avg - R
        tau_max = R

        return {
            'sigma_bending': sigma_b,
            'tau_torsion': tau,
            'sigma_1': sigma_1,
            'sigma_2': sigma_2,
            'tau_max': tau_max
        }

    @staticmethod
    def axial_bending_torsion(P_kN, M_kNm, T_kNm, A_mm2, I_mm4, J_mm4, c_mm):
        """
        Combined axial, bending, and torsion.
        """
        P = P_kN * 1e3
        M = M_kNm * 1e6
        T = T_kNm * 1e6

        # Normal stress at extreme fiber
        sigma_axial = P / A_mm2
        sigma_bending = M * c_mm / I_mm4
        sigma_x = sigma_axial + sigma_bending  # Combined normal stress

        # Shear stress
        tau_xy = T * c_mm / J_mm4

        # Principal stresses
        sigma_avg = sigma_x / 2
        R = np.sqrt(sigma_avg**2 + tau_xy**2)

        sigma_1 = sigma_avg + R
        sigma_2 = sigma_avg - R
        tau_max = R

        return {
            'sigma_axial': sigma_axial,
            'sigma_bending': sigma_bending,
            'sigma_x': sigma_x,
            'tau_xy': tau_xy,
            'sigma_1': sigma_1,
            'sigma_2': sigma_2,
            'tau_max': tau_max
        }


# Example: Circular shaft properties
d = 50  # mm
A = np.pi * (d/2)**2
I = np.pi * d**4 / 64
J = np.pi * d**4 / 32
c = d / 2

print("Combined Loading Analysis")
print(f"Shaft diameter: {d} mm")
print("=" * 50)

# Case 1: Axial + Bending
print("\nCase 1: Axial + Bending")
result = CombinedLoading.axial_bending(
    P_kN=20, M_kNm=0.5, A_mm2=A, I_mm4=I, c_mm=c, position='bottom'
)
print(f"  Axial stress: {result['sigma_axial']:.2f} MPa")
print(f"  Bending stress: {result['sigma_bending']:.2f} MPa")
print(f"  Total stress ({result['position']}): {result['sigma_total']:.2f} MPa")

# Case 2: Bending + Torsion
print("\nCase 2: Bending + Torsion")
result = CombinedLoading.bending_torsion(
    M_kNm=0.8, T_kNm=1.2, I_mm4=I, J_mm4=J, c_mm=c
)
print(f"  Bending stress: {result['sigma_bending']:.2f} MPa")
print(f"  Torsional shear: {result['tau_torsion']:.2f} MPa")
print(f"  Principal stress σ₁: {result['sigma_1']:.2f} MPa")
print(f"  Principal stress σ₂: {result['sigma_2']:.2f} MPa")
print(f"  Max shear stress: {result['tau_max']:.2f} MPa")

# Case 3: All combined
print("\nCase 3: Axial + Bending + Torsion")
result = CombinedLoading.axial_bending_torsion(
    P_kN=15, M_kNm=0.8, T_kNm=1.2, A_mm2=A, I_mm4=I, J_mm4=J, c_mm=c
)
print(f"  Combined normal σx: {result['sigma_x']:.2f} MPa")
print(f"  Shear τxy: {result['tau_xy']:.2f} MPa")
print(f"  Principal σ₁: {result['sigma_1']:.2f} MPa")
print(f"  Principal σ₂: {result['sigma_2']:.2f} MPa")
🎯 3,000+ Engineers Placed
Sponsored
Harshal Sukenkar

Harshal

Fiat Chrysler

Abhishek

Abhishek

TATA ELXSI

Srinithin

Srinithin

Xitadel

Ranjith

Ranjith

Core Automotive

Gaurav Jadhav

Gaurav

Automotive Company

Bino K Biju

Bino

Design Firm

Aseem Shrivastava

Aseem

EV Company

Puneet

Puneet

Automotive Company

Vishal Kumar

Vishal

EV Startup

Failure Theories

Different materials fail in different ways. We use failure theories to predict when yielding or fracture will occur.

class FailureTheories:
    """Failure theory calculations for combined stress states."""

    @staticmethod
    def tresca(sigma_1, sigma_2, sigma_3=0):
        """
        Maximum Shear Stress Theory (Tresca).
        Conservative for ductile materials.

        Failure when: τmax = Sy/2
        """
        principals = sorted([sigma_1, sigma_2, sigma_3])
        tau_max = (principals[2] - principals[0]) / 2

        return {
            'tau_max': tau_max,
            'equivalent_stress': principals[2] - principals[0],
            'theory': 'Tresca (Max Shear Stress)'
        }

    @staticmethod
    def von_mises(sigma_1, sigma_2, sigma_3=0):
        """
        Distortion Energy Theory (von Mises).
        Best predictor for ductile materials.

        Failure when: σ_vm = Sy
        """
        sigma_vm = np.sqrt(0.5 * (
            (sigma_1 - sigma_2)**2 +
            (sigma_2 - sigma_3)**2 +
            (sigma_3 - sigma_1)**2
        ))

        return {
            'sigma_vm': sigma_vm,
            'equivalent_stress': sigma_vm,
            'theory': 'von Mises (Distortion Energy)'
        }

    @staticmethod
    def rankine(sigma_1, sigma_2, sigma_3=0):
        """
        Maximum Principal Stress Theory (Rankine).
        Used for brittle materials.

        Failure when: σ_max = Sut or σ_min = -Suc
        """
        sigma_max = max(sigma_1, sigma_2, sigma_3)
        sigma_min = min(sigma_1, sigma_2, sigma_3)

        return {
            'sigma_max': sigma_max,
            'sigma_min': sigma_min,
            'theory': 'Rankine (Max Principal Stress)'
        }

    @staticmethod
    def factor_of_safety(equivalent_stress, yield_strength):
        """Calculate factor of safety."""
        return yield_strength / abs(equivalent_stress) if equivalent_stress != 0 else float('inf')


def analyze_combined_stress(sigma_1, sigma_2, Sy_MPa, material_type='ductile'):
    """
    Complete failure analysis for plane stress state.
    """
    print(f"Failure Analysis")
    print(f"Principal Stresses: σ₁ = {sigma_1:.2f} MPa, σ₂ = {sigma_2:.2f} MPa")
    print(f"Yield Strength: {Sy_MPa} MPa")
    print("-" * 50)

    # Tresca
    tresca = FailureTheories.tresca(sigma_1, sigma_2)
    fos_tresca = FailureTheories.factor_of_safety(tresca['equivalent_stress'], Sy_MPa)
    print(f"\n{tresca['theory']}:")
    print(f"  τmax = {tresca['tau_max']:.2f} MPa")
    print(f"  Equivalent stress = {tresca['equivalent_stress']:.2f} MPa")
    print(f"  Factor of Safety = {fos_tresca:.2f}")

    # von Mises
    vm = FailureTheories.von_mises(sigma_1, sigma_2)
    fos_vm = FailureTheories.factor_of_safety(vm['sigma_vm'], Sy_MPa)
    print(f"\n{vm['theory']}:")
    print(f"  σ_vm = {vm['sigma_vm']:.2f} MPa")
    print(f"  Factor of Safety = {fos_vm:.2f}")

    # Recommendation
    if material_type == 'ductile':
        print(f"\n→ For ductile materials, use von Mises (FoS = {fos_vm:.2f})")
    else:
        rankine = FailureTheories.rankine(sigma_1, sigma_2)
        print(f"\n→ For brittle materials, use Rankine:")
        print(f"  Max tensile: {rankine['sigma_max']:.2f} MPa")
        print(f"  Max compressive: {abs(rankine['sigma_min']):.2f} MPa")

    return {'fos_tresca': fos_tresca, 'fos_vm': fos_vm}

# Example
analyze_combined_stress(sigma_1=120, sigma_2=-40, Sy_MPa=250)

Visualizing Failure Envelopes

def plot_failure_envelopes(Sy=250):
    """
    Plot failure envelopes for different theories.
    """
    fig, ax = plt.subplots(figsize=(10, 10))

    # Coordinate ranges
    sigma = np.linspace(-Sy*1.5, Sy*1.5, 500)
    s1, s2 = np.meshgrid(sigma, sigma)

    # Tresca envelope (hexagon)
    tresca = np.maximum(np.abs(s1 - s2), np.maximum(np.abs(s1), np.abs(s2)))
    ax.contour(s1, s2, tresca, levels=[Sy], colors='blue', linewidths=2)

    # von Mises envelope (ellipse)
    von_mises = np.sqrt(s1**2 - s1*s2 + s2**2)
    ax.contour(s1, s2, von_mises, levels=[Sy], colors='red', linewidths=2)

    # Rankine envelope (square)
    ax.axhline(y=Sy, color='green', linestyle='--', lw=1.5)
    ax.axhline(y=-Sy, color='green', linestyle='--', lw=1.5)
    ax.axvline(x=Sy, color='green', linestyle='--', lw=1.5)
    ax.axvline(x=-Sy, color='green', linestyle='--', lw=1.5)

    # Labels and formatting
    ax.axhline(y=0, color='k', lw=0.5)
    ax.axvline(x=0, color='k', lw=0.5)
    ax.plot([0], [0], 'ko', ms=5)

    # Example stress states
    stress_states = [
        (120, -40, 'State A'),
        (200, 100, 'State B'),
        (-100, -150, 'State C'),
    ]

    for s1_pt, s2_pt, label in stress_states:
        ax.scatter([s1_pt], [s2_pt], s=100, zorder=5)
        ax.annotate(label, xy=(s1_pt, s2_pt), xytext=(s1_pt+20, s2_pt+20))

    ax.set_xlabel('σ₁ (MPa)', fontsize=12)
    ax.set_ylabel('σ₂ (MPa)', fontsize=12)
    ax.set_title(f'Failure Envelopes (Sy = {Sy} MPa)', fontsize=14)
    ax.set_aspect('equal')
    ax.grid(True, alpha=0.3)
    ax.set_xlim(-Sy*1.3, Sy*1.3)
    ax.set_ylim(-Sy*1.3, Sy*1.3)

    # Legend
    from matplotlib.lines import Line2D
    legend_elements = [
        Line2D([0], [0], color='blue', lw=2, label='Tresca'),
        Line2D([0], [0], color='red', lw=2, label='von Mises'),
        Line2D([0], [0], color='green', lw=2, linestyle='--', label='Rankine')
    ]
    ax.legend(handles=legend_elements, loc='upper left')

    plt.tight_layout()
    plt.show()

plot_failure_envelopes(Sy=250)

Design with Combined Loading

def design_shaft_combined(P_kW, rpm, F_radial_kN, L_bearing_mm, Sy_MPa, FoS_required=2.0):
    """
    Design a shaft under combined bending and torsion.

    Parameters:
    -----------
    P_kW : float - Power transmitted
    rpm : float - Rotational speed
    F_radial_kN : float - Radial load (e.g., from gear)
    L_bearing_mm : float - Distance from load to bearing
    Sy_MPa : float - Material yield strength
    FoS_required : float - Required factor of safety
    """
    # Calculate torque
    T = P_kW * 1000 * 60 / (2 * np.pi * rpm)  # N·m
    T_mm = T * 1000  # N·mm

    # Bending moment from radial load
    M = F_radial_kN * 1000 * L_bearing_mm  # N·mm

    print(f"Shaft Design - Combined Loading")
    print(f"Power: {P_kW} kW at {rpm} RPM")
    print(f"Torque: {T:.2f} N·m")
    print(f"Radial load: {F_radial_kN} kN at {L_bearing_mm} mm from bearing")
    print(f"Bending moment: {M/1e6:.3f} kN·m")
    print("=" * 50)

    # Allowable stress
    sigma_allow = Sy_MPa / FoS_required
    print(f"Allowable stress (FoS={FoS_required}): {sigma_allow:.1f} MPa")

    # For combined bending and torsion using ASME code:
    # von Mises: σ_vm = sqrt(σ_b² + 3τ²) ≤ σ_allow
    # Using d:
    # σ_b = 32M/(πd³), τ = 16T/(πd³)
    # σ_vm = (16/πd³) * sqrt(4M² + 3T²)

    M_eq = np.sqrt(M**2 + 0.75 * T_mm**2)  # Equivalent moment

    # Required diameter
    # σ_allow = 32*M_eq / (π*d³)
    d_required = (32 * M_eq / (np.pi * sigma_allow)) ** (1/3)

    # Standard sizes
    standard_sizes = [25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80]
    d_selected = next((s for s in standard_sizes if s >= d_required), standard_sizes[-1])

    print(f"\nRequired diameter: {d_required:.1f} mm")
    print(f"Selected standard: {d_selected} mm")

    # Verify
    I = np.pi * d_selected**4 / 64
    J = np.pi * d_selected**4 / 32
    c = d_selected / 2

    sigma_b = M * c / I
    tau = T_mm * c / J
    sigma_vm = np.sqrt(sigma_b**2 + 3*tau**2)

    actual_fos = Sy_MPa / sigma_vm

    print(f"\nVerification (Ø{d_selected} mm):")
    print(f"  Bending stress: {sigma_b:.2f} MPa")
    print(f"  Shear stress: {tau:.2f} MPa")
    print(f"  von Mises stress: {sigma_vm:.2f} MPa")
    print(f"  Actual FoS: {actual_fos:.2f}")

    return d_selected

# Example
d = design_shaft_combined(
    P_kW=50,
    rpm=1500,
    F_radial_kN=8,
    L_bearing_mm=150,
    Sy_MPa=350,
    FoS_required=2.5
)

Key Takeaways

  • Superposition: Add stresses from different loads for linear elastic materials
  • Mohr's Circle: Find principal stresses for any combined stress state
  • von Mises: Best predictor for ductile material yielding
  • Tresca: More conservative than von Mises
  • Rankine: Use for brittle materials (max principal stress)

Next lesson: We'll study column buckling and stability.

3,000+ Engineers Placed in Top Companies
Career Growth

3,000+ Engineers Placed in Top Companies

Join the ranks of successful engineers at Bosch, Tata, L&T, and 500+ hiring partners.

Torsion