# sectionproperties: finite element analysis of arbitrary cross-sections in Python

> sectionproperties is an MIT-licensed Python package that meshes an arbitrary cross-section and computes its section properties and stresses with the finite element method, wrapping a 2D mesh generator, an element library and stress recovery. It suits a structural engineer checking a cold-formed or composite section, and the project asks you to verify its output rather than trust it.

**robbievanleeuwen/section-properties** — Analysis of an arbitrary cross-section in python using the finite element method.

- Repository: https://github.com/robbievanleeuwen/section-properties
- Website: https://sectionproperties.rtfd.io
- Stars: 565 · Forks: 118
- Language: Python
- License: MIT
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/robbievanleeuwen-section-properties

## What it computes, and for whom

sectionproperties is a Python package for the analysis of arbitrary cross-sections using the finite element method, and the stated uses are to determine section properties to be used in structural design and to visualise cross-sectional stresses resulting from combinations of applied forces and bending moments.

The word arbitrary is the important one. Structural design is full of shapes that are not in a table: a cold-formed section with a return lip, a built-up member of plates and bolts, a section with a lightening hole in the web, an extruded aluminium profile, a timber section with a chamfer. For a handful of standard profiles you look up Ixx and Iyy in a catalogue, and for everything else you either work them out by hand with parallel axis theorem and a pile of small calculations, or you build a model.

This package is the second option, and the finite element method is the reason it works for shapes rather than just formulas. The alternative to a finite element model is a shape-specific hand derivation, and a hand derivation for an arbitrary geometry is a project in itself. Here the geometry is described once, meshed, and the section properties fall out of the mesh, with the same code path for a rectangle and for a complicated profile.

The second capability, stress visualisation under applied forces and bending moments, is what turns it from a properties calculator into a design tool. Section properties tell you how stiff a member is. The stress plots tell you where the member fails, which for a thin-walled or asymmetric section is not where a naive formula would predict.

The package has a JOSS paper, with the DOI 10.21105/joss.06105, which is the marker of a project that has been through peer review as a research tool rather than as a script collection. The classification in the package metadata is Development Status :: 5 - Production/Stable, and the primary maintainers are Robbie van Leeuwen and Connor Ferster, with the project published on PyPI as sectionproperties and documented at sectionproperties.readthedocs.io.

## Installing it, and the optional extras that decide what you can do

Installation is a single command from PyPI:

```shell
pip install sectionproperties
```

The base dependency set is short and tells you what the package is built on: numpy, scipy, matplotlib, shapely, cytriangle, rich with the jupyter extra, and more-itertools.

That list is the architecture. shapely does the geometry, so any polygon the package can mesh comes from a shapely object, and a shapely object can come from almost anywhere, which is what makes the package composable with other tools. cytriangle is the constrained Delaunay triangulation library, and it is what turns a polygon into a mesh of triangles that respects concave boundaries, and getting that right is most of what separating a polygon into a finite element mesh involves. scipy provides the sparse linear algebra that the element equations need, matplotlib draws the results, and rich provides the console output with jupyter support so the same package works in a notebook.

The optional extras are where the integration options live, and the packaging lists four.

The rhino extra brings rhino3dm at 8.17.0 or newer, pinned for Python versions below 3.14, along with rhino-shapely-interop on the same condition. That pairing is the interesting one: the interop package is what converts Rhino geometry into shapely objects, which means a Rhino model can be handed straight to the analysis without a manual export step. The version condition on Python 3.14 tells you the author has not yet confirmed the combination works on the newest interpreter.

The dxf extra brings cad-to-shapely, which is the same idea for CAD drawings, taking a DXF file and producing shapely geometry.

The pardiso extra brings pypardiso, with a platform marker limiting it to Windows or Linux, and that one is about solver performance: a direct sparse solver changes the cost of the linear solve, which is where a larger mesh spends its time.

The numba extra brings numba, which is the JIT route for the hot loops in the post-processing.

