Upgrading from OpenMDAO 2.10 to OpenMDAO 3#

In the OpenMDAO 3.0 release, a few changes were made to the API. In addition, we removed all deprecation warnings and fully deprecated the old behavior for all API changes that were made over the lifespan of OpenMDAO 2.x. The changes are all summarized here.

Note

A significant number of the single line examples are a change in class camelcase or removing an underscore

Building Component Models#

Declare a Component with distributed variables#

class DistribComp(ExplicitComponent):

    def __init__(self, size):
        super().__init__()
        self.distributed = True

import openmdao.api as om


class DistribComp(om.ExplicitComponent):
    """Simple Distributed Component."""

    def initialize(self):
        self.options['distributed'] = True

Below each tabbed example in this notebook is the runnable code from above. However, since some things have been fully deprecated, the code from OpenMDAO 2.x is no longer operational. If that is the case, we have commented out those code cell examples.

Declare a variable that is explicitly unitless#

prob.model.add_subsystem('tgt', om.ExecComp('y = 3 * x', x={'units': 'unitless'}))
prob.model.add_subsystem('tgt', om.ExecComp('y = 3 * x', x={'units': None}))

Add a subsystem to a Group#

indeps = prob.model.add('indeps', om.IndepVarComp())
prob.model.add_subsystem('parab', Paraboloid(), promotes_inputs=['x', 'y'])

Add a linear or nonlinear solver to a Group#

self.nl_solver = om.NewtonSolver()
self.ln_solver = om.DirectSolver()
self.nonlinear_solver = om.NewtonSolver()
self.linear_solver = om.DirectSolver()

Declare an option with an explicit type#

def initialize(self):
    """
    Declare options.
    """
    self.options.declare('vec_size', type_=int, default=1,
                         desc='The number of points at which the vector magnitude is computed')
def initialize(self):
    """
    Declare options.
    """
    self.options.declare('vec_size', types=int, default=1,
                         desc='The number of points at which the vector magnitude is computed')

Component Library#

Create an interpolating component using Akima spline with uniform grid#

import openmdao.api as om

ycp = np.array([5.0, 12.0, 14.0, 16.0, 21.0, 29.0])
ncp = len(ycp)
n = 11

prob = om.Problem()

comp = om.AkimaSplineComp(num_control_points=ncp, num_points=n,
                          name='chord')

prob.model.add_subsystem('comp1', comp)

prob.setup()
prob['akima.chord:y_cp'] = ycp.reshape((1, ncp))
prob.run_model()
ycp = np.array([5.0, 12.0, 14.0, 16.0, 21.0, 29.0])
ncp = len(ycp)
n = 11

prob = om.Problem()

akima_option = {'delta_x': 0.1}
comp = om.SplineComp(method='akima', num_cp=ncp, x_interp_val=np.linspace(0.0, 1.0, n),
                     interp_options=akima_option)

prob.model.add_subsystem('comp1', comp)

comp.add_spline(y_cp_name='chord_cp', y_interp_name='chord', y_cp_val=ycp)

prob.setup()
prob.run_model()

Create an interpolating component using Akima spline with custom grid#

xcp = np.array([1.0, 2.0, 4.0, 6.0, 10.0, 12.0])
ycp = np.array([5.0, 12.0, 14.0, 16.0, 21.0, 29.0])
ncp = len(xcp)
n = 50
x = np.linspace(1.0, 12.0, n)

prob = om.Problem()

comp = om.AkimaSplineComp(num_control_points=ncp, num_points=n,
                          name='chord', input_x=True,
                          input_xcp=True)

prob.model.add_subsystem('akima', comp)

prob.setup(force_alloc_complex=True)

prob['akima.chord:x_cp'] = xcp
prob['akima.chord:y_cp'] = ycp.reshape((1, ncp))
prob['akima.chord:x'] = x

