# Model card: gusset-plate MLP surrogate

- **run id**: committed
- **trained at**: 2026-06-11 17:06:48 (committed repo artifact)
- **architecture**: 6 -> 64 -> 64 -> 2 MLP, tanh, standardized X and y (sklearn MLPRegressor, adam)
- **training data**: 7500 plane-stress FEM solves (gmsh + scikit-fem, P2 triangles, h=14 mm converged mesh), Latin hypercube, seed 42
- **test data**: 1500 independent FEM solves, separate seed 1337 (no leakage)
- **inputs**: W [mm], H [mm], t [mm], theta [deg], |P| [kN], Lc_eff [mm]
- **outputs**: peak von Mises stress [MPa], max displacement [mm]

## Valid domain (training ranges; do not trust predictions outside)

| parameter | range |
|---|---|
| W | 300 to 800 |
| H | 300 to 800 |
| t | 8 to 25 |
| theta | 30 to 60 |
| P | 100 to 1500 |
| Lc | 100 to 300 |

The model sees the brace force magnitude: in a linear elastic model tension
and compression mirror the stress field and the von Mises peak is identical.
Lc_eff is the connection length after geometric clamping (small plates at
extreme angles cannot fit the longest connections; the solver clamps and
reports).

## Held-out test metrics (n = 1500, FEM ground truth)

| output | GBM R2 | GBM MAE | MLP R2 | MLP MAE | MLP max err |
|---|---|---|---|---|---|
| peak von Mises [MPa] | 0.99800 | 4.845 | 0.99987 | 1.266 | 20.14 |
| max displacement [mm] | 0.99336 | 0.008 | 0.99970 | 0.002 | 0.03 |

Shipped: **MLP (direct)** (the browser needs a plain forward pass).

## Dataset sanity gates (enforced by generate.py before any sampling)

- reaction equilibrium vs applied load, gate 0.5%: worst sample in this
  dataset 0.00e+00%
- linearity at P vs P/2: ratio 2.0 to 9 decimals (see generation_log.txt)
- Whitmore hand stress vs FEM average over the Whitmore width: ratio
  0.534 to 1.486 across the dataset
  (mean 1.119); documented, not forced

## Timing (measured)

- FEM solve at the converged mesh: 0.89 s mean
  (0.23 to 2.55 s; ~51,702 DOF mean)
- surrogate forward pass: 6.11 us single,
  0.374 us/sample batched
- speedup: ~145,172x single,
  ~2,371,658x batched

## Parity

Manual numpy forward pass vs sklearn pipeline: max |deviation| =
0.00e+00. The browser re-runs 5 exported reference points
through its JS forward pass on every load and shows PASS/FAIL.

## Scope and honesty

Linear elastic plane stress, one plate configuration family (corner gusset,
two fixed edges, chamfered free corner, single brace). No buckling (the real
compression failure mode), no bolt holes, no welds, no out-of-plane action.
The capacity ratio (peak von Mises / Fy) is a screening number, not a
connection design. No LLM was involved at any stage.
