Desktop Scripting With IronPython
Desktop Scripting With IronPython
This document describes IronPython briefly and then goes on to describe the desktop provided
IronPython scripting console and scripting with IronPython. You can open an IronPython Command Window by clicking Tools>Command Window.
The document assumes that you know how desktop scripting works using VBScript or Javascript.
Introduction to IronPython
IronPython Mini-cookbook
Translating Script commands from VBScript to IronPython
Scripting Using Iron Python: Putting it all Together
IronPython Samples
Creating User Defined Primitives and User Defined Models in Python Scripts
Related Topics
Desktop Scripting with IronPython 22-1
ANSYS Electromagnetics Suite 15.0 - SAS IP, Inc. All rights reserved. - Contains proprietary and confidential information
of ANSYS, Inc. and its subsidiaries and affiliates.
Introduction to IronPython
IronPython is an implementation of the Python programming language targeting the .NET runtime.
What this means in practical terms is that IronPython uses the Python programming language syntax and standard python libraries and can additionally use .NET classes and objects to give one the
best of both worlds. This usage of .NET classes is fairly seamless in that a class defined in a .NET
assembly can be used as a base class of a python class.
Scope
Functioning as a tutorial on Python or IronPython is way out of the scope of this document. There
are several excellent resources online that do a very good job in that regard. This document only
attempts to provide a limited introduction to IronPython as used to script ANSYS EM products.
This document is also not a tutorial on the scripting of ANSYS EM products. It complements the
existing scripting guide (available from a product's Help menu) and provides a pythonic interpretation of that information. The reader might have to refer to either the scripting guide or recorded
samples of VBScript to follow some of the sections.
Python compatibility
The version of IronPython in use is 2.6.1 and built on the .NET framework version 2.0: this version
targets Python 2.6 language compatibility. While most python files will execute under IronPython
with no changes, python libraries that make use of extensions written in the C programming language (NumPy or SciPy for instance), are not expected to work under IronPython. In such cases, it
might be possible to locate .NET implementation of such libraries or explore the use of IronClad.
(http://code.google.com/p/ironclad/).
Advantages of IronPython
The advantages that IronPython use provides are significant:
Python has a large eco-system with plenty of supporting libraries, Visual IDEs and debuggers.
It is actively developed and enhanced.
IronPython, in addition, has access to the entire .NET eco system. This allows us, for instance,
to create a modern GUI using the System.Windows.Forms assembly from IronPython code
and call any other .NET assembly for that matter.
The use of IronPython's technologies enables the ability to interactively script Desktop (feature
in development). This allows better discovery of the scripting APIs as well as directly programming to the scripting API in python, a language more tractable and platform independent
compared with VBScript.
The Python syntax of dictionaries is somewhat easier to read and write when supplying arguments to the scripting methods.
Related Topics
IronPython Mini-cookbook
Translating Script commands from VBScript to IronPython
Scripting Using Iron Python: Putting it all Together
Desktop Scripting with IronPython 22-3
ANSYS Electromagnetics Suite 15.0 - SAS IP, Inc. All rights reserved. - Contains proprietary and confidential information
of ANSYS, Inc. and its subsidiaries and affiliates.
IronPython Samples
IronPython Mini-cookbook
While a tutorial on Python syntax is beyond the scope of this document, it will present simple counterparts the VBScript constructs that users tend to regularly use.
Comments
Assigning/Creating variables
Create Lists/Arrays
Create Dictionaries/Maps
Boolean Values
Converting Numbers to Strings and Vice Versa
String Formatting/Concatenation
Looping over Lists
Looping over a Range
A Note About Indentation
Additional Sections:
Obtaining More Information
Discovering Methods
Help on a Method
Comments
VBScript
IronPython
Assigning/Creating Variables
' Declare with a Dim
VBScript
IronPython
# No Set syntax. Simply create and assign
Dim oDesktop
oDesktop = oApp.GetAppDesktop()
Create Lists/Arrays
VBScript
' Declare as array of String with 11
IronPython
# Declare an empty array
myEmptyArray = []
myArray(1) = "bye"
myInitedArray = [ 1, 2, 3, 4, 5]
' known
ReDim array2(0 to 2) as String
# append to an array
array2(0) = "this"
mixed.append( 3.5 )
array2(1) = "also"
Create Dictionaries/Maps
VBScript
' No direct equivalent is available as
IronPython
# an IronPython dictionary is a collection of
Boolean Values
VBScript
' Boolean literals are in lower case
IronPython
# The first letter is capitalized
true
True
false
False
Converting Numbers to Strings and Vice Versa
VBScript
' Use CInt, CDbl, CBool, CLng
IronPython
# use the integer() or float() or double()
# casting to.
strInt = "3"
Dim n = CInt(nStr)
intVal = int(strVal)
floatVal = float(strVal)
Dim v, vStr
v = 100
vStr = CStr(v)
strVal = str(42)
strVal = str(42.345)
String formatting/concatenation
VBScript
IronPython
' operator
str1 = "hello"
str2 = "world"
num = 10
IronPython
vals = [1, 3, 3.456]
myArray(0) = "alpha"
myArray(1) = "bravo"
myArray(2) = "charlie"
def process(val):
return 2*val
# is of the form
# for variable_name in array ':'
Print i
Next
# <indent> statement2
for i in vals:
print i
print " -> " process(i)
Looping over a range
VBScript
' Loop over a range, specify start, end
IronPython
# prints out values from 0 through 9
For i = 0 To 10 Step 1
print i
Print i
Next
Related Topics
A Note About Indentation
Obtaining More Information
Discovering Methods
Help on a Method
Introduction to IronPython
Translating Script commands from VBScript to IronPython
Scripting Using Iron Python: Putting it all Together
IronPython Samples
Any statement that introduces a block of code should be written such that every line of the block
has the same indent (leading spaces or tabs) and the indent should be at least one more than the
indent of the introducing statement.
# define a function that starts at 0 indentation.
def multInt(a,b):
# every line following the def multInt which is expected
# to be a part of the function, must have the indent used
# by the first line of the function (3 spaces)
# here we introduce one more block, the if condition
# each line that belongs to the body of this func should
# have an indent that is more than the indent used by the
# if statement
If a%2 == 0:
# I am using an indent 2 more than the parent. i.e. 5
# spaces in total
return (a * b) + 100
else:
return (a * b) + 1000
Sample Script 1: Describing python indentation
Related Topics
Obtaining More Information
Discovering Methods
Help on a Method
Introduction to IronPython
Translating Script commands from VBScript to IronPython
Scripting Using Iron Python: Putting it all Together
IronPython Samples
by clicking Tools>Command Window. You can also aces the command window executable,
Ipy.exe, from the IronPython directory under the ANSYS EM product installation directory. You
can use this window to interactively enter python commands (any of the pure python samples in
this document)
Related Topics
Discovering Methods
Help on a Method
Introduction to IronPython
Translating Script commands from VBScript to IronPython
Scripting Using Iron Python: Putting it all Together
IronPython Samples
Discovering Methods
For instance, if you want to list all methods available in the string module, you would type in
"import string" to import the module first and then type in "dir(string)". You will get a list of all the
methods available (as well as some __somename__ internal names that can be ignored)
Related Topics
Obtaining More Information
Help on a Method
Introduction to IronPython
Translating Script commands from VBScript to IronPython
Scripting Using Iron Python: Putting it all Together
IronPython Samples
Help on a Method
Once you know a function name (maybe you see something you like from the dir(string) listing
above), you can get more help on it using the builtin help method. For instance, executing
help(string.split) in the IronPython Command Window displays the following:
Related Topics
Obtaining More Information
Discovering Methods
Introduction to IronPython
Translating Script commands from VBScript to IronPython
Scripting Using Iron Python: Putting it all Together
IronPython Samples
A primitive value
An array of primitive values
Another named array
A key, of the form "keyName:=" followed by
A primitive value
A function (described next)
Desktop Scripting with IronPython 22-13
ANSYS Electromagnetics Suite 15.0 - SAS IP, Inc. All rights reserved. - Contains proprietary and confidential information
of ANSYS, Inc. and its subsidiaries and affiliates.
Named Function
Named functions are arrays which start with Array( and do not have a leading "NAME:name"
item. They are always introduced by a key and can contain comma separated values of the following type:
A primitive value
A key (of the form "keyName:=") followed by
A primitive value
Another function (nested function)
Related Topics
Translating Script commands from VBScript to IronPython
"dB20(S(3,1))",
"dB20(S(3,2))",
"dB20(S(3,3))")), Array()
If you see a VBScript snippet that looks like a VBScript Sub-Routine, remember to add parentheses.
If you see a VBScript function that has no arguments and no parenthesis, remember to add
them around an empty argument list.
The parentheses change is the only one to keep in mind when converting VBScript function calls
syntax to IronPython.
Return Values
Primitive Method Arguments
Named Array Argument
Named Array Values with All Key Value Pairs
Named Arrays with Nested Named Arrays
Function Blocks
Return Values
VBscript return values are sometimes assigned via the Set declaration. IronPython return values are
simple assignment (see the cookbook chapter)
Related Topics
Converting VBScript Function calls to IronPython Syntax
, "Cone1",
"Flags:="
"Color:="
, "",
,
"Transparency:=" , 0,
"PartCoordinateSystem:=" , "Global",
"UDMId:=" , "",
"MaterialValue:=" , "\"vacuum\"",
22-16 Desktop Scripting with IronPython
ANSYS Electromagnetics Suite 15.0 - SAS IP, Inc. All rights reserved. - Contains proprietary and confidential information
of ANSYS, Inc. and its subsidiaries and affiliates.
"SolveInside:="
, True
])
Sample Script 5: Create a cone in IronPython
Note that the formatting (which helps readability immensely) is not really needed. All that had to
be done was
Related Topics
Converting VBScript Function calls to IronPython Syntax
oEditor.CreateCone(
{
"NAME" : "ConeParameters",
"XCenter": "0mm",
"YCenter": "0mm",
"ZCenter": "0mm",
"WhichAxis": "Z",
"Height": "2mm",
"BottomRadius": "1.56204993518133mm",
"TopRadius": "0mm"
Desktop Scripting with IronPython 22-17
ANSYS Electromagnetics Suite 15.0 - SAS IP, Inc. All rights reserved. - Contains proprietary and confidential information
of ANSYS, Inc. and its subsidiaries and affiliates.
},
{
"NAME": "Attributes",
"Name": "Cone1",
"Flags": "",
"Color":
"Transparency": 0,
"PartCoordinateSystem": "Global",
"UDMId": "",
"MaterialValue" : "\"vacuum\"",
"SolveInside": True
}
Sample Script 6: CreateCone in IronPython using dictionary syntax
Related Topics
Converting VBScript Function calls to IronPython Syntax
Sample Script 7: Named array with nested named array in array syntax
The above named array with a nested named array (after conversion to IronPython as named array)
can be converted to a dictionary as well. The dictionary can take any of the following forms
{ "NAME": "name",
"key1": 1,
"key2": 2,
22-18 Desktop Scripting with IronPython
ANSYS Electromagnetics Suite 15.0 - SAS IP, Inc. All rights reserved. - Contains proprietary and confidential information
of ANSYS, Inc. and its subsidiaries and affiliates.
: 255
}
}
Sample Script 10: Nested named array with optional "NAME:" field
Related Topics
Converting VBScript Function calls to IronPython Syntax
Function Blocks
Function blocks in VBScript argument syntax are represented as arrays without the "NAME:.."
field. However, functions are always introduced by a key in a parent structure. Function blocks can
therefore never exist as a top-level argument. They are only found as the value pairs inside a named
array or inside another function block.
Note
Function blocks and their items cannot be converted to dictionaries even though they
might be composed entirely of key value pairs.
The reason for this is the need to main the user-entered order. Every item in a function block is
expect to be transmitted to the script method in exactly the same order as typed out and this is
impossible to achieve when a dictionary is used (as the keys get reordered according to the dictionary's internal tree/key sorting scheme).
Note
When you see a function block, simply replace the Array( ) delimiters with the python
array delimiters [ ]
Related Topics
Converting VBScript Function calls to IronPython Syntax
Tools > Run Script menu item, select "IronPython" from the file type drop down
Launch the product with a script argument, e.g., HFSS -runscript someScript.py
Register an IronPython script as an external tool using the Tools > External Tools menu item.
When desktop executes a script, it does so in an execution environment setup with predefined variables and functions. These predefined variables and functions are how the script communicates
with the desktop and they come in three flavors.
Script Argument for IronPython
Script Objects for IronPython
Methods for IronPython
The use of these objects is done as per the individual product scripting guides with some syntax
adjustments made for the parameters to account for the IronPython differences.
Related Topics
IronPython Script Execution Environment
AddErrorMessage(str), AddWarningMessage(str), AddInfoMessage(str) and AddFatalMessage(str) this family of methods allows a script to add messages to the product's message window. All methods take a python string.
RunScriptFile(filename) runs the contents of the supplied file as a script. The type of the
script (Javascript/VBScript) is deduced from the file extension.
RunScriptCommand(CommandString) runs the supplied script text. The language of the text
is controlled by a previous call to SetScriptingLanguageToJavascript() or SetScriptingLanguageToVBScript()
RunModuleCommand(CommandString,ModuleName, DesignName=None, ProjectName=None) runs the supplied script text. The text is expected to be a single line and be a
method call on a oModule object. The design targeted is resolved using the supplied optional
DesignName and ProjectName parameters and the oModule object is initialized using the supplied Module name on that resolved design.
RunEditorCommand(CommandString, EditorName,DesignName=None, ProjectName=None) runs the supplied script text. The text is expected to be a single line and be a
method call on a oEditor object. The design targeted is resolved using the supplied optional
DesignName and ProjectName parameters and the oEditor object is initialized using the supplied Editor name on that resolved design.
Desktop Scripting with IronPython 22-23
ANSYS Electromagnetics Suite 15.0 - SAS IP, Inc. All rights reserved. - Contains proprietary and confidential information
of ANSYS, Inc. and its subsidiaries and affiliates.
Related Topics
IronPython Script Execution Environment
"3mm", _
"" & Chr(34) & "vacuum" & Chr(34) & "", "SolveInside:=",
true)
"""
SetScriptingLanguageToVBScript()
RunScriptCommand(coneScript)
Sample Script 11: Hybrid VBScript + IronPython scripting: parameterized Cone
Creation
Even though recorded VBScript is used for scripting, the incremental functionality that is provided
using IronPython is the ability to write a GUI using IronPython/.NET, collect information from the
user and then modify or generate the VBScript commands to actually script the ANSYS EM desktop. This GUI functionality is cross platform and a significant positive. The following example
demonstrates a contrived use of a .NET window form to display the argument supplied to the IronPython script (via the ScriptArgument variable).
#import the CLR references
import clr
clr.AddReference("System.Windows.Forms")
from System.Windows.Forms import Application, Form, Label,
Button, DockStyle
# the GUI form to show some text
# the class below derives from From (System.Windows.Forms.Form)
# imported above from the .NET assembly.
class ShowPropertiesForm(Form):
def __init__(self, name, text):
self.Name = name
self._label = Label()
self._label.Text = text
self._label.Dock = DockStyle.Fill
_button = Button()
Desktop Scripting with IronPython 22-25
ANSYS Electromagnetics Suite 15.0 - SAS IP, Inc. All rights reserved. - Contains proprietary and confidential information
of ANSYS, Inc. and its subsidiaries and affiliates.
_button.Text = "Close"
_button.Dock = DockStyle.Bottom
_button.Click += self._buttonPressed
self.Controls.Add(self._label)
self.Controls.Add(_button)
def _buttonPressed(self,sender,args):
self.Close()
#---------------------------------------------------# Main script code
#---------------------------------------------------#display the ScriptArgument variable as the text label
# in the form.
gui = ShowPropertiesForm("Sample Form", ScriptArgument)
# This makes it a modal dialog.
gui.ShowDialog()
# the following will make it a non-modal dialog
#Application.Run(gui)
Sample Script 12: Demonstrates the use of a .NET form from IronPython
While creating cross platform user interfaces from scripts is one of the main motivations driving
the adoption of IronPython, any .NET assembly can be used with the caveat that Linux use requires
Mono compatibility of any used assemblies.
While this hybrid approach is useful when you have existing VBScript commands that you want to
reuse or when you want to quickly parameterize a recorded sample, the one significant limitation of
this approach is the inability to capture return values from VBScript or JavaScript calls that do
return something. Full two way communication with the product requires the use of pure IronPython to directly invoke the script objects as described below.
Related Topics
IronPython Script Execution Environment
existing script assets in this fashion and mixing with IronPython code for new functionality as
needed is a viable and option.
Access to the application scripting objects is provided via the predefined oDesktop object (as listed
in Script Objects). Interacting with the script objects is very natural, method calls are made just like
in VBScript except that the argument syntax is somewhat simplified to follow natural Python syntax. All primitive types (string, integer, double) map to the natural primitive types in python. The
only differences from the VBScript syntax are seen when specifying array type arguments. The differences are described in earlier chapters.
Note
The typical VBScript calls to obtain the registered COM scripting interface via
CreateObject calls and then obtain the oDesktop object from it using the
GetAppDesktop() is not needed (or even supported on all platforms). Since all scripting
occurs in the context of a running workbench, the available Desktop object is always
provided and expected to be used directly.
Scripting using the IronPython scripting API is very much like scripting with VBScript except that
The samples section lists a collection of pure IronPython snippets: these, along with the various
script snippets listed in this document should serve as a guide and reference.
Related Topics
IronPython Script Execution Environment
IronPython Samples
Change property
The following snippets show how a change property command (in this case, to change the color of
a cone) looks in VBScript and its two possible IronPython variants.
oEditor.ChangeProperty Array("NAME:AllTabs",
Array("NAME:Geometry3DAttributeTab",_
Array("NAME:PropServers",
"Cone1"), _
Array("NAME:ChangedProps", _
Array("NAME:Color", "R:=", 255, "G:=", 255, "B:=",
0))))
"Cone1"],
["NAME:ChangedProps",
["NAME:Color", "R:=", 0, "G:=", 0, "B:=", 64]
]
]
])
Sample Script 14: ChangeProperty command to change color of cone using Python
arrays
Any time there are named arrays composed purely of key-value pairs, they can always be represented using a Python dictionary, irrespective of the nesting of said named array.
oEditor.ChangeProperty(
["NAME:AllTabs",
["NAME:Geometry3DAttributeTab",
["NAME:PropServers",
"Cone1"],
["NAME:ChangedProps",
{
"NAME":"Color",
"R"
"G"
: 0,
: 64,
"B"
: 0
}]]
])
Sample Script 15: ChangeProperty command to change the color of a cone using
Python arrays and dictionaries
Create a Cone using IronPython
Most scripting tasks using IronPython are expected to be formatted as the example below. One
starts with the predefined oDesktop object and drills down to the design, editors, modules etc and
issues any required commands on the object while formatting the script command arguments in
natural python syntax.
oProject = oDesktop.GetActiveProject()
oDesign =
oProject.InsertDesign("HFSS","Random","DrivenModal","")
oEditor = oDesign.SetActiveEditor("3D Modeler")
oEditor.CreateCone(
{
"NAME" : "ConeParameters",
"XCenter": "0mm",
"YCenter": "0mm",
"ZCenter": "0mm",
"WhichAxis": "Z",
"Height": "2mm",
"BottomRadius": "1.56204993518133mm",
"TopRadius": "0mm"
},
{
"NAME": "Attributes",
"Name": "Cone1",
"Flags": "",
"Color": "(132 132 193)",
"Transparency": 0,
"PartCoordinateSystem": "Global",
"UDMId": "",
"MaterialValue" : "\"vacuum\"",
"SolveInside": True
}
Desktop Scripting with IronPython 22-29
ANSYS Electromagnetics Suite 15.0 - SAS IP, Inc. All rights reserved. - Contains proprietary and confidential information
of ANSYS, Inc. and its subsidiaries and affiliates.
)
Sample Script 16: IronPython script to create a cone
Create geometry and then create a grid from it using copy/paste/move
The following script demonstrates slightly more advanced use of scripting and the use of return values from script methods. It creates a 5x5 grid of cones and also demonstrates the adding of information messages to the application's message window.
oProject = oDesktop.GetActiveProject()
oDesign = oProject.InsertDesign("HFSS","Hersheys
Kisses","DrivenModal","")
oEditor = oDesign.SetActiveEditor("3D Modeler")
"Transparency": 0,
"PartCoordinateSystem": "Global",
"UDMId": "",
22-30 Desktop Scripting with IronPython
ANSYS Electromagnetics Suite 15.0 - SAS IP, Inc. All rights reserved. - Contains proprietary and confidential information
of ANSYS, Inc. and its subsidiaries and affiliates.
"MaterialValue" : "\"vacuum\"",
"SolveInside": True
}
)
# Now replicate this a few times and create an array out of it
AddInfoMessage("Replicating it 24 times")
for x in range(5):
for y in range(5):
# leave the first one alone in it's created
# position
if x == 0 and y == 0:
continue
# all other grid positions, replicate from the
# first one
# copy first
oEditor.Copy(
{
"NAME": "Selections",
"Selections": firstConeName
}
)
# paste it and capture the pasted name
# the pasted names come in an array as we could
# be pasting a selection cmposed of multiple objects
pasteName = oEditor.Paste()[0]
# now move the pasted item to it's final position
oEditor.Move(
{
"NAME": "Selections",
"Selections": pasteName
Desktop Scripting with IronPython 22-31
ANSYS Electromagnetics Suite 15.0 - SAS IP, Inc. All rights reserved. - Contains proprietary and confidential information
of ANSYS, Inc. and its subsidiaries and affiliates.
},
{
"NAME": "TransalateParameters",
"CoordinateSystemID": -1,
"TranslateVectorX": "%d * 3 * %s" % (x, coneBotRad),
"TranslateVectorY": "%d * 3 * %s" % (y, coneBotRad),
"TranslateVectorZ": "0mm"
}
)
No need to create and build project; all you need to do is create a Python script
Python script is platform independent
Scripts can inherit functionality from existing scripts
Garbage collector - no need to free memory
Easy debugging
Changes compared to C
Though methods, constants and structures are kept as close to the C implementation as possible,
some changes had to be made to make code Python-compatible.
Structures
For a complete list of structures and examples please see UDP/UDM Structures.
Constants
Enumeration/Enum constants have almost the same names as in C but the enum must be qualified
by the type. Additionally, redundant "UDP", "UDM" or type prefixes have been removed. This
allows for better human-readability.
# Example of specifying the LengthUnit enum by qualifying it
# with the type of the enum: UnitType
unitType = UnitType.LengthUnit
For a complete list of enum constants please see UDP/UDM Constants.
Methods
Methods are described in IUDPExtension methods, IUDMExtension methods, UDPFunctionLibrary and UDMFunctionLibrary listed further in this document.
The main differences in functions parameters (from C implementation):
ANSYS Electromagnetics Suite 15.0 - SAS IP, Inc. All rights reserved. - Contains proprietary and confidential information
of ANSYS, Inc. and its subsidiaries and affiliates.
output parameters (pointer types that are filled during the function call) usually become return
values
Output Parameters
The rule for the output parameters is as follows:
If the function has one output parameter variable and no return value, the variable will become
function's return value.The same will happen if the return value is a 'success/failure' boolean
('None' will be returned on failure and parameter variable - on success).
If the function has one output parameter and a return value, the function will return a Python
tuple where function return value will be the first one in the tuple.
If there is more than one out variable, the function will return a Python tuple with all output
parameters in the specified order. If function has a return value, it must always be the first in
the tuple.
# one output parameter; return value is ignored
udmDefinition = udmFunctionLibrary.GetDefinition()
# one output parameter; return value must be preserved. return
# and output values are packed into the return tupe, in order
(lRet, partIdsList) = udpFunctionLibrary.DetachFaces(nPartIds,
faceIdsList)
# Two output parameter; return value must be preserved
# the return tuple is (returnVal, output1, output2)
(bRet, udpPositionLow, udpPositionHigh) =
udmFunctionLibrary.GetBoundingBox(partId,exact);
C
bool getDefinition(UDMDefinition* udmDefinition,
Python
udmDefinition = udmFunctionLibrary.GetDefinition()
void* callbackData );
where udmDefinition is an output parameter
(bRet, partIds) =
udmFunctionLibrary.DetachlFaces(nFacesAndPartIds,
faceIds)
long* faceIds,
long* partIds,
void* callbackData);
If function has input 'List' parameter and input 'list size' parameter, 'list size' parameter will be
omitted.
If function has output 'List' parameter and output 'list size' parameter, 'list size' parameter will
be omitted.
If function has output 'List' parameter and input 'list size' parameter, 'list size' parameter won't
be omitted as it's needed for memory allocation in the corresponding C++ function from the
UDP/UDM function library.
Example:
# input list, input list size
lret = udpFunctionLibrary.Unite(objectIds)
# output list, output list size
faceIdList = udmFunctionLibrary.GetAllFaces(PartId)
# output list, input list size
(lret, partIdList) = udpFunctionLibrary.DetachFaces(listSize,
faceIdList)
Python
faceIds = udmFunctionLibrary.GetAllFaces(partId)
long* numFaces,
long** faceIds,
void* callbackData);
where numFaces and faceIds are output parameters and
numFaces is the size of faceId.
long unite( long numObjects,
long* objectIds,
void* callbackData);
(ignore numObjects as redundant: folded into
where numObjects and objectIds are input parameters and objectIds
numObjects is the size of objectIds.
callbackData is omitted)
long detachFaces( long nSize,
long* faceIds,
(lret, partIdList) =
udpFunctionLibrary.DetachFaces(nSize, faceIds)
long* partIds,
void* callbackData);
(nSize is not ignored,
where partIds is and output list and nSize is an input
parameters and nSize is the size of partIds.
callbackData is omitted)
Added Parameters
There is a special case in UDPFunctionLibrary: two functions - DuplicateAlongLine and DuplicateAroundAxis - have new integer listSize parameter added to their signatures.
This parameter defines the size of the output List. This is done for compliance with C++ geometry
library as the size of the List must be predefined and this size is different from the existing parameters values.
Example:
(ret, cloneIDs) = funcLib.DuplicateAlongLine(partID, transVec,
numCubes, cloneIdsSize)
(ret, cloneIDs) = funcLib.DuplicateAroundAxis(partID, axis,
angle, nClones, cloneIdsSize)
Here cloneIdsSize is a new integer parameter.
Python
(lret, cloneIds) =
udmFunctionLibrary.DuplicateAlongLine(partId,
transVec, nClones, cloneIdsSize)
long* nClones,
void* callbackData);
(callbackData is omitted
cloneIdsSize is a new parameter)
long duplicateAroundAxis(
long partId,
UDPCoordinateSystemAxis axis,
(lret, cloneIds) =
udmFunctionLibrary.DuplicateAroundAxis(partId, axis,
angle, nClones, cloneIdsSize)
double angle,
int nClones,
long* nClones,
void* callbackData);
(callbackData is omitted
cloneIdsSize is a new parameter)
Developing a UDM/UDP
Creation
To create a User Defined Primitive in Python you write a Python script that implements UDPExtension class. To create a User Defined Model in Python you write a Python script that implements
UDMExtension class (see links for full description).
Location
The scripts are located the same way the C based UDM/UDP are. They are expected to be under the
UserDefinedParts or UserDefinedModels sub-directories of one of the library folders (SysLib,
UserLib or PersonalLib). They will then appear under the appropriate menu items: Draw>User
Defined Primitives for UDP or Draw>User Defined Model for UDM.
The sub-directories structure created in one of the specified directory will be displayed in the UDP/
UDM menu.
Keep in mind that there is no difference between the menu display for C and Python implementations of UDM or UDP - only the file names without extensions are displayed
Organize
"Lib" sub-directory is a special directory. The contents of this directory is not shown in the menu.
In the "Lib" directory you can create Python scripts with base classes and utilities to be used in
UDP/UDM Python scripts. All the Lib directories upstream of a script (till the UserDefinedModels
or UserDefinedPrimitives) are included in the Python search path and this allows for easy import of
helper modules in such directories.
Desktop Scripting with IronPython 22-37
ANSYS Electromagnetics Suite 15.0 - SAS IP, Inc. All rights reserved. - Contains proprietary and confidential information
of ANSYS, Inc. and its subsidiaries and affiliates.
To use UDM data structures, constants, and/or classes in your Lib sub-directory scripts you have to
add import statement to the scripts:
For UDM:extension:
from UDM import *
For UDP:extension:
from UDP import *
Edit/Reload
Python is a scripting language, so if you have errors in your script, you will see them at the time
you try to run the script. The errors will be displayed in the Message Manager Window. If you need
more information, you might be able to get it from log files. See Logging section for more details.
You can always change your script, call Update Menu command from Draw>User Defined
Model> menu or Draw>User Defined Primitives> menu and run the script again. If you delete
script you might want to restart the application instead of calling Update Menu.
UDPExtension
Import
You do not have to add import statements for the predefined classes, structures, and constants - it is
done for you and all data types described in this document can be used in your Python script.
However you have to add import statements to your helper scripts in your Lib sub-directory.
from UDP import *
Main class: UDPExtension
You must write a class derived from IUDPExtension with a mandatory name UDPExtension:
class UDPExtension(IUDPExtension):
The class should implement IUDPextension methods described below.
IUDPExtension methods
All methods are same as the methods in the C UDP implementation. The changes to the methods
signatures are just to conform to the Python style.
Mandatory methods.
These methods must be implemented in the UDP Python script as methods of UDPExtension class.
GetLengthParameterUnits()
returns string.
GetPrimitiveTypeInfo()
returns UDPPrimitiveTypeInfo.
GetPrimitiveParametersDefinition2()
AreParameterValuesValid2(errorMsg, udpParams)
CreatePrimitive2(funcLib, udpParams)
Optional methods
These methods, which have default implementations, can be implemented as methods of UDPExtension class as needed. Default methods will return NULL or FALSE depending on the return
type.
GetPrimitiveParameters()
GetRegisteredFaceNames()
GetRegisteredEdgeNames()
GetRegisteredVertexNames()
ProjectParametersOnToValidPlane2(currentUDPParams, projectedUDPParams)
MapParametersDefinitionVersions2(oldVersion, oldUDPParams)
oldVersion is a string
oldUDPParamsis a list of UDPParam
returns Python list of UDPParam or NULL
GetOldPrimitiveParametersDefinition2(version )
version is a string
returns a list of UDPPrimitiveParameterDefinition2 or None on failure.
Example UDP
import sys
class UDPExtension(IUDPExtension):
Desktop Scripting with IronPython 22-39
ANSYS Electromagnetics Suite 15.0 - SAS IP, Inc. All rights reserved. - Contains proprietary and confidential information
of ANSYS, Inc. and its subsidiaries and affiliates.
def GetLengthParameterUnits(self):
return "mm"
def GetPrimitiveTypeInfo(self)
typeInfo = UDPPrimitiveTypeInfo(
name = "SampleUDP",
purpose = "example",
company="ANSYS",
date="12.21.12",
version = "1.0")
return typeInfo
...
...
For the full example, see Example Scripts for Python UDP and UDM.
UDPFunctionLibrary
UDPFunctionLibrary implements IUDPFunctionLib interface: The IUDPFunctionLib object is
passed as a parameter to Python script in functions CreatePrimitive2. You can call any of the functions from the functions list (shown below).
udpFunctionLib.AddMessage(MessageSeverity.WarningMessage ,"New
warning");
Considering that out variables are returned as members of the return tuple, sample code that calls
DetachFaces in Python script can look like this:
intVal = 10
inList = [..., ...]
(lret, outList) = udpFunctionLibrary.DetachFaces(intVal,
inList)
As you can see outList output parameter is defined in the call to DetachFaces function. Unlike in C,
there is no need to define it before the function call.
Functions list:
1.
2.
3.
4.
5.
6.
7.
8.
int: iret = CreateRectangle(CoordinateSystemPlane: whichPlane, UDPPosition: centerPoint, List_of_double: widthAndHeight, int: isCovered)
9.
UDMExtension
Import
You do not have to add import statements for the predefined classes and structures - it is done for
you and all data types described in this document can be used in your Python script.
However you have to add import statements to your helper scripts in your Lib sun-directory.
from UDM import *
Main class: UDMExtension
You must write a class derived from IUDMExtension with a mandatory name UDMExtension:
class UDMExtension(IUDMExtension):
The class should implement IUDMExtension methods described below.
IUDMExtension methods
All methods are the same as the methods in the C UDM implementation. The changes to the methods signatures are just to conform to the Python style.
Mandatory methods.
These methods must be implemented in the UDM Python script as methods of UDMExtension
class.
Desktop Scripting with IronPython 22-43
ANSYS Electromagnetics Suite 15.0 - SAS IP, Inc. All rights reserved. - Contains proprietary and confidential information
of ANSYS, Inc. and its subsidiaries and affiliates.
GetInfo()
IsAttachedToExternalEditor()
CreateInstance(funcLib)
funcLib is UDMFunctionLibrary
returns UDMParameters.
GetUnits(instanceId)
instanceId is a long
returns string containing units for the instance.
funcLib is UDMFunctionLibrary
refreshModifiedPartsOnly is a boolean
ReleaseInstance(instanceId)
instanceId is a long
This should release any resources assigned to this particular instance of UDM.
returns True on success, False on failure.
GetAttribNameForEntityId()
Returns string that acts as a the name of the attribute containing entity IDs.
GetAttribNameForPartId()
Returns string that acts as a the name of the attribute containing entity IDs.
For example, it can return a unique string such as "ATTRIB_XACIS_ID" (Can be same as
GetAttribNameForEntityId())
Optional methods
These methods have default implementations (default is to return NULL or FALSE depending on
the return type) but can be overridden by the user as needed as methods of UDMExtension class.
DialogForDefinitionOptionsAndParams(self, defData, optData, params):
Replaces the old UDMDialogForDefinitionAndOptions method, which is still supported, but users
are urged to use UDMDialogForDefinitionOptionsAndParams. If both methods are present, application will use UDMDialogForDefinitionOptionsAndParams.
UDM can pop up dialog for UDM definition, options, parameters in this method. Definition,
options, and parameters are set/modified by user and returned to application. Dll can also just
give default definition, options and parameters.
GetInstanceSourceInfo(instanceId)
instanceId is a long
returns string containing source information of UDM instance. It is used to create initial name
for UDM instance.
ShouldAttachDefinitionFilesToProject()
Example UDM
class UDMExtension(IUDMExtension):
def IsAttachedToExternalEditor(self):
return False
def GetInfo(self)
udmInfo = UDMInfo(
name = "SampleUDM",
purpose = "udm example",
company="ANSYS",
date="12.21.12",
version = "1.0")
return udmInfo
...
...
UDMFunctionLibrary
UDMFunctionLibrary implements IUDMFunctionLib interface. The IUDMFunctionLib object is
passed as a parameter to Python script in the following functions
CreateInstance
Refresh
You can call any of the functions from the functions list (shown below).
partRefId = udmFunctionLib.GetPartRefId(partId)
For example sample code that calls GetBoundingBox in Python script can look like this:
partId
= 10
exact
= True
udpPosition = UDPPosition(0,0,0)
2.
3.
4.
5.
6.
7.
8.
9.
In addition to the above functions all functions defined in the UDPFunctionLib are available in the
IUDMFunctionLib and can be called directly exactly the same way as the IUDMFunctionLib functions.
Example:
udmFunctionLib.CreateCircle(center,radius,ratio,isCovered)
UDP/UDM Structures
UDP/UDM Constants
UDP/UDM Structures
Differences compared to C API
UDMDefinition
UDMOptions
UDMParameters
Instead of containing arrays of data, the structures contain single fields where each field corresponds to an item in a different array from the original C API. The structure objects thus constructed are added to the Python list. Alternately the Python list can be initialized using the
structure objects.
Example (creating UDMParameter list):
udmParamList = [UDMParameter("cubeSizeName",
UnitType.LengthUnit,
UDPParam(ParamDataType.Double, cubeSize),
ParamPropType.Value,
ParamPropFlag.MustBeReal),
UDMParameter("cubeDistanceName", UnitType.LengthUnit,
UDPParam(ParamDataType.Double, cubeDistance),
ParamPropType.Value,
ParamPropFlag.MustBeReal),
UDMParameter("numCubesName", UnitType.LengthUnit,
UDPParam(ParamDataType.Int, numCubes),
ParamPropType.Number,
ParamPropFlag.MustBeInt)]
UDPParam
UDPParamData
Data field in UDPParam is now an object - the same for all types of data used - as Python can work
with any type of data.
UDPParamData is obsolete, thus not implemented. Be sure to set proper data type to UDPParam.DataType when setting UDPParam.Data.
Example:
nCubesParam = UDPParam(ParamDataType.Int, numCubes)
nCubes = nCubesParam.Data
distanceParam = UDPParam()
distanceParam.setDouble(10.5)
doubleDistance = distanceParam.Data * 2
UDP3x3Matrix
The structure is not implemented. Use size 9 Python List of doubles instead.
Example:
rotationMatrix =[0,0,1, 1,0,0, 0,0,1]
udpFunctionLib.Transform(partId, rotationMatrix,
translationVector)
List of structures
You can use constructors to create a structure. You can also modify fields - directly or by provided
methods.
Example:
pos1 = UDPPosition(1,2,3)
pos2 = UDPPosition(x=1,y=10,z=0)
pos2.Z = pos1.Z
udpParam = UDPParam(ParamDataType.Double,1)
value = udpParam.Data
Structure
UDPPrimitiveTypeInfo
Construction
UDPPrimitiveTypeInfo(
Members
string Name
string name,
string Purpose
string purpose,
string Company
string company,
string Date
string date,
string Version
string version)
UDPPrimitiveParameterDefinition
string Description
string description,
UnitType UnitType
UnitType unitType,
double DefaultValue
double defaultValue)
UDPParam
UDPParam()
ParamDataType DataType
object Data
UDPParam(
ParamDataType dataType,
object data)
object can be int, double, string,
bool or UDPPosition
methods:
setInt(int val)
setBool(bool val)
setString(string val)
setDouble(double val)
setPosition(UDPPosition val)
Structure
UDPPrimitiveParameterDefinition2
Construction
Members
string Description
string description,
UnitType UnitType
UnitType unitType,
ParamPropType PropType
ParamPropType propType,
ParamPropFlag PropFlag
ParamPropFlag propFlag,
UDPParam DefaultValue
UDPParam defaultValue)
UDPPosition
UDPPosition(
double X
double x,
double Y
double y,
double Z
double z)
UDPVector
UDPVector(
double X
double x,
double Y
double y,
double Z
double z)
UDPSweepOptions
UDPSweepOptions(
SweepDraftType DraftType
SweepDraftType draftType,
double DraftAngle
double draftAngle,
double TwistAngle
double twistAngle)
UDPPolylineSegmentDefinition
UDPPolylineSegmentDefinition(
PolylineSegmentType
segmentType,
PolylineSegmentType
SegmentType
int segmentStartIndex,
int segmentStartIndex,
int numberOfPoints,
int numberOfPoints,
double angle,
double angle,
UDPPosition centerPoint,
UDPPosition centerPoint,
CoordinateSystemPlane
arcPlane)
CoordinateSystemPlane
arcPlane)
Structure
UDPPolylineDefinition
Construction
UDPPolylineDefinition()
Members
int IsClosed
int IsCovered
UDPPolylineDefinition(
List_of_UDPPosition positions,
List_of_UDPPosition
ArrayOfPosition
List_of_UDPPolylineSegmentDefini List_of_UDPPolylineSegmentD
efinition
tion segDefs,
ArrayOfSegmentDefinition
int closed,
int covered)
UDPEquationBasedCurveDefinition
double TStart
string functionZt,
double TEnd
double tStart,
int NumOfPointsOnCurve
double tEnd,
int numOfPointsOnCurve)
UDPEquationBasedSurfaceDefinition
double UStart
string functionZuv,
double UEnd
double uStart,
double VStart
double uEnd,
double VEnd
double vStart,
double vEnd)
UDPHelixDefinition
UDPHelixDefinition(
int ProfileID
int profileID,
UDPPosition PtOnAxis
UDPPosition ptOnAxis,
UDPPosition AxisDir
UDPPosition axisDir,
double NoOfTurns
double noOfTurns,
bool IsRightHanded
bool isRightHanded,
double RadiusChangePerTurn
double radiusChangePerTurn,
double Pitch
double pitch)
22-52 Desktop Scripting with IronPython
ANSYS Electromagnetics Suite 15.0 - SAS IP, Inc. All rights reserved. - Contains proprietary and confidential information
of ANSYS, Inc. and its subsidiaries and affiliates.
Structure
UDPSpiralDefinition
Construction
Members
UDPSpiralDefinition(
int ProfileID
int profileID,
UDPPosition PtOnAxis
UDPPosition ptOnAxis,
UDPPosition AxisDir
UDPPosition axisDir,
double NoOfTurns
double noOfTurns,
bool IsRightHanded
bool isRightHanded,
double RadiusChangePerTurn
double radiusChangePerTurn)
UDPBLNDElements
UDPBLNDElements(
int PartID
int partID)
List_of_int ListOfEdges
List_of_int ListOfFaces
UDPBLNDFilletOptions
UDPBLNDFilletOptions(
bool SupressFillet
bool supressFillet,
BLNDFilletRadiusLaw
FilletRadiusLaw
BLNDFilletRadiusLaw
filletRadiusLaw,
double FilletStartRadius
double filletStartRadius,
double FilletEndRadius
double filletEndRadius,
bool
FollowSmoothEdgeSequence
bool
followSmoothEdgeSequence,
BLNDFilletType FilletType
BLNDFilletType filletType,
double SetbackDistance
double setbackDistance,
double BulgeFactor
double bulgeFactor)
UDPBLNDChamferOptions
UDPBLNDChamferOptions(
bool SupressChamfer
bool supressChamfer,
BLNDChamferRangeLaw
ChamferRangeLaw
BLNDChamferRangeLaw
chamferRangeLaw,
double ChamferLeftRange
double chamferLeftRange,
double ChamferRightRange
double chamferRightRange)
UDPProgress
UDPProgress(
int Prog
int prog,
int SubProg
int subProg,
string Mesg
string mesg,
string SubMesg
string subMesg)
Structure
UDMInfo
Construction
UDMInfo(
Members
string Name
string name,
string Purpose
string purpose,
string Company
string company,
string Date
string date,
string Version
string version)
UDMDefinition
UDMDefinition()
string DefName
UDPParam DefValue
UDMDefinition(
ParamPropType PropType
string name,
ParamPropFlag PropFlag
UDParam value,
ParamPropType propType,
ParamPropFlag propFlag)
UDMOption
UDMOption()
string OptName
UDPParam OptValue
UDMOption(
string name,
ParamPropType PropType
ParamPropFlag PropFlag
UDParam value,
ParamPropType propType,
ParamPropFlag propFlag)
UDMParameter
UDMParameter()
string ParamName
UDPParam ParamValue
UDMParameter(
UnitType UnitType
string name,
ParamPropType PropType
UDParam value,
ParamPropFlag PropFlag
UnitType unitType,
ParamPropType propType,
ParamPropFlag propFlag)
UDP/UDM Constants
Full names of enum constants must be used in scripts.
Example:
unitType = UnitType.LengthUnit
22-54 Desktop Scripting with IronPython
ANSYS Electromagnetics Suite 15.0 - SAS IP, Inc. All rights reserved. - Contains proprietary and confidential information
of ANSYS, Inc. and its subsidiaries and affiliates.
dataType = ParamDataType.Int
Enum constants:
enum Constant
UnitType
Parameters
NoUnit
LengthUnit
AngleUnit
ParamDataType
Int
Double
String
Bool
Position
Unknown
ParamPropType
Text
Menu
Number
Value
FileName
Checkbox
Position
Unknown
ParamPropFlag
NoFlag
ReadOnly
MustBeInt
MustBeReal
Hidden
Unknown
CoordinateSystemAxis
XAxis
YAxis
ZAxis
CoordinateSystemPlane
XYPlane
YZPlane
ZXPlane
enum Constant
SweepDraftType
Parameters
ExtendedDraft
RoundDraft
NaturalDraft
MixedDraft
SplitWhichSideToKeep
SplitKeepBoth
SplitKeepPositiveOnly
SplitKeepNegativeOnly
PolylineSegmentType
LineSegment
ArcSegment
SplineSegment
AngularArcSegment
MessageSeverity
WarningMessage
ErrorMessage
InfoMessage
IncompleteMessage
FatalMessage
BLNDFilletRadiusLaw
BLNDConstantRadius
BLNDVariableRadius
BLNDFilletType
BLNDRound
BLNDMitered
BLNDChamferRangeLaw
BLNDConstantRange
BLNDVariableRange
PartPropertyFlags
PropNonModel
PropDisplayWireFrame
PropReadOnly
PostprocessingGeometry
PropInvisible
PropShowDirection
PropDummy
You can also add messages to Message Manager using the UDPFunctionLibrary AddMessage
method, but no logging is done in this case.
Collecting EBU Logs
The instructions below are for Windows, but they work similarly for Linux. On Linux, determine
your shell (execute echo $SHELL) and, based on that, use setenv or export to set the environment
variables.
1.
Create a directory that serves as a folder for the logs. Make sure that this directory is empty:
clean it out if it already has files. For this example, the name of the directory is c:\ansdir\ansdebug.
2.
Start a new shell to set the environment. (You can set it permanently, but this is not recommended.)
3.
Set ANSOFT_DEBUG_MODE to 2. Set it to a higher number such as 4 or 5 if the developer requests it.
Set ANSOFT_DEBUG_LOG_SEPARATE to 1.
4.
From the above shell, start the ANSYS Electromagnetics product and exercise the problem
scenario.
5.
Zip all the log files in the c:\ansdir\ansdebug directory, and send them to the developer or support person requesting them.
Collecting WB Logs
1.
Under WB, execute the Tools/Options menu option, and under the Journals And Logs section,
ensure the Write Workbench Log Files is checked.
Note the location of the log files. (On Windows this is typically %TEMP%\WorkbenchLogs.)
Navigate to that directory and remove all files.
2.
Set up the EBU env vars if you need to collect those as well, following the instructions above.
3.
4.
Collect the WB log files and optionally the ANSYS Electromagnetics logs and, send them to
the developer or support person requesting them.
2.