Skip to content

feat: Perform all mesh-doctor checks at once #100

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 13 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
18 changes: 15 additions & 3 deletions docs/geos-mesh.rst
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
GEOS Mesh tools
====================

**geos-mesh** is a Python package that contains several tools and utilities to handle processing and quality checks of meshes.

.. toctree::
:maxdepth: 5
:maxdepth: 1
:caption: Contents:

./geos_mesh_docs/home.rst
./geos_mesh_docs/doctor

./geos_mesh_docs/converter

./geos_mesh_docs/io

./geos_mesh_docs/model

./geos_mesh_docs/processing

./geos_mesh_docs/stats

./geos_mesh_docs/modules.rst
./geos_mesh_docs/utils
75 changes: 50 additions & 25 deletions docs/geos_mesh_docs/doctor.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,29 @@ Mesh Doctor
``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
^^^^^^^^^^^^^

To use mesh-doctor, you first need to have installed the ``geos-mesh`` package using the following command:

.. code-block:: bash

python -m pip install --upgrade ./geos-mesh

Once done, you can call ``mesh-doctor`` in your command line as presented in the rest of this documentation.

Modules
^^^^^^^

To list all the modules available through ``mesh-doctor``, you can simply use the ``--help`` option, which will list all available modules as well as a quick summary.

.. code-block::

$ python src/geos/mesh/doctor/mesh_doctor.py --help
$ mesh-doctor --help
usage: mesh_doctor.py [-h] [-v] [-q] -i VTK_MESH_FILE
{collocated_nodes,element_volumes,fix_elements_orderings,generate_cube,generate_fractures,generate_global_ids,non_conformal,self_intersecting_elements,supported_elements}
...

Inspects meshes for GEOSX.

positional arguments:
{collocated_nodes,element_volumes,fix_elements_orderings,generate_cube,generate_fractures,generate_global_ids,non_conformal,self_intersecting_elements,supported_elements}
Modules
Expand All @@ -40,14 +49,12 @@ To list all the modules available through ``mesh-doctor``, you can simply use th
Checks if the faces of the elements are self intersecting.
supported_elements
Check that all the elements of the mesh are supported by GEOSX.

options:
-h, --help
show this help message and exit
-v Use -v 'INFO', -vv for 'DEBUG'. Defaults to 'WARNING'.
-q Use -q to reduce the verbosity of the output.
-i VTK_MESH_FILE, --vtk-input-file VTK_MESH_FILE

Note that checks are dynamically loaded.
An option may be missing because of an unloaded module.
Increase verbosity (-v, -vv) to get full information.
Expand All @@ -57,9 +64,8 @@ For example

.. code-block::

$ python src/geos/mesh/doctor/mesh_doctor.py collocated_nodes --help
$ mesh-doctor collocated_nodes --help
usage: mesh_doctor.py collocated_nodes [-h] --tolerance TOLERANCE

options:
-h, --help show this help message and exit
--tolerance TOLERANCE [float]: The absolute distance between two nodes for them to be considered collocated.
Expand All @@ -78,6 +84,34 @@ You can solve this issue by installing the dependencies of ``mesh-doctor`` defin

Here is a list and brief description of all the modules available.

``all_checks``
""""""""""""""

``mesh-doctor`` modules are called ``actions`` and they can be splitted into 2 different categories:
``check actions`` that will give you a feedback on a .vtu mesh that you would like to use in GEOS.
``operate actions`` that will either create a new mesh or modify a mesh.

``all_checks`` aims at applying every single ``check`` action in one single command. The list is the following:
``collocated_nodes``, ``element_volumes``, ``non_conformal``, ``self_intersecting_elements``, ``supported_elements``.

.. code-block::

$ mesh-doctor all_checks --help
usage: mesh-doctor all_checks [-h] [--checks_to_perform CHECKS_TO_PERFORM] [--set_parameters SET_PARAMETERS]

options:
-h, --help show this help message and exit
--checks_to_perform CHECKS_TO_PERFORM
Comma-separated list of mesh-doctor checks to perform. If no input was given, all of the following checks will be executed by default:
['collocated_nodes', 'element_volumes', 'non_conformal', 'self_intersecting_elements', 'supported_elements'].
If you want to choose only certain of them, you can name them individually.
Example: --checks_to_perform collocated_nodes,element_volumes (default: )
--set_parameters SET_PARAMETERS
Comma-separated list of parameters to set for the checks (e.g., 'param_name:value'). These parameters override the defaults.
Default parameters are: For collocated_nodes: tolerance:0.0. For element_volumes: min_volume:0.0. For non_conformal: angle_tolerance:10.0, point_tolerance:0.0, face_tolerance:0.0.
For self_intersecting_elements: min_distance:2.220446049250313e-16. For supported_elements: chunk_size:1, nproc:8.
Example: --set_parameters parameter_name:10.5,other_param:25 (default: )

``collocated_nodes``
""""""""""""""""""""

