XelToFab
Guides

Quality Metrics

Mesh quality targets for FEA, metric computation, and benchmarking

FEA quality targets

For finite element analysis (FEA) to produce accurate results, mesh elements must meet minimum quality standards. XelToFab tracks three key metrics:

MetricTargetDescription
Aspect ratio< 5Ratio of longest to shortest edge. Lower is better (1.0 = equilateral)
Minimum angle> 20 degreesSmallest interior angle in each triangle. Higher is better (60 = equilateral)
Scaled Jacobian> 0.5Measures element distortion. Higher is better (1.0 = ideal)
Scaled Jacobian heatmap and histogram showing FEA quality distribution

Elements that violate these thresholds can cause numerical instability, poor conditioning, or inaccurate stress/strain results in FEA solvers.

How metrics are computed

Quality metrics are computed using PyVista, which wraps VTK's mesh quality filters. The benchmark script converts the pipeline output to a PyVista PolyData mesh and calls cell_quality() with three measures:

import numpy as np
import pyvista as pv

# Build PyVista mesh from pipeline state
faces_pv = np.column_stack([np.full(len(state.faces), 3), state.faces]).ravel()
pv_mesh = pv.PolyData(state.best_vertices.astype(np.float64), faces_pv)

# Compute quality metrics
qual = pv_mesh.cell_quality(["aspect_ratio", "min_angle", "scaled_jacobian"])

# Access per-cell values
aspect_ratios = qual.cell_data["aspect_ratio"]
min_angles = qual.cell_data["min_angle"]
jacobians = qual.cell_data["scaled_jacobian"]

Each metric produces a per-cell (per-triangle) array. The benchmark reports the minimum, mean, maximum, and standard deviation.

Additional properties checked by the benchmark:

  • Watertight -- Whether the mesh forms a closed manifold (checked via trimesh.Trimesh.is_watertight)
  • Volume -- Computed by trimesh for watertight meshes only
  • Surface area -- Total mesh surface area

Current baseline results

These results were captured with the default pipeline parameters using the benchmark script. They represent the baseline quality before any Tier 2 improvements (decimation, remeshing).

3D models

ModelVerticesFacesWatertightAR (mean)Angle (min)Jacobian (min)Time (s)
heat_cond_51_s07,08713,910no1.273.2 deg0.0640.011
heat_cond_51_s117,28733,528no1.263.2 deg0.0640.015
thermoelastic_16_s09791,806no1.390.8 deg0.0160.002
corner_3d_vf50_s02,1233,902no1.382.8 deg0.0560.003
corner_3d_vf30_s01,9613,568no1.420.5 deg0.0100.003
synthetic_sphere192380yes1.2030.4 deg0.5840.002
synthetic_sphere_sdf9841,964yes1.3124.2 deg0.4730.001

2D models

ModelContoursTotal PointsVolume FractionTime (s)
beam_2d_100x200_s053560.23750.001

Observations

  • Mean aspect ratios are good (all below 1.5), well within the < 5 target
  • Minimum angles are below the 20-degree target for most real-world TO models. The synthetic sphere meets the target, but TO geometry with thin features and sharp corners produces degenerate triangles
  • Minimum scaled Jacobians are below the 0.5 target for all TO models. Again, synthetic geometry is much closer to the target
  • No TO model produces a watertight mesh with the current pipeline. Watertight output will require dedicated repair/remeshing stages
  • These limitations are expected for marching cubes output without decimation or remeshing and represent the improvement targets for future pipeline stages

Running the benchmark

The benchmark script processes all registered models (EngiBench datasets, Corner-Based TO, and synthetic shapes) and generates meshes, comparison plots, 3D renders, and a metrics summary.

uv run python scripts/benchmark_baseline.py

Output goes to benchmarks/baseline/ by default. Specify a different directory to compare before/after:

uv run python scripts/benchmark_baseline.py --output-dir benchmarks/after-remeshing

The script generates:

FileDescription
<model>.stlExported mesh for each 3D model
<model>_comparison.pngSide-by-side scalar field vs extraction result
<model>_mesh.png3D mesh render (requires PyVista)
metrics.jsonFull metrics for all models (JSON)
summary.mdHuman-readable summary table

PyVista is required for quality metrics (aspect_ratio, min_angle, scaled_jacobian) and 3D renders. The benchmark still runs without it but skips those outputs.

Outline