So the pattern is clear. The core handles a shape you already have as a shapely polygon, and each extra is a bridge from a different world, a CAD file, a Rhino model, a faster solver or a faster inner loop. The base install is enough for a lot of work, and the extras are for people whose geometry arrives from somewhere else.

## The quick start, in about a dozen lines

The example in the project documentation is a rectangle, which is the right way to start, because you know what the answer should be and can check the software against it.

```python
from sectionproperties.pre.library import rectangular_section
from sectionproperties.analysis import Section

# create a 50 x 100 rectangle and mesh it
geom = rectangular_section(d=100, b=50)
geom.create_mesh(mesh_sizes=[5])

# run a geometric analysis
sec = Section(geometry=geom)
sec.calculate_geometric_properties()

# get some results
area = sec.get_area()
ixx_c, iyy_c, ixy_c = sec.get_ic()
print(f"Area = {area:.0f} mm²")
print(f"Ixx = {ixx_c:.0f} mm⁴, Iyy = {iyy_c:.0f} mm⁴")
```

and the printed result is:

```
Area = 5000 mm²
Ixx = 4166667 mm⁴, Iyy = 1041667 mm⁴
```

Reading the code tells you the shape of the API, and it is a sensible one. The preprocessing library builds the geometry, in this case a rectangle of depth 100 and breadth 50, and create_mesh turns it into a mesh with the given element size. The Section object wraps the geometry, calculate_geometric_properties runs the analysis, and the getters return the results. The fact that geometric properties and stress analysis are separate calls, rather than one call that does everything, matters: the geometry is the expensive part, and a workflow that analyses one geometry under many load cases should not remesh it each time.

The getters return the centroidal values, since the variable names carry a _c suffix, and that is the convention you want. Section properties are usually tabulated about the centroid, and the finite element computation works out the centroid itself as part of the analysis, so asking for the centroidal moments of inertia directly avoids you computing the parallel axis shift by hand.

The mesh size argument is the main quality knob. A finer mesh gives a more accurate answer and takes longer, and the documentation points at examples for composite sections, warping analysis and stress calculations for the more advanced uses.

## The repository, the tooling and the documentation

The repository is laid out like a package that intends to be maintained for a long time, and several details point the same way.

There is a src/ directory rather than a flat package at the root, which is the modern layout, and a tests/ directory alongside it. The documentation has its own source in docs/ with a .readthedocs.yaml configuration, and the project is published to Read the Docs at sectionproperties.readthedocs.io, where the documentation is described as fully documented including a user walkthrough, examples, background theory and an API guide. That combination of a walkthrough and background theory is what a computational engineering package needs, because the difference between a mesh and a correct model is not something an API reference can explain.

The tooling is modern and specific. There is a pyproject.toml with the project metadata and the optional dependency groups, a uv.lock, a .python-version file pinning the interpreter, a ruff.toml for linting, and a .pre-commit-config.yaml. The badges in the documentation reflect the same choices, with uv, Ruff and pre-commit all named, plus Codecov for coverage and a GitHub Actions workflow badge for the tests. The CITATION.cff file is the machine-readable citation metadata that goes with the JOSS paper, so citing the software is a matter of filling in a file rather than copying a citation by hand.

The versions move steadily: v3.10.2 from 2026-01-24, v3.10.1 from 2026-01-22 and v3.10.0 from 2025-12-11, and the last push to the repository was on 2026-04-16. The changes are documented on the releases page, which the project links as the changelog, so a version history is available without reading the commits.

There is also a mailing list, and the support routes are stated: the issue tracker for bugs and feature requests, and the discussions page for support. The licence is the MIT licence, and there is a CODE_OF_CONDUCT.md and a CONTRIBUTING.md in the tree, with the contributor guide linked from the documentation.

## Where sectionproperties is the wrong tool

The first limit is that a finite element mesh is not free, and for the common case it is unnecessary. If your section is a rectangle, a circle, an I-section or a channel from a standard table, the answer is in a handbook, it is exact enough, and running a mesh solver to get it is slower and less certain than looking it up. The package is for the shapes that have no table entry.

