"""
Steel Column Design Calculator - IS 800:2007 (Complete Implementation)
Comprehensive steel beam-column (compression + bending) design as per IS 800:2007.
Includes:
- Pure compression (Section 7)
- Combined axial load + biaxial bending (Section 9.3)
- Lateral-torsional buckling checks (Section 8.2.2)
- Interaction checks for beam-columns
- Section database integration ready
- Separate effective lengths for major/minor axes
"""
import math
from enum import Enum
from typing import Any, ClassVar, Dict, List, Optional, Tuple, Type
from pydantic import BaseModel, Field, ValidationInfo, field_validator
from ..base import BaseCalculator
# ============================================================================
# ENUMERATIONS
# ============================================================================
[docs]
class SectionType(str, Enum):
"""Standard steel section types."""
ISHB = "ISHB" # I-Section Heavy Beam
ISJB = "ISJB" # I-Section Junior Beam
ISLB = "ISLB" # I-Section Light Beam
ISMC = "ISMC" # Channel Section
ISMB = "ISMB" # I-Section Medium Beam
ISWB = "ISWB" # I-Section Wide Flange Beam
TUBULAR = "TUBULAR" # Hollow sections
[docs]
class EndCondition(str, Enum):
"""Column end conditions for effective length calculation."""
FIXED_FIXED = "fixed_fixed"
FIXED_PINNED = "fixed_pinned"
PINNED_PINNED = "pinned_pinned"
FIXED_FREE = "fixed_free"
CUSTOM = "custom" # User provides K-factor directly
[docs]
class BucklingClass(str, Enum):
"""Buckling classes as per IS 800:2007 Table 10."""
A = "a"
B = "b"
C = "c"
D = "d"
[docs]
class SteelGrade(str, Enum):
"""Steel grades (E-series only, no Fe-series)."""
E250 = "E250"
E350 = "E350"
E410 = "E410"
E450 = "E450"
[docs]
class SectionSource(str, Enum):
"""Section property source."""
DATABASE = "database" # From steel section database
MANUAL = "manual" # User-provided properties
BUILDUP = "buildup" # Built-up section (future)
# ============================================================================
# INPUT SCHEMA
# ============================================================================
# ============================================================================
# OUTPUT SCHEMA
# ============================================================================
[docs]
class SlendernessCheck(BaseModel):
"""Slenderness ratio check results."""
lambda_major: float = Field(..., description="Slenderness ratio about major axis")
lambda_minor: float = Field(..., description="Slenderness ratio about minor axis")
lambda_effective: float = Field(..., description="Effective slenderness ratio")
limit: float = Field(default=180.0, description="Maximum allowable slenderness ratio")
status: str = Field(..., description="PASS or FAIL")
[docs]
class BucklingAnalysis(BaseModel):
"""Buckling analysis results."""
buckling_class_major: BucklingClass = Field(..., description="Buckling class about major axis")
buckling_class_minor: BucklingClass = Field(..., description="Buckling class about minor axis")
imperfection_factor_major: float = Field(..., description="Imperfection factor alpha (major)")
imperfection_factor_minor: float = Field(..., description="Imperfection factor alpha (minor)")
non_dimensional_slenderness_major: float = Field(
..., description="Non-dimensional slenderness (major)"
)
non_dimensional_slenderness_minor: float = Field(
..., description="Non-dimensional slenderness (minor)"
)
stress_reduction_factor_major: float = Field(
..., description="Stress reduction factor chi (major)"
)
stress_reduction_factor_minor: float = Field(
..., description="Stress reduction factor chi (minor)"
)
governing_axis: str = Field(..., description="Major or Minor axis governing")
[docs]
class LTBCheck(BaseModel):
"""Lateral-torsional buckling check results."""
is_applicable: bool = Field(..., description="Whether LTB check is applicable")
effective_length_ltb: Optional[float] = Field(None, description="Effective length for LTB in m")
non_dimensional_slenderness_ltb: Optional[float] = Field(
None, description="Non-dimensional slenderness for LTB"
)
stress_reduction_factor_ltb: Optional[float] = Field(
None, description="Stress reduction factor chi_LT"
)
design_bending_strength_major: Optional[float] = Field(
None, description="Design bending strength considering LTB in kN-m"
)
design_bending_strength_minor: Optional[float] = Field(
None, description="Design bending strength about minor axis in kN-m"
)
[docs]
class InteractionCheck(BaseModel):
"""IS 800:2007 Section 9.3 interaction check."""
compression_ratio: float = Field(..., description="P/Pd ratio")
moment_major_ratio: float = Field(..., description="My/Mdy ratio")
moment_minor_ratio: float = Field(..., description="Mz/Mdz ratio")
interaction_ratio_1: float = Field(..., description="First interaction equation result")
interaction_ratio_2: float = Field(..., description="Second interaction equation result")
governing_interaction: float = Field(..., description="Maximum interaction ratio")
status: str = Field(..., description="SAFE or UNSAFE")
[docs]
class DesignCheck(BaseModel):
"""Design strength check results."""
design_strength_compression: float = Field(..., description="Design compression strength in kN")
design_strength_moment_major: float = Field(
..., description="Design moment strength (major axis) in kN-m"
)
design_strength_moment_minor: float = Field(
..., description="Design moment strength (minor axis) in kN-m"
)
applied_load: float = Field(..., description="Applied axial load in kN")
applied_moment_major: float = Field(..., description="Applied moment (major) in kN-m")
applied_moment_minor: float = Field(..., description="Applied moment (minor) in kN-m")
utilization_compression: float = Field(..., description="Compression utilization ratio")
utilization_bending_major: float = Field(..., description="Bending utilization (major)")
utilization_bending_minor: float = Field(..., description="Bending utilization (minor)")
overall_utilization: float = Field(..., description="Overall utilization ratio")
status: str = Field(..., description="SAFE or UNSAFE")
[docs]
class SteelColumnOutput(BaseModel):
"""Output schema for steel column design results."""
inputs: SteelColumnInput
# Section Classification
section_full_name: str = Field(..., description="Full section name")
yield_strength: float = Field(..., description="Yield strength in MPa")
# Effective Length Calculations
effective_length_major: float = Field(..., description="Effective length about major axis in m")
effective_length_minor: float = Field(..., description="Effective length about minor axis in m")
effective_length_factor_major: float = Field(..., description="K factor for major axis")
effective_length_factor_minor: float = Field(..., description="K factor for minor axis")
# Slenderness Checks
slenderness: SlendernessCheck
# Buckling Analysis
buckling: BucklingAnalysis
# Lateral-Torsional Buckling
ltb_check: LTBCheck
# Interaction Check (Section 9.3)
interaction: InteractionCheck
# Design Checks
design_check: DesignCheck
# Overall Status
status: str = Field(..., description="Overall design status")
design_type: str = Field(..., description="Pure Compression or Beam-Column")
remarks: List[str] = Field(
default_factory=list, description="Design remarks and recommendations"
)
# ============================================================================
# CALCULATOR IMPLEMENTATION
# ============================================================================
[docs]
class SteelColumnCalculator(BaseCalculator):
"""
Calculator for steel beam-column design per IS 800:2007.
Implements comprehensive steel member design including:
- Pure compression (Section 7)
- Combined compression + biaxial bending (Section 9.3)
- Effective length calculation (Clause 7.2)
- Slenderness ratio checks (Table 3)
- Buckling class determination (Table 10)
- Design compressive strength (Clause 7.1)
- Design bending strength (Clause 8.2)
- Lateral-torsional buckling (Clause 8.2.2)
- Interaction checks (Clause 9.3.2.2)
- Perry-Robertson formula for buckling
"""
# Effective length factors (Table 11, IS 800:2007 Clause 7.2.2)
EFFECTIVE_LENGTH_FACTORS: ClassVar[Dict[EndCondition, float]] = {
EndCondition.FIXED_FIXED: 0.65,
EndCondition.FIXED_PINNED: 0.80,
EndCondition.PINNED_PINNED: 1.00,
EndCondition.FIXED_FREE: 2.00,
}
# Yield strengths for steel grades (MPa)
YIELD_STRENGTHS: ClassVar[Dict[SteelGrade, float]] = {
SteelGrade.E250: 250.0,
SteelGrade.E350: 350.0,
SteelGrade.E410: 410.0,
SteelGrade.E450: 450.0,
}
# Imperfection factors for buckling classes (Table 10, IS 800:2007)
IMPERFECTION_FACTORS: ClassVar[Dict[BucklingClass, float]] = {
BucklingClass.A: 0.21,
BucklingClass.B: 0.34,
BucklingClass.C: 0.49,
BucklingClass.D: 0.76,
}
# Modulus of elasticity for steel (N/mm²)
E_STEEL: float = 200000.0
# Partial safety factors
GAMMA_M0: float = 1.10 # Resistance governed by yielding/buckling
[docs]
def __init__(self) -> None:
super().__init__("steel_column_design", "3.0.0")
@property
def input_schema(self) -> Type[BaseModel]:
"""Return input validation schema."""
return SteelColumnInput
@property
def output_schema(self) -> Type[BaseModel]:
"""Return output formatting schema."""
return SteelColumnOutput
[docs]
def calculate(self, inputs: Dict[str, Any]) -> Dict[str, Any]:
"""
Perform comprehensive steel beam-column design calculation.
Calculation sequence:
1. Extract and validate inputs
2. Determine material properties
3. Calculate effective lengths
4. Check slenderness ratios
5. Determine buckling classes
6. Calculate design compressive strength (Section 7)
7. Calculate design bending strength with LTB check (Section 8)
8. Perform interaction checks (Section 9.3)
9. Generate remarks and recommendations
"""
# Step 1: Parse and validate inputs
input_data = SteelColumnInput(**inputs)
# Step 2: Material properties
fy = self.YIELD_STRENGTHS[input_data.steel_grade]
section_name = f"{input_data.section_type.value} {input_data.section_designation}"
# Determine design type
has_moments = input_data.moment_major > 0 or input_data.moment_minor > 0
design_type = "Beam-Column" if has_moments else "Pure Compression"
# Step 3: Effective length calculation
k_major = self._get_effective_length_factor(
input_data.end_condition_major, input_data.k_factor_major
)
k_minor = self._get_effective_length_factor(
input_data.end_condition_minor, input_data.k_factor_minor
)
length_major_mm = input_data.length_major * 1000.0
length_minor_mm = input_data.length_minor * 1000.0
l_eff_major = k_major * length_major_mm
l_eff_minor = k_minor * length_minor_mm
# Step 4: Slenderness ratio calculation (Clause 7.2.1)
lambda_major = l_eff_major / input_data.radius_gyration_major
lambda_minor = l_eff_minor / input_data.radius_gyration_minor
lambda_effective = max(lambda_major, lambda_minor)
slenderness_status = "PASS" if lambda_effective <= 180.0 else "FAIL"
# Step 5: Buckling class determination (Table 10)
buckling_class_major, buckling_class_minor = self._determine_buckling_class(
input_data.section_type, input_data.thickness_flange
)
# Step 6: Design compressive strength calculation (Section 7)
alpha_major = self.IMPERFECTION_FACTORS[buckling_class_major]
alpha_minor = self.IMPERFECTION_FACTORS[buckling_class_minor]
lambda_bar_major = self._calculate_non_dimensional_slenderness(
lambda_major, fy, self.E_STEEL
)
lambda_bar_minor = self._calculate_non_dimensional_slenderness(
lambda_minor, fy, self.E_STEEL
)
chi_major = self._calculate_stress_reduction_factor(lambda_bar_major, alpha_major)
chi_minor = self._calculate_stress_reduction_factor(lambda_bar_minor, alpha_minor)
# Governing axis for compression
if chi_minor < chi_major:
chi_governing_compression = chi_minor
governing_axis = "Minor"
else:
chi_governing_compression = chi_major
governing_axis = "Major"
# Design compressive stress (Clause 7.1.2)
fcd = (chi_governing_compression * fy) / self.GAMMA_M0
# Design compressive strength
design_strength_compression_kn = (fcd * input_data.area) / 1000.0
# Step 7: Design bending strength with LTB check (Section 8)
ltb_check_result, design_moment_major, design_moment_minor = (
self._calculate_bending_strength_with_ltb(input_data, fy)
)
# Step 8: Interaction checks (Section 9.3.2.2)
interaction_result = self._calculate_interaction_check(
input_data,
design_strength_compression_kn,
design_moment_major,
design_moment_minor,
chi_major,
chi_minor,
)
# Step 9: Overall design checks
utilization_compression = input_data.axial_load / design_strength_compression_kn
utilization_bending_major = (
input_data.moment_major / design_moment_major if design_moment_major > 0 else 0.0
)
utilization_bending_minor = (
input_data.moment_minor / design_moment_minor if design_moment_minor > 0 else 0.0
)
# Overall utilization is governed by interaction check
overall_utilization = interaction_result["governing_interaction"]
design_status = "SAFE" if overall_utilization <= 1.0 else "UNSAFE"
overall_status = (
"PASS" if (slenderness_status == "PASS" and design_status == "SAFE") else "FAIL"
)
# Step 10: Generate remarks
remarks = self._generate_remarks(
input_data,
design_type,
lambda_effective,
overall_utilization,
governing_axis,
design_status,
ltb_check_result["is_applicable"],
)
# Construct output
return {
"inputs": input_data.model_dump(),
"section_full_name": section_name,
"yield_strength": round(fy, 2),
"effective_length_major": round(l_eff_major / 1000.0, 3),
"effective_length_minor": round(l_eff_minor / 1000.0, 3),
"effective_length_factor_major": round(k_major, 2),
"effective_length_factor_minor": round(k_minor, 2),
"slenderness": {
"lambda_major": round(lambda_major, 2),
"lambda_minor": round(lambda_minor, 2),
"lambda_effective": round(lambda_effective, 2),
"limit": 180.0,
"status": slenderness_status,
},
"buckling": {
"buckling_class_major": buckling_class_major,
"buckling_class_minor": buckling_class_minor,
"imperfection_factor_major": round(alpha_major, 3),
"imperfection_factor_minor": round(alpha_minor, 3),
"non_dimensional_slenderness_major": round(lambda_bar_major, 3),
"non_dimensional_slenderness_minor": round(lambda_bar_minor, 3),
"stress_reduction_factor_major": round(chi_major, 3),
"stress_reduction_factor_minor": round(chi_minor, 3),
"governing_axis": governing_axis,
},
"ltb_check": ltb_check_result,
"interaction": interaction_result,
"design_check": {
"design_strength_compression": round(design_strength_compression_kn, 2),
"design_strength_moment_major": round(design_moment_major, 2),
"design_strength_moment_minor": round(design_moment_minor, 2),
"applied_load": round(input_data.axial_load, 2),
"applied_moment_major": round(input_data.moment_major, 2),
"applied_moment_minor": round(input_data.moment_minor, 2),
"utilization_compression": round(utilization_compression, 3),
"utilization_bending_major": round(utilization_bending_major, 3),
"utilization_bending_minor": round(utilization_bending_minor, 3),
"overall_utilization": round(overall_utilization, 3),
"status": design_status,
},
"status": overall_status,
"design_type": design_type,
"remarks": remarks,
}
def _get_effective_length_factor(
self, end_condition: EndCondition, custom_k: Optional[float]
) -> float:
"""Get effective length factor from end condition or custom value."""
if end_condition == EndCondition.CUSTOM:
if custom_k is None:
raise ValueError("Custom K-factor required when end condition is CUSTOM")
return custom_k
return self.EFFECTIVE_LENGTH_FACTORS[end_condition]
def _determine_buckling_class(
self, section_type: SectionType, flange_thickness: float
) -> Tuple[BucklingClass, BucklingClass]:
"""
Determine buckling class as per IS 800:2007 Table 10.
Returns:
(buckling_class_major, buckling_class_minor)
"""
if section_type in [SectionType.ISHB, SectionType.ISMB, SectionType.ISLB, SectionType.ISWB]:
# Rolled I-sections
if flange_thickness <= 40.0:
return BucklingClass.A, BucklingClass.B
else:
return BucklingClass.B, BucklingClass.C
elif section_type == SectionType.ISMC:
# Channel sections
return BucklingClass.B, BucklingClass.C
elif section_type == SectionType.TUBULAR:
# Hollow sections
return BucklingClass.A, BucklingClass.A
else:
# Default conservative
return BucklingClass.C, BucklingClass.C
def _calculate_non_dimensional_slenderness(
self, lambda_ratio: float, fy: float, E: float
) -> float:
"""
Calculate non-dimensional slenderness ratio.
λ̄ = λ / λₑ = λ / (π√(E/fy))
"""
lambda_e = math.pi * math.sqrt(E / fy)
return lambda_ratio / lambda_e
def _calculate_stress_reduction_factor(self, lambda_bar: float, alpha: float) -> float:
"""
Calculate stress reduction factor using Perry-Robertson formula.
IS 800:2007 Clause 7.1.2:
φ = 0.5[1 + α(λ̄ - 0.2) + λ̄²]
χ = 1 / [φ + √(φ² - λ̄²)] ≤ 1.0
"""
if lambda_bar <= 0.2:
return 1.0
phi = 0.5 * (1.0 + alpha * (lambda_bar - 0.2) + lambda_bar**2)
discriminant = phi**2 - lambda_bar**2
if discriminant < 0:
chi = 1.0 / (2.0 * phi)
else:
chi = 1.0 / (phi + math.sqrt(discriminant))
return min(chi, 1.0)
def _calculate_bending_strength_with_ltb(
self, inputs: SteelColumnInput, fy: float
) -> Tuple[Dict[str, Any], float, float]:
"""
Calculate design bending strength considering lateral-torsional buckling.
Returns:
(ltb_check_dict, design_moment_major_knm, design_moment_minor_knm)
"""
# Design moment about minor axis (no LTB consideration)
design_moment_minor = (inputs.plastic_modulus_minor * fy) / (self.GAMMA_M0 * 1e6) # kN-m
# Check if LTB is applicable for major axis bending
# LTB not applicable for: minor axis bending, tubular sections, or no moments
ltb_applicable = inputs.moment_major > 0 and inputs.section_type != SectionType.TUBULAR
if not ltb_applicable:
# No LTB check needed
design_moment_major = (inputs.plastic_modulus_major * fy) / (self.GAMMA_M0 * 1e6)
return (
{
"is_applicable": False,
"effective_length_ltb": None,
"non_dimensional_slenderness_ltb": None,
"stress_reduction_factor_ltb": None,
"design_bending_strength_major": round(design_moment_major, 2),
"design_bending_strength_minor": round(design_moment_minor, 2),
},
design_moment_major,
design_moment_minor,
)
# LTB check applicable
# Use lateral support spacing if provided, otherwise use length_major
l_ltb = (
inputs.lateral_support_spacing
if inputs.lateral_support_spacing
else inputs.length_major
)
l_ltb_mm = l_ltb * 1000.0
# Simplified elastic critical moment (IS 800 Clause 8.2.2.1)
# For standard I-sections: Mcr ≈ (π²EIy/L²) * √(1 + (1/20)*(h/tf)²)
Iy = inputs.area * (inputs.radius_gyration_minor**2) # mm⁴
h = inputs.depth # mm
tf = inputs.thickness_flange # mm
term1 = (math.pi**2 * self.E_STEEL * Iy) / (l_ltb_mm**2)
term2 = math.sqrt(1 + (1 / 20) * ((h / tf) ** 2))
M_cr = term1 * term2 # N-mm
# Non-dimensional slenderness for LTB
beta_b = 1.0 # For plastic/compact sections
lambda_LT = math.sqrt((beta_b * inputs.plastic_modulus_major * fy) / M_cr)
# Imperfection factor for LTB (Table 13)
alpha_LT = 0.21 # For rolled sections (conservative)
# Stress reduction factor for LTB
phi_LT = 0.5 * (1.0 + alpha_LT * (lambda_LT - 0.2) + lambda_LT**2)
discriminant_LT = phi_LT**2 - lambda_LT**2
if discriminant_LT < 0 or lambda_LT <= 0.4:
chi_LT = 1.0
else:
chi_LT = 1.0 / (phi_LT + math.sqrt(discriminant_LT))
chi_LT = min(chi_LT, 1.0)
# Design bending strength considering LTB
design_moment_major = (chi_LT * inputs.plastic_modulus_major * fy) / (self.GAMMA_M0 * 1e6)
return (
{
"is_applicable": True,
"effective_length_ltb": round(l_ltb, 3),
"non_dimensional_slenderness_ltb": round(lambda_LT, 3),
"stress_reduction_factor_ltb": round(chi_LT, 3),
"design_bending_strength_major": round(design_moment_major, 2),
"design_bending_strength_minor": round(design_moment_minor, 2),
},
design_moment_major,
design_moment_minor,
)
def _calculate_interaction_check(
self,
inputs: SteelColumnInput,
pd_compression: float,
mdy_major: float,
mdz_minor: float,
chi_y: float,
chi_z: float,
) -> Dict[str, Any]:
"""
Calculate interaction check as per IS 800:2007 Section 9.3.2.2.
Interaction equations:
P/Pdy + Ky*My/Mdy + KLT*Mz/Mdz ≤ 1.0
P/Pdz + Kz*My/Mdy + KLT*Mz/Mdz ≤ 1.0
Where:
- Pdy, Pdz = Design strength governed by buckling about y, z axes
- Ky, Kz = Interaction factors
- KLT = Lateral-torsional buckling interaction factor
"""
# Compression ratios for each axis
# For interaction, we need design strength about each axis separately
fcd_major = (chi_y * self.YIELD_STRENGTHS[inputs.steel_grade]) / self.GAMMA_M0
fcd_minor = (chi_z * self.YIELD_STRENGTHS[inputs.steel_grade]) / self.GAMMA_M0
pdy = (fcd_major * inputs.area) / 1000.0 # kN (buckling about major axis)
pdz = (fcd_minor * inputs.area) / 1000.0 # kN (buckling about minor axis)
# Ratios
compression_ratio_y = inputs.axial_load / pdy if pdy > 0 else 0.0
compression_ratio_z = inputs.axial_load / pdz if pdz > 0 else 0.0
moment_major_ratio = inputs.moment_major / mdy_major if mdy_major > 0 else 0.0
moment_minor_ratio = inputs.moment_minor / mdz_minor if mdz_minor > 0 else 0.0
# Interaction factors (IS 800 Clause 9.3.2.2)
# Simplified: Cmy = Cmz = 1.0 (conservative)
# K factors depend on ny, nz (slenderness-based)
ny = compression_ratio_y
nz = compression_ratio_z
Cmy = 1.0 # Equivalent uniform moment factor (conservative)
Cmz = 1.0
CMLT = 1.0
Ky = Cmy * (1.0 + 0.2 * ny) / (1.0 - 0.8 * ny) if ny < 1.25 else Cmy * 10.0
Kz = Cmz * (1.0 + 0.2 * nz) / (1.0 - 0.8 * nz) if nz < 1.25 else Cmz * 10.0
KLT = CMLT * (1.0 - 0.1 * ny) / (1.0 - 0.25 * ny) if ny < 4.0 else 1.0
# Interaction equations
interaction_1 = compression_ratio_y + Ky * moment_major_ratio + KLT * moment_minor_ratio
interaction_2 = compression_ratio_z + Kz * moment_major_ratio + KLT * moment_minor_ratio
governing_interaction = max(interaction_1, interaction_2)
status = "SAFE" if governing_interaction <= 1.0 else "UNSAFE"
return {
"compression_ratio": round(max(compression_ratio_y, compression_ratio_z), 3),
"moment_major_ratio": round(moment_major_ratio, 3),
"moment_minor_ratio": round(moment_minor_ratio, 3),
"interaction_ratio_1": round(interaction_1, 3),
"interaction_ratio_2": round(interaction_2, 3),
"governing_interaction": round(governing_interaction, 3),
"status": status,
}
def _generate_remarks(
self,
inputs: SteelColumnInput,
design_type: str,
lambda_eff: float,
utilization: float,
governing_axis: str,
design_status: str,
ltb_applicable: bool,
) -> List[str]:
"""Generate design remarks and recommendations."""
remarks: List[str] = []
# Design type
remarks.append(f"Design type: {design_type}")
# Column classification
if lambda_eff < 50:
remarks.append("Short column - predominantly governed by material strength.")
elif lambda_eff < 140:
remarks.append("Intermediate column - buckling effects moderate.")
else:
remarks.append("Slender column - buckling is critical design consideration.")
# Governing axis
remarks.append(f"Design governed by buckling about {governing_axis.lower()} axis.")
# LTB consideration
if ltb_applicable:
remarks.append(
"Lateral-torsional buckling check applied - bending capacity reduced accordingly."
)
# Utilization assessment
if utilization < 0.6:
remarks.append("Member is under-utilized. Consider reducing section size for economy.")
elif 0.6 <= utilization <= 0.85:
remarks.append("Member utilization is optimal for economical design.")
elif 0.85 < utilization <= 1.0:
remarks.append(
"Member utilization is high. Design is adequate but consider larger section for safety margin."
)
else:
remarks.append(
"CRITICAL: Member capacity exceeded. Increase section size or reduce loads."
)
# Slenderness warning
if lambda_eff > 180:
remarks.append("WARNING: Slenderness ratio exceeds IS 800:2007 limit of 180 (Table 3).")
elif lambda_eff > 160:
remarks.append("Caution: Slenderness ratio is approaching the code limit.")
# Design status
if design_status == "SAFE":
if design_type == "Beam-Column":
remarks.append("Beam-column design is SAFE as per IS 800:2007 Sections 7 and 9.3.")
else:
remarks.append("Column design is SAFE as per IS 800:2007 Section 7.")
else:
remarks.append("Column design is UNSAFE. Revise section or reduce applied loads.")
# Code compliance
remarks.append(f"Design complies with IS 800:2007 for {inputs.steel_grade.value} steel.")
return remarks