Skip to content

Commit 9a3c489

Browse files
mlemayTTEpaloma-martinezalexbenedicto
authored
feat: Add meshing tools and stats (#81)
* Move vtkUtils and multiblockInspectorTreeFunctions + update dependencies * Add SplitMesh filters * Add array transfer from parent to child mesh and tests * add helpers to create mesh with multiple cells * add MeshIdCard class and tests + linting * create vtk filters to compute mesh stats * create Paraview plugins to wrap vtk filters * upgrade github actions * Merge helpers * Addition of data for tests * vtkUtils tests implemented * Reorganize utilities & update paths accordingly * documentation + typing, liniting, formating --------- Co-authored-by: Paloma Martinez <[email protected]> Co-authored-by: alexbenedicto <[email protected]>
1 parent 50b3241 commit 9a3c489

31 files changed

+2356
-74
lines changed

docs/geos_mesh_docs/model.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Model
2+
^^^^^^^
3+
4+
The `model` module of `geos-mesh` package contains data model.
5+
6+
7+
geos.mesh.model.CellTypeCounts filter
8+
--------------------------------------
9+
10+
.. automodule:: geos.mesh.model.CellTypeCounts
11+
:members:
12+
:undoc-members:
13+
:show-inheritance:

docs/geos_mesh_docs/modules.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,10 @@ GEOS Mesh tools
1111

1212
io
1313

14+
model
15+
16+
processing
17+
18+
stats
19+
1420
utils

docs/geos_mesh_docs/processing.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Processing filters
2+
^^^^^^^^^^^^^^^^^^^
3+
4+
The `processing` module of `geos-mesh` package contains filters to process meshes.
5+
6+
7+
geos.mesh.processing.SplitMesh filter
8+
--------------------------------------
9+
10+
.. automodule:: geos.mesh.processing.SplitMesh
11+
:members:
12+
:undoc-members:
13+
:show-inheritance:

docs/geos_mesh_docs/stats.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Mesh stats tools
2+
^^^^^^^^^^^^^^^^
3+
4+
The `stats` module of `geos-mesh` package contains filter to compute statistics on meshes.
5+
6+
7+
geos.mesh.stats.CellTypeCounter filter
8+
--------------------------------------
9+
10+
.. automodule:: geos.mesh.stats.CellTypeCounter
11+
:members:
12+
:undoc-members:
13+
:show-inheritance:

docs/geos_mesh_docs/utils.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Mesh utilities
22
^^^^^^^^^^^^^^^^
33

4-
The `utils` module of `geos-mesh` package contains different utilities methods for VTK meshes.
4+
The `utils` module of `geos-mesh` package contains various utilities for VTK meshes.
55

66

77
geos.mesh.utils.genericHelpers module

geos-mesh/pyproject.toml

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,9 @@ dependencies = [
2929
"networkx >= 2.4",
3030
"tqdm >= 4.67",
3131
"numpy >= 2.2",
32+
"pandas >= 2.2",
3233
"meshio >= 5.3",
33-
"pandas",
34+
"typing_extensions >= 4.12",
3435
]
3536

3637
[project.scripts]
@@ -48,7 +49,8 @@ build = [
4849
"build ~= 1.2"
4950
]
5051
dev = [
51-
"mypy",
52+
"mypy",
53+
"ruff",
5254
"yapf",
5355
]
5456
test = [
@@ -57,7 +59,7 @@ test = [
5759
]
5860

5961
[tool.pytest.ini_options]
60-
addopts="--import-mode=importlib"
62+
addopts = "--import-mode=importlib"
6163
console_output_style = "count"
6264
pythonpath = ["src"]
6365
python_classes = "Test"
@@ -66,7 +68,3 @@ python_functions = "test*"
6668
testpaths = ["tests"]
6769
norecursedirs = "bin"
6870
filterwarnings = []
69-
70-
[tool.coverage.run]
71-
branch = true
72-
source = ["src/geos"]

geos-mesh/src/geos/mesh/doctor/checks/generate_fractures.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
from vtkmodules.util.numpy_support import numpy_to_vtk, vtk_to_numpy
1414
from vtkmodules.util.vtkConstants import VTK_ID_TYPE
1515
from geos.mesh.doctor.checks.vtk_polyhedron import FaceStream
16-
from geos.mesh.utils.arrayHelpers import has_invalid_field
16+
from geos.mesh.utils.arrayHelpers import has_array
17+
1718
from geos.mesh.utils.genericHelpers import to_vtk_id_list, vtk_iter
1819
from geos.mesh.io.vtkIO import VtkOutput, read_mesh, write_mesh
1920
"""
@@ -558,7 +559,7 @@ def check( vtk_input_file: str, options: Options ) -> Result:
558559
try:
559560
mesh = read_mesh( vtk_input_file )
560561
# Mesh cannot contain global ids before splitting.
561-
if has_invalid_field( mesh, [ "GLOBAL_IDS_POINTS", "GLOBAL_IDS_CELLS" ] ):
562+
if has_array( mesh, [ "GLOBAL_IDS_POINTS", "GLOBAL_IDS_CELLS" ] ):
562563
err_msg: str = ( "The mesh cannot contain global ids for neither cells nor points. The correct procedure " +
563564
" is to split the mesh and then generate global ids for new split meshes." )
564565
logging.error( err_msg )

geos-mesh/src/geos/mesh/io/vtkIO.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ def __write_vtu( mesh: vtkUnstructuredGrid, output: str, toBinary: bool = False
160160

161161
def write_mesh( mesh: vtkPointSet, vtk_output: VtkOutput, canOverwrite: bool = False ) -> int:
162162
"""Write mesh to disk.
163+
163164
Nothing is done if file already exists.
164165
165166
Args:
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
# SPDX-FileCopyrightText: Copyright 2023-2024 TotalEnergies.
3+
# SPDX-FileContributor: Antoine Mazuyer, Martin Lemay
4+
import numpy as np
5+
import numpy.typing as npt
6+
from typing_extensions import Self
7+
from vtkmodules.vtkCommonDataModel import ( vtkCellTypes, VTK_TRIANGLE, VTK_QUAD, VTK_TETRA, VTK_VERTEX, VTK_POLYHEDRON,
8+
VTK_POLYGON, VTK_PYRAMID, VTK_HEXAHEDRON, VTK_WEDGE,
9+
VTK_NUMBER_OF_CELL_TYPES )
10+
11+
__doc__ = """
12+
CellTypeCounts stores the number of elements of each type.
13+
"""
14+
15+
16+
class CellTypeCounts():
17+
18+
def __init__( self: Self ) -> None:
19+
"""CellTypeCounts stores the number of cells of each type."""
20+
self._counts: npt.NDArray[ np.int64 ] = np.zeros( VTK_NUMBER_OF_CELL_TYPES, dtype=float )
21+
22+
def __str__( self: Self ) -> str:
23+
"""Overload __str__ method.
24+
25+
Returns:
26+
str: counts as string.
27+
"""
28+
return self.print()
29+
30+
def __add__( self: Self, other: Self ) -> 'CellTypeCounts':
31+
"""Addition operator.
32+
33+
CellTypeCounts addition consists in suming counts.
34+
35+
Args:
36+
other (Self): other CellTypeCounts object
37+
38+
Returns:
39+
Self: new CellTypeCounts object
40+
"""
41+
assert isinstance( other, CellTypeCounts ), "Other object must be a CellTypeCounts."
42+
newCounts: CellTypeCounts = CellTypeCounts()
43+
newCounts._counts = self._counts + other._counts
44+
return newCounts
45+
46+
def addType( self: Self, cellType: int ) -> None:
47+
"""Increment the number of cell of input type.
48+
49+
Args:
50+
cellType (int): cell type
51+
"""
52+
self._counts[ cellType ] += 1
53+
self._updateGeneralCounts( cellType, 1 )
54+
55+
def setTypeCount( self: Self, cellType: int, count: int ) -> None:
56+
"""Set the number of cells of input type.
57+
58+
Args:
59+
cellType (int): cell type
60+
count (int): number of cells
61+
"""
62+
prevCount = self._counts[ cellType ]
63+
self._counts[ cellType ] = count
64+
self._updateGeneralCounts( cellType, count - prevCount )
65+
66+
def getTypeCount( self: Self, cellType: int ) -> int:
67+
"""Get the number of cells of input type.
68+
69+
Args:
70+
cellType (int): cell type
71+
72+
Returns:
73+
int: number of cells
74+
"""
75+
return int( self._counts[ cellType ] )
76+
77+
def _updateGeneralCounts( self: Self, cellType: int, count: int ) -> None:
78+
"""Update generic type counters.
79+
80+
Args:
81+
cellType (int): cell type
82+
count (int): count increment
83+
"""
84+
if ( cellType != VTK_POLYGON ) and ( vtkCellTypes.GetDimension( cellType ) == 2 ):
85+
self._counts[ VTK_POLYGON ] += count
86+
if ( cellType != VTK_POLYHEDRON ) and ( vtkCellTypes.GetDimension( cellType ) == 3 ):
87+
self._counts[ VTK_POLYHEDRON ] += count
88+
89+
def print( self: Self ) -> str:
90+
"""Print counts string.
91+
92+
Returns:
93+
str: counts string.
94+
"""
95+
card: str = ""
96+
card += "| | |\n"
97+
card += "| - | - |\n"
98+
card += f"| **Total Number of Vertices** | {int(self._counts[VTK_VERTEX]):12} |\n"
99+
card += f"| **Total Number of Polygon** | {int(self._counts[VTK_POLYGON]):12} |\n"
100+
card += f"| **Total Number of Polyhedron** | {int(self._counts[VTK_POLYHEDRON]):12} |\n"
101+
card += f"| **Total Number of Cells** | {int(self._counts[VTK_POLYHEDRON]+self._counts[VTK_POLYGON]):12} |\n"
102+
card += "| - | - |\n"
103+
for cellType in ( VTK_TRIANGLE, VTK_QUAD ):
104+
card += f"| **Total Number of {vtkCellTypes.GetClassNameFromTypeId(cellType):<13}** | {int(self._counts[cellType]):12} |\n"
105+
for cellType in ( VTK_TETRA, VTK_PYRAMID, VTK_WEDGE, VTK_HEXAHEDRON ):
106+
card += f"| **Total Number of {vtkCellTypes.GetClassNameFromTypeId(cellType):<13}** | {int(self._counts[cellType]):12} |\n"
107+
return card

0 commit comments

Comments
 (0)