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.

Building Component Models

Declare a Component with distributed variables

class DistribComp(ExplicitComponent):

    def __init__(self, size):
        super().__init__()
        self.distributed = True
class DistribComp(om.ExplicitComponent):
    """Simple Distributed Component."""

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

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

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 ExternalCode

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(self.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()