From 42872ffd063762efc81cd256bf23c9b8e33803fa Mon Sep 17 00:00:00 2001 From: Jukka Aho Date: Sat, 9 May 2026 17:36:32 +0300 Subject: [PATCH] docs(mesh): tighten README for current Mesh surface Replace marketing-heavy prose with a short map of the active files, the parametric `Mesh{N,T}` role, refinement usage, and where import/tests live now. - Drop duplicated API inventories and speculative future-work bullets. - Point readers at `src/io/` for ingest and `llm/design/legacy-tests/mesh/` for retired parallel/coloring coverage. --- src/mesh/README.md | 334 ++++++++------------------------------------- 1 file changed, 57 insertions(+), 277 deletions(-) diff --git a/src/mesh/README.md b/src/mesh/README.md index 35b8d22..3d7ba45 100644 --- a/src/mesh/README.md +++ b/src/mesh/README.md @@ -1,303 +1,83 @@ -# Mesh Module +# src/mesh/ -**Purpose:** Mesh data structures, creation, manipulation, and optimization for finite element analysis. +Mesh data structures, mesh generation utilities and a few graph-level +optimisations used by the rest of the package. -## Overview +## Files -The mesh module provides the core `Mesh{N,T}` data structure and related functionality for representing finite element meshes. It handles node coordinates, element connectivity, named sets (for boundary conditions and material regions), and mesh optimization via graph algorithms. +- `api.jl` — `AbstractMesh`, `AbstractRefineStrategy` and the + abstract interface (`nnodes_total`, `nelements`, `get_node`, + `connectivity_matrix`, `get_node_set`, `get_element_set`, …). +- `mesh.jl` — concrete `Mesh{N, T<:AbstractTopology{N}}` + type, constructors with validation, the inverse connectivity + (`node -> elements`) needed by node-based assembly, helpers for sets + and surface extraction. +- `structured.jl` — `create_structured_box_mesh`, + `create_unit_cube_mesh`, `create_cantilever_mesh`, + `create_thin_plate_mesh`. Boundary node sets are populated + automatically (`:xmin`, `:xmax`, …). +- `refine.jl` — `LongestEdgeBisection` and the `refine` entry + point. Used for h-convergence studies. -## Key Concepts - -### Type-Stable Parametric Mesh +## Type-stable mesh ```julia Mesh{N, T<:AbstractTopology{N}} ``` -The mesh is **parametrically typed** on topology for: -- **Type stability** (10× faster than abstract mesh) -- **GPU optimization** (fixed-size connectivity enables matrix reinterpretation) -- **Industrial workflows** (separate mesh per component in multi-body assemblies) +`N` is the number of nodes per element and `T` is the element topology. +Concrete instances such as `Mesh{8, Hex8}` carry no abstract fields, so +the assembly hot path can be fully inferred. The mesh stores -### Core Data -- **`nodes::Vector{Vec{3,Float64}}`** - Nodal coordinates (always 3D, 2D uses z=0) -- **`connectivity::Vector{NTuple{N,UInt32}}`** - Fixed-size element connectivity tuples -- **`element_sets::Dict{Symbol,Set{UInt32}}`** - Named element groups (e.g., `:body`, `:surface`) -- **`node_sets::Dict{Symbol,Set{UInt32}}`** - Named node groups (e.g., `:fixed`, `:loaded`) -- **`inverse_connectivity::Vector{Vector{Tuple{UInt32,UInt8}}}`** - Node-to-elements map (critical for nodal assembly) +- `nodes::Vector{Vec{3, Float64}}` — coordinates (always 3D; 2D problems + use `z = 0`), +- `connectivity::Vector{NTuple{N, UInt32}}` — fixed-size connectivity, +- `element_sets::Dict{Symbol, Set{UInt32}}`, +- `node_sets::Dict{Symbol, Set{UInt32}}`, +- `inverse_connectivity::Vector{Vector{Tuple{UInt32, UInt8}}}` — + populated lazily; needed by node-based assembly. -### Advanced Features -- **Bandwidth optimization** via RCM (Reverse Cuthill-McKee) ordering -- **Named nodes/elements** for industrial CAE workflows (multi-part assemblies) -- **Parallel computing support** (node/element coloring, ghost data for MPI) - -## Files - -### Core Infrastructure - -#### `api.jl` -**Purpose:** Abstract types, interfaces, and API definitions - -Defines: -- `AbstractMesh` - Base type for all meshes -- `AbstractRefineStrategy` - Base type for refinement strategies -- Interface methods: `nnodes_total()`, `nelements()`, `get_node()`, `connectivity_matrix()`, etc. - -**Read this first** to understand the mesh abstraction contract. - -#### `mesh.jl` -**Purpose:** Concrete `Mesh{N,T}` implementation - -The main mesh data structure with: -- Full field documentation (see struct docstring) -- Inner constructor with validation -- API method implementations -- Helper functions for connectivity matrices, inverse maps, etc. - -**This is the workhorse file** - ~850 lines of core mesh functionality. - -### Mesh Creation - -#### `structured.jl` -**Purpose:** Generate simple structured meshes programmatically - -Functions: -- `create_structured_box_mesh(Hex8; xmin, xmax, nx, ...)` - Create regular box mesh -- Automatically creates boundary node sets (`:xmin`, `:xmax`, `:ymin`, etc.) -- Perfect for testing, tutorials, and simple geometries - -**Example:** -```julia -# 10×2×2 cantilever beam mesh -mesh = create_structured_box_mesh(Hex8, - xmin=0.0, xmax=10.0, nx=10, - ymin=0.0, ymax=2.0, ny=2, - zmin=0.0, zmax=2.0, nz=2) -``` - -#### `circular.jl` -**Purpose:** Generate circular/polar meshes for plates - -Functions: -- `create_circular_plate_mesh(Tri3; radius, nr, nθ)` - Polar triangulation for circular plates -- Fan topology from center node - ideal for Kirchhoff plate elements (DKT) -- Creates `:center` and `:outer` node sets for boundary conditions - -**Example:** -```julia -# Circular plate with 5 radial rings, 48 sectors -mesh = create_circular_plate_mesh(Tri3; radius=0.5, nr=5, nθ=48) -``` - -#### `gmsh_wrapper.jl` -**Purpose:** Interface to Gmsh mesh generator - -Functions: -- `gmsh_initialize()` - Initialize Gmsh API (consolidated from Gmsh.jl) -- Provides access to `gmsh` module for complex geometries -- Use for industrial CAD-to-mesh workflows - -**Note:** Requires `gmsh_jll` package for Gmsh binary. - -### Mesh Manipulation - -#### `refine.jl` -**Purpose:** Mesh refinement strategies for convergence studies - -Strategies: -- `LongestEdgeBisection(levels)` - Adaptive octree-style refinement - - Analyzes each element to find longest dimension - - Splits along that direction (preserves geometry aspect ratio) - - Creates 4 new nodes, 2 new elements per split - - Element count grows as 2^level - -**Example:** -```julia -# Refine 3 times: 1 → 2 → 4 → 8 elements -refined = refine(mesh, LongestEdgeBisection(3)) -``` - -**Use cases:** -- Convergence studies (h-refinement) -- Creating dense meshes from simple coarse definitions -- Mesh sensitivity analysis - -See [`README_REFINEMENT.md`](./README_REFINEMENT.md) for detailed documentation. - -### Mesh Optimization - -#### `graph_ordering.jl` -**Purpose:** Graph algorithms for bandwidth minimization - -Functions: -- `symrcm(G, v)` - Sparse Reverse Cuthill-McKee ordering (consolidated from GraphOrdering.jl) -- `bandwidth(G)` - Calculate graph bandwidth -- Returns `GraphOrderingResult` with permutation vectors - -**Purpose:** Minimize matrix bandwidth for direct solvers -- Reduces fill-in during factorization (Cholesky, LU) -- Improves cache locality -- Critical for large 3D problems with direct solvers - -**Integration:** Mesh stores `node_permutation` and `element_permutation` fields. - -## Usage Patterns - -### Creating a Mesh - -#### From Structured Grid -```julia -using JuliaFEM -using Tensors - -# Simple box mesh -mesh = create_structured_box_mesh(Hex8, xmax=1.0, ymax=1.0, zmax=1.0, nx=4, ny=4, nz=4) - -# Apply Dirichlet BC to xmin face -fixed_nodes = mesh.node_sets[:xmin] -``` - -#### From Gmsh -```julia -using JuliaFEM - -gmsh_initialize() -# ... gmsh commands to create geometry and mesh ... -mesh = import_gmsh_mesh() # TODO: implement import function -gmsh.finalize() -``` - -#### Manual Construction -```julia -# 4-node tetrahedron -nodes = [Vec(0.0, 0.0, 0.0), Vec(1.0, 0.0, 0.0), - Vec(0.0, 1.0, 0.0), Vec(0.0, 0.0, 1.0)] -connectivity = [(UInt32(1), UInt32(2), UInt32(3), UInt32(4))] - -mesh = Mesh{4, Tet4}(nodes, connectivity) -``` - -### Accessing Mesh Data +## Common usage ```julia -# Basic queries +mesh = create_structured_box_mesh(Hex8; + xmin = 0.0, xmax = 1.0, nx = 4, + ymin = 0.0, ymax = 1.0, ny = 4, + zmin = 0.0, zmax = 1.0, nz = 4, +) + n_nodes = nnodes_total(mesh) n_elems = nelements(mesh) -# Node coordinates -X = get_node(mesh, 42) # Vec{3}(x, y, z) - -# Connectivity -conn = connectivity_matrix(mesh) # Matrix{Int} - zero-copy view for GPU -elem_nodes = conn[elem_id, :] # Node IDs for element - -# Inverse connectivity (node → elements, critical for nodal assembly!) -elems_containing_node = get_elements_for_node(mesh, node_id) - -# Named sets -fixed_nodes = get_node_set(mesh, :fixed) -body_elements = get_element_set(mesh, :body) +X = get_node(mesh, 42) +fixed = get_node_set(mesh, :xmin) +body = get_element_set(mesh, :body) +elem_xs = get_elements_for_node(mesh, node_id) ``` -### Mesh Refinement +## Refinement ```julia -# Convergence study -coarse_mesh = create_structured_box_mesh(Hex8, nx=2, ny=2, nz=2) - -for level in 0:4 - if level == 0 - mesh = coarse_mesh - else - mesh = refine(coarse_mesh, LongestEdgeBisection(level)) - end - - println("Level $level: $(nelements(mesh)) elements") - # Run FEM analysis... -end +refined = refine(mesh, LongestEdgeBisection(3)) ``` -## Design Philosophy +`LongestEdgeBisection(levels)` performs adaptive bisection along the +longest edge of each element, doubling the element count per level. -### Separation of Concerns -- **Mesh owns topology** (nodes, connectivity, sets) -- **Physics references mesh** (does not own it) -- **Multiple physics can share one mesh** (multiphysics coupling) +## I/O -### Type Stability for Performance -- `Mesh{8, Hex8}` is fully concrete (no abstract fields) -- Fixed-size `NTuple{8,UInt32}` connectivity (not `Vector{Int}`) -- Enables 10× performance gains vs abstract mesh types +Mesh import lives in `src/io/` (currently the self-contained Gmsh +reader). VTK / XDMF output is not implemented in the new path; the +legacy results writers under `src/legacy/` cover existing tests. -### Industrial Workflows -- Named node/element IDs support multi-part assemblies - - Part 1: node IDs 10,000,001 → 10,050,000 - - Part 2: node IDs 20,000,001 → 20,030,000 -- Element/node sets for boundary conditions and material regions -- Multi-body assembly via separate meshes per component - -### GPU and Parallel Computing -- `connectivity_matrix()` provides zero-copy `Matrix{Int}` for GPU transfer -- Node/element coloring for thread-safe assembly -- Ghost nodes/elements for MPI domain decomposition -- `inverse_connectivity` enables efficient nodal assembly (see `docs/book/multigpu_nodal_assembly.md`) - -## Future Extensions - -Planned features: -- **Mixed-topology meshes** (`MixedMesh` type) -- **Gmsh import function** (read `.msh` files) -- **Abaqus/Code Aster readers** (consolidate from vendor packages) -- **More refinement strategies** (uniform octree, red-green, adaptive) -- **Surface extraction** (generate boundary mesh for visualization/BCs) -- **Mesh quality metrics** (Jacobian determinant, aspect ratio) -- **RCM integration** (automatic bandwidth minimization) - -## Testing - -Run tests: -```bash -julia --project=. test/mesh/runtests.jl -``` - -Key test files: -- `test/mesh/test_structured.jl` - Structured mesh generation -- `test/mesh/test_refine.jl` - Refinement algorithms -- `test/mesh/test_connectivity.jl` - Connectivity and inverse maps - -## Examples - -See: -- `examples/structured_mesh_demo.jl` - Creating and using structured meshes -- `examples/mesh_refinement_demo.jl` - Convergence study with refinement -- `examples/cantilever_minimal_new_api.jl` - Complete FEM example with mesh - -## Dependencies - -- `Tensors.jl` - For `Vec{3,Float64}` node coordinates -- `gmsh_jll` (optional) - For Gmsh mesh generation - -## Related Modules - -- **`src/topology/`** - Element topology (reference coordinates, edges, faces) -- **`src/basis/`** - Shape functions (interpolation on mesh) -- **`src/assemblers/`** - Uses `inverse_connectivity` for nodal assembly -- **`src/domains/`** - Physics modules that operate on meshes - -## Notes - -- **Always 3D coordinates:** Even 2D problems use `Vec{3}` with z=0 (simplifies code) -- **UInt32 for indices:** Saves memory vs Int64, supports 4 billion nodes -- **Memory profiling artifacts:** `*.mem` files are git-ignored (profiler output) - -## References - -- Reverse Cuthill-McKee: [SIAM J. Numer. Anal. 13, 865 (1976)] -- Octree refinement: Standard technique in adaptive mesh refinement (AMR) -- Nodal assembly architecture: `docs/book/multigpu_nodal_assembly.md` - ---- - -**Maintainer:** JuliaFEM Team -**Last Updated:** November 21, 2025 +## Related code +- `src/topology/` — element topologies referenced by `Mesh{N,T}`. +- `src/dofs/` — the DOF handler walks the mesh to assign + global DOF numbers. +- `src/assemblers/` — element-based and DOF-based assembly both + consume the mesh and its inverse connectivity. +- `test/` — mesh-level coverage rides on the active + domain test suites (`test/domains/`, `test/assemblers/`); the legacy + parallel/coloring/RCM tests live at + `llm/design/legacy-tests/mesh/`.