# Copyright (c) 2026 JSOL CORPORATION # # This script is released under the MIT License. # See the full license text at: # https://www.jmag-international.com/scriptlibrary/jmag_script_library_mit/ app = designer.GetApplication() geomApp = app.CreateGeometryEditor() geomDoc = geomApp.GetDocument() # Dimensional parameters Poles = 8 MagnetClearance = 0.6 SlitBridgeThickness = 0.6 RotorOuterDiameter = 125 RotorInnerDiameter = 102 SlitCornerRadius = 0.5 MagnetThickness = 2.3 MagnetWidth = 24.7 SlitLength1 = 0.5 SlitLength2 = 1.6 SlitAngle1 = 120 SlitAngle2 = 120 # Equation names EqPoles = u"POLES" EqMagnetClearance = u"DMAG" EqSlitBridgeThickness = u"DSLIT" EqRotorOuterDiameter = u"RD1" EqRotorInnerDiameter = u"RD2" EqSlitCornerRadius = u"RF" EqMagnetThickness = u"RT1" EqMagnetWidth = u"RW1" EqSlitLength1 = u"RW2" EqSlitLength2 = u"RW3" EqSlitAngle1 = u"RW4" EqSlitAngle2 = u"RW5" def setupEquation(equation, expression, equationType): """Configure the type and expression of an equation in DesignTable.""" # The argument of SetType # 0: Value # 1: Expression equation.SetType(equationType) equation.SetExpression(str(expression)) def createRotorEquations(): """Register the equations used for the rotor geometry in DesignTable.""" designTable = geomDoc.GetDesignTable() equationSettings = [ (EqPoles, Poles, 0), (EqMagnetClearance, MagnetClearance, 0), (EqSlitBridgeThickness, SlitBridgeThickness, 0), (EqRotorOuterDiameter, RotorOuterDiameter, 0), (EqRotorInnerDiameter, RotorInnerDiameter, 0), (EqSlitCornerRadius, SlitCornerRadius, 0), (EqMagnetThickness, MagnetThickness, 0), (EqMagnetWidth, MagnetWidth, 0), (EqSlitLength1, SlitLength1, 0), (EqSlitLength2, SlitLength2, 0), (EqSlitAngle1, SlitAngle1, 0), (EqSlitAngle2, SlitAngle2, 0), ] designTable.EditStart() for equationName, expression, equationType in equationSettings: designTable.AddEquation(equationName) equation = designTable.GetEquation(equationName) setupEquation(equation, expression, equationType) designTable.EditEnd() def createReference(item): """Create a ReferenceObject from a geometry item.""" return geomDoc.CreateReferenceFromItem(item) def addItemsToReferenceList(feature, propertyName, itemList): """Add geometry items to a stringlist-type property.""" for item in itemList: feature.AddPropertyByReference(propertyName, createReference(item)) def createRegionFromItems(sketch, itemList): """Create regions in the sketch from all items in itemList.""" selection = geomDoc.GetSelection() selection.Clear() for item in itemList: selection.Add(item) sketch.CreateRegions() selection.Clear() def getRegionItemByOrder(sketch, createdOrder): """Get the region object in the specified creation order.""" currentCount = 0 for i in range(sketch.NumItems()): item = sketch.GetItem(i) if item.GetScriptTypeName() == u"RegionItem": if currentCount == createdOrder - 1: return item currentCount += 1 return sketch def calculateDirectionByAngle(sketch, angle): """Get a unit vector in the specified angle from the X-axis as a Point object.""" dummyLine = sketch.CreateLineByLengthAngle(0, 0, 1, angle) endVertex = dummyLine.GetEndVertex() direction = geomApp.CreatePoint(endVertex.GetX(), endVertex.GetY(), 0) selection = geomDoc.GetSelection() selection.Clear() selection.Add(dummyLine) selection.Delete() selection.Clear() return direction def addPointAndVector(point, vector, length): """Get a point moved from the specified point by a specified distance along a vector as a Point object.""" x = point.GetX() + vector.GetX() * length y = point.GetY() + vector.GetY() * length return geomApp.CreatePoint(x, y, 0) def calculatePointOnRadialLine(radius, direction): """Get the intersection of an origin-centered circle and a line through the origin in the specified direction as a Point object.""" x = radius * direction.GetX() y = radius * direction.GetY() return geomApp.CreatePoint(x, y, 0) def calculateRayCircleIntersection(startPoint, direction, radius): """Get the nearer intersection of a ray from the specified point and an origin-centered circle as a Point object.""" dot = startPoint.GetX() * direction.GetX() + startPoint.GetY() * direction.GetY() squaredRadiusFromOrigin = startPoint.GetX() ** 2 + startPoint.GetY() ** 2 discriminant = dot ** 2 - (squaredRadiusFromOrigin - radius ** 2) root = discriminant ** 0.5 distance1 = -dot - root distance2 = -dot + root positiveDistances = [distance for distance in [distance1, distance2] if distance >= 0] distance = min(positiveDistances) return addPointAndVector(startPoint, direction, distance) def createArc(sketch, startPoint, endPoint): """Create an arc centered at the origin between the specified start and end points.""" return sketch.CreateArc(0, 0, startPoint.GetX(), startPoint.GetY(), endPoint.GetX(), endPoint.GetY()) def createLine(sketch, startPoint, endPoint): """Create a line between the specified start and end points.""" return sketch.CreateLine(startPoint.GetX(), startPoint.GetY(), endPoint.GetX(), endPoint.GetY()) def createDiameterConstraint(sketch, arc, expression): """Create a diameter constraint for an arc and set its equation.""" constraint = sketch.CreateMonoConstraint(u"radius", createReference(arc)) # The argument of SetType # 0: Radius # 1: Diameter constraint.SetType(1) constraint.SetProperty(u"Diameter", expression) def createDistanceConstraint(sketch, firstItem, secondItem, expression, useDoubleWidth=False): """Create a distance constraint between two geometry items and set its equation.""" constraint = sketch.CreateBiConstraint(u"distance", createReference(firstItem), createReference(secondItem)) constraint.SetProperty(u"Distance", expression) if useDoubleWidth: constraint.SetProperty(u"UseDoubleWidth", True) def createAngleConstraint(sketch, firstItem, secondItem, expression): """Create an angle constraint between two lines and set its equation.""" constraint = sketch.CreateBiConstraint(u"angle", createReference(firstItem), createReference(secondItem)) constraint.SetProperty(u"Angle", expression) def createSlitCornerFillet(sketch, slitBridgeArc, slitOuterReturnLine): """Create a fillet at the connection between the slit and bridge arc.""" selection = geomDoc.GetSelection() selection.Clear() selection.Add(slitBridgeArc) selection.Add(slitOuterReturnLine) geomDoc.GetSketchManager().CreateFillet(SlitCornerRadius) selection.Clear() filletArc = sketch.GetItem(sketch.NumItems() - 1) radiusConstraint = sketch.CreateMonoConstraint(u"radius", createReference(filletArc)) radiusConstraint.SetProperty(u"Radius", EqSlitCornerRadius) sketch.CreateBiConstraint(u"tangency", createReference(filletArc), createReference(slitBridgeArc)) sketch.CreateBiConstraint(u"tangency", createReference(filletArc), createReference(slitOuterReturnLine)) return filletArc def setRegionAppearance(region, name, color): """Set the name and display color of a region.""" region.SetName(name) region.SetProperty(u"Color", color) region.SetProperty(u"UseParentColor", 0) def createRotorBaseShape(sketch): """Create the base geometry and constraints for a half-pole pitch of the I-shaped outer rotor IPM motor.""" rotorOuterRadius = RotorOuterDiameter / 2.0 rotorInnerRadius = RotorInnerDiameter / 2.0 slitBridgeRadius = rotorInnerRadius + SlitBridgeThickness magnetInnerPosition = rotorInnerRadius + MagnetClearance magnetOuterPosition = magnetInnerPosition + MagnetThickness halfMagnetWidth = MagnetWidth / 2.0 halfPoleAngle = 360.0 / Poles / 2.0 radialDirection = calculateDirectionByAngle(sketch, halfPoleAngle) tangentDirection = calculateDirectionByAngle(sketch, halfPoleAngle - 90.0) slitInnerReturnDirection = calculateDirectionByAngle(sketch, halfPoleAngle - 90.0 - SlitAngle1) # Set the direction vector from the outer slit corner toward the bridge circle. slitOuterToBridgeDirection = calculateDirectionByAngle(sketch, halfPoleAngle - 90.0 - (180.0 - SlitAngle2)) # Create and fix the origin. originVertex = sketch.CreateVertex(0, 0) sketch.CreateMonoConstraint(u"fixture", createReference(originVertex)) # Calculate the vertex positions of each contour. pointInnerOnXAxis = geomApp.CreatePoint(rotorInnerRadius, 0, 0) pointOuterOnXAxis = geomApp.CreatePoint(rotorOuterRadius, 0, 0) pointInnerOnSymmetry = calculatePointOnRadialLine(rotorInnerRadius, radialDirection) pointOuterOnSymmetry = calculatePointOnRadialLine(rotorOuterRadius, radialDirection) pointMagnetInnerOnSymmetry = calculatePointOnRadialLine(magnetInnerPosition, radialDirection) pointMagnetOuterOnSymmetry = calculatePointOnRadialLine(magnetOuterPosition, radialDirection) pointMagnetInnerEnd = addPointAndVector(pointMagnetInnerOnSymmetry, tangentDirection, halfMagnetWidth) pointMagnetOuterEnd = addPointAndVector(pointMagnetOuterOnSymmetry, tangentDirection, halfMagnetWidth) pointSlitInnerCorner = addPointAndVector(pointMagnetInnerEnd, tangentDirection, SlitLength1) pointSlitOuterCorner = addPointAndVector(pointMagnetOuterEnd, tangentDirection, SlitLength2) pointSlitInnerOnBridge = calculateRayCircleIntersection(pointSlitInnerCorner, slitInnerReturnDirection, slitBridgeRadius) pointSlitOuterOnBridge = calculateRayCircleIntersection(pointSlitOuterCorner, slitOuterToBridgeDirection, slitBridgeRadius) # Create the rotor inner and outer arcs. rotorInnerArc = createArc(sketch, pointInnerOnXAxis, pointInnerOnSymmetry) createDiameterConstraint(sketch, rotorInnerArc, EqRotorInnerDiameter) rotorOuterArc = createArc(sketch, pointOuterOnXAxis, pointOuterOnSymmetry) createDiameterConstraint(sketch, rotorOuterArc, EqRotorOuterDiameter) # Create the rotor core boundary on the X-axis. radialLineOnXAxis = createLine(sketch, pointInnerOnXAxis, pointOuterOnXAxis) sketch.CreateMonoConstraint(u"horizontality", createReference(radialLineOnXAxis)) sketch.CreateBiConstraint(u"coincident", createReference(radialLineOnXAxis), createReference(originVertex)) # Create the rotor core and magnet boundaries on the pole-center side. innerSymmetryLine = createLine(sketch, pointInnerOnSymmetry, pointMagnetInnerOnSymmetry) sketch.CreateBiConstraint(u"coincident", createReference(innerSymmetryLine), createReference(originVertex)) magnetSymmetryLine = createLine(sketch, pointMagnetInnerOnSymmetry, pointMagnetOuterOnSymmetry) sketch.CreateBiConstraint(u"coincident", createReference(magnetSymmetryLine), createReference(originVertex)) coreSymmetryLine = createLine(sketch, pointMagnetOuterOnSymmetry, pointOuterOnSymmetry) sketch.CreateBiConstraint(u"coincident", createReference(coreSymmetryLine), createReference(originVertex)) createAngleConstraint(sketch, radialLineOnXAxis, coreSymmetryLine, u"360/{0}/2".format(EqPoles)) # Create the magnet outline. magnetInnerEdge = createLine(sketch, pointMagnetInnerOnSymmetry, pointMagnetInnerEnd) sketch.CreateBiConstraint(u"perpendicularity", createReference(magnetInnerEdge), createReference(magnetSymmetryLine)) magnetOuterEdge = createLine(sketch, pointMagnetOuterOnSymmetry, pointMagnetOuterEnd) magnetEndLine = createLine(sketch, pointMagnetInnerEnd, pointMagnetOuterEnd) # Create the slit outline from the magnet end to the bridge. slitInnerExtensionLine = createLine(sketch, pointMagnetInnerEnd, pointSlitInnerCorner) sketch.CreateBiConstraint(u"coincident", createReference(slitInnerExtensionLine), createReference(magnetInnerEdge)) slitInnerReturnLine = createLine(sketch, pointSlitInnerCorner, pointSlitInnerOnBridge) slitOuterExtensionLine = createLine(sketch, pointMagnetOuterEnd, pointSlitOuterCorner) sketch.CreateBiConstraint(u"coincident", createReference(slitOuterExtensionLine), createReference(magnetOuterEdge)) slitOuterReturnLine = createLine(sketch, pointSlitOuterCorner, pointSlitOuterOnBridge) slitBridgeArc = createArc(sketch, pointSlitOuterOnBridge, pointSlitInnerOnBridge) # Constrain the arcs concentrically and set the bridge thickness. sketch.CreateBiConstraint(u"concentricity", createReference(rotorInnerArc), createReference(rotorOuterArc)) sketch.CreateBiConstraint(u"concentricity", createReference(rotorInnerArc), createReference(slitBridgeArc)) createDistanceConstraint(sketch, rotorInnerArc, slitBridgeArc, EqSlitBridgeThickness) # Set the magnet position and dimensions. createDistanceConstraint(sketch, rotorInnerArc.GetEndVertex(), magnetSymmetryLine.GetStartVertex(), EqMagnetClearance) createDistanceConstraint(sketch, magnetInnerEdge, magnetOuterEdge, EqMagnetThickness) createDistanceConstraint(sketch, magnetEndLine, magnetSymmetryLine, EqMagnetWidth, useDoubleWidth=True) # Set the slit lengths and angles. createDistanceConstraint(sketch, slitInnerExtensionLine.GetStartVertex(), slitInnerExtensionLine.GetEndVertex(), EqSlitLength1) createDistanceConstraint(sketch, slitOuterExtensionLine.GetStartVertex(), slitOuterExtensionLine.GetEndVertex(), EqSlitLength2) createAngleConstraint(sketch, slitInnerReturnLine, slitInnerExtensionLine, EqSlitAngle1) createAngleConstraint(sketch, slitOuterExtensionLine, slitOuterReturnLine, EqSlitAngle2) # Create a fillet at the connection between the slit and bridge arc. filletArc = createSlitCornerFillet(sketch, slitBridgeArc, slitOuterReturnLine) # Collect the contours that form the rotor core and magnet regions. rotorCoreEdgeList = [ radialLineOnXAxis, rotorOuterArc, coreSymmetryLine, magnetOuterEdge, slitOuterExtensionLine, slitOuterReturnLine, filletArc, slitBridgeArc, slitInnerReturnLine, slitInnerExtensionLine, magnetInnerEdge, innerSymmetryLine, rotorInnerArc, ] magnetEdgeList = [ magnetSymmetryLine, magnetOuterEdge, magnetEndLine, magnetInnerEdge, ] # Get the three target vertices to apply fillets to the slit corners. slitRegionFilletVertexList = [ slitInnerExtensionLine.GetEndVertex(), slitInnerReturnLine.GetEndVertex(), slitOuterExtensionLine.GetEndVertex(), ] return rotorCoreEdgeList, magnetEdgeList, coreSymmetryLine, magnetSymmetryLine, slitRegionFilletVertexList def createSlitRegionFillet(sketch, targetVertexList): """Set fillets at the three slit corners of the rotor core region.""" regionFillet = sketch.CreateRegionFillet() regionFillet.SetName(u"SlitCornerRegionFillet") addItemsToReferenceList(regionFillet, u"Target", targetVertexList) regionFillet.SetProperty(u"Radius", EqSlitCornerRadius) def createRotorCorePattern(sketch, rotorCoreRegion, coreSymmetryLine): """Mirror-copy the rotor core region and circularly pattern it to create a 90deg partial model.""" # Mirror-copy the half-pole-pitch region to create one pole. coreMirror = sketch.CreateRegionMirrorCopy() coreMirror.SetName(u"CoreMirror1Pole") coreMirror.SetMerge(True) addItemsToReferenceList(coreMirror, u"Region", [rotorCoreRegion]) coreMirror.SetProperty(u"OverlappedAreaError", True) coreMirror.SetSymmetry(createReference(coreSymmetryLine)) # Circularly pattern the one-pole geometry for the number of poles in the 90deg partial model. corePattern = sketch.CreateRegionCircularPattern() corePattern.SetName(u"CoreCircularPattern") corePattern.SetMerge(True) addItemsToReferenceList(corePattern, u"Region", [rotorCoreRegion]) addItemsToReferenceList(corePattern, u"Feature", [coreMirror]) corePattern.SetProperty(u"CenterType", u"DefaultOrigin") corePattern.SetProperty(u"Angle", u"360/{0}".format(EqPoles)) corePattern.SetProperty(u"Instance", u"{0}/4".format(EqPoles)) def createMagnetPattern(sketch, magnetRegion, magnetSymmetryLine): """Mirror-copy the magnet region and circularly pattern it to create a 90deg partial model.""" # Mirror-copy the half-pole-pitch region to create the magnet geometry for one pole. magnetMirror = sketch.CreateRegionMirrorCopy() magnetMirror.SetName(u"MagnetMirror1Pole") magnetMirror.SetMerge(True) addItemsToReferenceList(magnetMirror, u"Region", [magnetRegion]) magnetMirror.SetSymmetry(createReference(magnetSymmetryLine)) # Circularly pattern the one-pole magnet geometry for the number of poles in the 90deg partial model. magnetPattern = sketch.CreateRegionCircularPattern() magnetPattern.SetName(u"MagnetCircularPattern") addItemsToReferenceList(magnetPattern, u"Region", [magnetRegion]) addItemsToReferenceList(magnetPattern, u"Feature", [magnetMirror]) magnetPattern.SetProperty(u"CenterType", u"DefaultOrigin") magnetPattern.SetProperty(u"Angle", u"360/{0}".format(EqPoles)) magnetPattern.SetProperty(u"Instance", u"{0}/4".format(EqPoles)) def drawRotor(sketch): """Create the 2D geometry of the I-shaped outer rotor IPM motor in the sketch.""" rotorCoreEdgeList, magnetEdgeList, coreSymmetryLine, magnetSymmetryLine, slitRegionFilletVertexList = createRotorBaseShape(sketch) regionOrder = 0 # Create the rotor core region and set its name and display color. createRegionFromItems(sketch, rotorCoreEdgeList) regionOrder += 1 rotorCoreRegion = getRegionItemByOrder(sketch, regionOrder) if rotorCoreRegion.GetScriptTypeName() == u"RegionItem": setRegionAppearance(rotorCoreRegion, u"Core", u"gray") # Create the magnet region and set its name and display color. createRegionFromItems(sketch, magnetEdgeList) regionOrder += 1 magnetRegion = getRegionItemByOrder(sketch, regionOrder) if magnetRegion.GetScriptTypeName() == u"RegionItem": setRegionAppearance(magnetRegion, u"Magnet", u"red") createSlitRegionFillet(sketch, slitRegionFilletVertexList) createRotorCorePattern(sketch, rotorCoreRegion, coreSymmetryLine) createMagnetPattern(sketch, magnetRegion, magnetSymmetryLine) def drawInSketch(sketch): """Open the sketch in editable status and create the geometry.""" sketch.OpenSketch() drawRotor(sketch) sketch.CloseSketch() def main(): """Create the 2D geometry of the I-shaped outer rotor IPM motor.""" createRotorEquations() assm = geomDoc.GetAssembly() refXYPlane = assm.GetPlaneXY() rotorSketch = assm.CreateSketch(refXYPlane) drawInSketch(rotorSketch) rotorSketch.SetProperty(u"Name", u"Rotor") main()