refactor(meshGeneration): working on gmsh to generate curvilinear isogeomatric spherical mesh

This commit is contained in:
2025-04-30 07:26:58 -04:00
parent ec37fda35b
commit 424f6eee9b
11 changed files with 43664 additions and 28 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,73 @@
import math
from icosphere import icosphere
def generate_mfem_sphere_mesh(subdivisions: int, outputFile: str):
"""Generate a P2 triangular sphere mesh and save in MFEM mesh v1.x format."""
# 1. Generate a geodesic icosphere
vertices, faces = icosphere(subdivisions) # returns (Nverts×3) array and list of 3-tuples :contentReference[oaicite:14]{index=14}
# 2. Build unique edges and mid-edge nodes
edgeToMidIndex = {}
edgesSet = set()
for tri in faces:
for i in range(3):
v0, v1 = tri[i], tri[(i+1) % 3]
edge = tuple(sorted((v0, v1)))
edgesSet.add(edge)
midPoints = []
for edge in edgesSet:
v0, v1 = edge
x0, y0, z0 = vertices[v0]
x1, y1, z1 = vertices[v1]
mx, my, mz = (x0 + x1)/2, (y0 + y1)/2, (z0 + z1)/2
r = math.sqrt(mx*mx + my*my + mz*mz)
mx, my, mz = mx/r, my/r, mz/r # project onto unit sphere :contentReference[oaicite:15]{index=15}
edgeToMidIndex[edge] = len(vertices) + len(midPoints)
midPoints.append((mx, my, mz))
# 3. Assemble all node coordinates (vertices + mid-edge nodes)
nodeCoords = [tuple(v) for v in vertices] + midPoints
# 4. Write MFEM mesh file
with open(outputFile, 'w') as f:
# Header
f.write("MFEM mesh v1.0\n\n")
# Topology
f.write("dimension\n2\n\n")
f.write(f"elements\n{len(faces)}\n")
for tri in faces:
v0, v1, v2 = tri
m0 = edgeToMidIndex[tuple(sorted((v0, v1)))]
m1 = edgeToMidIndex[tuple(sorted((v1, v2)))]
m2 = edgeToMidIndex[tuple(sorted((v2, v0)))]
# attribute=1, type=2 (triangle), followed by 6 vertex indices for P2 :contentReference[oaicite:16]{index=16}
f.write(f"1 2 {v0} {v1} {v2} {m0} {m1} {m2}\n")
f.write("\n")
# No boundary segments for a closed surface
f.write("boundary\n0\n\n")
# Vertices count (actual DOFs)
f.write(f"vertices\n{len(nodeCoords)}\n\n")
# Geometry: Nodes (P2 in 3D)
f.write("nodes\n")
f.write("FiniteElementSpace\n")
f.write("FiniteElementCollection: H1_3D_P2\n")
f.write("VDim: 3\n")
f.write("Ordering: 1\n")
for x, y, z in nodeCoords:
f.write(f"{x} {y} {z}\n")
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser(description='Generate a spherical mesh in MFEM format')
parser.add_argument('--subdivisions', type=int, default=2, help='Number of subdivisions for the icosphere')
parser.add_argument('--output', type=str, default='sphere.mesh', help='Output file name')
args = parser.parse_args()
# Generate the mesh
generate_mfem_sphere_mesh(args.subdivisions, args.output)
print(f"MFEM mesh generated: {args.output}")

View File

