Skip to content

Commit

Permalink
Merge 9465d7f into 82fc360
Browse files Browse the repository at this point in the history
  • Loading branch information
DKilkenny committed Oct 7, 2020
2 parents 82fc360 + 9465d7f commit 43b1590
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 4 deletions.
15 changes: 15 additions & 0 deletions openmdao/approximation_schemes/approximation_scheme.py
@@ -1,4 +1,5 @@
"""Base class used to define the interface for derivative approximation schemes."""
import time
from collections import defaultdict
from itertools import chain
from scipy.sparse import coo_matrix
Expand Down Expand Up @@ -33,6 +34,8 @@ class ApproximationScheme(object):
Array of sizes of data chunks that make up _j_colored. (Used for MPI Allgatherv)
_j_data_offsets : ndarray of int
Array of offsets of each data chunk that makes up _j_colored. (Used for MPI Allgatherv)
_progress_out : None
Attribute to output the progress of check_totals
"""

def __init__(self):
Expand All @@ -46,6 +49,7 @@ def __init__(self):
self._j_data_offsets = None
self._approx_groups_cached_under_cs = False
self._exec_dict = defaultdict(list)
self._progress_out = None

def __repr__(self):
"""
Expand Down Expand Up @@ -296,6 +300,8 @@ def _init_approximations(self, system):
def _compute_approximations(self, system, jac, total, under_cs):
from openmdao.core.component import Component

self._progress_out = self.out_stream if hasattr(self, "out_stream") else None

# Set system flag that we're under approximation to true
system._set_approx_mode(True)

Expand Down Expand Up @@ -368,6 +374,9 @@ def _compute_approximations(self, system, jac, total, under_cs):

# now do uncolored solves
for wrt, data, col_idxs, tmpJ, idx_info, nz_rows in approx_groups:
if self._progress_out:
start_time = time.time()

J = tmpJ[wrt]
full_idxs = J['loc_outvec_idxs']
out_slices = tmpJ['@out_slices']
Expand All @@ -393,6 +402,12 @@ def _compute_approximations(self, system, jac, total, under_cs):
else:
J['data'][:, i_count] = self._transform_result(result[full_idxs])

if self._progress_out:
end_time = time.time()
self.out_stream.write(f"{fd_count+1}/{len(full_idxs)}: Checking "
f"derivatives with respect to: '{wrt} [{idxs}]' ... "
f"{round(end_time-start_time, 4)} seconds\n")

fd_count += 1

mult = self._get_multiplier(data)
Expand Down
9 changes: 6 additions & 3 deletions openmdao/core/problem.py
Expand Up @@ -5,6 +5,7 @@
import os
import logging
import weakref
import time

