[S0066] I字型IPMアウタロータの2次元形状を作成する

JMAGの形状エディタに搭載されている形状ライブラリをスクリプトで作成します。
JMAGの形状エディタで解析形状を作ると、ベースとした形状を後で寸法変更してパラメトリックスタディや最適化に用いることが容易です。
フィレット形状は、調整の可能性がある場合には領域フィレットで作成すると後から寸法変更が容易になります。
このスクリプトでは、I字型IPMアウタロータの2次元形状を作成します。
I字型IPMアウタロータの2次元形状を作成する

前提条件

  • 極数を8として1/4モデルで作成する
  • 22.5degで鏡面対称性があり、45deg周期で同一形状が繰り返されるものとする
  • 極数は方程式としており変更した場合、周期性は追随するが1/4モデルでの作成は固定されている
    また寸法も固定しており、極数に応じたスケールはされない

スクリプトにおける設定内容

  • 極数及びロータ各部の寸法を方程式として登録する
  • XY平面上にスケッチを作成し、編集可能ステータスとする
  • 円弧と直線で1/2極ピッチ分のロータコア、磁石及びスリットの外形を作成し、拘束を付与する
    1/2極ピッチ分の角度は方程式の極数から算出する
  • ロータコアの領域を作成し、名前と色を設定する
  • 磁石の領域を作成し、名前と色を設定する
  • ロータコア領域のスリット角部に領域フィレットを設定する
  • ロータコアの領域の鏡面コピーを作成し、円形パターン化して1/4モデルとする
  • 磁石の領域の鏡面コピーを作成し、円形パターン化して1/4モデルとする
    円形パターンでの周期角度はスロット数から算出する
    円形パターンのインスタンス数はスロット数の1/4とする
# Copyright (c) 2026 JSOL CORPORATION
#
# 本スクリプトはMITライセンスのもとで公開しています。
# ライセンス全文は以下を参照してください。
# https://www.jmag-international.com/jp/scriptlibrary/jmag_script_library_mit/

app = designer.GetApplication()
geomApp = app.CreateGeometryEditor()
geomDoc = geomApp.GetDocument()

# 寸法パラメータ
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

# 方程式名
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):
    """DesignTableの方程式にタイプと式を設定する。"""
    # SetTypeの引数
    # 0: 値
    # 1: 式
    equation.SetType(equationType)
    equation.SetExpression(str(expression))


