STAAD.Pro Help

OS. Write an OpenSTAAD Program in Python

This example will introduce you to several concepts necessary to writing OpenSTAAD applications in Python.

Tip: If you followed the previous "Hello World!" example, you may simply delete that line and start from that point.

OS. Initiate OpenSTAAD in Python

Note: You must have a model open in STAAD.Pro for this example. Otherwise your code will return an error.
  1. Type the following statements and press <Return> at the end of each statement:
    from comtypes import automation
    from comtypes import client
    import ctypes

    This uses the comtypes library to allow you to use COM objects (such as OpenSTAAD).

  2. Type os = client.GetActiveObject("StaadPro.OpenSTAAD") and then press <Return>.

    This initiates OpenSTAAD and connects to the current STAAD.Pro model to your program.

Your program at this point should look like:
from comtypes import automation
from comtypes import client
import ctypes
os = client.GetActiveObject("StaadPro.OpenSTAAD")

OS. Use Geometry Methods

  1. Type geometry = os.Geometry and then press <Return>.

    This defines the geometry variable as the Geometry group of methods in OpenSTAAD.

  2. Type geometry._FlagAsMethod("GetNodeCount") and then press <Return>. This is required to correctly identify the OpenSTAAD methods as such in Python.
    Note: This approach is required for this first time you use a method in a python program using OpenSTAAD method. It is not required for each time that method is re-used within the same code.
  3. Type geometry._FlagAsMethod("GetMemberCount") and then press <Return>. This is required to correctly identify the OpenSTAAD methods as such in Python.
    Note: This approach is required for this first time you use a method in a python program using OpenSTAAD method. It is not required for each time that method is re-used within the same code.
Your program at this point should look like:
from comtypes import automation
from comtypes import client
import ctypes
os = client.GetActiveObject("StaadPro.OpenSTAAD")
geometry = os.Geometry
geometry._FlagAsMethod("GetNodeCount")
geometry._FlagAsMethod("GetMemberCount")

OS. Using functions that only return a single value

  1. Type nodeCount = geometry.GetNodeCount and then press <Return>.

    This uses the OpenSTAAD method GetNodeCount() to return the number of nodes in the active STAAD.Pro model into the specified variable.

  2. Type beamCount = geometry.GetMemberCount and then press <Return>.

    Similarly, this uses the OpenSTAAD method GetMemberCount() to return the number of members in the active STAAD.Pro model into the specified variable.

    Tip: Reference the OpenSTAAD documentation for details on available methods and what values are accepted as input or returned from each.
Your program at this point should look like:
from comtypes import automation
from comtypes import client
import ctypes
os = client.GetActiveObject("StaadPro.OpenSTAAD")
geometry = os.Geometry
geometry._FlagAsMethod("GetNodeCount")
geometry._FlagAsMethod("GetMemberCount")
nodeCount = geometry.GetNodeCount
beamCount = geometry.GetMemberCount

OS. Using functions that only return a list of values

