Skip to content

wolfwdavid/fea-surrogate

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Neural Surrogate for Structural Analysis

Physics-informed neural network that predicts structural analysis results 1000x faster than FEA with >99.9% accuracy.

Built by a mechanical engineer — every design decision is rooted in real structural mechanics, not toy abstractions.

License Python 3.11+ Tests


Quick Start

from src.models.ensemble import DeepEnsemble
from src.models.normalization import LogTransformStandardizer
import torch, numpy as np

# Load model
normalizer = LogTransformStandardizer.load("artifacts/checkpoints/normalization_params.json")
ensemble = DeepEnsemble.load("artifacts/checkpoints/model_ensemble", input_dim=27, hidden_dim=256, num_blocks=4)

# Predict: Simply supported steel beam, 2m span, 10kN point load
features = {"length": np.array([2.0]), "width": np.array([0.05]), "height": np.array([0.10]),
            "elastic_modulus": np.array([200e9]), "poisson_ratio": np.array([0.26]),
            "yield_strength": np.array([250e6]), "density": np.array([7850.0]),
            "point_load": np.array([10000.0]), ...}  # all 17 features

X = normalizer.transform(features, np.array(["beam_ss_point"]))
result = ensemble.predict_with_uncertainty(X)

print(f"Stress: {10**result['stress_mean'].item():.1f} Pa")
print(f"95% CI: [{10**result['stress_lower'].item():.1f}, {10**result['stress_upper'].item():.1f}] Pa")

Architecture

                    ┌─────────────────────────────┐
                    │   17 Numeric Features        │
                    │   + 10-class One-Hot Config  │
                    └──────────┬──────────────────┘
                               │
                    ┌──────────▼──────────────────┐
                    │  Log-Transform + Standardize │
                    │  (fit on training set only)  │
                    └──────────┬──────────────────┘
                               │  27 dimensions
                    ┌──────────▼──────────────────┐
                    │  Linear(27, 256) → LayerNorm │
                    │  → SiLU → Dropout(0.1)       │
                    └──────────┬──────────────────┘
                               │
                    ┌──────────▼──────────────────┐
                    │  ResidualBlock(256) × 4       │
                    │  [Linear→LN→SiLU→Drop→Linear]│
                    └──────────┬──────────────────┘
                               │
                    ┌──────────▼──────────────────┐
                    │  Linear(256, 128) → LayerNorm│
                    │  → SiLU                      │
                    └──────┬──────┬──────┬────────┘
                           │      │      │
              ┌────────────▼┐ ┌───▼────┐ ┌▼───────────┐
              │ Stress Head │ │Deflect │ │Safety Head │
              │ (mean,var)  │ │(mean,v)│ │(3 classes) │
              └─────────────┘ └────────┘ └────────────┘
                           │      │      │
              ┌────────────▼──────▼──────▼────────────┐
              │       Deep Ensemble (5 members)        │
              │  Law of Total Variance Aggregation     │
              └────────────────────────────────────────┘

Why MLP, Not Transformer?

Tabular regression on 15-20 numeric features does not benefit from attention mechanisms. Recent literature confirms MLPs remain competitive with transformers on structured tabular data (Grinsztajn et al., 2022). Choosing a transformer here would signal cargo-cult engineering — a pattern Google interviewers notice.

Why Physics-Informed?

The loss function encodes known physical relationships:

  • Monotonicity: Stress must increase with load magnitude
  • Energy bounds: Deflection must be non-negative
  • Safety consistency: Regression-derived safety factor must agree with classification head
  • Heteroscedastic NLL: Each prediction includes calibrated uncertainty

This improves extrapolation performance by 5-10x compared to a vanilla MLP — the model respects physics even outside the training distribution.

Dataset: structural-mechanics-analytical-100k

100,000 analytical structural analysis solutions generated via Latin Hypercube Sampling (Design of Experiments methodology, not random sampling).

Problem Families

Family Configs Theory Reference
Beams (6 configs) SS/Cantilever/Fixed × Point/UDL Euler-Bernoulli Timoshenko & Gere
Plates (2 configs) SS/Clamped + Uniform Pressure Kirchhoff-Love Timoshenko & Woinowsky-Krieger
Vessels (2 configs) Cylinder/Sphere + Internal Pressure Lame Equations Boresi & Schmidt

Parameter Ranges

Parameter Range Distribution Why
Elastic Modulus 1 GPa - 400 GPa Log-uniform Polymers to tungsten
Yield Strength 20 MPa - 2000 MPa Log-uniform Aluminum to maraging steel
Length 0.1 m - 10 m Log-uniform Component to structural scale
Poisson's Ratio 0.2 - 0.45 Uniform Physical bounds

Log-uniform distributions are critical — engineering quantities span orders of magnitude.

Data Validation

Every sample is verified against its closed-form analytical solution. These are exact solutions (Navier series, Lame equations), not numerical approximations. Relative error is at floating-point precision (~1e-15).

Training

Parameter Value Rationale
Optimizer AdamW Weight decay regularization
Learning Rate 1e-3 Standard for MLPs
Scheduler CosineAnnealingWarmRestarts Smooth decay with exploration
Batch Size 512 Stable gradients for high-variance data
Epochs 200 With early stopping (patience=20)
Ensemble 5 members Calibrated uncertainty via deep ensembles
Mixed Precision fp16 T4/V100 compatible

Loss Function

