Transformations and Projections#

Geometric Transformations#

Linear and affine transformations on mesh geometry. Each function returns a new Mesh with transformed point coordinates and appropriately invalidated caches. (Any cached quantities, such as normals and areas, are automatically recomputed on next access.)

All transformations are also available as methods on Mesh.

import numpy as np
from physicsnemo.mesh.primitives.surfaces import sphere_icosahedral

mesh = sphere_icosahedral.load(subdivisions=2)

# Via Mesh methods
translated = mesh.translate([1.0, 0.0, 0.0])
rotated = mesh.rotate(axis=[0, 0, 1], angle=np.pi / 4)
scaled = mesh.scale(2.0)
scaled_aniso = mesh.scale([2.0, 1.0, 0.5])

# Arbitrary linear transform
import torch
matrix = torch.eye(3) * 2
transformed = mesh.transform(matrix)

Geometric transformations for simplicial meshes.

This module implements linear and affine transformations with intelligent cache handling. By default, all caches are invalidated; transformations explicitly opt-in to preserve/transform specific cache fields.

Cached fields handled: - areas: point_data and cell_data - normals: point_data and cell_data - centroids: cell_data only

physicsnemo.mesh.transformations.geometric.rotate(
mesh: Mesh,
angle: float,
axis: Float[Tensor, 'n_spatial_dims'] | Sequence[float] | Literal['x', 'y', 'z'] | None = None,
center: Float[Tensor, 'n_spatial_dims'] | Sequence[float] | None = None,
transform_point_data: bool | TensorDict = False,
transform_cell_data: bool | TensorDict = False,
transform_global_data: bool | TensorDict = False,
) Mesh[source]#

Rotate the mesh about an axis by a specified angle.

Parameters:
  • mesh (Mesh) – Input mesh to rotate.

  • angle (float) – Rotation angle in radians (counterclockwise, right-hand rule).

  • axis (Float[torch.Tensor, " n_spatial_dims"] or Sequence[float] or {"x", "y", "z"} or None) – Rotation axis vector. None for 2D, shape \((3,)\) for 3D. String literals "x", "y", "z" are converted to unit vectors (1,0,0), (0,1,0), (0,0,1) respectively.

  • center (Float[torch.Tensor, " n_spatial_dims"] or Sequence[float] or None) – Center point for rotation. If None, rotates about the origin.

  • transform_point_data (bool or TensorDict) – Controls transformation of point_data fields. See transform() for full semantics.

  • transform_cell_data (bool or TensorDict) – Same semantics as transform_point_data, for cell_data.

  • transform_global_data (bool or TensorDict) – Same semantics as transform_point_data, for global_data.

Returns:

New Mesh with rotated geometry.

Return type:

Mesh

Notes

Cache Handling:

  • areas: Unchanged (rotation preserves volumes)

  • centroids: Rotated

  • normals: Rotated

physicsnemo.mesh.transformations.geometric.rotation_matrix(
angle: float,
axis: Float[Tensor, 'n_spatial_dims'] | Sequence[float] | Literal['x', 'y', 'z'] | None,
n_spatial_dims: int,
device: device,
dtype: dtype,
) Float[Tensor, 'n_spatial_dims n_spatial_dims'][source]#

Build a rotation matrix from angle and axis.

Parameters:
  • angle (float) – Rotation angle in radians (counterclockwise, right-hand rule).

  • axis (Float[torch.Tensor, " n_spatial_dims"] or Sequence[float] or {"x", "y", "z"} or None) – Rotation axis. None for 2D, tensor/sequence/string for 3D.

  • n_spatial_dims (int) – Number of spatial dimensions.

  • device (torch.device) – Target device for the output matrix.

  • dtype (torch.dtype) – Target dtype for the output matrix.

Returns:

Rotation matrix, shape \((S, S)\).

Return type:

Float[torch.Tensor, “n_spatial_dims n_spatial_dims”]

physicsnemo.mesh.transformations.geometric.scale(
mesh: Mesh,
factor: float | Float[Tensor, 'n_spatial_dims'] | Sequence[float],
center: Float[Tensor, 'n_spatial_dims'] | Sequence[float] | None = None,
transform_point_data: bool | TensorDict = False,
transform_cell_data: bool | TensorDict = False,
transform_global_data: bool | TensorDict = False,
assume_invertible: bool | None = None,
) Mesh[source]#

Scale the mesh by specified factor(s).

Parameters:
  • mesh (Mesh) – Input mesh to scale.

  • factor (float or Float[torch.Tensor, " n_spatial_dims"] or Sequence[float]) – Scale factor(s). Scalar for uniform, vector for non-uniform.

  • center (Float[torch.Tensor, " n_spatial_dims"] or Sequence[float] or None) – Center point for scaling. If None, scales about the origin.

  • transform_point_data (bool or TensorDict) – Controls transformation of point_data fields. See transform() for full semantics.

  • transform_cell_data (bool or TensorDict) – Same semantics as transform_point_data, for cell_data.

  • transform_global_data (bool or TensorDict) – Same semantics as transform_point_data, for global_data.

  • assume_invertible (bool or None) –

    Controls cache propagation:

    • True: Assume all factors are non-zero, propagate caches (compile-safe)

    • False: Assume some factor is zero, skip cache propagation (compile-safe)

    • None: Check determinant at runtime (may cause graph breaks under torch.compile)

