Skip to content

feat: VTK filters for mesh-doctor #124

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 32 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
ee78216
Add GenerateRectilinearGrid
alexbenedicto May 9, 2025
cc8e2a5
Add ElementVolumes filter
alexbenedicto May 9, 2025
b88bff7
Add GenerateFractures filter
alexbenedicto May 12, 2025
d32ad33
Add CollocatedNodes filter
alexbenedicto May 13, 2025
bac1a83
Add SupportElements filter but without polyhedron checking due to lac…
alexbenedicto May 15, 2025
f180f8f
To revert
alexbenedicto May 23, 2025
f6bc7f2
Merge remote-tracking branch 'origin/main' into benedicto/feature/vtk…
alexbenedicto Jun 24, 2025
f14cc1b
Keep supported_elements like before merging
alexbenedicto Jun 24, 2025
2f367bb
Update already implemented filters to work after merge
alexbenedicto Jun 24, 2025
0b44584
Temporary commit
alexbenedicto Aug 1, 2025
a9c4f7a
Merge remote-tracking branch 'origin/main' into benedicto/feature/vtk…
alexbenedicto Aug 1, 2025
f68b38d
Add base class for all mesh doctor VTK filters
alexbenedicto Aug 4, 2025
9727b21
Update existing filters with new base class
alexbenedicto Aug 4, 2025
9516825
Fix init for GenerateRectilinearGrid
alexbenedicto Aug 5, 2025
b9d9a78
Add SelfIntersectingElements
alexbenedicto Aug 5, 2025
4838fce
Change __action to mesh_action function for better clarity
alexbenedicto Aug 5, 2025
e7a4134
Change base class names + add MeshDoctorChecks base
alexbenedicto Aug 6, 2025
41ce1a1
Remove MeshDoctorChecks class
alexbenedicto Aug 6, 2025
353abc5
Fix global variable assignation for MESH in supported_elements
alexbenedicto Aug 12, 2025
0009e51
Add AllChecks and MainChecks filters
alexbenedicto Aug 12, 2025
a67d3cb
yapf on mesh-doctor
alexbenedicto Aug 12, 2025
686ff68
Update __doc__ for each filter
alexbenedicto Aug 12, 2025
8a07761
Update .rst documentations
alexbenedicto Aug 12, 2025
ed9843c
Merge remote-tracking branch 'origin/main' into benedicto/feature/vtk…
alexbenedicto Aug 12, 2025
d81951e
Improve displayed results for supported_elements
alexbenedicto Aug 12, 2025
dfe85b2
yapf
alexbenedicto Aug 13, 2025
ce1ca67
Update vtkIO to be more robust, reduce duplication
alexbenedicto Aug 13, 2025
bfe2517
Update mesh_action to only be given vtkUnstructuredGrid
alexbenedicto Aug 14, 2025
f99e42f
Review implementations + yapf
alexbenedicto Aug 14, 2025
71496c6
Fix invalid variable names
alexbenedicto Aug 14, 2025
40abad6
yapf
alexbenedicto Aug 14, 2025
ab17743
Fix docs
alexbenedicto Aug 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/geos-mesh.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ GEOS Mesh tools

./geos_mesh_docs/doctor

./geos_mesh_docs/doctor_filters

./geos_mesh_docs/converter

./geos_mesh_docs/io
Expand Down
61 changes: 54 additions & 7 deletions docs/geos_mesh_docs/doctor.rst
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
Mesh Doctor
---------------
-----------

``mesh-doctor`` is a ``python`` executable that can be used through the command line to perform various checks, validations, and tiny fixes to the ``vtk`` mesh that are meant to be used in ``geos``.
``mesh-doctor`` is organized as a collection of modules with their dedicated sets of options.
The current page will introduce those modules, but the details and all the arguments can be retrieved by using the ``--help`` option for each module.
| ``mesh-doctor`` is a ``python`` executable that can be used through the command line to perform various checks, validations, and tiny fixes to the ``vtkUnstructuredGrid`` mesh that are meant to be used in ``geos``.
``mesh-doctor`` is organized as a collection of modules with their dedicated sets of options.
| The current page will introduce those modules, but the details and all the arguments can be retrieved by using the ``--help`` option for each module.

Prerequisites
^^^^^^^^^^^^^
Expand Down Expand Up @@ -310,8 +310,55 @@ It will also verify that the ``VTK_POLYHEDRON`` cells can effectively get conver
.. code-block::

$ mesh-doctor supported_elements --help
usage: mesh_doctor.py supported_elements [-h] [--chunck_size 1] [--nproc 8]
usage: mesh_doctor.py supported_elements [-h] [--chunk_size 1] [--nproc 8]
options:
-h, --help show this help message and exit
--chunck_size 1 [int]: Defaults chunk size for parallel processing to 1
--nproc 8 [int]: Number of threads used for parallel processing. Defaults to your CPU count 8.
--chunk_size 1 [int]: Defaults chunk size for parallel processing to 1
--nproc 8 [int]: Number of threads used for parallel processing. Defaults to your CPU count 8.


