The Forming Quality Analyser takes a minimal material card and a measured strain state, then classifies forming quality as PASS / MARGINAL / FAIL.
/.POST /api/assess returns the verdict in <100 ms.Data flows left-to-right: the material card feeds physics functions that compute the FLD safety margin and thinning ratio; the classifier combines them into a verdict. [3] [4]
%%{init: {"theme":"base","themeVariables":{"fontFamily":"IBM Plex Sans, system-ui, sans-serif","fontSize":"13px","background":"#fbfaf6","primaryColor":"#fbfaf6","primaryTextColor":"#1d2330","primaryBorderColor":"#c8c1ad","lineColor":"#3a414f","secondaryColor":"#f5f1e8","tertiaryColor":"#fbfaf6"}}}%%
flowchart LR
mc["Material Card\nK ยท n ยท rโ ยท rโโ
ยท rโโ ยท tโ"] --> flc["fld0_keeler_brazier\nforming_limit_curve"]
mc --> hard["hollomon_flow_stress\nHardening plot"]
mc --> hill["hill48_equivalent_stress\nYield surface"]
ss["Strain state\nฮตโ ยท ฮตโ"] --> margin["safety_margin_to_fld"]
flc --> margin
ss --> thin["thinning_ratio"]
mc --> thin
margin --> cls["classify_quality"]
thin --> cls
cls --> vrd["QualityResult\nPASS / MARGINAL / FAIL"]
hard --> hplot["Hardening-curve tile\n/plot/hardening"]
flc --> fplot["FLD tile\n/plot/fld"]
ss --> fplot
The plot tiles update via postMessage from the outer page โ sliders do not reload the iframe; they push new curve data over GET /api/preview.
PASS (green) โ FLD safety margin > 0.10 AND thinning < 20 %. The part meets all forming-quality criteria.
MARGINAL (amber) โ margin in (0, 0.10] OR thinning in [20 %, 25 %). The part is near the forming limit โ review recommended.
FAIL (red) โ margin โค 0 (strain state above the FLC) OR thinning โฅ 25 %. Do not ship. [3]
A margin of 0.10 means the measured major strain sits 10 % below the forming-limit curve at the same minor strain. The FLD tile marks the operating point as a filled circle against the copper-coloured FLC. The closer the circle is to the curve, the higher the forming risk. A circle above the curve is a FAIL. [3] [4]
A thinning ratio of 0.25 (25 %) is the industry rule-of-thumb red line for forming-grade steels and aluminiums. If measured_thickness_mm is omitted, thinning is estimated from the strain state via volume conservation: $\theta \approx 1 - e^{-(\varepsilon_1+\varepsilon_2)}$.
The flags array in the API response carries human-readable reasons โ e.g. ABOVE FLC โ margin -0.042 or THINNING 26.3% >= 25% limit.
Typical DP800 deep-draw with a moderate strain state:
POST /api/assess
{
"name": "DP800",
"thickness_mm": 1.5,
"K_mpa": 1310,
"n": 0.16,
"r0": 0.83, "r45": 0.94, "r90": 0.97,
"major_strain": 0.15,
"minor_strain": -0.05
}Expected response: verdict = "PASS", fld_safety_margin โ 0.31, thinning_ratio โ 0.09. The operating point sits well below the Keeler-Brazier FLC on the drawing side (ฮตโ < 0). [3]
HSLA350 blank with a strain state above the FLC (biaxial stretching corner):
POST /api/assess
{
"name": "HSLA350",
"thickness_mm": 2.0,
"K_mpa": 650,
"n": 0.18,
"r0": 1.1, "r45": 0.9, "r90": 1.0,
"major_strain": 0.42,
"minor_strain": 0.05
}Expected response: verdict = "FAIL", FLD margin < 0 (operating point above the FLC stretching-side arm). Remediation: increase blank-holder force or reduce punch travel to keep ฮตโ below FLDโ + 0.6 ฮตโ. [3] [4]
The dashboard (GET /) provides the complete single-page analysis workflow: material-card sliders, strain-state inputs, an Assess button, a quality-verdict panel, and two live Plotly iframe tiles (FLD and hardening curve).
Sliders call GET /api/preview on every change and push updated curve data into the plot iframes via window.postMessage, keeping both plots in sync without a full page reload.
POST /api/assess โ primary quality-assessment endpoint. Accepts a JSON body matching the MaterialCardInput schema and returns a QualityResult object.
| Field | Range | Default | Description |
|---|---|---|---|
name | โ | DP800 | Grade designation (label only) |
thickness_mm | 0.5โ6.0 mm | 1.5 | Nominal blank thickness |
K_mpa | 100โ3000 MPa | 1310 | Hollomon strength coefficient [2] |
n | 0.01โ0.60 | 0.16 | Hollomon strain-hardening exponent [2] |
r0 | 0.1โ4.0 | 0.83 | Lankford rโ at rolling direction [1] |
r45 | 0.1โ4.0 | 0.94 | Lankford rโโ at 45ยฐ [1] |
r90 | 0.1โ4.0 | 0.97 | Lankford rโโ at transverse direction [1] |
major_strain | 0โ1 | 0.15 | Major engineering strain ฮตโ |
minor_strain | โ0.5โ0.5 | โ0.05 | Minor engineering strain ฮตโ |
measured_thickness_mm | 0.5โ6.0 | null | null | Direct thickness measurement; if omitted, thinning derived from strains |
QualityResult)| Field | Type | Description |
|---|---|---|
verdict | str | "PASS", "MARGINAL", or "FAIL" |
score_pct | float [0, 100] | Normalised quality score (convenience indicator) |
fld_safety_margin | float | Fractional distance below FLC; negative = above limit |
thinning_ratio | float | (tโ โ t) / tโ; โฅ 0.25 triggers FAIL |
message | str | Human-readable verdict summary |
flags | list[str] | Active failure / warning reasons |
GET /api/preview โ lightweight endpoint for live slider updates. Returns FLC trace data (200 points) and Hollomon hardening-curve data (200 points) as plain Python lists.
The outer-page JavaScript posts this data into the plot iframes via window.postMessage, triggering a Plotly.restyle call inside each iframe without reloading the iframe source. This keeps the UI responsive at slider-drag frequency.
Parameters: same as MaterialCardInput passed as query-string arguments.
Response shape:
{
"fld": {"eps2": [...], "eps1": [...]},
"hardening": {"eps": [...], "sigma": [...]},
"operating_point": {"major": float, "minor": float}
}
GET /plot/fld โ standalone axes-only Forming Limit Diagram tile rendered via Plotly. Draws the FLC (copper line) and the current operating point (filled circle).
Designed as an iframe tile: the outer page loads it once and then pushes live updates via postMessage without reloading the iframe src. Accepts the full material-card and strain parameters as query-string arguments for the initial render.
The FLC is computed by forming_limit_curve() using the Keeler-Brazier intercept. [3]
GET /plot/hardening โ standalone axes-only Hollomon hardening-curve tile. Shows flow stress ฯ (MPa) vs. plastic strain ฮตโ over [0.0001, 0.50]. Same postMessage live-update pattern as the FLD tile. [2]
Useful for checking whether the K and n values entered are physically reasonable for the grade โ compare visually against typical tensile-test curves for the same grade.
The FLD safety margin quantifies how far the measured strain state lies below the Forming Limit Curve at the same minor strain. [3] [4]
$$m = \frac{\varepsilon_1^{\text{limit}}(\varepsilon_2) - \varepsilon_1^{\text{meas}}}{\varepsilon_1^{\text{limit}}(\varepsilon_2)}$$where $\varepsilon_1^{\text{limit}}(\varepsilon_2)$ is the FLC ordinate at the measured minor strain (from forming_limit_curve()), and $\varepsilon_1^{\text{meas}}$ is the measured major strain.
The thinning ratio measures the fractional thickness loss at the point of interest.
$$\theta = \frac{t_0 - t_{\text{meas}}}{t_0}$$where $t_0$ is the nominal blank thickness and $t_{\text{meas}}$ is either the directly measured thickness or the value derived from volume conservation under plane stress:
$$t_{\text{meas}} = t_0 \exp(-(\varepsilon_1 + \varepsilon_2))$$Industry rule-of-thumb limits for forming-grade steel and aluminium:
The classifier applies two independent checks and combines them to a three-bucket verdict. A single-metric FAIL overrides the overall verdict regardless of the other metric. [3]
| Verdict | FLD margin condition | Thinning condition |
|---|---|---|
| PASS | $m > 0.10$ | $\theta < 0.20$ |
| MARGINAL | $0 < m \leq 0.10$ | $0.20 \leq \theta < 0.25$ |
| FAIL | $m \leq 0$ | $\theta \geq 0.25$ |
Rule precedence: FAIL is checked first, then MARGINAL, then PASS.
The quality score maps the two forming metrics to a single scalar in [0, 100] for display on the gauge tile. It is a convenience indicator only โ the shipping decision is made by classify_quality, not by this score.
where $m$ is the FLD safety margin and $\theta$ is the thinning ratio. A score of 100 corresponds to a 100 % safety margin and zero thinning. At the FAIL boundary (margin = 0, thinning = 0.25), the score resolves to approximately 50.
The normal anisotropy $\bar{r}$ summarises directional plastic resistance to thinning. It is used internally to parametrise the Hill-1948 yield criterion. [1]
$$\bar{r} = \frac{r_0 + 2r_{45} + r_{90}}{4}$$A value $\bar{r} > 1$ indicates good resistance to thinning โ the material deforms laterally rather than through the thickness. Typical values: DP800 โ 0.9, IF steel โ 1.8, AA6014 โ 0.6.
The Hill-1948 quadratic yield criterion computes the equivalent stress for anisotropic sheet-metal under plane-stress conditions. [1]
$$\bar{\sigma} = \sqrt{(G+H)\sigma_{xx}^2 - 2H\sigma_{xx}\sigma_{yy} + (F+H)\sigma_{yy}^2 + 2N\sigma_{xy}^2}$$The anisotropy coefficients are parametrised by the Lankford r-values via the standard substitution (Hill 1948, eq. 5.7, p. 286):
$$G = \frac{1}{1+r_0}, \quad H = \frac{r_0}{1+r_0}, \quad F = \frac{r_0}{r_{90}(1+r_0)}, \quad N = \frac{(r_0+r_{90})(1+2r_{45})}{2r_{90}(1+r_0)}$$The quadratic form is positive semi-definite for positive r-values, so $\bar{\sigma} \geq 0$ by construction. A QualityGateError is raised if the computed equivalent stress is non-finite.
Hollomon's power law relates flow stress to equivalent plastic strain for metals in the work-hardening regime. [2]
$$\sigma = K \varepsilon_p^n$$where $K$ (MPa) is the strength coefficient and $n$ is the strain-hardening exponent (Hollomon 1945, eq. 3, p. 271). Valid domain: $\varepsilon_p > 0$, $n \in (0, 1)$. Typical values for DP800: $K \approx 1310$ MPa, $n \approx 0.16$. The exponent $n$ also controls the Keeler-Brazier FLDโ intercept โ higher $n$ raises the forming limit. [3]
A CalibrationError is raised for negative strain inputs (Hollomon is undefined for $\varepsilon_p < 0$).
The Keeler-Brazier formula gives the plane-strain intercept FLDโ of the forming-limit curve as a function of sheet thickness and hardening exponent. [3]
$$\text{FLD}_0 = \frac{23.3 + 14.13\,t}{100} \cdot \frac{n}{0.21}$$where $t$ is the sheet thickness in mm and $n$ is the Hollomon exponent (Keeler & Brazier 1977, eq. 4, p. 521). The factor $(n/0.21)$ normalises the original Keeler curve (fit on $n = 0.21$ mild steel) to the material at hand.
Validity window: $0.5 \leq t \leq 3$ mm. The app saturates $t$ at 3 mm for thicker blanks to avoid extrapolating outside the empirically calibrated range. [4]
The full FLC is constructed by a two-slope linearisation anchored at the plane-strain intercept FLDโ (Keeler-Brazier [3], conceptual basis M-K [4]):
$$\varepsilon_1^{\text{limit}}(\varepsilon_2) = \begin{cases}\text{FLD}_0 - \varepsilon_2 & \varepsilon_2 \leq 0 \;\text{(drawing side, slope} -1\text{)} \\\text{FLD}_0 + 0.6\,\varepsilon_2 & \varepsilon_2 > 0 \;\text{(stretching side, slope} +0.6\text{)}\end{cases}$$The drawing-side slope of $-1$ reflects that deep-drawing is constrained by the same total major strain regardless of minor strain. The stretching-side slope of $+0.6$ is the standard M-K-derived envelope value used by most press-shop FLD overlays. [4]
The classify_quality() function applies a two-variable rule table to issue the three-bucket verdict. Thresholds are industry-typical values for forming-grade sheet steels and aluminium alloys. [3]
Rule (evaluated in order โ first match wins):
A hard FAIL on either metric overrides the other metric's result โ there is no weighted averaging. A part that clears the FLD check but exceeds the thinning limit is a FAIL.