Returns:

New Mesh with scaled geometry.

Return type:

Mesh

Notes

Cache Handling:

  • areas: Scaled correctly. For non-isotropic transforms of codimension-1

    embedded manifolds, per-element scaling is computed using normals.

  • centroids: Scaled

  • normals: Transformed by inverse-transpose (direction adjusted, magnitude normalized)

physicsnemo.mesh.transformations.geometric.scale_matrix(
factor: float | Float[Tensor, 'n_spatial_dims'] | Sequence[float],
n_spatial_dims: int,
device: device,
dtype: dtype,
) Float[Tensor, 'n_spatial_dims n_spatial_dims'][source]#

Build a diagonal scale matrix from a factor specification.

Parameters:
  • factor (float or Float[torch.Tensor, " n_spatial_dims"] or Sequence[float]) – Scale factor(s). Scalar for uniform, vector for non-uniform.

  • n_spatial_dims (int) – Number of spatial dimensions.

  • device (torch.device) – Target device for the output matrix.

  • dtype (torch.dtype) – Target dtype for the output matrix.

Returns:

Diagonal scale matrix, shape \((S, S)\).

Return type:

Float[torch.Tensor, “n_spatial_dims n_spatial_dims”]

Raises:

ValueError – If factor is a vector whose length does not match n_spatial_dims.

physicsnemo.mesh.transformations.geometric.transform(
mesh: Mesh,
matrix: Float[Tensor, 'new_n_spatial_dims n_spatial_dims'],
transform_point_data: bool | TensorDict = False,
transform_cell_data: bool | TensorDict = False,
transform_global_data: bool | TensorDict = False,
assume_invertible: bool | None = None,
) Mesh[source]#

Apply a linear transformation to the mesh.

Parameters:
  • mesh (Mesh) – Input mesh to transform.

  • matrix (Float[torch.Tensor, "new_n_spatial_dims n_spatial_dims"]) – Transformation matrix, shape \((S', S)\).

  • transform_point_data (bool or TensorDict) – Controls transformation of point_data fields. True transforms all compatible fields; False transforms none; a TensorDict (or dict) with scalar bool leaves selectively transforms only the named fields.

  • transform_cell_data (bool or TensorDict) – Same semantics as transform_point_data, for cell_data.

  • transform_global_data (bool or TensorDict) – Same semantics as transform_point_data, for global_data.

  • assume_invertible (bool or None) –

    Controls cache propagation for square matrices:

    • True: Assume matrix is invertible, propagate caches (compile-safe)

    • False: Assume matrix is singular, skip cache propagation (compile-safe)

    • None: Check determinant at runtime (may cause graph breaks under torch.compile)

Returns:

New Mesh with transformed geometry and appropriately updated caches.

Return type:

Mesh

Notes

Cache Handling:

  • areas: For square invertible matrices:

    • Full-dimensional meshes: scaled by |det|

    • Codimension-1 manifolds: per-element scaling using |det| * ||M^{-T} n||

    • Higher codimension: invalidated

  • centroids: Always transformed

  • normals: For square invertible matrices, transformed by inverse-transpose

physicsnemo.mesh.transformations.geometric.translate(
mesh: Mesh,
offset: Float[Tensor, 'n_spatial_dims'] | Sequence[float],
) Mesh[source]#

Apply a translation to the mesh.

Translation only affects point positions and centroids. Vector/tensor fields are unchanged by translation (they represent directions, not positions).

Parameters:
  • mesh (Mesh) – Input mesh to translate.

  • offset (Float[torch.Tensor, " n_spatial_dims"] or Sequence[float]) – Translation vector, shape \((S,)\).

Returns:

New Mesh with translated geometry.

Return type:

Mesh

Notes

Cache Handling:

  • areas: Unchanged

  • centroids: Translated

  • normals: Unchanged

Projections#

Spatial dimension manipulation – changing the embedding dimension of a mesh without altering its manifold dimension.

  • embed() – add spatial dimensions (non-destructive; for example, 2D mesh to 3D by appending zero coordinates)

  • extrude() – sweep a manifold to create a mesh one dimension higher (for example, a triangle mesh extruded to a prism mesh)

  • project() – reduce spatial dimensions (lossy; drops coordinate axes)

Projection operations for mesh extrusion, embedding, and spatial dimension manipulation.

This module provides functionality for: - Embedding meshes in higher-dimensional spaces (non-destructive) - Projecting meshes to lower-dimensional spaces (lossy) - Extruding manifolds to higher dimensions