tags

Sparse tag tables and the operations that carry them through a mesh.

class nekmeshpy.tags.Tags[source]

Bases: object

A mesh’s per-element region tags over size elements, stored sparsely: only tagged elements.

size is the total element count the table is over, so a tagged id outside it is refused at construction and to_dense needs no length argument.

ids: NDArray[int64]
tags: NDArray[str_]
size: int
classmethod empty(size)[source]

The nothing-tagged table over size elements – what an untagged mesh stores.

Parameters:

size (int)

Return type:

Tags

classmethod from_dense(array)[source]

From a dense per-element array where "" means untagged.

Parameters:

array (Sequence[str] | NDArray[str_])

Return type:

Tags

classmethod full(shape, fill_value)[source]

shape elements all named fill_value (or empty() when it is empty), as np.full.

Parameters:
  • shape (int)

  • fill_value (str)

Return type:

Tags

to_dense()[source]

The equivalent dense (size,) array, "" where untagged.

Return type:

NDArray[str_]

unique() → list[str][source]
unique(return_inverse: Literal[True], return_counts: Literal[False] = False) → tuple[list[str], NDArray[int64]]
unique(return_inverse: Literal[False] = False, *, return_counts: Literal[True]) → tuple[list[str], NDArray[int64]]
unique(return_inverse: Literal[True], return_counts: Literal[True]) → tuple[list[str], NDArray[int64], NDArray[int64]]

Sorted unique tags, as np.unique.

With return_inverse also the index into them of each stored row’s tag (aligned with ids), so inverse + 1 is a per-row integer code. With return_counts also how many elements carry each name.

Parameters:
  • return_inverse (bool)

  • return_counts (bool)

Return type:

list[str] | tuple[list[str], NDArray[int64]] | tuple[list[str], NDArray[int64], NDArray[int64]]

is_uniform()[source]

True when all size elements carry the same single tag.

Return type:

bool

count(tag)[source]

How many elements are named tag.

Parameters:

tag (str)

Return type:

int

isin(test_elements)[source]

Boolean mask over the rows (not the elements) whose tag is one of test_elements, as np.isin; a single string is one name.

Parameters:

test_elements (str | Sequence[str] | NDArray[str_])

Return type:

NDArray[bool]

flatnonzero(test_elements, strict=False)[source]

Ids of the elements whose tag is one of test_elements, ascending, as np.flatnonzero(np.isin(dense, test_elements)); a single string is one name.

strict raises ValueError if any name is carried by no element – an empty result is otherwise silent, and a mis-spelled name is almost always a typo.

Parameters:
Return type:

NDArray[int64]

compress(condition)[source]

The rows where condition is true, ascending id order preserved, as np.compress over the stored rows (size is unchanged).

condition is 1-D and may be shorter than the table, the missing rows counting as false; a true entry past the last row raises IndexError.

Parameters:

condition (NDArray[bool] | Sequence[bool])

Return type:

Tags

retag(spec)[source]

One entry point for changing a table, by what spec is: a mapping rename() the existing vocabulary; a string names every element; a Tags or a per-element sequence replaces the table outright (and must be over this table’s size).

Parameters:

spec (Mapping[str, str] | str | Tags | Sequence[str] | NDArray[str_])

Return type:

Tags

rename(mapping)[source]

The same elements under a new vocabulary: a tag the map does not name is left alone, the map applies simultaneously, two keys may share an image, and a key that names nothing raises.

Renaming a region to "" drops it back to untagged, which is what this sparse table stores as no row at all.

The map is read once and written once, hence simultaneous: {"a": "b", "b": "a"} swaps rather than collapsing. The result is re-widened, so a longer name is not truncated to the input’s dtype. A key naming nothing raises, since a rename that silently matches nothing is almost always a typo.

Parameters:

mapping (Mapping[str, str])

Return type:

Tags

take(indices)[source]

Tags for a new element list whose element k copies source indices[k], as np.take (mode='raise'): negative indices count from the end, one out of bounds raises IndexError. The result is over len(indices) elements.

The sparse form of dense[indices].

Parameters:

indices (NDArray[int64])

Return type:

Tags

take_dense(indices)[source]

The name of each element in indices as a string array, "" where untagged – take(indices).to_dense(), as np.take on the dense array.

Parameters:

indices (NDArray[int64])

Return type:

NDArray[str_]

put(ids, values)[source]

This table with ids named values (one string for all, or one per id), as np.put (mode='raise'): a name already on an id is overwritten, when an id repeats the last value wins, and one out of bounds raises IndexError.

A "" value names nothing and leaves that element as it was (use clear() to untag).

Parameters:
Return type:

Tags

clear(ids)[source]

This table with the tags on ids removed (size is unchanged); an id that is not tagged is ignored, one out of bounds raises IndexError.

Parameters:

ids (NDArray[int64])

Return type:

Tags

repeat(repeats)[source]

Each element repeated repeats times in place, over repeats * size elements: element i*repeats + j copies i.

The sparse form of np.repeat(dense, repeats) – a refine’s children each inherit their parent’s name.

Parameters:

repeats (int)

Return type:

Tags

is_tagged()[source]

The (size,) mask of tagged elements.

Return type:

NDArray[bool]

__init__(ids, tags, size)
Parameters:
  • ids (NDArray[int64])

  • tags (NDArray[str_])

  • size (int)

Return type:

None

tile(reps)[source]

This table tiled reps times, over reps * size elements: element i*size + q.

The sparse form of np.tile(dense, reps).

Parameters:

reps (int)

Return type:

Tags

static concatenate(arrays)[source]

The tables one after another over the summed element count, as np.concatenate: each table’s ids are offset by the sizes before it.

Parameters:

arrays (Sequence[Tags])

Return type:

Tags

renumber(new_id_of, size)[source]

Tags carried onto new ids in a table over size elements, where old element e becomes new_id_of[e].

Parameters:
  • new_id_of (NDArray[int64])

  • size (int)

Return type:

Tags

nekmeshpy.tags.sweep_tags(spec, n_layers, n_slice)[source]

The swept elements’ region tags from a loft’s element_tags argument.

None tags nothing, a str tags every swept element, and an Tags over one slice’s n_slice elements tags each element by the slice element it was extruded from (element i*n_slice + k).

Parameters:
Return type:

Tags

nekmeshpy.tags.sweep_cap(spec, default, n_slice)[source]

One cap’s dense (n_slice,) tag row from a loft’s first_tag / last_tag argument, falling back to default (the bounding slice’s own element tags – a cap side is that slice element) when the argument is None.

Parameters:
Return type:

NDArray[str_]

nekmeshpy.tags.weld(tables)[source]

Combine tables that may name the same element – what a merge produces once its weld has carried two blocks’ tags onto one shared entity.

Plain Tags.concatenate cannot do this: it would hand the constructor two rows for one id, which is rejected. Here the duplicate is expected and meaningful, so it is resolved rather than refused – but only when the two agree. Two different non-empty names on one entity is the contradiction the shared-entity storage exists to rule out, and there is no honest way to pick between them, so it raises.

An entity named by one side and left untagged by the other simply takes the name: that is the ordinary case of a tagged block welding onto an untagged neighbour.

Every table must be over the same element count, which the result keeps.

Parameters:

tables (Sequence[Tags])

Return type:

Tags