Listing Variables

When working with a model, it may sometimes be helpful to examine the input and output variables. Several methods are provided for this purpose.

.. automethod:: openmdao.core.system.System.list_inputs
    :noindex:

.. automethod:: openmdao.core.system.System.list_outputs
    :noindex:

Example

In the following example, we create a model consisting of two instances of ImplicitComponent.

The implicit components are both instances of QuadraticComp, defined as shown here.

import openmdao.api as om


class QuadraticComp(om.ImplicitComponent):
    """
    A Simple Implicit Component representing a Quadratic Equation.

    R(a, b, c, x) = ax^2 + bx + c

    Solution via Quadratic Formula:
    x = (-b + sqrt(b^2 - 4ac)) / 2a
    """

    def setup(self):
        self.add_input('a', val=1., tags=['tag_a'])
        self.add_input('b', val=1.)
        self.add_input('c', val=1.)
        self.add_output('x', val=0., tags=['tag_x'])

    def setup_partials(self):
        self.declare_partials(of='*', wrt='*')

    def apply_nonlinear(self, inputs, outputs, residuals):
        a = inputs['a']
        b = inputs['b']
        c = inputs['c']
        x = outputs['x']
        residuals['x'] = a * x ** 2 + b * x + c

    def solve_nonlinear(self, inputs, outputs):
        a = inputs['a']
        b = inputs['b']
        c = inputs['c']
        outputs['x'] = (-b + (b ** 2 - 4 * a * c) ** 0.5) / (2 * a)

These two components are placed in a Group with their common inputs promoted together.

import openmdao.api as om

group = om.Group()

sub = group.add_subsystem('sub', om.Group(), promotes_inputs=['a', 'b', 'c'])

sub.add_subsystem('comp1', QuadraticComp(), promotes_inputs=['a', 'b', 'c'])
sub.add_subsystem('comp2', QuadraticComp(), promotes_inputs=['a', 'b', 'c'])

global prob
prob = om.Problem(model=group)
prob.setup()

prob.set_val('a', 1.)
prob.set_val('b', -4.)
prob.set_val('c', 3.)
prob.run_model()

Usage

List Inputs

The list_inputs() method on a System will display all the inputs in execution order with their values. By default, the variable name and variable value are displayed. Also by default, the variables are displayed as part of the System hierarchy. Finally, the default is to display this information to ‘stdout’.

prob.model.list_inputs()
6 Input(s) in 'model'

varname  val  
-------  -----
sub
  comp1
    a    [1.] 
    b    [-4.]
    c    [3.] 
  comp2
    a    [1.] 
    b    [-4.]
    c    [3.] 
[('sub.comp1.a', {'val': array([1.])}),
 ('sub.comp2.a', {'val': array([1.])}),
 ('sub.comp1.b', {'val': array([-4.])}),
 ('sub.comp2.b', {'val': array([-4.])}),
 ('sub.comp1.c', {'val': array([3.])}),
 ('sub.comp2.c', {'val': array([3.])})]

List Outputs

The list_outputs() method will display all the outputs in execution order. There are many options to this method, which we will explore below. For this example, we will only display the value in addition to the name of the output variable.

prob.model.list_outputs()
0 Explicit Output(s) in 'model'


2 Implicit Output(s) in 'model'

varname  val 
-------  ----
sub
  comp1
    x    [3.]
  comp2
    x    [3.]
[('sub.comp1.x', {'val': array([3.])}), ('sub.comp2.x', {'val': array([3.])})]

List Implicit or Explicit Outputs

Note that explicit and implicit outputs are listed separately. If you are only interested in seeing one or the other, you can exclude the ones you do not wish to see via the implicit and explicit arguments.

prob.model.list_outputs(implicit=False)
0 Explicit Output(s) in 'model'
[]
prob.model.list_outputs(explicit=False)
2 Implicit Output(s) in 'model'

varname  val 
-------  ----
sub
  comp1
    x    [3.]
  comp2
    x    [3.]
[('sub.comp1.x', {'val': array([3.])}), ('sub.comp2.x', {'val': array([3.])})]

