From 4c03df5f1b72cad389e6e069683f8ab9580132a5 Mon Sep 17 00:00:00 2001 From: Alexandru Fikl Date: Tue, 5 Mar 2024 21:07:29 +0200 Subject: [PATCH] mesh: remove overdue deprecated functionality Removes: * BTAG_PARTITION.part_nr * MeshElementGroup.element_nr_base and node_nr_base * MeshElementGroup.copy * NodalAdjacency.copy * FacialAdjacencyGroup.copy --- meshmode/mesh/__init__.py | 171 +++++------------------------------- meshmode/mesh/processing.py | 54 ++++-------- 2 files changed, 35 insertions(+), 190 deletions(-) diff --git a/meshmode/mesh/__init__.py b/meshmode/mesh/__init__.py index 3f9fb914..ff29f774 100644 --- a/meshmode/mesh/__init__.py +++ b/meshmode/mesh/__init__.py @@ -21,8 +21,9 @@ """ from abc import ABC, abstractmethod -from dataclasses import dataclass, replace, field -from typing import Any, ClassVar, Hashable, Optional, Tuple, Type, Sequence +from dataclasses import dataclass, field, replace +from typing import Any, ClassVar, Hashable, Optional, Sequence, Tuple, Type +from warnings import warn import numpy as np import numpy.linalg as la @@ -32,6 +33,7 @@ from meshmode.mesh.tools import AffineMap + __doc__ = """ .. autoclass:: MeshElementGroup @@ -117,23 +119,8 @@ class BTAG_PARTITION(BTAG_NO_BOUNDARY): # noqa: N801 .. versionadded:: 2017.1 """ - def __init__(self, part_id: PartID, part_nr=None): - if part_nr is not None: - from warnings import warn - warn("part_nr is deprecated and will stop working in March 2023. " - "Use part_id instead.", - DeprecationWarning, stacklevel=2) - self.part_id = int(part_nr) - else: - self.part_id = part_id - - @property - def part_nr(self): - from warnings import warn - warn("part_nr is deprecated and will stop working in March 2023. " - "Use part_id instead.", - DeprecationWarning, stacklevel=2) - return self.part_id + def __init__(self, part_id: PartID) -> None: + self.part_id = part_id def __hash__(self): return hash((type(self), self.part_id)) @@ -251,43 +238,9 @@ class MeshElementGroup(ABC): """ order: int - - # NOTE: the mesh supports not having vertices if no facial or nodal - # adjacency is required, so we can mark this as optional vertex_indices: Optional[np.ndarray] nodes: np.ndarray - - # TODO: Remove ` = None` when everything is constructed through the factory - unit_nodes: np.ndarray = None - - # FIXME: these should be removed! - # https://github.com/inducer/meshmode/issues/224 - element_nr_base: Optional[int] = None - node_nr_base: Optional[int] = None - - # TODO: remove when everything has been constructed through the factory - _factory_constructed: bool = False - - def __post_init__(self): - if not self._factory_constructed: - from warnings import warn - warn(f"Calling the constructor of '{type(self).__name__}' is " - "deprecated and will stop working in July 2022. " - f"Use '{type(self).__name__}.make_group' instead", - DeprecationWarning, stacklevel=2) - - def __getattribute__(self, name): - if name in ("element_nr_base", "node_nr_base"): - new_name = ("base_element_nrs" - if name == "element_nr_base" else - "base_node_nrs") - - from warnings import warn - warn(f"'{type(self).__name__}.{name}' is deprecated and will be " - f"removed in July 2022. Use 'Mesh.{new_name}' instead", - DeprecationWarning, stacklevel=2) - - return super().__getattribute__(name) + unit_nodes: np.ndarray @property def dim(self): @@ -313,21 +266,6 @@ def nelements(self): def nnodes(self): return self.nelements * self.unit_nodes.shape[-1] - def copy(self, **kwargs: Any) -> "MeshElementGroup": - from warnings import warn - warn(f"{type(self).__name__}.copy is deprecated and will be removed in " - f"July 2022. {type(self).__name__} is now a dataclass, so " - "standard functions such as dataclasses.replace should be used " - "instead.", - DeprecationWarning, stacklevel=2) - - if "element_nr_base" not in kwargs: - kwargs["element_nr_base"] = None - if "node_nr_base" not in kwargs: - kwargs["node_nr_base"] = None - - return replace(self, **kwargs) - def __eq__(self, other): return ( type(self) is type(other) @@ -384,62 +322,10 @@ class _ModepyElementGroup(MeshElementGroup): .. attribute:: _modepy_space """ - # TODO: remove once `make_group` is used everywhere - dim: Optional[int] = None - _modepy_shape_cls: ClassVar[Type[mp.Shape]] = mp.Shape _modepy_shape: mp.Shape = field(default=None, repr=False) _modepy_space: mp.FunctionSpace = field(default=None, repr=False) - def __post_init__(self): - super().__post_init__() - if self._factory_constructed: - return - - # {{{ duplicates make_group below, keep in sync - - if self.unit_nodes is None: - if self.dim is None: - raise TypeError("either 'dim' or 'unit_nodes' must be provided") - else: - if self.dim is None: - object.__setattr__(self, "dim", self.unit_nodes.shape[0]) - - if self.unit_nodes.shape[0] != self.dim: - raise ValueError("'dim' does not match 'unit_nodes' dimension") - - # dim is now usable - assert self._modepy_shape_cls is not mp.Shape - object.__setattr__(self, "_modepy_shape", - # pylint: disable=abstract-class-instantiated - self._modepy_shape_cls(self.dim)) - object.__setattr__(self, "_modepy_space", - mp.space_for_shape(self._modepy_shape, self.order)) - - if self.unit_nodes is None: - unit_nodes = mp.edge_clustered_nodes_for_space( - self._modepy_space, self._modepy_shape) - object.__setattr__(self, "unit_nodes", unit_nodes) - - if self.nodes is not None: - if self.unit_nodes.shape[-1] != self.nodes.shape[-1]: - raise ValueError( - "'nodes' has wrong number of unit nodes per element." - f" expected {self.unit_nodes.shape[-1]}, " - f" but got {self.nodes.shape[-1]}.") - - if self.vertex_indices is not None: - if not issubclass(self.vertex_indices.dtype.type, np.integer): - raise TypeError("'vertex_indices' must be integral") - - if self.vertex_indices.shape[-1] != self.nvertices: - raise ValueError( - "'vertex_indices' has wrong number of vertices per element." - f" expected {self.nvertices}," - f" got {self.vertex_indices.shape[-1]}") - - # }}} - @property def nvertices(self): return self._modepy_shape.nvertices # pylint: disable=no-member @@ -486,11 +372,12 @@ def make_group(cls, order: int, raise ValueError("'unit_nodes' size does not match the dimension " f"of a '{type(space).__name__}' space of order {order}") - return cls(order=order, vertex_indices=vertex_indices, nodes=nodes, - dim=dim, + return cls(order=order, + vertex_indices=vertex_indices, + nodes=nodes, unit_nodes=unit_nodes, - _modepy_shape=shape, _modepy_space=space, - _factory_constructed=True) + _modepy_shape=shape, + _modepy_space=space) # }}} @@ -500,6 +387,7 @@ def make_group(cls, order: int, @dataclass(frozen=True, eq=False) class SimplexElementGroup(_ModepyElementGroup): r"""Inherits from :class:`MeshElementGroup`.""" + _modepy_shape_cls: ClassVar[Type[mp.Shape]] = mp.Simplex @property @@ -511,6 +399,7 @@ def is_affine(self): @dataclass(frozen=True, eq=False) class TensorProductElementGroup(_ModepyElementGroup): r"""Inherits from :class:`MeshElementGroup`.""" + _modepy_shape_cls: ClassVar[Type[mp.Shape]] = mp.Hypercube def is_affine(self): @@ -549,16 +438,6 @@ class NodalAdjacency: neighbors_starts: np.ndarray neighbors: np.ndarray - def copy(self, **kwargs: Any) -> "NodalAdjacency": - from warnings import warn - warn(f"{type(self).__name__}.copy is deprecated and will be removed in " - f"July 2022. {type(self).__name__} is now a dataclass, so " - "standard functions such as dataclasses.replace should be used " - "instead.", - DeprecationWarning, stacklevel=2) - - return replace(self, **kwargs) - def __eq__(self, other): return ( type(self) is type(other) @@ -605,16 +484,6 @@ class FacialAdjacencyGroup: igroup: int - def copy(self, **kwargs: Any) -> "FacialAdjacencyGroup": - from warnings import warn - warn(f"{type(self).__name__}.copy is deprecated and will be removed in " - f"July 2022. {type(self).__name__} is now a dataclass, so " - "standard functions such as dataclasses.replace should be used " - "instead.", - DeprecationWarning, stacklevel=2) - - return replace(self, **kwargs) - def __eq__(self, other): return ( type(self) is type(other) @@ -1076,8 +945,8 @@ def __init__(self, vertices, groups, *, skip_tests=False, assert fagrp.neighbor_faces.dtype == self.face_id_dtype assert fagrp.neighbor_faces.shape == (nfagrp_elements,) - from meshmode.mesh.processing import \ - test_volume_mesh_element_orientations + from meshmode.mesh.processing import ( + test_volume_mesh_element_orientations) if self.dim == self.ambient_dim and not skip_element_orientation_test: # only for volume meshes, for now @@ -1269,9 +1138,9 @@ def _test_node_vertex_consistency(mesh, tol): if isinstance(mgrp, _ModepyElementGroup): assert _test_node_vertex_consistency_resampling(mesh, igrp, tol) else: - from warnings import warn - warn("not implemented: node-vertex consistency check for '%s'" - % type(mgrp).__name__) + warn("Not implemented: node-vertex consistency check for " + f"groups of type '{type(mgrp).__name__}'.", + stacklevel=3) return True @@ -1657,7 +1526,7 @@ def as_python(mesh, function_name="make_mesh"): recreate the mesh given as an input parameter. """ - from pytools.py_codegen import PythonCodeGenerator, Indentation + from pytools.py_codegen import Indentation, PythonCodeGenerator cg = PythonCodeGenerator() cg(""" # generated by meshmode.mesh.as_python diff --git a/meshmode/mesh/processing.py b/meshmode/mesh/processing.py index a5013647..e1d387a2 100644 --- a/meshmode/mesh/processing.py +++ b/meshmode/mesh/processing.py @@ -22,12 +22,10 @@ THE SOFTWARE. """ +from dataclasses import dataclass, replace from functools import reduce from typing import ( - Callable, Dict, Optional, Union, Tuple, Mapping, List, Set, Sequence, - ) - -from dataclasses import dataclass + Callable, Dict, List, Mapping, Optional, Sequence, Set, Tuple, Union) import numpy as np import numpy.linalg as la @@ -35,17 +33,9 @@ import modepy as mp from meshmode.mesh import ( - MeshElementGroup, - Mesh, - BTAG_PARTITION, - PartID, - FacialAdjacencyGroup, - InteriorAdjacencyGroup, - BoundaryAdjacencyGroup, - InterPartAdjacencyGroup -) - -from meshmode.mesh import _FaceIDs + BTAG_PARTITION, BoundaryAdjacencyGroup, FacialAdjacencyGroup, + InteriorAdjacencyGroup, InterPartAdjacencyGroup, Mesh, MeshElementGroup, PartID, + _FaceIDs) from meshmode.mesh.tools import AffineMap @@ -179,12 +169,10 @@ def _filter_mesh_groups( # }}} - from dataclasses import replace new_groups = [ replace(grp, vertex_indices=new_vertex_indices[igrp], - nodes=grp.nodes[:, filtered_group_elements[igrp], :].copy(), - element_nr_base=None, node_nr_base=None) + nodes=grp.nodes[:, filtered_group_elements[igrp], :].copy()) for igrp, grp in enumerate(mesh.groups)] return new_groups, required_vertex_indices @@ -742,7 +730,6 @@ def flip_simplex_element_group( "ij,dej->dei", flip_matrix, grp.nodes[:, grp_flip_flags]) - from dataclasses import replace return replace(grp, vertex_indices=new_vertex_indices, nodes=new_nodes) @@ -764,11 +751,9 @@ def perform_flips( grp_flip_flags = flip_flags[base_element_nr:base_element_nr + grp.nelements] if grp_flip_flags.any(): - new_grp = flip_simplex_element_group( - mesh.vertices, grp, grp_flip_flags) + new_grp = flip_simplex_element_group(mesh.vertices, grp, grp_flip_flags) else: - from dataclasses import replace - new_grp = replace(grp, element_nr_base=None, node_nr_base=None) + new_grp = replace(grp) new_groups.append(new_grp) @@ -842,7 +827,6 @@ def merge_disjoint_meshes( if any(mesh._facial_adjacency_groups is not None for mesh in meshes): facial_adjacency_groups = False - from dataclasses import replace if single_group: from pytools import single_valued ref_group = single_valued( @@ -876,8 +860,7 @@ def merge_disjoint_meshes( for group in mesh.groups: assert group.vertex_indices is not None new_vertex_indices = group.vertex_indices + vert_base - new_group = replace(group, vertex_indices=new_vertex_indices, - element_nr_base=None, node_nr_base=None) + new_group = replace(group, vertex_indices=new_vertex_indices) new_groups.append(new_group) @@ -926,7 +909,6 @@ def split_mesh_groups( new_groups: List[MeshElementGroup] = [] subgroup_to_group_map = {} - from dataclasses import replace for igrp, (base_element_nr, grp) in enumerate( zip(mesh.base_element_nrs, mesh.groups) ): @@ -942,7 +924,6 @@ def split_mesh_groups( new_groups.append(replace(grp, vertex_indices=grp.vertex_indices[mask, :].copy(), nodes=grp.nodes[:, mask, :].copy(), - element_nr_base=None, node_nr_base=None, )) mesh = Mesh( @@ -1332,17 +1313,15 @@ def map_mesh(mesh: Mesh, f: Callable[[np.ndarray], np.ndarray]) -> Mesh: # {{{ assemble new groups list - from dataclasses import replace new_groups = [] - for group in mesh.groups: mapped_nodes = f(group.nodes.reshape(mesh.ambient_dim, -1)) if not mapped_nodes.flags.c_contiguous: mapped_nodes = np.copy(mapped_nodes, order="C") - new_groups.append(replace(group, - nodes=mapped_nodes.reshape(*group.nodes.shape), - element_nr_base=None, node_nr_base=None)) + new_groups.append( + replace(group, nodes=mapped_nodes.reshape(*group.nodes.shape)) + ) # }}} @@ -1384,17 +1363,15 @@ def affine_map( # {{{ assemble new groups list - from dataclasses import replace new_groups = [] - for group in mesh.groups: mapped_nodes = f(group.nodes.reshape(mesh.ambient_dim, -1)) if not mapped_nodes.flags.c_contiguous: mapped_nodes = np.copy(mapped_nodes, order="C") - new_groups.append(replace(group, - nodes=mapped_nodes.reshape(*group.nodes.shape), - element_nr_base=None, node_nr_base=None)) + new_groups.append( + replace(group, nodes=mapped_nodes.reshape(*group.nodes.shape)) + ) # }}} @@ -1424,7 +1401,6 @@ def compute_new_map(old_map: AffineMap) -> AffineMap: return AffineMap(matrix, offset) - from dataclasses import replace facial_adjacency_groups = [] for old_fagrp_list in mesh.facial_adjacency_groups: fagrp_list = []