Skip to content

Commit

Permalink
Merge f7e4000 into 60e676d
Browse files Browse the repository at this point in the history
  • Loading branch information
Kenneth-T-Moore committed Aug 1, 2017
2 parents 60e676d + f7e4000 commit 6e33d17
Show file tree
Hide file tree
Showing 5 changed files with 148 additions and 7 deletions.
18 changes: 12 additions & 6 deletions openmdao/core/problem.py
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ def setup(self, vector_class=DefaultVector, check=True, logger=None, mode='auto'

def check_partials(self, logger=None, comps=None, compact_print=False,
abs_err_tol=1e-6, rel_err_tol=1e-6, global_options=None,
force_dense=True):
force_dense=True, suppress_output=False):
"""
Check partial derivatives comprehensively for all components in your model.
Expand All @@ -334,6 +334,8 @@ def check_partials(self, logger=None, comps=None, compact_print=False,
'form', 'step', 'step_calc', and 'method' can be specified in this way.
force_dense : bool
If True, analytic derivatives will be coerced into arrays.
suppress_output : bool
Set to True to suppress all output.
Returns
-------
Expand Down Expand Up @@ -593,14 +595,15 @@ def check_partials(self, logger=None, comps=None, compact_print=False,
partials_data = {comp_name: dict(outer) for comp_name, outer in iteritems(partials_data)}

logging.getLogger().setLevel(logging.INFO)
_assemble_derivative_data(partials_data, rel_err_tol, abs_err_tol, logger,
compact_print, comps, global_options)
if not suppress_output:
_assemble_derivative_data(partials_data, rel_err_tol, abs_err_tol, logger,
compact_print, comps, global_options)

return partials_data

def check_total_derivatives(self, of=None, wrt=None, logger=None, compact_print=False,
abs_err_tol=1e-6, rel_err_tol=1e-6, method='fd', step=1e-6,
form='forward', step_calc='abs'):
form='forward', step_calc='abs', suppress_output=False):
"""
Check total derivatives for the model vs. finite difference.
Expand Down Expand Up @@ -631,6 +634,8 @@ def check_total_derivatives(self, of=None, wrt=None, logger=None, compact_print=
Form for finite difference, can be 'forward', 'backward', or 'central'.
step_calc : string
Step type for finite difference, can be 'abs' for absolute', or 'rel' for relative.
suppress_output : bool
Set to True to suppress all output.
Returns
-------
Expand Down Expand Up @@ -682,8 +687,9 @@ def check_total_derivatives(self, of=None, wrt=None, logger=None, compact_print=
fd_args['method'] = 'fd'

logging.getLogger().setLevel(logging.INFO)
_assemble_derivative_data(data, rel_err_tol, abs_err_tol, logger, compact_print,
[model], fd_args, totals=True)
if not suppress_output:
_assemble_derivative_data(data, rel_err_tol, abs_err_tol, logger, compact_print,
[model], fd_args, totals=True)
return data['']

def compute_total_derivs(self, of=None, wrt=None, return_format='flat_dict'):
Expand Down
96 changes: 96 additions & 0 deletions openmdao/core/tests/test_check_derivs.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,42 @@ def compute_partials(self, inputs, outputs, partials):
assert_rel_error(self, x2_error.forward, 9., 1e-8)
assert_rel_error(self, x2_error.reverse, 9., 1e-8)

def test_feature_check_partials_suppress(self):
class MyComp(ExplicitComponent):
def setup(self):
self.add_input('x1', 3.0)
self.add_input('x2', 5.0)

self.add_output('y', 5.5)

def compute(self, inputs, outputs):
""" Doesn't do much. """
outputs['y'] = 3.0*inputs['x1'] + 4.0*inputs['x2']

def compute_partials(self, inputs, outputs, partials):
"""Intentionally incorrect derivative."""
J = partials
J['y', 'x1'] = np.array([4.0])
J['y', 'x2'] = np.array([40])

prob = Problem()
prob.model = Group()

prob.model.add_subsystem('p1', IndepVarComp('x1', 3.0))
prob.model.add_subsystem('p2', IndepVarComp('x2', 5.0))
prob.model.add_subsystem('comp', MyComp())

prob.model.connect('p1.x1', 'comp.x1')
prob.model.connect('p2.x2', 'comp.x2')

prob.set_solver_print(level=0)

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

data = prob.check_partials(suppress_output=True)
print(data)

def test_component_only(self):
class MyComp(ExplicitComponent):
def setup(self):
Expand Down Expand Up @@ -145,6 +181,38 @@ def compute_partials(self, inputs, outputs, partials):
self.assertFalse(lines[y_wrt_x1_line+6].endswith('*'),
msg='Error flag not expected in output but displayed')

def test_component_only_suppress(self):
class MyComp(ExplicitComponent):
def setup(self):
self.add_input('x1', 3.0)
self.add_input('x2', 5.0)

self.add_output('y', 5.5)

def compute(self, inputs, outputs):
""" Doesn't do much. """
outputs['y'] = 3.0*inputs['x1'] + 4.0*inputs['x2']

def compute_partials(self, inputs, outputs, partials):
"""Intentionally incorrect derivative."""
J = partials
J['y', 'x1'] = np.array([4.0])
J['y', 'x2'] = np.array([40])

prob = Problem()
prob.model = MyComp()

prob.set_solver_print(level=0)

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

testlogger = TestLogger()
data = prob.check_partials(logger=testlogger, suppress_output=True)

lines = testlogger.get('info')
self.assertEqual(len(lines), 0)

def test_missing_entry(self):
class MyComp(ExplicitComponent):
def setup(self):
Expand Down Expand Up @@ -483,5 +551,33 @@ def test_cs(self):
assert_rel_error(self, totals['con_cmp2.con2', 'px.x']['J_fwd'], [[0.09692762]], 1e-5)
assert_rel_error(self, totals['con_cmp2.con2', 'px.x']['J_fd'], [[0.09692762]], 1e-5)

def test_cs_suppress(self):
prob = Problem()
prob.model = SellarDerivatives()
prob.model.nonlinear_solver = NonlinearBlockGS()

prob.model.add_design_var('x', lower=-100, upper=100)
prob.model.add_design_var('z', lower=-100, upper=100)
prob.model.add_objective('obj')
prob.model.add_constraint('con1', upper=0.0)
prob.model.add_constraint('con2', upper=0.0)

prob.set_solver_print(level=0)

prob.setup(force_alloc_complex=True)

# We don't call run_driver() here because we don't
# actually want the optimizer to run
prob.run_model()

# check derivatives with complex step and a larger step size.
testlogger = TestLogger()
totals = prob.check_total_derivatives(method='cs', step=1.0e-1, logger=testlogger,
suppress_output=True)

lines = testlogger.get('info')

self.assertEqual(len(lines), 0)

if __name__ == "__main__":
unittest.main()
21 changes: 21 additions & 0 deletions openmdao/core/tests/test_problem.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,27 @@ def test_feature_check_total_derivatives_from_driver(self):
# check derivatives of all obj+constraints w.r.t all design variables
prob.check_total_derivatives()

def test_feature_check_total_derivatives_suppress(self):
prob = Problem()
prob.model = SellarDerivatives()
prob.model.nonlinear_solver = NonlinearBlockGS()

prob.model.add_design_var('x', lower=-100, upper=100)
prob.model.add_design_var('z', lower=-100, upper=100)
prob.model.add_objective('obj')
prob.model.add_constraint('con1', upper=0.0)
prob.model.add_constraint('con2', upper=0.0)

prob.setup()

# We don't call run_driver() here because we don't
# actually want the optimizer to run
prob.run_model()

# check derivatives of all obj+constraints w.r.t all design variables
totals = prob.check_total_derivatives(suppress_output=True)
print(totals)

def test_feature_check_total_derivatives_cs(self):
prob = Problem()
prob.model = SellarDerivatives()
Expand Down
13 changes: 12 additions & 1 deletion openmdao/docs/features/defining_partials/checking_partials.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,15 @@ Usage
1. When the difference between the FD derivative and the provided derivative is larger (in either a relative or absolute sense) than :code:`1e-6`, that partial derivative will be marked with a :code:`'*'`.

.. embed-test::
openmdao.core.tests.test_check_derivs.TestProblemCheckPartials.test_feature_incorrect_jacobian
openmdao.core.tests.test_check_derivs.TestProblemCheckPartials.test_feature_incorrect_jacobian

----

Turn off standard output and just view the derivatives in the return:

.. embed-test::
openmdao.core.tests.test_check_derivs.TestProblemCheckPartials.test_feature_check_partials_suppress

Related Features
-----------------
check-total-derivatives
7 changes: 7 additions & 0 deletions openmdao/docs/features/running/check_total_derivatives.rst
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@ step size to trigger the nonlinear Gauss-Seidel solver to try to converge after
.. embed-test::
openmdao.core.tests.test_problem.TestProblem.test_feature_check_total_derivatives_cs

----

Turn off standard output and just view the derivatives in the return:

.. embed-test::
openmdao.core.tests.test_problem.TestProblem.test_feature_check_total_derivatives_suppress


Related Features
-----------------
Expand Down

0 comments on commit 6e33d17

Please sign in to comment.