Skip to content

Commit 8f73cbd

Browse files
committed
add hanging node tests before writing mesh to file
1 parent 6d06b51 commit 8f73cbd

File tree

2 files changed

+109
-16
lines changed

2 files changed

+109
-16
lines changed

tools/python_utils/geom_util.py

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -71,15 +71,15 @@ def get_ref_triangle_points(center, radius, add_center = False):
7171
7272
Reference triangle:
7373
74-
+ v2
75-
| \
76-
| \
77-
| \
78-
| o + v1
79-
| /
80-
| /
81-
| /
82-
+ v3
74+
# + v2
75+
# | \
76+
# | \
77+
# | \
78+
# | o + v1
79+
# | /
80+
# | /
81+
# | /
82+
# + v3
8383
8484
Radius: o-v1
8585
Axis vector: o-v1
@@ -378,4 +378,39 @@ def gmsh_translate(xc):
378378
new_coord = old_coord + translation_vector
379379
# Handle paramCoord properly - use empty list if paramCoord is None or empty
380380
param = paramCoord[3*i:3*(i+1)] if paramCoord is not None and len(paramCoord) > 0 else []
381-
gmsh.model.mesh.setNode(nodeTag, new_coord, param)
381+
gmsh.model.mesh.setNode(nodeTag, new_coord, param)
382+
383+
def check_hanging_nodes():
384+
"""Check for hanging/orphan nodes in the GMSH mesh that are not connected to any elements.
385+
386+
Returns:
387+
-------
388+
list
389+
List of node tags that are hanging (not connected to any elements)
390+
bool
391+
True if hanging nodes were found, False otherwise
392+
"""
393+
# Get all nodes in the mesh
394+
all_node_tags, _, _ = gmsh.model.mesh.getNodes()
395+
all_node_tags = set(all_node_tags)
396+
397+
# Get all nodes that are part of elements
398+
connected_nodes = set()
399+
400+
# Iterate through all entities in the model
401+
for entity in gmsh.model.getEntities():
402+
# Get elements for this entity
403+
elem_types, elem_tags, elem_node_tags = gmsh.model.mesh.getElements(entity[0], entity[1])
404+
405+
# Add all nodes from elements to connected set
406+
for nodes in elem_node_tags:
407+
connected_nodes.update(nodes)
408+
409+
# Find hanging nodes (nodes that exist but aren't in any elements)
410+
hanging_nodes = list(all_node_tags - connected_nodes)
411+
412+
has_hanging = len(hanging_nodes) > 0
413+
if has_hanging:
414+
print(f"Warning: Found {len(hanging_nodes)} hanging nodes with tags: {hanging_nodes}")
415+
416+
return hanging_nodes, has_hanging

tools/python_utils/gmsh_particles.py

Lines changed: 64 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from geom_util import *
99

1010