Expand All @@ -86,9 +120,8 @@ It is not uncommon to define multiple nodes for the exact same position, which w

.. code-block::

$ python src/geos/mesh/doctor/mesh_doctor.py collocated_nodes --help
$ mesh-doctor collocated_nodes --help
usage: mesh_doctor.py collocated_nodes [-h] --tolerance TOLERANCE

options:
-h, --help show this help message and exit
--tolerance TOLERANCE [float]: The absolute distance between two nodes for them to be considered collocated.
Expand All @@ -101,9 +134,8 @@ Cells with negative volumes will typically be an issue for ``geos`` and should b

.. code-block::

$ python src/geos/mesh/doctor/mesh_doctor.py element_volumes --help
$ mesh-doctor element_volumes --help
usage: mesh_doctor.py element_volumes [-h] --min 0.0

options:
-h, --help show this help message and exit
--min 0.0 [float]: The minimum acceptable volume. Defaults to 0.0.
Expand All @@ -117,12 +149,11 @@ This can be convenient if you cannot regenerate the mesh.

.. code-block::

$ python src/geos/mesh/doctor/mesh_doctor.py fix_elements_orderings --help
$ mesh-doctor fix_elements_orderings --help
usage: mesh_doctor.py fix_elements_orderings [-h] [--Hexahedron 1,6,5,4,7,0,2,3] [--Prism5 8,2,0,7,6,9,5,1,4,3]
[--Prism6 11,2,8,10,5,0,9,7,6,1,4,3] [--Pyramid 3,4,0,2,1]
[--Tetrahedron 2,0,3,1] [--Voxel 1,6,5,4,7,0,2,3]
[--Wedge 3,5,4,0,2,1] --output OUTPUT [--data-mode binary, ascii]

options:
-h, --help show this help message and exit
--Hexahedron 1,6,5,4,7,0,2,3
Expand All @@ -148,11 +179,10 @@ This tool can also be useful to generate a trial mesh that will later be refined

.. code-block::

$ python src/geos/mesh/doctor/mesh_doctor.py generate_cube --help
$ mesh-doctor generate_cube --help
usage: mesh_doctor.py generate_cube [-h] [--x 0:1.5:3] [--y 0:5:10] [--z 0:1] [--nx 2:2] [--ny 1:1] [--nz 4]
[--fields name:support:dim [name:support:dim ...]] [--cells] [--no-cells]
[--points] [--no-points] --output OUTPUT [--data-mode binary, ascii]

options:
-h, --help show this help message and exit
--x 0:1.5:3 [list of floats]: X coordinates of the points.
Expand All @@ -179,10 +209,9 @@ The ``generate_fractures`` module will split the mesh and generate the multi-blo

.. code-block::

$ python src/geos/mesh/doctor/mesh_doctor.py generate_fractures --help
$ mesh-doctor generate_fractures --help
usage: mesh_doctor.py generate_fractures [-h] --policy field, internal_surfaces [--name NAME] [--values VALUES] --output OUTPUT
[--data-mode binary, ascii] [--fractures_output_dir FRACTURES_OUTPUT_DIR]

options:
-h, --help show this help message and exit
--policy field, internal_surfaces
Expand Down Expand Up @@ -210,10 +239,9 @@ The ``generate_global_ids`` can generate `global ids` for the imported ``vtk`` m

.. code-block::

$ python src/geos/mesh/doctor/mesh_doctor.py generate_global_ids --help
$ mesh-doctor generate_global_ids --help
usage: mesh_doctor.py generate_global_ids [-h] [--cells] [--no-cells] [--points] [--no-points] --output OUTPUT
[--data-mode binary, ascii]

options:
-h, --help show this help message and exit
--cells [bool]: Generate global ids for cells. Defaults to true.
Expand All @@ -234,10 +262,9 @@ This module can be a bit time consuming.

.. code-block::

$ python src/geos/mesh/doctor/mesh_doctor.py non_conformal --help
$ mesh-doctor non_conformal --help
usage: mesh_doctor.py non_conformal [-h] [--angle_tolerance 10.0] [--point_tolerance POINT_TOLERANCE]
[--face_tolerance FACE_TOLERANCE]

options:
-h, --help show this help message and exit
--angle_tolerance 10.0 [float]: angle tolerance in degrees. Defaults to 10.0
Expand All @@ -254,9 +281,8 @@ This module will display the elements that have faces intersecting.

.. code-block::

$ python src/geos/mesh/doctor/mesh_doctor.py self_intersecting_elements --help
$ mesh-doctor self_intersecting_elements --help
usage: mesh_doctor.py self_intersecting_elements [-h] [--min 2.220446049250313e-16]

options:
-h, --help show this help message and exit
--min 2.220446049250313e-16
Expand All @@ -275,9 +301,8 @@ It will also verify that the ``VTK_POLYHEDRON`` cells can effectively get conver

.. code-block::

