Skip to content

Commit 2635880

Browse files
refactor: mesh-doctor Convert snake_case to camelCase & Update old formatted function docString (#146)
* Convert content of files in geos-mesh from snake case to lower camel case * Update all file names to match camelCase convention * Update .rst doc * Update vtkIO to use vtkXMLGenericDataObjectReader
1 parent ffc89dc commit 2635880

File tree

84 files changed

+4761
-4133
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

84 files changed

+4761
-4133
lines changed

docs/geos_mesh_docs/doctor.rst

Lines changed: 89 additions & 89 deletions
Large diffs are not rendered by default.

geos-mesh/pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ dependencies = [
3939
]
4040

4141
[project.scripts]
42-
mesh-doctor = "geos.mesh.doctor.mesh_doctor:main"
42+
mesh-doctor = "geos.mesh.doctor.meshDoctor:main"
43+
meshDoctor = "geos.mesh.doctor.meshDoctor:main"
4344
convert_abaqus = "geos.mesh.conversion.main:main"
4445

4546
[project.urls]
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
from dataclasses import dataclass
2+
from geos.mesh.doctor.register import __loadModuleAction
3+
from geos.mesh.doctor.parsing.cliParsing import setupLogger
4+
5+
6+
@dataclass( frozen=True )
7+
class Options:
8+
checksToPerform: list[ str ]
9+
checksOptions: dict[ str, any ]
10+
checkDisplays: dict[ str, any ]
11+
12+
13+
@dataclass( frozen=True )
14+
class Result:
15+
checkResults: dict[ str, any ]
16+
17+
18+
def action( vtkInputFile: str, options: Options ) -> list[ Result ]:
19+
checkResults: dict[ str, any ] = dict()
20+
for checkName in options.checksToPerform:
21+
checkAction = __loadModuleAction( checkName )
22+
setupLogger.info( f"Performing check '{checkName}'." )
23+
option = options.checksOptions[ checkName ]
24+
checkResult = checkAction( vtkInputFile, option )
25+
checkResults[ checkName ] = checkResult
26+
return Result( checkResults=checkResults )

geos-mesh/src/geos/mesh/doctor/actions/all_checks.py

Lines changed: 0 additions & 26 deletions
This file was deleted.
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
import numpy
2+
from dataclasses import dataclass
3+
from tqdm import tqdm
4+
from typing import Collection, Iterable, Sequence
5+
from vtkmodules.vtkCommonDataModel import vtkUnstructuredGrid, vtkCell
6+
from vtkmodules.vtkCommonCore import vtkPoints
7+
from vtkmodules.vtkIOXML import vtkXMLMultiBlockDataReader
8+
from vtkmodules.util.numpy_support import vtk_to_numpy
9+
from geos.mesh.doctor.actions.generateFractures import Coordinates3D
10+
from geos.mesh.doctor.parsing.cliParsing import setupLogger
11+
from geos.mesh.utils.genericHelpers import vtkIter
12+
13+
14+
@dataclass( frozen=True )
15+
class Options:
16+
tolerance: float
17+
matrixName: str
18+
fractureName: str
19+
collocatedNodesFieldName: str
20+
21+
22+
@dataclass( frozen=True )
23+
class Result:
24+
# First index is the local index of the fracture mesh.
25+
# Second is the local index of the matrix mesh.
26+
# Third is the global index in the matrix mesh.
27+
errors: Sequence[ tuple[ int, int, int ] ]
28+
29+
30+
def __readMultiblock( vtkInputFile: str, matrixName: str,
31+
fractureName: str ) -> tuple[ vtkUnstructuredGrid, vtkUnstructuredGrid ]:
32+
reader = vtkXMLMultiBlockDataReader()
33+
reader.SetFileName( vtkInputFile )
34+
reader.Update()
35+
multiBlock = reader.GetOutput()
36+
for b in range( multiBlock.GetNumberOfBlocks() ):
37+
blockName: str = multiBlock.GetMetaData( b ).Get( multiBlock.NAME() )
38+
if blockName == matrixName:
39+
matrix: vtkUnstructuredGrid = multiBlock.GetBlock( b )
40+
if blockName == fractureName:
41+
fracture: vtkUnstructuredGrid = multiBlock.GetBlock( b )
42+
assert matrix and fracture
43+
return matrix, fracture
44+
45+
46+
def formatCollocatedNodes( fractureMesh: vtkUnstructuredGrid ) -> Sequence[ Iterable[ int ] ]:
47+
"""Extract the collocated nodes information from the mesh and formats it in a python way.
48+
49+
Args:
50+
fractureMesh (vtkUnstructuredGrid): The mesh of the fracture (with 2d cells).
51+
52+
Returns:
53+
Sequence[ Iterable[ int ] ]: An iterable over all the buckets of collocated nodes.
54+
"""
55+
collocatedNodes: numpy.ndarray = vtk_to_numpy( fractureMesh.GetPointData().GetArray( "collocatedNodes" ) )
56+
if len( collocatedNodes.shape ) == 1:
57+
collocatedNodes: numpy.ndarray = collocatedNodes.reshape( ( collocatedNodes.shape[ 0 ], 1 ) )
58+
generator = ( tuple( sorted( bucket[ bucket > -1 ] ) ) for bucket in collocatedNodes )
59+
return tuple( generator )
60+
61+
62+
def __checkCollocatedNodesPositions(
63+
matrixPoints: Sequence[ Coordinates3D ], fracturePoints: Sequence[ Coordinates3D ], g2l: Sequence[ int ],
64+
collocatedNodes: Iterable[ Iterable[ int ] ]
65+
) -> Collection[ tuple[ int, Iterable[ int ], Iterable[ Coordinates3D ] ] ]:
66+
issues = []
67+
for li, bucket in enumerate( collocatedNodes ):
68+
matrix_nodes = ( fracturePoints[ li ], ) + tuple( map( lambda gi: matrixPoints[ g2l[ gi ] ], bucket ) )
69+
m = numpy.array( matrix_nodes )
70+
rank: int = numpy.linalg.matrix_rank( m )
71+
if rank > 1:
72+
issues.append( ( li, bucket, tuple( map( lambda gi: matrixPoints[ g2l[ gi ] ], bucket ) ) ) )
73+
return issues
74+
75+
76+
def myIter( ccc ):
77+
car, cdr = ccc[ 0 ], ccc[ 1: ]
78+
for i in car:
79+
if cdr:
80+
for j in myIter( cdr ):
81+
yield i, *j
82+
else:
83+
yield ( i, )
84+
85+
86+
def __checkNeighbors( matrix: vtkUnstructuredGrid, fracture: vtkUnstructuredGrid, g2l: Sequence[ int ],
87+
collocatedNodes: Sequence[ Iterable[ int ] ] ):
88+
fractureNodes: set[ int ] = set()
89+
for bucket in collocatedNodes:
90+
for gi in bucket:
91+
fractureNodes.add( g2l[ gi ] )
92+
# For each face of each cell,
93+
# if all the points of the face are "made" of collocated nodes,
94+
# then this is a fracture face.
95+
fractureFaces: set[ frozenset[ int ] ] = set()
96+
for c in range( matrix.GetNumberOfCells() ):
97+
cell: vtkCell = matrix.GetCell( c )
98+
for f in range( cell.GetNumberOfFaces() ):
99+
face: vtkCell = cell.GetFace( f )
100+
pointIds = frozenset( vtkIter( face.GetPointIds() ) )
101+
if pointIds <= fractureNodes:
102+
fractureFaces.add( pointIds )
103+
# Finding the cells
104+
for c in tqdm( range( fracture.GetNumberOfCells() ), desc="Finding neighbor cell pairs" ):
105+
cell: vtkCell = fracture.GetCell( c )
106+
cns: set[ frozenset[ int ] ] = set() # subset of collocatedNodes
107+
pointIds = frozenset( vtkIter( cell.GetPointIds() ) )
108+
for pointId in pointIds:
109+
bucket = collocatedNodes[ pointId ]
110+
localBucket = frozenset( map( g2l.__getitem__, bucket ) )
111+
cns.add( localBucket )
112+
found = 0
113+
tmp = tuple( map( tuple, cns ) )
114+
for nodeCombinations in myIter( tmp ):
115+
f = frozenset( nodeCombinations )
116+
if f in fractureFaces:
117+
found += 1
118+
if found != 2:
119+
setupLogger.warning( "Something went wrong since we should have found 2 fractures faces (we found" +
120+
f" {found}) for collocated nodes {cns}." )
121+
122+
123+
def __action( vtkInputFile: str, options: Options ) -> Result:
124+
matrix, fracture = __readMultiblock( vtkInputFile, options.matrixName, options.fractureName )
125+
matrixPoints: vtkPoints = matrix.GetPoints()
126+
fracturePoints: vtkPoints = fracture.GetPoints()
127+
128+
collocatedNodes: Sequence[ Iterable[ int ] ] = formatCollocatedNodes( fracture )
129+
assert matrix.GetPointData().GetGlobalIds() and matrix.GetCellData().GetGlobalIds() and \
130+
fracture.GetPointData().GetGlobalIds() and fracture.GetCellData().GetGlobalIds()
131+
132+
pointIds = vtk_to_numpy( matrix.GetPointData().GetGlobalIds() )
133+
g2l = numpy.ones( len( pointIds ), dtype=int ) * -1
134+
for loc, glo in enumerate( pointIds ):
135+
g2l[ glo ] = loc
136+
g2l.flags.writeable = False
137+
138+
issues = __checkCollocatedNodesPositions( vtk_to_numpy( matrix.GetPoints().GetData() ),
139+
vtk_to_numpy( fracture.GetPoints().GetData() ), g2l, collocatedNodes )
140+
assert len( issues ) == 0
141+
142+
__checkNeighbors( matrix, fracture, g2l, collocatedNodes )
143+
144+
errors = []
145+
for i, duplicates in enumerate( collocatedNodes ):
146+
for duplicate in filter( lambda i: i > -1, duplicates ):
147+
p0 = matrixPoints.GetPoint( g2l[ duplicate ] )
148+
p1 = fracturePoints.GetPoint( i )
149+
if numpy.linalg.norm( numpy.array( p1 ) - numpy.array( p0 ) ) > options.tolerance:
150+
errors.append( ( i, g2l[ duplicate ], duplicate ) )
151+
return Result( errors=errors )
152+
153+
154+
def action( vtkInputFile: str, options: Options ) -> Result:
155+
try:
156+
return __action( vtkInputFile, options )
157+
except BaseException as e:
158+
setupLogger.error( e )
159+
return Result( errors=() )

geos-mesh/src/geos/mesh/doctor/actions/check_fractures.py

Lines changed: 0 additions & 156 deletions
This file was deleted.

0 commit comments

Comments
 (0)