Skip to content

ch1_introduction.md

nathan-carmichael edited this page Mar 11, 2026 · 1 revision

Chapter 1: Introduction

Overview

ShepherdLab LW FEA-OPT is a lightweight, pure-Python toolkit for finite element analysis and stress-ratio thickness optimisation of two-dimensional frame and truss structures. It is a port of the original MATLAB implementation, designed to be readable, hackable, and easy to extend.

The core capabilities are:

  • 2-D Euler–Bernoulli frame elements with axial, shear, and bending degrees of freedom.
  • Linear and nonlinear (Newton–Raphson) large-deflection analysis.
  • Stress-ratio thickness optimisation for uniform stress distribution.
  • Truss subdivision for organic topology optimisation.
  • Geometry import from CSV and IGES files.
  • Image-processing-based profile export for CAD integration.

The Python port preserves the same mathematical formulations and algorithmic structure as the MATLAB original while taking advantage of NumPy vectorisation and SciPy sparse solvers for performance.

Installation

Clone or download the repository. The feaopt package can be imported directly from the project root, or installed into your environment:

pip install numpy scipy matplotlib scikit-image

No separate setup script is required. The feaopt/ directory is a standard Python package with an __init__.py that exposes all public classes and functions.

Requirements

  • Python 3.9 or later.
  • NumPy and SciPy — required for all numerical computation, sparse matrix assembly, and linear solves.
  • matplotlib — optional but recommended; required for all visualisation and diagnostic plots. If not installed, plotting is silently disabled.
  • scikit-image — required for profile export (rasterisation via skimage.draw.polygon, morphological cleanup via skimage.morphology, and contour extraction via skimage.measure.find_contours).

Quick Start

Two demo scripts are included:

python examples/demo_beam.py       # curved beam from an IGS file
python examples/demo_truss.py      # Warren truss with element subdivision

Each script follows the same four-stage workflow:

  1. Define geometry — import a curve or build a truss programmatically, assign material and section properties, and specify boundary conditions.
  2. Analyse — run linear and/or nonlinear FEA.
  3. Optimise — iterate with the stress-ratio method until convergence.
  4. Export — rasterise the optimised structure and export spline-ready boundary loops for SolidWorks.

Project Layout

Path Contents
feaopt/ Core package: structure_geometry.py, element_matrices.py, analysis_state.py, fea_analysis.py, load_case.py, structure_plotter.py, optimize_thickness.py, subdivide_truss.py, importers.py, export_profile.py.
examples/ Runnable demo scripts (demo_beam.py, demo_truss.py).
profiles/ Auto-created output directory for exported CAD profiles.
docs/ This documentation (LaTeX source).

Conventions

Throughout this document:

  • Vectors are set in bold italic: u, f.
  • Matrices are set in bold upright: K, T.
  • Transpose is denoted (·)ᵀ.
  • Scalar quantities use standard italic: E, A, I, L.
  • SI units are used throughout unless otherwise stated.
  • "Element" and "member" are used interchangeably.
  • Node DOFs are ordered [uₓ, u_y, θ] at each node.
  • All indexing is 0-based. Node IDs, element IDs, DOF indices, and constraint definitions use 0-based indexing, following Python convention. This differs from the MATLAB version, which uses 1-based indexing.

Differences from the MATLAB Version

The Python port is a faithful translation of the MATLAB original. The mathematical formulations, algorithm structure, and default parameters are identical. The key differences are:

  • Indexing. All node, element, and DOF indices are 0-based. Constraints are specified as [node_id, dof, value] where node_id starts at 0 and dof is 0 (uₓ), 1 (u_y), or 2 (θ).
  • Data structures. Results, options, and imported geometry data are returned as Python dicts rather than MATLAB structs. Properties and options use the same key names as the MATLAB field names.
  • Sparse linear algebra. The global stiffness matrix is assembled as a scipy.sparse.csr_matrix and solved with scipy.sparse.linalg.spsolve, rather than MATLAB's backslash operator.
  • Vectorisation. Element stiffness matrices, coordinate transformations, internal force assembly, and stress recovery are computed for all elements simultaneously using NumPy array operations and einsum, rather than per-element loops.
  • Visualisation. Plotting uses matplotlib with PatchCollection and PolyCollection for batch rendering of beam elements. The StructurePlotter class provides the same drawing capabilities as the MATLAB version.
  • Profile export. The export pipeline uses scikit-image functions (polygon, closing, find_contours) in place of MATLAB's Image Processing Toolbox (poly2mask, imclose, bwboundaries). Exported data is saved as .npz archives rather than .mat files.
  • Package structure. The MATLAB src/ and io/ directories are consolidated into a single feaopt/ Python package. Importers (import_csv_curve, import_igs_curve) are in importers.py; the exporter (export_profile) is in export_profile.py.

Clone this wiki locally