The second is that a numerical answer needs a numerical error estimate, and the package is a solver rather than a guarantee. A coarse mesh gives an answer that is wrong in an unknown direction, and the mesh size is the parameter that trades time for accuracy. A user who does not vary the mesh size and compare the results has a number, not a result. The documentation's disclaimer says as much in its own terms, stating that although efforts have been made to ensure the relevant engineering theories have been correctly implemented, it remains the user's responsibility to confirm and accept the output, and pointing at the licence for the conditions of use.

The third is the scope of the physics. The package analyses a cross-section, which means it computes properties and stresses for a member under given axial force and bending moments. It is not a frame analysis, it does not do buckling, it does not model connections, and it does not check a member against a design code. The numbers it produces feed into that work, they are not that work, and a design decision still needs an engineer and a code check.

The fourth is the geometry dependency. Everything routes through shapely, which is a good design, and it also means that a shape that is not a valid polygon will not mesh. Real geometry from a CAD system often needs repair first, and the package cannot do that for you. The dxf and rhino extras help with getting the shape in, not with fixing it.

And the fifth is the installation constraint that the classifiers make plain. Python 3.11 or newer is required, so an organisation on an older platform interpreter is out, and the extras add their own constraints on top, with the rhino package pinned for Python below 3.14 and pypardiso limited to Windows and Linux. For a package in a long-lived engineering workflow, those pins are the ones that decide whether you can adopt it.

## Conclusion

sectionproperties is worth installing for anyone who needs section properties for a shape that is not a standard catalogue section, because the finite element route gives you the same kind of answer for an arbitrary geometry that you would otherwise get from a table lookup for an I-beam, and because the mesh is a real two-dimensional mesh rather than a lumped approximation, so the result reflects the actual shape including holes and fillets. It is the wrong tool if a standard section from a table will do. Before you use it, check three things: that your Python is 3.11 or newer, since that is the stated requirement and the classifiers cover 3.11 through 3.14; that you install the optional extras you need, since the rhino extra brings rhino3dm and the rhino-shapely-interop bridge for Rhino geometry, the dxf extra brings cad-to-shapely for CAD files and the pardiso extra brings pypardiso on Windows and Linux for a direct sparse solver; and that you check the results independently, because the project's own disclaimer states that although efforts have been made to ensure the relevant engineering theories have been correctly implemented, it remains the user's responsibility to confirm and accept the output.

## FAQ

### How do I install sectionproperties and analyse a rectangle?

Run pip install sectionproperties, then build the geometry with the preprocessing library, for example rectangular_section(d=100, b=50), call create_mesh(mesh_sizes=[5]), wrap it in Section(geometry=geom), call calculate_geometric_properties() and read the results with get_area() and get_ic(), which returns the centroidal moments of inertia. Python 3.11 or newer is required.

### What optional features does sectionproperties offer?

The packaging defines four extras. The rhino extra brings rhino3dm and rhino-shapely-interop for Rhino geometry, the dxf extra brings cad-to-shapely for CAD files, the pardiso extra brings pypardiso on Windows and Linux for a direct sparse solver, and the numba extra brings numba for JIT compilation of the hot loops.

### Is sectionproperties suitable for production engineering work?

The package is classified as Development Status :: 5 - Production/Stable and carries a JOSS paper, but its own disclaimer states that although efforts have been made to ensure the relevant engineering theories have been correctly implemented, it remains the user's responsibility to confirm and accept the output. It computes section properties and stresses for a cross-section, not a complete design check.

## Sources

- [License: MIT](https://github.com/robbievanleeuwen/section-properties/blob/master/LICENSE)
- [Project website](https://sectionproperties.rtfd.io)
- [README](https://github.com/robbievanleeuwen/section-properties/blob/master/README.md)
- [Releases](https://github.com/robbievanleeuwen/section-properties/releases)
- [robbievanleeuwen/section-properties on GitHub](https://github.com/robbievanleeuwen/section-properties)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/robbievanleeuwen-section-properties
