diff --git a/docs/Unstructured.ipynb b/docs/Unstructured.ipynb index 932db9695..3d788e9ef 100644 --- a/docs/Unstructured.ipynb +++ b/docs/Unstructured.ipynb @@ -6,7 +6,7 @@ "# Unstructured Meshes\n", "\n", "The popular finite volumes and finite elements methods can operate on unstructured meshes, i.e. grids whose cells can have arbitrary numbers of faces.\n", - "Since version 2.5, ΦFlow supports unstructured meshes via the `geom.UnstructuredMesh` class.\n", + "Since version 2.5, ΦFlow supports unstructured meshes via the `geom.Mesh` class.\n", "Tensor operations for unstructured meshes are executed using sparse matrices and are fully GPU-supported." ], "metadata": { diff --git a/phi/field/_field.py b/phi/field/_field.py index e3c5b366d..2ecf949ef 100644 --- a/phi/field/_field.py +++ b/phi/field/_field.py @@ -3,7 +3,7 @@ from typing import Callable, Union, Tuple from phi import math -from phi.geom import Geometry, Box, Point, BaseBox, UniformGrid, UnstructuredMesh, Sphere +from phi.geom import Geometry, Box, Point, BaseBox, UniformGrid, Mesh, Sphere from phi.geom._geom import slice_off_constant_faces from phi.math import Shape, Tensor, channel, non_batch, expand, instance, spatial, wrap, dual, non_dual from phi.math.extrapolation import Extrapolation @@ -69,8 +69,8 @@ def geometry(self) -> Geometry: return self._geometry @property - def mesh(self) -> UnstructuredMesh: - assert isinstance(self._geometry, UnstructuredMesh), f"Geometry is not a mesh but {type(self._geometry)}" + def mesh(self) -> Mesh: + assert isinstance(self._geometry, Mesh), f"Geometry is not a mesh but {type(self._geometry)}" return self._geometry @property @@ -219,11 +219,11 @@ def is_grid(self): @property def is_mesh(self): - return isinstance(self._geometry, UnstructuredMesh) + return isinstance(self._geometry, Mesh) @property def is_point_cloud(self): - if isinstance(self._geometry, (UniformGrid, UnstructuredMesh)): + if isinstance(self._geometry, (UniformGrid, Mesh)): return False if isinstance(self._geometry, (BaseBox, Sphere, Point)): return True @@ -236,7 +236,7 @@ def dx(self) -> Tensor: @property def cells(self): - assert isinstance(self._geometry, (UniformGrid, UnstructuredMesh)) + assert isinstance(self._geometry, (UniformGrid, Mesh)) return self._geometry def at_centers(self, **kwargs) -> 'Field': diff --git a/phi/field/_resample.py b/phi/field/_resample.py index 6b709720f..0927e31c6 100644 --- a/phi/field/_resample.py +++ b/phi/field/_resample.py @@ -2,7 +2,7 @@ from typing import Union, List, Callable, Optional from phi import math -from phi.geom import Geometry, Box, Point, UniformGrid, UnstructuredMesh +from phi.geom import Geometry, Box, Point, UniformGrid, Mesh from phi.math import Shape, Tensor, instance, spatial, Solve, dual, si2d from phi.math.extrapolation import Extrapolation, ConstantExtrapolation, PERIODIC from phiml.math import unstack, channel, rename_dims, batch diff --git a/phi/geom/__init__.py b/phi/geom/__init__.py index 41b3e59c6..a24206ec6 100644 --- a/phi/geom/__init__.py +++ b/phi/geom/__init__.py @@ -15,7 +15,7 @@ from ._box import Box, BaseBox, Cuboid from ._sphere import Sphere from ._grid import UniformGrid -from ._mesh import UnstructuredMesh, load_su2, mesh_from_numpy +from ._mesh import Mesh, load_su2, mesh_from_numpy from ._transform import embed, infinite_cylinder from ._heightmap import Heightmap from ._geom_ops import union diff --git a/phi/geom/_mesh.py b/phi/geom/_mesh.py index 3b8cbc7ad..805431c39 100644 --- a/phi/geom/_mesh.py +++ b/phi/geom/_mesh.py @@ -21,7 +21,7 @@ class Face: # """Distance to primary (non-dual) cell between 0 and 1""" -class UnstructuredMesh(Geometry): +class Mesh(Geometry): def __init__(self, vertices: Tensor, polygons: Tensor, @@ -252,16 +252,16 @@ def __hash__(self): return hash((self._vertices, self._polygons)) def __getitem__(self, item): - assert 'vertices' not in item, "Cannot slice UnstructuredMesh along 'vertices'" - assert 'vertex_index' not in item, "Cannot slice UnstructuredMesh along 'vertex_index'" + assert 'vertices' not in item, "Cannot slice Mesh along 'vertices'" + assert 'vertex_index' not in item, "Cannot slice Mesh along 'vertex_index'" vertices = self._vertices[item] polygons = self._polygons[item] vertex_count = self._vertex_count[item] faces = Face(self._faces.center[item], self._faces.normal[item], self._faces.area[item]) - return UnstructuredMesh(vertices, polygons, vertex_count, self._boundaries, self._center[item], self._volume[item], faces, self._valid_mask[item]) + return Mesh(vertices, polygons, vertex_count, self._boundaries, self._center[item], self._volume[item], faces, self._valid_mask[item]) -def load_su2(file_or_mesh: str, cell_dim=instance('cells'), face_format: str = 'csc') -> UnstructuredMesh: +def load_su2(file_or_mesh: str, cell_dim=instance('cells'), face_format: str = 'csc') -> Mesh: """ Loads an unstructured mesh from a `.su2` file. @@ -271,7 +271,7 @@ def load_su2(file_or_mesh: str, cell_dim=instance('cells'), face_format: str = ' face_format: Sparse storage format for cell connectivity. Returns: - `UnstructuredMesh` + `Mesh` """ if isinstance(file_or_mesh, str): from ezmesh import import_from_file @@ -290,7 +290,7 @@ def mesh_from_numpy(points: Union[list, np.ndarray], polygons: list, boundaries: Dict[str, List[Sequence]], cell_dim: Shape = instance('cells'), - face_format: str = 'csc') -> UnstructuredMesh: + face_format: str = 'csc') -> Mesh: """ Construct an unstructured mesh from vertices. @@ -305,7 +305,7 @@ def mesh_from_numpy(points: Union[list, np.ndarray], face_format: Sparse storage format for cell connectivity. Returns: - `UnstructuredMesh` + `Mesh` """ cell_dim = cell_dim.with_size(len(polygons)) points = np.asarray(points) @@ -339,7 +339,7 @@ def mesh_from_numpy(points: Union[list, np.ndarray], faces = Face(faces.center, new_normals, faces.area) vol_contributions = faces.center.vector * faces.normal.vector * faces.area / dim volume = math.sum(vol_contributions, dual(faces.area)) - return UnstructuredMesh(vertices, polygons, vertex_count, boundary_slices, cell_centers, volume, faces, valid_mask) + return Mesh(vertices, polygons, vertex_count, boundary_slices, cell_centers, volume, faces, valid_mask) def build_faces_2d(points: np.ndarray, diff --git a/phi/physics/advect.py b/phi/physics/advect.py index cc2d090e5..d88b8076d 100644 --- a/phi/physics/advect.py +++ b/phi/physics/advect.py @@ -87,7 +87,7 @@ def differential(u: Field, For unstructured meshes, computes 1/V ∑_f (n·U_prev) U ρ A Args: - u: Scalar or vector-valued `Field` sampled on a `CenteredGrid`, `StaggeredGrid` or `UnstructuredMesh`. + u: Scalar or vector-valued `Field` sampled on a `CenteredGrid`, `StaggeredGrid` or `Mesh`. velocity: `Field` that can be sampled at the elements of `u`. For FVM, the advection term is typically linearized by setting `velocity = previous_velocity`. Passing `velocity=u` yields non-linear terms which cannot be traced inside linear functions. diff --git a/phi/physics/diffuse.py b/phi/physics/diffuse.py index e2f5f37ef..4cbc3368a 100644 --- a/phi/physics/diffuse.py +++ b/phi/physics/diffuse.py @@ -109,7 +109,7 @@ def differential(u: Field, In contrast to `explicit` and `implicit`, accuracy can be increased by using stencils of higher-order rather than calculating sub-steps. Args: - u: Scalar or vector-valued `Field` sampled on a `CenteredGrid`, `StaggeredGrid` or centered `UnstructuredMesh`. + u: Scalar or vector-valued `Field` sampled on a `CenteredGrid`, `StaggeredGrid` or centered `Mesh`. diffusivity: Dynamic viscosity, i.e. diffusion per time. Constant or varying by cell. gradient: Only used by FVM at the moment. Approximate gradient of `u`, e.g. ∇u of the previous time step. If `None`, approximates the gradient as `(u_neighbor - u_self) / distance`. diff --git a/phi/vis/_matplotlib/_matplotlib_plots.py b/phi/vis/_matplotlib/_matplotlib_plots.py index 0111e7511..bd613d577 100644 --- a/phi/vis/_matplotlib/_matplotlib_plots.py +++ b/phi/vis/_matplotlib/_matplotlib_plots.py @@ -16,7 +16,7 @@ from phi import math from phi.field import StaggeredGrid, Field -from phi.geom import Sphere, BaseBox, Point, Box, UnstructuredMesh +from phi.geom import Sphere, BaseBox, Point, Box, Mesh from phi.geom._heightmap import Heightmap from phi.geom._geom_ops import GeometryStack from phi.math import Tensor, channel, spatial, instance, non_channel, Shape, reshaped_numpy, shape @@ -603,7 +603,7 @@ def _plot_points(axis: Axes, data: Field, dims: tuple, vector: Shape, color: Ten angles = reshaped_numpy(math.rotation_angles(data.geometry.rotation_matrix), ['vector', data.shape.non_channel]) lower_x, lower_y = reshaped_numpy(data.geometry.center - math.rotate_vector(data.geometry.half_size, data.geometry.rotation_matrix), ['vector', data.shape.non_channel]) shapes = [plt.Rectangle((lxi, lyi), w2i * 2, h2i * 2, angle=ang*180/np.pi, linewidth=1, edgecolor='white', alpha=a, facecolor=ci) for lxi, lyi, w2i, h2i, ang, ci, a in zip(lower_x, lower_y, w2, h2, angles, mpl_colors, alphas)] - elif isinstance(data.geometry, UnstructuredMesh): + elif isinstance(data.geometry, Mesh): xs, ys = reshaped_numpy(data.geometry.vertices[data.geometry.polygons], ['vector', data.shape.non_channel, 'vertex_index']) counts = reshaped_numpy(data.geometry._vertex_count, [data.shape.non_channel]) shapes = [plt.Polygon(np.stack([x[:count], y[:count]], -1), closed=True, edgecolor='white', alpha=a, facecolor=ci) for x, y, count, ci, a in zip(xs, ys, counts, mpl_colors, alphas)]