From a175f527fe3e0fdd60bd6cbd5e4f29ecc78d1a1b Mon Sep 17 00:00:00 2001 From: Amadeus Gebauer Date: Tue, 2 Sep 2025 15:08:48 +0200 Subject: [PATCH] Implement lin_to_quad for wedges and to_serendipity --- pyproject.toml | 2 +- src/biomesh/adapt.py | 142 +++++++- tests/data/hex20.vtu | 332 +++++++++++++++++++ tests/data/hex27.vtu | 448 ++++++++++++++++++++++++++ tests/data/hex8.vtu | 156 +++++++++ tests/data/tet10.vtu | 746 +++++++++++++++++++++++++++++++++++++++++++ tests/data/tet4.vtu | 308 ++++++++++++++++++ tests/test_adapt.py | 42 +++ 8 files changed, 2161 insertions(+), 15 deletions(-) create mode 100644 tests/data/hex20.vtu create mode 100644 tests/data/hex27.vtu create mode 100644 tests/data/hex8.vtu create mode 100644 tests/data/tet10.vtu create mode 100644 tests/data/tet4.vtu diff --git a/pyproject.toml b/pyproject.toml index 41aae69..4767b43 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "biomesh" -version = "0.5.1" +version = "0.6.0" authors = [ { name="The biomesh Authors" }, ] diff --git a/src/biomesh/adapt.py b/src/biomesh/adapt.py index cfa9bf6..339ede8 100644 --- a/src/biomesh/adapt.py +++ b/src/biomesh/adapt.py @@ -6,6 +6,8 @@ """Small utilities for mesh adaption (e.g. converting linear elements to quadratic elements)""" +from typing import Callable, Optional + import meshio import numpy as np @@ -54,6 +56,23 @@ [1, 3], [2, 3], ], + "wedge": [ + [0], + [1], + [2], + [3], + [4], + [5], + [0, 1], + [1, 2], + [2, 0], + [3, 4], + [4, 5], + [5, 3], + [0, 3], + [1, 4], + [2, 5], + ], "triangle": [ [0], [1], @@ -68,26 +87,69 @@ _lin_to_quad_cell_type = { "hexahedron": "hexahedron27", "tetra": "tetra10", + "wedge": "wedge15", "triangle": "triangle6", "quad": "quad9", "line": "line3", } +_hex8_to_hex20 = [ + [0], + [1], + [2], + [3], + [4], + [5], + [6], + [7], + [0, 1], + [1, 2], + [2, 3], + [3, 0], + [4, 5], + [5, 6], + [6, 7], + [7, 4], + [0, 4], + [1, 5], + [2, 6], + [3, 7], +] -def lin_to_quad(mesh: meshio.Mesh) -> meshio.Mesh: - """Convert linear elements to quadratic elements in a mesh. - This function returns a new mesh in which all linear elements (triangles, quadrilaterals, tetrahedra, and hexahedra) - are converted into their corresponding quadratic elements. +def adapt_mesh( + mesh: meshio.Mesh, + adapting_scheme: Callable[[str], Optional[tuple[str, list[list[int]]]]], +) -> meshio.Mesh: + """Adapt a mesh to a higher-order (quadratic) representation using a + provided adapting scheme. - Args: - mesh: - The input mesh containing linear elements. + This function takes a mesh and, for each cell block, determines whether it should be adapted + to a new cell type. If so, it generates new mid-edge nodes and updates + the mesh accordingly. The adapting scheme determines the mapping from the original cell type + to the new cell type and specifies how to construct new nodes. + + Parameters: + mesh: The input mesh to be adapted. + adapting_scheme: + A function that takes a cell type string and returns either: + - None, if the cell type should not be adapted, + - or a tuple of (new_cell_type, node_mapping), where: + new_cell_type : str + The name of the quadratic cell type (e.g., "triangle6"). + node_mapping : list + A list specifying how to map old nodes and create new mid-edge nodes. + Each entry is either a tuple with one index (existing node) or multiple + indices (to create a new node as the mean of those nodes). Returns: - The modified mesh with quadratic elements. - """ + The adapted mesh with quadratic cells and updated points, point data, and cell data. + Notes + - Cell blocks that are already quadratic or are not to be adapted are left unchanged. + - New mid-edge nodes are created only once per unique edge and reused across cells. + - Point data is interpolated for new nodes using the mean of the corresponding data. + """ new_points = [coord for coord in mesh.points] new_point_data = {key: [d for d in data] for key, data in mesh.point_data.items()} new_cell_blocks = [] @@ -102,16 +164,17 @@ def lin_to_quad(mesh: meshio.Mesh) -> meshio.Mesh: new_cells = [] cell_type = cellblock.type - if cell_type in ["vertex", "hexahedron27", "tetra10", "triangle6", "quad9"]: - # this cell block is already quadratic, no need to convert + # determine the mapping of the nodes to the new quadratic celltype + scheme = adapting_scheme(cell_type) + + if not scheme: + # don't adapt this block new_cell_blocks.append(cellblock) for key, data in mesh.cell_data.items(): new_cell_data[key].append(data[i]) continue - # determine the mapping of the nodes to the new quadratic celltype - node_mapping = _lin_to_quad_nodes[cell_type] - new_cell_type = _lin_to_quad_cell_type[cell_type] + new_cell_type, node_mapping = scheme for cell in cellblock.data: cell_nodes = [] @@ -135,6 +198,7 @@ def lin_to_quad(mesh: meshio.Mesh) -> meshio.Mesh: np.mean( [mesh.point_data[name][cell[n]] for n in node], axis=0, + dtype=mesh.point_data[name].dtype, ) ) @@ -159,3 +223,53 @@ def lin_to_quad(mesh: meshio.Mesh) -> meshio.Mesh: key: [np.array(d) for d in data] for key, data in new_cell_data.items() }, ) + + +def lin_to_quad(mesh: meshio.Mesh) -> meshio.Mesh: + """Convert linear elements to quadratic elements in a mesh. + + This function returns a new mesh in which all linear elements (triangles, quadrilaterals, tetrahedra, and hexahedra) + are converted into their corresponding quadratic elements. + + Args: + mesh: + The input mesh containing linear elements. + + Returns: + The modified mesh with quadratic elements. + """ + + def lin_to_quad(cell_type: str) -> Optional[tuple[str, list[list[int]]]]: + """Returns the node mapping for quadratic elements.""" + if cell_type in ["vertex", "hexahedron27", "tetra10", "triangle6", "quad9"]: + return None + + return _lin_to_quad_cell_type[cell_type], _lin_to_quad_nodes[cell_type] + + return adapt_mesh(mesh, lin_to_quad) + + +def to_serendipity(mesh: meshio.Mesh) -> meshio.Mesh: + """Converts elements to serendipity elements in a mesh. + + Args: + mesh: + The input mesh containing linear elements. + + Returns: + The modified mesh with serendipity elements. + """ + + def _to_serendipity(cell_type: str) -> Optional[tuple[str, list[list[int]]]]: + """Returns the node mapping for serendipity elements.""" + if cell_type in ["hexahedron20"]: + return None + + if cell_type not in ["hexahedron"]: + raise ValueError( + f"Cell type {cell_type} not supported for serendipity conversion." + ) + + return "hexahedron20", _hex8_to_hex20 + + return adapt_mesh(mesh, _to_serendipity) diff --git a/tests/data/hex20.vtu b/tests/data/hex20.vtu new file mode 100644 index 0000000..0a353ff --- /dev/null +++ b/tests/data/hex20.vtu @@ -0,0 +1,332 @@ + + + + + + + +0.00000000000e+00 +0.00000000000e+00 +0.00000000000e+00 +0.00000000000e+00 +1.00000000000e+00 +0.00000000000e+00 +0.00000000000e+00 +0.00000000000e+00 +1.00000000000e+00 +0.00000000000e+00 +1.00000000000e+00 +1.00000000000e+00 +1.00000000000e+00 +0.00000000000e+00 +0.00000000000e+00 +1.00000000000e+00 +1.00000000000e+00 +0.00000000000e+00 +1.00000000000e+00 +0.00000000000e+00 +1.00000000000e+00 +1.00000000000e+00 +1.00000000000e+00 +1.00000000000e+00 +2.00000000000e+00 +0.00000000000e+00 +0.00000000000e+00 +2.00000000000e+00 +1.00000000000e+00 +0.00000000000e+00 +2.00000000000e+00 +0.00000000000e+00 +1.00000000000e+00 +2.00000000000e+00 +1.00000000000e+00 +1.00000000000e+00 +3.00000000000e+00 +0.00000000000e+00 +0.00000000000e+00 +3.00000000000e+00 +1.00000000000e+00 +0.00000000000e+00 +3.00000000000e+00 +0.00000000000e+00 +1.00000000000e+00 +3.00000000000e+00 +1.00000000000e+00 +1.00000000000e+00 +5.00000000000e-01 +0.00000000000e+00 +0.00000000000e+00 +1.00000000000e+00 +5.00000000000e-01 +0.00000000000e+00 +5.00000000000e-01 +1.00000000000e+00 +0.00000000000e+00 +0.00000000000e+00 +5.00000000000e-01 +0.00000000000e+00 +5.00000000000e-01 +0.00000000000e+00 +1.00000000000e+00 +1.00000000000e+00 +5.00000000000e-01 +1.00000000000e+00 +5.00000000000e-01 +1.00000000000e+00 +1.00000000000e+00 +0.00000000000e+00 +5.00000000000e-01 +1.00000000000e+00 +0.00000000000e+00 +0.00000000000e+00 +5.00000000000e-01 +1.00000000000e+00 +0.00000000000e+00 +5.00000000000e-01 +1.00000000000e+00 +1.00000000000e+00 +5.00000000000e-01 +0.00000000000e+00 +1.00000000000e+00 +5.00000000000e-01 +1.50000000000e+00 +0.00000000000e+00 +0.00000000000e+00 +2.00000000000e+00 +5.00000000000e-01 +0.00000000000e+00 +1.50000000000e+00 +1.00000000000e+00 +0.00000000000e+00 +1.50000000000e+00 +0.00000000000e+00 +1.00000000000e+00 +2.00000000000e+00 +5.00000000000e-01 +1.00000000000e+00 +1.50000000000e+00 +1.00000000000e+00 +1.00000000000e+00 +2.00000000000e+00 +0.00000000000e+00 +5.00000000000e-01 +2.00000000000e+00 +1.00000000000e+00 +5.00000000000e-01 +2.50000000000e+00 +0.00000000000e+00 +0.00000000000e+00 +3.00000000000e+00 +5.00000000000e-01 +0.00000000000e+00 +2.50000000000e+00 +1.00000000000e+00 +0.00000000000e+00 +2.50000000000e+00 +0.00000000000e+00 +1.00000000000e+00 +3.00000000000e+00 +5.00000000000e-01 +1.00000000000e+00 +2.50000000000e+00 +1.00000000000e+00 +1.00000000000e+00 +3.00000000000e+00 +0.00000000000e+00 +5.00000000000e-01 +3.00000000000e+00 +1.00000000000e+00 +5.00000000000e-01 + + + + + +0 +4 +5 +1 +2 +6 +7 +3 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +4 +8 +9 +5 +6 +10 +11 +7 +28 +29 +30 +17 +31 +32 +33 +21 +25 +34 +35 +26 +8 +12 +13 +9 +10 +14 +15 +11 +36 +37 +38 +29 +39 +40 +41 +32 +34 +42 +43 +35 + + + +20 +40 +60 + + + +25 +25 +25 + + + + + +1 +1 +1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +1 +0 +0 +0 +1 +1 +0 +0 +1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + + + +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +1 +1 +1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +1 +0 +0 +1 +0 +1 +1 + + + + + +1 +1 +2 + + + +1 +1 +2 + + + + + + diff --git a/tests/data/hex27.vtu b/tests/data/hex27.vtu new file mode 100644 index 0000000..4377300 --- /dev/null +++ b/tests/data/hex27.vtu @@ -0,0 +1,448 @@ + + + + + + + +0.00000000000e+00 +0.00000000000e+00 +0.00000000000e+00 +0.00000000000e+00 +1.00000000000e+00 +0.00000000000e+00 +0.00000000000e+00 +0.00000000000e+00 +1.00000000000e+00 +0.00000000000e+00 +1.00000000000e+00 +1.00000000000e+00 +1.00000000000e+00 +0.00000000000e+00 +0.00000000000e+00 +1.00000000000e+00 +1.00000000000e+00 +0.00000000000e+00 +1.00000000000e+00 +0.00000000000e+00 +1.00000000000e+00 +1.00000000000e+00 +1.00000000000e+00 +1.00000000000e+00 +2.00000000000e+00 +0.00000000000e+00 +0.00000000000e+00 +2.00000000000e+00 +1.00000000000e+00 +0.00000000000e+00 +2.00000000000e+00 +0.00000000000e+00 +1.00000000000e+00 +2.00000000000e+00 +1.00000000000e+00 +1.00000000000e+00 +3.00000000000e+00 +0.00000000000e+00 +0.00000000000e+00 +3.00000000000e+00 +1.00000000000e+00 +0.00000000000e+00 +3.00000000000e+00 +0.00000000000e+00 +1.00000000000e+00 +3.00000000000e+00 +1.00000000000e+00 +1.00000000000e+00 +5.00000000000e-01 +0.00000000000e+00 +0.00000000000e+00 +1.00000000000e+00 +5.00000000000e-01 +0.00000000000e+00 +5.00000000000e-01 +1.00000000000e+00 +0.00000000000e+00 +0.00000000000e+00 +5.00000000000e-01 +0.00000000000e+00 +5.00000000000e-01 +0.00000000000e+00 +1.00000000000e+00 +1.00000000000e+00 +5.00000000000e-01 +1.00000000000e+00 +5.00000000000e-01 +1.00000000000e+00 +1.00000000000e+00 +0.00000000000e+00 +5.00000000000e-01 +1.00000000000e+00 +0.00000000000e+00 +0.00000000000e+00 +5.00000000000e-01 +1.00000000000e+00 +0.00000000000e+00 +5.00000000000e-01 +1.00000000000e+00 +1.00000000000e+00 +5.00000000000e-01 +0.00000000000e+00 +1.00000000000e+00 +5.00000000000e-01 +0.00000000000e+00 +5.00000000000e-01 +5.00000000000e-01 +1.00000000000e+00 +5.00000000000e-01 +5.00000000000e-01 +5.00000000000e-01 +0.00000000000e+00 +5.00000000000e-01 +5.00000000000e-01 +1.00000000000e+00 +5.00000000000e-01 +5.00000000000e-01 +5.00000000000e-01 +0.00000000000e+00 +5.00000000000e-01 +5.00000000000e-01 +1.00000000000e+00 +5.00000000000e-01 +5.00000000000e-01 +5.00000000000e-01 +1.50000000000e+00 +0.00000000000e+00 +0.00000000000e+00 +2.00000000000e+00 +5.00000000000e-01 +0.00000000000e+00 +1.50000000000e+00 +1.00000000000e+00 +0.00000000000e+00 +1.50000000000e+00 +0.00000000000e+00 +1.00000000000e+00 +2.00000000000e+00 +5.00000000000e-01 +1.00000000000e+00 +1.50000000000e+00 +1.00000000000e+00 +1.00000000000e+00 +2.00000000000e+00 +0.00000000000e+00 +5.00000000000e-01 +2.00000000000e+00 +1.00000000000e+00 +5.00000000000e-01 +2.00000000000e+00 +5.00000000000e-01 +5.00000000000e-01 +1.50000000000e+00 +0.00000000000e+00 +5.00000000000e-01 +1.50000000000e+00 +1.00000000000e+00 +5.00000000000e-01 +1.50000000000e+00 +5.00000000000e-01 +0.00000000000e+00 +1.50000000000e+00 +5.00000000000e-01 +1.00000000000e+00 +1.50000000000e+00 +5.00000000000e-01 +5.00000000000e-01 +2.50000000000e+00 +0.00000000000e+00 +0.00000000000e+00 +3.00000000000e+00 +5.00000000000e-01 +0.00000000000e+00 +2.50000000000e+00 +1.00000000000e+00 +0.00000000000e+00 +2.50000000000e+00 +0.00000000000e+00 +1.00000000000e+00 +3.00000000000e+00 +5.00000000000e-01 +1.00000000000e+00 +2.50000000000e+00 +1.00000000000e+00 +1.00000000000e+00 +3.00000000000e+00 +0.00000000000e+00 +5.00000000000e-01 +3.00000000000e+00 +1.00000000000e+00 +5.00000000000e-01 +3.00000000000e+00 +5.00000000000e-01 +5.00000000000e-01 +2.50000000000e+00 +0.00000000000e+00 +5.00000000000e-01 +2.50000000000e+00 +1.00000000000e+00 +5.00000000000e-01 +2.50000000000e+00 +5.00000000000e-01 +0.00000000000e+00 +2.50000000000e+00 +5.00000000000e-01 +1.00000000000e+00 +2.50000000000e+00 +5.00000000000e-01 +5.00000000000e-01 + + + + + +0 +4 +5 +1 +2 +6 +7 +3 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +4 +8 +9 +5 +6 +10 +11 +7 +35 +36 +37 +17 +38 +39 +40 +21 +25 +41 +42 +26 +29 +43 +44 +45 +46 +47 +48 +8 +12 +13 +9 +10 +14 +15 +11 +49 +50 +51 +36 +52 +53 +54 +39 +41 +55 +56 +42 +43 +57 +58 +59 +60 +61 +62 + + + +27 +54 +81 + + + +29 +29 +29 + + + + + +1 +1 +1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +1 +0 +0 +0 +1 +1 +0 +0 +1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + + + +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +1 +1 +1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +1 +0 +0 +1 +0 +1 +1 +1 +0 +0 +0 +0 +0 + + + + + +1 +1 +2 + + + +1 +1 +2 + + + + + + diff --git a/tests/data/hex8.vtu b/tests/data/hex8.vtu new file mode 100644 index 0000000..cae25b8 --- /dev/null +++ b/tests/data/hex8.vtu @@ -0,0 +1,156 @@ + + + + + + + +0.00000000000e+00 +0.00000000000e+00 +0.00000000000e+00 +0.00000000000e+00 +1.00000000000e+00 +0.00000000000e+00 +0.00000000000e+00 +0.00000000000e+00 +1.00000000000e+00 +0.00000000000e+00 +1.00000000000e+00 +1.00000000000e+00 +1.00000000000e+00 +0.00000000000e+00 +0.00000000000e+00 +1.00000000000e+00 +1.00000000000e+00 +0.00000000000e+00 +1.00000000000e+00 +0.00000000000e+00 +1.00000000000e+00 +1.00000000000e+00 +1.00000000000e+00 +1.00000000000e+00 +2.00000000000e+00 +0.00000000000e+00 +0.00000000000e+00 +2.00000000000e+00 +1.00000000000e+00 +0.00000000000e+00 +2.00000000000e+00 +0.00000000000e+00 +1.00000000000e+00 +2.00000000000e+00 +1.00000000000e+00 +1.00000000000e+00 +3.00000000000e+00 +0.00000000000e+00 +0.00000000000e+00 +3.00000000000e+00 +1.00000000000e+00 +0.00000000000e+00 +3.00000000000e+00 +0.00000000000e+00 +1.00000000000e+00 +3.00000000000e+00 +1.00000000000e+00 +1.00000000000e+00 + + + + + +0 +4 +5 +1 +2 +6 +7 +3 +4 +8 +9 +5 +6 +10 +11 +7 +8 +12 +13 +9 +10 +14 +15 +11 + + + +8 +16 +24 + + + +12 +12 +12 + + + + + +1 +1 +1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + + + +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +1 +1 +1 +1 + + + + + +1 +1 +2 + + + +1 +1 +2 + + + + + + diff --git a/tests/data/tet10.vtu b/tests/data/tet10.vtu new file mode 100644 index 0000000..645c63e --- /dev/null +++ b/tests/data/tet10.vtu @@ -0,0 +1,746 @@ + + + + + + + +0.00000000000e+00 +0.00000000000e+00 +0.00000000000e+00 +0.00000000000e+00 +1.00000000000e+00 +0.00000000000e+00 +0.00000000000e+00 +0.00000000000e+00 +1.00000000000e+00 +0.00000000000e+00 +1.00000000000e+00 +1.00000000000e+00 +1.00000000000e+00 +0.00000000000e+00 +0.00000000000e+00 +1.00000000000e+00 +1.00000000000e+00 +0.00000000000e+00 +1.00000000000e+00 +0.00000000000e+00 +1.00000000000e+00 +1.00000000000e+00 +1.00000000000e+00 +1.00000000000e+00 +5.00000000000e-01 +5.00000000000e-01 +0.00000000000e+00 +5.00000000000e-01 +0.00000000000e+00 +5.00000000000e-01 +1.00000000000e+00 +5.00000000000e-01 +5.00000000000e-01 +5.00000000000e-01 +1.00000000000e+00 +5.00000000000e-01 +0.00000000000e+00 +5.00000000000e-01 +5.00000000000e-01 +5.00000000000e-01 +5.00000000000e-01 +1.00000000000e+00 +5.00000000000e-01 +5.00000000000e-01 +5.00000000000e-01 +0.00000000000e+00 +0.00000000000e+00 +5.00000000000e-01 +0.00000000000e+00 +2.50000000000e-01 +2.50000000000e-01 +0.00000000000e+00 +2.50000000000e-01 +7.50000000000e-01 +2.50000000000e-01 +0.00000000000e+00 +7.50000000000e-01 +2.50000000000e-01 +0.00000000000e+00 +2.50000000000e-01 +2.50000000000e-01 +2.50000000000e-01 +5.00000000000e-01 +0.00000000000e+00 +5.00000000000e-01 +0.00000000000e+00 +0.00000000000e+00 +7.50000000000e-01 +2.50000000000e-01 +2.50000000000e-01 +2.50000000000e-01 +0.00000000000e+00 +2.50000000000e-01 +7.50000000000e-01 +0.00000000000e+00 +2.50000000000e-01 +5.00000000000e-01 +2.50000000000e-01 +0.00000000000e+00 +1.00000000000e+00 +5.00000000000e-01 +0.00000000000e+00 +7.50000000000e-01 +7.50000000000e-01 +2.50000000000e-01 +1.00000000000e+00 +2.50000000000e-01 +2.50000000000e-01 +1.00000000000e+00 +7.50000000000e-01 +2.50000000000e-01 +7.50000000000e-01 +5.00000000000e-01 +0.00000000000e+00 +5.00000000000e-01 +1.00000000000e+00 +2.50000000000e-01 +7.50000000000e-01 +1.00000000000e+00 +2.50000000000e-01 +2.50000000000e-01 +1.00000000000e+00 +2.50000000000e-01 +5.00000000000e-01 +7.50000000000e-01 +5.00000000000e-01 +0.00000000000e+00 +1.00000000000e+00 +7.50000000000e-01 +0.00000000000e+00 +7.50000000000e-01 +7.50000000000e-01 +2.50000000000e-01 +1.00000000000e+00 +5.00000000000e-01 +2.50000000000e-01 +7.50000000000e-01 +5.00000000000e-01 +0.00000000000e+00 +0.00000000000e+00 +7.50000000000e-01 +2.50000000000e-01 +0.00000000000e+00 +7.50000000000e-01 +0.00000000000e+00 +2.50000000000e-01 +5.00000000000e-01 +2.50000000000e-01 +2.50000000000e-01 +5.00000000000e-01 +1.00000000000e+00 +0.00000000000e+00 +7.50000000000e-01 +1.00000000000e+00 +2.50000000000e-01 +7.50000000000e-01 +7.50000000000e-01 +0.00000000000e+00 +5.00000000000e-01 +7.50000000000e-01 +2.50000000000e-01 +5.00000000000e-01 +1.00000000000e+00 +1.00000000000e+00 +7.50000000000e-01 +7.50000000000e-01 +1.00000000000e+00 +7.50000000000e-01 +1.00000000000e+00 +7.50000000000e-01 +5.00000000000e-01 +7.50000000000e-01 +7.50000000000e-01 +1.00000000000e+00 +0.00000000000e+00 +5.00000000000e-01 +1.00000000000e+00 +2.50000000000e-01 +7.50000000000e-01 +1.00000000000e+00 +2.50000000000e-01 +2.50000000000e-01 +7.50000000000e-01 +2.50000000000e-01 +5.00000000000e-01 +1.00000000000e+00 +5.00000000000e-01 +0.00000000000e+00 +1.00000000000e+00 +7.50000000000e-01 +2.50000000000e-01 +7.50000000000e-01 +5.00000000000e-01 +2.50000000000e-01 +1.00000000000e+00 +1.00000000000e+00 +5.00000000000e-01 +1.00000000000e+00 +7.50000000000e-01 +7.50000000000e-01 +7.50000000000e-01 +7.50000000000e-01 +5.00000000000e-01 +1.00000000000e+00 +5.00000000000e-01 +1.00000000000e+00 +7.50000000000e-01 +5.00000000000e-01 +7.50000000000e-01 +2.50000000000e-01 +5.00000000000e-01 +5.00000000000e-01 +5.00000000000e-01 +5.00000000000e-01 +7.50000000000e-01 +5.00000000000e-01 +2.50000000000e-01 +5.00000000000e-01 +5.00000000000e-01 +5.00000000000e-01 +2.50000000000e-01 +5.00000000000e-01 +7.50000000000e-01 +5.00000000000e-01 +7.50000000000e-01 +5.00000000000e-01 +5.00000000000e-01 + + + + + +2 +0 +12 +9 +15 +16 +17 +18 +19 +20 +0 +1 +12 +8 +21 +22 +16 +23 +24 +25 +1 +3 +12 +11 +26 +27 +22 +28 +29 +30 +3 +2 +12 +13 +31 +17 +27 +32 +33 +34 +2 +6 +9 +13 +35 +36 +18 +33 +37 +38 +0 +4 +8 +9 +39 +40 +23 +19 +41 +42 +1 +5 +11 +8 +43 +44 +28 +24 +45 +46 +3 +7 +13 +11 +47 +48 +32 +29 +49 +50 +6 +4 +9 +10 +51 +41 +36 +52 +53 +54 +4 +5 +8 +10 +55 +45 +40 +53 +56 +57 +5 +7 +11 +10 +58 +49 +44 +56 +59 +60 +7 +6 +13 +10 +61 +37 +48 +59 +52 +62 +12 +9 +13 +2 +20 +38 +34 +17 +18 +33 +12 +8 +9 +0 +25 +42 +20 +16 +23 +19 +12 +11 +8 +1 +30 +46 +25 +22 +28 +24 +12 +13 +11 +3 +34 +50 +30 +27 +32 +29 +10 +13 +9 +6 +62 +38 +54 +52 +37 +36 +10 +9 +8 +4 +54 +42 +57 +53 +41 +40 +10 +8 +11 +5 +57 +46 +60 +56 +45 +44 +10 +11 +13 +7 +60 +50 +62 +59 +49 +48 +12 +13 +9 +14 +34 +38 +20 +63 +64 +65 +12 +9 +8 +14 +20 +42 +25 +63 +65 +66 +12 +8 +11 +14 +25 +46 +30 +63 +66 +67 +12 +11 +13 +14 +30 +50 +34 +63 +67 +64 +10 +9 +13 +14 +54 +38 +62 +68 +65 +64 +10 +8 +9 +14 +57 +42 +54 +68 +66 +65 +10 +11 +8 +14 +60 +46 +57 +68 +67 +66 +10 +13 +11 +14 +62 +50 +60 +68 +64 +67 + + + +10 +20 +30 +40 +50 +60 +70 +80 +90 +100 +110 +120 +130 +140 +150 +160 +170 +180 +190 +200 +210 +220 +230 +240 +250 +260 +270 +280 + + + +24 +24 +24 +24 +24 +24 +24 +24 +24 +24 +24 +24 +24 +24 +24 +24 +24 +24 +24 +24 +24 +24 +24 +24 +24 +24 +24 +24 + + + + + +1 +1 +1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +1 +0 +0 +1 +1 +1 +0 +0 +0 +1 +1 +0 +0 +0 +1 +1 +0 +0 +0 +1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 + + + +0 +0 +0 +0 +1 +1 +1 +1 +0 +0 +1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +1 +1 +1 +0 +1 +1 +0 +1 +1 +0 +1 +0 +0 +0 +0 +0 +0 +0 + + + + + +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 + + + + + + diff --git a/tests/data/tet4.vtu b/tests/data/tet4.vtu new file mode 100644 index 0000000..79bd5a7 --- /dev/null +++ b/tests/data/tet4.vtu @@ -0,0 +1,308 @@ + + + + + + + +0.00000000000e+00 +0.00000000000e+00 +0.00000000000e+00 +0.00000000000e+00 +1.00000000000e+00 +0.00000000000e+00 +0.00000000000e+00 +0.00000000000e+00 +1.00000000000e+00 +0.00000000000e+00 +1.00000000000e+00 +1.00000000000e+00 +1.00000000000e+00 +0.00000000000e+00 +0.00000000000e+00 +1.00000000000e+00 +1.00000000000e+00 +0.00000000000e+00 +1.00000000000e+00 +0.00000000000e+00 +1.00000000000e+00 +1.00000000000e+00 +1.00000000000e+00 +1.00000000000e+00 +5.00000000000e-01 +5.00000000000e-01 +0.00000000000e+00 +5.00000000000e-01 +0.00000000000e+00 +5.00000000000e-01 +1.00000000000e+00 +5.00000000000e-01 +5.00000000000e-01 +5.00000000000e-01 +1.00000000000e+00 +5.00000000000e-01 +0.00000000000e+00 +5.00000000000e-01 +5.00000000000e-01 +5.00000000000e-01 +5.00000000000e-01 +1.00000000000e+00 +5.00000000000e-01 +5.00000000000e-01 +5.00000000000e-01 + + + + + +2 +0 +12 +9 +0 +1 +12 +8 +1 +3 +12 +11 +3 +2 +12 +13 +2 +6 +9 +13 +0 +4 +8 +9 +1 +5 +11 +8 +3 +7 +13 +11 +6 +4 +9 +10 +4 +5 +8 +10 +5 +7 +11 +10 +7 +6 +13 +10 +12 +9 +13 +2 +12 +8 +9 +0 +12 +11 +8 +1 +12 +13 +11 +3 +10 +13 +9 +6 +10 +9 +8 +4 +10 +8 +11 +5 +10 +11 +13 +7 +12 +13 +9 +14 +12 +9 +8 +14 +12 +8 +11 +14 +12 +11 +13 +14 +10 +9 +13 +14 +10 +8 +9 +14 +10 +11 +8 +14 +10 +13 +11 +14 + + + +4 +8 +12 +16 +20 +24 +28 +32 +36 +40 +44 +48 +52 +56 +60 +64 +68 +72 +76 +80 +84 +88 +92 +96 +100 +104 +108 +112 + + + +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 + + + + + +1 +1 +1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +1 +0 +0 + + + +0 +0 +0 +0 +1 +1 +1 +1 +0 +0 +1 +0 +0 +0 +0 + + + + + +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 + + + + + + diff --git a/tests/test_adapt.py b/tests/test_adapt.py index 5b6a8ae..f6ee8e1 100644 --- a/tests/test_adapt.py +++ b/tests/test_adapt.py @@ -66,3 +66,45 @@ def test_lin_to_quad(): mesh_quad.cells[1].data[0, :], [16, 17, 18, 19, 70, 71, 72, 73, 74, 75], ) + + +def test_lin_to_quad_hex8(): + """Testing lin_to_quad for hex elements.""" + _my_script_dir = pathlib.Path(__file__).parent + + mesh = meshio.read(_my_script_dir / "data" / "hex8.vtu") + + mesh_quad = biomesh.adapt.lin_to_quad(mesh) + + # compare with reference mesh + mesh_ref = meshio.read(_my_script_dir / "data" / "hex27.vtu") + np.testing.assert_allclose(mesh_quad.points, mesh_ref.points) + np.testing.assert_allclose(mesh_quad.cells[0].data, mesh_ref.cells[0].data) + + +def test_lin_to_quad_tet4(): + """Testing lin_to_quad for tet elements.""" + _my_script_dir = pathlib.Path(__file__).parent + + mesh = meshio.read(_my_script_dir / "data" / "tet4.vtu") + + mesh_quad = biomesh.adapt.lin_to_quad(mesh) + + # compare with reference mesh + mesh_ref = meshio.read(_my_script_dir / "data" / "tet10.vtu") + np.testing.assert_allclose(mesh_quad.points, mesh_ref.points) + np.testing.assert_allclose(mesh_quad.cells[0].data, mesh_ref.cells[0].data) + + +def test_to_serendipity(): + """Testing to_serendipity for hex elements.""" + _my_script_dir = pathlib.Path(__file__).parent + + mesh = meshio.read(_my_script_dir / "data" / "hex8.vtu") + + mesh_hex20 = biomesh.adapt.to_serendipity(mesh) + + # compare with reference mesh + mesh_ref = meshio.read(_my_script_dir / "data" / "hex20.vtu") + np.testing.assert_allclose(mesh_hex20.points, mesh_ref.points) + np.testing.assert_allclose(mesh_hex20.cells[0].data, mesh_ref.cells[0].data)