Importing and Exporting ANSYS Mechanical Loads as XML Files

I was futzing around with some loads the other day and noticed that, to my shock, that if you click on the value for a load and instead of typing a value in, click on the drop down menu and you will find that it has an Import and an Export on it.   I’m not sure when that became a capability, but I think it has been there for a while.  A quick check with the staff here at PADT and only a few knew about it.  Which makes it a great topic for The Focus.image

XML, Engineering Data, and Verbosity

The easiest way to check this out is to go into a model and insert a force into your model.  Go ahead and pick the geometry.  In the Details for the force, click on the magnitude cell and you will see a little drop-down menu triangle:


Click on that and you will see the menu:


Click on Export and give it a file name.  You will notice when you do this that it makes an XML file.  If you didn’t know it, ANSYS Mechanical uses a lot of XML.  In fact, they used to even store results in an XML file.  The good thing about XML files is that they kind of self-describe themselves and organize the data in them in a sort of object oriented way.  This makes them very easy to read and portable between programs. 

XML stands for eXtensible Markup Language and it is an expansion of HTML to handle data. Check out the Wikipedia article on the topic to learn more.  XML is hear to stay and if you don’t get it, you might struggle with some advanced stuff in a lot of areas, not just ANSYS.

The down side of XML is that it is very wordy – verbose.  It has lots of text in there that specifies relationships, names, ID’s, etc…  Tags out the wazoo.  For those of us that grew up feeding our simulation programs fixed format or comma delimited files where the first line specified all the constants and the rest was the data, this can be a bit annoying.  But it does make the data portable and “human readable”

Let’s take a look at the XML file from applying a load of 0.0 lbf to our model.  The best way to view an XML file is to doubleclick on it. Your browser will bring it up and show what is inside.   If you have Dreamweaver or some other HTML editor, that will work even better.

Here is our example:

   1: <?xml version="1.0" encoding="UTF-8" standalone="no" ?>
1.5: <

   2:     <MaterialData/>

   3:     <ConvectionData/>

   4:     <LoadVariationData>

   5:           <MatML_Doc>

   6:               <LoadVariation>

   7:                     <BulkDetails>

   8:                         <Name>Force 2</Name>

   9:                         <Form>

  10:                               <Description/>

  11:                     </Form>

  12:                         <PropertyData property="pr1">

  13:                               <Data format="float">0.,0.</Data>

  14:                               <Qualifier>Force</Qualifier>

15: <ParameterValue format="float" parameter="pa1">

  16:                     </PropertyData>

  17:                 </BulkDetails>

  18:                     <Metadata>

  19:                         <ParameterDetails id="pa1">

  20:                               <Name>Time</Name>

  21:                     </ParameterDetails>

  22:                         <PropertyDetails id="pr1">

  23:                               <Name>Force</Name>

  24:                     </PropertyDetails>

  25:                 </Metadata>

  26:             </LoadVariation>

  27:         </MatML_Doc>

  28:     </LoadVariationData>

  29:     <BeamSectionData/>

  30: </ANSYS_EnggData>

The first thing you will notice is that the second tag (right after the XML version info) is <ANSYS_EnggData>.  That is because ANSYS already had a nice well defined format for putting tabular data into Workbench applications: EngineeringData.  So they just used the same format for loads.

The next thing you will notice is a lot of text to specify two value at two time points.  A lot of the data is just blank. There in case you need it.  To understand this let’s step back and look at tags in HTML.

A tag goes around some piece of information and describes what that information is.  Usually you have a starting tag which is the string with a less-than sign at the start and a greater-than sign at the back:


You then put in your information.  It could be data, text, more tags, whatever you want.  then when you are done, you close out the tag with the same string, but this time start with less-than followed by a forward slash. You still end with greater than:


You can nest these guys, with tags inside tags. This is how you get your object parent-child relationships.

So let’s look at our first couple of lines again, repeated here with the meat taken out (<…>) so we don’t have to scroll back and forth:

   1: <?xml version="1.0" encoding="UTF-8" standalone="no" ?><ANSYS_EnggData>

   2:     <MaterialData/>

   3:     <ConvectionData/>

   4:     <LoadVariationData>

   5:           <MatML_Doc>

   6:               <LoadVariation>

   7:                     <BulkDetails>

   8:                         <...>

   9:                     </BulkDetails>

  10:                     <Metadata>

  11:                         <...>                       

  12:                     </Metadata>

  13:             </LoadVariation>

  14:         </MatML_Doc>

  15:     </LoadVariationData>

  16:     <BeamSectionData/>

  17: </ANSYS_EnggData>

You will notice that a lot of the tags in our example end with a forward slash:


This is an empty tag. It tells the program I got no data of this type. It does save some text compared to other market languages where you just have a blank start and end tag. 

So, our example starts and ends with <ANSYS_EnggData> and </ANSYS_EnggData>  Everything between in engineering data.  Then it says no material data and no convection data.  It does say it has load variation data.  We then find the LoadVariationData tag.  This is what we actually have in the file.  It then goes one step down and has a MatML_Doc tag.  This tells the program the format of the data being given is in the MatML schema.  more on that below.

Then we break the load into two parts: The BulkDetails where the actual data values are specified and the MetaData, which tells the program information it needs to know about the data.  Then everything has its end tag, you tell the program you don’t have BeamSectionData, and you finish up.

If you want to, you can not include all the empty tags.  the <tagString/> tags.  Mechanical reads the file just fine without them.   But you can’t get rid of anything else.

The MatML Language

MatML is “an extensible markup language (XML) developed especially for the interchange of materials information.”  You can read all about it at:  History, examples, news, etc…  It is all there.   Like most standards, you can waste a lot of time saying what is good or bad about it.  But in the end, what matters is that everyone uses the same standard. (Of course, MatWeb doesn’t support this standard because they want you to pay for native format… grumble, grumble…).

Looking at the Data and MetaData

Let’s look at the heart of our file, the actual data we want.  In MatML they call it BulkDetails:

   1: <BulkDetails>

   2:     <Name>Force 2</Name>

   3:     <PropertyData property="pr1">

   4:         <Data format="float">0.,0.</Data>

   5:         <Qualifier>Force</Qualifier>

   6:         <ParameterValue format="float" parameter="pa1">0.,1.</ParameterValue>

   7:     </PropertyData>

   8: </BulkDetails>

The first thing we find is the name.  This is not the name that will be used in the tree.  It is the name that will show up in the library if you combine a bunch of XML files and the name that will show up in your detail view for magnitude.  So if you make your own load, give it something descriptive here so you can pick it out of the library but not so long that you can’t read it in the detail. Calling it F1 will just tick you off in six months when you try to reuse a load.

Next is the PropertyData tag.  It will always have the name “prn” as far as I can tell, where n is an integer starting at 1 and increasing for each property in the file.  If you change it, everything gets messed up – so always use pr1. 

Now the data.  You give it a format, float in most cases, then a comma delimited list.  That is it.

Then you tell the program that it is a Force with the Qualifier.

Last, you need to specify the parameters that your load will vary over.  Usually this is time.  Use <ParameterValue> to do this.  Notice how you specify a format and what the parameter is called, and this is always “pa1”  (or pan actually, where n starts at 1 and increases for each property in the file).

Now we have to tell the program some additional information about our data, which is called Meta Data.  For loads, the only thing that is supported is the definition of the type of load being specified:

   1: <Metadata>

   2:     <ParameterDetails id="pa1">

   3:         <Name>Time</Name>

   4:     </ParameterDetails>

   5:     <PropertyDetails id="pr1">

   6:         <Name>Force</Name>

   7:     </PropertyDetails>

   8: </Metadata>

Don’t worry too much about this formating stuff.  The best thing for you to do is make a load like the one you want in Mechanical, export it to XML, then modify the values inside as you see fit.  Much easier than understanding the schema… or even what a schema is.


Please notice that there are no units anywhere.  Right now all of your values must be in SI units, and Mechanical will convert when it displays the values.  This is because Mechanical always stores values internally as SI.  So, if you make your own load files, make sure you convert to SI.

This is the single biggest potential for error… so mind your units!

Importing XML Load Files

The process of reading in the loads is a bit more complicated then simply pointing to a file.  This is because each file can hold more than one load. You should think of the XML file as a library.

To read the file go to your Magnitude, click on the drop-down menu icon and choose “Import…”  This brings up the “Import Load History Data” dialog:


Note that instead of picking a file you are given a Data Source area and a Load History Data to Import area.  the top Data Source is the file.  Click Add… and point to your XML file.  Once it reads that file in it will always remember the file and every time you open this dialog box, it will re-read it and update the Load History data to Import values.



You can see our sample file, tt4.xml, is the library Data Source and within it are two loads.  You use the radio button to choose the load you want to apply.  Click OK and you will notice that your Details for the load now lists that name as the Magnitude:


As you can imagine, you can put a ton of loads in one file, maybe all the loads for your project.  Then use the filter to find the load you want in a big file.  This is again a reminder of why it is important to specify a useful name when you create the load.


The examples above deal with tabular data.  You can also store formulas in the file.  This looks a little different in the <BulkDetails> in that you specify format=”function> in the <Data> tag.  Here is an example:

   1: <MatML_Doc>

   2:     <LoadVariation>

   3:           <BulkDetails>

   4:               <Name>Force 2</Name>

   5:               <Form>

   6:                     <Description/>

   7:           </Form>

   8:               <PropertyData property="pr1">

   9:                     <Data AngleInDegrees="1" AngularVelocityInRPM="1" 

  10:                         TemperatureUnit="3" UnitSystem="4" format="function">

  11:                         <Domain LowerLimit="0." UpperLimit="-999.">

  12:                             time

  13:                         </Domain>

  14:                         <Domain LowerLimit="0." UpperLimit="-999.">

  15:                             1.2*sin(time/6)

  16:                         </Domain>

  17:               </Data>

  18:                     <Qualifier>Force</Qualifier>

  19:                     <ParameterValue format="float" parameter="pa1">

  20:                            0.,.1,.2,.3,.4,.5,.6,.7,.8,.9,

  21:                            1.0,1.1,1.2,1.3,1.4,1.5,1.6,

  22:                            1.7,1.8,1.9,2.0

  23:                     </ParameterValue>

  24:           </PropertyData>

  25:       </BulkDetails>

  26:           <Metadata>

  27:               <ParameterDetails id="pa1">

  28:                     <Name>Time</Name>

  29:           </ParameterDetails>

  30:               <PropertyDetails id="pr1">

  31:                     <Name>Force</Name>

  32:           </PropertyDetails>

  33:       </Metadata>

  34:   </LoadVariation>

  35: MatML_Doc>

A lot more complicated. The best way to make one of these is to do it interactively and export.

Generating XML Load Files

At first blush, the file looks complicated but a simple VBA script in excel or a python macro can build the file very quickly because most of the text is static, you are really just changing the data and parameter value values.  I was going to do such an example, but ran out of time.  If any of you have one or write one, please let us know so we can share.

Making Animated GIF’s of ANSYS Graphics for Fun and Profit

In last weeks article I included some animations of some plots from the examples.  While doing that I remembered that we have received a couple of questions recently about how to get result animations in a PowerPoint or a Website.  In this article we will talk about the tool I use and give some tips on making the process better. And, it give me an excuse to write about some software other than ANSYS, Inc.

Animated Gif Humor (14)Animated GIFs and Why we Need Them

As you know, an animation is simply a series of still images shown one right after another.  When we create Video on a computer we generally make something with 30 still frames shown every second.  Although the various formats for video have gotten much better, that is still a lot of pixels to send around. That makes a big file that may not be best for your web page or PowerPoint.  However, with modern high speed internet and fast computers, that is not the problem it used to be.  It is still a concern.

What we really have to deal with is making sure that whatever we are using to present our animation can play it.  Can the persons web browser show it?  Can PowerPoint show it?  Although YouTube is a possibility more an more, you really want a portable format that you can imped in your document or site and that everyone can see.  If you research…  the only format that fits that bill is an animated GIF.

The gif format is compact, and because the early Netscape Navigator browser supported it, it became a default format.  Even Microsoft decided to support it.  So, as in some ways, it is the least common denominator that works for everyone.  Another cool thing is that the programs treat it as an image, not as a video or animation.  You copy and paste it, insert it, place it, edit its size just like you would any JPEG, PNG, or TIFF image.

You can learn about the format on wikipedia. But if the binary info that greats you on that page causes your eyes to glaze over, you only really need to know the following:

    1. It is a file format that supports multiple images all contained in one image file
    2. You can specify how long to play a given image (frame)
    3. It supports transparency
    4. It is a standard and all web browsers and PowerPoint will display it
    5. You can imbed it in a PowerPoint so you don’t have to worry about carrying your animation files around in a folder with your PowerPoint.
    6. It only supports 256 colors. This is the downside of GIF’s

Unfortunately non of the ANSYS products make an animated GIF file.  They generally make an AVI, which is the most common video file, but something that most people can’t display on their website or put in a PowerPoint.  So we need to convert the AVI to a GIF, or create a GIF from a series of images. 

There is one option we should mention, and that is creating an Adobe Flash file. This is a more modern and capable format but it has problems.  First and foremost, iPhones and iPads don’t display flash.  Second, to show a flash animation in PowerPoint you have to make sure a special flash player is installed.  So again, lowly GIF wins out.

GIF Movie Gear

I use a program called GIF Movie Gear. If you Google “AVI to GIF” you will find other tools. I picked this one because it had the features I wanted, it was cheap, and it works so far just fine. Over time, I have found it to be very robust as well.  It is from a company called Gamani, and you can download a trial version or purchase it for $29.95.  They have a nice website that lists all the features and offers some tutorials at:

Once you have it installed check it out. If you have not tried similar tools in the past, go through the tutorial. It is worth the time. 

For the ANSYS user, here are the important features:

    1. It will import an AVI and break it into individual images (frames)
    2. You can crop and resize
    3. You can set the speed of the animation
    4. It is easy to use (important, since if you are like me you only need it once in a while)
    5. You can easily make a ping-pong animation (copy frames then reverse them)
    6. You can make an animation by reading in a series of images (important for MAPDL users that want to make a high quality animation)

There are a ton more features, but these are the ones that matter to us ANSYS types.

Building Animations from Images