Here, you will store a list of values into an array.

  1. Define several variant arrays for use with different data types making use of the automation class imported from the comptypes library:
    1. Type def make_safe_array_double(size): return automation._midlSAFEARRAY(ctypes.c_double).create([0]*size) and then press <Return>.

      This defines an array type consisting of double-precision floating point decimal values.

    2. Type def make_safe_array_int(size): return automation._midlSAFEARRAY(ctypes.c_int).create([0]*size) and then press <Return>.

      This defines an array type consisting of integers.

    3. Type def make_safe_array_long(size): return automation._midlSAFEARRAY(ctypes.c_long).create([0]*size) and then press <Return>.

      This defines an array type consisting of long integer values.

  2. Type the following statements and press <Return> at the end of each statement:
    def make_variant_vt_ref(obj, var_type):
        var = automation.VARIANT()
        var._.c_void_p = ctypes.addressof(obj)
        var.vt = var_type | automation.VT_BYREF
        return var
    With this definitions in place, you can now call methods which return lists of long type values, such as GetBeamList().
  3. Type geometry._FlagAsMethod("GetBeamList") and the press <Return>.
  4. Now, use this identified method to populate a new array with the list of beams in the model:
    1. Type safe_array_beam_list = automation._midlSAFEARRAY(ctypes.c_long).create([0]*beamCount) and then press <Return>.

      This uses the previous beamCount result to establish the necessary size of the array.

    2. Type beams = make_variant_vt_ref(safe_array_beam_list, automation.VT_ARRAY | automation.VT_I4) and then press <Return>.

      This creates an array named beams which has the correct size to store the values.

    3. Type geometry.GetBeamList(beams) and then press <Return>.

      This is used to store the returning values into the newly created array beams.

  5. Similar to how you have done in previous steps, next you will add a group of methods in OpenSTAAD which are used to retrieve analysis results and identify the method to use.
    1. Type output = os.Output and then press <Return>.

      This defines the output variable as the Output group of methods in OpenSTAAD, which is used to retrieve analysis results.

    2. Type output._FlagAsMethod("GetSupportReactions") and the press <Return>.
  6. Type the following statements and press <Return> at the end of each statement:
    nodeNo = 1
    loadcaseNo = 1
    You'll "hard code" these values for the purposes of this tutorial.
    Note: Here it is assumed node number 1 and load case number 1 are present in the active STAAD.Pro model and the analysis results are also available.
  7. Now, use this identified method to populate a new array with the support reactions for the specified node and load case:
    1. Type safe_array_reactions = make_safe_array_double(6) and then press <Return>. This uses the double array type defined earlier to make an array of a fixed size (six, as this is the number of reactions possible at any support).
    2. Type reactions = make_variant_vt_ref(safe_array_reactions, automation.VT_ARRAY | automation.VT_R8) and then press <Return>. This creates an array named reactions which has the correct size to store the values.
    3. Type output.GetSupportReactions(nodeNo, loadcaseNo, reactions) and then press <Return>.

      This method uses the first two parameters as input and then stores the returning values for into the newly created array reactions.

Your program at this point should look like:
from comtypes import automation
from comtypes import client
import ctypes
os = client.GetActiveObject("StaadPro.OpenSTAAD")
geometry = os.Geometry
geometry._FlagAsMethod("GetNodeCount")
geometry._FlagAsMethod("GetMemberCount")
nodeCount = geometry.GetNodeCount()
beamCount = geometry.GetMemberCount()
def make_safe_array_double(size): 
    return automation._midlSAFEARRAY(ctypes.c_double).create([0]*size)
def make_safe_array_int(size): 
    return automation._midlSAFEARRAY(ctypes.c_int).create([0]*size)
def make_safe_array_long(size): 
    return automation._midlSAFEARRAY(ctypes.c_long).create([0]*size)
def make_variant_vt_ref(obj, var_type):
    var = automation.VARIANT()
    var._.c_void_p = ctypes.addressof(obj)
    var.vt = var_type | automation.VT_BYREF
    return var
geometry._FlagAsMethod("GetBeamList")
safe_array_beam_list = automation._midlSAFEARRAY(ctypes.c_long).create([0]*beamCount)
beams = make_variant_vt_ref(safe_array_beam_list, automation.VT_ARRAY | automation.VT_I4)
geometry.GetBeamList(beams)
output = os.Output
output._FlagAsMethod("GetSupportReactions")
nodeNo = 1
loadcaseNo = 1
safe_array_reactions = make_safe_array_double(6)
reactions = make_variant_vt_ref(safe_array_reactions, automation.VT_ARRAY | automation.VT_R8)
output.GetSupportReactions(nodeNo, loadcaseNo, reactions)