from collections import defaultdict, namedtuple, OrderedDict
from fnmatch import fnmatchcase
Expand Down Expand Up @@ -1404,7 +1405,7 @@ def check_partials(self, out_stream=_DEFAULT_OUT_STREAM, includes=None, excludes

def check_totals(self, of=None, wrt=None, out_stream=_DEFAULT_OUT_STREAM, compact_print=False,
driver_scaling=False, abs_err_tol=1e-6, rel_err_tol=1e-6,
method='fd', step=None, form=None, step_calc='abs'):
method='fd', step=None, form=None, step_calc='abs', show_progress=False):
"""
Check total derivatives for the model vs. finite difference.
Expand Down Expand Up @@ -1443,6 +1444,8 @@ def check_totals(self, of=None, wrt=None, out_stream=_DEFAULT_OUT_STREAM, compac
step_calc : string
Step type for finite difference, can be 'abs' for absolute', or 'rel' for relative.
Default is 'abs'.
show_progress : bool
Bool to show progress of check_totals
Returns
-------
Expand Down Expand Up @@ -1497,8 +1500,8 @@ def check_totals(self, of=None, wrt=None, out_stream=_DEFAULT_OUT_STREAM, compac
step_calc=step_calc if method == 'fd' else None)
total_info = _TotalJacInfo(self, of, wrt, False, return_format='flat_dict', approx=True,
driver_scaling=driver_scaling)
Jfd = total_info.compute_totals_approx(initialize=True)

Jfd = total_info.compute_totals_approx(initialize=True, show_progress=show_progress,
out_stream=out_stream)
# reset the _owns_approx_jac flag after approximation is complete.
if not approx:
model._jacobian = old_jac
Expand Down
62 changes: 62 additions & 0 deletions openmdao/core/tests/test_check_derivs.py
Expand Up @@ -2287,6 +2287,68 @@ def test_cs(self):
self.assertTrue('9.7743e+00' in compact_lines[11],
"'9.7743e+00' not found in '%s'" % compact_lines[11])

def test_check_totals_show_progress(self):
prob = om.Problem()
prob.model = SellarDerivatives()
prob.model.nonlinear_solver = om.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)

prob.model.nonlinear_solver.options['atol'] = 1e-15
prob.model.nonlinear_solver.options['rtol'] = 1e-15

# 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.
stream = StringIO()
totals = prob.check_totals(method='fd', show_progress=True, out_stream=stream)

lines = stream.getvalue().splitlines()
self.assertTrue(lines[0], "1/3: Checking derivatives with respect to: '_auto_ivc.v0 [0]' ... 0.0088 seconds")
self.assertTrue(lines[1], "2/3: Checking derivatives with respect to: '_auto_ivc.v0 [1]' ... 9.2891 seconds")
self.assertTrue(lines[2], "3/3: Checking derivatives with respect to: '_auto_ivc.v1 [2]' ... 0.0087 seconds")

def test_check_totals_show_progress_false(self):
prob = om.Problem()
prob.model = SellarDerivatives()
prob.model.nonlinear_solver = om.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)

prob.model.nonlinear_solver.options['atol'] = 1e-15
prob.model.nonlinear_solver.options['rtol'] = 1e-15

# 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.
stream = StringIO()
totals = prob.check_totals(method='fd', show_progress=False, out_stream=stream)

lines = stream.getvalue().splitlines()
self.assertNotEqual(lines[0], "1/3: Checking derivatives with respect to: '_auto_ivc.v0 [0]' ... 0.0088 seconds")
self.assertNotEqual(lines[1], "2/3: Checking derivatives with respect to: '_auto_ivc.v0 [1]' ... 9.2891 seconds")
self.assertNotEqual(lines[2], "3/3: Checking derivatives with respect to: '_auto_ivc.v1 [2]' ... 0.0087 seconds")

def test_desvar_as_obj(self):
prob = om.Problem()
prob.model = SellarDerivatives()
Expand Down
10 changes: 9 additions & 1 deletion openmdao/core/total_jac.py
Expand Up @@ -1443,7 +1443,7 @@ def compute_totals(self):

return self.J_final

def compute_totals_approx(self, initialize=False):
def compute_totals_approx(self, initialize=False, show_progress=False, out_stream=None):
"""
Compute derivatives of desired quantities with respect to desired inputs.
Expand All @@ -1454,6 +1454,11 @@ def compute_totals_approx(self, initialize=False):
initialize : bool
Set to True to re-initialize the FD in model. This is only needed when manually
calling compute_totals on the problem.
show_progress : bool
Bool to show progress of check_totals
out_stream : file-like object
Where to send human readable output. By default it goes to stdout.
Set to None to suppress.
Returns
-------
Expand Down Expand Up @@ -1494,6 +1499,9 @@ def compute_totals_approx(self, initialize=False):
if model._coloring_info['coloring'] is not None:
model._update_wrt_matches(model._coloring_info)

if show_progress:
model._approx_schemes[method].out_stream = out_stream

# Linearize Model
model._linearize(model._assembled_jac,
sub_do_ln=model._linear_solver._linearize_children())
Expand Down

0 comments on commit 43b1590

Please sign in to comment.