Validation and Quality#

Tools for assessing mesh integrity and element quality.

Validation

validate() checks structural correctness: valid index ranges, consistent dimensions, proper data types, and data shape compatibility. It returns a report of any errors found and is also accessible as mesh.validate(). validate_mesh remains available as a pending-deprecation compatibility name.

Quality metrics

compute_quality_metrics() returns per-cell geometric quality indicators including aspect ratio, minimum and maximum angles, edge length ratios, and an overall quality score in a TensorDict. It is also accessible as mesh.quality_metrics.

Statistics

compute_mesh_statistics() returns aggregate summaries (minimum, maximum, mean, and standard deviation) of geometric quantities across the entire mesh, including edge lengths, cell areas, angles, and quality scores. It is also accessible as mesh.statistics.

from physicsnemo.mesh.primitives.surfaces import sphere_icosahedral

mesh = sphere_icosahedral.load(subdivisions=2)

# Validate structural integrity
report = mesh.validate()

# Per-cell quality
quality = mesh.quality_metrics
print(quality["quality_score"].mean())

# Aggregate statistics
stats = mesh.statistics

API Reference#

Mesh validation, quality metrics, and statistics.

This module provides tools for validating mesh integrity, computing quality metrics, and generating mesh statistics.

physicsnemo.mesh.validation.compute_mesh_statistics(
mesh: Mesh,
tolerance: float = 1e-10,
) Mapping[str, int | float | tuple[float, float, float, float]][source]#

Compute summary statistics for mesh.

Returns dictionary with mesh statistics:

  • n_points: Number of vertices

  • n_cells: Number of cells

  • n_manifold_dims: Manifold dimension

  • n_spatial_dims: Spatial dimension

  • n_degenerate_cells: Cells with area < tolerance

  • n_isolated_vertices: Vertices not in any cell

  • edge_length_stats: (min, mean, max, std) of edge lengths

  • cell_area_stats: (min, mean, max, std) of cell areas

  • aspect_ratio_stats: (min, mean, max, std) of aspect ratios

  • quality_score_stats: (min, mean, max, std) of quality scores

Parameters:
  • mesh (Mesh) – Mesh to analyze

  • tolerance (float) – Threshold for degenerate cell detection

Returns:

Dictionary with statistics

Return type:

Mapping[str, int | float | tuple[float, float, float, float]]

Examples

>>> from physicsnemo.mesh.primitives.basic import two_triangles_2d
>>> mesh = two_triangles_2d.load()
>>> stats = compute_mesh_statistics(mesh)
>>> assert "n_points" in stats and "n_cells" in stats
physicsnemo.mesh.validation.compute_quality_metrics(mesh: Mesh) TensorDict[source]#

Compute geometric quality metrics for all cells.

Returns TensorDict with per-cell quality metrics:

  • aspect_ratio: normalized max_edge / min_altitude (lower is better, 1.0 is a regular simplex)

  • min_angle: Minimum interior angle in radians

  • max_angle: Maximum interior angle in radians

  • edge_length_ratio: max_edge / min_edge (1.0 is a regular simplex)

  • quality_score: Combined metric in [0,1] (1.0 is a regular simplex)

Parameters:

mesh (Mesh) – Mesh to analyze

Returns:

TensorDict of shape (n_cells,) with quality metrics

Return type:

TensorDict

Notes

A 0-simplex has no shape to distort, so its aspect ratio, edge-length ratio, and quality score are 1. Its edge lengths and angles are undefined and reported as NaN.

Examples

>>> from physicsnemo.mesh.primitives.basic import two_triangles_2d
>>> mesh = two_triangles_2d.load()
>>> metrics = compute_quality_metrics(mesh)
>>> assert "quality_score" in metrics.keys()
physicsnemo.mesh.validation.validate(
mesh: Mesh,
check_degenerate_cells: bool = True,
check_duplicate_vertices: bool = True,
check_inverted_cells: bool = False,
check_out_of_bounds: bool = True,
check_manifoldness: bool = False,
tolerance: float | None = None,
raise_on_error: bool = False,
*,
check_self_intersection: bool = False,
) Mapping[str, bool | int | Tensor][source]#

Validate mesh integrity and detect common errors.

Performs a comprehensive set of checks to ensure mesh is well-formed and suitable for geometric computations. Call it as validate(mesh, ...) or as mesh.validate(...). The bound method supplies mesh automatically.

Parameters:
  • mesh (Mesh) – Mesh to validate

  • check_degenerate_cells (bool) – Check for zero/negative area cells

  • check_duplicate_vertices (bool) – Check for coincident vertices within tolerance

  • check_inverted_cells (bool) – Check for cells with negative orientation (expensive)

  • check_out_of_bounds (bool) – Check that cell indices are valid

  • check_manifoldness (bool) – Check manifold topology (2D only, expensive)

  • tolerance (float | None) – Tolerance for geometric checks (areas, distances). If None (default), uses a dtype-aware epsilon via safe_eps().

  • raise_on_error (bool) – If True, raise ValueError on first error. If False, return dict with all validation results.

  • check_self_intersection (bool) – Request a self-intersection check. This option is keyword-only and not yet implemented; passing True raises NotImplementedError.

Returns:

Dictionary with validation results:

  • ”valid”: bool, True if all enabled checks passed

  • ”n_degenerate_cells”: int, number of degenerate cells found

  • ”degenerate_cell_indices”: Tensor of indices (if any found)

  • ”n_duplicate_vertices”: int, number of duplicate vertex pairs

  • ”duplicate_vertex_pairs”: Tensor of index pairs (if any found)

  • ”n_out_of_bounds_cells”: int, cells with invalid indices

  • ”out_of_bounds_cell_indices”: Tensor of cell indices (if any)

  • ”n_inverted_cells”: int (if check enabled)

  • ”inverted_cell_indices”: Tensor (if check enabled and any found)

  • ”is_manifold”: bool (if check enabled, 2D only)

  • ”non_manifold_edges”: Tensor of edge indices (if check enabled)

Return type:

Mapping[str, bool | int | torch.Tensor]

Raises:
  • ValueError – If raise_on_error=True and validation fails

  • NotImplementedError – If check_self_intersection=True because that check is not yet implemented.

Examples

>>> from physicsnemo.mesh.primitives.basic import two_triangles_2d
>>> mesh = two_triangles_2d.load()
>>> report = validate(mesh)
>>> assert report["valid"] == True
physicsnemo.mesh.validation.validate_mesh(
mesh: Mesh,
check_degenerate_cells: bool = True,
check_duplicate_vertices: bool = True,
check_inverted_cells: bool = False,
check_out_of_bounds: bool = True,
check_manifoldness: bool = False,
check_self_intersection: bool = False,
tolerance: float | None = None,
raise_on_error: bool = False,
) Mapping[str, bool | int | Tensor][source]#

Compatibility wrapper for validate() pending deprecation.