apeGmsh mesh partitioning and renumbering¶
A guide to mesh partitioning for parallel solvers and node/element renumbering for bandwidth reduction.
Grounded in the current source:
src/apeGmsh/mesh/_mesh_partitioning.py—_Partitioningsub-compositesrc/apeGmsh/solvers/Numberer.py— renumbering algorithms
All snippets assume a meshed model:
from apeGmsh import apeGmsh
g = apeGmsh(model_name="demo")
g.begin()
g.model.geometry.add_box(0, 0, 0, 10, 10, 3)
g.mesh.sizing.set_global_size(0.5)
g.mesh.generation.generate(3)
1. Why renumber¶
Gmsh assigns node and element tags as it meshes. These tags are typically non-contiguous (gaps from deleted entities, merged nodes) and unordered (no spatial locality). This causes two problems:
- Sparse arrays — if max_tag = 50000 but you only have 10000 nodes, solver arrays waste 5× memory.
- High bandwidth — the stiffness matrix has nonzero entries wherever two nodes share an element. If adjacent nodes have tags far apart, the bandwidth is large and direct solvers are slow.
Renumbering solves both: contiguous IDs (no gaps) and optionally bandwidth-reducing orderings.
2. Simple renumbering¶
g.mesh.partitioning.renumber(dim=3, method="simple", base=1)
fem = g.mesh.queries.get_fem_data(dim=3)
method="simple" assigns contiguous IDs starting from base:
- Nodes: 1, 2, 3, ..., N
- Elements: 1, 2, ..., E
The ordering is whatever Gmsh's internal traversal produces — no bandwidth optimization. Use this when you just need contiguous IDs (e.g., for OpenSees which requires base=1).
3. RCM renumbering¶
g.mesh.partitioning.renumber(dim=3, method="rcm", base=1)
fem = g.mesh.queries.get_fem_data(dim=3)
print(f"Bandwidth: {fem.info.bandwidth}")
method="rcm" uses the Reverse Cuthill-McKee algorithm to
minimize the semi-bandwidth of the stiffness matrix. This is the
gold standard for direct solvers (Cholesky, LDL^T) — lower
bandwidth means less fill-in, less memory, faster factorization.
How much does it help? For a typical 3D tet mesh, RCM reduces the bandwidth by 3-10× compared to the natural ordering. For structured hex meshes, the improvement is smaller (the natural ordering is already decent).
When to use RCM: - Direct solvers (sparse Cholesky, LDL^T) — always - Iterative solvers (CG, GMRES) — usually helps with ILU preconditioner - Explicit dynamics — no benefit (diagonal mass matrix)
4. Parameters¶
| Parameter | Default | Meaning |
|---|---|---|
dim |
2 | Element dimension for adjacency graph |
method |
"rcm" |
"simple" (contiguous), "rcm", "hilbert", or "metis" |
base |
1 | Starting ID. 1 for OpenSees/Abaqus, 0 for C-style |
5. Mesh partitioning (for MPI)¶
Splits the mesh into n_parts sub-domains using METIS graph
partitioning. This creates Gmsh partition entities that can be
exported to separate mesh files for parallel solvers.
When to use: - MPI-parallel OpenSees runs - Domain decomposition methods - Parallel mesh export (each partition → separate file)
6. Public API¶
renumber() is the only public entry point on _Partitioning. It handles
both nodes and elements in a single call; the per-step helpers
(_renumber_nodes_simple, _renumber_elements_simple) are private and
should not be invoked directly.
7. Standalone Numberer¶
For renumbering a FEMData object without modifying the Gmsh model:
from apeGmsh import Numberer
fem = g.mesh.queries.get_fem_data(dim=3)
numb = Numberer(fem)
nm = numb.renumber(method="rcm", base=1) # → NumberedMesh
print(nm)
8. Best practices¶
-
Always renumber before
get_fem_data()— the FEM broker captures whatever IDs exist at extraction time. Renumber first so the broker has clean, contiguous, optimized IDs. -
Use
base=1for OpenSees — OpenSees expects 1-based node/ element tags.base=0is for C-style solvers. -
Use
method="rcm"for direct solvers — the bandwidth reduction is free (runs in milliseconds) and can speed up factorization by orders of magnitude. -
Call renumber only once — renumbering mutates the Gmsh model. Calling it twice produces correct but redundant work.
See also¶
guide_meshing.md— mesh generation and sizingguide_fem_broker.md— extracting FEM data after renumberingguide_opensees.md— OpenSees model building