2. Finite element mesh representations for machine learning

Crash simulation meshes are not naturally tensor-like. An LS-DYNA or Radioss deck stores geometry as an unstructured collection of nodes and elements, with arbitrary node numbering, mixed element types, and variable connectivity. Before any machine learning model can consume this data, the mesh must be re-expressed in a representation the model can process. This section covers the four canonical representations — raw nodal/connectivity arrays, graphs, images, and point clouds — and the conversion paths between them.

Node Coordinates and Element Connectivity

The irreducible core of any FE mesh is two arrays. The node coordinate array is an N × 3 float matrix, where row i holds the (x, y, z) position of node i. The connectivity array is an M × k integer matrix, where row j lists the node indices belonging to element j. For a mesh with N = 480,000 nodes and M = 470,000 shell elements, the coordinate array occupies about 11.5 MB in float32, and the connectivity array about 3.8 MB in int32 — small enough to hold in memory, which matters because crash decks routinely exceed one million elements.

Two conventions must be fixed before any conversion, because they propagate into every downstream representation:

  • Indexing base. LS-DYNA and most solvers use 1-based node IDs; NumPy, PyTorch Geometric, and most ML tooling use 0-based indices. Convert once, at ingestion, and record the offset. A silent off-by-one here produces a mesh that looks plausible but has every element attached to the wrong nodes.
  • Coordinate frame and units. Crash decks are typically in millimetres with the vehicle X-axis pointing forward, Y to the left, and Z up. If you normalize coordinates for a neural network, store the mean and scale so predictions can be mapped back to physical space.

Element type is encoded implicitly by the width k of the connectivity row and by the solver's element card. A 4-node shell (LS-DYNA *ELEMENT_SHELL) has k = 4; a 3-node shell has k = 3; a 4-node solid tetrahedron (*ELEMENT_SOLID, ELFORM 10) has k = 4; an 8-node hexahedron has k = 8. Because shell and solid elements can share the same k, the element type must be carried as a separate label array, not inferred from connectivity width alone.

Shell and Solid Element Topology

Shell and solid elements differ in ways that directly constrain the choice of ML representation. A shell element is a 2D surface embedded in 3D: its four nodes are nominally coplanar, it carries a thickness t and often multiple through-thickness integration points, and its normal direction defines bending behaviour. A solid element is a 3D volume: its nodes are not coplanar, and it has no thickness attribute.

This matters for defect detection. A common crash-mesh defect is a warped or inverted shell, where the four nodes deviate from planarity or the element normal flips relative to its neighbours. Detecting this requires the element's local geometry — the normal vector, the warp angle, the Jacobian — which is computed from the four node coordinates in connectivity order. If the connectivity order is permuted during conversion, the computed normal flips sign and the defect signal is destroyed. Connectivity order is semantically meaningful for shells and must be preserved.

Solid elements have a different failure mode: negative or near-zero Jacobian, indicating an inverted or degenerate hex. Here the relevant signal is the signed volume computed from the eight corner nodes. Both cases illustrate the same principle: the ML representation must retain enough local geometric context to reconstruct the defect criterion, or the model is learning from corrupted inputs.

Practical rule: before converting a mesh, compute the defect criterion you intend to predict (warp angle, Jacobian, aspect ratio, free-edge flag) directly on the raw mesh. Store it as a per-element label. Then verify that your converted representation can reproduce that label from its own features. If it cannot, the representation has lost the signal.

Conversion to Graph, Image, and Point-Cloud Formats

The three ML-facing representations each preserve a different subset of mesh structure. The diagram below shows how a single shell mesh maps onto each.

From FE Mesh to ML Representations Raw FE Mesh nodes N×3, conn M×k Graph nodes = mesh nodes edges = element adjacency features: coords, thickness labels: per-node defect flag preserves topology, not order Image / Voxel Grid rasterize coords to H×W×C channels: thickness, normal, warp angle, material ID labels: per-pixel defect mask requires regular sampling Point Cloud points = node coords features: x, y, z, normal labels: per-point defect class no connectivity retained order-invariant, loses adjacency Signal Retention Graph ✓ element adjacency ✓ node coordinates ✓ connectivity order (if directed) ✗ regular spatial grid Image ✓ regular spatial neighbourhood ✓ multi-channel features ✗ exact connectivity ✗ non-uniform mesh density Point Cloud ✓ exact node positions ✓ permutation invariance ✗ element connectivity ✗ shell normal from order Selection guide Topology defects → Graph Spatial patterns → Image Local geometry → Point cloud

Choosing and Building the Representation

