OpenMDAO V3.14 is chocked full of speedy goodness. You can check out the full release notes for all the details, but I wanted to highlight two key developments that each give speed in their own special way
Faster Structured Interpolation
The in-house OpenMDAO Applications team had found that some of their Dymos applications were spending excessive amounts of time computing interpolations from data tables from the StructuredMetaModel component. We’ve known for a while that our interpolation code wasn’t super fast. In fact we specifically chose an implementation that we knew to be slower, because it offered N-dimensional capability.
However the bottlenecks in our own work got bad enough that we felt it was time to add some less flexible, but a lot faster option. The new interpolants only work for a fixed dimensionality (i.e. 1D or 3D), but they are about 100x faster. We have a new naming scheme, laid out in POEM 058. Any interpolation method that starts with its dimension (e.g. 3Dlagrange3
) is one of the new fast ones. We started off with 1D and 3D interpolants because these were the ones we needed. We plan to add some 2D ones in the future though.
If you are using StrucuturedMetaModel, these new methods are worth a try for sure. If you are using cubic
or scipy-cubic
then I highly recommend that you give lagrange3
a try, or the 3D-lagrange3
if you are using 3D data. You’ll get a significant speed up either way.
Functional Component API
We’ve introduced a new component API, that can possibly help you code a bit faster. This feature is so big, it spans two whole POEMs: 056 and 057. If you’re going to use the new API, you should definitely read both poems.
Just to be clear, this new API is not going to replace the existing class based one but will live along side it. The new API, as the name suggests lets you build components using standard python functions. It works with both explicit functions and implicit ones
import openmdao.api as om
import openmdao.func_api as omf
def func(a=2.0, b=3.0):
x = 2. * a
y = b - 1.0 / 3.0
return x, y
f = (omf.wrap(func)
.defaults(method='cs')
.declare_partials(of='x', wrt='a')
.declare_partials(of='y', wrt='b'))
p = om.Problem()
p.model.add_subsystem('comp', om.ExplicitFuncComp(f))
p.setup()
p.run_model()
J = p.compute_totals(of=['comp.x', 'comp.y'], wrt=['comp.a', 'comp.b'])
If you don’t like the boiler plate of the class APIs, you may find this API to be a lot cleaner. If you happen to have a library of existing python functions, you’ll probably find this API to be a nice way to integrate that into OpenMDAO without having to write any class wrappers yourself.
The most fundamental motivation for this new API is that it more easily supports algorithmic differentiation (AD). AD relies on functional APIs, and OpenMDAO’s classed based API was always a tough fit. So if you’ve wanted to try out JAX or pyTorch then this new API is for you!
Adding analytic derivatives offers huge computational benefits, but is often a very slow development step. We’ve also found that when taking derivatives by hand, we tend toward smaller components to keep the derivations simpler.
Our goal with the functional API is to help alleviate the development bottleneck of derivatives, and offer a path for having larger chunks of engineering code in single components.