prob.run_model()
xcp = np.array([1.0, 2.0, 4.0, 6.0, 10.0, 12.0])
ycp = np.array([5.0, 12.0, 14.0, 16.0, 21.0, 29.0])
n = 50
x = np.linspace(1.0, 12.0, n)

prob = om.Problem()

akima_option = {'delta_x': 0.1}
comp = om.SplineComp(method='akima', x_cp_val=xcp, x_interp_val=x,
                     interp_options=akima_option)

prob.model.add_subsystem('akima1', comp)

comp.add_spline(y_cp_name='ycp', y_interp_name='y_val', y_cp_val=ycp)

prob.setup(force_alloc_complex=True)
prob.run_model()

Create an interpolating component using Bsplines#

prob = om.Problem()
model = prob.model

n_cp = 5
n_point = 10

t = np.linspace(0, 0.5*np.pi, n_cp)
x = np.empty((2, n_cp))
x[0, :] = np.sin(t)
x[1, :] = 2.0*np.sin(t)

comp = om.BsplinesComp(num_control_points=n_cp,
                       num_points=n_point,
                       bspline_order=4,
                       distribution='sine',
                       vec_size=2,
                       in_name='h_cp',
                       out_name='h')

model.add_subsystem('interp', comp)

prob.setup()
prob.run_model()
from openmdao.utils.spline_distributions import sine_distribution

prob = om.Problem()
model = prob.model

n_cp = 5
n_point = 10

t = np.linspace(0, 0.5 * np.pi, n_cp)
x = np.empty((2, n_cp))
x[0, :] = np.sin(t)
x[1, :] = 2.0 * np.sin(t)

# In 2.x, the BsplinesComp had a built-in sinusoidal distribution.
t_sin = sine_distribution(n_point) * np.pi * 0.5

bspline_options = {'order': 4}
comp = om.SplineComp(method='bsplines',
                     x_interp_val=t_sin,
                     num_cp=n_cp,
                     vec_size=2,
                     interp_options=bspline_options)

prob.model.add_subsystem('interp', comp)

comp.add_spline(y_cp_name='h_cp', y_interp_name='h', y_cp_val=x, y_units='km')

prob.setup()
prob.run_model()

Create an ExecComp with diagonal partials#

model.add_subsystem('comp', ExecComp('y=3.0*x + 2.5',
                                     vectorize=True,
                                     x=np.ones(5), y=np.ones(5)))
model.add_subsystem('comp', om.ExecComp('y=3.0*x + 2.5',
                                        has_diag_partials=True,
                                        x=np.ones(5), y=np.ones(5)))

Create an IndepVarComp with multiple outputs#

comp = om.IndepVarComp((
    ('indep_var_1', 1.0, {'lower': 0, 'upper': 10}),
    ('indep_var_2', 2.0, {'lower': 1., 'upper': 20}),
))
comp = om.IndepVarComp()
comp.add_output('indep_var_1', val=1.0)
comp.add_output('indep_var_2', val=2.0)

Create an ExternalCodeComp#

class ParaboloidExternalCodeCompDerivs(om.ExternalCode):
class ParaboloidExternalCodeCompDerivs(om.ExternalCodeComp):

Create a KSComponent#

model.add_subsystem('ks', om.KSComponent(width=2))
model.add_subsystem('ks', om.KSComp(width=2))

Create a MetaModel#

sin_mm = om.MetaModel()
sin_mm = om.MetaModelUnStructuredComp()

Create a MetaModelUnstructured#

sin_mm = om.MetaModelUnstructured()
sin_mm = om.MetaModelUnStructuredComp()

Create a MetaModelStructured#

interp = om.MetaModelStructured(method='scipy_cubic', vec_size=2)
interp = om.MetaModelStructuredComp(method='scipy_cubic', vec_size=2)

Create a MultiFiMetaModel#

mm = om.MultiFiMetaModel(nfi=2)
mm = om.MultiFiMetaModelUnStructuredComp(nfi=2)

