Experimenting with ANSYS ACT in Mechanical

ANSYS ACT is the scripting API for various ANSYS products. It is available for Workbench, Mechanical, Fluent, and others. It uses Python 2 and in Mechanical it allows much of the standard click operations to be accessed programmatically.

Usage

In Mechanical, the ACT Console is a pane that allows for running and testing scripts. It is accessed by clicking the white rectangular icon next to the Help menu by default (in pre-tabbed interfaces - in ANSYS 2019R2, the program switched to a tabbed interface).

With the ACT Console open, you have more or less a standard Python interpreter. You issue commands in the command line (darkened area at the bottom), and see results in the area above it. The console features auto-completion and can be used interactively, especially while developing new scripts. New lines, such as with for loops, can be entered with SHIFT + ENTER.

There is a pane on the left which holds Snippets, which are simply files storing code for reuse. You can create your own snippets for actions that you want to remember or perform more than once. You do this by clicking on the Add Snippet button (left most icon in the snippet portion of the toolbar). Then, when you click on the snippet from the Bookmarks pane, the code is simply inserted into the command line and can be executed by pressing ENTER.

A collection of snippets can be grouped together and imported/exported. This might be useful if you or your company has a set of scripts that you use. To use this functionality, create a new group and give it a name. Drag your snippets into it. Then, in the ACT toolbar, export the snippets to an XML file. This exports all of the snippets, including the default ones that came loaded when you opened the console. These can easily be removed by editing the XML file after it is saved. In the XML file, find the group that has the name of your group, and delete everything else, not including the parent xml tags. For example, if I add the following snippet Snippet 1 and group My Snippets:

After exporting I find an xml file with the following:

<!--?xml version=\"1.0\" encoding=\"utf-8\"?-->
<model maxid=\"5\">
<root>
    <folder id=\"1\" label=\"Folder\">
    <bookmark id=\"2\" label=\"ExtAPI\">
    \t<!--[CDATA[ExtAPI.]]-->
    </bookmark>
    </folder>
    <folder id=\"4\" label=\"My Snippets\">
    <bookmark id=\"5\" label=\"Snippet 1\">
    \t<!--[CDATA[print Hello World!]]-->
    </bookmark>
    </folder>
</root>
</model>

In this case I will want to simply delete the <folder> item with the label=\"Folder\" attribute, since that is code not pertaining to my custom folder. ANSYS stores the actual code for the snippet in the bookmark field; in this case the code is print Hello World!.

API

An API is how operations and objects in Mechanical are retrieved and manipulated with code. The default global variable that gives access to all objects in Mechanical is ExtAPI. From this you can access all other objects using Python dot syntax. Listed below are some of the objects in Mechanical and their classes and access points. It is common to assign these to a variable so that they do not need to be fetched each time. For example:

solution = ExtAPI.DataModel.Project.Model.Analyses[0].Solution
Object Access Note
The Project ExtAPI.DataModel.Project  
List of Analyses ExtAPI.DataModel.Project.Model.Analyses This is list-like and indexable/loopable
Analysis working directory ExtAPI.DataModel.Project.Model.Analyses[0].WorkingDir Gets the working directory for the first analysis system (zeroth index)
Connections ExtAPI.DataModel.Project.Model.Connections  
Solution ExtAPI.DataModel.Project.Model.Analyses[0].Solution This is the solution object for the first analysis system (zeroth index)

Object Class
Force Reaction Probe Ansys.ACT.Automation.Mechanical.Results.ProbeResults.ForceReaction
Moment Reaction Probe Ansys.ACT.Automation.Mechanical.Results.ProbeResults.MomentReaction
Beam Probe Ansys.ACT.Automation.Mechanical.Results.ProbeResults.BeamProbe
Tree Group Folder Ansys.ACT.Automation.Mechanical.TreeGroupingFolder

Change the Python directory to the user_files directory for a Project

Scripts that save out to a file might want to take advantage of the user_files directory. The user_files directory exists at the first level of the project files directory and is for storing user information pertaining to a Workbench project. I haven't found the path for this as a parameter in the API directly so the below is a way to obtain it from an analysis working directory. It splits the path at the Workbench project folder, so _files must not come before the Workbench folder in the path or it will return the wrong location.

from os import chdir
MECH_dir = ExtAPI.DataModel.Project.Model.Analyses[0].WorkingDir
user_dir = MECH_dir.split('_files')[0] + r'_files\user_files'
chdir(user_dir)

Usage Example: Results Exporting

One of the major limitations of Workbench / Mechanical is getting result probes out of Mechanical and into an external file (Excel, text file, etc.). If you only have a few result probes this is no problem - copy and paste will work fine. However, if you have a hundred, there is not an easy way to get all of the data and more importantly formatted as you like. Additionally, for a contact, you will likely want a Force Probe and a Moment Probe; these are two separate items in the Solution and you must export both and associate correctly with the contact they are referring to. With ACT, you can programmatically loop through these items and save them to a text file.

Beams

In this case you have some beams in your model defined under the Connections folder and you'd like to export the beam probes. If you've already created a result probe for them, you can retrieve and export them as follows:

solution = ExtAPI.DataModel.Project.Model.Analyses[0].Solution
beam_probes = filter(lambda item: item.GetType() == Ansys.ACT.Automation.Mechanical.Results.ProbeResults.BeamProbe, solution.Children)

f = open('Beam results.txt','w')
f.write('Beam Probes\n\n')
f.write('Name\tAxial Force\tTorque\tShear Force at I\tShear Force at J\tMoment at I\tMoment at J\n\n')

for bp in beam_probes:
    name = bp.BoundaryConditionSelection.Name
    f.write(name + '\t' +
        str(bp.AxialForce).split('[')[0] + '\t' +
        str(bp.Torque).split('[')[0] + '\t' +
        str(bp.ShearForceAtI).split('[')[0] + '\t' +
        str(bp.ShearForceAtJ).split('[')[0] + '\t' +
        str(bp.MomentAtI).split('[')[0] + '\t' +
        str(bp.MomentAtJ).split('[')[0] + '\n' )
f.close()

With the following tree, and after setting the working directory to the user_files directory, running the above code produces Beam results.txt:

Name    Axial Force Torque  Shear Force at I    Shear Force at J    Moment at I Moment at J

Bolt 1  23.464579153988097  -0.69336988094428165    95.214531366676013  95.214531366676013  12.945849648564687  11.227034167745025
Bolt 2  -23.464579153988097     -0.70081092496467057    104.8404773221031   104.8404773221031   14.025457881021863  12.521195678519947

This file is tab-delimited and the bolt names come from the name of the beam items in the Connections folder. Additionally, the unit is stripped from the result.

See full snippets on Github: https://github.com/robsiegwart/ANSYS-ACT-snippets.