Get List via Return Value

Both of these methods also return the information in the form of a list. You can disable the display of the information by setting the argument out_stream to None and then access the data instead via the return value.

# list inputs
inputs = prob.model.list_inputs(out_stream=None)
print(sorted(inputs))
[('sub.comp1.a', {'val': array([1.])}), ('sub.comp1.b', {'val': array([-4.])}), ('sub.comp1.c', {'val': array([3.])}), ('sub.comp2.a', {'val': array([1.])}), ('sub.comp2.b', {'val': array([-4.])}), ('sub.comp2.c', {'val': array([3.])})]

The System.get_io_metadata method, which is used internally by list_inputs and list_outputs, returns the specified variable information as a dict.

List Names Only

If you just need the names of the variables, you can disable the display of the values by setting the optional argument, val, to False.

# list inputs
inputs = prob.model.list_inputs(val=False)
6 Input(s) in 'model'

varname
-------
sub
  comp1
    a  
    b  
    c  
  comp2
    a  
    b  
    c  
# list only explicit outputs
outputs = prob.model.list_outputs(implicit=False, val=False)
0 Explicit Output(s) in 'model'

List Names and Promoted Name

If you want the names of the variables and their promoted name within the model, you can enable the display of promoted names by setting the optional argument, prom_name, to True.

prob.model.list_outputs(prom_name=True)
0 Explicit Output(s) in 'model'


2 Implicit Output(s) in 'model'

varname  val   prom_name  
-------  ----  -----------
sub
  comp1
    x    [3.]  sub.comp1.x
  comp2
    x    [3.]  sub.comp2.x
[('sub.comp1.x', {'val': array([3.]), 'prom_name': 'sub.comp1.x'}),
 ('sub.comp2.x', {'val': array([3.]), 'prom_name': 'sub.comp2.x'})]

List Variables Filtered by Name

You can use the includes and excludes optional arguments to filter what variables are returned from System.list_inputs and System.list_outputs. Here are some short examples showing this feature.

# list inputs
inputs = prob.model.list_inputs(val=False, includes=['*comp2*',])
3 Input(s) in 'model'

varname
-------
sub
  comp2
    a  
    b  
    c  
inputs = prob.model.list_inputs(val=False, excludes=['*comp2*',])
3 Input(s) in 'model'

varname
-------
sub
  comp1
    a  
    b  
    c  
# list only explicit outputs
outputs = prob.model.list_outputs(implicit=False, val=False, includes=['*b',])
outputs = prob.model.list_outputs(implicit=False, val=False, excludes=['*b',])
0 Explicit Output(s) in 'model'

List Variables Filtered by Tags

When you add inputs and outputs to components, you can optionally set tags on the variables. These tags can then be used to filter what variables are printed and returned by the System.list_inputs and System.list_outputs methods. Each of those methods has an optional argument tags for that purpose.

Here is a simple example to show you how this works. Imagine that a model-builder builds a model with some set of variables they expect other non-model-builder users to vary. They want to classify the inputs into two sets: “beginner” and “advanced”. The model-builder would like to write some functions that query the model for the set of beginner and advanced inputs and do some stuff with those lists (like make fancy formatted outputs or something).

import openmdao.api as om

