Skip to content

Commit

Permalink
Add support for wrapping planar periodic meshes.
Browse files Browse the repository at this point in the history
Further testing is need to move the spherical wrapping into the
new method used by planar periodic meshes.
  • Loading branch information
andrewdnolan committed Dec 20, 2024
1 parent 7827e11 commit 9de3628
Showing 1 changed file with 53 additions and 3 deletions.
56 changes: 53 additions & 3 deletions mosaic/descriptor.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ def cell_patches(self) -> ndarray:
patch. Nodes are ordered counter clockwise around the cell center.
"""
patches = _compute_cell_patches(self.ds)
patches = self._fix_antimeridian(patches, "Cell")
patches = self._wrap_patches(patches, "Cell")
return patches

@cached_property
Expand All @@ -314,7 +314,7 @@ def edge_patches(self) -> ndarray:
corresponding node will be collapsed to the edge coordinate.
"""
patches = _compute_edge_patches(self.ds)
patches = self._fix_antimeridian(patches, "Edge")
patches = self._wrap_patches(patches, "Edge")
return patches

@cached_property
Expand All @@ -340,7 +340,7 @@ def vertex_patches(self) -> ndarray:
position.
"""
patches = _compute_vertex_patches(self.ds)
patches = self._fix_antimeridian(patches, "Vertex")
patches = self._wrap_patches(patches, "Vertex")
return patches

def _transform_coordinates(self, projection, transform):
Expand All @@ -355,6 +355,56 @@ def _transform_coordinates(self, projection, transform):
self.ds[f"x{loc}"].values = transformed_coords[:, 0]
self.ds[f"y{loc}"].values = transformed_coords[:, 1]

def _wrap_patches(self, patches, loc):
"""Wrap patches for spherical and planar-periodic meshes
"""

def _find_boundary_patches(patches, loc, coord):
"""
Find the patches that cross the periodic boundary and what
direction they cross the boundary (i.e. their ``sign``). This
method assumes the patch centroids are not periodic
"""
# get axis index we are inquiring over
axis = 0 if coord == "x" else 1
# get requested coordinate of patch centroids
center = self.ds[f"{coord}{loc.title()}"].values.reshape(-1, 1)
# get difference b/w centroid and nodes of patches
diff = patches[..., axis] - center

#
if self.__getattribute__(f"{coord}_period"):
period = self.__getattribute__(f"{coord}_period")

mask = np.abs(diff) > np.abs(period) / (2. * np.sqrt(2.))
sign = np.sign(diff)

return mask, sign

def _wrap_1D(patches, mask, sign, axis, period):
"""Correct patch periodicity along a single dimension"""
patches[..., axis][mask] -= np.sign(sign[mask]) * period
return patches

if self.x_period:
# find the patch that are periodic in x-direction
x_mask, x_sign = _find_boundary_patches(patches, loc, "x")
# using the sign of the difference correct patches x coordinate
patches = _wrap_1D(patches, x_mask, x_sign, 0, self.x_period)

if self.y_period:
# find the patch that are periodic in y-direction
y_mask, y_sign = _find_boundary_patches(patches, loc, "y")
# using the sign of the difference correct patches y coordinate
patches = _wrap_1D(patches, y_mask, y_sign, 1, self.y_period)

if self.is_spherical:
# call current spherical wrapping function for now
patches = self._fix_antimeridian(patches, loc)

return patches

def _fix_antimeridian(self, patches, loc, projection=None):
"""Correct vertices of patches that cross the antimeridian.
Expand Down

0 comments on commit 9de3628

Please sign in to comment.