This guide takes how you did things in OpenMDAO 1 and shows how to do them OpenMDAO 2. It is not a comprehensive guide to using OpenMDAO 2, but focuses only on the things that have changed in the API.

## Build a Model¶

### Define an Explcit Component¶

class Paraboloid(Component):
"""
Evaluates the equation f(x,y) = (x-3)^2 + xy + (y+4)^2 - 3.
"""

def __init__(self):
super(Paraboloid, self).__init__()

def solve_nonlinear(self, params, unknowns, resids):
"""
f(x,y) = (x-3)^2 + xy + (y+4)^2 - 3

Optimal solution (minimum): x = 6.6667; y = -7.3333
"""
x = params['x']
y = params['y']

unknowns['f_xy'] = (x-3.0)**2 + x*y + (y+4.0)**2 - 3.0

def linearize(self, params, unknowns, resids):
"""
Jacobian for our paraboloid.
"""
x = params['x']
y = params['y']

J = {}
J['f_xy', 'x'] = 2.0*x - 6.0 + y
J['f_xy', 'y'] = 2.0*y + 8.0 + x

return J

class Paraboloid(ExplicitComponent):
"""
Evaluates the equation f(x,y) = (x-3)^2 + xy + (y+4)^2 - 3.
"""

def setup(self):

self.declare_partials('*', '*')

def compute(self, inputs, outputs):
"""
f(x,y) = (x-3)^2 + xy + (y+4)^2 - 3

Optimal solution (minimum): x = 6.6667; y = -7.3333
"""
x = inputs['x']
y = inputs['y']

outputs['f_xy'] = (x-3.0)**2 + x*y + (y+4.0)**2 - 3.0

def compute_partials(self, inputs, partials):
"""
Jacobian for our paraboloid.
"""
x = inputs['x']
y = inputs['y']

partials['f_xy', 'x'] = 2.0*x - 6.0 + y
partials['f_xy', 'y'] = 2.0*y + 8.0 + x


### Define an Implicit Component¶

class ImplCompOneState(Component):
"""
A Simple Implicit Component

R(x,y) = 0.5y^2 + 2y + exp(-16y^2) + 2exp(-5y) - x

Solution:
x = 1.2278849186466743
y = 0.3968459
"""

def setup(self):

def apply_nonlinear(self, params, unknowns, resids):
"""
Don't solve; just calculate the residual.
"""
x = params['x']
y = unknowns['y']

resids['y'] = 0.5*y*y + 2.0*y + exp(-16.0*y*y) + 2.0*exp(-5.0*y) - x

def linearize(self, params, unknowns, resids):
"""
Analytical derivatives.
"""
y = unknowns['y']

J = {}

# State equation
J[('y', 'x')] = -1.0
J[('y', 'y')] = y + 2.0 - 32.0*y*exp(-16.0*y*y) - 10.0*exp(-5.0*y)

return J

class ImplCompOneState(ImplicitComponent):
"""
A Simple Implicit Component

R(x,y) = 0.5y^2 + 2y + exp(-16y^2) + 2exp(-5y) - x

Solution:
x = 1.2278849186466743
y = 0.3968459
"""

def setup(self):

self.declare_partials(of='*', wrt='*')

def apply_nonlinear(self, inputs, outputs, resids):
"""
Don't solve; just calculate the residual.
"""
x = inputs['x']
y = outputs['y']

resids['y'] = 0.5*y*y + 2.0*y + exp(-16.0*y*y) + 2.0*exp(-5.0*y) - x

def linearize(self, inputs, outputs, J):
"""
Analytical derivatives.
"""
y = outputs['y']

# State equation
J[('y', 'x')] = -1.0
J[('y', 'y')] = y + 2.0 - 32.0*y*exp(-16.0*y*y) - 10.0*exp(-5.0*y)


### Input-Input connections¶

See more details in the doc for add_subsystem().

prob = Problem()
root = prob.root = Group()

#input-input connection
root.connect('comp1.x', 'comp2.x')
#then connect the indep var to just one of the inputs
root.connect('p1.x', 'comp1.x')

prob.setup()
prob.run()

from openmdao.api import Problem, Group, IndepVarComp
from openmdao.test_suite.components.paraboloid import Paraboloid

prob = Problem()
model = prob.model = Group()

#promote the two inputs to the same name

#connect the source to the common name
model.connect('p1.x', 'x')

prob.setup()
prob.run_model()


## Run a Model¶

### Assemble and Run a Simple Model¶

prob = Problem()
root = prob.root = Group()

root.connect('p1.x', 'comp.x')
root.connect('p2.y', 'comp.y')

prob.setup()
prob.run()

from openmdao.api import Problem, Group, IndepVarComp
from openmdao.test_suite.components.paraboloid import Paraboloid

prob = Problem()
model = prob.model = Group()