Why only use vtkUnstructuredGrid?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The mesh doctor is designed specifically for unstructured meshes used in GEOS.
| All input files are expected to be ``.vtu`` (VTK Unstructured Grid) format.
| What about other formats?

VTK Hierarchy
"""""""""""""

Supposedly, other grid types that are part of the following VTK hierarchy could be used::

vtkDataObject
└── vtkDataSet
└── vtkCartesianGrid
└── vtkRectilinearGrid
└── vtkImageData
└── vtkStructuredPoints
└── vtkUniformGrid
└── vtkPointSet
└── vtkExplicitStructuredGrid
└── vtkPolyData
└── vtkStructuredGrid
└── vtkUnstructuredGrid

And when looking at specific methods used in mesh-doctor, it could suggest that other formats could be used:

* Points access: mesh.GetPoints() - Available in all vtkPointSet subclasses ✓
* Cell iteration: mesh.GetNumberOfCells(), mesh.GetCell() - Available in all vtkDataSet subclasses ✓
* Cell types: mesh.GetCellType() - Available in all vtkDataSet subclasses ✓
* Cell/Point data: mesh.GetCellData(), mesh.GetPointData() - Available in all vtkDataSet subclasses ✓

VTK Filter Compatibility
""""""""""""""""""""""""

| vtkCellSizeFilter, vtkMeshQuality, and other VTK filters used in the actions expect vtkDataSet or its subclasses
vtkUnstructuredGrid is compatible with all VTK filters used.
| vtkPolyData has a different data structure, not suitable for 3D volumetric meshes.