If you are using Mechanical APDL (MAPDL) you can use the ANIM command to build an animation of your model as an AVI. The problem with this is that the AVI file format that ANSYS uses compresses the images to save space, and to do so it really reduces the quality of the image.  So instead, you can write your own animation macro and save a PNG file for each frame, then use GIF Movie Gear to make an animation.

To learn about how to make the images for your own animation, check out an old Focus article in Issue 49 from 2006, on page 6.  It talks about the program we used to use to make an AVI instead of a GIF, but it works the same.  You basically make a plot and save it as a PNG then modify your image and make the next one.  We use that macro in the examples below and put it here for you to use.  Take a good long look at it

You probably also want to reread (because I know you read it when we put it out) the more recent article on making pretty images from March of this year.

A Simple Example

To get the gist of how this all works, let’s build a simple tower model, put a pressure on the side, then animate it’s displacement.  Download this macro and run it in MAPDL.  If you look at the macro the last thing it does is make a contour plot of the total deflection (PLNSOL, U, SUM).  This is what we want to animate.

So we simply type: “agif_anm1,10”  into the command line to run the animation macro and it will make 10 PNG file. Look in your working directory and you will see twrexmp000.png through twrexmp009.png.  These are the frames.  Now on to making our GIF.

Start GIF Movie Gear and you will get the little start wizard:


Click on Insert Frames.  This opens a file selection dialog box. Shift-select the 10 frames we just made and click open:


You will now see the upper right corner of the first frame… Don’t panic.  this is the size of your image and the window is small.  Click the little zoom in icon (magnifying glass with a minus sign) until you see a couple of frames.  If you click the play icon, you will see your animation play very fast.  Not what we want. 

So the first thing we will do is change the animation speed by changing the duration of each frame. It is 0 by default.  Go to Animation->Timing and it will show your hyper animation again. At the bottom, change the 0 to a 20 and hit return:


That calmed things down a bit. Close that window.

At this point you can simply save your animation and be done: File->Save and give it a name.  And this is what you get:


The Bloging software resizes it. Click on the image to get the full size version.

Changing the Size

That may not be the shape, size, or content you want.  To resize the image, use Animation->Resize:


Make sure that “Maintain aspect ratio” is checked.  If you don’t, your image can get distorted.  Then set the width or height to what you want.   I’ll use a width of 400.  Make sure the Bicubic is picked for your resizing.  The other method is slower to run but makes bad images unless you have only a few colors.  If you save this image you get the following:


Now, we may want to crop. We do that the same way: Animation->Crop. Now this is the only feature I don’t like. It shows the image in a small window. 


So click on the Zoom In icon till you can see your image and drag to where you want it and click OK. Save that and you get:



One of the coolest things about GIF files is that you can tell the display program to not show a certain color, to make your image transparent.  This is great for PowerPoints.  To do this you need to mark one of the colors in your animation as “transparent.”

Go to Animation->Properties then click on the Global Frame tab:


Click on Transparent and it will bring up your color Pallet.  click on the black background or the black color in the table and that will be the transparent color.  Now you need to set the bottom menu to “Restore to Background before drawing next frame”.  If you don’t do this you will see ghosting. 

Click OK. Save that and you get:


Not too exciting on this blog because the background is white.  But imagine we had some fancy background.  Copy and paste this into your corporate PowerPoint template and you will see:


Converting for AVI’s

What, you are not a gray haired throw back to a past time.  You use CDF Post or ANSYS Mechanical?  You can skip a lot of the first steps and just go straight from an AVI to an Animated GIF. 

Regardless of which tool you are using, you simply need to save an AVI to get started.  For ANSYS Mechanical you do that by using the animation viewer to get the animation you want then click on the “Export Video File” Icon.  Remember to make sure you have turned off the fancy Aero window stuff. 

To make a CFD animation read Clinton’s Article

Now that you have the AVI file you can make a GIF. Start GIF Movie Gear and click on Open File this time.  Choose the AVI and you will see all the frames in the AVI (zoom out if you need to).  If you like what you see, just do a File->Save As and save as a GIF. 


Just like the animations made from images, you can adjust the size of the image, crop, and set animations.

One thing you may notice is the banding on the background. This is in the AVI due to compression in the AVI.  So if you are making animation we recommend you create a solid background (set in the project schematic->Tools->Options->Appearance) :


And once you have done that, you can use transparency:


Other Things You Should Know

When setting transparencies above we talk about making sure it says: “Restore to Background before drawing next frame” If you don’t, this is what your animation will look like:



For debugging it is kid of a pain to place in PowerPoint then view as slide show.  A faster way to view an animated GIF is to RMB on it in the explorer and say Open With… and choose Internet Explorer.  You can also drag it into your browser.  Much faster.

The program has an Undo.  Use it.  Try stuff, save the file, look at it, then undo if you need to.

Another thing to be aware of is Ping-Pong.  If you remember our first animation of the deflected tower, it only goes to the max deflection then snaps back to the beginning. It would be much nicer if it went back.   You can do that by going to Animation->Rearrange Frames –>Ping-Pong Animation.


Now save and you have an “up and back” animation.  The original is on the left, the ping-pong is on the right.


This tool is also a great way to grab a single frame from an animation.  Say you have an animation and you need a picture, and you don’t want to go back in to the program to make it.  Simply read the AVI into this program, find the frame you want, then do a File->Save As. Pick your format and set “Save as Style” to Individual Image(s).  Then select the “Only selected frames(s)”


That is about it.  I hope this will help you make better presentations and cool web sites.

Do you have seizures yet?









HSFLD241/242: Modeling Enclosed Liquids

This is a second attempt at this posting.  The first attempt got 60% of the way done, then I rebooted my machine before I saved the posting… Doh.  So let’s try this again:


Every once in a while I feel the need to stop exploring all the new and cool stuff in the world of workbench and do a deep dive into something that involves names which are restricted to eight characters or less. Something that involves a script rather than a GUI click.  Something that requires you to look at a real equation, something with an integral sign in it:


I want to learn about something that uses comma delimited commands. 

So, up comes ANSYS Help, dive down into the release notes for Mechanical APDL and look for something obscure but useful.  New elements…  Aha!  HSFLD21 – now that is a name to make any I-only-use-the-GUI-and-manuals-with-equations-but-without-color-animations-make-me-nervous user cringe.  Hydrostatic.  I like that word.  It reads:

This 2-D hydrostatic fluid element models fluids that are fully enclosed by 2-D planar and axisymmetric solids. This element is well suited for modeling fluid-solid interaction with incompressible or compressible fluids under uniform pressure. It can be used in geometrically linear as well as nonlinear static and transient dynamic analyses.

Now I have something I can sink my teeth in.

The Basics on the HSFLD241 and HSFLD242

New at R13, these elements are used to model compressible or incompressible fluids that are surrounded by solids. The key assumption to be aware of is deserving of its own line:

The fluid volume has uniform pressure, temperature, and density without any gradients

So no sloshing, variation due to gravity, etc.. Take a look at FLUID80 if you want these things… maybe a future article topic.

HSFLD241 is the 2D and axisymetric version, and HSFLD242 is the 3D version.  If you look at the element pictures from the manual at the top of the posting you’ll see that they are a surface effect element with an extra node, called a pressure node.  You use ESURF to apply the element to the inside face of your enclosing volume, and you link all the faces that make up the volume by making them share a node (L or Q).  The fact that they all share the same node tells the solver that they make a volume. Besides sharing the node, they must share the same material and real number. 

When you use ESURF to make the elements, it automatically makes them a positive volume by the order it defines the face nodes with.  But sometimes you may want to create a negative volume inside your positive. Say you are modeling a tire (what this element was added for actually) and you will find that the pressure node is outside of the volume.  The calculated volume is not correct.  You need to subtract volume for the elements that are actually not in your volume. Here is a cross section to try and make more sense of it.


The purple parts are the fluid.  So this is not right. You need to go in and create negative elements on any faces that face away from the origin.  You do this in two steps:  Mesh using ESURF like you normally would, then grab the elements you want to turn into negative elements and issue the ESURF,pnode,REVERSE command.  This will turn those elements into negative volumes.  The key hear is to create your geometry in a way so that you can easily select faces that point away from the center of your volume. If you don’t, you will need to write a macro that loops through the elements, checks the vector from the face centroid to the center of you volume and if it facing out, swap the element normal. Not hard, just tedious.  In our example, the negative element will look like this (color changed for clarity):



The elements have displacement (UX,UY and UX,UY,UZ) Degrees of Freedom on the face part of the element, the part that sits on your structural elements.  The pressure node has a DOF of HDSP or hydrostatic pressure by default, and both PRES and HDSP if you set KEYOPT(1) = 1.  This is so you can hook the node to other elements that have PRES DOF’s like the FLUID116.

Real Constants

For real properties you have the ability to specify a thickness (defaults to 1) on the 2D element so the program can calculate volume correctly. Both versions have a real constant of PREF, the reference pressure. Simple enough.

Material Properties

If you opt for an incompressible fluid, just specify a density and coefficient of thermal expansion for your material.  But if you are modeling a compressible fluid, you use a new material property table to specify the material properties:  TB,FLUID.  Within the FLUID model you have three options:  a model for liquids, a model for gases, or you can provide pressure-volume data. It is recommended that you read the theory manual on these three to understand the difference and how to use them, as well as the standard command information for the TB.

For TB,FLUID,,,,LIQUID the model is basically a squishy solid.  You give a bulk modulus, coefficient of thermal expansion, and an initial density over up to 20 temperatures. 

For TB,FLUID,,,,GAS you simply give a Density. The program then simply uses the Ideal Gas Law… you remember that from freshman physics? Or was it chemistry.  I kind of remember it… sort of:


If you have a compressible fluid that does not follow the idea gas law, then you can supply your own pressure vs. volume table with TB,FLUID,,,,PVDATA.


KEYOPT(1) controls the DOF’s on the pressure node.  By default the uniform pressure for the solid is stored as HDSP.  If you set KEYOPT(1) to 1, then a PRES DOF is added and is set to be equal to HDSP.  This is so you can hook a FLUID116 up to it and flow out of your volume… more below.

KEYOPT(3) is used on the HSFLD241 element to say if it is Planer (0) or Axisymmetric (1)

Use KEYOPT(5) to turn on mass effects for the elements. Remember, this is a uniform mass. But if you have gravity or you are doing a modal analysis, you need this turned on.

Turn compressibility off by setting KEYOPT(1) to 1.

Other Basic Info

Give the manual page a read on the element.  There are a lot of output options besides the DOF solution. Stuff like Volume, Mass, and mass flow rate. 

Simple ExampleHSFLD_EXMP1

(Want to know how I made this animation… that will be next weeks article.
  I used a program called GIF Movie Gear, best $29.95 I’ve spent in a while…)

So, having waded through the boring bits, let’s build a model.  Our first example is simply a 2D hollow rectangle that we apply a pressure to. Here is the macro.  Take a look at the comments and follow the process.

   1: !Square Baloon Macro   - Example for HDSP241

   2: !

   3: ! Get in the begin level, clear the databse

   4: !   and go to the preprocessor

   5: finish

   6: /clear

   7: /prep7

   8: ! Define Dimensions as parameters

   9: wdth = 2

  10: hght = 4

  11: thk = .1

  12: ! Build two rectangles and subtract the inner one

  13: !  to make an enclosure

  14: blc4,(-1*wdth/2),0,wdth,hght

  15: blc4,(-1*wdth/2)+thk,thk,wdth-2*thk,hght-2*thk

  16: asba,1,2

  17: ! Make a component out of the inner lines - this is

  18: !  where we will put our HDSP elements

  19: lsel,s,,,5,8

  20: cm,l_insd,line


  22: ! Define a 182 for the solid and 241 for the fluid

  23: et,1,182

  24: et,2,241


  26: ! Sort of soft material for the enclosure wall

  27: mp,ex,1,10e5

  28: mp,nuxy,1,.3

  29: mp,dens,1,.001


  31: ! Some fluid properties

  32: tb,fluid,2,,,,liquid   ! Liquid Properties

  33: tbdata,1,300000        ! Bulk Modulous

  34: tbdata,2,6.4e-4        ! Coeficient of thermal exp.

  35: tbdata,3,.001          ! Density


  37: ! Mesh the enclosure wall

  38: type,1

  39: mat,1

  40: esize,thk/2

  41: amesh,all


  43: ! Grab the inside nodes from the compenent and create

  44: !   the fluid mesh using esurf

  45: cmsel,s,l_insd

  46: nsll,s,1

  47: type,2

  48: mat,2

  49: n,999,0,2

  50: esurf,999  ! Tell esurf to make the "extra" node 999

  51:            ! That all the elements share

  52: allsel,all


  54: ! Fix the bottom of the enclosure vertically

  55: !  And fix the bottom right corner tangentially

  56: !  to constrain the model

  57: nsel,s,loc,y,0

  58: d,all,uy

  59: nsel,r,loc,x,-1*wdth/2

  60: d,all,ux

  61: allsel


  63: ! Specify an load of 100 psi as the internal pressure

  64: !  The model will ramp up to that load over the specified

  65: !  substeps

  66: d,999,hdsp,100


  68: ! Set up Solve and Run

  69: /solu

  70: nlgeom,on

  71: nsubst,50,100,20

  72: outres,all,all   ! Don't forget to save substeps so you

  73:                  !   can animate them

  74: solve

  75: finish


  77: ! Animate the resulting displacement

  78: /post1

  79: set,last

  80: /dscale,1,1

  81: plnsol,u,sum

  82: andata,0.5,,0,0,0,1,0,1

One key thing to note in the code is the ESURF command.  Notice how you specify the common node as the first argument in the command. This is pretty useful and avoids making you go through and specify.  You can download the macro here.

HSFLD_Piston1A More Complex Example

The help on this element is pretty cool, and it even includes an example of how to build a piston. Unfortunately it does not include the part that solves it.  So I’ve added that imagemade some other changes, including an animation and a short trip into POST26 to get pressure and volume of the fluid over time. The code is below.  The most obvious thing when looking at this animation is the funny triangle thingy.  that is a negative element that deals with the fact that the volume is changing over time.  It is not 100% accurate but basically says any fluid above the piston needs to be subtracted.  In the image on the right, the solid geometry mesh, you can imagine that your fluid volume can be anywhere inside the piston, from the top of the yellow line to the whole length of the green.  The red dot shows the bottom corner of the piston.  If you make an element from the red dot to the top and bottom of the yellow line, no mater where the piston goes you will subtract the volume of any part of the total volume that is above the piston.  I found that kind of slick and clever of the ANSYS developers.  It doesn’t plot so cool, but it gets the job done.

Here is the code:

   1: finish

   2: /clear

   3: /prep7

   4: ! Define element types

   5: et,1,182    !plane182

   6: keyopt,1,3,1    !axisymmetric option

   7: et,2,241    !hsfld241 

   8: keyopt,2,3,1 ! axi option

   9: ! Material properties for Steel

  10: mp,ex,1,2.0e5    !Young's Modulus in N/mm^2

  11: mp,nuxy,1,0.3    !Poisson's ratio

  12: mp,dens,1,7.7e-9!Density in ton/mm^3


  14: ! Material properties for hydraulic fluid

  15: tb,fluid,2,,,,liquid

  16: tbdata,1,2000.0    !Bulk Modulus in N/mm^2

  17: tbdata,2,6.4e-4    !Coefficient of thermal expansion

  18: tbdata,3,8.42e-5!Density in ton/mm^3

  19: ! Nodes

  20: n,1,0.0,50.0    !pressure node

  21: ! Keypoints

  22: k, 1, 0.0,  0.0

  23: k, 2,25.0,  0.0

  24: k, 3,25.0,100.0

  25: k, 4,10.0,100.0

  26: k, 5,10.0, 95.0

  27: k, 6,20.0, 95.0

  28: k, 7,20.0,  5.0

  29: k, 8, 0.0,  5.0

  30: k, 9, 0.0, 80.0

  31: k,10,19.0, 80.0

  32: k,11,19.0, 85.0

  33: k,12, 3.5, 85.0

  34: k,13, 3.5,185.0

  35: k,14, 0.0,185.0

  36: ! Areas

  37: a,1,2,3,4,5,6,7,8

  38: a,9,10,11,12,13,14

  39: ! Planar elements

  40: type,1

  41: mat,1

  42: esize,2.5

  43: amesh,all

  44: ! Hydrostatic fluid elements--automatic generation

  45: type,2

  46: mat,2

  47: lsel,s,line,,6,9

  48: nsll,s,1

  49: esurf,1

  50: allsel,all

  51: ! Create the Negative volume element- needed to take into account

  52: ! the movement of the piston

  53: e,61,162,,1    !element with negative volume--nodes 61 and 162 swapped

  54: ! Symmetry boundary condition on pressure node   [REQUIRED]

  55: d,1,ux,0.0

  56: ! Symmetry boundary condition on planar mesh

  57: lsel,s,line,,8,14,6

  58: nsll,s,1

  59: d,all,ux,0.0

  60: allsel,all

  61: ! Fixed boundary condition on planar mesh

  62: lsel,s,line,,1

  63: nsll,s,1

  64: d,all,all,0.0

  65: allsel,all


  67: ! Grab the nodes on top and apply a downward displacement 

  68: nsel,s,,,179

  69: nsel,a,,,219

  70: cm,ptop,node

  71: d,ptop,uy,-35


  73: ! Run the model

  74: finish

  75: /solu

  76: nlgeom,on

  77: nsubst,200,500,10

  78: outres,all,all

  79: solve


  81: ! Go to post 26 and get pressure and volume over time

  82: /post26

  83: numvar,200

  84: ESOL,2,180,1 ,NMISC,2,NMISC2_2 

  85: nsol,3,1,HDSP

  86: /grtyp,2

  87: plvar,2 ,3


  89: !Animate the results

  90: /post1

  91: set,last

  92: /dscale,1,1

  93: /pnum,mat,1

  94: /number,1

  95: /edge,1,1

  96: !esel,u,,,eflp

  97: pldisp

  98: andata,0.1,,0,0,0,1,0,1


Here is the graph of the results.  Not very exciting.


Download the Macro here.

Other things to know

OK, this was a lot more involved than planned, and there is still more to learn.  But I’ve got HR paperwork to fill out so we will wrap it up.

You should go through the verification problem for this element: VM209