def createRotorEquations():
    """ロータ形状に使用する方程式を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):
    """形状アイテムからReferenceObjectを作成する。"""
    return geomDoc.CreateReferenceFromItem(item)


def addItemsToReferenceList(feature, propertyName, itemList):
    """形状アイテムをstringlist型のプロパティへ追加する。"""
    for item in itemList:
        feature.AddPropertyByReference(propertyName, createReference(item))


def createRegionFromItems(sketch, itemList):
    """引数のitemListすべてからスケッチ上に領域を作成する。"""
    selection = geomDoc.GetSelection()
    selection.Clear()
    for item in itemList:
        selection.Add(item)
    sketch.CreateRegions()
    selection.Clear()


def getRegionItemByOrder(sketch, createdOrder):
    """指定した順番目の領域オブジェクトを取得する。"""
    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):
    """X軸から指定した角度方向の単位ベクトルをPoint型で取得する。"""
    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):
    """指定した点からベクトル方向へ指定距離だけ移動した点をPoint型で取得する。"""
    x = point.GetX() + vector.GetX() * length
    y = point.GetY() + vector.GetY() * length
    return geomApp.CreatePoint(x, y, 0)


def calculatePointOnRadialLine(radius, direction):
    """原点中心の円と、原点を通る指定方向の直線との交点をPoint型で取得する。"""
    x = radius * direction.GetX()
    y = radius * direction.GetY()
    return geomApp.CreatePoint(x, y, 0)


def calculateRayCircleIntersection(startPoint, direction, radius):
    """指定した点から伸ばした半直線と原点中心の円との近い側の交点をPoint型で取得する。"""
    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):
    """原点を中心として、指定した始点と終点を結ぶ円弧を作成する。"""
    return sketch.CreateArc(0, 0, startPoint.GetX(), startPoint.GetY(), endPoint.GetX(), endPoint.GetY())


def createLine(sketch, startPoint, endPoint):
    """指定した始点と終点を結ぶ直線を作成する。"""
    return sketch.CreateLine(startPoint.GetX(), startPoint.GetY(), endPoint.GetX(), endPoint.GetY())


def createDiameterConstraint(sketch, arc, expression):
    """円弧に直径拘束を作成し、方程式を設定する。"""
    constraint = sketch.CreateMonoConstraint(u"radius", createReference(arc))
    # SetTypeの引数
    # 0: 半径
    # 1: 直径
    constraint.SetType(1)
    constraint.SetProperty(u"Diameter", expression)


def createDistanceConstraint(sketch, firstItem, secondItem, expression, useDoubleWidth=False):
    """2つの形状間に距離拘束を作成し、方程式を設定する。"""
    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):
    """2つの直線間に角度拘束を作成し、方程式を設定する。"""
    constraint = sketch.CreateBiConstraint(u"angle", createReference(firstItem), createReference(secondItem))
    constraint.SetProperty(u"Angle", expression)


def createSlitCornerFillet(sketch, slitBridgeArc, slitOuterReturnLine):
    """スリットとブリッジ円弧の接続部にRを作成する。"""
    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):
    """領域の名前と表示色を設定する。"""
    region.SetName(name)
    region.SetProperty(u"Color", color)
    region.SetProperty(u"UseParentColor", 0)


def createRotorBaseShape(sketch):
    """1/2極ピッチ分のアウターロータ型IPMモータの基本形状と拘束を作成する。"""
    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)
    # 外側スリット角部からブリッジ円へ向かう方向ベクトルを設定する。
    slitOuterToBridgeDirection = calculateDirectionByAngle(sketch, halfPoleAngle - 90.0 - (180.0 - SlitAngle2))

    # 原点を作成して固定する。
    originVertex = sketch.CreateVertex(0, 0)
    sketch.CreateMonoConstraint(u"fixture", createReference(originVertex))

    # 各輪郭の頂点位置を計算する。
    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)

    # ロータ内径と外径の円弧を作成する。
    rotorInnerArc = createArc(sketch, pointInnerOnXAxis, pointInnerOnSymmetry)
    createDiameterConstraint(sketch, rotorInnerArc, EqRotorInnerDiameter)
    rotorOuterArc = createArc(sketch, pointOuterOnXAxis, pointOuterOnSymmetry)
    createDiameterConstraint(sketch, rotorOuterArc, EqRotorOuterDiameter)

    # X軸上にロータコアの境界を作成する。
    radialLineOnXAxis = createLine(sketch, pointInnerOnXAxis, pointOuterOnXAxis)
    sketch.CreateMonoConstraint(u"horizontality", createReference(radialLineOnXAxis))
    sketch.CreateBiConstraint(u"coincident", createReference(radialLineOnXAxis), createReference(originVertex))

    # 極中心側にロータコアと磁石の境界を作成する。
    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))

    # 磁石外形を作成する。
    magnetInnerEdge = createLine(sketch, pointMagnetInnerOnSymmetry, pointMagnetInnerEnd)
    sketch.CreateBiConstraint(u"perpendicularity", createReference(magnetInnerEdge), createReference(magnetSymmetryLine))
    magnetOuterEdge = createLine(sketch, pointMagnetOuterOnSymmetry, pointMagnetOuterEnd)
    magnetEndLine = createLine(sketch, pointMagnetInnerEnd, pointMagnetOuterEnd)

    # 磁石端部からブリッジまでのスリット外形を作成する。
    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)

    # 各円弧を同心に拘束し、ブリッジ厚さを設定する。
    sketch.CreateBiConstraint(u"concentricity", createReference(rotorInnerArc), createReference(rotorOuterArc))
    sketch.CreateBiConstraint(u"concentricity", createReference(rotorInnerArc), createReference(slitBridgeArc))
    createDistanceConstraint(sketch, rotorInnerArc, slitBridgeArc, EqSlitBridgeThickness)

    # 磁石位置と寸法を設定する。
    createDistanceConstraint(sketch, rotorInnerArc.GetEndVertex(), magnetSymmetryLine.GetStartVertex(), EqMagnetClearance)
    createDistanceConstraint(sketch, magnetInnerEdge, magnetOuterEdge, EqMagnetThickness)
    createDistanceConstraint(sketch, magnetEndLine, magnetSymmetryLine, EqMagnetWidth, useDoubleWidth=True)

    # スリット長さと角度を設定する。
    createDistanceConstraint(sketch, slitInnerExtensionLine.GetStartVertex(), slitInnerExtensionLine.GetEndVertex(), EqSlitLength1)
    createDistanceConstraint(sketch, slitOuterExtensionLine.GetStartVertex(), slitOuterExtensionLine.GetEndVertex(), EqSlitLength2)
    createAngleConstraint(sketch, slitInnerReturnLine, slitInnerExtensionLine, EqSlitAngle1)
    createAngleConstraint(sketch, slitOuterExtensionLine, slitOuterReturnLine, EqSlitAngle2)

    # スリットとブリッジ円弧の接続部にRを作成する。
    filletArc = createSlitCornerFillet(sketch, slitBridgeArc, slitOuterReturnLine)

    # ロータコア領域と磁石領域を構成する輪郭をまとめる。
    rotorCoreEdgeList = [
        radialLineOnXAxis,
        rotorOuterArc,
        coreSymmetryLine,
        magnetOuterEdge,
        slitOuterExtensionLine,
        slitOuterReturnLine,
        filletArc,
        slitBridgeArc,
        slitInnerReturnLine,
        slitInnerExtensionLine,
        magnetInnerEdge,
        innerSymmetryLine,
        rotorInnerArc,
    ]
    magnetEdgeList = [
        magnetSymmetryLine,
        magnetOuterEdge,
        magnetEndLine,
        magnetInnerEdge,
    ]
    # スリット角部にRを設定するため、フィレット対象となる3頂点を取得する。
    slitRegionFilletVertexList = [
        slitInnerExtensionLine.GetEndVertex(),
        slitInnerReturnLine.GetEndVertex(),
        slitOuterExtensionLine.GetEndVertex(),
    ]
    return rotorCoreEdgeList, magnetEdgeList, coreSymmetryLine, magnetSymmetryLine, slitRegionFilletVertexList


def createSlitRegionFillet(sketch, targetVertexList):
    """ロータコア領域のスリット角部3箇所にRを設定する。"""
    regionFillet = sketch.CreateRegionFillet()
    regionFillet.SetName(u"SlitCornerRegionFillet")
    addItemsToReferenceList(regionFillet, u"Target", targetVertexList)
    regionFillet.SetProperty(u"Radius", EqSlitCornerRadius)


def createRotorCorePattern(sketch, rotorCoreRegion, coreSymmetryLine):
    """ロータコア領域を鏡面コピーし、90deg部分モデルへ円形パターン化する。"""
    # 1/2極ピッチの領域を鏡面コピーして1極分の形状を作成する。
    coreMirror = sketch.CreateRegionMirrorCopy()
    coreMirror.SetName(u"CoreMirror1Pole")
    coreMirror.SetMerge(True)
    addItemsToReferenceList(coreMirror, u"Region", [rotorCoreRegion])
    coreMirror.SetProperty(u"OverlappedAreaError", True)
    coreMirror.SetSymmetry(createReference(coreSymmetryLine))

    # 1極分の形状を90deg部分モデルの極数分だけ円形パターン化する。
    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):
    """磁石領域を鏡面コピーし、90deg部分モデルへ円形パターン化する。"""
    # 1/2極ピッチの領域を鏡面コピーして1極分の磁石形状を作成する。
    magnetMirror = sketch.CreateRegionMirrorCopy()
    magnetMirror.SetName(u"MagnetMirror1Pole")
    magnetMirror.SetMerge(True)
    addItemsToReferenceList(magnetMirror, u"Region", [magnetRegion])
    magnetMirror.SetSymmetry(createReference(magnetSymmetryLine))

    # 1極分の磁石形状を90deg部分モデルの極数分だけ円形パターン化する。
    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):
    """スケッチにアウターロータ型IPMモータの2次元形状を作成する。"""
    rotorCoreEdgeList, magnetEdgeList, coreSymmetryLine, magnetSymmetryLine, slitRegionFilletVertexList = createRotorBaseShape(sketch)

    regionOrder = 0

    # ロータコア領域を作成し、名前と表示色を設定する。
    createRegionFromItems(sketch, rotorCoreEdgeList)
    regionOrder += 1
    rotorCoreRegion = getRegionItemByOrder(sketch, regionOrder)
    if rotorCoreRegion.GetScriptTypeName() == u"RegionItem":
        setRegionAppearance(rotorCoreRegion, u"Core", u"gray")

    # 磁石領域を作成し、名前と表示色を設定する。
    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):
    """スケッチを編集可能な状態にして形状を作成する。"""
    sketch.OpenSketch()
    drawRotor(sketch)
    sketch.CloseSketch()


def main():
    """アウターロータ型IPMモータの2次元形状を作成する。"""
    createRotorEquations()
    assm = geomDoc.GetAssembly()
    refXYPlane = assm.GetPlaneXY()
    rotorSketch = assm.CreateSketch(refXYPlane)
    drawInSketch(rotorSketch)
    rotorSketch.SetProperty(u"Name", u"Rotor")


main()

Download Python source code

ファイルご利用の注意点
JMAGスクリプトライブラリをご利用されるに際し、以下をよくお読みいただき、ご同意の上ご利用くださるようお願い申し上げます。
絞込み検索
  • カテゴリー 一覧

JMAG-Express Online
An engineer's diary