Not Everything Should Be a Direct Translation

Like learning another language, not everything in OpenSees, and programming in general, is a direct translation from textbooks.

Your mother tongue could be {\bf x} = {\bf A}^{-1}{\bf b}, but you should never invert the matrix then multiply. Instead, call an equation solver. For small matrices in OpenSees, use A.Solve(b, x) from the Matrix class. In your Python scripts you can use np.linalg.solve while In Tcl it’s ::math::linearalgebra::solveGauss.

Another example of lengua materna is how you handle constants expressed in scientific notation. When you see 2.1 \times 10^{-8}, you may be inclined to type one of the following:

  • C++: 2.1*pow(10,-8)
  • Python: 2.1*10**-8
  • Tcl: 2.1*10.0**-8 or 2.1*pow(10,-8) — Note: 2.1*10**-8 will be zero due to integer division in Tcl.

I’ve seen constants defined with the above statements many times in OpenSees scripts and in the OpenSees source code.

But NO! There’s no need to use the pow function or ** to calculate a power of 10.

Just type 2.1e-8

This is a format all languages will accept for scientific notation.

You might say “What’s the big deal? There’s no difference in performance.” And you would be correct for a single call with the pow function taking only microseconds longer to evaluate than the literal 2.1e-8. But when those pow calls are in a material model or in a script that gets invoked a million times, those microseconds become seconds.

While interpreted languages like Python and Tcl can’t do much optimization on your scripts, a good C++ compiler will pick up your slack–but that’s never a reliable approach. Here is a good analysis of the pow function in C++.

Another issue with multiplication and powers of 10 is you could introduce small, unnecessary round off errors. For example, in both Python and Tcl, 2.1*10**-8 overflows slightly while 2.01*10**-8 underflows. These round off errors will pose a problem for logical comparisons later in your script.

When your script performs many algebraic operations, you will accumulate small round off errors no matter what. So, limit potential round off to necessary computations like 57000*fc**0.5 and just type 2.1e-8 for the literals.

Finally, never do the MATLAB-style exponent ^ in any language other than MATLAB.

Expressions like 10^-8 are perfectly legal in C++, Python, and Tcl–the compiler or interpreter will not complain. However, the ^ operator is bit-wise eXclusive OR (XOR) on the two integers expressed in binary format. Write 10 and -8 out in binary, then XOR the bits. The compiler or interpreter is kind enough to convert the binary result back to an integer and the results will be not at all what you expect.

I have no doubt the topics covered in this post have been and will be the source for many suspicious OpenSees analysis results. And, in some cases, those results have been and will be published. ¡Qué aterrador!

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 )

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.