Basic Recording Example#
Recording Terminology#
Case: A Case stores a snapshot of all the variable values, metadata, and options of a model, or a sub-set of a model, at a particular point in time
Case Recorder: An OpenMDAO module used to store a snapshot of a model before, during, or after execution in an SQL file.
Sources: The OpenMDAO object responsible for recording the case. Can be
Problem
,Driver
or a specificSystem
orSolver
identified by pathname.
Basic Recording Example#
Below is a basic example of how to create a recorder, attach it to a Problem, save the information,
and retrieve the data from the recorder. list_outputs
is a quick way to show all of your outputs
and their values at the time the case was recorded, and should you need to isolate a single value OpenMDAO provides two ways to
retrieve them. To view all the design variables, constraints, and
objectives, you can use their methods like the example below.
SellarMDAWithUnits
class definition
class SellarMDAWithUnits(om.Group):
"""
Group containing the Sellar MDA.
"""
class SellarDis1Units(om.ExplicitComponent):
"""
Component containing Discipline 1 -- no derivatives version.
"""
def setup(self):
# Global Design Variable
self.add_input('z', val=np.zeros(2), units='degC')
# Local Design Variable
self.add_input('x', val=0., units='degC')
# Coupling parameter
self.add_input('y2', val=1.0, units='degC')
# Coupling output
self.add_output('y1', val=1.0, units='degC')
def setup_partials(self):
# Finite difference all partials.
self.declare_partials('*', '*', method='fd')
def compute(self, inputs, outputs):
"""
Evaluates the equation
y1 = z1**2 + z2 + x1 - 0.2*y2
"""
z1 = inputs['z'][0]
z2 = inputs['z'][1]
x1 = inputs['x']
y2 = inputs['y2']
outputs['y1'] = z1**2 + z2 + x1 - 0.2*y2
class SellarDis2Units(om.ExplicitComponent):
"""
Component containing Discipline 2 -- no derivatives version.
"""
def setup(self):
# Global Design Variable
self.add_input('z', val=np.zeros(2), units='degC')
# Coupling parameter
self.add_input('y1', val=1.0, units='degC')
# Coupling output
self.add_output('y2', val=1.0, units='degC')
def setup_partials(self):
# Finite difference all partials.
self.declare_partials('*', '*', method='fd')
def compute(self, inputs, outputs):
"""
Evaluates the equation
y2 = y1**(.5) + z1 + z2
"""
z1 = inputs['z'][0]
z2 = inputs['z'][1]
y1 = inputs['y1']
# Note: this may cause some issues. However, y1 is constrained to be
# above 3.16, so lets just let it converge, and the optimizer will
# throw it out
if y1.real < 0.0:
y1 *= -1
outputs['y2'] = y1**.5 + z1 + z2
def setup(self):
cycle = self.add_subsystem('cycle', om.Group(), promotes=['*'])
cycle.add_subsystem('d1', self.SellarDis1Units(), promotes_inputs=['x', 'z', 'y2'],
promotes_outputs=['y1'])
cycle.add_subsystem('d2', self.SellarDis2Units(), promotes_inputs=['z', 'y1'],
promotes_outputs=['y2'])
cycle.set_input_defaults('x', 1.0, units='degC')
cycle.set_input_defaults('z', np.array([5.0, 2.0]), units='degC')
# Nonlinear Block Gauss Seidel is a gradient free solver
cycle.nonlinear_solver = om.NonlinearBlockGS()
self.add_subsystem('obj_cmp', om.ExecComp('obj = x**2 + z[1] + y1 + exp(-y2)',
z={'val': np.array([0.0, 0.0]), 'units': 'degC'},
x={'val': 0.0, 'units': 'degC'},
y1={'units': 'degC'},
y2={'units': 'degC'}),
promotes=['x', 'z', 'y1', 'y2', 'obj'])
self.add_subsystem('con_cmp1', om.ExecComp('con1 = 3.16 - y1', y1={'units': 'degC'},
con1={'units': 'degC'}),
promotes=['con1', 'y1'])
self.add_subsystem('con_cmp2', om.ExecComp('con2 = y2 - 24.0', y2={'units': 'degC'},
con2={'units': 'degC'}),
promotes=['con2', 'y2'])
from openmdao.test_suite.components.sellar_feature import SellarMDAWithUnits
import numpy as np
import openmdao.api as om
# build the model
prob = om.Problem(model=SellarMDAWithUnits())
model = prob.model
model.add_design_var('z', lower=np.array([-10.0, 0.0]), upper=np.array([10.0, 10.0]))
model.add_design_var('x', lower=0.0, upper=10.0)
model.add_objective('obj')
model.add_constraint('con1', upper=0.0)
model.add_constraint('con2', upper=0.0)
# setup the optimization
driver = prob.driver = om.ScipyOptimizeDriver(optimizer='SLSQP', tol=1e-9, disp=False)
# Create a recorder variable
recorder = om.SqliteRecorder('cases.sql')
# Attach a recorder to the problem
prob.add_recorder(recorder)
prob.setup()
prob.set_solver_print(0)
prob.run_driver()
prob.record("after_run_driver")
# Instantiate your CaseReader
cr = om.CaseReader("cases.sql")
# Isolate "problem" as your source
driver_cases = cr.list_cases('problem', out_stream=None)
# Get the first case from the recorder
case = cr.get_case('after_run_driver')
# These options will give outputs as the model sees them
# Gets value but will not convert units
const = case['con1']
print(const)
# get_val can convert your result's units if desired
const_K = case.get_val("con1", units='K')
print(const_K)
[-1.68550507e-10]
[273.15]
# list_outputs will list your model's outputs and return a list of them too
print(case.list_outputs())
5 Explicit Output(s) in 'model'
varname val
-------- -----------------
cycle
d1
y1 [3.16]
d2
y2 [3.75527777]
obj_cmp
obj [3.18339395]
con_cmp1
con1 [-1.68550507e-10]
con_cmp2
con2 [-20.24472223]
0 Implicit Output(s) in 'model'
[('con_cmp1.con1', {'val': array([-1.68550507e-10])}), ('con_cmp2.con2', {'val': array([-20.24472223])}), ('cycle.d1.y1', {'val': array([3.16])}), ('cycle.d2.y2', {'val': array([3.75527777])}), ('obj_cmp.obj', {'val': array([3.18339395])})]
# This code below will find all the objectives, design variables, and constraints that the
# problem source contains
objectives = case.get_objectives()
print(objectives['obj'])
design_vars = case.get_design_vars()
print(design_vars['x'])
constraints = case.get_constraints()
print(constraints['con1'])
[3.18339395]
[0.]
[-1.68550507e-10]