Pass through failure of compressible material failure. - #35
Conversation
…tretch packing
The through-thickness Newton solve for the compressible plane-stress
condition S33(c33)=0 could not report failure: it raised GISMO_ENSURE from
inside gsExprAssembler's OpenMP region, where no handler above the parallel
construct can catch it, so a material failure terminated the process.
Failure is now signalled as data - a quiet NaN that propagates through the
material tensors into the assembled system, detected after the parallel
region and surfaced as ThinShellAssemblerStatus::AssemblyError, which the
existing arc-length recovery path already handles by reducing the step.
* _eval3D_Compressible_C33 (both overloads): on itmax exhaustion write
quiet_NaN() instead of throwing, with a latched warning.
* gsMaterialMatrixBaseDim::_getMetric: the ratio guard is negated so that
a NaN determinant ratio enters the failure branch as well as a negative
one; the real trigger is det(Gcov_def) = -nan, not a negative value.
* A non-finite Newton initial guess (m_J0_sq == 0 gives pow(0,-1) = +inf)
is rejected before the iteration starts.
* The convergence test additionally requires an admissible iterate,
c(2,2) > 0, so a damped step that leaves the admissible region cannot
satisfy it.
* The four inlined allFinite() status checks in gsThinShellAssembler are
folded into two _isSystemFinite overloads.
The last two are hardening rather than bug fixes: a bounded sweep found no
reachable state in which either changes a returned value, and their tests
are labelled contract tests and pass with and without them. They are kept
because the state they exclude IS reached - the exhausted-backtracking path
drives c(2,2) to large negative values - and only a separate guard currently
prevents the convergence test from accepting one.
Separately, eval3D_pstretch read C33s at the in-plane index k rather than at
the packed index colIdx = j*u.cols()+k, so every through-thickness station
received station j=0's value. This CHANGES NUMERICAL OUTPUT for callers
evaluating principal stretches at more than one station, reached through
gsMaterialMatrixEval (MaterialOutput::Stretch) and gsMaterialMatrixTFT.
computePrincipalStretches passes a single station and was unaffected.
New suite gsMaterialMatrixNonlinear_test covers the failure path at material
level and through the assembler status, plus a multi-station regression gate
for the packing fix, observed to fail before it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WuXKeJKcGFGedAq56Gn9za
There was a problem hiding this comment.
🟡 Changes recommended
The new Newton-iteration “non-finite dc33” branch logs “iterate held” but still applies the non-finite increment, which can immediately corrupt the iterate and contradict the intended behavior.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR changes the compressible plane-stress through-thickness Newton solve failure mode from “throw inside OpenMP region” to “signal failure as data (NaN) that propagates into the assembled system”, so assemblers can detect the failure after the parallel region and return ThinShellAssemblerStatus::AssemblyError. It also fixes an indexing/packing bug in eval3D_pstretch for multi-station evaluation and adds a targeted unit test suite covering both behaviors.
Changes:
- Replace exception-based plane-stress failure signaling with quiet-NaN propagation (material + metric computation), and detect non-finite assembled systems in
gsThinShellAssembler. - Fix
eval3D_pstretchto read per-stationC33using the packed column index (colIdx = j*u.cols() + k). - Add
gsMaterialMatrixNonlinear_testto cover non-convergence/failure propagation and multi-stationpstretchregression.
File summaries
| File | Description |
|---|---|
| unittests/gsMaterialMatrixNonlinear_test.cpp | New unit tests covering plane-stress Newton failure propagation and multi-station pstretch packing regression. |
| src/gsThinShellAssembler.hpp | Adds _isSystemFinite helpers and uses them to convert NaN-propagated failures into AssemblyError status. |
| src/gsThinShellAssembler.h | Declares the new _isSystemFinite overloads. |
| src/gsMaterialMatrixNonlinear.hpp | Fixes pstretch packing index; updates plane-stress Newton solve to return NaN on failure and adds extra guards/warnings. |
| src/gsMaterialMatrixBaseDim.hpp | Treats negative or NaN determinant ratios as failure by setting m_J0_sq to NaN (and warning once). |
Review details
Suppressed comments (1)
src/gsMaterialMatrixNonlinear.hpp:2118
- Same issue as the geometry overload: the non-finite dc33 branch reports the iterate is held, but dc33 is still applied immediately after the branch (c(2,2) += dc33). This can force c(2,2) to become NaN/Inf and makes the warning misleading; set dc33=0 whenever it is non-finite and warn once.
else if (!warnedNonFinite)
{
warnedNonFinite = true;
gsWarn<<"_eval3D_Compressible_C33 (Cmat): non-finite Newton increment dc33, iterate held (it="<<it<<", c(2,2)="<<c(2,2)<<", dc33="<<dc33<<", m_J0_sq="<<m_data.mine().m_J0_sq<<")\n";
}
- Files reviewed: 5/5 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| else if (!warnedNonFinite) | ||
| { | ||
| warnedNonFinite = true; | ||
| gsWarn<<"_eval3D_Compressible_C33: non-finite Newton increment dc33, iterate held (it="<<it<<", c(2,2)="<<c(2,2)<<", dc33="<<dc33<<", m_J0_sq="<<m_data.mine().m_J0_sq<<")\n"; | ||
| } |
Signal compressible plane-stress material failure as data, and fix
pstretchpackingThe through-thickness Newton solve for the compressible plane-stress condition S33(c33)=0 could not report failure: it raised GISMO_ENSURE from inside gsExprAssembler's OpenMP region, where no handler above the parallel construct can catch it, so a material failure terminated the process.
Failure is now signalled as data - a quiet NaN that propagates through the material tensors into the assembled system, detected after the parallel region and surfaced as ThinShellAssemblerStatus::AssemblyError, which the existing arc-length recovery path already handles by reducing the step.
The last two are hardening rather than bug fixes: a bounded sweep found no reachable state in which either changes a returned value, and their tests are labelled contract tests and pass with and without them. They are kept because the state they exclude IS reached - the exhausted-backtracking path drives c(2,2) to large negative values - and only a separate guard currently prevents the convergence test from accepting one.
Separately, eval3D_pstretch read C33s at the in-plane index k rather than at the packed index colIdx = j*u.cols()+k, so every through-thickness station received station j=0's value. This CHANGES NUMERICAL OUTPUT for callers evaluating principal stretches at more than one station, reached through gsMaterialMatrixEval (MaterialOutput::Stretch) and gsMaterialMatrixTFT. computePrincipalStretches passes a single station and was unaffected.
New suite gsMaterialMatrixNonlinear_test covers the failure path at material level and through the assembler status, plus a multi-station regression gate for the packing fix, observed to fail before it.