Get a comparison plot in under a minute:
/). The main page loads with default parameters for both criteria (mild steel AA6014-T4 proxy).postMessage call to /api/yield-surface./manual for full parameter documentation.Each slider interaction triggers a chain from browser to constitutive math and back to the plot iframe:
%%{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",
"noteBkgColor": "#f5f1e8",
"noteTextColor": "#1d2330",
"noteBorderColor": "#c2613a",
"activationBkgColor": "#c2613a",
"altBackground": "#f5f1e8"
}
}}%%
flowchart LR
A[Browser slider input] -->|postMessage params| B[index.html JS]
B -->|GET /api/yield-surface?...| C[FastAPI route]
C -->|vegter2017_locus| D[app.math β Vegter 2017]
C -->|bbc2005_locus| E[app.math β BBC-05]
D -->|normalised s1 s2 + convex flag| F[JSON response]
E -->|normalised s1 s2 + convex flag| F
F -->|postMessage locus arrays| G[iplot_comparison iframe]
G -->|Plotly.restyle| H[Comparison plot SVG]
Normalisation: Vegter locus points are divided by Οun; BBC-05 points by Οy. Both curves therefore sit in dimensionless stress space anchored near (1, 0) for direct shape comparison regardless of absolute yield stress.
Error handling: if the math module raises CalibrationError or QualityGateError the API returns an empty locus array and the convexity badge turns red β the plot clears that criterion without crashing.
The plot shows normalised plane-stress yield loci in the (Οβ/Οref, Οβ/Οref) space:
Shape comparisons to watch:
A typical low-carbon steel has rβ β 1.8, rββ β 1.0, rββ β 2.2 and equibiaxial stress close to uniaxial. Set:
Expected: a rounded locus with a noticeable shoulder near the plane-strain point. The badge should read CONVEX.
FCC aluminium has lower r-values and equibiaxial stress slightly above uniaxial. Set BBC-05 with k = 4 (FCC). Default coefficients (a = 0.89, b = 0.92, β¦) are tuned for an aluminium-like response. Compare to Vegter with Οeb/Οun β 1.05.
Push k = 4 and set N = 2.5. The locus develops very sharp corners; the convexity badge turns NON-CONVEX once the cross-product check (Pilthammar 2020 Β§3) detects a sign reversal. Reduce N or switch to k = 3 to restore convexity.
The root route renders webapp/templates/index.html via Jinja2. It serves:
/plot/comparison) that listens for postMessage events from the parent.No authentication required. The page is stateless β slider state lives in the DOM only; refreshing resets everything to defaults.
Accepts 17 query parameters (7 Vegter + 10 BBC-05) and returns a JSON object with both normalised loci and anchor points:
{
"vegter": { "s1": [...], "s2": [...], "convex": true, "error": null },
"bbc05": { "s1": [...], "s2": [...], "convex": true, "error": null },
"vegter_anchors": {
"uniaxial_RD": [1.0, 0.0],
"plane_strain": [1.2, 0.6],
"equibiaxial": [1.05, 1.05],
"shear": [-0.6, 0.6]
}
}All s1/s2 values are dimensionless (normalised by the respective reference yield stress). On math failure the locus arrays are empty and convex is false.
Renders the axes-only Plotly iframe template (webapp/templates/iplot_comparison.html). The iframe listens for window.addEventListener('message', β¦) events from the parent and calls Plotly.restyle to update both traces without a full page reload.
The Plotly chart is configured with displayModeBar: false and hovermode: false for a clean engineering-drawing aesthetic β controls live outside the iframe, not inside it.
Renders all MANUAL_ENTRIES from app/manual_content.py as a scrollable list of panels, with KaTeX math rendered client-side and inline citation superscripts linking to the collapsible reference list at the bottom.
A contributions sheet (/manual/contributions) aggregates the per-agent contributions/*.json files and is downloadable as PDF via /manual/contributions.pdf (headless Chromium).
The Vegter locus is anchored on four stress states and three r-values from standard sheet metal tests (Vegter & van den Boogaard 2006, pp. 558β560):
| Parameter | Unit | Range (app) | Default | Physical meaning |
|---|---|---|---|---|
| Οun | MPa | 50β2000 | 200 | Uniaxial yield stress in RD (normalisation reference). Must be > 0. |
| Οps | MPa | 50β2500 | 240 | Plane-strain yield stress in RD (Ξ΅β = 0 constraint). Von Mises baseline: $\sigma_{ps} = \frac{2}{\sqrt{3}}\sigma_{un} \approx 1.155\,\sigma_{un}$. |
| Οsh | MPa | 30β1200 | 120 | Pure-shear yield stress. Von Mises baseline: $\sigma_{sh} = \sigma_{un}/\sqrt{3} \approx 0.577\,\sigma_{un}$. |
| Οeb | MPa | 50β2000 | 210 | Equibiaxial yield stress from ISO 16808 hydraulic bulge test. |
| rβ | β | 0.30β3.00 | 0.80 | Lankford r-value at 0Β° (RD). Plastic width-to-thickness strain ratio per ISO 10113. |
| rββ | β | 0.30β3.00 | 1.20 | Lankford r-value at 45Β°. Sets hinge bias in the off-axis quadrant. |
| rββ | β | 0.30β3.00 | 1.00 | Lankford r-value at 90Β° (TD). Mirrors rβ role for TD uniaxial. |
BBC-05 uses eight anisotropy coefficients plus an integer exponent k (Banabic et al. 2005, eq. 5, p. 497):
| Parameter | Unit | Range | Default | Role |
|---|---|---|---|---|
| a | β | 0.10β3.00 | 0.890 | Weight on ΞΒ±Ξ terms; must be > 0 (eq. 8). |
| b | β | 0.10β3.00 | 0.920 | Weight on 2Ξ¨ term; must be > 0 (eq. 8). |
| L, M | β | 0.10β3.00 | 1.080, 0.800 | Coefficients of first linear transformation: Ξ = LΟxx + MΟyy. |
| N, P | β | 0.10β3.00 | 1.150, 1.050 | Coefficients computing Ξ = β[(NΟxx β PΟyy)Β² + ΟxyΒ²]. |
| Q, R | β | 0.10β3.00 | 0.920, 1.000 | Coefficients computing Ξ¨ = β[(QΟxx β RΟyy)Β² + ΟxyΒ²]. |
| k | integer | 3 or 4 | 3 | Crystal-structure exponent: 3 for BCC (steel), 4 for FCC (aluminium). Higher k β sharper locus corners (Pilthammar 2020 Β§2). |
| Οy | MPa | 50β2000 | 200 | Reference uniaxial yield stress used for normalisation of the output locus. |
The two criteria use different absolute yield stresses, so raw MPa values are not directly comparable. The API normalises each locus before returning it:
With both loci anchored at the same dimensionless point, the plot shows pure shape differences β how the two criteria predict anisotropy at plane-strain, equibiaxial, and shear stress states.
The Vegter 2017 implementation in this v0.1 release covers the upper half of the yield locus (anchors aββaβ : uniaxial RD, plane-strain RD, equibiaxial, plane-strain TD, uniaxial TD) with full-fidelity BΓ©zier arcs. The lower half (compression quadrants, anchors aββaβ) uses a sparse 3-anchor sketch that drifts up to ~42% from the von Mises reference in the isotropic limit (r = 1, all anchor stresses equal).
Practical implication. For tension-dominated forming (deep drawing, stretch forming, bending under tension) the upper-half locus is what governs the result and v0.1 is faithful. For compression-dominated paths (springback after unloading, reverse loading) prefer the BBC-2005 panel β it has a continuous analytic locus across all four quadrants.
v0.2 will mirror anchors aββaβ into the lower half (8 new anchors total) and re-route the BΓ©zier walker to 16 arcs. Tracked in docs/v0_2_backlog.md.
See also: Vegter 2017 yield criterion β BΓ©zier interpolation and BBC-05 yield criterion β two linear transformations.
Vegter & van den Boogaard (2006) represent the plane-stress yield locus as a C0-continuous chain of quadratic BΓ©zier arcs between eight reference (anchor) points in the (Οxx, Οyy) plane (eq. 4, p. 560):
$$\mathbf{r}(t) = (1-t)^2\,\mathbf{p}_0 + 2(1-t)t\,\mathbf{p}_1 + t^2\,\mathbf{p}_2, \quad t \in [0,1]$$
The four physical anchor points per half-locus are:
The hinge point pβ between two anchors is the intersection of the locus tangent lines at the endpoints (eq. 6, p. 561). Tangent directions are taken from the von Mises gradient and then rotated by an r-valueβdependent angle:
$$\delta\theta = \arctan\!\left(\frac{r - 1}{r + 1}\right)$$
This rotation biases the BΓ©zier arc toward the anchor whose r-value is being honoured: r = 1 (isotropic) gives zero rotation and recovers the von Mises ellipse; r > 1 widens the arc; r < 1 narrows it.
Convexity gate: the signed cross product of consecutive chord vectors must not change sign around the full locus. A sign change triggers QualityGateError('Vegter locus is non-convex').
Banabic et al. (2005) define the BBC-05 effective stress via two linear transformations of the Cauchy stress (eq. 5, p. 497):
$$\Gamma = L\,\sigma_{xx} + M\,\sigma_{yy}$$
$$\Lambda = \sqrt{(N\sigma_{xx} - P\sigma_{yy})^2 + \sigma_{xy}^2}$$
$$\Psi = \sqrt{(Q\sigma_{xx} - R\sigma_{yy})^2 + \sigma_{xy}^2}$$
$$\bar{\sigma} = \left[ a(\Gamma+\Lambda)^{2k} + a(\Gamma-\Lambda)^{2k} + b(2\Psi)^{2k} \right]^{1/(2k)}$$
where $k \in \{3, 4\}$ (BCC / FCC) and $a, b > 0$ (positivity constraint, eq. 8). The yield locus is the level set $\bar{\sigma}(\sigma_{xx}, \sigma_{yy}, 0) = \bar{\sigma}(\sigma_y, 0, 0)$, traced by bisection along 360 radial directions.
Calibration note (Pilthammar 2020): non-integer k and high N values can produce non-convex loci that fail the cross-product gate. The app enforces k β {3, 4} and raises CalibrationError on illegal values.
Drucker's postulate requires a convex yield surface for the associated flow rule to yield unique plastic strain increments (Banabic 2010, Β§4). The app tests convexity by checking the sign of the cross product of consecutive chord vectors:
$$z_i = (\mathbf{p}_{i+1} - \mathbf{p}_i) \times (\mathbf{p}_{i+2} - \mathbf{p}_{i+1})$$
For a counter-clockwise locus, all $z_i$ must be $\geq -\epsilon$ (convex) or all $\leq +\epsilon$ (convex in the other orientation). A mixed-sign result means the locus has a concave region and triggers QualityGateError.
Pilthammar (2020) Β§3 documents that BBC-05 with large N or high k can develop concavity near the equibiaxial point. Reduce N or switch k = 3 β k = 4 to recover convexity for those parameter sets.