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(2)
prob.run_driver()
prob.record("after_run_driver")
# Instantiate your CaseReader
cr = om.CaseReader(prob.get_outputs_dir() / "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)
=====
cycle
=====
NL: NLBGS 1 ; 29.0742299 1
NL: NLBGS 2 ; 2.26505979 0.0779060975
NL: NLBGS 3 ; 0.0438762115 0.00150911001
NL: NLBGS 4 ; 0.000867730413 2.98453446e-05
NL: NLBGS 5 ; 1.715381e-05 5.90000492e-07
NL: NLBGS 6 ; 3.39109478e-07 1.16635756e-08
NL: NLBGS 7 ; 6.70377103e-09 2.30574328e-10
NL: NLBGS 8 ; 1.32523072e-10 4.55809395e-12
NL: NLBGS Converged
=====
cycle
=====
NL: NLBGS 1 ; 2.62038164e-12 1
NL: NLBGS Converged
=====
cycle
=====
NL: NLBGS 1 ; 19.1706591 1
NL: NLBGS 2 ; 1.13589624 0.0592518093
NL: NLBGS 3 ; 0.0406301437 0.00211939211
NL: NLBGS 4 ; 0.00140619452 7.33513916e-05
NL: NLBGS 5 ; 4.87225696e-05 2.54151771e-06
NL: NLBGS 6 ; 1.68809957e-06 8.80564178e-08
NL: NLBGS 7 ; 5.84879658e-08 3.05091053e-09
NL: NLBGS 8 ; 2.02644495e-09 1.05705544e-10
NL: NLBGS 9 ; 7.02105639e-11 3.66239698e-12
NL: NLBGS Converged
=====
cycle
=====
NL: NLBGS 1 ; 5.26036062 1
NL: NLBGS 2 ; 0.514550635 0.0978166083
NL: NLBGS 3 ; 0.0258623712 0.00491646354
NL: NLBGS 4 ; 0.00126421196 0.000240328002
NL: NLBGS 5 ; 6.18806611e-05 1.17635777e-05
NL: NLBGS 6 ; 3.02873598e-06 5.75765845e-07
NL: NLBGS 7 ; 1.48241324e-07 2.81808292e-08
NL: NLBGS 8 ; 7.25566271e-09 1.37930899e-09
NL: NLBGS 9 ; 3.55128357e-10 6.75102682e-11
NL: NLBGS Converged
=====
cycle
=====
NL: NLBGS 1 ; 1.07485557 1
NL: NLBGS 2 ; 0.0990937833 0.0921926498
NL: NLBGS 3 ; 0.00548653523 0.00510443949
NL: NLBGS 4 ; 0.000301840405 0.0002808195
NL: NLBGS 5 ; 1.66114932e-05 1.54546282e-05
NL: NLBGS 6 ; 9.14179754e-07 8.50514039e-07
NL: NLBGS 7 ; 5.03100777e-08 4.68063608e-08
NL: NLBGS 8 ; 2.76871581e-09 2.57589567e-09
NL: NLBGS 9 ; 1.52370833e-10 1.41759355e-10
NL: NLBGS 10 ; 8.38508293e-12 7.80112523e-12
NL: NLBGS Converged
=====
cycle
=====
NL: NLBGS 1 ; 0.158851235 1
NL: NLBGS 2 ; 0.015354566 0.0966600355
NL: NLBGS 3 ; 0.000862519812 0.00542973314
NL: NLBGS 4 ; 4.8401591e-05 0.000304697607
NL: NLBGS 5 ; 2.71628247e-06 1.70995364e-05
NL: NLBGS 6 ; 1.52436453e-07 9.5961768e-07
NL: NLBGS 7 ; 8.55466141e-09 5.38532888e-08
NL: NLBGS 8 ; 4.80083221e-10 3.02221901e-09
NL: NLBGS 9 ; 2.69419589e-11 1.6960497e-10
NL: NLBGS Converged
=====
cycle
=====
NL: NLBGS 1 ; 0.0172187065 1
NL: NLBGS 2 ; 0.00168376513 0.0977869697
NL: NLBGS 3 ; 9.47059838e-05 0.00550017993
NL: NLBGS 4 ; 5.32629055e-06 0.00030933163
NL: NLBGS 5 ; 2.99553925e-07 1.73970051e-05
NL: NLBGS 6 ; 1.68470947e-08 9.78418133e-07
NL: NLBGS 7 ; 9.47490739e-10 5.50268244e-08
NL: NLBGS 8 ; 5.32877417e-11 3.0947587e-09
NL: NLBGS Converged
=====
cycle
=====
NL: NLBGS 1 ; 0.00175633489 1
NL: NLBGS 2 ; 0.000171891791 0.0978695987
NL: NLBGS 3 ; 9.66953315e-06 0.00550551789
NL: NLBGS 4 ; 5.43939913e-07 0.000309701707
NL: NLBGS 5 ; 3.05982528e-08 1.74216506e-05
NL: NLBGS 6 ; 1.72124338e-09 9.80020035e-07
NL: NLBGS 7 ; 9.68247166e-11 5.51288466e-08
NL: NLBGS Converged
=====
cycle
=====
NL: NLBGS 1 ; 0.000177747673 1
NL: NLBGS 2 ; 1.73975926e-05 0.097878033
NL: NLBGS 3 ; 9.78689658e-07 0.00550606173
NL: NLBGS 4 ; 5.5055453e-08 0.000309739375
NL: NLBGS 5 ; 3.0971034e-09 1.74241573e-05
NL: NLBGS 6 ; 1.74225412e-10 9.80183927e-07
NL: NLBGS 7 ; 9.80113177e-12 5.51407038e-08
NL: NLBGS Converged
=====
cycle
=====
NL: NLBGS 1 ; 1.79815247e-05 1
NL: NLBGS 2 ; 1.76001162e-06 0.0978788866
NL: NLBGS 3 ; 9.90083751e-08 0.00550611678
NL: NLBGS 4 ; 5.56965516e-09 0.000309743208
NL: NLBGS 5 ; 3.1331762e-10 1.7424419e-05
NL: NLBGS 6 ; 1.76256505e-11 9.80208895e-07
NL: NLBGS Converged
=====
cycle
=====
NL: NLBGS 1 ; 1.8163361e-06 1
NL: NLBGS 2 ; 1.77781071e-07 0.0978789503
NL: NLBGS 3 ; 1.00009665e-08 0.00550612108
NL: NLBGS 4 ; 5.62598486e-10 0.000309743602
NL: NLBGS 5 ; 3.16491348e-11 1.74247128e-05
NL: NLBGS Converged
=====
cycle
=====
NL: NLBGS 1 ; 1.85896329e-07 1
NL: NLBGS 2 ; 1.81954097e-08 0.0978793381
NL: NLBGS 3 ; 1.02357168e-09 0.0055061425
NL: NLBGS 4 ; 5.75801779e-11 0.000309743491
NL: NLBGS Converged
=====
cycle
=====
NL: NLBGS 1 ; 1.88099812e-08 1
NL: NLBGS 2 ; 1.84097393e-09 0.0978721832
NL: NLBGS 3 ; 1.03563111e-10 0.00550575302
NL: NLBGS 4 ; 5.82600946e-12 0.00030972968
NL: NLBGS Converged
=====
cycle
=====
NL: NLBGS 1 ; 1.89912911e-09 1
NL: NLBGS 2 ; 1.85875293e-10 0.0978739635
NL: NLBGS 3 ; 1.045628e-11 0.00550582891
NL: NLBGS Converged
[-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 prom_name
-------- ----------------- ---------
cycle
d1
y1 [3.16] y1
d2
y2 [3.75527777] y2
obj_cmp
obj [3.18339395] obj
con_cmp1
con1 [-1.68550507e-10] con1
con_cmp2
con2 [-20.24472223] con2
0 Implicit Output(s) in 'model'
[('con_cmp1.con1', {'val': array([-1.68550507e-10]), 'io': 'output', 'prom_name': 'con1'}), ('con_cmp2.con2', {'val': array([-20.24472223]), 'io': 'output', 'prom_name': 'con2'}), ('cycle.d1.y1', {'val': array([3.16]), 'io': 'output', 'prom_name': 'y1'}), ('cycle.d2.y2', {'val': array([3.75527777]), 'io': 'output', 'prom_name': 'y2'}), ('obj_cmp.obj', {'val': array([3.18339395]), 'io': 'output', 'prom_name': 'obj'})]
# 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]