Specific Operations Require vtkUnstructuredGrid
"""""""""""""""""""""""""""""""""""""""""""""""

* GetCellNeighbors() - Only available in vtkUnstructuredGrid
* GetFaceStream() - Only available in vtkUnstructuredGrid (for polyhedron support)
* GetDistinctCellTypesArray() - Only available in vtkUnstructuredGrid
19 changes: 19 additions & 0 deletions docs/geos_mesh_docs/doctor_filters.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
VTK Filters
===========

In addition to the command-line interface, mesh-doctor functionality is also available as VTK filters for programmatic use in Python. These filters provide the same mesh validation and processing capabilities but can be integrated directly into Python workflows and visualization pipelines.

The VTK filters offer several advantages:

* **Integration**: Easy integration with existing VTK/ParaView workflows
* **Scripting**: Programmatic access for batch processing and automation
* **Visualization**: Direct output suitable for ParaView visualization
* **Flexibility**: Configurable parameters and output options
* **Chaining**: Ability to combine multiple filters in processing pipelines

For detailed documentation on available filters, their parameters, and usage examples, see:

.. toctree::
:maxdepth: 1

filters/index
88 changes: 88 additions & 0 deletions docs/geos_mesh_docs/filters/AllChecks.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
AllChecks Filter
================

.. autoclass:: geos.mesh.doctor.filters.Checks.AllChecks
:members:
:undoc-members:
:show-inheritance:

Overview
--------

The AllChecks filter performs comprehensive mesh validation by running all available quality checks on a vtkUnstructuredGrid. This filter is part of the mesh doctor toolkit and provides detailed analysis of mesh quality, topology, and geometric integrity.

Features
--------

* Comprehensive mesh validation with all available quality checks
* Configurable check parameters for customized validation
* Detailed reporting of found issues
* Integration with mesh doctor parsing system
* Support for both individual check parameter customization and global parameter setting

Usage Example
-------------

.. code-block:: python

from geos.mesh.doctor.filters.Checks import AllChecks

# Instantiate the filter for all available checks
allChecksFilter = AllChecks()

# Set input mesh
allChecksFilter.SetInputData(mesh)

# Optionally customize check parameters
allChecksFilter.setCheckParameter("collocated_nodes", "tolerance", 1e-6)
allChecksFilter.setGlobalParameter("tolerance", 1e-6) # applies to all checks with tolerance parameter

# Execute the checks and get output
output_mesh = allChecksFilter.getGrid()

# Get check results
check_results = allChecksFilter.getCheckResults()

# Write the output mesh
allChecksFilter.writeGrid("output/mesh_with_check_results.vtu")

Parameters
----------

The AllChecks filter supports parameter customization for individual checks:

* **setCheckParameter(check_name, parameter_name, value)**: Set specific parameter for a named check
* **setGlobalParameter(parameter_name, value)**: Apply parameter to all checks that support it

Common parameters include:

* **tolerance**: Distance tolerance for geometric checks (e.g., collocated nodes, non-conformal interfaces)
* **angle_tolerance**: Angular tolerance for orientation checks
* **min_volume**: Minimum acceptable element volume

Available Checks
----------------

The AllChecks filter includes all checks available in the mesh doctor system:

* Collocated nodes detection
* Element volume validation
* Self-intersecting elements detection
* Non-conformal interface detection
* Supported element type validation
* And many more quality checks

Output
------

* **Input**: vtkUnstructuredGrid
* **Output**: vtkUnstructuredGrid (copy of input with potential additional arrays marking issues)
* **Check Results**: Detailed dictionary with results from all performed checks

See Also
--------

* :doc:`MainChecks <MainChecks>` - Subset of most important checks
* :doc:`CollocatedNodes <CollocatedNodes>` - Individual collocated nodes check
* :doc:`ElementVolumes <ElementVolumes>` - Individual element volume check
* :doc:`SelfIntersectingElements <SelfIntersectingElements>` - Individual self-intersection check
131 changes: 131 additions & 0 deletions docs/geos_mesh_docs/filters/CollocatedNodes.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
CollocatedNodes Filter
======================

.. automodule:: geos.mesh.doctor.filters.CollocatedNodes
:members:
:undoc-members:
:show-inheritance:

Overview
--------

The CollocatedNodes filter identifies and handles duplicated/collocated nodes in a vtkUnstructuredGrid. Collocated nodes are nodes that are positioned very close to each other (within a specified tolerance), which can indicate mesh quality issues or modeling problems.

Features
--------

* Detection of collocated/duplicated nodes within specified tolerance
* Identification of elements with wrong support (nodes appearing multiple times)
* Optional marking of problematic elements in output mesh
* Configurable tolerance for distance-based node comparison
* Detailed reporting of found collocated node groups

Usage Example
-------------

.. code-block:: python

from geos.mesh.doctor.filters.CollocatedNodes import CollocatedNodes

# Instantiate the filter
collocatedNodesFilter = CollocatedNodes()

# Set the tolerance for detecting collocated nodes
collocatedNodesFilter.setTolerance(1e-6)

# Optionally enable painting of wrong support elements
collocatedNodesFilter.setPaintWrongSupportElements(1) # 1 to enable, 0 to disable

# Set input mesh
collocatedNodesFilter.SetInputData(mesh)

# Execute the filter and get output
output_mesh = collocatedNodesFilter.getGrid()

# Get results
collocated_buckets = collocatedNodesFilter.getCollocatedNodeBuckets() # list of tuples with collocated node indices
wrong_support_elements = collocatedNodesFilter.getWrongSupportElements() # list of problematic element indices

# Write the output mesh
collocatedNodesFilter.writeGrid("output/mesh_with_collocated_info.vtu")

Parameters
----------

setTolerance(tolerance)
Set the distance tolerance for determining if two nodes are collocated.

* **tolerance** (float): Distance threshold below which nodes are considered collocated
* **Default**: 0.0

setPaintWrongSupportElements(choice)
Enable/disable creation of array marking elements with wrong support nodes.

* **choice** (int): 1 to enable marking, 0 to disable
* **Default**: 0

Results Access
--------------

getCollocatedNodeBuckets()
Returns groups of collocated node indices.

* **Returns**: list[tuple[int]] - Each tuple contains indices of nodes that are collocated

getWrongSupportElements()
Returns element indices that have support nodes appearing more than once.

* **Returns**: list[int] - Element indices with problematic support nodes

Understanding the Results
-------------------------

**Collocated Node Buckets**

Each bucket is a tuple containing node indices that are within the specified tolerance of each other:

.. code-block:: python

# Example result: [(0, 15, 23), (7, 42), (100, 101, 102, 103)]
# This means:
# - Nodes 0, 15, and 23 are collocated
# - Nodes 7 and 42 are collocated
# - Nodes 100, 101, 102, and 103 are collocated

**Wrong Support Elements**

Elements where the same node appears multiple times in the element's connectivity. This usually indicates:

* Degenerate elements
* Mesh generation errors
* Topology problems

Common Use Cases
----------------

* **Mesh Quality Assessment**: Identify potential mesh issues before simulation
* **Mesh Preprocessing**: Clean up meshes by detecting node duplicates
* **Debugging**: Understand why meshes might have connectivity problems
* **Validation**: Ensure mesh meets quality standards for specific applications

Output
------

* **Input**: vtkUnstructuredGrid
* **Output**: vtkUnstructuredGrid with optional arrays marking problematic elements
* **Additional Data**: When painting is enabled, adds "WrongSupportElements" array to cell data

Best Practices
--------------

* Set tolerance based on mesh scale and precision requirements
* Use smaller tolerances for high-precision meshes
* Enable painting to visualize problematic areas in ParaView
* Check both collocated buckets and wrong support elements for comprehensive analysis

See Also
--------

* :doc:`AllChecks <AllChecks>` - Includes collocated nodes check among others
* :doc:`MainChecks <MainChecks>` - Includes collocated nodes check in main set
* :doc:`SelfIntersectingElements <SelfIntersectingElements>` - Related geometric validation
Loading