Changelog#

This page lists user-visible changes for every tagged femorph-solver release. Entries follow the Keep a Changelog structure (Added / Changed / Deprecated / Removed / Fixed / Security) so the diff between any two releases reads consistently regardless of which contributor authored it.

Versions follow Semantic Versioning: the public API is the surface enumerated by femorph_solver.__all__ and the public methods of the classes it re-exports. Pre-1.0 minor bumps may break the public API; bumps after 1.0 will not.

Unreleased#

Tracking main. Compare against the most recent tag on GitHub: v0.22.1…main.

v0.22.1 — 2026-05-08#

Docs deploy unblock. Compare against the prior tag: v0.22.0…v0.22.1.

Fixed#

  • Tag-triggered docs deploy no longer blocks on latent unknown document references in historical-tag snapshots. sphinx-multiversion re-checks out every released tag and rebuilds its docs through the current Sphinx environment; v0.20.0 tutorials reference doc tree paths that hadn’t been written yet (/interop/nastran, /interop/abaqus, /getting-started/known-limitations, /reference/theory/stress_recovery). Under the shared -W (warnings as errors) those latent refs become hard failures and the Cloudflare Pages deploy never runs. Split SPHINXOPTS_MV so the multiversion build keeps --keep-going without -W; single-version main / PR builds keep -W (#912).

v0.22.0 — 2026-05-08#

MAPDL parity push, native geometry creation, harness rebuild. Compare against the prior tag: v0.21.0…v0.22.0.

Added#

  • MAPDL parity playbook + scoreboard discipline. tests/mapdl_reference/PLAYBOOK.md is now the canonical handoff doc for the 100-VM parity push. Documents the four- layer strictness hierarchy (element K/M bit-level → assembled K/M → probe values → reference targets), the curatorial restraint rules for the deck-verb skip set, the multi-pass deck families (/CLEAR,NOSTART / FINISH+``/PREP7`` / ETCHG element-type swap), and a working-without-binary- solver-access section so the same discipline applies to Hexagon’s MSC.Nastran / Abaqus parity (#878, #886, #907). Companion AGENTS.md at the repo root spells out the rules for any AI / human contributor: element-first rule + solver-native kernel naming convention.

  • Per-kernel parity tests against MAPDL ``.emat``. Element K / M now diff bit-level (~1e-12 relative) against MAPDL’s file.emat for every implemented kernel: COMBIN14 (#876), HEX8 (SOLID185), QUAD4_PLANE (PLANE182), TRUSS2 (LINK180), BEAM2 (BEAM188), MASS21, PLANE55 + LINK33 + LINK34 thermal, HEX20 (SOLID186). These tests are the gate every kernel must pass before any probe-level VM closure.

  • Native geometry-creation pillar. New femorph_solver.geometry module: Point / Line / Area / Volume primitives (frozen dataclasses), structured pure-NumPy meshers for rectangle (Q4) and box (Hex8) with bit-level patch-test verification, gmsh fallback for unstructured 2-D / 3-D, lazy pyvista tessellation. Mesher choice locked to gmsh-first (open-source robust) per RFC, native superior later. Runnable from-scratch demo at docs/examples/geometry_from_scratch.py exercises the full pipeline end-to-end (build geometry → mesh → solve → extract results in pure Python) and is gated in CI by tests/geometry/test_example_from_scratch.py (#890, #891, #892, #893, #901, #902).

  • VM parity scoreboard. 16 VMs in the first 100 now pass end-to-end within the 5% relative-error gate (vm3, vm10, vm12, vm16, vm45, vm47, vm48, vm50, vm57, vm61, vm84, vm89, vm90, vm92, vm94, vm99). Closures this release: vm3 (CSYS,1 + thermal pre-strain in LS,1 stress recovery, #881), vm10 (BEAM2 T-section fiber-stress recovery, #900), vm12 (BEAM2 PLNSOL principal-stress recovery, #909), vm16 (PLNSOL,0,MAX evaluator + F-range form, #899), vm21 (RFORCE / VARI POST26 reaction-force evaluator, #898), vm50 (DK keypoint-displacement, #884).

  • Multi-pass deck routing. /CLEAR,NOSTART-segmented decks (vm12 / vm33 / vm34) now route to the last solving pass for the build/solve pipeline, with last-write semantics on *VFILL so the comparison block at the deck tail resolves against the correct *GET bindings (#908).

  • Harness probe-evaluator coverage. PLNSOL / PLESOL stress contours: principal stresses, intensity, von Mises, with beam-element fiber-stress augmentation so PLNSOL,S,1 aggregates over both solid principals and BEAM2 cardinal fibers (#903, #909). POST26 RFORCE / VARI reaction-time-history (#898). ETABLE / LS element-table extraction expanded.

  • Solver-native kernel naming. Element registry renamed away from MAPDL-vendor names (Solid185, Plane182, …) to physics+topology names (Hex8, Quad4Plane, Bar2Conduction, LumpedSpringMass, …). The MAPDL catalogue dispatch lives at the interop boundary (_apdl_dialect._MAPDL_ALIASES); core registry and downstream code never see vendor names. Convention locked in AGENTS.md (#880).

  • DAT loader: traceable skip table + unknown-verb tracking. Every verb the parser doesn’t fully implement is recorded on model._deck_skipped (with a stated reason) or model._deck_unknown so the scoreboard surfaces the gap loudly rather than silently dropping commands (#885). Curated skip set covers post-only verbs (*VWRITE, *VFILL, ETABLE, PLNSOL, PRRSOL, OUTPR, OUTRES, POST26 RFORCE / DERIV), default-toggle no-ops (HROPT,FULL, TRNOPT,FULL, CSYS), and deck- formatting artifacts (FORTRAN format continuations, LABEL(i,j) = '...' array assignments) without ever silently skipping a physics-relevant verb.

  • DAT loader: more handlersRMORE (extend real constants beyond 6 slots, #897), stacked *IF / *DO / *DOWHILE block-skipper (#896), *CREATE / *END macro-body block-skip (#889), DSYM symmetry-plane handler (#888), SFBEAM with MAPDL→solver-native face remap (#883), DK keypoint-displacement (#884), TREF / BFUNIF / BF / CP (#881).

  • CHAN beam section for vm14 (channel-section beam properties derived from MAPDL SECTYPE,..,BEAM,CHAN SECDATA).

  • Result-file magic marker + version stamp so disk-backed results identify the femorph-solver version that wrote them.

Changed#

  • Model.assign is a no-op on empty kernels; new Model.assign_all helper attaches every registered kernel to its matching element block in one call.

  • solvers.linear.list_available() runtime introspection reports which optional backends loaded (Cholmod / SuperLU / PARDISO).

  • TTY-aware progress output: progress bars no longer overlap via \r when redirected to a non-TTY pipe.

Fixed#

  • FV2/FV4 ARPACK degenerate-pair flake: deterministic v0 initialisation for the K-σM eigensolver path (#114, PRs #115, cyclic-modal companion fix).

  • BEAM2 xfail closure: static condense MAPDL’s 24×24 cubic-shape function (BEAM188 KEYOPT(1)=3) down to the Hermite 12×12 we ship — element-K parity within ~1e-12 rel.

  • gmsh OSError on NixOS: harden the lazy-import path against both ImportError and OSError so a broken gmsh wheel doesn’t break the geometry pillar (#893).

Deprecated#

  • MAPDL-vendor kernel names (Solid185 etc.) accepted at the interop boundary; downstream code that still references them via private imports should switch to the solver-native names (Hex8 etc.). Vendor names will continue to translate through the alias table indefinitely; the deprecation is about internal uses only.

v0.21.0 — 2026-05-04#

API consistency cleanup + documentation overhaul + tag-triggered release infrastructure. Compare against the prior tag: v0.20.2…v0.21.0.

Added#

  • Documentation overhaul (`#583 <https://github.com/femorph/solver/issues/583>`_). Multi-week push to bring documentation up to commercial-solver quality ahead of the public release.

    • Phase 0: doc style guide (#604), numpydoc.validate per-symbol CI gate (#606), doctest gate + nightly linkcheck (#611).

    • Phase 1: bucket-A docstrings on the public Model solve verbs (#610), the disk- backed result hierarchy (#614), CyclicModel (#616), and the interop / utility surface (#618).

  • Verification corpus. MAPDL Verification Manual coverage driven by the #511 tracker — VM6 (pinched cylinder) and VM10 (T-section beam) added under the shared verification harness.

  • Interop coverage. ET KEYOPT slot recognition for PLANE182 / BEAM188 (#607); CSYS,1 cylindrical coordinates with NSEL / DSYM / D,ALL / F,ALL (#588, #602).

Changed#

  • API consistency cleanup (`#750 <https://github.com/femorph/solver/issues/750>`_). Thirteen PRs that close the long tail of API / docs / module-naming gaps the v0.20 release surfaced. All renames ship a deprecation alias for one minor release; the next minor drops them.

    • Solve-method renames (#764). Every analysis driver now reads solve_<analysis>:

      Model.solve(...)            → Model.solve_static(...)
      Model.modal_solve(...)      → Model.solve_modal(...)
      Model.transient_solve(...)  → Model.solve_transient(...)
      Model.harmonic_solve(...)   → Model.solve_harmonic(...)
      CyclicModel.modal_solve(...) → CyclicModel.solve_modal(...)
      solve_harmonic_modal(...)   → solve_harmonic(...)
      solve_cyclic_modal(...)     → solve_cyclic(...)
      
    • Kwarg consistency. Every Model.*_solve now accepts the same set of common kwargs (progress, thread_limit, release_inputs, mixed_precision, linear_solver). CyclicModel.solve_modal gains lumped (#762). The cyclic side’s eigensolver= is renamed to eigen_solver= to match the rest of the modal-family API; defaults are aligned to "auto" everywhere (#754).

    • Result types re-exported from the top level (#753): from femorph_solver import ModalResult, ModalResultDisk, read is now the canonical import. Frozen Result dataclasses (#759).

    • Module renames (drop false-private prefix on documented public types): _cyclic_model.pycyclic_model.py (#756), _labels.pylabels.py (#765).

    • Factory parity: Model.from_cdb mirrors CyclicModel.from_cdb (#758).

    • Doctest gating expanded from one module to thirteen so docstring Examples blocks across Model, CyclicModel, the result hierarchy, and the solver functions are now CI-tested (#763).

  • Pre-existing illustrative >>> blocks in femorph_solver.Model docstrings (save, from_lines, apply_force) rewritten as runnable doctests using the bundled cyclic_bladed_rotor_sector fixture.

Deprecated#

  • All pre-PR-K solve method + function names continue to work with a DeprecationWarning; removed in the next minor release.

Fixed#

  • Three cyclic gallery examples and tutorial_06_cdb_to_results no longer crash for users walking the docs verbatim (#752).

  • T-section SECTYPE thickness convention bug (#576).

  • PBAR / PBEAM I1 / I2 swap on non-canonical NASTRAN decks (#573).

  • Drilling-DOF false alarm on FV4 — turned out to be n_modes configuration, not a kernel bug (#567).

v0.20.2 — 2026-04-25#

Documentation green-build patch. Compare against the prior tag: v0.20.1…v0.20.2.

Fixed#

  • Documentation green-main fix: corrected the -j4 Sphinx-build flag spacing and dropped a broken release-only :doc: cross- reference that prevented the build from running on PR branches (#416).

  • CI: cached sphinx-gallery output and dropped parallel from 8 to 4 to fit the runner pool budget (#413).

Changed#

  • Test coverage lifted to 100 % on femorph_solver.result.modal (#418), femorph_solver.result.static (#410), and to 99 % on femorph_solver.result._base (#412).

v0.20.1 — 2026-04-25#

CI / verification follow-up release. Compare against the prior tag: v0.20.0…v0.20.1.

Added#

  • New verification example: continuous beam over three supports, cross-checked against the Clapeyron three-moment theorem (#404).

  • CI failure-tracker workflow that auto-files (or updates) a ci-failure-main-labeled GitHub issue when main breaks (#398, #406).

Changed#

  • Pinned sphinx<9 because Sphinx 9.1 changed Config.read’s positional argument signature, which the current sphinx-multiversion release passes (#405).

  • Tightened the §1.7 verification mesh — now beats every MSC element family on the curved-beam reference (#400).

Fixed#

  • femorph_solver.result.transient and femorph_solver.result.cyclic_modal coverage gaps (#407, #403) — no behaviour changes, but the test sweep flushed out a handful of edge-case paths that were previously unreachable from any test.

v0.20.0 — 2026-04-25#

First milestone tag of the public-release cadence. Compare against the project’s git history: everything before v0.20.0.

This tag captures the state of femorph-solver after the four-phase landing of the public-API + verification-corpus build-out:

Added#

  • Public femorph_solver.Model API with the full set of solve verbs (solve, modal_solve, harmonic_solve, transient_solve, cyclic_modal_solve). Note: Model.cyclic_modal_solve was removed in v0.20.x; use solve_modal() instead.

  • Disk-backed result hierarchy (StaticResult, ModalResult, TransientResult, HarmonicResultDisk, CyclicModalResult) with lazy .pv IO via pyvista-zstd. Note: the disk-backed classes were renamed in v0.20.x to StaticResultDisk / ModalResultDisk / TransientResultDisk / CyclicModalResultDisk to disambiguate from the in-memory dataclasses returned by the solve methods.

  • Element kernels for HEX8, HEX20, TET10, WEDGE15, PYR13, BEAM2, TRUSS2, QUAD4 (plane + shell), POINT_MASS, SPRING — independently derived from public FEM textbooks; sourcing tracked under Provenance inventory.

  • Pluggable solver backends: Pardiso / CHOLMOD / MUMPS / UMFPACK / SuperLU (linear); ARPACK / LOBPCG / PRIMME / dense LAPACK (eigen). Auto-dispatch picks the fastest available SPD direct solver.

  • Foreign-deck import readers under femorph_solver.interop: NASTRAN BDF, Abaqus INP, MAPDL CDB, OptiStruct FEM. Import-only — the resulting Model is identical to one built natively.

  • Multi-version documentation site driven by sphinx-multiversion with a version switcher across every v* tag (#392).

  • User-guide tutorials covering cantilever combined loading, modal survey, pressure-vessel DBA, and cyclic-symmetry rotor design (#561#569).

  • Cross-vendor terminology Rosetta and per-vendor migration deep-dives for MAPDL, NASTRAN, Abaqus, and LS-DYNA (#566#574).

Changed#

  • mapdl_api re-homed under femorph_solver.interop.mapdl. The legacy import path remains for one release with a DeprecationWarning.

Removed#

  • Cross-solver tests that the verification-registry harness now covers were retired to keep the suite focused (#563, #565).

Pre-v0.20.0 history#

The project’s pre-tag history (the first eight months of development) lived on main without formal releases — feature branches landed via PR, with verification-coverage and CI-quality gates as the de-facto release criteria. See the GitHub commit history for the detailed log.

How this page is maintained#

  • New entries go under Unreleased as work lands. When a tag is cut, the maintainer renames the Unreleased heading to the new version and date and starts a fresh Unreleased block.

  • PRs that warrant a changelog entry should propose one in their description; the merging maintainer copies it across. Pure test or CI churn (anything labelled ci-failure-* or whose scope is test: / ci:) is excluded by default.

  • The release-readiness.yml workflow surfaces missing changelog entries on a PR’s checks page so the gap is visible before merge.