Chapter 13: Legacy Wrappers#

This chapter explains the compatibility layer in matlab.py and compat.py. The goal is not to hide the modern Python API. The goal is to let older FemLab scripts keep working while the underlying code uses the shared core modules.

Why The Wrappers Exist#

The original FemLab material was organized as single-call drivers such as elastic, flowq4, nlbar, plastps, and plastpe. The wrapper layer keeps that entry point available, but each wrapper delegates to the shared core routines rather than duplicating the implementation.

That separation matters:

  • the wrappers preserve the old classroom interface,

  • the core modules stay reusable and testable,

  • the plotting and recovery logic remains centralized.

Shared Helpers#

_legacy_bundle#

_legacy_bundle(T, X, G, C, P, dof=None) converts the legacy input deck into a typed dictionary with normalized arrays. It resolves the degree-of-freedom count from X when needed and creates an empty load table when P is omitted.

The wrappers use this helper so every legacy driver sees the same normalized shape and dtype rules.

_set_axis#

_set_axis(ax, limits) applies MATLAB-style axis vectors to Matplotlib axes. It supports both 2D and 3D limit arrays and is used only for compatibility with the old plotting scripts.

compat.setpath#

compat.setpath() returns the package and examples directories and can append the examples directory to sys.path.

That mirrors the original MATLAB setpath.m helper closely enough for old scripts that expect the examples directory to be discoverable without manual path setup.

Benchmark Data Wrappers#

The simplest wrappers just return packaged benchmark decks:

  • canti()

  • flow()

  • bar01()

  • bar02()

  • bar03()

  • square()

  • hole()

These functions are data accessors, not solvers. They give you the original coordinates, topology, materials, loads, and constraints in the exact format expected by the legacy drivers.

square() and hole() both accept plane_strain so the caller can choose the plane-stress or plane-strain benchmark variant.

Solver Wrappers#

elastic#

elastic(T, X, G, C, P, ...) solves the linear Q4 elasticity workflow. It uses init, kq4e, setload, setbc, qq4e, and reaction under the hood.

If plot=True, it also returns figures for the mesh, loads, constraints, and stress field. That makes it a faithful compatibility wrapper for the original single-call MATLAB driver.

flowq4 and flowt3#

These wrappers solve the scalar potential benchmark using either Q4 or T3 elements. Internally they both call _flow_driver, which chooses the correct element kernels:

  • kq4p and qq4p for quadrilaterals,

  • kt3p and qt3p for triangles.

The return value contains the solved field, the recovered gradients, and an optional figure that matches the legacy classroom output.

nlbar#

nlbar(...) wraps solve_nlbar. It keeps the original load-step controls and optionally builds the load-displacement and deformed-geometry plots.

plastps and plastpe#

These wrappers call _plast_driver, which in turn uses solve_plastic.

  • plastps configures plane stress.

  • plastpe configures plane strain.

Both wrappers preserve the old MATLAB-style plot controls and can return the equivalent plastic strain field in the deformed configuration.

What The Wrappers Return#

The wrappers return dictionaries rather than bare arrays. That is a deliberate departure from the original MATLAB style because it keeps the response data and the optional figures together in one object.

The most common keys are:

  • u

  • q

  • S

  • E

  • R

  • data

  • figures

That structure makes it easier to inspect results programmatically and keeps the legacy wrappers usable in notebooks and scripts.

Reading Order#

If you need to modify the compatibility layer, read these files in this order:

  1. compat.py

  2. matlab.py

  3. core.py

  4. boundary.py

  5. loads.py

  6. elements/

  7. solvers.py

  8. plotting.py

  9. postprocess.py

That path matches the actual dependency chain used by the wrappers.