Create a MultiFiMetaModelUnStructured#

mm = om.MultiFiMetaModelUnStructured(nfi=2)
mm = om.MultiFiMetaModelUnStructuredComp(nfi=2)

Add a FloatKrigingSurrogate to a MetaModelStructuredComp#

sin_mm.add_output('f_x', 0., surrogate=om.FloatKrigingSurrogate())
sin_mm.add_output('f_x', 0., surrogate=om.KrigingSurrogate())

Specify a default surrogate model for MetaModelStructuredComp#

trig = om.MetaModelUnStructuredComp(vec_size=size)
trig.default_surrogate = om.KrigingSurrogate()
trig = om.MetaModelUnStructuredComp(vec_size=size, default_surrogate=om.KrigingSurrogate())

Solvers#

Declare a NewtonSolver with solve_subsystems set to False#

newton = model.nonlinear_solver = om.NewtonSolver()
newton = model.nonlinear_solver = om.NewtonSolver(solve_subsystems=False)

Control how a solver handles an error raised in a subsolver#

newton = model.nonlinear_solver = NewtonSolver()
newton.options['maxiter'] = 1
newton.options['err_on_maxiter'] = True
newton = model.nonlinear_solver = om.NewtonSolver(solve_subsystems=False)
newton.options['maxiter'] = 1
newton.options['err_on_non_converge'] = True

Add a preconditioner to PETScKrylov#

model.linear_solver = om.PETScKrylov()
model.linear_solver.preconditioner = om.LinearBlockGS()
model.linear_solver = om.PETScKrylov()
model.linear_solver.precon = om.LinearBlockGS()

Add a preconditioner to ScipyKrylov#

model.linear_solver.preconditioner = om.LinearBlockGS()
model.linear_solver.precon = om.LinearBlockGS()

Add a ArmijoGoldsteinLS to a NewtonSolver#

top.model.nonlinear_solver = om.NewtonSolver(solve_subsystems=False)
top.model.nonlinear_solver.options['maxiter'] = 10
top.model.linear_solver = om.ScipyKrylov()

ls = top.model.nonlinear_solver.line_search = om.ArmijoGoldsteinLS(bound_enforcement='vector')
top.model.nonlinear_solver = om.NewtonSolver(solve_subsystems=False)
top.model.nonlinear_solver.options['maxiter'] = 10
top.model.linear_solver = om.ScipyKrylov()

ls = top.model.nonlinear_solver.linesearch = om.ArmijoGoldsteinLS(bound_enforcement='vector')

Create a NonLinearRunOnce#

model.nonlinear_solver = om.NonLinearRunOnce()
model.nonlinear_solver = om.NonlinearRunOnce()

Create a PetscKSP#

model.linear_solver = om.PetscKSP()
model.linear_solver = om.PETScKrylov()

Create a ScipyIterativeSolver#

model.linear_solver = om.ScipyIterativeSolver()
model.linear_solver = om.ScipyKrylov()

Drivers#

Activate dynamic coloring on a Driver#

p.driver.options['dynamic_simul_derivs'] = True
p.driver.declare_coloring()

Add a ScipyOptimizer to a Problem#

prob.driver = om.ScipyOptimizer()
prob.driver = om.ScipyOptimizeDriver()

Working with Derivatives#

Use a pre-computed coloring on a model#

p.driver.set_simul_deriv_color()
p.driver.use_fixed_coloring()

Case Reading#

Query the iteration coordinate for a case#

cr = om.CaseReader(self.filename)

for i, c in enumerate(cr.list_cases()):
    case = cr.get_case(c)

    coord = case.iteration_coordinate
cr = om.CaseReader(filename)

for i, c in enumerate(cr.list_cases(out_stream=None)):
    case = cr.get_case(c)

    coord = case.name

Running a Model#

Run a Driver#

prob.run()
prob.run_driver()

Run a Model without Running the Driver#

prob.run_once()
prob.run_model()