Source code for nekmeshpy.quadmesh.tag

"""Vocabulary-only ``QuadMesh`` operations: rename the tags, touch nothing else.

Separate from :mod:`morph <nekmeshpy.quadmesh.morph>`, which is the delta-0 rung for
operations on the *geometry*. These change neither coordinates nor connectivity nor
numbering -- only what the two tag tables call things -- so a caller reading the
sibling list can tell at a glance that a retag cannot have moved a node.
"""

from __future__ import annotations

from collections.abc import Mapping, Sequence

import numpy as np

from .._typing import IntArray, StrArray
from ..linemesh import LineMesh
from ..linemesh import tag as linemesh
from ..tags.tags import ElementTagSpec
from .quadmesh import QuadMesh


[docs] def retag_element(mesh: QuadMesh, tags: ElementTagSpec) -> QuadMesh: """The same mesh with its ``element_tags`` changed, by what ``tags`` is: a mapping renames the existing names (a tag the map does not name is left alone, the map applies simultaneously, a key naming nothing raises, a rename to ``NO_TAG`` untags); a string names every element; a ``Tags`` or per-element sequence replaces the table. Geometry and the side tags are untouched.""" return QuadMesh(mesh.line_mesh, mesh.quads, mesh.orient, mesh.interior, mesh.element_tags.retag(tags))
[docs] def retag_edge(mesh: QuadMesh, mapping: Mapping[str, str]) -> QuadMesh: """The same mesh with its ``edge_tags`` renamed through ``mapping``, rows kept in stored order (see :func:`retag_element` for the map's own rules). Renaming a tag to ``NO_TAG`` **drops** its rows rather than storing an empty name: a side-tag table is a named subset, so leaving it is leaving the table. That is how a boundary name that has stopped meaning anything is retired.""" return QuadMesh(linemesh.retag_element(mesh.line_mesh, mapping), mesh.quads, mesh.orient, mesh.interior, mesh.element_tags)
[docs] def tag_edges(mesh: QuadMesh, rows: IntArray, tags: str | Sequence[str] | StrArray) -> QuadMesh: """The same mesh with the shared edge each ``(quad, side)`` row names given its tag. The authoring bridge. A factory knows its geometry element-locally -- "side 1 of the outermost ring is the wall" -- while storage is one tag per shared edge, so the row is resolved through ``mesh.quads[quad, side - 1]`` and the tag written there. What changes is only where it lands: two rows that name the same edge from either side of it no longer become two entries that could disagree, and the later row wins. ``tags`` is one name for all the rows or one name per row, as :func:`hexmesh.tag_faces <nekmeshpy.hexmesh.tag.tag_faces>` takes them. Rows tagged ``NO_TAG`` name nothing, so a partly-tagged row block can be handed over whole.""" edge_of: IntArray = np.asarray(mesh.quads, dtype=np.int64) r: IntArray = np.asarray(rows, dtype=np.int64).reshape(-1, 2) # One name for all of them, or one per row -- as ``hexmesh.tag_faces`` takes them. # A bare string is a sequence *of characters*, so without this it zipped against the # rows and quietly tagged only the first. No dtype on the broadcast either: # ``np.str_`` is a one-character width, which clips every name to its first letter. names: StrArray = (np.full(r.shape[0], tags) if isinstance(tags, str) else np.asarray(tags, dtype=np.str_).reshape(-1)) if names.shape[0] != r.shape[0]: raise ValueError( "tag_edges: got %d rows but %d tags -- pass one name for all of them or " "one per row" % (r.shape[0], names.shape[0])) named = mesh.edge_tags.put(edge_of[r[:, 0], r[:, 1] - 1], names) return QuadMesh( LineMesh(mesh.line_mesh.point_mesh, mesh.line_mesh.lines, mesh.line_mesh.interior, named), mesh.quads, mesh.orient, mesh.interior, mesh.element_tags)
__all__ = [ "retag_edge", "retag_element", "tag_edges", ]