@@ -1,37 +1,39 @@
import pygmsh
import meshio
import numpy as np
from math import sqrt
import argparse
import subprocess as sp
import os
def mesh_size_callback(dim, tag, x, y, z, lc, a, b, k):
r = np.sqrt(x**2 + y**2 + z**2)
size = a + (b-a) * (1-np.exp(-k*r))
return size
def generateMesh(coreMeshRes, outerMeshRes, k, order):
# gmsh sphere.geo -3 -setnumber Parameters/Order 1 -setnumber Parameters/CoreRes 0.2 -setnumber Parameters/OuterRes 0.4 -setnumber Parameters/K 2.0 -o sphere_order2.msh
gmsh_cmd = [
'gmsh',
'sphere.geo', # Path to your GMSH geometry file
'-3', # Generate 3D mesh
'-setnumber', 'Parameters/Order', str(order),
'-setnumber', 'Parameters/CoreRes', str(coreMeshRes),
'-setnumber', 'Parameters/OuterRes', str(outerMeshRes),
'-setnumber', 'Parameters/K', str(k),
'-o', 'sphere.vtk', # Output mesh file
'-format', 'vtk'
def generate_spherical_mesh(radius=1.0, coreRes = 0.1, outRes = 0.1, k = 2):
with pygmsh.occ.Geometry() as geom:
originPoint = geom.add_point([0.0, 0.0, 0.0], mesh_size=coreRes)
geom.add_ball([0.0, 0.0, 0.0], 1.0)
geom.set_mesh_size_callback(lambda dim, tag, x, y, z, lc: mesh_size_callback(dim, tag, x, y, z, lc, coreRes, outRes, k))
mesh = geom.generate_mesh(verbose=True)
return mesh
def write_mfem_mesh(meshData, filename):
meshio.write(filename, meshData, file_format='gmsh22')
]
# Use popen to run
process = sp.Popen(gmsh_cmd)
stdout, stderr = process.communicate()
if process.returncode != 0:
print(f"Error generating mesh: {stderr.decode()}")
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Generate a spherical mesh')
parser.add_argument('--radius', type=float, default=1.0, help='Radius of the sphere')
parser.add_argument('--coreMeshRes', type=float, default=0.01, help='Core Mesh Resolution')
parser.add_argument('--outerMeshRes', type=float, default=0.1, help='Outer Mesh Resolution')
parser.add_argument('--coreMeshRes', type=float, default=0.1, help='Core Mesh Resolution target')
parser.add_argument('--outerMeshRes', type=float, default=0.3, help='Outer Mesh Resolution target')
parser.add_argument('--k', type=float, default=2, help='Mesh size scaling factor')
parser.add_argument('--output', type=str, default='sphere.msh', help='Output file name')
# Add argument for element order
parser.add_argument('--order', type=int, default=2, help='Mesh element order (e.g., 1 for linear, 2 for quadratic)')
parser.add_argument('--output', type=str, default='sphere.vtk', help='Output file name')
args = parser.parse_args()
meshData = generate_spherical_mesh(args.radius, args.coreMeshRes, args.outerMeshRes, args.k)
write_mfem_mesh(meshData, args.output)
# Generate the mesh
generateMesh(args.coreMeshRes, args.outerMeshRes, args.k, args.order)

View File

@@ -0,0 +1,38 @@
SetFactory("OpenCASCADE");
// Define parameters - these can be overridden from the command line
// using the -setnumber flag, e.g., gmsh sphere.geo -setnumber Parameters/Order 2
DefineConstant[
radius = {1.0, Name "Parameters/Radius"},
coreRes = {0.01, Name "Parameters/CoreRes"},
outerRes = {0.1, Name "Parameters/OuterRes"},
kVal = {2.0, Name "Parameters/K"},
order = {2, Name "Parameters/Order"} // Mesh element order
];
// Define Geometry
Sphere(1) = {0, 0, 0, radius};
Physical Volume("sphere_volume", 1) = {1}; // Tag the volume
// Define variable mesh size using a MathEval Field
// Field Formula: a + (b-a) * (1 - Exp(-k*r))
// Need to handle r=0 case for Sqrt and Exp
Field[1] = MathEval;
Field[1].F = Sprintf("%.15g + (%.15g - %.15g) * (1 - Exp(-%.15g * Max(Sqrt(x*x+y*y+z*z), 1e-9)))", coreRes, outerRes, coreRes, kVal);
// Use this field as the background mesh size field
Background Field = 1;
// Set Mesh Options
Mesh.ElementOrder = order; // Set the mesh order (1=linear, 2=quadratic, etc.)
// Optional: Optimize high-order elements for better quality
// Mesh.HighOrderOptimize = 1;
// Optional: Choose 3D meshing algorithm if default isn't good (e.g., 1=MeshAdapt, 4=Frontal, 5=Delaunay, 6=Frontal-Delaunay, 7=MMG3D)
// Mesh.Algorithm3D = 7;
// Define Physical Groups (optional but good practice)
// Physical Volume("sphere_volume", 1) = {1}; // Tag the volume
// Physical Surface("sphere_surface", 2) = {1}; // Tag the boundary surface

View File

