OpenSees Cloud

OpenSees AMI

Tcl as a Front End for Python

Original Post - 20 Jun 2021 - Michael H. Scott

Visit Structural Analysis Is Simple on Substack.


I know I’m not the only one who enjoys converting between scripting languages or between structural analysis programs. I’ve had fun writing bespoke Tcl middleware between OpenSees and MATLAB, but now OpenSeesPy makes all of that obsolete.

But, let’s say you have an OpenSees Tcl script that you’d like to run in OpenSeesPy. There’s a line-by-line converter available on GitHub, but it does not handle variables, conditionals, loops, or procedures. This line-by-line approach is great for converting the Tcl files exported by OpenSees Navigator or other front ends that pump out Tcl files to run OpenSees.

But what do you do when there’s Tcl variables, conditionals, loops, and procedures? Consider this snippet of OpenSees Tcl code I received a couple weeks ago and wanted to convert to OpenSees Python.

for {set i 1} {$i <= $nyweb} {incr i 1} {
    for {set j 1} {$j <= $nxweb} {incr j 1} {
        set e [expr $e+1]
        set n1 [expr ($nxweb+1)*(($i-1)+1)-($nxweb-($j-1))]
        set n2 [expr ($nxweb+1)*(($i-1)+1)-($nxweb-$j)]
        set n3 [expr ($nxweb+1)*($i+1)-($nxweb-$j)]
        element ShellNLDKGT $e $n1 $n2 $n3 $websection
    }
}

Converting the loops from Tcl to Python would be relatively easy–use range(1,nyweb+1). However, converting the expressions in the loop body would be ripe for error.

But, all I wanted was to analyze the model with OpenSeesPy, not keep the variables, loops, etc. from the Tcl script. So, I took an approach from my bespoke middleware days–use a Tcl filestream.

set python [open model.py w]
 
puts $python "import openseespy.opensees as ops"
puts $python "ops.wipe()"
puts $python "ops.model('basic','-ndm',3,'-ndf',6)"
 
#
# Do some stuff
#
 
for {set i 1} {$i <= $nyweb} {incr i 1} {
    for {set j 1} {$j <= $nxweb} {incr j 1} {
        set e [expr $e+1]
        set n1 [expr ($nxweb+1)*(($i-1)+1)-($nxweb-($j-1))]
        set n2 [expr ($nxweb+1)*(($i-1)+1)-($nxweb-$j)]
        set n3 [expr ($nxweb+1)*($i+1)-($nxweb-$j)]
        element ShellNLDKGT $e $n1 $n2 $n3 $websection
        # Write to .py file
        puts $python "ops.element('ShellNLDKGT',$e,$n1,$n2,$n3,$secTag)"
    }
}
 
#
# Do some more stuff
#
 
close $python

The output in model.py is line-by-line element definitions.

ops.element('ShellNLDKGT',207,161,162,164,2)
ops.element('ShellNLDKGT',208,162,165,164,2)
ops.element('ShellNLDKGT',209,163,164,166,2)
ops.element('ShellNLDKGT',210,164,167,166,2)
ops.element('ShellNLDKGT',211,164,165,167,2)
ops.element('ShellNLDKGT',212,165,168,167,2)

With this approach, any changes you make to the Tcl script will appear in the output Python script, i.e., the Tcl script is a front end for the OpenSeesPy analysis.