class ActuatorDiscWithTags(om.ExplicitComponent):
    """Simple wind turbine model based on actuator disc theory"""

    def setup(self):

        # Inputs
        self.add_input('a', 0.5, desc="Induced Velocity Factor", tags="advanced")
        self.add_input('Area', 10.0, units="m**2", desc="Rotor disc area", tags="basic")
        self.add_input('rho', 1.225, units="kg/m**3", desc="air density", tags="advanced")
        self.add_input('Vu', 10.0, units="m/s",
                       desc="Freestream air velocity, upstream of rotor", tags="basic")

        # Outputs
        self.add_output('Vr', 0.0, units="m/s",
                        desc="Air velocity at rotor exit plane")
        self.add_output('Vd', 0.0, units="m/s",
                        desc="Slipstream air velocity, downstream of rotor")
        self.add_output('Ct', 0.0, desc="Thrust Coefficient")
        self.add_output('thrust', 0.0, units="N",
                        desc="Thrust produced by the rotor")
        self.add_output('Cp', 0.0, desc="Power Coefficient")
        self.add_output('power', 0.0, units="W", desc="Power produced by the rotor")

    def setup_partials(self):
        self.declare_partials('Vr', ['a', 'Vu'])
        self.declare_partials('Vd', 'a')
        self.declare_partials('Ct', 'a')
        self.declare_partials('thrust', ['a', 'Area', 'rho', 'Vu'])
        self.declare_partials('Cp', 'a')
        self.declare_partials('power', ['a', 'Area', 'rho', 'Vu'])

    def compute(self, inputs, outputs):
        """ Considering the entire rotor as a single disc that extracts
        velocity uniformly from the incoming flow and converts it to
        power."""

        a = inputs['a']
        Vu = inputs['Vu']

        qA = .5 * inputs['rho'] * inputs['Area'] * Vu ** 2

        outputs['Vd'] = Vd = Vu * (1 - 2 * a)
        outputs['Vr'] = .5 * (Vu + Vd)

        outputs['Ct'] = Ct = 4 * a * (1 - a)
        outputs['thrust'] = Ct * qA

        outputs['Cp'] = Cp = Ct * (1 - a)
        outputs['power'] = Cp * qA * Vu

    def compute_partials(self, inputs, J):
        """ Jacobian of partial derivatives."""

        a = inputs['a']
        Vu = inputs['Vu']
        Area = inputs['Area']
        rho = inputs['rho']

        # pre-compute commonly needed quantities
        a_times_area = a * Area
        one_minus_a = 1.0 - a
        a_area_rho_vu = a_times_area * rho * Vu

        J['Vr', 'a'] = -Vu
        J['Vr', 'Vu'] = one_minus_a

        J['Vd', 'a'] = -2.0 * Vu

        J['Ct', 'a'] = 4.0 - 8.0 * a

        J['thrust', 'a'] = .5 * rho * Vu**2 * Area * J['Ct', 'a']
        J['thrust', 'Area'] = 2.0 * Vu**2 * a * rho * one_minus_a
        J['thrust', 'rho'] = 2.0 * a_times_area * Vu ** 2 * (one_minus_a)
        J['thrust', 'Vu'] = 4.0 * a_area_rho_vu * (one_minus_a)

        J['Cp', 'a'] = 4.0 * a * (2.0 * a - 2.0) + 4.0 * (one_minus_a)**2

        J['power', 'a'] = 2.0 * Area * Vu**3 * a * rho * (
        2.0 * a - 2.0) + 2.0 * Area * Vu**3 * rho * one_minus_a ** 2
        J['power', 'Area'] = 2.0 * Vu**3 * a * rho * one_minus_a ** 2
        J['power', 'rho'] = 2.0 * a_times_area * Vu ** 3 * (one_minus_a)**2
        J['power', 'Vu'] = 6.0 * Area * Vu**2 * a * rho * one_minus_a**2


# build the model
prob = om.Problem()
indeps = prob.model.add_subsystem('indeps', om.IndepVarComp(), promotes=['*'])
indeps.add_output('a', .5, tags="advanced")
indeps.add_output('Area', 10.0, units='m**2', tags="basic")
indeps.add_output('rho', 1.225, units='kg/m**3', tags="advanced")
indeps.add_output('Vu', 10.0, units='m/s', tags="basic")

prob.model.add_subsystem('a_disk', ActuatorDiscWithTags(),
                        promotes_inputs=['a', 'Area', 'rho', 'Vu'])

# setup the optimization
prob.driver = om.ScipyOptimizeDriver()
prob.driver.options['optimizer'] = 'SLSQP'

prob.model.add_design_var('a', lower=0., upper=1.)
# negative one so we maximize the objective
prob.model.add_objective('a_disk.Cp', scaler=-1)

