Skip to content

Commit

Permalink
improved conveter, added docs, added back translator
Browse files Browse the repository at this point in the history
  • Loading branch information
akaszynski committed Aug 20, 2018
1 parent 1046eaa commit 23e2627
Show file tree
Hide file tree
Showing 10 changed files with 1,450 additions and 277 deletions.
5 changes: 5 additions & 0 deletions doc/ansys_commands.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@

ANSYS Object Methods
--------------------
.. autoclass:: pyansys.ANSYS
:members:
287 changes: 269 additions & 18 deletions doc/ansys_control.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ To run, ``pyansys`` needs to know the location of the ANSYS binary. When runnin
from pyansys import examples
examples.CylinderANSYS()
Python will automatically attempt to detect your ANSYS binary based on enviornmental variables. If it is unable to find a copy of ANSYS, you will be prompted for the location of the ANSYS executable. Here is a sample input for Linux and Windows:
Python will automatically attempt to detect your ANSYS binary based on environmental variables. If it is unable to find a copy of ANSYS, you will be prompted for the location of the ANSYS executable. Here is a sample input for Linux and Windows:

.. code::
Expand Down Expand Up @@ -169,6 +169,7 @@ For example, verification file vm1.dat:

.. code::
/COM,ANSYS MEDIA REL. 150 (11/8/2013) REF. VERIF. MANUAL: REL. 150
/VERIFY,VM1
/PREP7
/TITLE, VM1, STATICALLY INDETERMINATE REACTION FORCE ANALYSIS
Expand All @@ -183,52 +184,277 @@ For example, verification file vm1.dat:
N,3,,7
N,4,,10
E,1,2 ! DEFINE ELEMENTS
Translates to:

EGEN,3,1,1
D,1,ALL,,,4,3 ! BOUNDARY CONDITIONS AND LOADING
F,2,FY,-500
F,3,FY,-1000
FINISH
/SOLU
OUTPR,BASIC,1
OUTPR,NLOAD,1
SOLVE
FINISH
/POST1
NSEL,S,LOC,Y,10
FSUM
*GET,REAC_1,FSUM,,ITEM,FY
NSEL,S,LOC,Y,0
FSUM
*GET,REAC_2,FSUM,,ITEM,FY
*DIM,LABEL,CHAR,2
*DIM,VALUE,,2,3
LABEL(1) = 'R1, lb','R2, lb '
*VFILL,VALUE(1,1),DATA,900.0,600.0
*VFILL,VALUE(1,2),DATA,ABS(REAC_1),ABS(REAC_2)
*VFILL,VALUE(1,3),DATA,ABS(REAC_1 / 900) ,ABS( REAC_2 / 600)
/OUT,vm1,vrt
/COM
/COM,------------------- VM1 RESULTS COMPARISON ---------------------
/COM,
/COM, | TARGET | Mechanical APDL | RATIO
/COM,
*VWRITE,LABEL(1),VALUE(1,1),VALUE(1,2),VALUE(1,3)
(1X,A8,' ',F10.1,' ',F10.1,' ',1F5.3)
/COM,----------------------------------------------------------------
/OUT
FINISH
*LIST,vm1,vrt
Translates to:
.. code:: python
""" Script generated by pyansys version 0.30.1"""
import pyansys
ansys = pyansys.ANSYS(loglevel="debug")
ansys = pyansys.ANSYS()
ansys.Run("/COM,ANSYS MEDIA REL. 150 (11/8/2013) REF. VERIF. MANUAL: REL. 150")
ansys.Run("/VERIFY,VM1")
ansys.Run("/PREP7")
ansys.Run("/TITLE, VM1, STATICALLY INDETERMINATE REACTION FORCE ANALYSIS")
ansys.Run("C*** STR. OF MATL., TIMOSHENKO, PART 1, 3RD ED., PAGE 26, PROB.10")
ansys.Antype("STATIC ! STATIC ANALYSIS")
ansys.Antype("STATIC") #STATIC ANALYSIS
ansys.Et(1, "LINK180")
ansys.Sectype(1, "LINK")
ansys.Secdata("1 ! CROSS SECTIONAL AREA (ARBITRARY) = 1")
ansys.Secdata(1) #CROSS SECTIONAL AREA (ARBITRARY) = 1
ansys.Mp("EX", 1, 30E6)
ansys.N(1)
ansys.N(2, "", 4)
ansys.N(3, "", 7)
ansys.N(4, "", 10)
ansys.E(1, "2 ! DEFINE ELEMENTS")
ansys.E(1, 2) #DEFINE ELEMENTS
ansys.Egen(3, 1, 1)
ansys.D(1, "ALL", "", "", 4, 3) #BOUNDARY CONDITIONS AND LOADING
ansys.F(2, "FY", -500)
ansys.F(3, "FY", -1000)
ansys.Finish()
ansys.Run("/SOLU")
ansys.Outpr("BASIC", 1)
ansys.Outpr("NLOAD", 1)
ansys.Solve()
ansys.Finish()
ansys.Run("/POST1")
ansys.Nsel("S", "LOC", "Y", 10)
ansys.Fsum()
ansys.Run("*GET,REAC_1,FSUM,,ITEM,FY")
ansys.Nsel("S", "LOC", "Y", 0)
ansys.Fsum()
ansys.Run("*GET,REAC_2,FSUM,,ITEM,FY")
ansys.Run("*DIM,LABEL,CHAR,2")
ansys.Run("*DIM,VALUE,,2,3")
ansys.Run("LABEL(1) = 'R1, lb','R2, lb '")
ansys.Run("*VFILL,VALUE(1,1),DATA,900.0,600.0")
ansys.Run("*VFILL,VALUE(1,2),DATA,ABS(REAC_1),ABS(REAC_2)")
ansys.Run("*VFILL,VALUE(1,3),DATA,ABS(REAC_1 / 900) ,ABS( REAC_2 / 600)")
ansys.Run("/OUT,vm1,vrt")
ansys.Run("/COM")
ansys.Run("/COM,------------------- VM1 RESULTS COMPARISON ---------------------")
ansys.Run("/COM,")
ansys.Run("/COM, | TARGET | Mechanical APDL | RATIO")
ansys.Run("/COM,")
with ansys.non_interactive:
ansys.Run("*VWRITE,LABEL(1),VALUE(1,1),VALUE(1,2),VALUE(1,3)")
ansys.Run("(1X,A8,' ',F10.1,' ',F10.1,' ',1F5.3)")
ansys.Run("/COM,----------------------------------------------------------------")
ansys.Run("/OUT")
ansys.Finish()
ansys.Run("*LIST,vm1,vrt")
ansys.Exit()
Some of the commands with ``/`` are not directly translated to functions and are instead run as commands. Also, please note that the ``*VWRITE`` command requires a command immediately following it. This normally locks CORBA, so it's implemented in the background as an input file using ``ansys.non_interactive``. See the following Caveats and Notes section for more details.

