Skip to content

PhysicsNeMo-Mesh: Adds new capability of Polyhedra triangulation in PyVista/VTU I/O#1469

Merged
peterdsharpe merged 21 commits intoNVIDIA:mainfrom
peterdsharpe:psharpe/add-mesh-polyhedra-conversion
Mar 9, 2026
Merged

PhysicsNeMo-Mesh: Adds new capability of Polyhedra triangulation in PyVista/VTU I/O#1469
peterdsharpe merged 21 commits intoNVIDIA:mainfrom
peterdsharpe:psharpe/add-mesh-polyhedra-conversion

Conversation

@peterdsharpe
Copy link
Collaborator

@peterdsharpe peterdsharpe commented Mar 4, 2026

PhysicsNeMo Pull Request

To import VTK meshes (typically VTU unstructured grid files) into PhysicsNeMo-Mesh, all cells need to be converted to simplices - in 3D, this means tetrahedra. While this can be readily accomplished for hexahedra, wedges, pyramids, prisms, etc., polyhedra are notoriously difficult. When we say "polyhedra", we're referring to VTK's most-generic-possible cell type, which allows for arbitrary face connectivity.

These are difficult to process because there are very few geometric guarantees that you can make about how many tets each polyhedron needs to decompose into.

This PR fixes that, and adds tests to verify correctness by asserting that various geometric invariants hold across this conversion.

A direct consequence of this is that we can now support conversion for the High Lift Aero dataset internally. @coreyjadams

Description

Checklist

Dependencies

Review Process

All PRs are reviewed by the PhysicsNeMo team before merging.

Depending on which files are changed, GitHub may automatically assign a maintainer for review.

We are also testing AI-based code review tools (e.g., Greptile), which may add automated comments with a confidence score.
This score reflects the AI’s assessment of merge readiness and is not a qualitative judgment of your work, nor is
it an indication that the PR will be accepted / rejected.

AI-generated feedback should be reviewed critically for usefulness.
You are not required to respond to every AI comment, but they are intended to help both authors and reviewers.
Please react to Greptile comments with 👍 or 👎 to provide feedback on their accuracy.

- Updated the handling of UnstructuredGrid meshes to utilize the celltypes array instead of cells_dict, improving compatibility with variable-length polyhedra.
- Adjusted error messages and test cases to reflect the new attribute usage.
- Renamed tessellation references to triangulation for clarity in the context of mesh conversion.
@peterdsharpe peterdsharpe requested a review from coreyjadams March 4, 2026 17:15
@peterdsharpe peterdsharpe marked this pull request as ready for review March 4, 2026 17:16
@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 4, 2026

Greptile Summary

This PR fixes VTK_POLYHEDRON support in the PyVista I/O layer by replacing cells_dict-based cell counting (which raises ValueError for variable-length polyhedra) with celltypes array lookups, and by switching from tessellate() to triangulate() for tetrahedralization. The change is architecturally correct and well-motivated; pv.DataSetTriangleFilter (invoked by triangulate()) handles VTK_POLYHEDRON natively, whereas tessellate() did not.

Key changes and observations:

  • celltypes (a simple integer array) replaces cells_dict for cell-type counting throughout the auto-detection path, avoiding the ValueError that polyhedra cells trigger in cells_dict.
  • pv.CellType.POLYHEDRON is added to the volume cell type list so mixed-polyhedra grids are auto-detected as 3D.
  • triangulate() replaces tessellate(max_n_subdivide=1) as the tetrahedralization step; the hexbeam test is updated accordingly (no new vertices are added, so the point count equality assertion is tightened from >= to ==).
  • Guard condition is fragile: the hasattr(pyvista_mesh, "celltypes") check on line 147 is intended to reject pv.PolyData inputs, but in PyVista ≥ 0.43 celltypes is available on the DataSet base class and therefore on PolyData too. This means a surface mesh passed with manifold_dim=3 silently bypasses the intended guard and produces a confusing downstream error instead of the intended "please use an UnstructuredGrid" message. An isinstance(pyvista_mesh, pv.UnstructuredGrid) check would be reliable across all PyVista versions.
  • The test_polydata_3d_no_celltypes_raises test depends on the same fragile assumption and will fail on modern PyVista installations where the guard is not triggered.
  • New TestFromPyvistaPolyhedra tests are comprehensive, covering auto-detection, explicit dim, point-data preservation, mixed hex+polyhedra meshes, and rigorous geometric-invariant checks (volume, surface area, bounding box, manifold watertightness, per-face area decomposition).

Important Files Changed

Filename Overview
physicsnemo/mesh/io/io_pyvista.py Replaces cells_dict-based cell counting with celltypes array to handle VTK_POLYHEDRON cells; switches from tessellate() to triangulate() for tetrahedralization. Core logic is sound, but the guard hasattr(…, "celltypes") is not reliable for distinguishing PolyData from UnstructuredGrid in modern PyVista.
test/mesh/io/io_pyvista/test_error_handling.py Updated error-handling test to match new error message; the assumption that pv.PolyData lacks celltypes is incorrect for modern PyVista (≥ 0.43), which may cause test_polydata_3d_no_celltypes_raises to fail.
test/mesh/io/io_pyvista/test_from_pyvista_3d.py Comprehensive new test suite for VTK_POLYHEDRON cells, including geometric-invariant checks (volume, surface area, bounding box, manifold property) and per-face area decomposition verification. Tests are well-structured and cover realistic CFD mixed-cell scenarios.

