Skip to content

Adds parametric type system for PhysicsNeMo-Mesh#1500

Merged
peterdsharpe merged 9 commits intoNVIDIA:mainfrom
peterdsharpe:psharpe/add-mesh-typing
Mar 15, 2026
Merged

Adds parametric type system for PhysicsNeMo-Mesh#1500
peterdsharpe merged 9 commits intoNVIDIA:mainfrom
peterdsharpe:psharpe/add-mesh-typing

Conversation

@peterdsharpe
Copy link
Collaborator

@peterdsharpe peterdsharpe commented Mar 14, 2026

Parametric type hints for Mesh

Adds subscript syntax to Mesh so that Mesh[2, 3] denotes a 2-dimensional manifold embedded in 3-dimensional space. This enables dimension-aware type annotations and runtime isinstance checks with no changes to Mesh's data model or serialization.

Subscript syntax

Mesh[m, s] always takes exactly two parameters. Use ... (Ellipsis) for an unconstrained dimension. Concrete integer dimensions are validated at spec-creation time (non-negative, manifold <= spatial). Symbolic string labels like "n-1" are parsed and, when both dimensions share a variable, the implied codimension is validated at isinstance time.

Mesh[2, 3]          # 2d manifold in 3d space
Mesh[1, ...]        # 1d manifold in any space
Mesh[..., 3]        # any manifold in 3d space
Mesh["n-1", "n"]    # codimension-1 manifold

isinstance(mesh, Mesh[2, 3])   # True for a triangle mesh in 3D
Mesh[2, 3].boundary            # -> Mesh[1, 3]
Mesh[2, 3] is Mesh[2, 3]       # True (cached)

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.

- Introduced `MeshDims` class for dimension-aware type hints in the `Mesh` class.
- Implemented `__class_getitem__` method in `Mesh` to support subscript syntax for specifying manifold and spatial dimensions.
- Added convenience aliases: `PointCloud` for 0-manifold and `Graph` for 1-manifold.
- Updated mesh representation formatting to include dimension information.
- Added comprehensive tests for the new functionality, including validation of dimension constraints and type checks.
@peterdsharpe peterdsharpe changed the title Adds type system for PhysicsNeMo-Mesh Adds parametric type system for PhysicsNeMo-Mesh Mar 14, 2026
@peterdsharpe peterdsharpe marked this pull request as ready for review March 14, 2026 03:09
- Updated the conditional check for string types in the MeshDims class to enhance code clarity by formatting the line breaks.
- Removed string type assertions for manifold and spatial dimensions in the MeshDims class.
- Updated dimension parsing to include type ignore comments for better compatibility with type checkers.
@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 14, 2026

Greptile Summary

This PR adds a parametric type system for PhysicsNeMo-Mesh, enabling Mesh[m, s] subscript syntax for dimension-aware type annotations and runtime isinstance checks. The implementation is well-structured: a new _mesh_spec.py module contains the frozen MeshDims dataclass, a _MeshSpecMeta metaclass that hooks __instancecheck__, and a module-level identity-preserving cache (Mesh[2, 3] is Mesh[2, 3]). The Mesh class gains __class_getitem__, two convenience aliases (PointCloud, Graph) are added to __init__.py, and the repr format is updated from Mesh(manifold_dim=m, spatial_dim=s, ...) to Mesh[m, s](...).

Key items to be aware of:

  • Note on repr breaking change: The updated repr format (Mesh[2, 3](...) vs. the previous Mesh(manifold_dim=2, spatial_dim=3, ...)) is a user-visible breaking change for any downstream code that parses or pattern-matches against the repr string. The test suite is updated accordingly, but this should be called out in the changelog/release notes.
  • Logic concern in matches(): When a symbolic string dimension is paired with an unconstrained (None) dimension — e.g. Mesh["n-1", ...] — the symbolic constraint is silently never evaluated and the spec matches all meshes. The PR's design intentionally restricts symbolic codimension checks to cases where both dimensions share a variable, but this "no-op" case is not tested and may confuse users.
  • Minor performance: _parse_dim_expr re-runs the regex on every isinstance call inside _check_symbolic_constraint, despite the expressions being immutable after MeshDims construction. Pre-computing the (variable, offset) pairs in __post_init__ would avoid redundant work.

Important Files Changed

Filename Overview
physicsnemo/mesh/_mesh_spec.py New core module implementing the parametric type system. Contains MeshDims dataclass, _MeshSpecMeta metaclass, and the cached factory. Two logic concerns: (1) symbolic constraints are silently dropped when only one dimension is a string, making Mesh["n-1", ...] match all meshes with no warning; (2) _parse_dim_expr is called on every isinstance check despite immutable inputs.
physicsnemo/mesh/mesh.py Adds class_getitem classmethod to enable Mesh[m, s] syntax. Implementation correctly validates param count and type before delegating to _get_mesh_spec. No issues found.
test/mesh/test_mesh_spec.py Comprehensive test suite for the new parametric type system, covering isinstance checks, caching, symbolic constraints, boundary derived types, and MeshDims dataclass. Missing a test for the Mesh["n-1", ...] (symbolic + unconstrained) edge case which always matches all meshes.

Last reviewed commit: 32c1b63

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 don't have any particular objection to this though I kind of liked the old way better. It was more explicit: you are used to writing this every day and remember if the manifold dimension or spatial dimension is first but the rest of us don't. I liked using the keywords.

Is this just for representations? Or is this driving type checking and match cases too?

- Improved error handling for symbolic dimensions in the MeshDims class by adding checks to ensure paired dimensions are provided.
- Updated parsing logic to cache results for symbolic dimensions, enhancing performance and clarity.
- Added new tests to validate the behavior of symbolic dimensions and ensure proper error messages are raised when constraints are not met.
@peterdsharpe
Copy link
Collaborator Author

/blossom-ci

@peterdsharpe peterdsharpe enabled auto-merge March 14, 2026 14:35
@peterdsharpe peterdsharpe disabled auto-merge March 14, 2026 14:42
@peterdsharpe
Copy link
Collaborator Author

peterdsharpe commented Mar 14, 2026

Thanks for the speedy review @coreyjadams ! :)

Re:

I kind of liked the old way better. It was more explicit: you are used to writing this every day and remember if the manifold dimension or spatial dimension is first but the rest of us don't. I liked using the keywords.

So, the nice thing here is that it's actually unambiguous, since n_manifold_dims <= n_spatial_dims, always. So, even if you don't remember the order:

  • Mesh[2, 3] must be a 2d manifold embedded in 3d space. (Since a 3d manifold cannot be embedded in 2d space.)
  • Mesh[3, 3] is also unambiguous, since both the manifold dim and the spatial dim are the same.

This ordering also matches how mathematicians discuss these: "Let M be a 2d manifold in 3d space" -> "Mesh[2, 3]".

My feeling is that the conciseness (at least in terms of type signatures) is a nice win here, especially as we start doing more complicated Mesh ops (e.g., bundling a surface mesh and a volume mesh together, so we can manipulate them as one).

That said, I can see how having it be more explicit in the repr might be more readable for new users, and in printouts. I'll make it so that the repr defaults to the older style (Mesh[n_manifold_dims=2, n_spatial_dims=3]), while still allowing for Mesh[2, 3] in type signatures.

…on information

- Modified the string representation of the Mesh class to specify manifold and spatial dimensions explicitly.
- Updated related test cases to reflect the new format in expected outputs, ensuring consistency across representations.
@peterdsharpe peterdsharpe enabled auto-merge March 14, 2026 16:15
…n representation

- Modified the assertion in the test case to check for the updated string format that includes explicit manifold and spatial dimensions.
- Ensured consistency with recent changes in the Mesh class representation.
@peterdsharpe
Copy link
Collaborator Author

/blossom-ci

@NickGeneva
Copy link
Collaborator

/blossom-ci

1 similar comment
@NickGeneva
Copy link
Collaborator

/blossom-ci

@peterdsharpe peterdsharpe added this pull request to the merge queue Mar 15, 2026
Merged via the queue into NVIDIA:main with commit 1759678 Mar 15, 2026
4 checks passed
@peterdsharpe peterdsharpe deleted the psharpe/add-mesh-typing branch March 15, 2026 18:00
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