From 6a9f9ade0302b5a85d915856884813f9d1aff514 Mon Sep 17 00:00:00 2001 From: adtzlr Date: Thu, 21 Apr 2022 22:59:06 +0200 Subject: [PATCH 1/4] add mesh tool triangulate see #201 --- felupe/mesh/__init__.py | 1 + felupe/mesh/_tools.py | 126 +++++++++++++++++++++++++++++++++------- tests/test_mesh.py | 24 ++++++++ 3 files changed, 131 insertions(+), 20 deletions(-) diff --git a/felupe/mesh/__init__.py b/felupe/mesh/__init__.py index d6bfd31c..6b1f3b6d 100644 --- a/felupe/mesh/__init__.py +++ b/felupe/mesh/__init__.py @@ -5,6 +5,7 @@ revolve, sweep, mirror, + triangulate, ) from ._convert import ( convert, diff --git a/felupe/mesh/_tools.py b/felupe/mesh/_tools.py index f69971fd..b3500d4e 100644 --- a/felupe/mesh/_tools.py +++ b/felupe/mesh/_tools.py @@ -43,10 +43,12 @@ def expand(points, cells, cell_type, n=11, z=1): Original point-connectivity of cells. cell_type : str A string in VTK-convention that specifies the cell type. - n : int, optional (default is 11) - Number of n-point repetitions or (n-1)-cell repetitions - z : int, optional (default is 1) - Total expand dimension (edge length in expand direction is z / n) + n : int, optional + Number of n-point repetitions or (n-1)-cell repetitions, + default is 11. + z : int, optional + Total expand dimension (edge length in expand direction is z / n), + default is 1. Returns ------- @@ -102,8 +104,8 @@ def rotate(points, cells, cell_type, angle_deg, axis, center=None): Rotation angle in degree. axis : int Rotation axis. - center : list or ndarray or None, optional (default is None) - Center point coordinates. + center : list or ndarray or None, optional + Center point coordinates (default is None). Returns ------- @@ -143,12 +145,13 @@ def revolve(points, cells, cell_type, n=11, phi=180, axis=0): Original point-connectivity of cells. cell_type : str A string in VTK-convention that specifies the cell type. - n : int, optional (default is 11) - Number of n-point revolutions (or (n-1) cell revolutions). - phi : int, optional (default is 180) - Revolution angle in degree. - axis : int, optional (default is 0) - Revolution axis. + n : int, optional + Number of n-point revolutions (or (n-1) cell revolutions), + default is 11. + phi : int, optional + Revolution angle in degree (default is 180). + axis : int, optional + Revolution axis (default is 0). Returns ------- @@ -206,8 +209,8 @@ def sweep(points, cells, cell_type, decimals=None): Original point-connectivity of cells. cell_type : str A string in VTK-convention that specifies the cell type. - decimals : int or None, optional (default is None) - Number of decimals for point coordinate comparison. + decimals : int or None, optional + Number of decimals for point coordinate comparison (default is None). Returns ------- @@ -257,12 +260,12 @@ def mirror( Original point-connectivity of cells. cell_type : str A string in VTK-convention that specifies the cell type. - normal: list or ndarray, optional (default is [1, 0, 0]) - Mirror-plane normal vector. - centerpoint: list or ndarray, optional (default is [0, 0, 0]) - Center-point coordinates on the mirror plane. - axis: int or None, optional (default is None) - Mirror axis. + normal: list or ndarray, optional + Mirror-plane normal vector (default is [1, 0, 0]). + centerpoint: list or ndarray, optional + Center-point coordinates on the mirror plane (default is [0, 0, 0]). + axis: int or None, optional + Mirror axis (default is None). Returns ------- @@ -310,3 +313,86 @@ def mirror( cells_new[:, face] = cells[:, face[::-1]] return points_new, cells_new, cell_type + + +@mesh_or_data +def triangulate(points, cells, cell_type, mode=3): + """Triangulate a quad or a hex mesh. + + Parameters + ---------- + points : list or ndarray + Original point coordinates. + cells : list or ndarray + Original point-connectivity of cells. + cell_type : str + A string in VTK-convention that specifies the cell type. + mode: int, optional + Choose a mode how to convert hexahedrons to tets [1] (default is 3). + + Returns + ------- + points : ndarray + Modified point coordinates. + cells : ndarray + Modified point-connectivity of cells. + cell_type : str or None + A string in VTK-convention that specifies the cell type. + + References + ---------- + [1] Dompierre, J., Labbé, P., Vallet, M. G., & Camarero, R. (1999). + How to Subdivide Pyramids, Prisms, and Hexahedra into Tetrahedra. + IMR, 99, 195. + """ + + if cell_type == "quad": + + # triangles out of a quad + i = [0, 3] + j = [1, 1] + k = [3, 2] + + cells_new = np.dstack( + ( + cells[:, i], + cells[:, j], + cells[:, k], + ) + ) + + cell_type_new = "triangle" + + elif cell_type == "hexahedron": + + # tets out of a hex + # mode ... no. of diagional through hex-point 6. + if mode == 0: + i = [0, 0, 0, 0, 2] + j = [1, 2, 2, 5, 7] + k = [2, 7, 3, 7, 5] + l = [5, 5, 7, 4, 6] + + elif mode == 3: + i = [0, 0, 0, 0, 1, 1] + j = [2, 3, 7, 5, 5, 6] + k = [3, 7, 4, 6, 6, 2] + l = [6, 6, 6, 4, 0, 0] + + else: + raise NotImplementedError(f"Mode {mode} not implemented.") + + cells_new = np.dstack( + ( + cells[:, i], + cells[:, j], + cells[:, k], + cells[:, l], + ) + ) + + cell_type_new = "tetra" + + cells_new = cells_new.reshape(-1, cells_new.shape[-1]) + + return points, cells_new, cell_type_new diff --git a/tests/test_mesh.py b/tests/test_mesh.py index ac74304c..7cfa0d71 100644 --- a/tests/test_mesh.py +++ b/tests/test_mesh.py @@ -198,6 +198,30 @@ def test_mirror(): assert np.isclose(r.dV.sum(), s.dV.sum()) +def test_triangulate(): + + m = fe.Rectangle(n=3) + n = fe.mesh.triangulate(m) + + rm = fe.RegionQuad(m) + rn = fe.RegionTriangle(n) + + assert np.isclose(rm.dV.sum(), rn.dV.sum()) + + for mode in [0, 3]: + m = fe.Cube(n=3) + n = fe.mesh.triangulate(m) + + rm = fe.RegionHexahedron(m) + rn = fe.RegionTetra(n) + + assert np.isclose(rm.dV.sum(), rn.dV.sum()) + + with pytest.raises(NotImplementedError): + n = fe.mesh.triangulate(m, mode=-1) + + if __name__ == "__main__": test_meshes() test_mirror() + test_triangulate() From f386f2d3e654382a2a2680478218654f78b69109 Mon Sep 17 00:00:00 2001 From: adtzlr Date: Thu, 21 Apr 2022 23:02:59 +0200 Subject: [PATCH 2/4] Update README.md update changelog --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 52c5eda6..e539a503 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,7 @@ All notable changes to this project will be documented in this file. The format - Add `parallel` keyword to constitutive models (`NeoHooke`, `LinearElasticTensorNotation` and `ThreeFieldVariation`). - Add `RegionBoundary` along with template regions for `Quad` and `Hexahedron` and `GaussLegendreBoundary`. - Add optional normal vector argument for function and gradient methods of `AreaChange`. +- Add a new Mesh-tool `triangulate()`, applicable on Quad and Hexahedron meshes. ### Changed - Enforce consistent arguments for functions inside `mesh.tools` (`points, cells, cell_data` or `Mesh`). From f7a9dce03b17da3720791c019d044a1b63f5a99a Mon Sep 17 00:00:00 2001 From: adtzlr Date: Thu, 21 Apr 2022 23:03:07 +0200 Subject: [PATCH 3/4] Update test_mesh.py test mode --- tests/test_mesh.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_mesh.py b/tests/test_mesh.py index 7cfa0d71..04f5b877 100644 --- a/tests/test_mesh.py +++ b/tests/test_mesh.py @@ -210,7 +210,7 @@ def test_triangulate(): for mode in [0, 3]: m = fe.Cube(n=3) - n = fe.mesh.triangulate(m) + n = fe.mesh.triangulate(m, mode=mode) rm = fe.RegionHexahedron(m) rn = fe.RegionTetra(n) From 1656fb7c171fb6271e216ebeb158423f9eae4cb1 Mon Sep 17 00:00:00 2001 From: adtzlr Date: Thu, 21 Apr 2022 23:06:15 +0200 Subject: [PATCH 4/4] update api docs --- docs/felupe/global/region.rst | 2 +- docs/felupe/mesh/mesh.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/felupe/global/region.rst b/docs/felupe/global/region.rst index ecb91a22..5c56bf5f 100644 --- a/docs/felupe/global/region.rst +++ b/docs/felupe/global/region.rst @@ -6,7 +6,7 @@ Region :undoc-members: :inherited-members: -.. .. autoclass:: felupe.RegionBoundary +.. autoclass:: felupe.RegionBoundary :members: :undoc-members: :inherited-members: diff --git a/docs/felupe/mesh/mesh.rst b/docs/felupe/mesh/mesh.rst index 8749050a..ab5ac8a1 100644 --- a/docs/felupe/mesh/mesh.rst +++ b/docs/felupe/mesh/mesh.rst @@ -17,4 +17,4 @@ felupe.mesh :inherited-members: .. automodule:: felupe.mesh - :members: expand, rotate, revolve, sweep, mirror, convert, collect_edges, collect_faces, collect_volumes, add_midpoints_edges, add_midpoints_faces, add_midpoints_volumes \ No newline at end of file + :members: expand, rotate, revolve, sweep, mirror, triangulate, convert, collect_edges, collect_faces, collect_volumes, add_midpoints_edges, add_midpoints_faces, add_midpoints_volumes \ No newline at end of file