Graph conversion. Treat each mesh node as a graph node and each element as a clique (or a star centred on a virtual element node) connecting its constituent nodes. Node features are the three coordinates plus optional thickness and material ID; edge features can encode the element type or the edge length. In PyTorch Geometric this is an edge_index tensor of shape 2 × E and an x tensor of shape N × F. For a shell mesh with 470,000 elements, the clique expansion produces roughly E ≈ 2.8M undirected edges — manageable, but the clique expansion inflates edge count by a factor of k(k-1)/2 relative to the element count. A star expansion (one virtual node per element) keeps E = M × k and is often preferable for large decks.

Image conversion. Project the mesh onto a regular grid. For a vehicle body-in-white, a common choice is to rasterize onto the X–Y plane at 5 mm resolution, producing a H × W grid where each pixel aggregates the elements whose centroids fall inside it. Channels typically include element count, mean thickness, mean warp angle, and a binary free-edge flag. The critical limitation is density mismatch: a 5 mm pixel may contain 20 elements in a refined crush zone and zero in a coarse panel, so the image is sparse and non-uniform. Padding empty pixels with zeros introduces a strong artificial signal that a CNN will happily learn. Mask the loss to valid pixels, or use a sparse convolution backbone.

Point-cloud conversion. Use node coordinates directly as an N × 3 point set, optionally augmented with per-node normals computed from adjacent shell elements. Point-cloud models such as PointNet++ or KPConv are permutation-invariant and handle non-uniform density, but they discard connectivity entirely. A warped shell whose four nodes are individually well-placed but collectively non-planar is invisible to a point-cloud model that only sees node positions — the warp signal lives in the connectivity, not the coordinates.

Conversion checklist. (1) Convert node IDs to 0-based and record the offset. (2) Preserve connectivity order for shell elements. (3) Compute and store the defect label on the raw mesh before conversion. (4) After conversion, verify the label is recoverable from the representation's own features. (5) For image conversion, mask invalid pixels in the loss. (6) For graph conversion, decide clique vs. star expansion based on element count.

Worked Example: Converting a 470k-Element Shell Mesh

Consider a body-in-white deck with N = 480,000 nodes and M = 470,000 quad shell elements. The target defect is warped shell, defined as a warp angle exceeding 15°. The conversion proceeds as follows.

import numpy as np

# nodes: (N, 3) float32, 0-based after offset correction
# conn:  (M, 4) int32, connectivity order preserved
# warp:  (M,)   float32, per-element warp angle in degrees

# --- Graph (star expansion) ---
# virtual element nodes appended after real nodes
elem_ids = np.arange(M) + N
src = np.concatenate([conn[:, 0], conn[:, 1], conn[:, 2], conn[:, 3]])
dst = np.tile(elem_ids, 4)
edge_index = np.stack([np.concatenate([src, dst]),
                       np.concatenate([dst, src])])  # undirected

# --- Image (5 mm raster on X-Y) ---
centroids = nodes[conn].mean(axis=1)          # (M, 3)
ij = np.floor(centroids[:, :2] / 5.0).astype(np.int32)
H, W = ij[:, 1].max() + 1, ij[:, 0].max() + 1
warp_img = np.zeros((H, W), dtype=np.float32)
count_img = np.zeros((H, W), dtype=np.float32)
np.add.at(warp_img, (ij[:, 1], ij[:, 0]), warp)
np.add.at(count_img, (ij[:, 1], ij[:, 0]), 1)
valid = count_img > 0
warp_img[valid] /= count_img[valid]            # mean warp per pixel

# --- Point cloud ---
pc = nodes.copy()                              # (N, 3)
# per-node normal from adjacent shells omitted for brevity

After conversion, verify that the graph representation can reproduce the warp label: for each virtual element node, gather its four real neighbours, recompute the warp angle from their coordinates, and compare against warp. A maximum absolute difference below 1e-4 degrees confirms the connectivity order survived conversion. If the difference is large, the most likely cause is a permuted connectivity row — check whether the element normal flipped sign, which indicates nodes 2 and 3 were swapped.

For the image representation, inspect valid: if fewer than 60% of pixels are valid, the 5 mm resolution is too fine for the mesh density and you should coarsen to 10 mm. For the point cloud, the warp signal is not directly recoverable, which is expected — point clouds are appropriate for node-position defects such as duplicate or missing nodes, not for element-level warp.

The choice of representation is therefore not a matter of convenience but of which defect class you intend to detect. Graph representations preserve the connectivity that shell and solid defect criteria depend on; images trade exact topology for spatial regularity and CNN efficiency; point clouds preserve exact geometry but discard the adjacency that defines element-level defects. Matching representation to defect class is the first design decision in any mesh-defect ML pipeline.