Skip to content

Instantly share code, notes, and snippets.

@akaszynski
Created October 30, 2023 21:14
Show Gist options
  • Save akaszynski/cdbdb5b16756961fe04e0a32dc871f17 to your computer and use it in GitHub Desktop.
Save akaszynski/cdbdb5b16756961fe04e0a32dc871f17 to your computer and use it in GitHub Desktop.
Generates a hexahedral mesh model for rotor and stator geometry using the Gmsh library.
"""
This script generates a mesh model for rotor and stator geometry using the Gmsh library.
The mesh is then written to disk and subsequently read and converted into an archive file
with mapdl-archive for further FEM analysis. The module uses pyvista for optional visualization.
Generates a single cyclic sector.
Requirements
------------
.. code::
pip install gmsh mapdl-archive pyvista numpy
"""
import math
import time
import gmsh
import mapdl_archive
import numpy as np
import pyvista as pv
# Define geometric parameters
r1 = 0.057 # internal radious
r2 = 0.067 # from bottom of rotor slot to the center
r3 = 0.08 # from top of rotor slot to the center
r4 = 0.0814 # from top of stator slot to the center
r5 = 0.0944 # from bottom of rotor slot to the center
r6 = 0.1044 # external radious (half of the diameter)
N_ROTOR = 400
N_STATOR = 440
PT_ROTOR = 0.5 # fill factor for rotor teeth from 0 to 1
PT_STATOR = 0.5 # fill factor for stator teeth from 0 to 1
# state
AR = 2 # rotor position in mechanical degrees
N_RAD_DENSITY = 4
N_TAN_DENSITY = 10
def polar_to_cartesian(radius, angle, center):
x = center[0] + radius * math.cos(angle)
y = center[1] + radius * math.sin(angle)
return (x, y)
# Start Gmsh API
gmsh.initialize()
gmsh.model.add("Model")
# Add points to gmsh model
center_xy = (0.0, 0.0)
p_center = gmsh.model.geo.addPoint(*center_xy, 0.0)
def gen_arcs(n_arc, radius, ang_start=0, fill_factor=0.5):
"""Generate all inner arcs."""
arc_len = math.pi / (n_arc / 2)
points = []
angle = ang_start
for ii in range(n_arc):
x, y = polar_to_cartesian(radius, angle, center_xy)
if ii % 2:
angle += 2 * arc_len * fill_factor
else:
angle += 2 * arc_len * (1 - fill_factor)
points.append(gmsh.model.geo.addPoint(x, y, 0.0))
# Create arcs
arcs = []
for ii in range(n_arc - 1):
arcs.append(gmsh.model.geo.addCircleArc(points[ii], p_center, points[ii + 1]))
arcs.append(gmsh.model.geo.addCircleArc(points[-1], p_center, points[0]))
# Set transfinite lines
for ii in range(n_arc):
gmsh.model.geo.mesh.setTransfiniteCurve(arcs[ii], N_TAN_DENSITY)
return points, arcs
def gen_cyc(n_arc, r_inner, r_middle, ang_start=0.0, fill_factor=0.5):
ang_start_rad = ang_start * math.pi / 180
points_inner, arcs_inner = gen_arcs(n_arc, r_inner, ang_start_rad, fill_factor)
loop_inner = gmsh.model.geo.addCurveLoop(arcs_inner)
points_middle, arcs_middle = gen_arcs(n_arc, r_middle, ang_start_rad, fill_factor)
loop_middle = gmsh.model.geo.addCurveLoop(arcs_middle)
# generate inner to mid connecting lines
in_to_mid_con_lines = []
for ii in range(n_arc):
in_to_mid_con_lines.append(
gmsh.model.geo.addLine(points_inner[ii], points_middle[ii])
)
gmsh.model.geo.mesh.setTransfiniteCurve(in_to_mid_con_lines[-1], N_RAD_DENSITY)
# generate individual "loops" representing the magnets and iron cores
plane_inner = []
# plane_outer = []
# for ii in range(n_arc):
for ii in range(1): # single arc override
# generate "inner core", these are all iron
line0 = in_to_mid_con_lines[ii]
# wrap around last line
if ii == n_arc - 1:
line1 = in_to_mid_con_lines[0]
else:
line1 = in_to_mid_con_lines[ii + 1]
loop = gmsh.model.geo.addCurveLoop(
[arcs_inner[ii], line0, arcs_middle[ii], line1], reorient=True
)
plane = gmsh.model.geo.addPlaneSurface([loop])
plane_inner.append(plane)
gmsh.model.geo.mesh.setTransfiniteSurface(plane)
return plane_inner
###############################################################################
# Generate 2D geometry
inner_plane = gen_cyc(4, 1, 2)
gmsh.model.geo.synchronize()
# Set option to generate quadrilateral elements
gmsh.option.setNumber("Mesh.RecombineAll", True)
# Generate 2D mesh
# gmsh.model.mesh.generate(2)
###############################################################################
# Generate 3D geometry
# Define extrusion vector [dx, dy, dz]
extrude_vector = [0, 0, 0.5] # Replace 0.1 with your extrusion length
pgroup = 2
base_surf_pg = gmsh.model.addPhysicalGroup(
pgroup, inner_plane, tag=100, name="lower_surface"
)
# Extrude the mesh
subdivision = [3]
dimTags = gmsh.model.getEntities(2)
extrusion = gmsh.model.geo.extrude(
[(pgroup, inner_plane[0])], 0, 0, 1, subdivision, recombine=True
)
###############################################################################
# Mesh in 3D
gmsh.model.geo.synchronize()
volume = gmsh.model.addPhysicalGroup(3, [extrusion[1][1]], name="volume")
gmsh.model.mesh.generate(3)
gmsh.model.mesh.refine()
###############################################################################
# Write out to a file
filename = "/tmp/model.msh"
gmsh.write(filename)
###############################################################################
# read in using pyvista and convert to an archive file using mapdl-archive
grid = pv.read(filename)
# grid.plot(color='w', show_edges=True, line_width=1.5)
mapdl_archive.save_as_archive("/tmp/archive.cdb", grid)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment