PADT Ansys API Python Script Part 1 Solve Post Tutorial
PADT Ansys API Python Script Part 1 Solve Post Tutorial
• Most serious ANSYS users would benefit from learning at least the basics of how the DPF-Post and pyMAPDL
work for a couple reasons:
1. To extend their current simulation capabilities. Although we won’t dive deeply into it, in this article
we’ll explore how users may export a model’s system equations and post-process a model outside of
Ansys These two tasks may seem unrelated, but a future article will tie them together (and show users
how to solve the system equations outside of ANSYS!)
2. To extend their current post-processing capabilities. This is actually the main ‘killer-app’ of the DPF-
Core product. Although ANSYS users have access to the ACT customization process automation tools,
that framework is limited to what’s currently available in the .NET version that ships with ANSYS. To
take a simple example: Suppose users want to perform a custom spectrum analysis (perhaps an
industry-specific mode-combination technique) using the eigenvectors from an ANSYS modal solution.
In such a case, the ACT framework is not ideal as it has no native capability for manipulating large
matrix systems*
• Read more about the DPF-Core and view a quick example here:
[Link]
• So, we suggest installing Python 3.8 if you dont’ already have it. And again: We mean a
‘standalone’ installation. Users may download an installer for Windows here *veteran python users should also
know that the following useful
modules ship WITH the pyANSYS
products:
• numpy
• scipy
• pyVista
We Make Innovation Work • matplotlib
[Link]
• and more...
Preliminaries: Installing. From Scratch
• After downloading the installer, right-click on it and “Run as administrator” (you really should have
administrative privileges to install software)
• Check “Add Python 3.8 to PATH” –but only if you don’t already
have a path variable set for another installation (or you’re ok
with overriding it. Or you simply specify the Scripts folder each
time you want to launch an editor).
• An alternative (if you insist on having multiple versions of
python installed) is to set custom environment variables –one
for each installation. Then execute the environment variable
corresponding to the installation you want to access at the
command prompt
• Click “Install Now”
We Make Innovation Work
[Link]
Preliminaries: Installing. From Scratch
• Now, launch a command prompt as adminstrator (right-click on Command Prompt from the main menu and
select Run as administrator)
• If everything went smoothly so far, you should be able to type “python –version” at the prompt and see the
following:
• Try a simple test of the installation at the command prompt. Open a python shell by typing “python”
• Then, at the prompt, type “from ansys-mapdl-core import launch_mapdl”
• If successful, you wont’ see any errors or warnings (like below)
• However, some users may get an error related to the version of Google’s protobuf installed
• If you fall into this category, uninstall protobuf, and then install protobuf version 3.20* (first type “pip
uninstall protobuf <enter>” followed by “pip install protobuf == 3.20 <enter>”
.py files,
dp0\SYS-1\MECH
Single [Link],
[Link],
Quadratic [Link]
Rectangle [Link]
[Link]
Model [Link]
• We’ll fix
uy here
1
2
• We’ll fix
ux and uy
here
file: [Link]
import os
import sys
• Change this path to wpath = r"C:\Users\[Link]\exporting_matrices" • Specify the python working
your location before [Link](wpath) directory
execution! [Link](wpath)
• import [Link]
from kmat import *
solution = post.load_solution(resultpath)
disp = [Link]()
stress = [Link]() • Plot ux
disp.x.plot_contour(cpos='xy',cmap='rainbow',n_colors=9) • Plot sx
[Link].plot_contour(cpos='xy',cmap='rainbow',n_colors=9)
[Link]() • close the MAPDL connection
We Make Innovation Work
[Link]
The Example Problem: Single Linear Rectangle Model
• From the Start Menu, open a python shell and simply cut-and-paste the
lines from the previous slide into the shell
• You’ll see the displacement plot first pop up in a ‘blocking’ window
• You’ll have to explicitly close this window before you can see the stress
result, which will pop up the same way
• Just make sure to close both windows to execute all the code
• Note that this behavior is a feature of the python shell we’re using to execute this
code. Different editors will have behave differently when confronted with an
interactive blocking process σx
ux
• Just verify that these plots are the same as what’s shown in Workbench
• This verifies the NAFEMS solution for the linear rectangle case: A null result. Dont’
worry, there’s nothing wrong here. The authors of the challenge problem
specifically designed it to produce a null result over a linear rectangle!
ux σx
file: [Link]
• Following the NAFEMS challenge
import os
problem directions, next verify the
import sys
single quadratic element by wpath = r"C:\Users\[Link]\exporting_matrices"
cutting-and-pasting the code at [Link](wpath)
right into a new python shell [Link](wpath)
• Notice, this code is nearly identical from kmat import *
to the code we previously
executed for the linear rectangle, solverfilesloc = wpath + "\\plane_stress_files\\dp0\\SYS-1\\MECH"
but this time we’re pointing to a dspath = solverfilesloc + "\\[Link]"
resultpath = solverfilesloc + "\\[Link]"
different folder for the [Link] and
mapdl = launch_mapdl(run_location=solverfilesloc,override=True)
results file (see slide 10) runandsolve(mapdl,dspath)
matrix_export(mapdl,kname='k2',fname='f2')
solution = post.load_solution(resultpath)
disp = [Link]()
stress = [Link]()
disp.x.plot_contour(cpos='xy',cmap='rainbow',n_colors=9)
[Link].plot_contour(cpos='xy',cmap='rainbow',n_colors=9)
We Make Innovation Work
[Link]()
[Link]
The Example Problem: Single Quadratic Rectangle Model
• And again: compare
ux (Workbench) σx (Workbench)
ux (dpf-post) σx (dpf-post)
ux
ux
• They ARE the same
values
• It’s just that the DPF-
post plot seems to
just be interpolating
the 4 corner node
values (or something.
We’ll get to the
We Make Innovation Work bottom of this!)
[Link]
The Example Problem: Single Quadratic Rectangle Model
• It’s worth spending a little time contemplating what’s going on here
• To help with this, we’ll first introduce a VERY useful tool which came to us silently,
without charge and without any mention when we downloaded the pyANSYS
modules: pyVista
• All the mesh-based contour plots we see in pyMAPDL, pyDPF-Post, and DPF-Core
are provided using this tool ‘under the hood’
• To prove this, type the following in the same open python session (we want the
‘mapdl’ and ‘solution’ objects to be instantiated before doing this)
import pyvista as pv <enter>
[Link] <enter>
[Link] <enter>
• This makes sense, right? We should be looking at a single quadrilateral rectangle, right?
• Note that if you copied the [Link] instead, you would see 5 elements. This is
because that mesh differs in that it also contains the surface effect elements (and these are
just line elements coincident with the quadrilateral edges) which are used to apply the
surface tractions...
• According to
Workbench, the solution
should be as shown as
shown at the right:
copygrid['ux'] = ux
• This line adds the result data to the grid for plotting.
Note the dictionary-like syntax
• Plot the displacement like so:
p = [Link]()
p.add_mesh(copygrid,scalars='ux',
cmap='rainbow',n_colors=9)
p.camera_position='xy'
• This is what you should see!
[Link]()
• This is identical to the pyDPF-Post
plot
We Make Innovation Work
[Link]
The Example Problem: Single Quadratic Rectangle Model
• Ok. We’ve verified the pyDPF solution. But we still neeed to explain why it differs from the WB
solution
• Here’s where things get really interesting (for readers interested in the guts of FEA)
• We menionted (on slide 18) that pyDPF-Post seems to be only interpolating the corner nodes,
and so it does –even for the plot we just created OUTSIDE of both ANSYS and pyDPF-Post where
we were quite careful to map all the nodal results to their correct place.
• We can verify that pyDPF-Post is doing that by querying the mesh’s connectivity:
• Remember that in pyVista (and python generally), arrays are indexed by zero. So when we query this
mesh’s node connectivity, we expect to see (according to the ANSYS convention and mesh we see in
Workbench):
• [0,1,2,3,4,6,7,5]
• What’s happening is that pyDPF-Post is copying the mid-side nodes to lie on top of the corner nodes!
• We can use pyVista to generate a contour plot like the one shown in Workbench
• Hopefully, doing so will reveal much about how modern FEA software works AND the NAFEMS
challenge problem
• First, let’s create a better displacement plot. We’ll build on what we’ve learned so far and create a
quadratic quadrilateral mesh ‘from scratch’. This time, we’ll properly define the midside nodes
• pyVista is a high-level python wrapper around a larger and older framework called VTK
• When we define a mesh (‘grid’ in VTK parlance) in pyVista, we’re using the names and conventions
of VTK. So, for example, to define a quadratic quadrilateral, we first have to look that up in VTK
(see the link here).
• The type we’re looking for is called VTK_QUADRATIC_QUAD (id = 23)
• To create this grid type in pyVista with the nodes we already have, simply cut-and-paste the
following into the python session:
import vtk
cells = [Link]([8,0,1,2,3,4,6,7,5])
cell_type = [Link]([vtk.VTK_QUADRATIC_QUAD])
myquad = [Link](cells,cell_type,[Link])
• Well, that’s MUCH better. At least values along edges look right.
• It looks like the Workbench solution still has an advantage, though.
• Notice that we can query the center of the mesh, even though we DON’T HAVE A NODE THERE
• Remember, a finite element solution is smooth throughout it’s domain (sometimes called ‘the
support’). Though we don’t have nodes within that domain, we should still be able to query values
ANYWHERE (via the shape functions). This fact is leveraged when creating finite element contour
plots (even if users can’t query any location they want. In a future article, we’ll show how DPF-Post
and pyVista will allow us to overcome obstacles like that)
• Now, append the center ‘ux’ value from Workbench to our ux solution and add it the mesh:
ux = [Link](ux,0.5)
mybiquad['ux'] = ux
• And plot as before...
p = [Link]()
p.add_mesh(mybiquad,scalars='ux',cmap
='rainbow',n_colors=9)
p.camera_position='xy'
[Link]()
• And compare...
• This is as far as we can go with a
single cell in pyVista. We can verify
that every node has the correct value
• Differences in the two plots are due
to different plotting algorithms. We
will return to this in a future article
• Let’s return again to the challenge problem. Recall that we get a null solution (both displacements
and stresses) with the linear rectangle. We’re NOT getting a null solution now
• As we mentioned, this problem was designed to produce a null solution for a linear rectangle, but
the exact solution is only zero over a region of the rectangle as reflected in the (exact) component
stress solutions shown below (we’ve already verified σx)
• Let’s follow the author and reproduce some of the “low fidelity” stress results he reports.
• In particular, we want to show how CS1 and CS2 below can come about with the solution post-
processing techniques we’ve just seen
• In the same python session we’ve been using (we need the ‘stress’ object active), execute the following:
stress.von_mises.plot_contour(cpos='xy',cmap='rainbow',n_colors=9)
• This should result in the following:
• This is identical to
the plot the
NAFEMS author
calls CS1 (and it’s
also what you get in
MAPDL)
• Based on the work we’ve already done, we can easily check to see if the quadratic or
bi-quadratic pyVista cell can produce solutions similar to the Workbench result.
• We’ll re-use the pyVista grids we’ve already created
• Just as we obtained the ux result, stored it in an array with correct node ordering and
plotted it over the pyVista cell vertices, we can do the same with the von Mises stress
• Try the following:
seqv = [Link](8)
ids = [Link](stress.von_mises.get_scoping_at_field())
seqv[ids-1] = stress.von_mises.get_data_at_field()
myquad['seqv'] = seqv
mybiquad['seqv'] =[Link](seqv,1.0) • add the WB stress at center
• To plot the eight-node • To plot the nine-node
quadrilateral von Mises bi-quadrilateral von
stress: Mises stress:
p = [Link]() p = [Link]()
p.add_mesh(myquad,scalars='seqv', p.add_mesh(mybiquad,scalars='seqv',
cmap='rainbow',n_colors=9) cmap='rainbow',n_colors=9)
p.camera_position='xy' p.camera_position='xy'
[Link]() [Link]()
We Make Innovation Work
[Link]
The Example Problem: Single Quadratic Rectangle Model
• And this is what results
• We defintely believe the CS2 models as a trend (at least at the edges if not the center).
It’s not really clear if the Workbench plotting algorithm adds any more information than
the one we used with pyVista (botom left. In other words: is the Workbench solution
‘closer’ to the exact result?)
σeqv σ eqv
solution = post.load_solution(resultpath)
disp = [Link]()
stress = [Link]()
#commenting the displacement plots because we don't need them for demo...
#disp.x.plot_contour(cpos='xy',cmap='rainbow',n_colors=9)
stress.von_mises.plot_contour(cpos='xy',cmap='rainbow',n_colors=9)
[Link]()
seqv = [Link](newquad.n_points)
ids = [Link](stress.von_mises.get_scoping_at_field())
seqv[ids-1] = stress.von_mises.get_data_at_field()
newquad['seqv'] = seqv
We Make Innovation Work
[Link]
The Example Problem: Conclusions
• Finally, plot as before (but this time, set the ‘show_edges’ option to ‘yes’)
p = [Link]()
p.add_mesh(newquad,scalars='seqv',
cmap='rainbow',n_colors=9, • show edges to revealt the
show_edges='yes') VTK_QUADRILATERAL_QUAD cell edges
p.camera_position='xy'
[Link]()
• Finaly, comparing all three algorithms on an 8 x 8 mesh of quadratic elements reveals that the
Workbench algorithm (CS2) and our pyVista solution (middle figure) are both smoother (converge
faster) than the CS1 solution (DPF-Post and MAPDL)
σeqv σeqv σeqv
• One last thing: though the NAFEMS author neglects displacements, we plot the
distorted displacement of the refined model just to show readers how this contrived
model behaves (compare to single quadratic element on slide 28)
ux uy