Additional examples with more conversion options can be found in the APDL conversion page.


Retreiving Parameters
---------------------
APDL parameters can be retrieved using ``pyansys`` using the ``LoadParameters`` method. For example, after using the ``*GET`` command:

.. code:: python
ansys.Get('DEF_Y', 'NODE' , 2, 'U' ,'Y')
ansys.LoadParameters()
The parameters are now accessible within the ``ANSYS`` object:

.. code:: python
>>> ansys.parameters
{'AAS_MAPD': 1.0,
'DEF_X': 8.631926066372,
'DEF_Y': 4.532094298033,
'ST_EN': 24.01187254488,
'_RETURN': 0.0,
'_STATUS': 1.0}
>>> ansys.parameters['DEF_Y']
4.532094298033
Some of the commands with ``/`` are not directly translated to functions and are instead run as commands. See the following Caveats and Notes section for more details.

Caveats and Notes
-----------------

Command Naming Conventions and Rules
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When calling ANSYS commands as functions, each command has been translated from its original ANSYS all caps format to a PEP8 format. For example, ``ESEL`` is now ``Esel``. Additionally, ANSYS commands containing a ``/`` or ``*`` have had those characters removed, unless this causes a conflict with an existing name. Most notable is ``/SOLU`` which would conflict with ``SOLU``. Therefore, the ``/SOLU`` has been renamed to ``Slashsolu`` to differentiate it from ``Solu``. Out of the 1500 ANSYS commands, about 15 start with ``Slash`` and 8 with ``Star``. Check the ``ANSYS Object Methods`` reference below when necessary.

When calling ANSYS commands as functions, each command has been translated from its original ANSYS all caps format to a PEP8 format. For example, ``ESEL`` is now ``Esel``. Additionally, ANSYS commands containing a ``/`` or ``*`` have had those characters removed, unless this causes a conflict with an existing name. Most notable is ``/SOLU`` which would conflict with ``SOLU``. Therefore, the ``/SOLU`` has been renamed to ``Slashsolu`` to differentiate it from ``Solu``. Out of the 1500 ANSYS commands, about 15 start with ``Slash``, 8 with ``Star``. Check the ``ANSYS Object Methods`` reference below when necessary.