prob.setup()
prob.run_driver()
Optimization terminated successfully.    (Exit mode 0)
            Current function value: -0.5925925906659251
            Iterations: 5
            Function evaluations: 6
            Gradient evaluations: 5
Optimization Complete
-----------------------------------
False
prob.model.list_inputs(tags='basic', units=True, shape=True)
2 Input(s) in 'model'

varname  val    units  shape
-------  -----  -----  -----
a_disk
  Area   [10.]  m**2   (1,) 
  Vu     [10.]  m/s    (1,) 
[('a_disk.Area', {'units': 'm**2', 'shape': (1,), 'val': array([10.])}),
 ('a_disk.Vu', {'units': 'm/s', 'shape': (1,), 'val': array([10.])})]
prob.model.list_inputs(tags=['basic','advanced'], units=True, shape=True)
4 Input(s) in 'model'

varname  val           units    shape
-------  ------------  -------  -----
a_disk
  a      [0.33335528]  None     (1,) 
  Area   [10.]         m**2     (1,) 
  rho    [1.225]       kg/m**3  (1,) 
  Vu     [10.]         m/s      (1,) 
[('a_disk.a', {'units': None, 'shape': (1,), 'val': array([0.33335528])}),
 ('a_disk.Area', {'units': 'm**2', 'shape': (1,), 'val': array([10.])}),
 ('a_disk.rho', {'units': 'kg/m**3', 'shape': (1,), 'val': array([1.225])}),
 ('a_disk.Vu', {'units': 'm/s', 'shape': (1,), 'val': array([10.])})]
prob.model.list_outputs(tags='basic', units=False, shape=False)
2 Explicit Output(s) in 'model'

varname  val  
-------  -----
indeps
  Area   [10.]
  Vu     [10.]


0 Implicit Output(s) in 'model'
[('indeps.Area', {'val': array([10.])}), ('indeps.Vu', {'val': array([10.])})]
prob.model.list_outputs(tags=['basic','advanced'], units=False, shape=False)
4 Explicit Output(s) in 'model'

varname  val         
-------  ------------
indeps
  a      [0.33335528]
  Area   [10.]       
  rho    [1.225]     
  Vu     [10.]       


0 Implicit Output(s) in 'model'
[('indeps.a', {'val': array([0.33335528])}),
 ('indeps.Area', {'val': array([10.])}),
 ('indeps.rho', {'val': array([1.225])}),
 ('indeps.Vu', {'val': array([10.])})]

Notice that if you only have one tag, you can set the argument tags to a string. If you have more than one tag, you use a list of strings.

This example showed how to add tags when using the add_input and add_output methods. You can also add tags to IndepVarComp and ExecComp Components using code like this:

comp = om.IndepVarComp('indep_var', tags='tag1')
ec = om.ExecComp('y=x+z+1.',
                  x={'val': 1.0, 'units': 'm', 'tags': 'tagx'},
                  y={'units': 'm', 'tags': ['tagy','tagm']},
                  z={'val': 2.0, 'tags': 'tagz'},
                  )

Note that outputs of IndepVarComp are always tagged with indep_var_comp.

List Residuals Above a Tolerance

In some cases, it might be convenient to only list variables whose residuals are above a given tolerance. The System.list_outputs method provides an optional argument, residuals_tol for this purpose.

import openmdao.api as om
from openmdao.test_suite.components.sellar import SellarImplicitDis1, SellarImplicitDis2
prob = om.Problem()
model = prob.model

model.add_subsystem('p1', om.IndepVarComp('x', 1.0))
model.add_subsystem('d1', SellarImplicitDis1())
model.add_subsystem('d2', SellarImplicitDis2())
model.connect('d1.y1', 'd2.y1')
model.connect('d2.y2', 'd1.y2')

model.nonlinear_solver = om.NewtonSolver(solve_subsystems=False)
model.nonlinear_solver.options['maxiter'] = 5
model.linear_solver = om.ScipyKrylov()
model.linear_solver.precon = om.LinearBlockGS()

prob.setup()
prob.set_solver_print(level=-1)

