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. .. _changelog-unreleased: Unreleased ---------- Tracking ``main``. Compare against the most recent tag on GitHub: `v0.22.1…main `_. .. _changelog-v0.22.1: 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 `_). .. _changelog-v0.22.0: 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 handlers** — ``RMORE`` (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. .. _changelog-v0.21.0: 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 `_).** 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 `_).** 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_``: .. code-block:: text 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.py`` → ``cyclic_model.py`` (`#756 `_), ``_labels.py`` → ``labels.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 `_). .. _changelog-v0.20.2: 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 `_). .. _changelog-v0.20.1: 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. .. _changelog-v0.20.0: 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 :meth:`~femorph_solver.CyclicModel.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 :doc:`/dev/provenance`. * 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 :class:`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 :ref:`changelog-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.