Last reviewed commit: a2d8cdb

@peterdsharpe peterdsharpe changed the title PhysicsNeMo-Mesh: Properly handles Polyhedra triangulation in PyVista/VTU I/O PhysicsNeMo-Mesh: Adds new capability of Polyhedra triangulation in PyVista/VTU I/O Mar 4, 2026
…or 3D meshes, improving error handling and clarity in mesh validation.
- Implemented `to_edge_graph`, `to_dual_graph`, and `to_point_cloud` methods to facilitate the extraction of edge graphs, dual graphs, and point clouds from the Mesh class.
- Each method includes detailed docstrings with examples for better usability.
- Added comprehensive unit tests to validate the functionality of the new methods, ensuring correct edge and dual graph generation from various mesh configurations.
…e dimension detection

- Updated the logic for passing cell data to ensure compatibility with varying manifold dimensions and native mesh dimensions.
- Improved the detection of native dimensions by adding checks for line types, enhancing the robustness of the function.
- Clarified comments to better explain the conditions under which cell data can be passed through.
- Introduced a new `force_copy` parameter to control whether point and cell arrays are copied, allowing the returned Mesh to own its memory independently of the source PyVista mesh.
- Updated documentation to clarify the implications of this parameter on memory sharing and data mutation.
- Enhanced the logic for determining manifold dimensions and improved error handling for ambiguous mesh types.
@coreyjadams
Copy link
Collaborator

Hey @peterdsharpe - What are you thinking to do with this? I wasn't able to test successfully on the high lift dataset because, as you know, it timed out with 100M + polyhedra 😬 . It seems like a really nice path to go down though, maybe there is a way to implement these polyhedra -> simplex conversion we can vectorize and actually finish before the heat death of the universe?

@peterdsharpe
Copy link
Collaborator Author

Yeah, upon further testing with the high lift aero dataset (192 million polyhedra cells per VTU mesh), this is probably still not scalable :( However, hopefully this will still be useful for others processing more-typical smaller meshes (a few million cells?).

Moreover, this PR also provides a few other features, beyond just polyhedra I/O handling:

  • It allows you to import VTK meshes as pure point clouds, if you don't care about connectivity information. This point cloud info can come from either mesh vertices or mesh cell centroids.
  • It also allows you to convert Meshes to these point clouds, via Mesh.to_point_cloud(). You can also convert to graphs with Mesh.to_edge_graph() and Mesh.to_dual_graph(). Both of these offer opportunities for simplifications in cases where actual cell geometry is unimportant.

…vista.py

- Updated matplotlib to version 3.10.8 and pyvista to version 0.47.0 in the mesh-extras section of pyproject.toml.
- Added vtk version requirement to the _build_dual_graph_edges function in io_pyvista.py, improving module import handling with importlib for better compatibility.
@peterdsharpe peterdsharpe requested a review from ktangsali as a code owner March 5, 2026 20:09
- Enhanced test classes for edge graph, dual graph, and point cloud extraction with comprehensive docstrings explaining their functionality and verification processes.
- Improved clarity on the expected behavior and data handling in the tests for better maintainability and understanding.
@peterdsharpe peterdsharpe enabled auto-merge March 6, 2026 00:56
@peterdsharpe
Copy link
Collaborator Author

/blossom-ci

Copy link
Collaborator

@coreyjadams coreyjadams left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am using this in production so it seems to be working!

LGTM

@peterdsharpe peterdsharpe disabled auto-merge March 6, 2026 18:42
@peterdsharpe
Copy link
Collaborator Author

/blossom-ci

@peterdsharpe peterdsharpe enabled auto-merge March 6, 2026 20:15
@peterdsharpe peterdsharpe disabled auto-merge March 9, 2026 16:19
Copy link
Collaborator

@ktangsali ktangsali left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving the changes to the TOML and lock file.

@peterdsharpe
Copy link
Collaborator Author

/blossom-ci

@peterdsharpe
Copy link
Collaborator Author

/blossom-ci

@peterdsharpe peterdsharpe enabled auto-merge March 9, 2026 21:29
…ell, and global data. This change ensures compatibility with PyVista DataSetAttributes by converting them to plain dictionaries before assignment.
@peterdsharpe
Copy link
Collaborator Author

/blossom-ci

@peterdsharpe peterdsharpe added this pull request to the merge queue Mar 9, 2026
Merged via the queue into NVIDIA:main with commit 71ce949 Mar 9, 2026
4 checks passed
@peterdsharpe peterdsharpe deleted the psharpe/add-mesh-polyhedra-conversion branch March 10, 2026 14:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants