Computing Total Derivatives#
Problem has a method, compute_totals
, that allows you to compute the unscaled total derivative values for a model.
If the model approximated its Jacobian, the method uses an approximation method.
- Problem.compute_totals(of=None, wrt=None, return_format='flat_dict', debug_print=False, driver_scaling=False, use_abs_names=False, get_remote=True, coloring_info=None)[source]
Compute derivatives of desired quantities with respect to desired inputs.
- Parameters:
- oflist of variable name str or None
Variables whose derivatives will be computed. Default is None, which uses the driver’s objectives and constraints.
- wrtlist of variable name str or None
Variables with respect to which the derivatives will be computed. Default is None, which uses the driver’s desvars.
- return_formatstr
Format to return the derivatives. Can be ‘dict’, ‘flat_dict’, or ‘array’. Default is a ‘flat_dict’, which returns them in a dictionary whose keys are tuples of form (of, wrt).
- debug_printbool
Set to True to print out some debug information during linear solve.
- driver_scalingbool
When True, return derivatives that are scaled according to either the adder and scaler or the ref and ref0 values that were specified when add_design_var, add_objective, and add_constraint were called on the model. Default is False, which is unscaled.
- use_abs_namesbool
This is deprecated and has no effect.
- get_remotebool
If True, the default, the full distributed total jacobian will be retrieved.
- coloring_infoColoringMeta, None, or False
If False, do no coloring. If None, use driver coloring info to compute the coloring. Otherwise use the given coloring info object to provide the coloring, if it exists.
- Returns:
- object
Derivatives in form requested by ‘return_format’.
Usage#
Here is a simple example of using compute_totals
:
Paraboloid
class definition
class Paraboloid(om.ExplicitComponent):
"""
Evaluates the equation f(x,y) = (x-3)^2 + xy + (y+4)^2 - 3.
"""
def setup(self):
self.add_input('x', val=0.0)
self.add_input('y', val=0.0)
self.add_output('f_xy', val=0.0)
def setup_partials(self):
self.declare_partials('*', '*')
def compute(self, inputs, outputs):
"""
f(x,y) = (x-3)^2 + xy + (y+4)^2 - 3
Optimal solution (minimum): x = 6.6667; y = -7.3333
"""
x = inputs['x']
y = inputs['y']
outputs['f_xy'] = (x-3.0)**2 + x*y + (y+4.0)**2 - 3.0
def compute_partials(self, inputs, partials):
"""
Jacobian for our paraboloid.
"""
x = inputs['x']
y = inputs['y']
partials['f_xy', 'x'] = 2.0*x - 6.0 + y
partials['f_xy', 'y'] = 2.0*y + 8.0 + x
import openmdao.api as om
from openmdao.test_suite.components.paraboloid import Paraboloid
prob = om.Problem()
model = prob.model
model.add_subsystem('comp', Paraboloid())
model.set_input_defaults('comp.x', 3.0)
model.set_input_defaults('comp.y', -4.0)
prob.setup()
prob.run_model()
totals = prob.compute_totals(of=['comp.f_xy'], wrt=['comp.x', 'comp.y'])
print(totals[('comp.f_xy', 'comp.x')][0][0])
-4.0
print(totals[('comp.f_xy', 'comp.y')][0][0])
3.0
totals = prob.compute_totals(of=['comp.f_xy'], wrt=['comp.x', 'comp.y'], return_format='dict')
print(totals['comp.f_xy']['comp.x'][0][0])
-4.0
print(totals['comp.f_xy']['comp.y'][0][0])
3.0
By default, compute_totals
returns the derivatives unscaled, but you can also request that they be scaled by the driver scale values declared when the des_vars, objectives, or constraints are added:
import openmdao.api as om
from openmdao.test_suite.components.paraboloid import Paraboloid
prob = om.Problem()
model = prob.model
model.add_subsystem('comp', Paraboloid())
model.set_input_defaults('comp.x', 3.0)
model.set_input_defaults('comp.y', -4.0)
model.add_design_var('comp.x', 3.0, ref0=50.0)
model.add_design_var('comp.y', -4.0)
model.add_objective('comp.f_xy')
prob.setup()
prob.run_model()
totals = prob.compute_totals(of=['comp.f_xy'], wrt=['comp.x', 'comp.y'], driver_scaling=True)
print(totals[('comp.f_xy', 'comp.x')][0][0])
196.00000000000003
print(totals[('comp.f_xy', 'comp.y')][0][0])
3.0