Architecture

System Overview

StructEngine-v2 is a full-stack web application for IS code-compliant structural engineering calculations. The system follows a calculator pattern architecture where each calculator is a self-contained module implementing the BaseCalculator interface.

Tech Stack:

  • Backend: FastAPI (Python 3.11) with Pydantic for validation

  • Frontend: Vue.js 3 with TypeScript

  • Documentation: Sphinx with autodoc and napoleon

  • Standards: IS 456:2000 (Concrete), IS 800:2007 (Steel), IS 875:1987 (Loads), IS 1893 (Seismic)

Module Structure

        graph TD
    A[FastAPI App] --> B[Calculator Router]
    B --> C[Analysis Module]
    B --> D[Concrete Module]
    B --> E[Steel Module]

    C --> F[Section Properties]
    C --> G[Beam Analysis]

    D --> H[Beam Design]
    D --> I[Column Design]
    D --> J[Slab Design]
    D --> K[Crack Width]
    D --> L[Footings]

    E --> M[Base Plate]
    E --> N[Steel Column]
    E --> O[Purlin Design]
    E --> P[Gantry Girder]

    style A fill:#f9f,stroke:#333,stroke-width:2px
    style B fill:#bbf,stroke:#333,stroke-width:2px
    style C fill:#bfb,stroke:#333,stroke-width:2px
    style D fill:#fbf,stroke:#333,stroke-width:2px
    style E fill:#ffb,stroke:#333,stroke-width:2px
    

Module Organization:

api/app/calculators/
├── base.py                    # BaseCalculator interface
├── analysis/
│   ├── section_properties.py  # Geometric properties
│   └── beam_analysis.py       # Deflection, moments, shear
├── concrete/                  # IS 456:2000
│   ├── conc_beam_design.py
│   ├── conc_column_design.py
│   ├── slab_design.py
│   ├── crack_width.py
│   └── footing_types/
└── steel/                     # IS 800:2007
    ├── base_plate.py
    ├── steel_column.py
    ├── purlin_design.py
    └── gantry_girder.py

Calculation Flow

        sequenceDiagram
    participant Client
    participant FastAPI
    participant Router
    participant Calculator
    participant Pydantic
    participant ISCode

    Client->>FastAPI: POST /api/calculators/{type}/calculate
    FastAPI->>Router: Route to calculator
    Router->>Pydantic: Validate input schema
    Pydantic->>Calculator: Pass validated inputs
    Calculator->>ISCode: Apply IS code checks
    ISCode->>Calculator: Return compliance status
    Calculator->>Pydantic: Create output schema
    Pydantic->>FastAPI: Validated output
    FastAPI->>Client: JSON response
    

Request/Response Pattern:

  1. Client request with calculator inputs (JSON)

  2. Pydantic validation ensures type safety and constraints

  3. Calculator.calculate() performs IS code-compliant calculations

  4. IS code checks validate against clause requirements

  5. Pydantic output structures results with IS references

  6. JSON response returns to client

Design Patterns

### 1. Strategy Pattern

Used in Column Design for short vs. long column calculations:

class ColumnDesignStrategy:
    """Strategy interface for column design."""

    def calculate_slenderness_moment(
        self,
        geometry: ColumnGeometry,
        factored_axial_load: float,
        effective_length: float,
        depth_or_width: float
    ) -> float:
        raise NotImplementedError

class ShortColumnStrategy(ColumnDesignStrategy):
    """Short columns: slenderness moment = 0"""

    def calculate_slenderness_moment(...) -> float:
        return 0.0

class LongColumnStrategy(ColumnDesignStrategy):
    """Long columns: IS 456 Clause 39.7.1"""

    def calculate_slenderness_moment(...) -> float:
        return (P × L²) / (2000 × D × 1000)

### 2. Parameter Objects (Dataclasses)

Group related inputs to reduce function complexity:

from dataclasses import dataclass

@dataclass
class ColumnGeometry:
    """Parameter object for column geometry."""
    width: float          # B (mm)
    depth: float          # D (mm)
    unsupported_length_x: float
    unsupported_length_y: float
    clear_cover: float
    main_bar_dia: float
    tie_dia: float

@dataclass
class MaterialProperties:
    """Parameter object for material properties."""
    fck: float  # Concrete grade (N/mm²)
    fy: float   # Steel grade (N/mm²)

### 3. Method Extraction

Keep cyclomatic complexity < 10 per method:

class BeamDesignCalculator(BaseCalculator):

    def calculate(self, inputs: dict) -> dict:
        # High-level orchestration
        geometry = self._extract_geometry(inputs)
        loads = self._calculate_loads(geometry, inputs)
        moments = self._calculate_moments(loads)
        steel = self._design_steel(moments, geometry)
        shear = self._design_shear(loads, geometry, steel)

        return self._create_output(geometry, steel, shear)

    def _extract_geometry(self, inputs: dict) -> Geometry:
        """Single-purpose method."""
        pass

    def _calculate_loads(self, geometry: Geometry, inputs: dict) -> Loads:
        """Single-purpose method."""
        pass

IS Code Integration

### IS Code Reference Format

All calculators reference IS codes in docstrings:

def calculate_flexural_strength(self, d: float, Ast: float, fck: float, fy: float) -> float:
    """
    Calculate ultimate moment capacity per IS 456:2000 Clause 38.1.

    Args:
        d: Effective depth (mm)
        Ast: Area of tension steel (mm²)
        fck: Characteristic compressive strength of concrete (N/mm²)
        fy: Yield strength of steel (N/mm²)

    Returns:
        Ultimate moment capacity (kN-m)

    References:
        IS 456:2000 Clause 38.1 - Assumptions for flexure
        IS 456:2000 Clause G-1.1 - Stress-strain curve for concrete
    """
    pass

### IS Code Clause Mapping

IS 456:2000 (Concrete):

  • Clause 26.5.1.1: Flexural design

  • Clause 26.5.1.6: Shear design

  • Clause 39.4: Column axial capacity

  • Clause 39.7.1: Slenderness effects

  • Clause 35.3: Crack width limits

IS 800:2007 (Steel):

  • Clause 7.4.3: Base plate bearing

  • Clause 8.2: Column buckling

  • Clause 8.7: Lateral-torsional buckling

  • Table 2: Section classification

IS 875:1987 (Loads):

  • Part 1: Dead loads

  • Part 2: Live loads

  • Part 3: Wind loads

### Where IS Code Checks Are Implemented

  1. Input validation: Pydantic Field constraints ensure IS code limits

  2. Material properties: Grade mappings (M25, Fe415) from IS codes

  3. Calculation methods: Direct implementation of IS code formulas

  4. Output validation: Capacity ratios, safety factors per IS codes

  5. Remarks: Warnings if design violates IS code limits

Type Safety and Validation

### Strict Type Hints

All functions use type hints per Agent.md guidelines:

from typing import Dict, List, Tuple, Optional

def analyze_beam(
    span: float,
    loads: List[float],
    material: str
) -> Dict[str, float]:
    """Type hints are mandatory."""
    pass

### Pydantic Validation

Input/output schemas enforce constraints:

class BeamDesignInput(BaseModel):
    width: float = Field(..., gt=0, le=2000, description="Width in mm")
    concrete_grade: str = Field(..., regex="^M(15|20|25|30|35|40|45|50)$")
    steel_grade: str = Field(..., regex="^Fe(250|415|500|550)$")

Adding IS Code References

Step 1: Identify applicable IS code clause

Step 2: Add reference to docstring:

def check_deflection(self, span: float, deflection: float) -> bool:
    """
    Check deflection limits per IS 456:2000 Clause 23.2.

    Limit: span/250 for general structures.
    """
    pass

Step 3: Implement formula from IS code:

limit = span / 250  # IS 456:2000 Clause 23.2(a)
return deflection <= limit

Step 4: Add to output remarks:

if not deflection_ok:
    remarks.append("Deflection exceeds IS 456:2000 Clause 23.2 limits")

Testing Architecture

### Unit Tests

Test individual calculator methods:

def test_flexural_capacity():
    calc = BeamDesignCalculator()
    result = calc._calculate_flexural_capacity(
        d=450, Ast=1256, fck=25, fy=415
    )
    assert result > 0

### Integration Tests

Test full calculate() flow:

def test_beam_design_full():
    calc = BeamDesignCalculator()
    result = calc.calculate({
        "width": 300,
        "depth": 500,
        # ... full inputs
    })
    assert result["status"] == "PASS"

### API Tests

Test FastAPI endpoints:

def test_beam_design_endpoint(client):
    response = client.post(
        "/api/calculators/beam_design/calculate",
        json={...}
    )
    assert response.status_code == 200

Performance Considerations

  • Caching: Material property lookups cached

  • Vectorization: NumPy used for section analysis

  • Profiling: interrogate enforces 80%+ docstring coverage

  • Type checking: mypy runs in pre-commit hooks

Next Steps