天天看點

python tcl 外部,在python中為Tcl調用不同的解釋器

python tcl 外部,在python中為Tcl調用不同的解釋器

I wish to run a Tcl script with a different interpreter (OpenSees) from python itself, similar to this question, what would be the most practical way? I've tried tkinter and subprocess routines but as far as I understand i'm running the script in pure Tcl and nothing happens (functions are defined in the OpenSees environment).

I've tried calling my Tcl script via tkinter and but I can't for the life of me figure out how to run tcl with another interpreter, what i've tried is:

for-test.tcl

proc fractional_while {j float_increment upper_limit} {

while {$j < $upper_limit} {

set j [expr $j + $float_increment]

}

}

puts "time it took: [time {fractional_while 1 0.001 500} 1]"

python file

import tkinter

r = tkinter.Tk()

r.eval('source {for-test.tcl}')

What I want to do is call Opensees inside python and run the following routine:

elastic-1dof-spectrum.tcl

model BasicBuilder -ndm 2 -ndf 3

set time_zero [clock clicks -millisec]

set node_restraint 1

set node_spring 2

...

set load_dir $x_direction

set x_mass 1

set elastic_modulus 2e6

set rotation_z 6

node $node_restraint 0 0 -mass 0 0 0

node $node_spring 0 0 -mass 0 0 0

fix $node_restraint 1 1 1

equalDOF $master_node $slave_node 1 2

geomTransf Linear $transf_tag

uniaxialMaterial Elastic $linear_elastic_mat_tag $elastic_modulus

element zeroLength 0 $node_restraint $node_spring -mat $linear_elastic_mat_tag -dir $rotation_z

set accel_series "Path -filePath acelerograma_85_ii.191 -dt $ground_motion_time_step -factor 1"

pattern UniformExcitation $load_tag $load_dir -accel $accel_series

set oscillator_length 1

set node_mass 3

set counter 1

while {$oscillator_length < 1000} {

set oscillator_length [expr $counter*0.1]

set node_mass [expr $counter + 2]

node $node_mass 0 $oscillator_length

mass $node_mass $x_mass 0 0

element elasticBeamColumn $node_mass $node_spring $node_mass $area_column $elastic_modulus $inertia_column $transf_tag

set eigenvalue [eigen -fullGenLapack 1]

set period [expr 2*$pi/sqrt($eigenvalue)]

recorder EnvelopeNode -file results/acceleration-envelope-period-$period.out -time -node $node_mass -dof $x_direction accel

...

rayleigh [expr 2*$damping_ratio*$x_mass*$eigenvalue] 0 0 0

constraints Transformation

# determines how dof constraits are treated and assigned

numberer Plain

# numbering schemes are tied directly to the efficiency of numerical solvers

system BandGeneral

# defines the matricial numerical solving method based on the form of the stiffness matrix

test NormDispIncr 1e-5 10 0

integrator Newmark $gamma $beta

# defines the integrator for the differential movement equation

algorithm Newton

# solve nonlinear residual equation

analysis Transient

# for uniform timesteps in excitations

analyze [expr int($duration_motion/$time_step)] $time_step

incr counter

}

puts stderr "[expr {([clock clicks -millisec]-$time_zero)/1000.}] sec" ;# RS

wipe

解決方案

It depends on how OpenSees is built and what options it offers.

Typically programs that embed Tcl have two main options how to do it, quite similar to Python.

Variant one is to have a normal C/C++ main program and link to the Tcl library, in effect the same thing tclsh does, a shell that can execute Tcl commands and providing extra commands statically.

Variant two is using a normal tclsh and just loading some extension modules to add the functionality. If that is the case, you can often simply load the package in the tkinter shell if they are similar enough, and are done.

OpenSees seems to be a program that implements variant one, a bigwish that includes some extra commands not available outside. So you cannot load the code directly in a tkinter shell.

You have three options:

Use something like the Tcllib comm package to communicate between Tkinter and the OpenSees shell (see Running TCL code (on an existing TCL shell) from Python for an example)

Run opensees via subprocess and implement some kind of communication protocol to send your commands.

Hack at the OpenSees code to build it as a loadable package for Tcl and load it into your tkinter process (might be hard).