prob.run_model()

outputs = model.list_outputs(residuals_tol=0.01, residuals=True)
0 Explicit Output(s) in 'model'


1 Implicit Output(s) in 'model'

varname  val          resids      
-------  -----------  ------------
d2
  y2     [0.2323928]  [0.01679515]
print(outputs)
[('d2.y2', {'val': array([0.2323928]), 'resids': array([0.01679515])})]

List Additional Variable Metadata

The list_outputs() method has many options to also display units, shape, bounds (lower and upper), and scaling (res, res0, and res_ref) for the variables.

import openmdao.api as om

prob = om.Problem()
model = prob.model

model.add_subsystem('p1', om.IndepVarComp('x', 12.0,
                                          lower=1.0, upper=100.0,
                                          ref=1.1, ref0=2.1,
                                          units='inch',
                                          ))
model.add_subsystem('p2', om.IndepVarComp('y', 1.0,
                                          lower=2.0, upper=200.0,
                                          ref=1.2, res_ref=2.2,
                                          units='ft',
                                          ))
model.add_subsystem('comp', om.ExecComp('z=x+y',
                                        x={'val': 0.0, 'units': 'inch'},
                                        y={'val': 0.0, 'units': 'inch'},
                                        z={'val': 0.0, 'units': 'inch'}))
model.connect('p1.x', 'comp.x')
model.connect('p2.y', 'comp.y')

prob.setup()
prob.set_solver_print(level=0)
prob.run_model()

inputs = prob.model.list_inputs(units=True)
2 Input(s) in 'model'

varname  val    units
-------  -----  -----
comp
  x      [12.]  inch 
  y      [12.]  inch 
print(inputs)
[('comp.x', {'units': 'inch', 'val': array([12.])}), ('comp.y', {'units': 'inch', 'val': array([12.])})]
outputs = prob.model.list_outputs(implicit=False,
                                  val=True,
                                  units=True,
                                  shape=True,
                                  bounds=True,
                                  residuals=True,
                                  scaling=True,
                                  hierarchical=False,
                                  print_arrays=False)
3 Explicit Output(s) in 'model'
varname val resids units shape lower upper ref ref0 res_ref
p1.x 12 0 inch (1,) 1 100 1.1 2.1 1.1
p2.y 1 0 ft (1,) 2 200 1.2 0 2.2
comp.z 24 0 inch (1,) 1 0 1
print(sorted(outputs))
[('comp.z', {'val': array([24.]), 'units': 'inch', 'shape': (1,), 'lower': None, 'upper': None, 'ref': 1.0, 'ref0': 0.0, 'res_ref': 1.0, 'resids': array([0.])}), ('p1.x', {'val': array([12.]), 'units': 'inch', 'shape': (1,), 'lower': array([1.]), 'upper': array([100.]), 'ref': 1.1, 'ref0': 2.1, 'res_ref': 1.1, 'resids': array([0.])}), ('p2.y', {'val': array([1.]), 'units': 'ft', 'shape': (1,), 'lower': array([2.]), 'upper': array([200.]), 'ref': 1.2, 'ref0': 0.0, 'res_ref': 2.2, 'resids': array([0.])})]
outputs = prob.model.list_outputs(implicit=False,
                                  val=True,
                                  units=True,
                                  shape=True,
                                  bounds=True,
                                  residuals=True,
                                  scaling=True,
                                  hierarchical=True,
                                  print_arrays=False)
3 Explicit Output(s) in 'model'

varname  val    resids  units  shape  lower  upper   ref  ref0  res_ref
-------  -----  ------  -----  -----  -----  ------  ---  ----  -------
p1
  x      [12.]  [0.]    inch   (1,)   [1.]   [100.]  1.1  2.1   1.1    
p2
  y      [1.]   [0.]    ft     (1,)   [2.]   [200.]  1.2  0.0   2.2    
comp
  z      [24.]  [0.]    inch   (1,)   None   None    1.0  0.0   1.0    

List Global Shape

