The System Setup Stack: Understanding When to Use setup and configure

This document explains what happens during the OpenMDAO Problem setup process, and how some of the model API methods interact during that process.

The purpose of the setup process is to prepare the data structures that OpenMDAO needs to efficiently run your model or driver. In particular, this includes setting up the vectors used for passing data to inputs, converging solvers, and calculating derivatives. It also includes setting up the MPI communicators.

Setup also performs some level of model checking, mainly for critical errors. More extensive model checking can be done by setting “check” when calling setup, or by using the openmdao command line check. It is recommended that you do this after making any changes to the configuration of your model. The “check” argument to setup can be set to True, which will cause a default set of checks to run. It can also be set to ‘all’, which will run all available checks. A value of None or True will result in no checks being run. Finally, it can be set to a specific list of checks to run as a list of strings. The checks that are available can be determined by running the following command:

openmdao check -h
usage: openmdao [-h] [--version] command [command_options] filename check
       [-h] [-o OUTFILE] [-p PROBLEM] [-c CHECKS] file

positional arguments:
  file                  Python file containing the model

optional arguments:
  -h, --help            show this help message and exit
  -o OUTFILE            output file
  -p PROBLEM, --problem PROBLEM
                        Problem name
  -c CHECKS             Only perform specific check(s). Default checks are:
                        ['auto_ivc_warnings', 'comp_has_no_outputs',
                        'dup_inputs', 'missing_recorders', 'out_of_order',
                        'solvers', 'system']. Other available checks are:
                        ['cycles', 'promotions', 'unconnected_inputs']

By default, the output of all checks will be written to a file called ‘openmdao_checks.out’ in addition to stdout. Checks can also be performed by calling the check_config method on your problem object.

The OpenMDAO Group API includes three methods that are invoked during the setup process: initialize, setup, and configure. Most of the time, setup is all you need to build a group. The specific use case for configure is shown below in the next section. The initialize method is only used for declaring options for your group (and also in Component), and their placement here allows them to be passed into the group as instantiation arguments.

One question that is often asked is: why can’t we just put all of our model building code into our group’s __init__ method so that everything is there when I instantiate the class? The answer is, when running a parallel model under MPI, certain systems might only be executed on certain processors. To save memory across the model, these systems are not fully set up on processors where they are not local. The only way to do this is to isolate the model building process into a custom method (setup) and only call it on the processors where that system is active. While not everyone will run their models in parallel, it is a good practice to follow the stricter guideline so that, if someone wants to include your model in a larger parallel model, they won’t be forced to allocate any unnecessary memory.

Usage of setup vs. configure

The need for two methods for setting up a group arose from a need to sometimes change the linear or nonlinear solvers in a subgroup after it had been added. When setup is called on the problem, the setup method in each group is called recursively from top to bottom of the hierarchy. For example, a group may contain several components and groups. Setup is first called in that top group, during which, those components and groups are instantiated. However, the setup methods belonging to those sub-components and groups cannot be called until the top group’s setup finishes. This means they are in a state where components and groups that are declared in the subgroup don’t exist yet.

To remedy this, there is a second api method called configure that lets you make changes to your subsystems after they have been created. The configure method is only needed with groups, and it is called recursively from the bottom of the hierarchy to the top, so that at any level, you can be sure that configure has already run for all your subsystems. This assures that changes made in higher-level groups take precedence over those in lower-level ones. Top precedence is given to changes made after calling setup on the Problem.

A second use case for configure is issuing connections to subsystems when you need information (e.g. path names) that has been set during setup of those subsystems. Since configure runs after setup has been called on all subsystems, you can be sure that this information will be available.

Here is a quick guide covering what you can do in the setup and configure methods.

Action

Setup

Configure

Add subsystems

o

Issue connections

o

o

Set system execution order

o

Add inputs and outputs to components within this group

o

o

Promote variables from subsystems

o

o

Assign solvers at this group level

o

o

Assign solvers within subsystems

o

o

Change solver settings for any solver at this group level

o

o

Change solver settings in subsystems

o

Assign Jacobians at this group level

o

o

Assign Jacobians within subsystems

o

Add design variables, objectives, and constraints relative to this group level

o

o

Add design variables, objectives, and constraints to subsystems

o

Add a case recorder to the group or to a solver in this group

o

o

Add a case recorder to the group or to a solver in a subsystem

o

Keep in mind that, when configure is being run, you are already done calling setup on every group and component in the model, so if you add a new subsystem here, setup will never be called on it, and it will not be properly integrated into the model hierarchy.

Problem setup and final_setup

OpenMDAO 2.0 introduced a new change to the setup process in which the original monolithic process is split into two separate phases triggered by the methods: setup and final_setup. The final_setup method is however something you will probably never have to call, as it is called automatically the first time that you call run_model or run_driver after running setup. The reason that the setup process was split into two phases is to allow you to perform certain actions after setup:

Post-setup actions

  • Set values of inputs and indepvarcomps

  • Change settings on solvers

  • Change options on systems

  • Add recorders

  • Assign Jacobians

  • Add training data to metamodels

If you do anything that changes the model hierarchy, such as adding a component to a group, then you will need to run setup again.

During setup, the following things happen:

  • MPI processors are allocated

  • For each custom Group, setup function is called recursively from top to bottom

  • Model hierarchy is created

  • For each custom Group, configure function is called recursively from bottom to top

  • Connections are assembled and verified

  • Variables are sized

This is just enough to allow you to perform the post-setup actions listed above, but there are still more things to do before the model can run. In final_setup, the following happens:

  • All vectors for the nonlinear and linear systems are created and allocated

  • Data transfers are created (i.e., scatters for MPI)

  • Solvers are set up

  • Jacobians are set up and allocated

  • Recorders are set up

  • Drivers are set up

  • Initial values are loaded into the inputs and outputs vectors