11+
1112
def circle_mesh_symmetric(xc = [0., 0., 0.], r = 1., h = 0.1, filename = 'mesh', vtk_out = False, symmetric_mesh = True):
1213
"""
1314
Create a circular mesh, either symmetric or full.
@@ -78,6 +79,9 @@ def circle_mesh_symmetric(xc = [0., 0., 0.], r = 1., h = 0.1, filename = 'mesh',
7879
# generate mesh
7980
gmsh.model.mesh.generate(3)
8081

82+
# Check for hanging nodes before writing
83+
check_hanging_nodes()
84+
8185
# write
8286
gmsh.write(filename + '.msh')
8387
if vtk_out:
@@ -158,6 +162,9 @@ def ellipse_mesh_symmetric(xc = [0., 0., 0.], rx = 1., ry = 0.5, h = 0.1, filena
158162
# generate mesh
159163
gmsh.model.mesh.generate(3)
160164

165+
# Check for hanging nodes before writing
166+
check_hanging_nodes()
167+
161168
# Write output files
162169
gmsh.write(filename + '.msh')
163170
if vtk_out:
@@ -243,6 +250,9 @@ def sphere_mesh_symmetric(xc = [0., 0., 0.], r = 1., h = 0.1, filename = 'mesh',
243250
# Generate 3D mesh
244251
gmsh.model.mesh.generate(3)
245252

253+
# Check for hanging nodes before writing
254+
check_hanging_nodes()
255+
246256
# Write output files
247257
gmsh.write(filename + '.msh')
248258
if vtk_out:
@@ -328,6 +338,9 @@ def rectangle_mesh_symmetric(xc = [0., 0., 0.], Lx = 1., Ly = 1., h = 0.1, filen
328338
# generate mesh
329339
gmsh.model.mesh.generate(3)
330340

341+
# Check for hanging nodes before writing
342+
check_hanging_nodes()
343+
331344
# write
332345
gmsh.write(filename + '.msh')
333346
if vtk_out:
@@ -409,6 +422,9 @@ def hexagon_mesh_symmetric(xc = [0., 0., 0.], r = 1., h = 0.1, filename = 'mesh'
409422
# generate mesh
410423
gmsh.model.mesh.generate(3)
411424

425+
# Check for hanging nodes before writing
426+
check_hanging_nodes()
427+
412428
# Write output files
413429
gmsh.write(filename + '.msh')
414430
if vtk_out:
@@ -497,6 +513,9 @@ def drum2d_mesh_symmetric(xc = [0., 0., 0.], r = 1., width = 1., h = 0.1, filena
497513
# generate mesh
498514
gmsh.model.mesh.generate(3)
499515

516+
# Check for hanging nodes before writing
517+
check_hanging_nodes()
518+
500519
# Write output files
501520
gmsh.write(filename + '.msh')
502521
if vtk_out:
@@ -565,6 +584,9 @@ def polygon_mesh_symmetric(points, theta, xc=[0., 0., 0.], h=0.1, filename='mesh
565584

566585
# Translate to final position if needed
567586
gmsh_translate(xc)
587+
588+
# Check for hanging nodes before writing
589+
check_hanging_nodes()
568590

569591
# Write output files
570592
gmsh.write(filename + '.msh')
@@ -636,10 +658,18 @@ def cylindrical2d_wall_mesh(center=[0., 0., 0.], outer_radius=1.0, inner_radius=
636658
# Create surface with hole
637659
s1 = gmsh.model.geo.addPlaneSurface([outer_loop, inner_loop])
638660

639-
# Synchronize and generate mesh
661+
# Synchronize geometry before adding physical groups
640662
gmsh.model.geo.synchronize()
663+
664+
# Add physical group for the surface
665+
gmsh.model.addPhysicalGroup(2, [s1], 1)
666+
667+
# Generate mesh
641668
gmsh.model.mesh.generate(2)
642669

670+
# Check for hanging nodes before writing
671+
check_hanging_nodes()
672+
643673
# Write output files
644674
gmsh.write(filename + '.msh')
645675
if vtk_out:
@@ -729,6 +759,9 @@ def triangle_mesh_symmetric(xc=[0., 0., 0.], r=1., h=0.1, filename='mesh', vtk_o
729759
# Generate mesh
730760
gmsh.model.mesh.generate(3)
731761

762+
# Check for hanging nodes before writing
763+
check_hanging_nodes()
764+
732765
# Write output files
733766
gmsh.write(filename + '.msh')
734767
if vtk_out:
@@ -807,6 +840,9 @@ def cuboid_mesh_symmetric(xc = [0., 0., 0.], Lx = 1., Ly = 1., Lz = 1., h = 0.1,
807840
# Generate 3D mesh
808841
gmsh.model.mesh.generate(3)
809842

843+
# Check for hanging nodes before writing
844+
check_hanging_nodes()
845+
810846
# Write output files
811847
gmsh.write(filename + '.msh')
812848
if vtk_out:
@@ -891,6 +927,9 @@ def ellipsoid_mesh_symmetric(xc = [0., 0., 0.], rx = 1., ry = 0.5, rz = 0.3, h =
891927
# Generate 3D mesh
892928
gmsh.model.mesh.generate(3)
893929

930+
# Check for hanging nodes before writing
931+
check_hanging_nodes()
932+
894933
# Write output files
895934
gmsh.write(filename + '.msh')
896935
if vtk_out:
@@ -979,6 +1018,9 @@ def cylinder_mesh_symmetric(xc = [0., 0., 0.], r = 1., h = 1., mesh_size = 0.1,
9791018
# Generate 3D mesh
9801019
gmsh.model.mesh.generate(3)
9811020

1021+
# Check for hanging nodes before writing
1022+
check_hanging_nodes()
1023+
9821024
# Write output files
9831025
gmsh.write(filename + '.msh')
9841026
if vtk_out:
@@ -1071,12 +1113,17 @@ def annulus_circle_mesh_symmetric(xc = [0., 0., 0.], r_outer = 1., r_inner = 0.5
10711113
# surface
10721114
s1 = gmsh.model.geo.addPlaneSurface([outer_loop, inner_loop])
10731115

1074-
# designate surface as physical surface
1075-
gmsh.model.addPhysicalGroup(2, [s1], 1)
1076-
1077-
# Synchronize and generate mesh
1116+
# Synchronize geometry before adding physical groups
10781117
gmsh.model.geo.synchronize()
1118+
1119+
# Add physical group for the surface
1120+
gmsh.model.addPhysicalGroup(2, [s1], 1)
1121+
1122+
# Generate mesh
10791123
gmsh.model.mesh.generate(2)
1124+
1125+
# Check for hanging nodes before writing
1126+
check_hanging_nodes()
10801127

10811128
# Write output files
10821129
gmsh.write(filename + '.msh')
@@ -1194,6 +1241,9 @@ def annulus_rectangle_mesh(xc=[0., 0., 0.], Lx=1., Ly=1., hole_Lx=0.3, hole_Ly=0
11941241
gmsh.model.geo.synchronize()
11951242
gmsh.model.mesh.generate(2)
11961243

1244+
# Check for hanging nodes before writing
1245+
check_hanging_nodes()
1246+
11971247
# Write mesh files
11981248
gmsh.write(filename + '.msh')
11991249
if vtk_out:
@@ -1257,6 +1307,9 @@ def open_rectangle_mesh(xc = [0., 0., 0.], Lx = 1., Ly = 1., hole_Lx = 0.5, hole
12571307
gmsh.model.mesh.removeDuplicateNodes()
12581308
gmsh_translate(xc)
12591309

1310+
# Check for hanging nodes before writing
1311+
check_hanging_nodes()
1312+
12601313
gmsh.write(filename + '.msh')
12611314
if vtk_out:
12621315
gmsh.write(filename + '.vtk')
@@ -1340,6 +1393,9 @@ def open_pipe_mesh(xc=[0., 0., 0.], axis=[0., 0., 1.], length=2., outer_radius=1
13401393

13411394
# Generate 3D mesh
13421395
gmsh.model.mesh.generate(3)
1396+
1397+
# Check for hanging nodes before writing
1398+
check_hanging_nodes()
13431399

13441400
# Write mesh files
13451401
gmsh.write(filename + '.msh')
@@ -1353,7 +1409,9 @@ def open_pipe_mesh(xc=[0., 0., 0.], axis=[0., 0., 1.], length=2., outer_radius=1
13531409
if __name__ == "__main__":
13541410
inp_dir = './'
13551411

1356-
test_meshes = ['circle', 'ellipse', 'sphere', 'cuboid', 'ellipsoid', 'rectangle', 'hexagon', 'drum2d', 'triangle', 'polygon', 'cylindrical2d_wall', 'cylinder', 'annulus_circle', 'annulus_rectangle', 'open_rectangle', 'open_pipe']
1412+
test_meshes = ['circle', 'ellipse', 'sphere', 'cuboid', 'ellipsoid', 'rectangle', \
1413+
'hexagon', 'drum2d', 'triangle', 'polygon', 'cylindrical2d_wall', \
1414+
'cylinder', 'annulus_circle', 'annulus_rectangle', 'open_rectangle', 'open_pipe']
13571415
test_meshes = ['open_pipe']
13581416
symm_flag = 0 # 0 - both, 1 - symmetric, 2 - non-symmetric
13591417

0 commit comments

Comments
 (0)