【简介】HFSS在射频集成电路设计起到了至关重要的作用,堪称射频集成电路工程师的左膀右臂。
HFSS支持基于Python语言的脚本[1]。如能熟练使用脚本,我们就能避免大量的、重复性的绘图工作,并实现电磁结构设计与仿真的自动化。本文,作者将以简单片上电感为例,介绍HFSS脚本中的常见代码。
之后,作者会陆续发布系列文章,讨论HFSS脚本如何在芯片自动化设计中发挥作用。
| 变量名 | 数值 |
|---|---|
| L | 100 um |
| Lg | 20 um |
| W | 6 um |
| D | 10 um |
在demo.py中依次输入下列代码
import ScriptEnv
ScriptEnv.Initialize("Ansoft.ElectronicsDesktop")
oDesktop.RestoreWindow()
oProject = oDesktop.SetActiveProject("tutorial")
oProject.InsertDesign("HFSS", "Design1", "DrivenModal", "")
oDesign = oProject.SetActiveDesign("Design1")
oEditor = oDesign.SetActiveEditor("3D Modeler")
oEditor.SetModelUnits(
[
"NAME:Units Parameter",
"Units:=" , "um",
"Rescale:=" , False
])
oEditor = oDesign.SetActiveEditor("3D Modeler")
oEditor.CreateBox(
[
"NAME:BoxParameters",
"XPosition:=" , "3cm",
"YPosition:=" , "3cm",
"ZPosition:=" , "3cm",
"XSize:=" , "-6cm",
"YSize:=" , "-6cm",
"ZSize:=" , "-6cm"
],
[
"NAME:Attributes",
"Name:=" , "Airbox",
"Flags:=" , "",
"Color:=" , "(143 175 143)",
"Transparency:=" , 1,
"PartCoordinateSystem:=", "Global",
"UDMId:=" , "",
"MaterialValue:=" , "\"vacuum\"",
"SurfaceMaterialValue:=", "\"\"",
"SolveInside:=" , True,
"ShellElement:=" , False,
"ShellElementThickness:=", "0mm",
"IsMaterialEditable:=" , True,
"UseMaterialAppearance:=", False,
"IsLightweight:=" , False
])
oEditor = oDesign.SetActiveEditor("3D Modeler")
oEditor.AssignMaterial(
[
"NAME:Selections",
"AllowRegionDependentPartSelectionForPMLCreation:=", True,
"AllowRegionSelectionForPMLCreation:=", True,
"Selections:=" , "Airbox"
],
[
"NAME:Attributes",
"MaterialValue:=" , "\"air\"",
"SolveInside:=" , True,
"ShellElement:=" , False,
"ShellElementThickness:=", "nan ",
"IsMaterialEditable:=" , True,
"UseMaterialAppearance:=", False,
"IsLightweight:=" , False
])
oModule = oDesign.GetModule("BoundarySetup")
oModule.AssignRadiation(
[
"NAME:Rad1",
"Objects:=" , ["Airbox"],
"IsFssReference:=" , False,
"IsForPML:=" , False
])
oDefinitionManager = oProject.GetDefinitionManager()
oDefinitionManager.AddMaterial(
[
"NAME:silicon_bulk",
"CoordinateSystemType:=", "Cartesian",
"BulkOrSurfaceType:=" , 1,
[
"NAME:PhysicsTypes",
"set:=" , ["Electromagnetic"]
],
"permittivity:=" , "11.7",
"conductivity:=" , "0.02"
])
oDefinitionManager.AddMaterial(
[
"NAME:silicon_dioxide_pro",
"CoordinateSystemType:=", "Cartesian",
"BulkOrSurfaceType:=" , 1,
[
"NAME:PhysicsTypes",
"set:=" , ["Electromagnetic"]
],
"permittivity:=" , "4.0",
"conductivity:=" , "0.00"
])
oEditor = oDesign.SetActiveEditor("3D Modeler")
oEditor.CreateBox(
[
"NAME:BoxParameters",
"XPosition:=" , "0.5mm",
"YPosition:=" , "0.5mm",
"ZPosition:=" , "0cm",
"XSize:=" , "-1mm",
"YSize:=" , "-1mm",
"ZSize:=" , "300um"
],
[
"NAME:Attributes",
"Name:=" , "Silicon_bulk",
"Flags:=" , "",
"Color:=" , "(143 175 143)",
"Transparency:=" , 1,
"PartCoordinateSystem:=", "Global",
"UDMId:=" , "",
"MaterialValue:=" , "\"silicon_bulk\"",
"SurfaceMaterialValue:=", "\"\"",
"SolveInside:=" , True,
"ShellElement:=" , False,
"ShellElementThickness:=", "0mm",
"IsMaterialEditable:=" , True,
"UseMaterialAppearance:=", False,
"IsLightweight:=" , False
])
oEditor.CreateBox(
[
"NAME:BoxParameters",
"XPosition:=" , "0.5mm",
"YPosition:=" , "0.5mm",
"ZPosition:=" , "300um",
"XSize:=" , "-1mm",
"YSize:=" , "-1mm",
"ZSize:=" , "10.8um"
],
[
"NAME:Attributes",
"Name:=" , "Silicon_dioxide",
"Flags:=" , "",
"Color:=" , "(143 175 143)",
"Transparency:=" , 1,
"PartCoordinateSystem:=", "Global",
"UDMId:=" , "",
"MaterialValue:=" , "\"silicon_dioxide_pro\"",
"SurfaceMaterialValue:=", "\"\"",
"SolveInside:=" , True,
"ShellElement:=" , False,
"ShellElementThickness:=", "0mm",
"IsMaterialEditable:=" , True,
"UseMaterialAppearance:=", False,
"IsLightweight:=" , False
])
oEditor.CreateBox(
[
"NAME:BoxParameters",
"XPosition:=" , "0.5mm",
"YPosition:=" , "0.5mm",
"ZPosition:=" , "310.8um",
"XSize:=" , "-1mm",
"YSize:=" , "-1mm",
"ZSize:=" , "0.6um"
],
[
"NAME:Attributes",
"Name:=" , "Protect_layer",
"Flags:=" , "",
"Color:=" , "(143 175 143)",
"Transparency:=" , 1,
"PartCoordinateSystem:=", "Global",
"UDMId:=" , "",
"MaterialValue:=" , "\"silicon_nitrate\"",
"SurfaceMaterialValue:=", "\"\"",
"SolveInside:=" , True,
"ShellElement:=" , False,
"ShellElementThickness:=", "0mm",
"IsMaterialEditable:=" , True,
"UseMaterialAppearance:=", False,
"IsLightweight:=" , False
])
oEditor.CreateRelativeCS(
[
"NAME:RelativeCSParameters",
"Mode:=" , "Axis/Position",
"OriginX:=" , "0um",
"OriginY:=" , "0um",
"OriginZ:=" , "306um",
"XAxisXvec:=" , "1um",
"XAxisYvec:=" , "0um",
"XAxisZvec:=" , "0um",
"YAxisXvec:=" , "0um",
"YAxisYvec:=" , "1um",
"YAxisZvec:=" , "0um"
],
[
"NAME:Attributes",
"Name:=" , "IND"
])
oEditor.SetWCS(
[
"NAME:SetWCS Parameter",
"Working Coordinate System:=", "IND",
"RegionDepCSOk:=" , False
])
oDesign.ChangeProperty(
[
"NAME:AllTabs",
[
"NAME:LocalVariableTab",
[
"NAME:PropServers",
"LocalVariables"
],
[
"NAME:NewProps",
[
"NAME:L",
"PropType:=" , "VariableProp",
"UserDef:=" , True,
"Value:=" , "100um"
],
[
"NAME:W",
"PropType:=" , "VariableProp",
"UserDef:=" , True,
"Value:=" , "6um"
],
[
"NAME:D",
"PropType:=" , "VariableProp",
"UserDef:=" , True,
"Value:=" , "10um"
],
[
"NAME:Lg",
"PropType:=" , "VariableProp",
"UserDef:=" , True,
"Value:=" , "20um"
]
]
]
])
oEditor.CreateBox(
[
"NAME:BoxParameters",
"XPosition:=" , "L/2+W/2",
"YPosition:=" , "L/2+W/2",
"ZPosition:=" , "0",
"XSize:=" , "-L-W",
"YSize:=" , "-L-W",
"ZSize:=" , "3um"
],
[
"NAME:Attributes",
"Name:=" , "BOX1",
"Flags:=" , "",
"Color:=" , "(255 128 0)",
"Transparency:=" , 0,
"PartCoordinateSystem:=", "Global",
"UDMId:=" , "",
"MaterialValue:=" , "\"aluminum\"",
"SurfaceMaterialValue:=", "\"\"",
"SolveInside:=" , False,
"ShellElement:=" , False,
"ShellElementThickness:=", "0mm",
"IsMaterialEditable:=" , True,
"UseMaterialAppearance:=", False,
"IsLightweight:=" , False
])
oEditor.CreateBox(
[
"NAME:BoxParameters",
"XPosition:=" , "L/2-W/2",
"YPosition:=" , "L/2-W/2",
"ZPosition:=" , "0",
"XSize:=" , "-L+W",
"YSize:=" , "-L+W",
"ZSize:=" , "3um"
],
[
"NAME:Attributes",
"Name:=" , "BOX2",
"Flags:=" , "",
"Color:=" , "(255 128 0)",
"Transparency:=" , 0,
"PartCoordinateSystem:=", "Global",
"UDMId:=" , "",
"MaterialValue:=" , "\"aluminum\"",
"SurfaceMaterialValue:=", "\"\"",
"SolveInside:=" , False,
"ShellElement:=" , False,
"ShellElementThickness:=", "0mm",
"IsMaterialEditable:=" , True,
"UseMaterialAppearance:=", False,
"IsLightweight:=" , False
])
oEditor.CreateBox(
[
"NAME:BoxParameters",
"XPosition:=" , "-L/2-W/2",
"YPosition:=" , "-D/2",
"ZPosition:=" , "0",
"XSize:=" , "W",
"YSize:=" , "D",
"ZSize:=" , "3um"
],
[
"NAME:Attributes",
"Name:=" , "BOX3",
"Flags:=" , "",
"Color:=" , "(255 128 0)",
"Transparency:=" , 0,
"PartCoordinateSystem:=", "Global",
"UDMId:=" , "",
"MaterialValue:=" , "\"aluminum\"",
"SurfaceMaterialValue:=", "\"\"",
"SolveInside:=" , False,
"ShellElement:=" , False,
"ShellElementThickness:=", "0mm",
"IsMaterialEditable:=" , True,
"UseMaterialAppearance:=", False,
"IsLightweight:=" , False
])
oEditor.CreateBox(
[
"NAME:BoxParameters",
"XPosition:=" , "-L/2-W/2",
"YPosition:=" , "-D/2",
"ZPosition:=" , "0",
"XSize:=" , "-Lg",
"YSize:=" , "-W",
"ZSize:=" , "3um"
],
[
"NAME:Attributes",
"Name:=" , "BOX4",
"Flags:=" , "",
"Color:=" , "(255 128 0)",
"Transparency:=" , 0,
"PartCoordinateSystem:=", "Global",
"UDMId:=" , "",
"MaterialValue:=" , "\"aluminum\"",
"SurfaceMaterialValue:=", "\"\"",
"SolveInside:=" , False,
"ShellElement:=" , False,
"ShellElementThickness:=", "0mm",
"IsMaterialEditable:=" , True,
"UseMaterialAppearance:=", False,
"IsLightweight:=" , False
])
oEditor.CreateBox(
[
"NAME:BoxParameters",
"XPosition:=" , "-L/2-W/2",
"YPosition:=" , "D/2",
"ZPosition:=" , "0",
"XSize:=" , "-Lg",
"YSize:=" , "W",
"ZSize:=" , "3um"
],
[
"NAME:Attributes",
"Name:=" , "BOX5",
"Flags:=" , "",
"Color:=" , "(255 128 0)",
"Transparency:=" , 0,
"PartCoordinateSystem:=", "Global",
"UDMId:=" , "",
"MaterialValue:=" , "\"aluminum\"",
"SurfaceMaterialValue:=", "\"\"",
"SolveInside:=" , False,
"ShellElement:=" , False,
"ShellElementThickness:=", "0mm",
"IsMaterialEditable:=" , True,
"UseMaterialAppearance:=", False,
"IsLightweight:=" , False
])
oEditor.Subtract(
[
"NAME:Selections",
"Blank Parts:=" , "BOX1",
"Tool Parts:=" , "BOX2,BOX3"
],
[
"NAME:SubtractParameters",
"KeepOriginals:=" , False
])
oEditor.Unite(
[
"NAME:Selections",
"Selections:=" , "BOX1,BOX4,BOX5"
],
[
"NAME:UniteParameters",
"KeepOriginals:=" , False
])
oEditor.CreateBox(
[
"NAME:BoxParameters",
"XPosition:=" , "-L/2-W/2-Lg-40um",
"YPosition:=" , "-L/2-W/2-Lg-40um",
"ZPosition:=" , "-4um",
"XSize:=" , "L+W+2*Lg+80um",
"YSize:=" , "L+W+2*Lg+80um",
"ZSize:=" , "1um"
],
[
"NAME:Attributes",
"Name:=" , "GND",
"Flags:=" , "",
"Color:=" , "(0 0 255)",
"Transparency:=" , 0,
"PartCoordinateSystem:=", "Global",
"UDMId:=" , "",
"MaterialValue:=" , "\"aluminum\"",
"SurfaceMaterialValue:=", "\"\"",
"SolveInside:=" , False,
"ShellElement:=" , False,
"ShellElementThickness:=", "0mm",
"IsMaterialEditable:=" , True,
"UseMaterialAppearance:=", False,
"IsLightweight:=" , False
])
oEditor.CreateBox(
[
"NAME:BoxParameters",
"XPosition:=" , "-L/2-W/2-Lg",
"YPosition:=" , "-L/2-W/2-Lg",
"ZPosition:=" , "-4um",
"XSize:=" , "L+W+2*Lg",
"YSize:=" , "L+W+2*Lg",
"ZSize:=" , "1um"
],
[
"NAME:Attributes",
"Name:=" , "BOX6",
"Flags:=" , "",
"Color:=" , "(0 0 255)",
"Transparency:=" , 0,
"PartCoordinateSystem:=", "Global",
"UDMId:=" , "",
"MaterialValue:=" , "\"aluminum\"",
"SurfaceMaterialValue:=", "\"\"",
"SolveInside:=" , False,
"ShellElement:=" , False,
"ShellElementThickness:=", "0mm",
"IsMaterialEditable:=" , True,
"UseMaterialAppearance:=", False,
"IsLightweight:=" , False
])
oEditor.Subtract(
[
"NAME:Selections",
"Blank Parts:=" , "GND",
"Tool Parts:=" , "BOX6"
],
[
"NAME:SubtractParameters",
"KeepOriginals:=" , False
])
oEditor.CreateRectangle(
[
"NAME:RectangleParameters",
"IsCovered:=" , True,
"XStart:=" , "-2um",
"YStart:=" , "-5um",
"ZStart:=" , "0um",
"Width:=" , "4um",
"Height:=" , "10um",
"WhichAxis:=" , "Z"
],
[
"NAME:Attributes",
"Name:=" , "Rectangle1",
"Flags:=" , "",
"Color:=" , "(143 175 143)",
"Transparency:=" , 0,
"PartCoordinateSystem:=", "Global",
"UDMId:=" , "",
"MaterialValue:=" , "\"vacuum\"",
"SurfaceMaterialValue:=", "\"\"",
"SolveInside:=" , True,
"ShellElement:=" , False,
"ShellElementThickness:=", "0um",
"IsMaterialEditable:=" , True,
"UseMaterialAppearance:=", False,
"IsLightweight:=" , False
])
oModule = oDesign.GetModule("BoundarySetup")
oModule.AssignLumpedPort(
[
"NAME:1",
"Objects:=" , ["Rectangle1"],
"DoDeembed:=" , True,
"RenormalizeAllTerminals:=", True,
[
"NAME:Modes",
[
"NAME:Mode1",
"ModeNum:=" , 1,
"UseIntLine:=" , True,
[
"NAME:IntLine",
"Start:=" , ["0um","-5um","306um"],
"End:=" , ["0um","5um","306um"]
],
"AlignmentGroup:=" , 0,
"CharImp:=" , "Zpi",
"RenormImp:=" , "50ohm"
]
],
"ShowReporterFilter:=" , False,
"ReporterFilter:=" , [True],
"Impedance:=" , "50ohm"
])
oEditor.ChangeProperty(
[
"NAME:AllTabs",
[
"NAME:Geometry3DCmdTab",
[
"NAME:PropServers",
"Rectangle1:CreateRectangle:1"
],
[
"NAME:ChangedProps",
[
"NAME:Position",
"X:=" , "-Lg-L/2-W/2",
"Y:=" , "-D/2",
"Z:=" , "0um"
],
[
"NAME:YSize",
"Value:=" , "D"
],
[
"NAME:XSize",
"Value:=" , "4um"
]
]
]
])
oModule = oDesign.GetModule("AnalysisSetup")
oModule.InsertSetup("HfssDriven",
[
"NAME:Setup1",
"SolveType:=" , "Single",
"Frequency:=" , "3GHz",
"MaxDeltaS:=" , 0.01,
"UseMatrixConv:=" , False,
"MaximumPasses:=" , 10,
"MinimumPasses:=" , 1,
"MinimumConvergedPasses:=", 2,
"PercentRefinement:=" , 30,
"IsEnabled:=" , True,
[
"NAME:MeshLink",
"ImportMesh:=" , False
],
"BasisOrder:=" , 1,
"DoLambdaRefine:=" , True,
"DoMaterialLambda:=" , True,
"SetLambdaTarget:=" , False,
"Target:=" , 0.3333,
"UseMaxTetIncrease:=" , False,
"PortAccuracy:=" , 2,
"UseABCOnPort:=" , False,
"SetPortMinMaxTri:=" , False,
"UseDomains:=" , False,
"UseIterativeSolver:=" , False,
"SaveRadFieldsOnly:=" , False,
"SaveAnyFields:=" , True,
"IESolverType:=" , "Auto",
"LambdaTargetForIESolver:=", 0.15,
"UseDefaultLambdaTgtForIESolver:=", True,
"IE Solver Accuracy:=" , "Balanced"
])
oModule.InsertFrequencySweep("Setup1",
[
"NAME:Sweep",
"IsEnabled:=" , True,
"RangeType:=" , "LinearCount",
"RangeStart:=" , "1GHz",
"RangeEnd:=" , "5GHz",
"RangeCount:=" , 401,
"Type:=" , "Interpolating",
"SaveFields:=" , False,
"SaveRadFields:=" , False,
"InterpTolerance:=" , 0.5,
"InterpMaxSolns:=" , 250,
"InterpMinSolns:=" , 0,
"InterpMinSubranges:=" , 1,
"ExtrapToDC:=" , False,
"InterpUseS:=" , True,
"InterpUsePortImped:=" , False,
"InterpUsePropConst:=" , True,
"UseDerivativeConvergence:=", False,
"InterpDerivTolerance:=", 0.2,
"UseFullBasis:=" , True,
"EnforcePassivity:=" , True,
"PassivityErrorTolerance:=", 0.0001
])
oProject.Save()
oDesign.Analyze("Setup1 : Sweep")
oModule = oDesign.GetModule("OutputVariable")
oModule.CreateOutputVariable("Q", "im(Z11)/re(Z11)", "Setup1 : Sweep", "Modal Solution Data", [])
oModule.CreateOutputVariable("L_ind", "im(Z11)/2/pi/freq*1e9", "Setup1 : Sweep", "Modal Solution Data", [])
oModule.CreateReport("Output Variables Plot 1", "Modal Solution Data", "Rectangular Plot", "Setup1 : Sweep",
[
"Domain:=" , "Sweep"
],
[
"Freq:=" , ["All"],
"L:=" , ["Nominal"],
"W:=" , ["Nominal"],
"https://www.gofarlic.com=" , ["Nominal"],
"Lg:=" , ["Nominal"]
],
[
"X Component:=" , "Freq",
"Y Component:=" , ["Q"]
])
oModule.CreateReport("Output Variables Plot 2", "Modal Solution Data", "Rectangular Plot", "Setup1 : Sweep",
[
"Domain:=" , "Sweep"
],
[
"Freq:=" , ["All"],
"L:=" , ["Nominal"],
"W:=" , ["Nominal"],
"https://www.gofarlic.com=" , ["Nominal"],
"Lg:=" , ["Nominal"]
],
[
"X Component:=" , "Freq",
"Y Component:=" , ["L_ind"]
])
上述脚本自动完成了HFSS建模,仿真,和输出仿真结果