Recorders Not Recording?

Python is one of the best things to happen with OpenSees. Unfortunately, the break from Tcl has not been squeaky clean.

A very sticky transition point has been element recorders. When we wrote the internal setResponse functions to identify which element, section, material, or fiber response to record, we put C-style int argc, char **argv arguments in the method signature. So, setResponse sees everything as a string. This is not entirely Tcl’s fault, but the “everything is a string” mantra definitely affected the implementation decision.

To demonstrate, let’s suppose you wanted to record the stress response history of the fiber closest to coordinates (10,5) on section 3 of element 1. In Tcl, you’d write something like this:

set y 10.0
set z 5.0
recorder Element -ele 1 section 3 fiber $y $z stress

For brevity, I omitted the -file and -time options.

After variable substitution in Tcl, element 1 sees an array of strings in setResponse:

argv[0] = "section"
argv[1] = "3"
argv[2] = "fiber"
argv[3] = "10.0"
argv[4] = "5.0"
argv[5] = "stress"

Then, the element uses atoi(argv[1]) to get the section number and passes the remaining information on to setResponse of the requested section. The section calls atof on the coordinates then searches for the fiber closest to those coordinates to figure out which material object to call next.

With Python, you’d be inclined to write the recorder command like this:

y = 10.0
z = 5.0
ops.recorder('Element', '-ele', 1, 'section', 3, 'fiber', y, z, 'stress')

After variable substitution in Python, element 1 will receive the following argv assignments in setResponse:

argv[0] = "section"
argv[1] = 3
argv[2] = "fiber"
argv[3] = 10.0
argv[4] = 5.0
argv[5] = "stress"

Looks reasonable. But look closely and you’ll see we’re dumping integers and floats (with no quotes) into character strings. In fact, if you print to screen (using opserr <<) the argv values that are passed to the element setResponse, you’ll see Invalid String Input! for argv[1], argv[3], and argv[4].

To make matters worse, neither atoi nor atof throws an exception, i.e., there is no error when the element calls atoi(argv[1]). As a result, your recorder command will appear to work, but then not record anything–you’ll get an empty output file.

Fixing this issue will not be easy. Hard coding on the front end what should or should not be a string is not a good idea. Neither is trying to code a workaround in all the setResponse methods.

What you can do in the meantime is cast the arguments using Python’s str function, forcing the OpenSees interpreter to generate strings for everything it passes to setResponse:

y = 10.0
z = 5.0
ops.recorder('Element', '-ele', 1, 'section', str(3), 'fiber', str(y), str(z), 'stress')

You need to string cast only the arguments that drill down beyond the element setResponse, not the element tags (notice str(1) is not used for the element tag after '-ele' above). Basically, any numeric argument that comes after 'section', 'material', or 'fiber' in an element recorder needs to be cast as a string. Node recorders are not affected.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.