OS. Generate OpenSTAAD Output

  1. Type print( str(nodeCount) + ' joints') and then press <Return>.

    Working from the inner-most operation outward, this line is first converting the numerical result stored in nodeCount to a string. This is then combined with the text string ' joints' to make the output easier to interpret. Then the entire concatenated string is being printed to the terminal.

  2. Type print(str(beamCount) + ' members').

    Similarly, this is concatenating the beamCount value, converted to a string, with some text and displaying that result to the terminal.

  3. To print the beam numbers in the model, type the following statements and press <Return> at the end of each statement:
    print("Beam Numbers")
    for beam in beams:
        print(beam)

    This uses a "for" loop to print each beam number within the array named beams.

  4. To print the support reaction values at node 1 for load case 1, type the following statements and press <Return> at the end of each statement:
    print("Support Reactions")
    for reaction in reactions:
        print(reaction)
Your final program should look like:
from comtypes import automation
from comtypes import client
import ctypes
os = client.GetActiveObject("StaadPro.OpenSTAAD")
geometry = os.Geometry
geometry._FlagAsMethod("GetNodeCount")
geometry._FlagAsMethod("GetMemberCount")
nodeCount = geometry.GetNodeCount()
beamCount = geometry.GetMemberCount()
def make_safe_array_double(size): 
    return automation._midlSAFEARRAY(ctypes.c_double).create([0]*size)
def make_safe_array_int(size): 
    return automation._midlSAFEARRAY(ctypes.c_int).create([0]*size)
def make_safe_array_long(size): 
    return automation._midlSAFEARRAY(ctypes.c_long).create([0]*size)
def make_variant_vt_ref(obj, var_type):
    var = automation.VARIANT()
    var._.c_void_p = ctypes.addressof(obj)
    var.vt = var_type | automation.VT_BYREF
    return var
geometry._FlagAsMethod("GetBeamList")
safe_array_beam_list = automation._midlSAFEARRAY(ctypes.c_long).create([0]*beamCount)
beams = make_variant_vt_ref(safe_array_beam_list, automation.VT_ARRAY | automation.VT_I4)
geometry.GetBeamList(beams)
output = os.Output
output._FlagAsMethod("GetSupportReactions")
nodeNo = 1
loadcaseNo = 1
safe_array_reactions = make_safe_array_double(6)
reactions = make_variant_vt_ref(safe_array_reactions, automation.VT_ARRAY | automation.VT_R8)
output.GetSupportReactions(nodeNo, loadcaseNo, reactions)
print(str(nodeCount) + ' joints')
print(str(beamCount) + ' members')
print("Beam Numbers")
for beam in beams:
    print(beam)
print("Support Reactions")
for reaction in reactions:
    print(reaction)

OS. Run Your Code

You should now have a working piece of python code which will provide you information about the currently active STAAD.Pro model. You’ll now run the code to test it.

  1. Save your progress by either:

    selecting File > Save

    or

    pressing <Ctrl+S>

  2. Select the Run tool to execute your code. The terminal will open and display the results.
    Tip: You may notice the Powershell instruction used to perform this action. This command can be used from any Powershell window outside of Visual Studio Code to run your program.

It is best practice to annotate your code with comments. This allows others to easily understand what your code is doing (or at least what your intention was). The full example here contains comments accordingly.

Microsoft Visual Studio Code running a Python example

OS. What if it Didn't Work?

If you did not already do so, be sure to install a linter. This provides useful feedback on your python program along with helpful hints to optimize the code.

The IDE should also provide you feedback on any detected issues with the code. Much like a spell check or grammar check in a word processor, this can alert you to errors before you ever run the code.

Verify that the full environment is set up, including the python interpreter (Python v3.8.n), the pywin32 extension, and that you have a model open in STAAD.Pro. While not all STAAD.Pro programs do require an active model in STAAD.Pro, this particular program does.

You can use the debugging tools in Visual Studio Code to help "step" through the code interpretation to identify issues. Clicking to the left of the line number in the main code window will add a break point. Then select the Run tab (or press <Ctrl+Shift+D>). Click the Run and Debug button to start the process. The terminal will provide additional information as it runs the program and will pause at each break point.

Refer to the Visual Studio Code help for detailed information on using the debugging features in this editor.