Error Checking Partial Derivatives

Simple Example Using Problem.check_partial_derivatives

OpenMDAO provides a way for a Component developer to verify that their partial derivatives, for each individual component, are correct.

Problem has a method, check_partial_derivatives, that checks partial derivatives comprehensively for all Components in your model (as long as you didn’t set deriv_options[‘type’] = ‘fd’ on that component). To do this check, the framework compares the analytic result against a finite difference result. This means that the check_partial_derivatives function can be quite computationally expensive. So use it to check your work, but don’t leave the call in your production run scripts.

Note

check_partial_derivatives has three optional arguments,

out_stream, lets you define where the results of the check are written to. The default is sys.stdout. This example explicitly sets the value of out_stream to sys.stdout to make our automated doc tests work correctly. You would only set this argument if you wanted to pipe it to a file or some other stream.

comps is a list of component pathnames, which you can specify if you want to only check the gradients on a subset of the components as a time saver while debugging

compact_print can be set to True for more compact results (essentially each input/output pair is summarized on one line.) You should be careful with this, particuarly for arrays where an important difference in a single array element might not be noticed when looking purely at the norm of the difference between the arrays.

Here is example code for a model that consists of a single Component, SimpleArrayComp. After setting up the model, it runs `check_partial_derivatives on the Problem.

import numpy as np
import sys

from openmdao.api import IndepVarComp, Problem, Group
from openmdao.test.simple_comps import SimpleArrayComp

prob = Problem()
prob.root = Group()
prob.root.add('comp', SimpleArrayComp())
prob.root.add('p1', IndepVarComp('x', np.ones([2])))

prob.root.connect('p1.x', 'comp.x')

prob.setup(check=False)
prob.run()

data = prob.check_partial_derivatives(out_stream=sys.stdout)

This code generates output that looks like this:

Partial Derivatives Check

-------------------
Component: 'comp'
-------------------
  comp: 'y' wrt 'x'

    Forward Magnitude : 9.327379e+00
    Reverse Magnitude : 9.327379e+00
         Fd Magnitude : 9.327379e+00 (fd:forward)

    Absolute Error (Jfor - Jfd) : 1.769949e-09
    Absolute Error (Jrev - Jfd) : 1.769949e-09
    Absolute Error (Jfor - Jrev): 0.000000e+00

    Relative Error (Jfor - Jfd) : 1.897585e-10
    Relative Error (Jrev - Jfd) : 1.897585e-10
    Relative Error (Jfor - Jrev): 0.000000e+00

    Raw Forward Derivative (Jfor)

[[ 2.  7.]
 [ 5. -3.]]

    Raw Reverse Derivative (Jrev)

[[ 2.  7.]
 [ 5. -3.]]

    Raw FD Derivative (Jfd)

[[ 2.  7.]
 [ 5. -3.]]
...

You can control the finite difference used in the check by setting some additional options in the deriv_options dictionary.

# Set form to 'central', 'forward', or 'reverse'
prob.root.comp.deriv_options['check_form'] = 'central'

# Can check with 'fd' (finite difference) or 'cs' (complex step)
prob.root.comp.deriv_options['check_type'] = 'fd'

# Can be 'relative' or 'absolute'
prob.root.comp.deriv_options['check_step_calc'] = 'relative'

# Set a step size
prob.root.comp.deriv_options['check_step_size'] = 1.0e-5

You can also use the check_partial_derivatives method to compare two different kinds of finite difference executions (e.g., forward and central) with each other or to complex step. Do this by setting ‘type’ in your component to ‘fd’ or ‘cs’. The options for this second check are the regular ‘fd’ options ‘step_size’, ‘form’, ‘type’, and ‘step_calc’.

import numpy as np
import sys

from openmdao.api import IndepVarComp, Problem, Group
from openmdao.test.simple_comps import SimpleArrayComp

prob = Problem()
prob.root = Group()
prob.root.add('comp', SimpleArrayComp())
prob.root.add('p1', IndepVarComp('x', np.ones([2])))

prob.root.connect('p1.x', 'comp.x')

# Turn on fd in comp using forward difference
prob.root.comp.deriv_options['type'] = 'fd'
prob.root.comp.deriv_options['form'] = 'forward'

# Compare the fd with central difference
prob.root.comp.deriv_options['check_form'] = 'central'

prob.setup(check=False)
prob.run()

data = prob.check_partial_derivatives(out_stream=sys.stdout)

This code generates output that looks like this:

Partial Derivatives Check

-------------------
Component: 'comp'
-------------------
  comp: 'y' wrt 'x'

    Fwd/Rev Magnitude : Component supplies no analytic derivatives.
         Fd Magnitude : 9.327379e+00 (fd:central)
        Fd2 Magnitude : 9.327379e+00 (fd:forward)

    Absolute Error (Jfd2 - Jfd): 2.551098e-09

    Relative Error (Jfd2 - Jfd) : 2.735064e-10

    Raw FD Derivative (Jfd)

[[ 2.  7.]
 [ 5. -3.]]

    Raw FD Check Derivative (Jfd2)

[[ 2.  7.]
 [ 5. -3.]]
...

Return Value of check_partial_derivatives

The method check_partial_derivatives returns a dict of dicts of dicts with comprehensive information about the check of the partial derivatives. You can use this data to write scripts to interact with the derivatives check information if you want.

The keys of the nested dicts are:

Dict Key Example
Component name ‘subcomp’
A tuple of strings indicating the (output, input) variables (‘y1’, ‘x2’)
One of [‘rel error’, ‘abs error’, ‘magnitude’, ‘fdstep’] ‘rel error’

The type of the values depends on key of the innermost dict.

Key of Innermost Dict Type of value
‘rel error’, ‘abs error’, ‘magnitude’ A tuple containing norms for (forward - finite differences), ( adjoint - finite differences), (forward - adjoint) using the best case fdstep
‘J_fd’, ‘J_fwd’, ‘J_rev’, ‘J_fd2’* A numpy array representing the computed Jacobian for the three different methods of computation