From d61b9207500a41671d1012056a757ce8ab32586d Mon Sep 17 00:00:00 2001 From: DENEL Bertrand Date: Tue, 3 Feb 2026 11:50:32 -0600 Subject: [PATCH 01/10] Draft --- .../mesh_doctor/actions/generateFractures.py | 35 +++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py b/mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py index e818ebd8..3c387834 100644 --- a/mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py +++ b/mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py @@ -433,6 +433,38 @@ def __performSplit( oldMesh: vtkUnstructuredGrid, cellToNodeMapping: Mapping[ in collocatedNodes[ o ] = i collocatedNodes.flags.writeable = False + # For each 2D cell, find its adjacent 3D cell and copy the node mapping + setupLogger.info("Building 2D cell mappings from adjacent 3D cells...") + cell_2d_to_mapping: dict[ int, dict[ int, int ] ] = {} + + for c in tqdm( range( oldMesh.GetNumberOfCells() ), desc="Matching 2D to 3D cells" ): + cell: vtkCell = oldMesh.GetCell( c ) + if cell.GetCellDimension() != 2: + continue + + # Get the point IDs of this 2D cell + pointIds = cell.GetPointIds() + + # Find a 3D cell neighbor + neighborIds = vtkIdList() + oldMesh.GetCellNeighbors( c, pointIds, neighborIds ) + + # Use the first 3D neighbor's mapping + for i in range( neighborIds.GetNumberOfIds() ): + neighborId = neighborIds.GetId( i ) + neighborCell = oldMesh.GetCell( neighborId ) + if neighborCell.GetCellDimension() == 3: + # This 3D cell has a mapping - use it for the 2D cell + if neighborId in cellToNodeMapping: + cell_2d_to_mapping[ c ] = cellToNodeMapping[ neighborId ] + break + + setupLogger.info(f"Found mappings for {len(cell_2d_to_mapping)} 2D cells") + + # Merge 2D mappings into main mapping + combined_mapping = dict( cellToNodeMapping ) + combined_mapping.update( cell_2d_to_mapping ) + # We are creating a new mesh. # The cells will be the same, except that their nodes may be duplicated or renumbered nodes. # In vtk, the polyhedron and the standard cells are managed differently. @@ -446,7 +478,7 @@ def __performSplit( oldMesh: vtkUnstructuredGrid, cellToNodeMapping: Mapping[ in newMesh.Allocate( oldMesh.GetNumberOfCells() ) for c in tqdm( range( oldMesh.GetNumberOfCells() ), desc="Performing the mesh split" ): - cellNodeMapping: IDMapping = cellToNodeMapping.get( c, {} ) + cellNodeMapping: IDMapping = combined_mapping.get( c, {} ) cell: vtkCell = oldMesh.GetCell( c ) cellType: int = cell.GetCellType() # For polyhedron, we'll manipulate the face stream directly. @@ -475,7 +507,6 @@ def __performSplit( oldMesh: vtkUnstructuredGrid, cellToNodeMapping: Mapping[ in return newMesh - def __generateFractureMesh( oldMesh: vtkUnstructuredGrid, fractureInfo: FractureInfo, cellToNodeMapping: Mapping[ int, IDMapping ] ) -> vtkUnstructuredGrid: """Generates the mesh of the fracture. From a09792f4cb0644e54b0b74ad913760e9b0fef853 Mon Sep 17 00:00:00 2001 From: DENEL Bertrand Date: Tue, 3 Feb 2026 12:13:16 -0600 Subject: [PATCH 02/10] Fixed syntax --- .../src/geos/mesh_doctor/actions/generateFractures.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py b/mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py index 3c387834..06191dc8 100644 --- a/mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py +++ b/mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py @@ -438,12 +438,12 @@ def __performSplit( oldMesh: vtkUnstructuredGrid, cellToNodeMapping: Mapping[ in cell_2d_to_mapping: dict[ int, dict[ int, int ] ] = {} for c in tqdm( range( oldMesh.GetNumberOfCells() ), desc="Matching 2D to 3D cells" ): - cell: vtkCell = oldMesh.GetCell( c ) - if cell.GetCellDimension() != 2: + cell2d: vtkCell = oldMesh.GetCell( c ) + if cell2d.GetCellDimension() != 2: continue # Get the point IDs of this 2D cell - pointIds = cell.GetPointIds() + pointIds = cell2d.GetPointIds() # Find a 3D cell neighbor neighborIds = vtkIdList() @@ -456,7 +456,7 @@ def __performSplit( oldMesh: vtkUnstructuredGrid, cellToNodeMapping: Mapping[ in if neighborCell.GetCellDimension() == 3: # This 3D cell has a mapping - use it for the 2D cell if neighborId in cellToNodeMapping: - cell_2d_to_mapping[ c ] = cellToNodeMapping[ neighborId ] + cell_2d_to_mapping[ c ] = dict( cellToNodeMapping[ neighborId ] ) break setupLogger.info(f"Found mappings for {len(cell_2d_to_mapping)} 2D cells") From 0393bbca2b2a5a59b4946563f471011e14f1a2c9 Mon Sep 17 00:00:00 2001 From: DENEL Bertrand Date: Tue, 3 Feb 2026 13:16:11 -0600 Subject: [PATCH 03/10] Ruff --- .../geos/mesh_doctor/actions/generateFractures.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py b/mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py index 06191dc8..e33de737 100644 --- a/mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py +++ b/mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py @@ -436,19 +436,19 @@ def __performSplit( oldMesh: vtkUnstructuredGrid, cellToNodeMapping: Mapping[ in # For each 2D cell, find its adjacent 3D cell and copy the node mapping setupLogger.info("Building 2D cell mappings from adjacent 3D cells...") cell_2d_to_mapping: dict[ int, dict[ int, int ] ] = {} - + for c in tqdm( range( oldMesh.GetNumberOfCells() ), desc="Matching 2D to 3D cells" ): cell2d: vtkCell = oldMesh.GetCell( c ) if cell2d.GetCellDimension() != 2: continue - + # Get the point IDs of this 2D cell pointIds = cell2d.GetPointIds() - + # Find a 3D cell neighbor neighborIds = vtkIdList() oldMesh.GetCellNeighbors( c, pointIds, neighborIds ) - + # Use the first 3D neighbor's mapping for i in range( neighborIds.GetNumberOfIds() ): neighborId = neighborIds.GetId( i ) @@ -458,9 +458,9 @@ def __performSplit( oldMesh: vtkUnstructuredGrid, cellToNodeMapping: Mapping[ in if neighborId in cellToNodeMapping: cell_2d_to_mapping[ c ] = dict( cellToNodeMapping[ neighborId ] ) break - + setupLogger.info(f"Found mappings for {len(cell_2d_to_mapping)} 2D cells") - + # Merge 2D mappings into main mapping combined_mapping = dict( cellToNodeMapping ) combined_mapping.update( cell_2d_to_mapping ) From 6798c754d2233505549f794ef4f000f5016193f9 Mon Sep 17 00:00:00 2001 From: DENEL Bertrand Date: Tue, 3 Feb 2026 15:40:41 -0600 Subject: [PATCH 04/10] yapf --- .../src/geos/mesh_doctor/actions/generateFractures.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py b/mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py index e33de737..ef139093 100644 --- a/mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py +++ b/mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py @@ -434,7 +434,7 @@ def __performSplit( oldMesh: vtkUnstructuredGrid, cellToNodeMapping: Mapping[ in collocatedNodes.flags.writeable = False # For each 2D cell, find its adjacent 3D cell and copy the node mapping - setupLogger.info("Building 2D cell mappings from adjacent 3D cells...") + setupLogger.info( "Building 2D cell mappings from adjacent 3D cells..." ) cell_2d_to_mapping: dict[ int, dict[ int, int ] ] = {} for c in tqdm( range( oldMesh.GetNumberOfCells() ), desc="Matching 2D to 3D cells" ): @@ -459,7 +459,7 @@ def __performSplit( oldMesh: vtkUnstructuredGrid, cellToNodeMapping: Mapping[ in cell_2d_to_mapping[ c ] = dict( cellToNodeMapping[ neighborId ] ) break - setupLogger.info(f"Found mappings for {len(cell_2d_to_mapping)} 2D cells") + setupLogger.info( f"Found mappings for {len(cell_2d_to_mapping)} 2D cells" ) # Merge 2D mappings into main mapping combined_mapping = dict( cellToNodeMapping ) @@ -507,6 +507,7 @@ def __performSplit( oldMesh: vtkUnstructuredGrid, cellToNodeMapping: Mapping[ in return newMesh + def __generateFractureMesh( oldMesh: vtkUnstructuredGrid, fractureInfo: FractureInfo, cellToNodeMapping: Mapping[ int, IDMapping ] ) -> vtkUnstructuredGrid: """Generates the mesh of the fracture. From d959a57f4c76951e52bbd53419adac3cc5625293 Mon Sep 17 00:00:00 2001 From: Bertrand Denel <120652669+bd713@users.noreply.github.com> Date: Wed, 4 Feb 2026 10:08:25 -0800 Subject: [PATCH 05/10] Update mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py Co-authored-by: Jacques Franc <49998870+jafranc@users.noreply.github.com> --- mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py b/mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py index ef139093..27843063 100644 --- a/mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py +++ b/mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py @@ -456,7 +456,7 @@ def __performSplit( oldMesh: vtkUnstructuredGrid, cellToNodeMapping: Mapping[ in if neighborCell.GetCellDimension() == 3: # This 3D cell has a mapping - use it for the 2D cell if neighborId in cellToNodeMapping: - cell_2d_to_mapping[ c ] = dict( cellToNodeMapping[ neighborId ] ) + cell2dToMapping[ c ] = dict( cellToNodeMapping[ neighborId ] ) break setupLogger.info( f"Found mappings for {len(cell_2d_to_mapping)} 2D cells" ) From 2097ba404440358c8463e91a6b6402ba274892d8 Mon Sep 17 00:00:00 2001 From: Bertrand Denel <120652669+bd713@users.noreply.github.com> Date: Wed, 4 Feb 2026 10:08:43 -0800 Subject: [PATCH 06/10] Update mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py Co-authored-by: Jacques Franc <49998870+jafranc@users.noreply.github.com> --- mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py b/mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py index 27843063..4a579bb3 100644 --- a/mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py +++ b/mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py @@ -459,7 +459,7 @@ def __performSplit( oldMesh: vtkUnstructuredGrid, cellToNodeMapping: Mapping[ in cell2dToMapping[ c ] = dict( cellToNodeMapping[ neighborId ] ) break - setupLogger.info( f"Found mappings for {len(cell_2d_to_mapping)} 2D cells" ) + setupLogger.info( f"Found mappings for {len(cell2dToMapping)} 2D cells" ) # Merge 2D mappings into main mapping combined_mapping = dict( cellToNodeMapping ) From e09c95747f4033e79fc5cafbcf1477e3afb80254 Mon Sep 17 00:00:00 2001 From: Bertrand Denel <120652669+bd713@users.noreply.github.com> Date: Wed, 4 Feb 2026 10:09:20 -0800 Subject: [PATCH 07/10] Update mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py Co-authored-by: paloma-martinez <104762252+paloma-martinez@users.noreply.github.com> --- mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py b/mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py index 4a579bb3..9506aad0 100644 --- a/mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py +++ b/mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py @@ -462,7 +462,7 @@ def __performSplit( oldMesh: vtkUnstructuredGrid, cellToNodeMapping: Mapping[ in setupLogger.info( f"Found mappings for {len(cell2dToMapping)} 2D cells" ) # Merge 2D mappings into main mapping - combined_mapping = dict( cellToNodeMapping ) + combinedMapping = dict( cellToNodeMapping ) combined_mapping.update( cell_2d_to_mapping ) # We are creating a new mesh. From 7fe1099e51650c61d1f6943c53e0817421086641 Mon Sep 17 00:00:00 2001 From: Bertrand Denel <120652669+bd713@users.noreply.github.com> Date: Wed, 4 Feb 2026 10:09:32 -0800 Subject: [PATCH 08/10] Update mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py Co-authored-by: Jacques Franc <49998870+jafranc@users.noreply.github.com> --- mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py b/mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py index 9506aad0..d3d849c1 100644 --- a/mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py +++ b/mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py @@ -435,7 +435,7 @@ def __performSplit( oldMesh: vtkUnstructuredGrid, cellToNodeMapping: Mapping[ in # For each 2D cell, find its adjacent 3D cell and copy the node mapping setupLogger.info( "Building 2D cell mappings from adjacent 3D cells..." ) - cell_2d_to_mapping: dict[ int, dict[ int, int ] ] = {} + cell2dToMapping: dict[ int, dict[ int, int ] ] = {} for c in tqdm( range( oldMesh.GetNumberOfCells() ), desc="Matching 2D to 3D cells" ): cell2d: vtkCell = oldMesh.GetCell( c ) From 3014248ed0fcd4d2f16d708ed31ae677faf495ee Mon Sep 17 00:00:00 2001 From: Bertrand Denel <120652669+bd713@users.noreply.github.com> Date: Wed, 4 Feb 2026 10:09:52 -0800 Subject: [PATCH 09/10] Update mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py Co-authored-by: Jacques Franc <49998870+jafranc@users.noreply.github.com> --- mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py b/mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py index d3d849c1..dd3a89dd 100644 --- a/mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py +++ b/mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py @@ -463,7 +463,7 @@ def __performSplit( oldMesh: vtkUnstructuredGrid, cellToNodeMapping: Mapping[ in # Merge 2D mappings into main mapping combinedMapping = dict( cellToNodeMapping ) - combined_mapping.update( cell_2d_to_mapping ) + combinedMapping.update( cell2dToMapping ) # We are creating a new mesh. # The cells will be the same, except that their nodes may be duplicated or renumbered nodes. From 8ed360b384db90874a49082b8f3c11c897bcb662 Mon Sep 17 00:00:00 2001 From: DENEL Bertrand Date: Wed, 4 Feb 2026 13:12:04 -0600 Subject: [PATCH 10/10] Filtered mapping to 2d nodes --- .../mesh_doctor/actions/generateFractures.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py b/mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py index dd3a89dd..a243198d 100644 --- a/mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py +++ b/mesh-doctor/src/geos/mesh_doctor/actions/generateFractures.py @@ -453,10 +453,18 @@ def __performSplit( oldMesh: vtkUnstructuredGrid, cellToNodeMapping: Mapping[ in for i in range( neighborIds.GetNumberOfIds() ): neighborId = neighborIds.GetId( i ) neighborCell = oldMesh.GetCell( neighborId ) - if neighborCell.GetCellDimension() == 3: + + if neighborCell.GetCellDimension() == 3 and neighborId in cellToNodeMapping: # This 3D cell has a mapping - use it for the 2D cell - if neighborId in cellToNodeMapping: - cell2dToMapping[ c ] = dict( cellToNodeMapping[ neighborId ] ) + # Get the 2D cell's point IDs + cell2dPointIds = set( vtkIter( pointIds ) ) + + # Only copy mappings for nodes that belong to the 2D cell + neighborMapping = cellToNodeMapping[ neighborId ] + cell2dToMapping[ c ] = { + node: newNode + for node, newNode in neighborMapping.items() if node in cell2dPointIds + } break setupLogger.info( f"Found mappings for {len(cell2dToMapping)} 2D cells" ) @@ -478,7 +486,7 @@ def __performSplit( oldMesh: vtkUnstructuredGrid, cellToNodeMapping: Mapping[ in newMesh.Allocate( oldMesh.GetNumberOfCells() ) for c in tqdm( range( oldMesh.GetNumberOfCells() ), desc="Performing the mesh split" ): - cellNodeMapping: IDMapping = combined_mapping.get( c, {} ) + cellNodeMapping: IDMapping = combinedMapping.get( c, {} ) cell: vtkCell = oldMesh.GetCell( c ) cellType: int = cell.GetCellType() # For polyhedron, we'll manipulate the face stream directly.