@@ -0,0 +1,261 @@
MFEM mesh v1.0
dimension
2
elements
80
1 2 0 16 12 53 137 159
1 2 16 5 18 71 83 153
1 2 16 18 12 153 51 137
1 2 12 18 1 51 112 73
1 2 0 14 16 45 106 53
1 2 14 3 25 93 110 111
1 2 14 25 16 111 147 106
1 2 16 25 5 147 72 71
1 2 0 13 14 123 74 45
1 2 13 2 21 88 135 66
1 2 13 21 14 66 82 74
1 2 14 21 3 82 84 93
1 2 0 15 13 133 161 123
1 2 15 4 22 108 95 127
1 2 15 22 13 127 151 161
1 2 13 22 2 151 89 88
1 2 0 12 15 159 79 133
1 2 12 1 17 73 56 92
1 2 12 17 15 92 145 79
1 2 15 17 4 145 120 108
1 2 1 18 19 112 48 65
1 2 18 5 30 83 54 60
1 2 18 30 19 60 142 48
1 2 19 30 8 142 143 132
1 2 5 25 31 72 77 141
1 2 25 3 27 110 150 57
1 2 25 27 31 57 75 77
1 2 31 27 10 75 46 67
1 2 3 21 26 84 129 62
1 2 21 2 23 135 144 155
1 2 21 23 26 155 94 129
1 2 26 23 7 94 68 43
1 2 2 22 24 89 158 99
1 2 22 4 29 95 85 139
1 2 22 29 24 139 146 158
1 2 24 29 11 146 115 134
1 2 4 17 28 120 160 130
1 2 17 1 20 56 125 121
1 2 17 20 28 121 80 160
1 2 28 20 9 80 140 55
1 2 7 38 32 138 128 109
1 2 38 11 36 117 103 97
1 2 38 36 32 97 118 128
1 2 32 36 6 118 70 149
1 2 11 41 36 78 64 103
1 2 41 9 34 116 126 96
1 2 41 34 36 96 122 64
1 2 36 34 6 122 61 70
1 2 9 39 34 102 86 126
1 2 39 8 33 47 114 136
1 2 39 33 34 136 154 86
1 2 34 33 6 154 107 61
1 2 8 40 33 100 58 114
1 2 40 10 35 69 91 156
1 2 40 35 33 156 76 58
1 2 33 35 6 76 119 107
1 2 10 37 35 101 59 91
1 2 37 7 32 50 109 42
1 2 37 32 35 42 152 59
1 2 35 32 6 152 149 119
1 2 2 24 23 99 81 144
1 2 24 11 38 134 117 148
1 2 24 38 23 148 63 81
1 2 23 38 7 63 138 68
1 2 4 28 29 130 124 85
1 2 28 9 41 55 116 90
1 2 28 41 29 90 44 124
1 2 29 41 11 44 78 115
1 2 1 19 20 65 87 125
1 2 19 8 39 132 47 49
1 2 19 39 20 49 131 87
1 2 20 39 9 131 102 140
1 2 5 31 30 141 98 54
1 2 31 10 40 67 69 52
1 2 31 40 30 52 104 98
1 2 30 40 8 104 100 143
1 2 3 26 27 62 105 150
1 2 26 7 37 43 50 157
1 2 26 37 27 157 113 105
1 2 27 37 10 113 101 46
boundary
0
vertices
162
nodes
FiniteElementSpace
FiniteElementCollection: H1_3D_P2
VDim: 3
Ordering: 1
0.0 0.5257311121191336 0.85065080835204
0.0 -0.5257311121191336 0.85065080835204
0.5257311121191336 0.85065080835204 0.0
-0.5257311121191336 0.85065080835204 0.0
0.85065080835204 0.0 0.5257311121191336
-0.85065080835204 0.0 0.5257311121191336
-0.0 -0.5257311121191336 -0.85065080835204
-0.0 0.5257311121191336 -0.85065080835204
-0.5257311121191336 -0.85065080835204 -0.0
0.5257311121191336 -0.85065080835204 -0.0
-0.85065080835204 -0.0 -0.5257311121191336
0.85065080835204 -0.0 -0.5257311121191336
0.0 0.0 1.0
0.3090169943749474 0.8090169943749473 0.5
-0.3090169943749474 0.8090169943749473 0.5
0.5000000000000001 0.30901699437494745 0.8090169943749475
-0.5000000000000001 0.30901699437494745 0.8090169943749475
0.5000000000000001 -0.30901699437494745 0.8090169943749475
-0.5000000000000001 -0.30901699437494745 0.8090169943749475
-0.3090169943749474 -0.8090169943749473 0.5
0.3090169943749474 -0.8090169943749473 0.5
0.0 1.0 0.0
0.8090169943749475 0.5000000000000001 0.30901699437494745
0.3090169943749474 0.8090169943749473 -0.5
0.8090169943749475 0.5000000000000001 -0.30901699437494745
-0.8090169943749475 0.5000000000000001 0.30901699437494745
-0.3090169943749474 0.8090169943749473 -0.5
-0.8090169943749475 0.5000000000000001 -0.30901699437494745
0.8090169943749475 -0.5000000000000001 0.30901699437494745
1.0 0.0 0.0
-0.8090169943749475 -0.5000000000000001 0.30901699437494745
-1.0 0.0 0.0
-0.0 0.0 -1.0
-0.3090169943749474 -0.8090169943749473 -0.5
0.3090169943749474 -0.8090169943749473 -0.5
-0.5000000000000001 -0.30901699437494745 -0.8090169943749475
0.5000000000000001 -0.30901699437494745 -0.8090169943749475
-0.5000000000000001 0.30901699437494745 -0.8090169943749475
0.5000000000000001 0.30901699437494745 -0.8090169943749475
0.0 -1.0 -0.0
-0.8090169943749475 -0.5000000000000001 -0.30901699437494745
0.8090169943749475 -0.5000000000000001 -0.30901699437494745
-0.26286555605956685 0.16245984811645317 -0.9510565162951536
-0.16062203564002311 0.6937804775604491 -0.702046444776163
0.9510565162951536 -0.26286555605956685 -0.16245984811645317
-0.16062203564002311 0.6937804775604491 0.702046444776163
-0.8626684804161862 0.25989191300775444 -0.4338885645526948
-0.2732665289126717 -0.9619383577839176 -0.0
-0.42532540417602 -0.5877852522924731 0.6881909602355868
-0.16245984811645314 -0.9510565162951536 0.2628655560595668
-0.25989191300775444 0.4338885645526948 -0.8626684804161862
-0.26286555605956685 -0.16245984811645317 0.9510565162951536
-0.9510565162951536 -0.26286555605956685 -0.16245984811645317
-0.25989191300775444 0.4338885645526948 0.8626684804161862
-0.8626684804161862 -0.25989191300775444 0.4338885645526948
0.6937804775604491 -0.7020464447761631 0.16062203564002314
0.25989191300775444 -0.4338885645526948 0.8626684804161862
-0.8506508083520399 0.5257311121191337 0.0
-0.5877852522924731 -0.6881909602355867 -0.42532540417601994
-0.5257311121191337 0.0 -0.8506508083520399
-0.6881909602355868 -0.42532540417602005 0.5877852522924731
0.16062203564002311 -0.6937804775604491 -0.702046444776163
-0.43388856455269476 0.8626684804161862 -0.2598919130077544
0.42532540417602 0.5877852522924731 -0.6881909602355868
0.6881909602355868 -0.42532540417602005 -0.5877852522924731
-0.16062203564002311 -0.6937804775604491 0.702046444776163
0.16245984811645314 0.9510565162951536 0.2628655560595668
-0.9619383577839176 0.0 -0.2732665289126717
0.16062203564002311 0.6937804775604491 -0.702046444776163
-0.8626684804161862 -0.25989191300775444 -0.4338885645526948
0.25989191300775444 -0.4338885645526948 -0.8626684804161862
-0.7020464447761631 0.16062203564002314 0.6937804775604491
-0.8626684804161862 0.25989191300775444 0.4338885645526948
0.0 -0.2732665289126717 0.9619383577839176
0.0 0.8506508083520399 0.5257311121191336
-0.9510565162951536 0.26286555605956685 -0.16245984811645317
-0.42532540417602 -0.5877852522924731 -0.6881909602355868
-0.9510565162951536 0.26286555605956685 0.16245984811645317
0.8626684804161862 -0.25989191300775444 -0.4338885645526948
0.26286555605956685 0.16245984811645317 0.9510565162951536
0.5877852522924731 -0.6881909602355867 0.42532540417601994
0.5877852522924731 0.6881909602355867 -0.42532540417601994
-0.16245984811645314 0.9510565162951536 0.2628655560595668
-0.7020464447761631 -0.16062203564002314 0.6937804775604491
-0.2732665289126717 0.9619383577839176 0.0
0.9619383577839176 0.0 0.2732665289126717
0.16245984811645314 -0.9510565162951536 -0.2628655560595668
0.0 -0.8506508083520399 0.5257311121191336
0.43388856455269476 0.8626684804161862 0.2598919130077544
0.6937804775604491 0.7020464447761631 0.16062203564002314
0.8506508083520399 -0.5257311121191337 0.0
-0.7020464447761631 -0.16062203564002314 -0.6937804775604491
0.26286555605956685 -0.16245984811645317 0.9510565162951536
-0.43388856455269476 0.8626684804161862 0.2598919130077544
0.0 0.8506508083520399 -0.5257311121191336
0.8626684804161862 0.25989191300775444 0.4338885645526948
0.5877852522924731 -0.6881909602355867 -0.42532540417601994
0.5257311121191337 0.0 -0.8506508083520399
-0.9510565162951536 -0.26286555605956685 0.16245984811645317
0.6937804775604491 0.7020464447761631 -0.16062203564002314
-0.6937804775604491 -0.7020464447761631 -0.16062203564002314
-0.7020464447761631 0.16062203564002314 -0.6937804775604491
0.2732665289126717 -0.9619383577839176 -0.0
0.7020464447761631 -0.16062203564002314 -0.6937804775604491
-0.8506508083520399 -0.5257311121191337 0.0
-0.5877852522924731 0.6881909602355867 -0.42532540417601994
-0.42532540417602 0.5877852522924731 0.6881909602355868
-0.16062203564002311 -0.6937804775604491 -0.702046444776163
0.7020464447761631 0.16062203564002314 0.6937804775604491
-0.0 0.2732665289126717 -0.9619383577839176
-0.6937804775604491 0.7020464447761631 0.16062203564002314
-0.5877852522924731 0.6881909602355867 0.42532540417601994
-0.25989191300775444 -0.4338885645526948 0.8626684804161862
-0.6881909602355868 0.42532540417602005 -0.5877852522924731
-0.43388856455269476 -0.8626684804161862 -0.2598919130077544
0.9619383577839176 0.0 -0.2732665289126717
0.6937804775604491 -0.7020464447761631 -0.16062203564002314
0.7020464447761631 0.16062203564002314 -0.6937804775604491
0.26286555605956685 -0.16245984811645317 -0.9510565162951536
-0.25989191300775444 -0.4338885645526948 -0.8626684804161862
0.7020464447761631 -0.16062203564002314 0.6937804775604491
0.42532540417602 -0.5877852522924731 0.6881909602355868
0.42532540417602 -0.5877852522924731 -0.6881909602355868
0.16062203564002311 0.6937804775604491 0.702046444776163
0.9510565162951536 -0.26286555605956685 0.16245984811645317
0.16062203564002311 -0.6937804775604491 0.702046444776163
0.43388856455269476 -0.8626684804161862 -0.2598919130077544
0.6881909602355868 0.42532540417602005 0.5877852522924731
0.26286555605956685 0.16245984811645317 -0.9510565162951536
-0.16245984811645314 0.9510565162951536 -0.2628655560595668
0.8626684804161862 -0.25989191300775444 0.4338885645526948
0.16245984811645314 -0.9510565162951536 0.2628655560595668
-0.43388856455269476 -0.8626684804161862 0.2598919130077544
0.25989191300775444 0.4338885645526948 0.8626684804161862
0.8626684804161862 0.25989191300775444 -0.4338885645526948
0.2732665289126717 0.9619383577839176 0.0
-0.16245984811645314 -0.9510565162951536 -0.2628655560595668
-0.26286555605956685 0.16245984811645317 0.9510565162951536
0.25989191300775444 0.4338885645526948 -0.8626684804161862
0.9510565162951536 0.26286555605956685 0.16245984811645317
0.43388856455269476 -0.8626684804161862 0.2598919130077544
-0.9619383577839176 0.0 0.2732665289126717
-0.5877852522924731 -0.6881909602355867 0.42532540417601994
-0.6937804775604491 -0.7020464447761631 0.16062203564002314
0.43388856455269476 0.8626684804161862 -0.2598919130077544
0.5257311121191337 0.0 0.8506508083520399
0.9510565162951536 0.26286555605956685 -0.16245984811645317
-0.6881909602355868 0.42532540417602005 0.5877852522924731
0.6881909602355868 0.42532540417602005 -0.5877852522924731
-0.0 -0.2732665289126717 -0.9619383577839176
-0.6937804775604491 0.7020464447761631 -0.16062203564002314
0.5877852522924731 0.6881909602355867 0.42532540417601994
-0.26286555605956685 -0.16245984811645317 -0.9510565162951536
-0.5257311121191337 0.0 0.8506508083520399
0.0 -0.8506508083520399 -0.5257311121191336
0.16245984811645314 0.9510565162951536 -0.2628655560595668
-0.6881909602355868 -0.42532540417602005 -0.5877852522924731
-0.42532540417602 0.5877852522924731 -0.6881909602355868
0.8506508083520399 0.5257311121191337 0.0
0.0 0.2732665289126717 0.9619383577839176
0.6881909602355868 -0.42532540417602005 0.5877852522924731
0.42532540417602 0.5877852522924731 0.6881909602355868

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff