Skip to content

PhysicsNeMo-Mesh: adds DomainMesh for combined manipulation of volume + surface meshes.#1504

Merged
peterdsharpe merged 37 commits intoNVIDIA:mainfrom
peterdsharpe:psharpe/add-domain-mesh
Mar 19, 2026
Merged

PhysicsNeMo-Mesh: adds DomainMesh for combined manipulation of volume + surface meshes.#1504
peterdsharpe merged 37 commits intoNVIDIA:mainfrom
peterdsharpe:psharpe/add-domain-mesh

Conversation

@peterdsharpe
Copy link
Collaborator

PhysicsNeMo Pull Request

Description

This is a proposal for a multi-mesh, which stores volume and surface data together (e.g., what you'd get from a single CFD simulation) and allows for easy manipulation of them together.

DomainMesh is a tensorclass that groups an interior Mesh with zero or more named boundary Mesh objects and optional domain-level metadata (global_data). The interior and boundary meshes can have any combination of manifold dimensions (volumetric, surface, graph, point cloud); the only structural invariant enforced at construction is that all meshes share the same spatial embedding dimension. Dimensional constraints on individual meshes can be checked via Mesh's own parametric types (e.g., isinstance(dm.interior, Mesh[3, 3])).

All Mesh operations that make sense at the domain level are exposed as passthrough methods via a private _map_meshes helper that applies a Mesh -> Mesh function to the interior and every boundary using TensorDict.apply(fn, call_on_nested=True), preserving global_data unchanged. This includes geometric transforms (translate, rotate, scale, transform), cleanup and refinement (clean, strip_caches, subdivide), data conversion (cell_data_to_point_data, point_data_to_cell_data), and calculus (compute_point_derivatives, compute_cell_derivatives). A validate method aggregates per-mesh validation reports into a single domain-level result. All methods return DomainMesh and support fluent chaining (e.g., dm.translate([1, 0, 0]).scale(2.0).clean()).

Note: this is a stacked PR on top of:

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.

…emoved unnecessary comments, added checks for non-empty data fields, and ensured proper alignment in the output. This enhances readability and maintains consistency in the mesh representation output.
- 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.
- 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.
- 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.
…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.
…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.
- Simplified the default cache structure initialization and updated the caching logic to overlay provided caches.
- Introduced a new method `_cached_adjacency` to streamline adjacency retrieval and caching.
- Enhanced documentation for adjacency methods to clarify caching behavior and efficiency.
- Added comprehensive tests to validate caching functionality and ensure correctness across various adjacency computations.
- Included the 'topology' in the output of the transform and translate functions to improve data handling.
- Updated adjacency tests to assert that offsets remain consistent after transformations, ensuring integrity of adjacency data across operations.
- Removed unnecessary device specification in TensorDict initialization for 'cell' and 'point' caches in the transform and translate functions, simplifying the code and improving readability.
- Introduced parametric dimension syntax via `DomainMesh[m, s]`, allowing for dimension-aware type annotations and runtime `isinstance` checks.
- Enhanced validation to ensure boundary meshes conform to the expected manifold dimensions.
- Added comprehensive tests for the new syntax and validation rules, ensuring correct behavior and caching of parametrized types.
- Updated the DomainMesh class to remove the shadow parameter from the tensorclass decorator.
- Enhanced type annotations for the interior and boundaries attributes to specify parametric dimensions, improving type safety and clarity in the codebase.
- Introduced methods for translating, rotating, scaling, and applying linear transformations to all meshes within a DomainMesh.
- Implemented a private helper method `_map_meshes` to apply transformations to both interior and boundary meshes while preserving global data.
- Added comprehensive tests to validate the functionality of the new transformation methods, ensuring correct behavior across various scenarios.
@peterdsharpe peterdsharpe added the 5 - Merge After Dependencies Depends on another PR: do not merge out of order label Mar 14, 2026
@coreyjadams coreyjadams mentioned this pull request Mar 17, 2026
6 tasks
@peterdsharpe peterdsharpe marked this pull request as ready for review March 17, 2026 17:57
@peterdsharpe peterdsharpe self-assigned this Mar 17, 2026
@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 17, 2026

Greptile Summary

This PR introduces DomainMesh, a tensorclass that groups an interior Mesh with zero or more named boundary Mesh objects and optional domain-level metadata (global_data), along with a suite of passthrough transform, cleanup, data-conversion, and validation methods. The design is clean, well-documented, and integrates naturally with the existing Mesh/TensorDict infrastructure.

Key observations:

  • Shared global_data reference in _map_meshes: Every transform method calls _map_meshes, which forwards global_data=self.global_data without cloning. Because __post_init__ only mutates batch_size (a no-op on an already-normalised TensorDict), both the original and the transformed DomainMesh end up pointing at the same TensorDict. An in-place write on the result (e.g. dm2.global_data["Re"].fill_(0.0)) silently propagates back to the source. A self.global_data.clone() in _map_meshes would decouple the two instances.
  • n_boundaries materialises an unnecessary list: len(list(self.boundaries.keys())) can be simplified to len(self.boundaries).
  • Missing test coverage: compute_point_derivatives and compute_cell_derivatives are the only passthrough methods not exercised by the new test file.
  • mesh_repr.py improvement: Skipping empty data fields makes the repr cleaner; the change is correct.

Important Files Changed

Filename Overview
physicsnemo/mesh/domain_mesh.py New DomainMesh tensorclass grouping an interior Mesh with named boundary Mesh objects and optional global_data. Well-structured with thorough docstrings. Minor issue: global_data is passed by reference in _map_meshes, so transformed instances share the same TensorDict object, enabling unintended cross-instance in-place mutations. Also, n_boundaries materialises an unnecessary list.
test/mesh/test_domain_mesh_transforms.py Comprehensive test suite covering geometric transforms, cleanup/refinement, data operations, validation, and fluent chaining. Missing test coverage for compute_point_derivatives and compute_cell_derivatives.
physicsnemo/mesh/utilities/mesh_repr.py Small improvement to format_mesh_repr: empty data fields (point_data, cell_data, global_data) are now skipped, making the representation cleaner for sparse meshes. Change is correct and well-implemented.
physicsnemo/mesh/init.py Adds DomainMesh to the public physicsnemo.mesh namespace. Straightforward, no issues.

Last reviewed commit: db2e28d

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
@peterdsharpe peterdsharpe removed the 5 - Merge After Dependencies Depends on another PR: do not merge out of order label Mar 17, 2026
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.

Looking great! Overall, I think this is awesome functionality and we should move forward. It's really valuable for the CAE effort but it's going to be useful beyond that as well. I left some comments; I really have just one that I consider an "issue" and that is this: I think we discussed the possibility to encode things like global vectors (inlet velocity, for example) with a DomainMesh, that would transform with the DomainMesh. As implemented I think those would fall through the cracks - am I missing something?

I also made some comments about meta data but we can keep that as a conversation going on the design, rather than something to resolve before merge.

- Updated the `rotate`, `scale`, and `transform` methods in `DomainMesh` to apply transformations to the domain-level `global_data` in addition to individual mesh data.
- Refactored the transformation logic to ensure proper handling of global data during geometric transformations.
- Improved type annotations in `geometric.py` for better clarity and compliance with typing standards.
@peterdsharpe peterdsharpe changed the title [stacked] [prototype] PhysicsNeMo-Mesh: adds DomainMesh for combined manipulation of volume + surface meshes. PhysicsNeMo-Mesh: adds DomainMesh for combined manipulation of volume + surface meshes. Mar 18, 2026
…line expected output formatting. Adjusted expected strings to reflect changes in representation, ensuring clarity in test assertions.
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.

Thanks for making the updates to the global data tensors and aligning the apis with Mesh. I think this is good to go!

@peterdsharpe
Copy link
Collaborator Author

/blossom-ci

@peterdsharpe peterdsharpe enabled auto-merge March 18, 2026 20:14
@peterdsharpe
Copy link
Collaborator Author

/blossom-ci

@peterdsharpe peterdsharpe added this pull request to the merge queue Mar 19, 2026
Merged via the queue into NVIDIA:main with commit 16d5fda Mar 19, 2026
4 checks passed
@peterdsharpe peterdsharpe deleted the psharpe/add-domain-mesh branch March 19, 2026 12:53
coreyjadams pushed a commit to coreyjadams/physicsnemo that referenced this pull request Mar 19, 2026
…me + surface meshes. (NVIDIA#1504)

* Adds WIP domain_mesh changes

* Refactor mesh_repr.py to improve formatting of mesh representation. Removed unnecessary comments, added checks for non-empty data fields, and ensured proper alignment in the output. This enhances readability and maintains consistency in the mesh representation output.

* Add parametric mesh type specifications and convenience aliases

- 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.

* Refactor conditional check in MeshDims class for improved readability

- Updated the conditional check for string types in the MeshDims class to enhance code clarity by formatting the line breaks.

* Refactor dimension parsing in MeshDims class to ignore type checks

- 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.

* Minor review fixes

* Enhance dimension validation in MeshDims class

- 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.

* Updates all primitives to have as-narrow type returns as possible

* formatting fix

* Update mesh representation and test cases to include detailed dimension 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.

* Update test for Mesh class serialization to reflect detailed dimension 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.

* Strips out tons of needless batch_size=[]

* propagate caches

* Refactor caching mechanism in Mesh class for adjacency computations

- Simplified the default cache structure initialization and updated the caching logic to overlay provided caches.
- Introduced a new method `_cached_adjacency` to streamline adjacency retrieval and caching.
- Enhanced documentation for adjacency methods to clarify caching behavior and efficiency.
- Added comprehensive tests to validate caching functionality and ensure correctness across various adjacency computations.

* Add topology to transformation outputs and enhance adjacency tests

- Included the 'topology' in the output of the transform and translate functions to improve data handling.
- Updated adjacency tests to assert that offsets remain consistent after transformations, ensuring integrity of adjacency data across operations.

* changelog update

* Refactor TensorDict initialization in geometric transformations

- Removed unnecessary device specification in TensorDict initialization for 'cell' and 'point' caches in the transform and translate functions, simplifying the code and improving readability.

* formatting

* Add parametric dimension support to DomainMesh

- Introduced parametric dimension syntax via `DomainMesh[m, s]`, allowing for dimension-aware type annotations and runtime `isinstance` checks.
- Enhanced validation to ensure boundary meshes conform to the expected manifold dimensions.
- Added comprehensive tests for the new syntax and validation rules, ensuring correct behavior and caching of parametrized types.

* Refactor DomainMesh type annotations for clarity

- Updated the DomainMesh class to remove the shadow parameter from the tensorclass decorator.
- Enhanced type annotations for the interior and boundaries attributes to specify parametric dimensions, improving type safety and clarity in the codebase.

* Add geometric transformation methods to DomainMesh

- Introduced methods for translating, rotating, scaling, and applying linear transformations to all meshes within a DomainMesh.
- Implemented a private helper method `_map_meshes` to apply transformations to both interior and boundary meshes while preserving global data.
- Added comprehensive tests to validate the functionality of the new transformation methods, ensuring correct behavior across various scenarios.

* Removes explicit dims

* strips the class getitem, which didn't work due to variable manifold dimensionality

* formatting

* Update physicsnemo/mesh/domain_mesh.py

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* adds docstrings

* Fixes clone

* Adds iter

* Adds tests

* Enhance DomainMesh transformations to include global data manipulation

- Updated the `rotate`, `scale`, and `transform` methods in `DomainMesh` to apply transformations to the domain-level `global_data` in addition to individual mesh data.
- Refactored the transformation logic to ensure proper handling of global data during geometric transformations.
- Improved type annotations in `geometric.py` for better clarity and compliance with typing standards.

* formatting

* Refactor repr tests in Mesh to remove unnecessary comments and streamline expected output formatting. Adjusted expected strings to reflect changes in representation, ensuring clarity in test assertions.

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
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.

2 participants