When working with Distributed Components, it may also be useful to display the global shape of a variable as well as the shape on the current processor. Note that this information is not available until after the model has been completely set up and run.

Note

This feature requires MPI, and may not be able to be run on Colab.

%%px

import numpy as np
import openmdao.api as om
from openmdao.test_suite.components.distributed_components import DistribComp, Summer

size = 15

model = om.Group()
indep = model.add_subsystem("indep", om.IndepVarComp())
indep.add_output('x', np.zeros(size), distributed=True)
model.add_subsystem("C2", DistribComp(size=size))
model.add_subsystem("C3", Summer(size=size))

model.connect('indep.x', 'C2.invec')
model.connect('C2.outvec', 'C3.invec', src_indices=om.slicer[:])

prob = om.Problem(model)
prob.setup()

# prior to model execution, the global shape of a distributed variable is not available
# and only the local portion of the value is available
model.C2.list_inputs(hierarchical=False, shape=True, global_shape=True, print_arrays=True)
[stdout:0] 1 Input(s) in 'C2'
[output:0]
varname val shape global_shape
C2.invec [1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] (4,) (15,)
Out[0:56]: 
[('invec',
  {'val': array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]),
   'shape': (4,),
   'global_shape': (15,)})]
Out[1:56]: []
Out[2:56]: []
Out[3:56]: []
%%px

model.C2.list_outputs(hierarchical=False, shape=True, global_shape=True, print_arrays=True)

prob['indep.x'] = np.ones(size)
prob.run_model()

# after model execution, the global shape of a distributed variable is available
# and the complete global value is available
model.C2.list_inputs(hierarchical=False, shape=True, global_shape=True, print_arrays=True)
[stdout:0] 
1 Explicit Output(s) in 'C2'
0 Implicit Output(s) in 'C2'


1 Input(s) in 'C2'
[output:0]
varname val shape global_shape
C2.outvec[1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] (4,) (15,)
varname val shape global_shape
C2.invec [1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] (4,) (15,)
Out[0:57]: 
[('invec',
  {'shape': (4,),
   'global_shape': (15,),
   'val': array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])})]
Out[1:57]: []
Out[2:57]: []
Out[3:57]: []
%%px

model.C2.list_outputs(hierarchical=False, shape=True, global_shape=True, print_arrays=True)

# note that the shape of the input variable for the non-distributed Summer component
# is different on each processor, use the all_procs argument to display on all processors
model.C3.list_inputs(hierarchical=False, shape=True, global_shape=True, print_arrays=True, all_procs=True)
[stdout:0] 
1 Explicit Output(s) in 'C2'
0 Implicit Output(s) in 'C2'


1 Input(s) in 'C3'
[stdout:1] 1 Input(s) in 'C3'
[stdout:2] 1 Input(s) in 'C3'
[stdout:3] 1 Input(s) in 'C3'
[output:0]
varname val shape global_shape
C2.outvec[ 2. 2. 2. 2. -3. -3. -3. -3. -3. -3. -3. -3. -3. -3. -3.] (4,) (15,)
varname val shape global_shape
C3.invec [ 2. 2. 2. 2. -3. -3. -3. -3. -3. -3. -3. -3. -3. -3. -3.] (15,) (15,)
[output:1]
varname val shape global_shape
C3.invec [ 2. 2. 2. 2. -3. -3. -3. -3. -3. -3. -3. -3. -3. -3. -3.] (15,) (15,)
[output:2]
varname val shape global_shape
C3.invec [ 2. 2. 2. 2. -3. -3. -3. -3. -3. -3. -3. -3. -3. -3. -3.] (15,) (15,)
[output:3]
varname val shape global_shape
C3.invec [ 2. 2. 2. 2. -3. -3. -3. -3. -3. -3. -3. -3. -3. -3. -3.] (15,) (15,)
Out[0:58]: 
[('invec',
  {'shape': (15,),
   'global_shape': (15,),
   'val': array([ 2.,  2.,  2.,  2., -3., -3., -3., -3., -3., -3., -3., -3., -3.,
          -3., -3.])})]
