Read next:
- solver roadmap:
SOLVER_ROADMAP.md - benchmark/proof status:
BENCHMARKS.md
This file is the historical record. It should capture what changed, not what should be built next.
- hardened the beam-station extraction contract for downstream RC/steel workflows:
- added
schemaVersionto station payloads with documented evolution rules - added no-phantom-governing protections so empty governing entries do not serialize fake combo IDs or infinities
- added representative full-pipeline regression fixtures for RC and steel solve → stations → demands workflows
- added grouped/member-level snapshot and contract coverage
- added governing combo names to governing entries and grouped member-governing entries
- added
- added pre-solve model-quality gates for:
- disconnected nodes / isolated components
- near-duplicate nodes
- initial 2D instability-risk detection
- expanded structured diagnostics and trust signals:
- machine-readable diagnostic codes, severity, node/DOF references, and path-parity coverage
- equilibrium and residual summaries in representative result payloads
- sparse fill-ratio diagnostics after sparse Cholesky
- documented tolerance policy by test type
- added a solver-run artifact contract for reproducibility and replay:
SolverRunMetawith engine version, build SHA, solver path, and model sizeSolverRunArtifactcarrying metadata, diagnostics, equilibrium, timings, result summary, and compact output fingerprint- JSON round-trip coverage for artifact serialization
- rewired kinematic analysis (2D/3D) to delegate to WASM when available, falling back to full TS LU rank analysis when not
- deduplicated diagram code: diagrams-3d.ts
computeDiagram3Dnow callsevaluateDiagramAtinstead of duplicating 140-line switch/case; diagrams.ts uses sharedbuildDiagramhelper - added TS fallback for
computeDeformedShape(was WASM-only, broke tests) - restored TS fallback for
analyzeSectionStress(2D),analyzeSectionStress3D, andanalyzeSectionStressFromForces— all had been migrated to WASM-only without fallback - rewired
moving-loads.tsto use TS solver when WASM unavailable - net reduction of ~240 LOC across migrated files
- fixed
i18n/store.svelte.tslocalStorage crash in vitest:typeof localStorage !== 'undefined'passes in Node but.getItemis not a function; addedhasLocalStorage()guard - fixed test imports in
inclined-supports.test.tsandkinematic-analysis.test.tsto import kinematic functions fromkinematic-2dinstead ofsolver-js - test suite went from 122 passing / 3 failing / 31 suites crashing to 1625 passing / 0 failing / 35 suites green
- added
engine/src/postprocess/beam_stations.rswith 2D and 3D station extraction extract_beam_stations()andextract_beam_stations_3d()evaluate M/V/N (or all 6 force components in 3D) at configurable stations per member, across all load combinations, tracking governing pos/neg values with combo provenance- exposed as WASM functions
extract_beam_stationsandextract_beam_stations_3dfor direct use from the product layer - default 11 stations (tenth-points), configurable via
num_stations - 8 unit tests (endpoint parity, midspan UDL, governing combo split, configurable count, missing element skip, determinism, 3D endpoint parity, envelope cross-check)
- 3 integration tests (full solve→station extraction with multi-span continuous beam and two combos, JSON round-trip with camelCase verification, snapshot stability test for product-team contract)
- unblocks RC design tables, reinforcement schedules, and downstream BBS generation
Option<GoverningEntry>pattern prevents phantom infinities / sentinel combo_id=0 when no combo data existscombo_namepropagated into per-station combo force entries — frontend never needs a separate joinSignConvention2D/SignConvention3Dmetadata embedded in every result payload- grouped-by-member convenience layer:
extract_beam_stations_grouped()/extract_beam_stations_grouped_3d()with member-level governing summaries (MemberGoverning/MemberGoverningEntryincluding station index), WASM bindings, 5 unit tests, 1 integration test
- added
modified_nr: boolparameter to corotational 2D/3D and fiber nonlinear 2D/3D solvers - when enabled, caches the Cholesky factorization from iteration 0 and reuses it across subsequent NR iterations within each load increment, avoiding refactorization; falls back to full NR if Cholesky fails on iteration 0
- measured on fiber nonlinear 2D with bilinear steel (fy=250 MPa, 1% hardening): converges for moderate plasticity with 2-3× more iterations; diverges for deep plasticity — not a blanket win, useful where factorization cost dominates and nonlinearity is moderate
- corotational (geometric nonlinearity) diverges under modified NR; full NR remains more robust for geometric-nonlinear and deep-plasticity cases
- added 3 parity tests (corotational 2D, corotational 3D, fiber 2D) and 1 measurement benchmark
- added
lanczos_buckling_eigen_sparseinengine/src/linalg/lanczos.rs - wired
solve_buckling_3dto use the sparse buckling eigensolver path directly in the common unconstrained case, while keeping a dense path for small models and conservative fallback behavior - added sparse shell gate coverage for sparse buckling parity
- confirmed the sparse buckling path handles the generalized
K phi = lambda (-Kg) phicase by factorizingKand applyingK^{-1}(-Kg)as the operator
- added sparse Lanczos operators in
engine/src/linalg/lanczos.rs, including sparse symmetric mat-vec and sparse shift-invert helpers - wired
solve_modal_3dto use the sparse eigensolver path directly in the common unconstrained case, skipping denseK_ffreconstruction there - added sparse shell gate coverage for:
- sparse faster than dense at representative shell size
- deterministic sparse assembly
- fill-ratio regression bounds
- sparse modal parity
- added measured modal sparse-vs-dense timing coverage, including an
11.8×speedup at20×20 MITC4 - measured AMD vs RCM fill behavior and confirmed AMD wins materially on larger shell meshes
- switched
solve_modal_3d,solve_buckling_3d,solve_harmonic_3d,guyan_reduce_3d, andcraig_bampton_3dfrom densen×nassembly to sparse assembly plus denseK_ffconversion - eliminated full dense
n×nstiffness allocation in those workflows while leaving mass matrices, geometric stiffness, and eigensolver internals unchanged - added sparse shell gate coverage for these reuse paths (
321tests reported green)
- rewrote
from_tripletsfrom per-column duplicate compaction to global sort + single-pass CSC build, eliminating the memmove-heavy hotspot - added
k_ff-only sparse assembly where full reactions are not needed - sparse assembly on representative shell models moved from major regression to runtime win after those fixes
- added dense vs sparse benchmarks for all three shell families: MITC4, Quad9, and curved shell
- measured factorization-only speedups: 4.5× at 700 DOFs, 22× at 2600 DOFs, 77-89× at 5700 DOFs
- measured end-to-end speedup: 22× at 30×30 MITC4 (sparse 0.56s vs dense 12.3s)
- 0 pivot perturbations across all tested sizes and element families
- sparse wins on all families above ~500 DOFs; dense still faster at curved 8×8 (~450 DOFs)
- fill ratio grows from 2.6× (10×10) to 7.0× (50×50) under RCM ordering — not constant as previously estimated
- extended
bench_solve_3d_shellto 20×20 and 30×30 mesh sizes - added
bench_solve_3d_quad9(5×5 to 15×15),bench_solve_3d_curved(8×8 to 24×24), andbench_full_solve_3d_familiescriterion benchmarks - added
sparse_vs_dense_comparisonin opt-inbench_phases.rsprofiling test target, now gated behind--features manual-bench-phases
- replaced broken etree-based symbolic Cholesky with direct left-looking symbolic factorization that correctly computes fill structure
- added two-tier pivot perturbation in numeric Cholesky: hard threshold (1e-20 × max_diag) rejects true singularities, soft threshold (1e-10 × max_diag) perturbs drilling-DOF pivots with controlled regularization
- added RCM (Reverse Cuthill-McKee) ordering with George-Liu pseudo-peripheral start node; fill ratio dropped from 673× to 1.8× on representative shell meshes
- eliminated dense LU fallback on shell models: sparse Cholesky now survives MITC4, MITC9, and curved-shell plates that previously always fell back to dense LU (87% of wall time → 0%)
- made all assembly paths (dense, sparse, parallel) deterministic by sorting HashMap element iterations by ID
- fixed DOF numbering determinism: when multiple supports target the same node, constraint flags are now merged with OR instead of nondeterministic HashMap overwrite
- added residual-based parity testing for ill-conditioned shell matrices: both sparse and dense solutions verified via ||Ku-f||/||f|| < 1e-6 instead of max-displacement comparison
- added benchmark gate tests: no-dense-fallback gate, fill-ratio gate (< 200×), and sparse-vs-dense residual parity gate
- wired pivot perturbation count and max perturbation into SolveTimings and solver diagnostics
- added
PivotInfotoNumericCholeskyfor tracking perturbation statistics
- added
assemble_sparse_3d_parallel()behind#[cfg(feature = "parallel")]using rayon - unified all 8 element families (frame, truss, plate, quad, quad9, solid-shell, curved-shell, connector) into a single
AnyElement3Denum for onepar_iter()work pool - pre-built element-id load index reduces load dispatch from O(elem × loads) to O(elem + loads)
- serial fallback via
#[cfg(not(feature = "parallel"))]delegates to the existingassemble_sparse_3d() - wired parallel path into
solve_3d()as the default sparse assembly call - added parity tests: flat-plate (4×4) and mixed frame+slab (4 columns + 16 quads + nodal + pressure loads)
- added criterion benchmarks: flat-plate up to 50×50 (2500 quads, ~15k DOFs) and mixed frame+slab up to 8-storey 8×8
- measured 2-6% speedup on MITC4 flat plates (lightweight per-element cost); later profiling showed CSC construction, not element math, is the real sparse-assembly bottleneck
- made
inclined_rotation_matrixandapply_inclined_transform_tripletspublic for reuse - fixed pre-existing
transform_forcescope issue in the 2D parallel path
- integrated the curved-shell family into the solver narrative as a production shell option for genuinely curved geometry
- established that the old hemisphere extremes were partly inflated by an
Eunit issue in the benchmark setup, and corrected that interpretation across the shell benchmark story - added curved-shell benchmark coverage showing near-reference hemisphere behavior while preserving credible flat-shell and barrel-vault performance
- clarified that the shell stack is now
MITC4 + MITC9 + SHB8-ANS + curved shell, with the remaining work focused on family guidance, workflow hardening, and shell-adjacent breadth
- integrated the
MITC99-node quadrilateral shell through the full solver stack: dense+sparse assembly, mass, geometric stiffness, buckling, stress recovery, and all shell load types - added
MITC9acceptance/workflow models covering cantilever shell response, mixed beam+slab building workflow, cylindrical tank wall behavior, and modal plate extraction - integrated the
SHB8-ANSsolid-shell family as a new shell path for the curved/non-planar frontier - added shell-family frontier gates and comparative benchmarks across
MITC4,MITC9, andSHB8-ANS - established explicit shell selection guidance instead of treating shell support as a single undifferentiated element family
- shifted the shell roadmap from “add more shell breadth” to “harden and guide the multi-family shell stack”
- completed sparse 3D assembly for plates, quads, inclined supports, and diagnostics
- wired sparse path into
solve_3d()for models with 64+ free DOFs - 11-22x memory reduction on shell models (10×10 to 15×15 quad meshes)
- 13 new validation tests: 8 dense-vs-sparse parity, 2 performance benchmarks, 3 drilling regression
- added
QuadSelfWeightbody force load type (density, gx, gy, gz) with consistent Gauss integration, wired into assembly - added mesh distortion robustness study: aspect ratio, parallelogram skew, trapezoidal taper, and random perturbation sweeps against Navier analytical
- added MacNeal-Harder pinched cylinder benchmark (R=300, L=600, t=3, E=3×10⁶) at 6×6 and 8×8 meshes
- added edge load validation: normal (in-plane) and tangential (axial extension) against beam theory
- added thermal gradient convergence sweep: 4×4, 8×8, 16×16 with monotonic convergence and tightened tolerances
- added warped element accuracy study: cantilever strip at 0%, 5%, 10%, 20% warp with graceful degradation tracking
- verified quad shell load vectors, mass, geometric stiffness, and quality metrics
- verified mixed DKT and MITC4 assembly and beam-shell DOF interfacing
- wired plate and quad stress recovery into the major nonlinear 3D solver families
- added beam-shell mixed benchmarks, shell buckling benchmarks, shell thermal benchmarks, and shell acceptance models
- added plate geometric stiffness contribution in 3D buckling
- added assembly diagnostics for distorted/low-quality plate and quad meshes
- added full nodal stress tensor recovery for MITC4 quads
- pushed constraint-system unification further across solver families
- added connector-element assembly coverage across dense and sparse 2D/3D paths
- added constraint-force output in constrained solver paths
- added eccentric-connection integration tests and new constraint benchmark coverage
- propagated constraint-force output into plastic and fiber nonlinear solver paths
- added cross-solver constraint-force parity coverage
- added explicit gate suites for:
- constraints
- contact
- shells
- reduction
- sparse and conditioning paths
- added explicit CI gate steps for shell benchmarks, shell acceptance models, and constraint benchmarks before the full suite
- added conditioning diagnostics
- added sparse triplet assembly infrastructure
- added parallel element assembly behind the
parallelfeature flag - extended criterion benchmarks with larger-model assembly and dense-vs-sparse solve comparisons
- switched CI and local default full-suite execution toward
cargo nextest, with engine-local nextest config and Linuxmoldlinker support
- implemented true assumed natural strain (ANS) transverse shear interpolation (Bathe & Dvorkin, 1986) in the MITC4 quad shell element
- uses covariant strain tying at 4 edge midpoints with Jacobian-correct transformation at each Gauss point, eliminating transverse shear locking on thin plates
- added EAS-4 membrane softening to the MITC4 quad shell element via static condensation
- benchmark improvements: Scordelis-Lo 6×6 ratio from 0.14 to 0.80, Navier plate from 0.08 to 0.93, cantilever pressure from 0.10 to 1.05, buckling from wide tolerance to 1.02, modal frequencies from ~6× error to 0.1% error
- tightened shell benchmark tolerances across the board to lock in the formulation quality
- added
quad_check_jacobian()for negative/degenerate Jacobian detection - added moderate warping diagnostics (0.01-0.1 range) in assembly
- added dedicated thin-plate locking test (a/t = 1000) to prevent regression
- expanded CI shell benchmark gate to cover plate bending, Navier convergence, Scordelis-Lo, cantilever, hemisphere, and thin-plate tests
- EAS-4 is mathematically correct and stable, but pinched hemisphere remains a known membrane-locking limit; that boundary is now documented explicitly
- replaced the 4-mode membrane enhancement with EAS-7 using a generic small-matrix inverse and 7 enhanced membrane modes
- Scordelis-Lo improved further to roughly 0.84 of reference with no regressions on Navier, buckling, modal, or existing shell gates
- added new shell tracking benchmarks for Raasch hook and twisted beam as explicit non-planar / curved-shell formulation-limit indicators
- clarified that the remaining shell decision is no longer
EAS-4 vs EAS-7; it isbounded MITC4+EAS-7 vs broader shell family
- fixed 3D DOF numbering: multiple supports targeting the same node now merge constraint flags with OR instead of nondeterministic HashMap overwrite
- fixed 2D DOF numbering: supports sorted by ID for deterministic overwrite order
- fixed nondeterministic assembly: all element iterations in dense, sparse, and parallel assembly paths now sorted by element ID
- fixed point-of-contraflexure inflection detection: rewrote to use nodal moment profile approach that handles inflection points on element boundaries
- fixed the staged fixed-end-force accumulation bug by tracking cumulative loads across stages
- corrected four pre-existing TME validation expectations involving formulas, sign conventions, and a wrong midspan-node assumption
- added residual-checked Cholesky fallback: if ||Kff*u - f||/||f|| > 1e-6, the sparse 3D solve falls back to dense LU
- latest reported full-suite status reached
5908passing tests with0failures