model.connect('p1.x', 'comp.x')
model.connect('p2.y', 'comp.y')

prob.setup()
prob.run_model()


### Run a Driver¶

prob.run()

prob.run_driver()


### Run a Model without Running the Driver¶

prob.run_once()

prob.run_model()


## Check a Model¶

### Specify Finite Difference for all Component Derivatives¶

def __init__(self):
super(SellarDis1, self).__init__()

# Global Design Variable

# Local Design Variable

# Coupling parameter

# Coupling output

# Finite difference all partials.
self.deriv_options['type'] = 'fd'

    def setup(self):

# Global Design Variable

# Local Design Variable

# Coupling parameter

# Coupling output

# Finite difference all partials.
self.declare_partials('*', '*', method='fd')


### Specify FD Form and Stepsize on Specific Derivatives¶

def __init__(self):
super(PartialComp, self).__init__()


def setup(self):

self.declare_partials('f', 'y*', method='fd', form='backward', step=1e-6)
self.declare_partials('f', 'x', method='fd', form='central', step=1e-4)


### Check Partial Derivatives on All Components¶

data = prob.check_partials()

data = prob.check_partials()


### Check Partial Derivatives with Complex Step¶

  prob.root.deriv_options['check_type'] = 'cs'

prob.setup()
prob.run()

prob.check_partials()

def test_set_method_global(self):
from openmdao.api import Problem, Group, IndepVarComp
from openmdao.core.tests.test_check_derivs import ParaboloidTricky
from openmdao.test_suite.components.paraboloid_mat_vec import ParaboloidMatVec

prob = Problem()
prob.model = Group()

prob.model.connect('p1.x', 'comp.x')
prob.model.connect('p2.y', 'comp.y')
prob.model.connect('comp.f_xy', 'comp2.x')

prob.set_solver_print(level=0)

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

prob.check_partials(method='cs')


## Change Group Level Derivative Behavior¶

### Force Group or Model to use Finite Difference¶

model.deriv_options['type'] = 'fd'

model.approx_totals()


### Force Group or Model to use Finite Difference with Specific Options¶

model.deriv_options['type'] = 'fd'
model.deriv_options['step_size'] = '1e-7'
model.deriv_options['form'] = 'central'
model.deriv_options['step_calc'] = 'relative'

model.approx_totals(method='fd', step=1e-7, form='central', step_calc='rel')


### Add a Design Variable to a Model¶

prob = Problem()
prob.root = SellarDerivatives()


prob = Problem()
prob.model = model = SellarDerivatives()



### Add a Design Variable with Scale and Offset that Maps [3, 5] to [0, 1]¶

prob = Problem()
prob.root = SellarDerivatives()


prob = Problem()
prob.model = model = SellarDerivatives()



## Set Solvers¶

### Setup a Problem Using the PETScVector¶

prob.setup(impl=PetscImpl)

def test_feature_basic_setup(self):
from openmdao.api import Problem, Group, IndepVarComp
from openmdao.test_suite.components.paraboloid import Paraboloid

prob = Problem()
model = prob.model = Group()

prob.setup()

prob['x'] = 2.
prob['y'] = 10.
prob.run_model()
assert_rel_error(self, prob['f_xy'], 214.0, 1e-6)

prob['x'] = 0.
prob['y'] = 0.
prob.run_model()
assert_rel_error(self, prob['f_xy'], 22.0, 1e-6)

# skip the setup error checking
prob.setup()
prob['x'] = 4
prob['y'] = 8.

prob.run_model()
assert_rel_error(self, prob['f_xy'], 174.0, 1e-6)


### Specify Newton as a Nonlinear Solver in a Group¶

model.nl_solver = Newton()

model.nonlinear_solver = NewtonSolver()


### Specify Block Gauss-Seidel as a Nonlinear Solver in a Group¶

model.nl_solver = NLGaussSeidel()

model.nonlinear_solver = NonlinearBlockGS()


### Specify Scipy GMRES as a Linear Solver in a Group¶

model.ln_solver = ScipyGMRES()

model.linear_solver = ScipyKrylov()


### Specify Linear Block Gauss-Seidel as a Linear Solver in a Group¶

model.ln_solver = LinearGaussSeidel()

model.linear_solver = LinearBlockGS()


## Total Derivatives¶

### Computing Total Derivatives¶

prob.calc_gradient(indep_list=['p1.x', 'p2.y'], unknown_list=['comp.f_xy'])

totals = prob.compute_totals(of=['comp.f_xy'], wrt=['p1.x', 'p2.y'])


### Setting Derivative Computation Mode¶

root.ln_solver.options['mode'] = 'rev'
# root.ln_solver.options['mode'] = 'fwd'
# root.ln_solver.options['mode'] = 'auto'
prob.setup()
prob.run()

prob.setup(mode='rev')