Out[1:58]: 
[('invec',
  {'shape': (15,),
   'global_shape': (15,),
   'val': array([ 2.,  2.,  2.,  2., -3., -3., -3., -3., -3., -3., -3., -3., -3.,
          -3., -3.])})]
Out[2:58]: 
[('invec',
  {'shape': (15,),
   'global_shape': (15,),
   'val': array([ 2.,  2.,  2.,  2., -3., -3., -3., -3., -3., -3., -3., -3., -3.,
          -3., -3.])})]
Out[3:58]: 
[('invec',
  {'shape': (15,),
   'global_shape': (15,),
   'val': array([ 2.,  2.,  2.,  2., -3., -3., -3., -3., -3., -3., -3., -3., -3.,
          -3., -3.])})]
%%px

print(prob['C3.sum'])
[stdout:0] [-25.]
[stdout:1] [-25.]
[stdout:2] [-25.]
[stdout:3] [-25.]

Listing Problem Variables

Problem has a method list_problem_vars which prints out the values and metadata for design, constraint, and objective variables.

.. automethod:: openmdao.core.problem.Problem.list_problem_vars
    :noindex:

You can optionally print out a variety of metadata. In this example, all the metadata is printed. The print_arrays option is also set to true so that full array values are printed.

import numpy as np
import openmdao.api as om
from openmdao.test_suite.components.sellar import SellarDerivatives

prob = om.Problem(model=SellarDerivatives())
model = prob.model
model.nonlinear_solver = om.NonlinearBlockGS()

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

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)

prob.setup()
prob.run_driver()
NL: NLBGS Converged in 8 iterations
NL: NLBGS Converged in 1 iterations
NL: NLBGS Converged in 9 iterations
NL: NLBGS Converged in 10 iterations
NL: NLBGS Converged in 10 iterations
NL: NLBGS Converged in 9 iterations
NL: NLBGS Converged in 6 iterations
Optimization terminated successfully.    (Exit mode 0)
            Current function value: 3.1833939517255843
            Iterations: 6
            Function evaluations: 6
            Gradient evaluations: 6
Optimization Complete
-----------------------------------
False
prob.list_problem_vars(print_arrays=True,
                       desvar_opts=['lower', 'upper', 'ref', 'ref0',
                                    'indices', 'adder', 'scaler',
                                    'parallel_deriv_color'],
                       cons_opts=['lower', 'upper', 'equals', 'ref', 'ref0',
                                  'indices', 'adder', 'scaler', 'linear'],
                       objs_opts=['ref', 'ref0',
                                  'indices', 'adder', 'scaler',
                                  'parallel_deriv_color',
                                  'cache_linear_solution'])
----------------
Design Variables
----------------
name  val                   size  lower   upper                 ref   ref0  indices  adder  scaler  parallel_deriv_color  
----  --------------------  ----  ------  --------------------  ----  ----  -------  -----  ------  -------------------- 
z     |1.9776388834867473|  2     |10.0|  |14.142135623730951|  None  None  None     None   None    None                  
      val:
      array([1.97763888, 0.        ])

      lower:
      array([-10.,   0.])

      upper:
      array([10., 10.])

x     [0.]                  1     0.0     10.0                  None  None  None     None   None    None                  

-----------
Constraints
-----------
name           val                size  lower   upper  equals  ref   ref0  indices  adder  scaler  linear  
-------------  -----------------  ----  ------  -----  ------  ----  ----  -------  -----  ------  ------ 
con_cmp1.con1  [-8.60893579e-11]  1     -1e+30  0.0    None    None  None  None     None   None    False   
con_cmp2.con2  [-20.24472223]     1     -1e+30  0.0    None    None  None  None     None   None    False   

----------
Objectives
----------
name         val           size  ref   ref0  indices  adder  scaler  parallel_deriv_color  cache_linear_solution  
-----------  ------------  ----  ----  ----  -------  -----  ------  --------------------  --------------------- 
obj_cmp.obj  [3.18339395]  1     None  None  None     None   None    None                  False