ANSYS commands that normally have an empty space, such as ``ESEL, S, TYPE, , 1`` must include an empty string when called by python:
ANSYS commands that normally have an empty space, such as ``ESEL, S, TYPE, , 1`` should include an empty string when called by Python:

.. code:: python
ansys.Esel('s', 'type', '', 1)
None of these restrictions apply to commands run with ``Run`` and this command can be used alongside the python functions:
or these commands can be called using parameters:

.. code:: python
ansys.Esel('s', 'type', vmin=1)
None of these restrictions apply to commands run with ``Run``:

.. code:: python
ansys.Run('/SOLU')
ansys.Solve()
Some commands can only be run non-interactively in a script. ``pyansys`` gets around this restriction by writing the commands to a temporary input file and then reading the input file. To run a group of commands that must be run non-interactively, set the ``ANSYS`` object to run a series of commands as an input file by using ``non_interactive`` as in this example:

.. code:: python
with ansys.non_interactive:
ansys.Run("*VWRITE,LABEL(1),VALUE(1,1),VALUE(1,2),VALUE(1,3)")
ansys.Run("(1X,A8,' ',F10.1,' ',F10.1,' ',1F5.3)")
Also note that macros created within pyansys (rather than loaded from a file) do not appear to run correctly. For example, the macro ``DISP`` created using the ``*CREATE`` command within APDL:

.. code::
*CREATE,DISP
NSEL,R,LOC,Z,10 ! SELECT NODES AT Z = 10 TO APPLY DISPLACEMENT
D,ALL,UZ,ARG1
NSEL,ALL
/OUT,SCRATCH
SOLVE
*END
! Call the function
*USE,DISP,-.032
*USE,DISP,-.05
*USE,DISP,-.1
Should be written as:

.. code:: python
def DISP(ARG1='', ARG2='', ARG3='', ARG4='', ARG5='', ARG6='',
ARG7='', ARG8='', ARG9='', ARG10='', ARG11='', ARG12='',
ARG13='', ARG14='', ARG15='', ARG16='', ARG17='', ARG18=''):
ansys.Nsel("R", "LOC", "Z", 10) #SELECT NODES AT Z = 10 TO APPLY DISPLACEMENT
ansys.D("ALL", "UZ", ARG1)
ansys.Nsel("ALL")
ansys.Run("/OUT,SCRATCH")
ansys.Solve()
DISP(-.032)
DISP(-.05)
DISP(-.1)
If you have an existing input file with a macro, it can be converted using the ``ConvertFile`` function:

.. code:: python
pyansys.ConvertFile(apdl_inputfile, pyscript, macros_as_functions=True)
See the ``vm7.dat`` example in the APDL Conversion Examples page.

..
If you're using a blocked macro, it's possible to write a macro using ``with ansys.non_interactive:``. See the ``vm8.dat`` example in the APDL Conversion Examples page.

Conditional Statements and Loops
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
APDL conditional statements such as ``*IF`` must be either implemented pythonically or using ``with ansys.non_interactive:``. See the ``vm8.dat`` example in the APDL Conversion Examples page. For example:

.. code::
*IF,ARG1,EQ,0,THEN
*GET,ARG4,NX,ARG2 ! RETRIEVE COORDINATE LOCATIONS OF BOTH NODES
*GET,ARG5,NY,ARG2
*GET,ARG6,NZ,ARG2
*GET,ARG7,NX,ARG3
*GET,ARG8,NY,ARG3
*GET,ARG9,NZ,ARG3
*ELSE
*GET,ARG4,KX,ARG2 ! RETRIEVE COORDINATE LOCATIONS OF BOTH KEYPOINTS
*GET,ARG5,KY,ARG2
*GET,ARG6,KZ,ARG2
*GET,ARG7,KX,ARG3
*GET,ARG8,KY,ARG3
*GET,ARG9,KZ,ARG3
*ENDIF
Should be implemented as:

.. code:: python
with ansys.non_interactive:
ansys.Run("*IF,ARG1,EQ,0,THEN")
ansys.Run("*GET,ARG4,NX,ARG2 ") # RETRIEVE COORDINATE LOCATIONS OF BOTH NODES
ansys.Run("*GET,ARG5,NY,ARG2")
ansys.Run("*GET,ARG6,NZ,ARG2")
ansys.Run("*GET,ARG7,NX,ARG3")
ansys.Run("*GET,ARG8,NY,ARG3")
ansys.Run("*GET,ARG9,NZ,ARG3")
ansys.Run("*ELSE")
ansys.Run("*GET,ARG4,KX,ARG2 ") # RETRIEVE COORDINATE LOCATIONS OF BOTH KEYPOINTS
ansys.Run("*GET,ARG5,KY,ARG2")
ansys.Run("*GET,ARG6,KZ,ARG2")
ansys.Run("*GET,ARG7,KX,ARG3")
ansys.Run("*GET,ARG8,KY,ARG3")
ansys.Run("*GET,ARG9,KZ,ARG3")
ansys.Run("*ENDIF")
Or pythonically as:

.. code:: python
# ANSYS parameters can be obtained using LoadParameters
if ARG1 == 0:
ansys.Run("*GET,ARG4,NX,ARG2 ") # RETRIEVE COORDINATE LOCATIONS OF BOTH NODES
ansys.Run("*GET,ARG5,NY,ARG2")
ansys.Run("*GET,ARG6,NZ,ARG2")
ansys.Run("*GET,ARG7,NX,ARG3")
ansys.Run("*GET,ARG8,NY,ARG3")
ansys.Run("*GET,ARG9,NZ,ARG3")
else:
ansys.Run("*GET,ARG4,KX,ARG2 ") # RETRIEVE COORDINATE LOCATIONS OF BOTH KEYPOINTS
ansys.Run("*GET,ARG5,KY,ARG2")
ansys.Run("*GET,ARG6,KZ,ARG2")
ansys.Run("*GET,ARG7,KX,ARG3")
ansys.Run("*GET,ARG8,KY,ARG3")
ansys.Run("*GET,ARG9,KZ,ARG3")
APDL loops using ``*DO`` or ``*DOWHILE`` should also be implemetned using ``ansys.non_interactive`` or pythonically.


Warnings and Errors
~~~~~~~~~~~~~~~~~~~
Expand Down Expand Up @@ -262,10 +488,36 @@ You can change this behavior so ignored commands can be logged as warnings not r
ansys.allow_ignore = True
ansys.K() # error ignored
Prompts
~~~~~~~
Prompts from ANSYS automatically continued as if ANSYS is in batch mode.
Prompts from ANSYS automatically continued as if ANSYS is in batch mode. Commands requiring user input, such as ``*VWRITE`` will fail and must be entered in non-interactively.


APDL Command Logging
--------------------
While ``pyansys`` is designed to make it easier to control an APDL session by calling it using Python, it may be necessary to call ANSYS again using an input file generated from a pyansys script. This is automatically enabled with the ``log_apdl=True`` parameter. Enabling this parameter will cause ``pyansys`` to write each command run from an ``ansys`` object into a log file named ``"log.inp"`` in the ANSYS working directory of the active ``ansys`` object. For example

.. code:: python
import pyansys
ansys = pyansys.ANSYS(log_apdl=True)
ansys.Prep7()
ansys.K(1, 0, 0, 0)
ansys.K(2, 1, 0, 0)
ansys.K(3, 1, 1, 0)
ansys.K(4, 0, 1, 0)
Will write the following to ``"log.inp"``:

! APDL script generated using pyansys 0.30.1
/PREP7,
K,1,0,0,0
K,2,1,0,0
K,3,1,1,0
K,4,0,1,0

This allows for the translation of a Python script to an APDL script except for conditional statements, loops, or functions.


Plotting Non-Interactively
Expand Down Expand Up @@ -448,4 +700,3 @@ ANSYS Object Methods
--------------------
.. autoclass:: pyansys.ANSYS
:members:

40 changes: 40 additions & 0 deletions doc/ansys_functions.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
ANSYS Functions
===============
These functions can be called directly from an ``ANSYS`` object. This is to simplifiy calling ANSYS, especially when inputs are variables within Python. For example, the following two commands are equivalent:

.. code:: python
ansys.K(1, 0, 0, 0)
ansys.Run('K, 1, 0, 0, 0')
This approach has some obvious advantages, chiefly that it's a bit easier to script as ``pyansys`` takes care of the string formatting for you. For example, inputting points from a numpy array:

.. code:: python
# make 10 random keypoints in ANSYS
points = np.random.random((10, 3))
for i, (x, y, z) in enumerate(points):
ansys.K(i + 1, x, y, z)
Additionally, exceptions are caught and handled within Python.

.. code:: python
>>> ansys.Run('AL, 1, 2, 3')
Exception:
AL, 1, 2, 3
DEFINE AREA BY LIST OF LINES
LINE LIST = 1 2 3
(TRAVERSED IN SAME DIRECTION AS LINE 1)
*** ERROR *** CP = 0.338 TIME= 09:45:36
Keypoint 1 is referenced by only one line. Improperly connected line
set for AL command.
Available Commands
==================
.. autoclass:: pyansys.ansys_functions._InternalANSYS
:members:
Loading

0 comments on commit 23e2627

Please sign in to comment.