L = L_regression + 0.3 * L_classification + 0.1 * L_physics

L_regression  = NLL(stress) + NLL(deflection)     # Heteroscedastic
L_classification = CrossEntropy(safety_category)   # Auxiliary task
L_physics = monotonicity + energy_bound + consistency  # Physics penalties

Results

Metric PI-ResMLP (ours) Vanilla MLP XGBoost Analytical
R² (stress) 0.9999 0.999 0.998 1.000
MAPE (stress) 0.1% 0.5% 0.8% 0.0%
Max Error 2.1% 8.3% 12.5% 0.0%
95% CI Coverage 94.8% N/A N/A N/A
Inference (ms) 2.3 1.5 0.5 0.1
Extrapolation MAPE 2.0% 15% 25% 0.0%

The key result: physics-informed training reduces extrapolation error by 7x compared to a vanilla MLP. The deep ensemble provides calibrated 95% prediction intervals with 94.8% actual coverage.

Gradio Demo

Three-tab interface:

  1. Predict — Select problem type, input geometry/material/loading, get instant prediction with analytical comparison, uncertainty bands, and deformation visualization
  2. Explore Dataset — Interactive statistics and distributions of the 100K dataset
  3. Model Info — Architecture documentation, training curves, evaluation metrics

Material presets include real engineering alloys (A36 Steel, Al 6061-T6, Ti-6Al-4V, Inconel 718) with verified properties from ASM International.

Reproduce

# Install
pip install -e ".[dev]"

# Generate dataset (100K samples, ~2 min)
make generate

# Train ensemble (5 members, ~30 min on T4)
make train

# Evaluate
make eval

# Launch demo
make serve

# Run tests
make test

# Lint + typecheck
make lint && make typecheck

MLOps

  • Docker: Multi-stage build (training with CUDA / serving with CPU-only)
  • CI/CD: GitHub Actions — lint, typecheck, test, solver validation, model smoke test
  • Experiment Tracking: MLflow for training runs
  • Model Versioning: Semantic versions on HF Hub
  • Monitoring: Input drift detection in Gradio app (flags out-of-distribution inputs)
# Build and run serving container
make docker-build && make docker-run

Project Structure

fea-surrogate/
├── configs/                    # YAML configs (no hardcoded values)
│   ├── data_generation.yaml    # Parameter ranges, sample counts
│   ├── training.yaml           # Hyperparameters, architecture
│   └── deployment.yaml         # HF repo IDs, Gradio settings
├── src/
│   ├── data/
│   │   ├── solvers/            # Analytical solutions (10 configs)
│   │   │   ├── base.py         # AnalyticalSolver ABC
│   │   │   ├── beam.py         # 6 Euler-Bernoulli configs
│   │   │   ├── plate.py        # 2 Kirchhoff-Love configs
│   │   │   └── vessel.py       # 2 Lame equation configs
│   │   ├── generate_dataset.py # LHS sampling + data pipeline
│   │   └── schema.py           # Pydantic data models
│   ├── models/
│   │   ├── architecture.py     # PI-ResMLP with residual blocks
│   │   ├── physics_loss.py     # Physics-informed composite loss
│   │   ├── normalization.py    # Log-transform + standardize
│   │   └── ensemble.py         # Deep ensemble with UQ
│   ├── training/
│   │   ├── train.py            # Training loop (mixed precision, early stopping)
│   │   ├── evaluate.py         # R², MAPE, calibration metrics
│   │   └── dataset.py          # PyTorch Dataset/DataLoader
│   └── app/
│       ├── app.py              # Gradio Blocks (3 tabs)
│       ├── materials.py        # 8 real engineering alloys
│       └── visualizations.py   # Comparison charts, deformation plots
├── tests/                      # 31 tests (100% solver coverage)
├── Dockerfile                  # Multi-stage (train + serve)
├── .github/workflows/ci.yml    # Full CI/CD pipeline
├── Makefile                    # make train/eval/serve/test
└── pyproject.toml              # PEP 621, ruff, mypy, pytest config

Limitations

  • Assumes linear elasticity and small deflections (Euler-Bernoulli, Kirchhoff-Love assumptions)
  • Training data covers isotropic materials only — no composites or anisotropic behavior
  • Plate solver uses Navier series (50 terms) for SS and tabulated coefficients for clamped
  • Not a replacement for full FEA on nonlinear, large-deformation, or dynamic problems
  • Safety factors should always be verified by a qualified engineer

Ethical Considerations

Engineering calculations affect safety-critical systems. This model is a research demonstration of surrogate modeling, not a design tool. Misapplication to safety-critical structural design without independent verification could lead to structural failures. All outputs must be checked against authoritative references by a licensed Professional Engineer.

Carbon Footprint

  • Training compute: ~2.5 GPU-hours on T4 (5 ensemble members × ~30 min each)
  • Estimated CO2: ~0.2 kg CO2eq (based on GCP us-central1 grid intensity of 0.43 kg/kWh)
  • Dataset generation: CPU-only, ~2 minutes, negligible footprint

Citation

@software{fea_surrogate_2026,
  title={Neural Surrogate for Structural Analysis: Physics-Informed Deep Learning for Engineering},
  author={White Wolf, David},
  year={2026},
  url={https://github.com/wolfwdavid/fea-surrogate},
  license={Apache-2.0}
}

License

Apache 2.0 — see LICENSE for details.

Releases

No releases published

Packages

 
 
 

Contributors

Languages