Known limitations#
Honest list of what femorph-solver does not do, what it does imperfectly today, and the failure modes a user can hit by exceeding the scope. Read this page before integrating femorph-solver into a workflow that depends on a capability listed here.
Items in this list are the ones we’d rather a user know about up front than discover three weeks into a project. The Roadmap page tracks which of these are scheduled to be fixed; this page focuses on the current failure modes and workarounds.
Material model#
Small-strain linear elasticity only. Every element kernel assumes geometric linearity and a linear elastic constitutive law. No plasticity (yield, hardening, creep), no hyperelasticity (Mooney-Rivlin, Ogden, Yeoh), no viscoelasticity, no damage / fracture. A nonlinear-material analysis run through femorph-solver silently treats the material as elastic — the numbers come back, but they’re wrong.
Anisotropic / orthotropic materials are partial. Isotropic with
EX,PRXY,DENSis the well-trodden path. An orthotropic constitutive matrix can be assembled by hand and passed to the per-element kernel, but the publicassign()API does not yet expose an orthotropic material card.
Geometric model#
No large deformation. Linear strain–displacement (small rotations, small strains). A geometric-nonlinear analysis with significant rotation or stretch is out of scope and will return wrong answers without raising.
No buckling solve yet. See Roadmap — linear buckling and pre-stressed modal are scheduled but not yet shipped.
No contact. Surface-surface contact, gap elements, and bonded-contact MPCs are not implemented.
CP(coupled DOFs) is supported as a workaround for rigid bonded contact in some cases.
Element library#
Locking modes are present where the literature documents them. HEX8 with full integration shear-locks on bending- dominated meshes (use the EAS variant or HEX20). Pure-axial TRUSS2 has zero stiffness in the transverse DOFs (auto-pinned during the solve). See Mesh quality and Troubleshooting flowchart for the diagnostic flowchart.
No drilling DOF on QUAD4_SHELL. The DKT shell carries five DOFs per node; coupling a shell to a solid that expects six DOFs requires an explicit
CPbetween the shell rotation and the solid translation.Beam fibre stress recovery on BEAM2 is recent (v0.20.0). Stress at the section fibres ships, but only for the cross- sections registered today (rectangular, circular, I, T). Custom sections compute correctly for the matrices but not for fibre-stress recovery.
Solver backends#
Pardiso mixed-precision is MKL-implementation-dependent.
Model.solve_modal(mixed_precision=True)andModel.solve_harmonic(mixed_precision=True)honour the request only when the linked MKL exposesiparm(28). Some Conda / vendor MKL builds silently no-op the request — see the note onsolve_modal().CyclicModel.solve_modaldoes not yet acceptmixed_precision— its inner shift-invert factor lives below the kwarg-pass-through layer; tracked as a follow-up.Out-of-core (OOC) solver paths are estimator-only. The
estimate_solve()cost predictor knows about OOC multipliers, but the actual solve does not run out-of-core; problems that need OOC factorisation will run out of RAM rather than fall through to disk.
Foreign-deck interop#
Import-only. All four readers (NASTRAN, Abaqus, MAPDL, OptiStruct) read decks; none currently write. Round-tripping a CDB deck through femorph-solver back to MAPDL requires writing a fresh deck against the original solver’s grammar.
MAPDL native ``.dat`` files are not yet readable directly. The CDB path (
cdwrite) is the supported entry point — see #513 for the native.datreader work.Coverage of card / KEYOPT combinations is rolling forward. The Vendor verification-manual coverage matrix tracks which problems round-trip cleanly through each reader. Cards that the deck parser doesn’t recognise are skipped silently — verify against the matrix before trusting a parsed deck on a new card.
No vendor binary write. RST / EMAT / FULL / HBMAT writers are out of scope for now; binary read is supported as a parity fixture.
Result formats#
The native ``.pv`` format is the only round-trip-safe one.
Model.save/Model.loadand the result classes’.save/.loadmethods round-trip the full state through zstd-compressed pyvista. Saving a result as VTU loses the per-mode / per-step metadata; consume those formats only for external visualisation.Stress / strain are derived on demand, not stored. The
.pvfiles store displacement (and time / frequency / mode number) only.Result.stress(model=…)recomputes from the displacement plus the model’s element kernels. This is by design (lean files, lossless math), but it means the model must be available when reading a result back — the saved file alone is not enough to recover stress.
Performance#
Single-process only. Element assembly and the inner factorise / back-solve run on a single host with BLAS / OpenMP threading. No MPI, no GPU. See Thread control for thread-pool tuning.
Memory bound by the linear-solver backend. A 1 M-DOF HEX20 model needs ~10 GB peak RSS for a CHOLMOD factorisation. The
estimate_solve()predictor reports pre-solve so the user can size the host before launching.
Documentation#
Reporting a new limitation#
If you hit a failure mode not on this list, please file an issue at femorph/solver#issues with:
the smallest input that reproduces it,
the expected vs observed result, and
femorph_solver.Report()output (it captures the BLAS / MKL / backend versions the failure depends on).
Limitations that come up repeatedly get promoted onto this page; listed limitations get linked tracking issues so you can subscribe to progress.
See also#
Roadmap — what’s coming.
Changelog — what shipped when.
Troubleshooting flowchart — symptom-driven flowchart for diagnosing model / solver failures.