$ python src/geos/mesh/doctor/mesh_doctor.py supported_elements --help
$ mesh-doctor supported_elements --help
usage: mesh_doctor.py supported_elements [-h] [--chunck_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
Expand Down
4 changes: 0 additions & 4 deletions docs/geos_mesh_docs/home.rst

This file was deleted.

20 changes: 0 additions & 20 deletions docs/geos_mesh_docs/modules.rst

This file was deleted.

28 changes: 28 additions & 0 deletions geos-mesh/src/geos/mesh/doctor/actions/all_checks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from dataclasses import dataclass
from geos.mesh.doctor.register import __load_module_action
from geos.utils.Logger import getLogger

logger = getLogger( "All_checks" )


@dataclass( frozen=True )
class Options:
checks_to_perform: list[ str ]
checks_options: dict[ str, any ]
check_displays: dict[ str, any ]


@dataclass( frozen=True )
class Result:
check_results: dict[ str, any ]


def action( vtk_input_file: str, options: Options ) -> list[ Result ]:
check_results: dict[ str, any ] = dict()
for check_name in options.checks_to_perform:
check_action = __load_module_action( check_name )
logger.info( f"Performing check '{check_name}'." )
option = options.checks_options[ check_name ]
check_result = check_action( vtk_input_file, option )
check_results[ check_name ] = check_result
return Result( check_results=check_results )
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import logging
import numpy
from dataclasses import dataclass
from tqdm import tqdm
Expand All @@ -7,8 +6,11 @@
from vtkmodules.vtkCommonCore import vtkPoints
from vtkmodules.vtkIOXML import vtkXMLMultiBlockDataReader
from vtkmodules.util.numpy_support import vtk_to_numpy
from geos.mesh.doctor.checks.generate_fractures import Coordinates3D
from geos.mesh.doctor.actions.generate_fractures import Coordinates3D
from geos.mesh.utils.genericHelpers import vtk_iter
from geos.utils.Logger import getLogger

logger = getLogger( "check_fractures" )


@dataclass( frozen=True )
Expand Down Expand Up @@ -113,11 +115,11 @@ def __check_neighbors( matrix: vtkUnstructuredGrid, fracture: vtkUnstructuredGri
if f in fracture_faces:
found += 1
if found != 2:
logging.warning( f"Something went wrong since we should have found 2 fractures faces (we found {found})" +
f" for collocated nodes {cns}." )
logger.warning( f"Something went wrong since we should have found 2 fractures faces (we found {found})" +
f" for collocated nodes {cns}." )


def __check( vtk_input_file: str, options: Options ) -> Result:
def __action( vtk_input_file: str, options: Options ) -> Result:
matrix, fracture = __read_multiblock( vtk_input_file, options.matrix_name, options.fracture_name )
matrix_points: vtkPoints = matrix.GetPoints()
fracture_points: vtkPoints = fracture.GetPoints()
Expand Down Expand Up @@ -148,9 +150,9 @@ def __check( vtk_input_file: str, options: Options ) -> Result:
return Result( errors=errors )


def check( vtk_input_file: str, options: Options ) -> Result:
def action( vtk_input_file: str, options: Options ) -> Result:
try:
return __check( vtk_input_file, options )
return __action( vtk_input_file, options )
except BaseException as e:
logging.error( e )
logger.error( e )
return Result( errors=() )
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
from collections import defaultdict
from dataclasses import dataclass
import logging
import numpy
from typing import Collection, Iterable
from vtkmodules.vtkCommonCore import reference, vtkPoints
from vtkmodules.vtkCommonDataModel import vtkIncrementalOctreePointLocator
from geos.mesh.io.vtkIO import read_mesh
from geos.utils.Logger import getLogger

logger = getLogger( "collocated_nodes" )


@dataclass( frozen=True )
Expand All @@ -19,7 +21,7 @@ class Result:
wrong_support_elements: Collection[ int ] # Element indices with support node indices appearing more than once.


def __check( mesh, options: Options ) -> Result:
def __action( mesh, options: Options ) -> Result:
points = mesh.GetPoints()

locator = vtkIncrementalOctreePointLocator()
Expand All @@ -38,7 +40,7 @@ def __check( mesh, options: Options ) -> Result:
# If it's not inserted, `point_id` contains the node that was already at that location.
# But in that case, `point_id` is the new numbering in the destination points array.
# It's more useful for the user to get the old index in the original mesh, so he can look for it in his data.
logging.debug(
logger.debug(
f"Point {i} at {points.GetPoint(i)} has been rejected, point {filtered_to_original[point_id.get()]} is already inserted."
)
rejected_points[ point_id.get() ].append( i )
Expand All @@ -63,6 +65,6 @@ def __check( mesh, options: Options ) -> Result:
return Result( nodes_buckets=tmp, wrong_support_elements=wrong_support_elements )


def check( vtk_input_file: str, options: Options ) -> Result:
def action( vtk_input_file: str, options: Options ) -> Result:
mesh = read_mesh( vtk_input_file )
return __check( mesh, options )
return __action( mesh, options )
Loading