image image

  • You can connect different volumes with FLUID116 elements.  This allows some pretty fancy system modeling.  Add in some control elements and electromagnetics and you can really capture some complex systems.
  • Be very aware of the negative volume issues when modeling tires and such. 
  • After I started on this article I found out that we are in the middle of a project for a customer who is modeling an optical device that has a fluid core.  It is working very well for them. I wish I could show the model, but I would be shot by the customer.  I can say that we are getting much better results than when we modeled the volume with solids.
  • The FLUID80 is a solid fluid volume element that does take into account non-uniform pressure, mass, etc… Take a look at it if these guys don’t do what you need.
  • Can you do this in Workbench?  Sort of.  You should be able to write a macro that uses a component to create your hydrostatic elements and define the material properties.  You won’t be able to post process the results but you can at least set it up and bring back plots. (check out this presentation, slide 41)
  • Workbench Scripting: Using Forms in your Script

    Last week we had a very well attended Webinar on using Scripting with Workbench. We talked about how you can control projects, parameters, and material properties with python.  We also talked about how you can use python to drive data compliant applications by sending commands and/or parameters to it.  You can watch the webinar at: or click Here to download it and watch it with the WebEx player.

    Click on PADT ANSYS Webinar Series and then find the recording from August 11, 2011.

    Several attendees asked if we had an example of using python to bring up a GUI on top of workbench. We did not. This is how The Focus articles are born.

    The Basics

    In case you missed the webinar or didn’t follow some of it, here are the important points:

    • Workbench has IronPython built into it from the ground up
    • You can record whatever you do in the GUI to create scripts
    • You can read those scripts in to control Workbench
    • ANSYS uses IronPython because it talks to Windows programs
    • Get detailed info at,, and

    Most of the examples below are derived from information I got at:

    We will be making a GUI for the famous Tower of Test application.  We will need a place to enter in the size of the tower, a pressure load. Then a simple table showing the results when we get them. And of course, buttons to cancel and execute.

    If you are already an experienced Windows programmer, this will be a slam dunk. If you are not, then you will need to make sure you learn your way around the MSDN .Net Class Library Reference:

    That is where you find properties and methods for the GUI.  We will be spending most of our time in System.Windows.Form.

    Why .NET?

    Right now, some of you might be asking “Why .NET?”  Python supports probably over a dozen different GUI’s.  I am using .NET for a few reasons:

    1. It is built into IronPython. No need to download a library and install it right
    2. It will have a consistent look and feel to Workbench
    3. More people know .NET than the other GUI libraries.

    If you are anit-microsoft, you can poke around and find a library that fits your needs.  The process will be the same.

    Crawl: Always Start with Hello World

    Anytime I try and learn a new language, I usually find a “Hello World” Example.  And, thanks to the internet I found one that only needed slight modification:

       1: import clr

       2: clr.AddReference('System.Windows.Forms')


       4: from System.Windows.Forms import Application, Form, Label


       6: form = Form(Text="Hello World Form")

       7: label = Label(Text="Hello World!")


       9: form.Controls.Add(label)


      11: Form.ShowDialog(form)

    So first, we access the huge number of Windows tools by importing clr.  Then, get a reference to Windows Forms.  Once that is done we need to import more from Windows Forms. This is a big tool box so it has lots of levels you have to dig through.  For this guy we need to be able to do the form itself (the window) and a label (text in the window).

    Now that we have our objects, we create a form with the title “Hello World Form” and a label with the text “Hello World!”  We then use the Add method to add the label control to the form. Last, we use the Show Dialog method to show the form.  TADA.

    To give it a try, copy and paste this into your own text editor and then go into Workbench and choose:

    File->Scripting->Open Command Window…

    Then paste in the script.  Or you can save it to a file and read it in. I like to paste so I can see my error messages as it goes.


    Now you are a Workbench GUI programmer.  Put it on your resume!

    Walk: Add Some Controls to the Window

    Next we want to do a bit more than saying hello.

    The important thing I learned that I just didn’t’ get before is that you have to make a class out of your form and any functions that get called when the user clicks on a button or interacts in any way with the form.  You do this because Windows will then pass information about the form back to the event function.

    In the example below is like “Hello World” to start, then we make 4 text boxes with labels for the user to enter data into.  We then add an OK and a Cancel button.  The code is commented with an explanation of what is going on.  If something does not make sense, look it up in a python reference or ask someone who is a python programmer.

       1: # --  Bring in the .NET stuff, and reference Forms and drawing

       2: import clr

       3: clr.AddReference('System.Windows.Forms')

       4: clr.AddReference('System.Drawing')


       6: #   get the objects you need from forms and drawing

       7: from System.Windows.Forms import Form, Label, Button, TextBox

       8: from System.Drawing import Point, ContentAlignment


      10: #-- The way python works with events, you have to make a class out of your form.  

      11: #   Then the objects 

      12: #    you add are available in event functions.

      13: class TowerForm(Form):

      14:     def __init__(self):

      15: #-- First, make the form (self)

      16:         self.text="Tower Simulation Tool"

      17:         self.Height=500

      18:         self.Width=250


      20: #-- Create a Simple Text Label describing the tool

      21: #   it is not self.label because we are not going to access it in event functions

      22:         lbl1 = Label()

      23:         lbl1.Text = "This is the Tower of Test Tool. \n\

      24:             Please Enter values and click OK to run the \

      25:             model and get new results\n"

      26:         lbl1.Height = 50

      27:         lbl1.Width = 200


      29: #-- Create the Text Labels and text boxes to get Dimensions and Pressure

      30: #   We need to get to the textboxes so we will make them part of the class

      31: #

      32: #   some constants to make the positioning easier

      33:         x1 = 10

      34:         y1 = 80

      35:         w1 = 70

      36:         w2 = 80

      37:         x2 = x1 + w1 + 10

      38: #   Make the labels for the text boxes.  This is done in the Labe() call with 

      39: #   Name = Value arguments 

      40: #   instead of = value to save space.  All in one line instead of 

      41: #   four lines.

      42: #     The alighment is done so that the labels are all right justified to line 

      43: #     up with the boxes. Set ContentAlignment.MiddleRight to mr to save space

      44:         mr = ContentAlignment.MiddleRight

      45:         lb_Length=Label(Text="Length", Width=w1,TextAlign=mr)

      46:         lb_Width  = Label(Text="Width",   Width = w1, TextAlign=mr)

      47:         lb_Height = Label(Text="Height",  Width = w1, TextAlign=mr)

      48:         lb_Press  = Label(Text="Pressure",Width = w1, TextAlign=mr)


      50: #   Make the text boxes. Note that these are put in the self. class. 

      51: #   We do this so that when the OK 

      52: #   button is pushed, we have access to the text boxes and therefore the values 

      53: #   typed within


      55:         self.tb_Length = TextBox(Width = w2)

      56:         self.tb_Width  = TextBox(Width = w2)

      57:         self.tb_Height = TextBox(Width = w2)

      58:         self.tb_Press  = TextBox(Width = w2)


      60: #   Specify the location for the label and the text boxes.  Move down by 

      61: #   30 after each line

      62:         lb_Length.Location = Point(x1,y1)

      63:         self.tb_Length.Location = Point(x2,y1)

      64:         y1 = y1 + 30

      65:         lb_Width.Location = Point(x1,y1)

      66:         self.tb_Width.Location = Point(x2,y1)

      67:         y1 = y1 + 30

      68:         lb_Height.Location = Point(x1,y1)

      69:         self.tb_Height.Location = Point(x2,y1)

      70:         y1 = y1 + 30

      71:         lb_Press.Location = Point(x1,y1)

      72:         self.tb_Press.Location = Point(x2,y1)


      74: #   Make an OK and a Cancel Button

      75:         okBut = Button(Text="OK", Width=50)

      76:         okBut.Location = Point(30,430)

      77: #       This is where you specify the funtion to be called when the button is clicked

      78: #       note that you call the function self.functionname.

      79:         okBut.Click += self.okButPressed


      81:         cancelBut = Button(Text="Cancel", Width=50)

      82:         cancelBut.Location = Point(110,430)

      83:         cancelBut.Click += self.cancelButPressed


      85: #   Put everything on the form (some sort of list and loop would make this easier)

      86:         self.Controls.Add(lbl1)

      87:         self.Controls.Add(lb_Length)

      88:         self.Controls.Add(self.tb_Length)

      89:         self.Controls.Add(lb_Width)

      90:         self.Controls.Add(self.tb_Width)

      91:         self.Controls.Add(lb_Height)

      92:         self.Controls.Add(self.tb_Height)

      93:         self.Controls.Add(lb_Press)

      94:         self.Controls.Add(self.tb_Press)

      95:         self.Controls.Add(okBut)

      96:         self.Controls.Add(cancelBut)


      98: #-- Now define the button event functions as part of the class

      99: #

     100: # Cancel simply closes the form down.  Nothing fancy

     101:     def cancelButPressed(self, sender, args ):

     102:         print 'Closing the Window... Bye...\n'

     103:         self.Close()


     105: # OK prints the values of the text boxes to the console

     106: #   This will be replaced with calls to workbench for the next step

     107:     def okButPressed(self, sender, args ):

     108:         print 'Values Entered:\n'

     109:         print '  Length: %s\n' %self.tb_Length.Text

     110:         print '   Width: %s\n' %self.tb_Width.Text

     111:         print '  Height: %s\n' %self.tb_Height.Text

     112:         print 'Pressure: %s\n' %self.tb_Press.Text

     113:         self.Close()

     114: #---------End of class definition



     117: # Instantiate the form and make the form visible

     118: print '=======================================\n'

     119: print 'Opening the Windows...\n'

     120: myForm = TowerForm()

     121: Form.ShowDialog(myForm)


    If you have not programmed a go dialog box in a while by hand, instead of using a WYSIWIG GUI builder, you can see why.  Lots of lines… lots of lines…
    Here is the file without the numbers in it so you can run it in Workbench:

    imageRun:  Send Values to Workbench, Update Model, Get Results

    If you remember the previous article on Driving Workbench from Excel this will all look familiar.  If you don’t review the article, especially the part about getting parameters in and out of Workbench with Python.  To finish our example we will use the same basic code to:

    • Get the current values from Workbench and set our dialog to show those values
    • When the user hits OK:
      • Set the Workbench parameters to the current dialog box parameters
      • Update the model
      • Get the resulting deflection and display it.

    The code is shown below, with the bits added for the Workbench interaction highlighted.  Note that we also introduced the specification of font properties on a label.  Making it even more fancy.

       1: # --  Bring in the .NET stuff, and reference Forms and drawing

       2: import clr

       3: clr.AddReference('System.Windows.Forms')

       4: clr.AddReference('System.Drawing')


       6: #   get the objects you need from forms and drawing

       7: from System.Windows.Forms import Form, Label, Button, TextBox

       8: from System.Drawing import Point, ContentAlignment,

    Font, FontStyle, GraphicsUnit


      10: #-- The way python works with events, you have to make a class out of your form.  

      11: #   Then the objects 

      12: #    you add are available in event functions.

      13: class TowerForm(Form):

      14:     def __init__(self):

      15: #-- First, make the form (self)

      16:         self.text="Tower Simulation Tool"

      17:         self.Height=500

      18:         self.Width=250


      20: #-- Create a Simple Text Label describing the tool

      21: #   it is not self.label because we are not going to access it in event functions

      22:         lbl1 = Label()

      23:         lbl1.Text = "This is the Tower of Test Tool. \n\

      24:             Please Enter values and click OK to run the \

      25:             model and get new results\n"

      26:         lbl1.Height = 50

      27:         lbl1.Width = 200


      29: #-- Create the Text Labels and text boxes to get Dimensions and Pressure

      30: #   We need to get to the textboxes so we will make them part of the class

      31: #

      32: #   some constants to make the positioning easier

      33:         x1 = 10

      34:         y1 = 80

      35:         w1 = 70

      36:         w2 = 80

      37:         x2 = x1 + w1 + 10

      38: #   Make the labels for the text boxes.  This is done in the Labe() call with 

      39: #   Name = Value arguments 

      40: #   instead of = value to save space.  All in one line instead of 

      41: #   four lines.

      42: #     The alighment is done so that the labels are all right justified to line 

      43: #     up with the boxes. Set ContentAlignment.MiddleRight to mr to save space

      44:         mr = ContentAlignment.MiddleRight

      45:         lb_Length=Label(Text="Length", Width=w1,TextAlign=mr)

      46:         lb_Width  = Label(Text="Width",   Width = w1, TextAlign=mr)

      47:         lb_Height = Label(Text="Height",  Width = w1, TextAlign=mr)

      48:         lb_Press  = Label(Text="Pressure",Width = w1, TextAlign=mr)


      50: #   Make a label to give status of the update in:


    self.updlbl = Label(Text=” “,Width=200, Height=100,\




    self.updlbl.Location = Point(0,200)


    self.updlbl.Font = \


    Font(‘Verdana’,10, FontStyle.Bold, GraphicsUnit.Point,0)


      57: #   Make the text boxes. Note that these are put in the self. class. 

      58: #   We do this so that when the OK 

      59: #   button is pushed, we have access to the text boxes and therefore the values 

      60: #   typed within


      62:         self.tb_Length = TextBox(Width = w2)

      63:         self.tb_Width  = TextBox(Width = w2)

      64:         self.tb_Height = TextBox(Width = w2)

      65:         self.tb_Press  = TextBox(Width = w2)


      67: #   Specify the location for the label and the text boxes.  Move down by 

      68: #   30 after each line

      69:         lb_Length.Location = Point(x1,y1)

      70:         self.tb_Length.Location = Point(x2,y1)

      71:         y1 = y1 + 30

      72:         lb_Width.Location = Point(x1,y1)

      73:         self.tb_Width.Location = Point(x2,y1)

      74:         y1 = y1 + 30

      75:         lb_Height.Location = Point(x1,y1)

      76:         self.tb_Height.Location = Point(x2,y1)

      77:         y1 = y1 + 30

      78:         lb_Press.Location = Point(x1,y1)

      79:         self.tb_Press.Location = Point(x2,y1)


      81:         self.tb_Length.Text = Parameters.GetParameter(Name="P1").Expression

      82:         self.tb_Width.Text = Parameters.GetParameter(Name="P2").Expression

      83:         self.tb_Height.Text = Parameters.GetParameter(Name="P3").Expression

      84:         self.tb_Press.Text = Parameters.GetParameter(Name="P5").Expression


      86: #   Make an OK and a Cancel Button

      87:         okBut = Button(Text="OK", Width=50)

      88:         okBut.Location = Point(30,430)

      89: #       This is where you specify the funtion to be called when the button is clicked

      90: #       note that you call the function self.functionname.

      91:         okBut.Click += self.okButPressed


      93:         cancelBut = Button(Text="Cancel", Width=50)

      94:         cancelBut.Location = Point(110,430)

      95:         cancelBut.Click += self.cancelButPressed


      97: #   Put everything on the form (some sort of list and loop would make this easier)

      98:         self.Controls.Add(lbl1)

      99:         self.Controls.Add(lb_Length)

     100:         self.Controls.Add(self.tb_Length)

     101:         self.Controls.Add(lb_Width)

     102:         self.Controls.Add(self.tb_Width)

     103:         self.Controls.Add(lb_Height)

     104:         self.Controls.Add(self.tb_Height)

     105:         self.Controls.Add(lb_Press)

     106:         self.Controls.Add(self.tb_Press)



     108:         self.Controls.Add(okBut)

     109:         self.Controls.Add(cancelBut)


     111: #-- Now define the button event functions as part of the class

     112: #

     113: # Cancel simply closes the form down.  Nothing fancy

     114:     def cancelButPressed(self, sender, args ):

     115:         print 'Closing the Window... Bye...\n'

     116:         self.Close()


     118: # OK prints the values of the text boxes to the console

     119: #   This will be replaced with calls to workbench for the next step

     120:     def okButPressed(self, sender, args ):


     122: # In Workbench: Get objects for all the parameters you need access to

     123: #   Remember, it goes by parameter name, not the name you give them.


    lenParam = Parameters.GetParameter(Name=“P1”)


    widParam = Parameters.GetParameter(Name=“P2”)


    hgtParam = Parameters.GetParameter(Name=“P3”)


    prsParam = Parameters.GetParameter(Name=“P5”)

     128: # don't forget the resulting deflection output parameter:


    defParam = Parameters.GetParameter(Name=“P4”)


     131: # Now set the workbench values to the values from the dialog


    lenParam.Expression = self.tb_Length.Text


    widParam.Expression = self.tb_Width.Text


    hgtParam.Expression = self.tb_Height.Text


    prsParam.Expression = self.tb_Press.Text


    self.updlbl.Text = “Updating”





    dflValue = defParam.Value.Value


    self.updlbl.Text = “Deflection is %s in\n” %dflValue



     143: #---------End of class definition



     146: # Instantiate the form and make the form visible

     147: print '=======================================\n'

     148: print 'Opening the Windows...\n'

     149: myForm = TowerForm()

     150: Form.ShowDialog(myForm)



    Next Steps and Suggestions

    And that in a nutshell is the basics of putting a GUI on Workbench.  By using the calls to Workbench, .NET or any other complaint application, you can script away and do what you want.

    Much more can be done.  You could have the solver you are running in update and create some plots, and then use python to find those plots (say search for any *.jpg files in the project director created after the OK button was pushed) and insert them into PowerPoint with text that you also gather.

    There really are no limitations.

    To learn more, try stuff.  Get to know the MSDN documentation to know what you can do to make a more professional GUI.  The Windows Forms part of is a great resource for this and points to MSDN as needed.

    There is a lot more you can do with ANSYS  Workbench and the various solvers.  And with each release, workbench will add and document more.

    If you write a cool application you can share, make sure you put it on XANSYS or send it to Sheldon at

    CAE Market Fully Analyzed… Is that Cannibalism?

    Just saw a news article that a consulting company called 01 Consulting just did a study of the CAE market.  Unfortunately the report is $2,850 so, no matter how interested I am in the results I’m not going to buy one.

    However they did release an Executive Summary:

    And in there they have a cool graph that shows relative size (by revenue):

    The size of MathWorks was shocking to me how big they are.  At their price point that is a lot of seats.  ANSYS dominates, with between 20% and 25% of the market. 

    The other thing they mention is continued double digit growth in the CAE segment.  Even in these times, people are getting the message that simulation pays back big. 

    Workbench and Excel, Part 2: Driving Workbench From Excel with Python

    imageFor a couple of releases now you have been able to use the very common scripting language python to script applications that are considered Workbench native: the project page, Engineering Data, DesignXplorer, and the Parameter Manager.  This is pretty cool and something that we will cover in a future The Focus article.  But one thing that most people don’t know is that python also works well with Microsoft Excel.  So if it works with Excel and Workbench, you should be able to use it to connect the two. 

    Now before you get too excited, realize that ANSYS Mechanical, CFX, FLUENT, CFX Post and most other solvers and post processors that launch from Workbench are not workbench native applications, so they don’t speak python. So no, this is not a replacement for PADL or CCL.  They are called “data integrated” applications in that they share data through the Workbench interface, but they have their own software structure that is unique, and their own scripting language.

    So to take advantage of this python commonality you have to connect to one of the native applications, and the parameter manager makes the most sense.  And fortunately the kind technical people at ANSYS, Inc. have provided a great example in the help system to do just that. And in doing so they have cut the length of this article in half.

    ANSYS Documentation Example

    You can find the example under: Workbench //  Scripting Guide // Using Scripting in ANSYS Workbench // Usage Examples // Updating a Workbench Project and Parameters from Excel.  It is a very simple example, a cantilever beam, but it shows the basics and is a great place to start.


    Read the manual page completely, especially the notes at the bottom.  They point out the key things you need to know.  The files you need are in the documentation, but you need to dig up the excel/workbench files and copy the python script and get rid of the line numbers.  I’ve put them all together in a zip file to make things easier:  

    There are a few things worth discussing on this example before we move on to something more complicated.

    How to Run It

    One thing the example leaves out is the details on how to run it.  To start, you need to copy all the files to one directory: the python script, the workbench database, the workbench files, the excel file.  Then (it does point this out) you need to set the working directory variable in the script to the directory with all the files.  Now it is time to run. To do this open up Workbench with a new project (or File->New if you already have Workbench open).  Now run the script with File->Scripting->Run Script File…


    This will launch Excel and Workbench and add the command to execute the update script when you push the button.  So, what next?  Change the value for Bar Length or Load and press the button.  This should cause Workbench to update and the Maximum Deformation value to change to Updating… and then the new value when the run is done.  And that, in a nutshell, is the basics of making the two tools talk.

    How it Works

    The documentation does a pretty good job of explaining the details. The important take away is that you have to do a couple of key steps in any program that is going to do this sort of thing:

    1. Tell python to load the Excel stuff
    2. Set up the working directory, the routines all need absolute paths to work
    3. Grab cell’s from excel, grab params from Workbench, and set one to the other as needed
    4. Do an update
    5. Provide a mechanism to start the process (the button in this case)

    If you have these steps, you can make Excel and ANSYS talk.

    Where Things Run

    An important thing to get your head around is where the script is running, or more accurately, what process is reading and executing the script. The python interpreter is actually in the Workbench environment.  When you run the python script you are not running it in Excel or in the operating system.  It is running through a interpreter inside Workbench. 

    This is important because it controls what information is automatically available to the script as well as how you launch it.  In this example, you launch from Workbench and it starts up Excel, does stuff in Excel, and then assigns a python routine to the button. When the button is clicked, you are still running a python script in Workbench – it is just talking to Excel.

    Limitations in the Example

    There are two big limitations with this example when it comes to using it on a real problem. First, it is not general enough because you have to hard code in file names, directory locations, cell locations and strings. This is not a huge deal because if you are going to use an excel based simulation tool over and over, you only have to set it up once and go.

    The other problem is that the action to update the spreadsheet and model is assigned as an OLEObject to the button. Unfortunately this is only active when the script is running. Once it is done the click action is removed, and the button becomes useless… allowing for only one use of the button.  This is a significant issue.

    A More General and Complex (Sort Of) Example

    A common potential usage for this sort of tool would be to provide a user with an Excel based tool that they would use to design a part and see the results.  For this example we are going to use a very complicated tool for designing towers with a rectangular cross section.  The input variables are the length, width, and height of the tower as well as a pressure applied to one face.  The output variables are the deflection from the pressure and the first 10 natural frequencies. 

    Of course a real example would have more complex input and output values, and the spreadsheet would probably do a lot more calculations, perhaps even optimization.

    This example avoids the button problem by actually running Workbench from Excel by launching it from the command console and supplying the project file AND the python script as startup parameters to Workbench.  Workbench loads the project, runs the script, then exits.

    The Spreadsheet

    The spreadsheet is called TowerTool1 and it is a macro (xlsm) spreadsheet. You can download it here:


    The sheet is not that different from the ANSYS provided example. It has cells for input and output parameters.  It also has a button to update the system.  The first thing that is different is that it uses named ranges for the input and output cells.  To see the names go to Formulas->Defined Names->Name Manager.  I used “Create from Selection” to automatically assign the text in Column B to the values in Column C an D for each row. 

    Also note the units. Because Workbench parameters (with the exception of Design Modeler parameters) are unit sensitive, you can specify the units in those columns and use them to do unit conversion as needed. In this example only the units on the Pressure are implemented to show how this is done.

    There is also a little Drop Down Yes/No choice for the user to decide if they want to save the project file or not when they are done running.

    The button is also different from the ANSYS example.  Instead of being assigned an action by the python script, it executes a very simple Visual Basic routine:

    Private Sub CommandButton1_Click()
       retval = Shell(“C:\Program Files\Ansys Inc\V130\Framework\bin\win64\runwb2 \
    -X -R -F ExcelTower1.wbpj”, vbNormalFocus)
       End Sub

    The line uses the Shell function to execute a system level command in Windows.  The command it runs is the command line way to start Workbench.

    The –X says run interactive and exit when any given command line options are completed. 

    The –R gives a python script to be run, and this is our python script that is presented in detail below. 

    The –F specifies that project file to be executed.  As an aside, you could make this program more general by having a cell in the spreadsheet hold that file name and then substituting that value in the execution string.

    The ANSYS Model

    This extremely complex model can be found in the following archived project file:

    The model contains a DesignModeler solid, a static structural solution, and a modal analysis. The key aspect of the model are the parameters. 


    The outline for the parameter manager looks like this:



    The various parameters were set up in each system in the normal way, by clicking on the parameter box next to them for each value you want to supply or return.  The key thing to note here are the Names (P1-P15) for the parameters, because this is what our python script will use to change or retrieve values before and after the model update.

    The Script

    The actual script we are using is shown below.  Comments have been added to describe important steps.  You can download it, without the line numbers, here:

    Please don’t laugh too hard. I ran out of time to convert the code into something more concise using do loops and variables.  The whole thing could be made much more general if you know python better than I do.

       1: # IronPython imports to enable Excel interop,

       2: import clr

       3: clr.AddReference("Microsoft.Office.Interop.Excel")

       4: import Microsoft.Office.Interop.Excel as Excel

       5: from System.Runtime.InteropServices import Marshal


       7: # import system things needed below

       8: from System.IO import Directory, Path

       9: from System import DateTime


      11: # use the ANSYS function GetProjectDirectory to figure out what directory you are in

      12: # and set that to the current directory

      13: projDir = GetProjectDirectory()

      14: Directory.SetCurrentDirectory(projDir)


      16: # Open up a log file to put useful information in

      17: logFile = open("TowerTool.log","w")


      19: # Put a header in the log file

      20: logFile.write("================================================\n")

      21: logFile.write("Tower Tool Run Log File\n")

      22: logFile.write("================================================\n")

      23: logFile.write("Start time: " + DateTime.Now.ToString('yyyy-mm-dd hh:mm:ss') + "\n")

      24: logFile.write("Proj Dir: %s\n\n" % projDir)



      27: # Use the Excel GetActiveObject funtion to get the object for the excel session

      28: ex = Marshal.GetActiveObject("Excel.Application")

      29: # Make Excel visible

      30: ex.Visible = True

      31: # Define the active workbook and worksheet

      32: wb = ex.ActiveWorkbook

      33: ws = wb.ActiveSheet


      35: # In Excel: Grab values for the cells that we want data from (input cells)

      36: length = ws.Range["Length"](1,1).Value2

      37: width = ws.Range["Width"](1,1).Value2

      38: height = ws.Range["Height"](1,1).Value2

      39: press = ws.Range["Pressure"](1,1).Value2

      40: upress =  ws.Range["Pressure"](1,2).Value2


      42: # In Excel: See if the user wants to save the project after the update

      43: saveit = ws.Range["Save_Project"](1,1).Value2


      45: # In Workbench: Grab the parameter objects for the input values

      46: lenParam = Parameters.GetParameter(Name="P1")

      47: widParam = Parameters.GetParameter(Name="P2")

      48: hgtParam = Parameters.GetParameter(Name="P3")

      49: prsParam = Parameters.GetParameter(Name="P5")


      51: # In Workbench: Get the object for the deflection parameter vlue

      52: defParam = Parameters.GetParameter(Name="P4")


      54: #In Workbench: Set the value of the input parameters in Workbench using the values 

      55: #   we got from Excel

      56: lenParam.Expression = length.ToString()

      57: widParam.Expression = width.ToString()

      58: hgtParam.Expression = height.ToString()

      59: prsParam.Expression = press.ToString() + " [" + upress + "]"


      61: # Set the output values to "Calculating..." since they no longer match the input values

      62: ws.Range["Max_Bending_Distance"](1,1).Value2 = "Calculating..."

      63: ws.Range["Mode_1"](1,1).Value2 = "Calculating..."

      64: ws.Range["Mode_2"](1,1).Value2 = "Calculating..."

      65: ws.Range["Mode_3"](1,1).Value2 = "Calculating..."

      66: ws.Range["Mode_4"](1,1).Value2 = "Calculating..."

      67: ws.Range["Mode_5"](1,1).Value2 = "Calculating..."

      68: ws.Range["Mode_6"](1,1).Value2 = "Calculating..."

      69: ws.Range["Mode_7"](1,1).Value2 = "Calculating..."

      70: ws.Range["Mode_8"](1,1).Value2 = "Calculating..."

      71: ws.Range["Mode_9"](1,1).Value2 = "Calculating..."

      72: ws.Range["Mode_10"](1,1).Value2 = "Calculating..."


      74: # Now let Workbench go to town and update the systems using the new parameter values

      75: logFile.write("Updating Project\n")

      76: Update()


      78: # If asked for, save the project


      80: if saveit == "Yes": 

      81:     logFile.write("Saving Project\n")

      82:     Save()


      84: # Assign the value of the Excel deflection cell output deflection from Workbench 

      85: ws.Range["Max_Bending_Distance"](1,1).Value2 = defParam.Value.Value


      87: # Now go through the value of each natural frequency in Workbench and 

      88: #   set the corresponding cell in Excel

      89: #    This could be made more general or at least more concise by using a do loop

      90: #    Also note that instead of getting the objects, then the values the two steps are 

      91: #    combined for these values

      92: ws.Range["Mode_1"](1,1).Value2 = Parameters.GetParameter(Name="P6").Value.Value

      93: ws.Range["Mode_2"](1,1).Value2 = Parameters.GetParameter(Name="P7").Value.Value

      94: ws.Range["Mode_3"](1,1).Value2 = Parameters.GetParameter(Name="P8").Value.Value

      95: ws.Range["Mode_4"](1,1).Value2 = Parameters.GetParameter(Name="P9").Value.Value

      96: ws.Range["Mode_5"](1,1).Value2 = Parameters.GetParameter(Name="P10").Value.Value

      97: ws.Range["Mode_6"](1,1).Value2 = Parameters.GetParameter(Name="P11").Value.Value

      98: ws.Range["Mode_7"](1,1).Value2 = Parameters.GetParameter(Name="P12").Value.Value

      99: ws.Range["Mode_8"](1,1).Value2 = Parameters.GetParameter(Name="P13").Value.Value

     100: ws.Range["Mode_9"](1,1).Value2 = Parameters.GetParameter(Name="P14").Value.Value

     101: ws.Range["Mode_10"](1,1).Value2 = Parameters.GetParameter(Name="P15").Value.Value


     103: # Done!  Close the log file and move on 

     104: logFile.write("End time: " + DateTime.Now.ToString('yyyy-mm-dd hh:mm:ss') + "\n")

     105: logFile.close()


    Execution is pretty simple.  When the user pushes  the Update system button the program goes off and launches Workbench with the script as input.  The script changes the parameters, updates the model, saves if asked for, updates the values in the spreadsheet, then Workbench exits.

    One key thing to know is the issue with working directories.  The Excel file needs to be in the same directory as the script and the project.  Sometimes Excel changes the working directory (say you opened a different spreadsheet).  If you get an error on execution that Workbench can’t find the project file, you just need to go back to Excel and do a Save As in of your file on top of itself.  That fixes the problem. More advanced users can use VBA to control directories.


    The first resource for doing this type of work is the ANSYS Workbench->Scripting Guide in the online help. 

    ANSYS uses a flavor of python called IronPython. They have a great web site at:

    Specific info on the connection to Excel can be found at:

    Thoughts and Suggestions

    Both examples presented are pretty simple, but they have the core of what you need to drive Workbench from Excel. It really is not that hard to do and can provide a nice interface for users who don’t know Workbench. 

    Some areas for improvement and suggestions for a real application are:

    • Use jScript in Workbench to add a button that runs a script that attaches to an open Excel file and update based on the current values in that Excel file. So instead of running Workbench in batch from Excel, pressing the button would update everything.  That seems to be a more effective way to do it. (maybe a quick article in the future if Matt help me figure out how to add a button quickly…)
    • Do more with VBA or Python in the Excel file to make you Excel based tool more sophisticated. 
    • There is no error checking in this example… very bad.  For a real world tool a lot more code should be added to check things and to capture errors from various functions.
    • As one can imagine, this can be extended to other programs.  A good example would be an optimization tool or another “calculating” tool like MathCAD or Matlab. 

    Retrieving Accurate PSD Reaction Forces in ANSYS Mechanical

    We just finished up a tech support call for a customer that wanted a way to get accurate reaction loads from a PSD run in ANSYS Mechanical. Alex Grishin took the call and provided a nice example to the customer, so we thought we would leverage that and share it with all of you.  Even if you are not in need of this particular function, it is a great example of using snippets.  If you are not familiar with this, check out our recent webinar on the subject.

    The reason why you have to do this is because doing an accurate PSD force calculation is not a simple thing.  The math is a bit complicated, because PSD responses are probabilities of results that loose sign.  And it is right now only available in Mechanical APDL (MAPDL).  This is not a problem because we can use an APDL command object to get the results from MAPDL and bring them back to ANSYS Mechanical.

    Three Simple Steps

    There are three very simple steps needed to get this done:

    1. Identify the geometry you want the reaction loads calculated on
      Do this by selecting a face, edge, or corner and create a named component.  You will use that named component to grab the nodes that sit on the piece of geometry and do an FSUM in MAPDL. In our example, we call the named selection react_area1.
    2. Tell the solver to store the required modal information
      Since ANSYS Mechanical doesn’t do reaction force calculations they save disk space by not storing the info needed for such calculations, but we need them.  So add a command object in your modal analysis environment that says save all my results (outres) and expand all my modes (mxpand):
    3. Calculate the reaction force
      Now we simply need to add a command object to the post processing branch that:
      • gets the PSD deflection results (set,3)
      • selects the named selection (cmsel),which is a nodal component in MAPDL,
      • gets the nodes attached (esln)
      • calculates the reaction load (fsum)
      • stores the results in parameters that we return to ANSYS Mechanical. (*get,my_).  Remember that anytime you create a MAPDL parameter in the post processor that starts with my_ it gets returned to ANSYS Mechanical. (well, that is the default, you can change the prefix)
      • select everything so that MAPDL can keep post processing like normal

      For our example, it looks like this:

    The following figure shows the model tree for our example, and the returned parameters:


    Nothing fancy, simple in fact: Make a component, store the required info in the result files, do an FSUM and bring back the results.

    You can download the example here.


    That was a short article!  And no exciting pictures.  So… if you want to you could check out the travels of The PADT Hat around the world. 

    Workbench and Excel, Part 1: Using the Excel Component System

    It is a fact.  Microsoft Excel is the most used engineer tool in the world.  If you are like me, you do everything you can’t do in ANSYS in Excel.  And a lot of the time you wish you could talk directly from Excel to ANSYS – and in the day many of us wrote kludgey VB Macros that would write APDL scripts run ANSYS MAPDL in the background.  In the past couple of releases our friendly neighborhood ANSYS developers have added a lot of different ways to work with Excel: saving tables to a file, Python scripting to talk to Excel, and an Excel System.  I remember reading about these things as they came out, even wrote about how cool they were, but I never had the opportunity to use them.

    Then, last week, I noticed an Excel icon just sitting there in the toolbox, mocking me, taunting me to use it. 


    So I dragged it out on my project page and tried to use it… and got no where.  My assumptions were not valid, it  didn’t work the way I expected because, it turned out, I was not thinking about how it fit into the project correctly.  So I backed up, actually read the help (gasp!) and after a experimenting got it to work, I thought.  Then I talked to some folks at ANSYS, Inc. and they reminded me of what this is: an Excel Solver System.  It is  not a tool that lets you “drive” your project from Excel. It lets you use Excel to calculate values.

    This posting is a summary of what I learned. And as I was working through it I thought it would be good to also cover the python interface to Excel and how to save tabular information to Excel. These will be covered in future articles (hence this being Part 1).

    What You Need to Know

    As I said above, my problem was that I was thinking about how Excel fit into my project all wrong.  The first thing you should do is read the help on the Excel System.  The best way to find it is type excel into search.  The item with the most hits will take you to the article for component systems, then click on Microsoft Office Excel. (I wish I could just put a link in… grumble… grumble… Instead, I leave the link to buy MS Office 2013 for those who does not have it).

    To use the Excel system you do the following:

    1. Add the System to your project
    2. Make a spreadsheet and use range names to identify parameters
    3. Attach an Excel spreadsheet
    4. Edit the system and tell the program which parameters are input and which are output
    5. Go into the parameter manager and hook up any derived parameters you want to pass to Excel and use any of the Excel parameters with other parameters as needed
    6. Tell ANSYS to run a VB macro (if you want)
    7. Update your project or Design Points

    We will go through the process in detail but first, a few things you should know:

    • The system kind of looks and feels like the parameter manager in Workbench, but it is not.  You have to think of Excel as a “solver” that feeds parameters from and to the parameter manager.
      • I struggled with this because I thought of output parameters as values calculated by Workbench and input parameters as ones that come from Excel, but the opposite is true.
      • Excel Input Parameter: A value calculated in Workbench parameter manager
      • Excel Output Parameter: A value calculated in Excel
      • You need to get your head around this or you will get stuck like I did.  The example should help.
    • Parameters that come from DesignModeler are dimensionless in the parameter manager.
    • This one really held me up for a while.  If you assign a parameter from Excel that has a unit to drive your geometry in design modeler, you get an error. 
    • The solution is to make sure that you DO NOT use units on Excel parameters that you get or pass to DesingModeler
  • When you attach the Excel file to your Excel system on the project page Workbench copies the Excel file to your project and buries it in dpall\XLS.
    • You will get burned by this if you go to your original excel file, edit it, then try and update your project.  Your changes will not show up.  That is because it is not linked to the original file, it is linked to a copy stored in that XLS directory.
    • Once you have linked a file you should exit Excel then open the file by RMB on the Excel system and choose  “Open File in Excel” (see below for more on this whole process)
    • I recommend that you start buy making your Excel file, save it with the name you want in the C:\Temp directory, attach that file, close Excel, then open from Workbench.
    • Now you have a file to add your stuff to and you don’t have to worry about having an earlier version lurking around.
    • An important side effect of this is if you delete your system, it deletes your Excel file!  So make sure you make a copy or do a save as before you remove the Excel system
  • To get changes in Excel to show up in your project, you need to save the file AND refresh/reload.
    • Making a change to he Excel file will put the system out of date.  A refresh on the project page or a reload on the “Edit Configuration” page will update things.
  • The parameter names in Excel are case sensitive.  So whatever your prefix is in the system properties (WB_ by default) you need to have the same in your Excel spreadsheet for range names.
  • To get a full update, including running any macros and doing any calculation, you have to update the system.   This is kind of obvious, but I kept forgetting to do it.
  • Your Excel file will not update if you use RSM.  Make sure your default for updating your project is to run local and, that if you are using design points, you set that update to run in the foreground.
    • The easiest way to check and change this is to click on the parameter bar and view its properties.  Under Design Point Update Process set Update Option to Run in Foreground.
  • If you want to have your Excel file define both input and output parameters for the same ANSYS simulation, workbench sees that as  a “cyclic dependency and will not let you do it.
    • Although annoying at first glance, it kind of makes sense.  If you feed a value to Excel and then Excel calculates a new value that effects your ANSYS model, you need to update the ANSYS model, which will change the value that gets passed into Excel, which will change the value that gets passed out which changes your ANSYS model, which… and so it goes in a loop. This is considered a bad thing.
    • This goes back to the fact that Excel should be used as a solver, not as  ‘”driver” of you simulation.
    • If you do want to drive your analysis from Excel, you’ll need to do some scripting. We’ll cover that in a future article.

    The Process

    I started this article with a really cool valve demo model. Then found that it was just too slow and a pain to work with for showing how the Excel system works.  So I went back to my second favorite type of model, a simple “tower of test.”  (my favorite is a FPWHII – flat plate with a  hole in it).  You can download the project here.

    Add the System to Your Project

    Like every other system in Workbench, you simply drag from the toolbox to the Project Schematic.  Notice how the green “drop zones” are all empty spaces.  You can’t drop it on an existing cell in a system because there is no dependency between other systems and an Excel system.  The Excel system is connected through parameters, which we will see in a bit.


    Once you have dropped it onto the schematic, click on the Top cell (C1 in this case) and check out the properties (RMB Properties if the window is not already open).  From the properties you can see the system ID (XLS) and you can specify an Analysis Type.  You can leave it blank or type in something like “Home Grown Optimization.”

    Then click on the Analysis cell (C2 in this case) and look at the properties.  They are shown here:


    One key thing to note is that the directory where the Excel file will be copied is shown.  I did this once already on this project so it made a XLS-1 directory. If I did it again, I’d see XLS-2, etc…   In fact, by the time I got done with this article and trying all sorts of things, it ended up in XLS-8.

    The most important option under Setup is the “Parameter Key”   Any Excel named range that begins with this string will get read into the parameter manager.  If you make it blank, all the named ranges will come in. 

    Make a Spreadsheet and Use Range Names to Identify Parameters

    Now you need to create your spreadsheet.  You need to plan ahead here a bit.  Figure out what parameters you need Excel to get from your models and what parameters you want to send back.  Come up with good names because that is what gets passed to Workbench.

    What happens when you attach a file is that Workbench goes to the Excel sheet and steps through all the named ranges in the file.  If it finds one with a name that starts with the filter value, it grabs the first value in the range as the parameter value and then grabs the second as the units.  If your range is bigger, it just ignores the rest.

    So this tells us that we need to create a range that has at least one cell, or two if units are important. For our simple example we will be calculating costs  and outputting that using the input Volume, Length and Width. There is a formula in the cost cell that multiples those values times pre-set costs per unit volume, length and width and sums them up to get a cost.

    So the laziest thing you can do is select a cell and name it. 

    But it will help you and others if you actually make a table that has a descriptive name, the parameter name (WB_ should be your default), the value for that parameter, and the units, if any.  Note that for an input parameter you can just set the value to zero to get started.  Here is what the tables look like for our example:


    To create a range you select the value and units for a given parameter, hold down the Right-Mouse-Button (RMB), and Select “Define Range”


    A cool thing that Excel does is to use the value just to the left of the range as the default name of the range.  So by creating the table you save yourself some typing.  Or, if you don’t use a table, just type in the name you want . 


    Now just click OK and you have a named range.  You can repeat this for each range, or you can get fancy and use the fact that your data is in a table, with the parameter name to the left, to quickly generate all the ranges at once.

    To do this, select the WB Param, value and unit columns. Then go to –>Formulas –> Defined Names –> Create from Selection.  When the dialog box pops up make sure only “Left column” is checked.  Click OK.


    In one fell swoop you created all your named ranges.  To see, edit, and delete ranges, regardless of how they were created, go to Formulas –> Defined Names –> Name Manager. 


    Take some time to look at this and understand it. When you are debugging and fixing stuff, you will use this window. 

    Now you have an Excel file that Workbench will like!  Time to attach  it. Save it (I recommend to save to temp so you don’t get it confused with the copy that Workbench will make).

    Attach an Excel Spreadsheet

    This is the easiest step. Simply RMB on the Analysis cell in the system and browse for the file.

    imageNow your Analysis cell has a lightning bolt, update to have it read the file and find parameters.  If you have your parameters set up wrong, such that you don’t have any named ranges with the specified prefix, it will generate an error but will still attach the file.

    NOTE:  If you get some weird errors  “Unexpected error…” and “Exception from HRESULT:…” when updating your Excel system, check your Excel file.  Odds are you have an open dialog box or the file is somehow locked. The error generates because Workbench can’t get Excel to talk to it. 

    Edit the System and Tell the Program Which Parameters are Input and Which are Output

    Although you have a green check mark, you will notice that your system is still not connected to your parameters, and therefor it is not connected to the rest of your model.  The way to fix this is to RMB->Edit Configuration. Double-clicking on Analysis also does the same thing.


    This puts you in Outline Mode.  You should be familiar with this mode from the Parameter Manager or Engineering Data. 


    Take some time to explore this outline.  Notice the setup cell, where you have access to the system properties.  Then it’s child, the Excel file.  Click on it to the properties for the file connection.  Under that is the important stuff, the parameters.

    If you did everything correctly, you will see all of your parameters in alphabetical order.  If you click on one, you will see the properties.  Here they are for the cost value:


    It shows the range, the value and units (C column) and the Quantity name.  Workbench guesses by units.  So PSI comes in as pressure by default.  If it is a stress, you need to change it here.

    But your main task right now is to tell Workbench which of these parameters you want passed to the parameter manager, and what type of parameter, input or output, they are.  Here is where I get screwed up.  Because an input parameter in the parameter manager is an output parameter here.  Remember, the Excel system is a solver that takes in parameters from the parameter manager and send back values to drive your models.  So in our example, all the dimensions and the volume are passed from the parameter manager TO excel, so they are input.  The cost is passed from Excel to the Parameter manager so it is output. 


    Now you have hooked up your Excel system. Click on the “Return to Project” at the top of the window and you will go back to the project schematic and see that a Parameters cell has been added to the system and it has been attached to the parameter bar.


    Go Into the Parameter Manager and Hook Things Up

    Although the Geometry and Mechanical systems are connected through the parameters to the Excel system, no relationships exist.  We need to assign some values to our Excel parameters.

    This is what our test model looks like before we do this:


    Our goal is to have the parameters in the first column below to drive those in the second:

    Driving Parameter Driven Parameter
    P7: Len P10: WB_L
    P5: W1 P12: WB_W
    P8: Solid Volume P11: WB_V

    I tried to just click on the value in value column (C) and change the value from the number it is to the parameter name it should be but that does not work.  Because the parameter is set as a constant.  So, you need to click anywhere on the row for the parameter you want to set, then go down to the Properties window and change the Expression to the Parameter ID you want to change.  This changes the Expression to be an equation and the Expression Type to be Derived:


    That is it. You now have Excel in your project as a solver. Update your project and the cost will be calculated and presented as a parameter for optimization, DOE studies or whatever you want.

    Tell ANSYS to run a VB macro (if you want)

    One really cool feature is that you can tell the program to run a VB macro on an update. What you do is go to your system, click on Analysis then RMB-> Edit Configuration.  Then click on the file cell (A3).  The property area now shows info on your file, and has a Use Macro row at the bottom. Click on the checkbox and a Macro Name row will popup.  Enter the name of a macro in your spreadsheet and you are off.

    Here is a silly example where I use a macro to calculate a value.  For the example I put in the well known equation for deriving the Kafizle of a system:

    1. Create a new row in my table for the Kafizle value to go in
    2. Create a name WB_KF for the value
    3. Write my macro (don’t laugh):  
      Sub CalcKafizle()
             Range("E7") = Rnd(1) + Cos(Range("E5").Value)
      End Sub
    4. Save my sheet and KABOOM. I now need to save it as an xlsm, not xlsx!  I didn’t think about that!
      • This means my Excel connection wont’ work.  So you have to delete your system and start again with your macro file.  So plan ahead! I’m glad I did this silly example rather than running in to it on a real problem.
    5. Once everything is right again, go into the outline for the excel system and make that new parameter (WB_KF)  an output parameter.
    6. Then click on the File (A3) and go to the properties window and click on the Use Macro checkbox
    7. Put the macro name into the  Macro Name field


    Now you can run you project, and every time you do, the program will calculate a new cost and Kafizle value.  This of course begs the question, what are the proper units of Kafizle?  Here is the Design Point table:


    Thoughts and Conclusions

    I started this effort thinking I would drive my model from Excel, basically replacing the Parameter Manager with Excel.  But that does not work because Excel doesn’t know enough about your project to handle the dependencies that can really cause problems if you don’t solve in the correct order.  So once I figured that out I found some pretty good uses.  Here are some other ideas for how to use the Excel System:

    • Do additional post processing on result values
    • Use formulas or lookup tables to calculate loads. 
    • Just make sure that the values you take from your ANSYS model into Excel (inputs) are also input parameters in the parameter manager. 
  • Use tables and lookups to calculate input values for an analysis
    • A good example would be a “family of parts” application where you put in a part number and Excel does a vlookup() on a table that has all the input parameters listed by part number.
  • To include results from an ANSYS analysis in a system model you have in Excel.
    • You still have to force the update on the ANSYS side, which is not the ideal way to run a system model, but it may be easier than writing scripts and hooking it up that way.

    This is a new feature at R13 and it can be a bit “touchy.”  Especially if you are rooting around in it like a Javalina rooting around in your flower bed (Arizona reference).  If you do something really crazy it can loose its way and start generated errors. I found the best solution at that point was to save a copy of my Excel file, delete the system, and start over. 

    This took a lot longer than I thought to write, but the Excel System does a lot more than I thought.  I think as we all start thinking about how to use this tool, people will come up with some pretty cool applications.

    Knowing the ID of Coordinate Systems Created in ANSYS Mechanical – or perhaps – You didn’t know that, everyone knows that…

    During this weeks webinar on Using APDL Snippets in ANSYS Mechanical a question came up about coordinate systems. I actually don’t remember the original question, but in answering it the question came into my mind: how do you get access to the ID of coordinate systems that you create in ANSYS Mechanical?

    For a lot of items you can add to the ANSYS Mechanical model tree, you can attach a Command Object (snippet) and ANSYS Mechanical passes a parameter with the ID of the thing you want access to (material, contact pair, spring, joint, etc…).  But there is no way to add a Command Object to a coordinate system.

    So I dug into it and found something I didn’t know.  The problem with discovering something like this and sharing it is that you either just uncovered something that can help a lot of users or you are going to embarrass yourself over something that everyone already knows.  The idea of a blog is to be casual and informal, so let’s see which I did.

    If you click on a user created coordinate system in ANSYS Mechanical The Detail View list two things in the first grouping “Definition”.  They are Type and Coordinate System ID.  The default for the ID is “Program Controlled”  I’ve never clicked on it to see what the other options are. It turns out you can change it to “Manual”


    Once you do that it gives you a second “Coordinate System ID” line and you can put in whatever number you want there.


    Problem solved.  Just give your coordinate system whatever number you want and use that number in your macro.  Couldn’t be easier.

    Hopefully, this was helpful. If so, rate this posting at a 5.

    If you already knew this little factoid, rate it as a 1.

    – Eric

    Files and Info from “Using APDL Snippets in ANSYS Mechanical”

    We just finished the webinar “Using APDL Snippets in ANSYS Mechanical” and wanted to share the files weimage used and some additional information.

    The presentation can be found here.

    The sample script for plotting mode shapes is here.

    You can view a recording of the presentation here on our WebEx site.

    PADT’s ANSYS Webinar Series is now off on Summer Break. We will be back in August!

    A Further Assessment of Design Assessment

    Last weeks PADT ANSYS Webinar Series webinar was on a little used feature in ANSYS Mechanical called Design Assessment, or DA.  If you missed it, you can view a recording at:


    And a PDF of the presentation can be found here:

    As promised, this weeks The Focus posting will be a follow up on that webinar with an in-depth look at the scripts that were used in the example.  But first, let us review what DA is for those that don’t remember, fell asleep, or don’t want to sit through 60+ minutes of me mumbling into the telephone.

    Review of DA

    Design Assessment is a tool in ANSYS Workbench that works with ANSYS Mechanical to take results from multiple time or load steps, perform post processing on those results, and bring the calculated values back into ANSYS Mechanical for viewing as contour plots.  It was developed to allow the ANSYS, Inc. developers to add some special post processing tools needed in the off shore industry, but as they were working on it they saw the value of exposing the Application Programmers Interface (API) to the user community so anyone can write their own post processing tools.


    You use it by adding a Design Assessment system to you project.  In its most basic form, the default configuration, it is set up to do load case combinations.  That in itself is worth knowing how to use it.  But if you want to do more, you can point it to a custom post processing set of files and do your own calculations.

    A custom DA is defined by two things.  First is an XML file that tells ANSYS Mechanical what user input you want to capture, how you want to get results out of mechanical, what you want to do with the results, and how you want them displayed in your model tree.  Second is one or more Python scripts that actually do the work of capturing what the user input, getting results, doing the calculation, and sticking the resulting values back in the model.  Both are well documented and, once you get your head around the whole thing, pretty simple.

    Right now DA works with Static and Transient Structural models.  It also only allows access to element stress values.  Lots of good enhancements are coming in R14, but R13 is mature enough to use now.

    If that review was too quick, review the recording or the PowerPoint presentation.

    A Deep Dive Into an Example

    For the webinar we had a pretty simple, and a bit silly, example – the custom post processing tool took the results from a static stress model and truncates the stress values if they are above or below a user specified value.  Not a lot of calculating but a good example of how the tool works. 

    Note, this posting is going to be long because there is a lot of code pasted in.  For each section of code I’ll also include a link to the original file so you can download that yourself to use.

    Here is the XML file for the example (Original File):

       1:  <?xml version="1.0" encoding="utf-8"?>
    The first lesson learned was that you have to get all the tags and headers just right. 
    It is case sensitive and all the version and other stuff has to be there
    Cutting and pasting from something that work is the best way to go
       2:  <!-- 
       4:            XML file for ANSYS DA R13
       5:            Demonstration of how to use DA at R13
       6:            Goes through results and sets stresses below floor value to floor
       7:              value and above ceiling value to ceiling value.     
       9:          User adds DA Result to specify Floor and Ceiling
      10:          Attribute group can be used to specify a comment
      12:          Calls and in c:\temp
      14:          Eric Miller
      15:          5/18/2011
      16:  -->
    Everything is in a DARoot tag.
      18:  <DARoot ObjId ="1" Type="CAERep" Ver="2">
    Attributes tags define items you want to ask the user about.  
      19:    <Attributes ObjId="2" Type="CAERepBase" Ver="2">
    This first attribute is a drop down for the user to decide which stress value they want 
    You use <AttributeType> to make it a dropdown then put the values in <Validation>
      20:      <DAAttribute ObjId="101" Type="DAAttribute" Ver="2">
      21:        <AttributeName PropType="string">Stress Value</AttributeName>
      22:        <AttributeType PropType="string">DropDown</AttributeType>
      23:        <Application PropType="string">All</Application>
      24:        <Validation PropType="vector&amp;lt;string>">
      25:               SX,SY,SZ,SXY,SYZ,SXZ,S1,S2,S3,SEQV
      26:        </Validation>
      27:      </DAAttribute>
    Next is the prompt for the stress floor value
      28:      <DAAttribute ObjId="102" Type="DAAttribute" Ver="2">
      29:        <AttributeName PropType="string">Stress Floor</AttributeName>
      30:        <AttributeType PropType="string">Double</AttributeType>
      31:        <Application PropType="string">All</Application>
      32:        <Validation PropType="vector&amp;lt;string>">-1000000,10000000</Validation>
      33:      </DAAttribute>
    Then the Ceiling Value
      34:       <DAAttribute ObjId="103" Type="DAAttribute" Ver="2">
      35:        <AttributeName PropType="string">Stress Ceiling</AttributeName>
      36:        <AttributeType PropType="string">Double</AttributeType>
      37:        <Application PropType="string">All</Application>
      38:        <Validation PropType="vector&amp;lt;string>">-1000000,10000000</Validation>
      39:      </DAAttribute>
    Finally a user comment, just to show how to do a string.
      40:      <DAAttribute ObjId="201" Type="DAAttribute" Ver="2">
      41:        <AttributeName PropType="string">User Comments</AttributeName>
      42:        <AttributeType PropType="string">Text</AttributeType>
      43:        <Application PropType="string">All</Application>
      44:      </DAAttribute>
      45:    </Attributes>
    To expose an attribute, you can put it in an AttributeGroup to get info shared by
    all DA result objects.  This one just does the Comment
      46:    <AttributeGroups ObjId ="3" Type="CAERepBase" Ver="2">
      47:      <DAAttributeGroup ObjId="100002" Type="DAAttributeGroup" Ver="2">
      48:        <GroupType PropType="string">User Comments</GroupType>
      49:        <GroupSubtype PropType="string">Failure Criteria</GroupSubtype>
      50:        <AttributeIDs PropType="vector&amp;lt;unsigned int>">201</AttributeIDs>
      51:      </DAAttributeGroup>
      52:    </AttributeGroups>
    <DAScripts> is the most important part of the file.  It defines the scripts to run for a 
    solve and for a evaluate.  At R13 you do need to specify the whole path to your python files
      53:    <DAScripts ObjId="4" Type="DAScripts" Ver="2">
      54:      <Solve PropType="string">c:\temp\</Solve>
      55:      <Evaluate PropType="string">c:\temp\</Evaluate>
      56:      <DAData PropType="int">1</DAData>
      57:      <CombResults PropType="int">1</CombResults>
      58:      <SelectionExtra PropType="vector&amp;lt;string>">DeltaMin, DeltaMax</SelectionExtra>
      59:    </DAScripts>
    The other way to get user input is to put attributes into a <Results> object.  
    Here we are putting the choice of stresses (101),and the floor and ceiling (102,103)
    into an object
      60:    <Results ObjId="5" Type="CAERepBase" Ver="2">
      61:      <DAResult ObjId ="110000"  Type="DAResult" Ver="2">
      62:        <GroupType PropType="string">Ceiling and Floor Values</GroupType>
      63:        <AttributeIDs PropType="vector&amp;lt;unsigned int>">101,102,103</AttributeIDs>
      64:        <DisplayType PropType="string">ElemCont</DisplayType>
      65:      </DAResult>
      66:    </Results>
      67:  </DARoot>

    I always have to go over XML files a few times to figure them out. There is a lot of information, but only a small amount that you need to pay attention to.  After a while you figure out which is which.

    Now on to the fun part, the Python scripts.  The first one gets executed when they user chooses solve. is shown below and you can get the original here.   The comments inside pretty much explain it all.  It basically does two things:  creates an ANSYS MAPDL macro that extracts all the element stresses and puts them in a text file, then it runs MAPDL with that macro.

       1:  import subprocess
       2:  import os
       3:  import shutil
       5:  #======================================================================
       6:  #
       7:  #   ------------------------------------------------------------  PADT
       8:  #
       9:  #
      10:  #
      11:  #         Demonstration python script for Design Assessment in 
      12:  #            ANSYS R13
      13:  #         Called on solve from ANSYS Mechanical
      14:  #         Bulk of code copied and modified from TsaiWu example
      15:  #            provided by ANSYS, Inc.
      16:  #
      17:  #       E. Miller
      18:  #       5/18/2011
      19:  #======================================================================
      20:  def trunc_solve(DesignAssessment) :
      22:      # Get number of elements in model
      25:      # Change directory to current workspace for DA
      26:      originaldir = os.getcwd()
      27:      os.chdir(DesignAssessment.getHelper().getResultPath())
      29:      #Get the path to the results file name and the location of the temp directory
      30:      rstFname = DesignAssessment.Selection(0).Solution(0).getResult().ResultFilePath()
      31:      rstFname = rstFname.rstrip('.rst')
      32:      apath = DesignAssessment.getHelper().getResultPath()
      34:      print "Result File:", rstFname
      35:      print "Apath:", apath
      37:      # Write an ANSYS APDL macro to start ANSYS, resume the result file, grab the stress
      38:      #   results and write them to a file
      40:      macfile = open(DesignAssessment.getHelper().getResultPath()+"\\runda1.inp", "w")
      42:      macfile.write("/batch\n")
      43:      macfile.write("/post1\n")
      44:      macfile.write("file,"+rstFname+"\n")
      45:      macfile.write("set,last\n")
      46:      macfile.write("*get,emx,elem,,num,max\n")
      47:      macfile.write("*dim,evls,,emx,10\n")
      48:      macfile.write("etable,esx,s,x\n")
      49:      macfile.write("etable,esy,s,y\n")
      50:      macfile.write("etable,esz,s,z\n")
      51:      macfile.write("etable,esxy,s,xy\n")
      52:      macfile.write("etable,esyz,s,yz\n")
      53:      macfile.write("etable,esxz,s,xz\n")
      54:      macfile.write("etable,es1,s,1\n")
      55:      macfile.write("etable,es2,s,2\n")
      56:      macfile.write("etable,es3,s,3\n")
      57:      macfile.write("etable,eseqv,s,eqv\n")
      58:      macfile.write("*vget,evls(1, 1),elem,1,etab,  esx\n")
      59:      macfile.write("*vget,evls(1, 2),elem,1,etab,  esy\n")
      60:      macfile.write("*vget,evls(1, 3),elem,1,etab,  esz\n")
      61:      macfile.write("*vget,evls(1, 4),elem,1,etab, esxy\n")
      62:      macfile.write("*vget,evls(1, 5),elem,1,etab, esyz\n")
      63:      macfile.write("*vget,evls(1, 6),elem,1,etab, esxz\n")
      64:      macfile.write("*vget,evls(1, 7),elem,1,etab,  es1\n")
      65:      macfile.write("*vget,evls(1, 8),elem,1,etab,  es2\n")
      66:      macfile.write("*vget,evls(1, 9),elem,1,etab,  es3\n")
      67:      macfile.write("*vget,evls(1,10),elem,1,etab,eseqv\n")
      69:      macfile.write("*cfopen,darsts,txt\n")
      70:      macfile.write("*vwrite,evls(1,1),evls(1,2),evls(1,3),evls(1,4),
      71:      macfile.write("(G16.9, X, G16.9, X, G16.9, X, G16.9, X, G16.9, X, 
    G16.9, X, G16.9, X, G16.9, X, G16.9, X, G16.9)\n")
      72:      macfile.write("*cfclose\n")
      73:      macfile.write("finish\n")
      74:      macfile.write("/exit,nosave\n")
      76:      macfile.close()
      78:      # Set up execution of ANSYS MAPDL. 
      79:      #   Note: Right now you need to grab a different license than what Workbench is using
      80:      exelocation = "C:\\Program Files\\ANSYS Inc\\v130\\ansys\\bin\\winx64\\ansys130.exe"
      81:      commandlinestring = " -p ansys -b nolist -i runda1.inp -o runda1.out /minimise"
      83:      #Execute MAPDL and wait for it to finish
      84:      proc = subprocess.Popen(commandlinestring,shell=True,executable=exelocation)
      85:      rc = proc.wait()
      87:      # Read the output fromt the run and echo it to the DA log file
      88:      File = open("runda1.out","r")
      89:      DesignAssessment.getHelper().WriteToLog(
      90:      File.close()
      92:      # Go back to the original directory
      93:      os.chdir(originaldir)
      95:  trunc_solve(DesignAssessment

    Some key things you should note about this script:

    • You have to use MAPDL to get your stress values. Right now there is no method in the API to get the values directly.
    • You need a second MAPDL license in order to run this script.  It does not share the license you are using for ANSYS Mechanical at R13.  This should be addressed in R14.
      • One work around right now is to use an APDL code snippet in the ANSYS mechanical run that makes the text file when the original problem is solved.  The SOLVE script is then no longer needed and you can just have an evaluate script.  Not a great solution but it will work if you only have once seat of ANSYS available.
    • Note the directory changes and getting of result file paths.  This is important. Mechanical does stuff all over the place and not in just one directory.
    • Make sure the MAPDL execution stuff is correct for your installation.

    Once the solve is done and our text file, darsts.txt, is written, we can start truncating with the evaluate script (Original File).  This script is a little more sophisticated. First it simply reads the darsts.txt file into a python array.  It then has to go through a list of DA Results objects that the user added to their model and extract the stress value wanted as well as the floor and ceiling to truncate to. For each result object requested, it then loops through all the elements truncating as needed.  Then it stores the truncated values.

       1:  import subprocess
       2:  import os
       3:  import shutil
       4:  import sys
       6:  #======================================================================
       7:  #
       8:  #   ------------------------------------------------------------  PADT
       9:  #
      10:  #
      11:  #
      12:  #         Demonstration python script for Design Assessment in 
      13:  #            ANSYS R13
      14:  #         Called on eval from ANSYS Mechanical
      15:  #         Bulk of code copied and modified from TsaiWu example
      16:  #            provided by ANSYS, Inc.
      17:  #
      18:  # NOTE: Right now it just does SX.  XML and script need to be modified to allow user
      19:  #       to specify component to use (X, Y, or Z)
      20:  #
      21:  #       E. Miller
      22:  #       5/18/2011
      23:  #======================================================================
      24:  def trunc_eval(DesignAssessment) :
      26:      # Change directory to current workspace for DA
      27:      originaldir = os.getcwd()
      28:      os.chdir(DesignAssessment.getHelper().getResultPath())
      30:      # Find number of elements in DA
      31:      Mesh = DesignAssessment.GeometryMeshData()
      32:      Elements = Mesh.Elements()
      33:      Ecount = len(Elements)
      34:      print "DA number of elements is ",Ecount
      35:      print "Number of Result Groups:",DesignAssessment.NoOfResultGroups()
      37:      # get User comment from Atribute Group
      38:      # Note: Assuems one.  Need to use a loop for multiple
      39:      attg = DesignAssessment.AttributeGroups()
      40:      atts = attg[0].Attributes()
      41:      usercomment = atts[0].Value().GetAsString()
      42:      print "User Comment = ", usercomment
      44:          # create arrays for SX/Y/Z values
      45:      sx = []
      46:      sy =  []
      47:      sz = []
      48:      sxy = []
      49:      syz =  []
      50:      sxz = []
      51:      s1 = []
      52:      s2 = []
      53:      s3 = []
      54:      seqv = []
      55:      # read file written during solve phase
      56:      #   append stress values to SX/Y/Z arrays
      57:      File = open("darsts.txt","r")
      58:      for line in File:
      59:          words = line.split()
      60:          sx.append(float(words[0]))
      61:          sy.append(float(words[1]))
      62:          sz.append(float(words[2]))
      63:          sxy.append(float(words[3]))
      64:          syz.append(float(words[4]))
      65:          sxz.append(float(words[5]))
      66:          s1.append(float(words[6]))
      67:          s2.append(float(words[7]))
      68:          s3.append(float(words[8]))
      69:          seqv.append(float(words[9]))
      70:      File.close()
      72:      # Loop over DA Results created by user
      73:      for ResultGroupIter in range(DesignAssessment.NoOfResultGroups()):
      74:          # Get the Result Group
      75:          ResultGroup = DesignAssessment.ResultGroup(ResultGroupIter)
      76:          # Extract Cieling and Floor for the Group
      77:          strscmp  = ResultGroup.Attribute(0).Value().GetAsString()
      78:          strFloor = float(ResultGroup.Attribute(1).Value().GetAsString())
      79:          strCeil  = float(ResultGroup.Attribute(2).Value().GetAsString())
      80:          print "DA Result", ResultGroupIter+1, ":", strFloor, strCeil
      82:          #Add a set of results to store values in
      83:          ResultStructure = ResultGroup.AddStepResult()
      85:          print "strscmp", strscmp
      87:          # Loop on elements 
      88:          for ElementIter in range(Ecount):
      89:              #Add a place to put the results for this element
      90:              ResultValue = ResultStructure.AddElementResultValue()
      91:              # Get the element number and then grab SX values that
      92:              #   was read from file
      93:              Element = Mesh.Element(ElementIter).ID()
      95:              if strscmp == "SX":
      96:                  sss = sx[Element-1]
      97:              elif strscmp == "SY":
      98:                  sss = sy[Element-1]
      99:              elif strscmp == "SZ":
     100:                  sss = sz[Element-1]
     101:              elif strscmp == "SXY":
     102:                  sss = sxy[Element-1]
     103:              elif strscmp == "SYZ":
     104:                  sss = syz[Element-1]
     105:              elif strscmp == "SXZ":
     106:                  sss = sxz[Element-1]
     107:              elif strscmp == "S1":
     108:                  sss = s1[Element-1]
     109:              elif strscmp == "S2":
     110:                  sss = s2[Element-1]
     111:              elif strscmp == "S3":
     112:                  sss = s3[Element-1]
     113:              elif strscmp == "SEQV":
     114:                  sss = seqv[Element-1]
     116:              # Compare to Ceiling and Floor and truncate if needed
     117:              if sss > strCeil:
     118:                  sss = strCeil
     119:              if sss < strFloor:
     120:                  sss = strFloor
     121:              # Store the stress value
     122:              ResultValue.setValue(sss)
     123:      # Go back to the original directory
     124:      os.chdir(originaldir)
     126:  trunc_eval(DesignAssessment)

    Some things to note about this script are:

    • The same directory issues hold here.  Make sure you follow them
    • Always loop on ResultGroups.  You can assume the number of attributes is constant but you never know how many results the user has asked for.
    • In this example it is assumed that the stress label is the first attribute and that the floor and ceiling are the second and third.  This is probably lazy on my part and it should be more general.
      • The way to make it more general is to loop on the attributes in a group and grab their label, then use the label to determine which value it represents.
    • Before you can store values, you have to create the result object and then each result value in that structure:
      • ResultStructure = ResultGroup.AddStepResult() for each result object the user adds to the tree
      • ResultValue = ResultStructure.AddElementResultValue() for each element
      • ResultValue.setValue(sss) to set the actual value

    And that is our example.  It should work with any model, just make sure you get the paths right for where the files are.

    Be a Good Citizen and Share!

    If you have the gumption to go and try this tool out, we do ask that you share what you come up with.  A good place is www.ANSYS.NET.  That is the repository for most things ANSYS.  If you have questions or need help, try or your ANSYS support provider.

    Happy Assessing!

    Files for Design Assessment in R13

    During the Webinar on 5/18/2011 we discussed a simple example we created to show how to use Design Assessment.  Click here to download the Zip file.

    You can get a PDF of the PowerPoint here.

    You can watch a recording of the webinar at:


    Murphy’s Law of Convergence

    Ted Harris was working at tech support problem and got this convergence graph.  Ouch!

    He calls it “Murphy’s Law of Convergence”

    Jason called it “Asymptotic Sisyphaen Convergence”

    Doug commented:

    “It’s like a pinball machine.  Just shake the monitor a little, but not too much, don’t want to trip the tilt sensor. “

    I call it annoying.  Share your names or comments for this type of convergence below.


    A Moving Look at a Solid Tool: Rigid Dynamics

    Most of us who have been doing this simulation thing  for a while (in fact, if you still call it analysis instead of simulation you probably fall in this group) always think of ADAMS or DADDS when someone brings up Rigid Body Dynamics tools. Most people forget that ANSYS, Inc. has had a strong offering in this area for some time, and at R13 it really is mature and full featured. 


    A good place to start is to step back and describe what Rigid Dynamics is.  That is the name ANSYS, Inc. uses, but many people refer to it as Kinematic/Dynamic, Multibody Dynamics, Rigid Body Dynamics (RBD), or motion simulation. In most case all of these names refer to a numerical simulation where:

    1. More than one part is connected as an assembly
    2. Joints defined between the parts
    3. Large deflection motion
    4. Time dependent motion (if not, then it is just kinematics)
    5. Parts are rigid (not flexible) in most cases

    imageThink back to your dynamics class, probably your sophomore year in college.  Linkages, gears, cams, etc…  You are basically solving for the full equation of motion where inertia, time, gyroscopics. And all that stuff is taken into consideration.  The key thing to remember is that you can model a rigid system as a set of point masses  (Bodies) with inertial properties and six degrees of freedom (UX/Y/Z, and ROTX/Y/Z) You then connect them by defining a relationship (Joints) between their degrees of freedom.  You then apply forces, acceleration, velocity, and/or displacement over time and solve. To solve, the problem must be fully constrained in that there may not be any free DOF’s.

    You can learn more background on Wikipedia:  The most comprehensive jumping off point I found for the topic is a website from a the University of Waterloo:

    Rigid Dynamics in ANSYS

    You have been able to do Rigid Dynamics in ANSYS MAPDL for a long time.  MPC184 for joints and MASS21 for the bodies has been there since the Spice Girls were popular.  But, you had to use the implicit solver in MAPDL which can take some time to solve a long problem.  So ANSYS, Inc. has been working for a few releases now on an explicit rigid body solver that is much more efficient for this type of problem. You get access to the kinematic (no inertia terms, just motion) for free if you have ANSYS Professional NLS or better. To solve dynamics problems, you need a license for the Rigid Body Dynamics Solver as an add-on to ANSYS Professional NLS or better.

    To create a model you simply insert a “Rigid Dynamics” system into your project:

    imageFigure 1: Rigid Dynamics System

    It looks and acts a lot like an ANSYS Mechanical system, but is set up a bit differently to deal with the needs of Rigid Dynamics and to take away the things that you need for flexible FEA in ANSYS Mechanical.

    Analysis Process

    A real model can be very complicated and take some time to create, but the process of making it is the same regardless of the complexity:

    1. Do your normal geometry and material setup
    2. Remove auto contacts if you don’t need them (joints should constrain in most cases)
    3. Add any point masses you want to add
    4. Define Joints
      • Fix to ground as needed
      • Key is to make sure joints are correct and you don’t over/under constrain the problem
      • Coordinate system orientation is critical
      • Constrained DOF’s show up on plot for each joint – Blue=free
      • Lots of nice options
    5. Define Springs
      • Between geometry or geometry to ground
    6. Set Up Analysis
      • Define step controls
      • Solver options
      • Nonlinear Controls
      • Output Controls
    7. Apply Loads
      • Acceleration
      • Gravity
      • Joint Loads
      • Remote Displacement
      • Constraint Equations
    8. Solve
    9. Post Process
      • Deformation, Velocity, Acceleration of Parts
      • Total or Aligned
      • Probes on Parts, Joints, Springs
      • Key thing is to get graphs of behavior
      • Also makes a table you can export

    Joints, Springs & Contact

    An important part of any Rigid Dynamics tool is the Joint Library. This defines what you can and can’t connect.  The ANSYS tool has all of the standard options:

    Table 1: Joints (Courtesy of the ANSYS User Manual)

    ROTZ Free
    UZ, ROTZ Free
    UX Free
    UX, UY, UZ,
    User specified stiffness and damping in all DOF’s
    UX, UY, ROTZ Free
    ROTX, ROTY Free
    User defines free DOF’s as well as stiffness and damping on free DOF’s

    You define joints by selecting the Connections part of the tree and insert the Joint you want.  Joints can be between two bodies or between a body and fixed ground.  Each details view is a little different but most look like the one for the revolute joint:


    imageFigure 2: Revolute Details View

    In most cases, defining the joints is very easy.  You use the geometric feature that is in your real part to define the joint.  Two holes for a revolute joint or a slot for a slot.  The important thing to pay attention to for joints is which body is the reference body, and which is the mobile body. The first body you click on is the reference and the second is the mobile one.  If you get it wrong, RMB on the joint in the tree and choose Flip Reference/Mobile. 

    Next, pay attention to your coordinate systems for the joint. By default, the coordinate system is defined in the reference face of the details and by default is aligned with the geometry you picked to define the reference.  This is because the coordinate system needs to move with the geometry.  If the reference geometry isn’t exactly what you want, you can change it by picking a new face, line, or point.  Make sure you check the graphics window and that the coordinate system is in the right place.

    Once your joints are done, you can insert the other type of connection, a spring. They work the same way except the define a force load on the bodies that is related to their relative position.  You can have tension only, compression only, or a normal spring.  They work like joints in that you specify two bodies or a body and ground to connect.  You have more control on where the end points of the spring are, by specifying a piece of geometry or a point in a coordinate system.  You can also add in preload.

    imageFigure 3: Spring in Assembly

    You can also specify contact.  But before you do, make sure that a joint won’t work first.  If contact makes sense, then put it in just like you would in ANSYS Mechanical.

    imageFigure 4: Contact

    Other Stuff you Should Know

    Sometimes you don’t have geometry? No worries. you can define a point mass and add in its inertia properties to get the same behavior. 

    The Rigid Dynamics solver has its own command language and just like when you use MAPDL as the solver, you can use code snippets to send it commands.  It uses Python and the commands are documented in the help.  The most common use for this is creating relationships between DOF’s that joints can’t do.  Gears are the best example, you can specify that body 2 rotate twice for every time body 1 rotates, etc…  It is also a good way to define a non-linear spring or a complicated stop condition. 

    imageFigure 5: Code Snippets

    Speaking of stops, you can specify stops and locks on the joints to control how far a joint can move and if it reaches that stop, that it freezes (lock).


    And, without going into too much detail, that is Rigid Dynamics in ANSYS.  You can see some cool examples on the ANSYS web site:

    The key as always is to take the time to really read understand the tool then crawl-walk-run.  Don’t start with a 100 part assembly and expect it to work.  Pick a simple assembly or a simple subassembly and go from there.  In fact, regardless of your part, start with a four bar linkage and get that going first.

    Happy motion!

    PADT’s New CUBE HVPC Computers

    Editors Note, 7/30/2014:
    This was an early post on our CUBE systems, we have since updated and improved our offering.  Visit to get the latest information.

    Cube_Logo_Trg_100Most of you should have received an e-mail blast yesterday announcing that PADT is now selling  a line computer systems that are configured specifically for CFD and FEA users.  Our CUBE High Value Performance Computers became a product line when a couple of customers asked us about the hardware we ran on and if they could get the same from us.  After doing a couple of systems this way we decided to go mainstream. 

    You can read our announcement here:

    And you can download a brochure here:


    We also have a new website with more details:

    Give us a call (480.813.4884) or send an e-mail ( if you need more information or have questions.

    What is PADT Up To?

    Since The Focus is kind of an engineer-to-engineer exchange, we thought we would use this weeks posting to give the hard core users out there some details on these systems and some things everyone should know.

    The thing we want to point out first is that these are not super-fast high performance systems.These are based on the new AMD chips which are fast per cycle, but run at a lower clock speed. You would need the latest Intel Nahelem chips for maximum performance.  What they are is a balance between speed and price.  As an example, you can go to the Dell website and configure a 3.0 GHz Intel based system with 8 cores that is as close to the CUBE w12 (12 core) system for about $9,800.  the w12 is $5,800.  that is 68% more expensive than the Intel based system for maybe a 40% speed increase.  And, if you have enough parallel licenses, it may be about the same speed 12 AMD cores vs. 8 Intel cores.  That is the kind of tradeoff we look at when configuring these systems.  If you need more than 8 cores then the price difference really gets big.

    That is one way we get the price down. The other is by cutting back on two big price drivers for someone selling computers: service and inventory.  We just don’t cut back, we pretty much cut it out.  When you buy a system we order the parts to build it. This saves us a ton on inventory and we pass that on to you.  We did this because in reality, you really don’t need it tomorrow.  In fact, it will probably take 3-4 weeks just to get buy-in from your management.  So way then pay a lot of money to get the machine in 2-3 days when you already waited 3-4 weeks? 

    We really cut back on support. We test your system here with your software and then ship it off.  You get 8 hours of phone support and a 1 year parts only warranty.  After that, you have to pay for time or parts.  We did this because in the years we have been running computers for simulation, we never use the service and we almost never have a bad part we need replaced after one year.  sometimes you get a bad part right out of the box, but if it lasts a year, it will last till it is out of date.

    So, in a nutshell, we are trying to find a sweet spot for users where, for a reasonable amount of money, they can get a reasonable amount of throughput. 

    Some Highlights

    Portable Mini Cluster – 96 Cores, Two Boxes, 256 GB of RAM: $43,250

    One cool thing to point out about our 96 core system is that we built it to be portable.  We felt that if someone needed that much horsepower they probably wanted to share it.  So we build it into its own rack that we put on wheels.  We also add two UPS’s to provide battery backup power.  So if you need to unplug it and roll it down the hallway, go for it.  This also makes these systems perfect for use in security areas where you need to wheel a box around between closed secure rooms as needed. When you get done with a project, pull the drives and wheel it to the next project.

    Another cool thing about this system is that it uses a special Infiniband interconnect that does not require a switch when you connect only two systems.  This saves a few thousand dollars.

    The “Sweet Spot” – 32 Cores, 128 GB of RAM, $12,300

    We feel that the best deal in the CUBE line is the 32 core system.  Not so much because of the hardware but more because of the ANSYS HPC license packs.  If you buy two packs, you get the ability to two jobs on 8 cores each or one job on 32 cores.  It also comes with enough RAM to handle bigger problems (128GB) at a great price.  Even if you add some bells and whistles it should still be under $15,000.  You need to run the numbers but most users will be able to purchase a CUBE w32 and two HPC packs for about the same or less than two 8 cores systems, an interconnect, and 16 parallel tasks, and still run faster.

    What To Do with all Those Dang Files! – The 10TB Fileserver

    We configured this system after a customer that bought a 96 core system from us told us that they were paying something like $20k for a fancy file storage device.  Now granted, this is a very fast I/O machine with software and hardware that lets you write files to it during a run.  But honestly, why do that?  Why not just put 1-3 TB on your compute server or mini-cluster and then get a cheap box with a bunch of inexpensive disk drive on it. Run on the fast machine and when you get done, copy your files to the inexpensive file server.  Our pre-configured FS10 has 10GB of disk space for $5,000.

    But that only solves one problem: what to do with those big files when you need to keep them around.  What do you do for long term storage?  At PADT we use these external hard drive docking stations (eSTAT Drive Bay) and we go out and buy standard 1TB hard drives.  We plug those guys in, copy our files to the hard drive, unplug it, label the drive, and throw it in a drawer.  To be safe, we often make two copies of the files and actually put one in a fire safe.  The fs10 comes with an external eSATA Dual Drive bay to solve your long term archiving problems in a simple and cost effective way.

    Bottom Line

    So, is a CUBE HVPC system right for you?  You need to decide if giving up some speed, support and delivery time is worth the savings. Also, is a system designed for CFD and FEA a better fit, vs. a database server that they label as an HPC machine.  The best way is to contact us, and we’ll help answer those questions.

    Not the most exciting The Focus posting, but we think you will agree that this approach to computing can be very efficient, so we thought we would share it with you.