Reloading Case Data into a Model

The OpenMDAO API provides a way to load into a model a case from a case recorder file. The method to do this is Problem.load_case. Its only argument is a case object from a case recorder file.

Problem.load_case(case)[source]

Pull all input and output variables from a case into the model.

Parameters
caseCase object

A Case from a CaseRecorder file.

The method pulls all input and output variables from a case into the model.

Using case recorders, you can record many sources (driver, system, problem, solver). Therefore, cases can have many different types of values. load_case works with all of these recordings.

It is important to keep in mind that just the variables in the case are updated in the model. The rest of the model variables are left unchanged.

Why would you want to load case?

There are several use cases for using load_case.

  • Save points from a Design of Experiments (DOE) run and then go back and run further analysis on them

  • Give an optimization run an initial guess with values from a previous optimization run. For example, a user would use one optimization method to quickly get a solution that is close, save the case, then using a more accurate, but slower method to find the solution after loading in that case from the first run

  • Run a sweep of constraint values. This would allow a user to save time by doing runs using initial values from previous runs instead of starting from scratch each time

Simple load case example

Here is a simple example of how to call the load_case method.

import openmdao.api as om
from openmdao.test_suite.components.sellar import SellarProblem

prob = SellarProblem()

model = prob.model
model.recording_options['record_inputs'] = True
model.recording_options['record_outputs'] = True
model.recording_options['record_residuals'] = True
case_recorder_filename = "cases.sql"
model.add_recorder(om.SqliteRecorder(case_recorder_filename))

prob.setup()

prob.run_driver()
prob.cleanup()

cr = om.CaseReader(case_recorder_filename)

system_cases = cr.list_cases('root', out_stream=None)
case = cr.get_case(system_cases[0])

# Now load in the case we recorded
prob.load_case(case)
/usr/share/miniconda/envs/test/lib/python3.8/site-packages/openmdao/recorders/sqlite_recorder.py:224: UserWarning:The existing case recorder file, cases.sql, is being overwritten.

As was mentioned before, just the variables values in the case get updated in the model. In this example, the case contains values for the model variables x,z,y1,y2,con1,con2, and obj.

But if the recorder had only been attached to a subsystem, like this

model.d2.add_recorder(om.SqliteRecorder(case_recorder_filename))

only the variables z,y1, and y2 would have been recorded and when load_case was called with a case from that recording, only those variables in the model would be updated.

Here is a somewhat more realistic use case for load_case. In this example, an optimization is run and then the third case is used to load the model and start the optimization again. Notice how in the second optimization run, the optimization requires fewer iterations since it was given an initial guess.

from openmdao.test_suite.components.sellar import SellarDerivativesGrouped

prob = SellarProblem(SellarDerivativesGrouped)

case_recorder_filename = "cases.sql"
prob.model.add_recorder(om.SqliteRecorder(case_recorder_filename))

driver = prob.driver = om.ScipyOptimizeDriver()
driver.options['optimizer'] = 'SLSQP'
driver.options['tol'] = 1e-9
driver.options['disp'] = False
driver.recording_options['record_desvars'] = True
driver.recording_options['record_objectives'] = True
driver.recording_options['record_constraints'] = True

prob.setup()
prob.run_driver()
prob.cleanup()

inputs_before = prob.model.list_inputs(val=True, units=True, out_stream=None)
outputs_before = prob.model.list_outputs(val=True, units=True, out_stream=None)

cr = om.CaseReader(case_recorder_filename)

# get third case
system_cases = cr.list_cases('root', out_stream=None)
third_case = cr.get_case(system_cases[4])

iter_count_before = driver.iter_count

# run the model again with a fresh model
prob = SellarProblem(SellarDerivativesGrouped)

driver = prob.driver = om.ScipyOptimizeDriver()
driver.options['optimizer'] = 'SLSQP'
driver.options['tol'] = 1e-9
driver.options['disp'] = False

prob.setup()
prob.load_case(third_case)
prob.run_driver()
prob.cleanup()

inputs_after = prob.model.list_inputs(val=True, units=True, out_stream=None)
outputs_after = prob.model.list_outputs(val=True, units=True, out_stream=None)

iter_count_after = driver.iter_count
print(f"iterations before: {iter_count_before} iterations after: {iter_count_after}")
iterations before: 7 iterations after: 4