Skip to content

Commit

Permalink
Merge 37b6457 into 01e26ea
Browse files Browse the repository at this point in the history
  • Loading branch information
Kenneth-T-Moore committed Aug 21, 2017
2 parents 01e26ea + 37b6457 commit 8357f16
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 8 deletions.
8 changes: 8 additions & 0 deletions openmdao/core/component.py
Expand Up @@ -792,3 +792,11 @@ def _set_partials_meta(self):

for approx in itervalues(self._approx_schemes):
approx._init_approximations()

def _guess_nonlinear(self):
"""
Provide initial guess for states.
Does nothing on any non-implicit component.
"""
pass
19 changes: 14 additions & 5 deletions openmdao/core/group.py
Expand Up @@ -21,6 +21,7 @@
from openmdao.solvers.nonlinear.nonlinear_runonce import NonLinearRunOnce
from openmdao.solvers.linear.linear_runonce import LinearRunOnce
from openmdao.utils.array_utils import convert_neg
from openmdao.utils.class_util import overrides_method
from openmdao.utils.general_utils import warn_deprecation
from openmdao.utils.units import is_compatible

Expand Down Expand Up @@ -1270,17 +1271,25 @@ def _solve_nonlinear(self):
# Execute guess_nonlinear if specified.
# We need to call this early enough so that any solver that needs initial guesses has
# them.
# TODO: It is pointless to run this ahead of non-iterative solvers.
for sub in self.system_iter(recurse=True):
if hasattr(sub, 'guess_nonlinear'):
with sub._unscaled_context(outputs=[sub._outputs], residuals=[sub._residuals]):
sub.guess_nonlinear(sub._inputs, sub._outputs, sub._residuals)
# TODO: It is pointless to run this ahead of non-iterative solvers, but multi-level
# models seem to ned it.
self._guess_nonlinear()

with Recording(name + '._solve_nonlinear', self.iter_count, self):
result = self._nonlinear_solver.solve()

return result

def _guess_nonlinear(self):
"""
Provide initial guess for states.
"""
from openmdao.api import ImplicitComponent
for isub, sub in enumerate(self._subsystems_myproc):
if overrides_method('guess_nonlinear', sub, ImplicitComponent):
self._transfer('nonlinear', 'fwd', isub)
sub._guess_nonlinear()

def _apply_linear(self, vec_names, mode, scope_out=None, scope_in=None):
"""
Compute jac-vec product. The model is assumed to be in a scaled state.
Expand Down
7 changes: 7 additions & 0 deletions openmdao/core/implicitcomponent.py
Expand Up @@ -71,6 +71,13 @@ def _solve_nonlinear(self):
else:
return result

def _guess_nonlinear(self):
"""
Provide initial guess for states.
"""
with self._unscaled_context(outputs=[self._outputs], residuals=[self._residuals]):
self.guess_nonlinear(self._inputs, self._outputs, self._residuals)

def _apply_linear(self, vec_names, mode, scope_out=None, scope_in=None):
"""
Compute jac-vec product. The model is assumed to be in a scaled state.
Expand Down
86 changes: 83 additions & 3 deletions openmdao/core/tests/test_impl_comp.py
Expand Up @@ -7,7 +7,7 @@
import numpy as np

from openmdao.api import Problem, Group, ImplicitComponent, IndepVarComp, NewtonSolver, \
ScipyIterativeSolver
ScipyIterativeSolver, NonlinearBlockGS
from openmdao.devtools.testutil import assert_rel_error


Expand All @@ -16,8 +16,8 @@
class QuadraticComp(ImplicitComponent):
"""
A Simple Implicit Component representing a Quadratic Equation.
R(a, b, c, x) = ax^2 + bx + c
R(a, b, c, x) = ax^2 + bx + c
Solution via Quadratic Formula:
x = (-b + sqrt(b^2 - 4ac)) / 2a
Expand Down Expand Up @@ -286,6 +286,86 @@ def guess_nonlinear(self, inputs, outputs, resids):
prob.run_model()
assert_rel_error(self, prob['comp2.x'], 3.)

def test_guess_nonlinear_transfer(self):
# Test that data is transfered to a component before calling guess_nonlinear.

class ImpWithInitial(ImplicitComponent):

def setup(self):
self.add_input('x', 3.0)
self.add_output('y', 4.0)

def solve_nonlinear(self, inputs, outputs):
""" Do nothing. """
pass

def apply_nonlinear(self, inputs, outputs, resids):
""" Do nothing. """
pass

def guess_nonlinear(self, inputs, outputs, resids):
# Passthrough
outputs['y'] = inputs['x']


group = Group()

group.add_subsystem('px', IndepVarComp('x', 77.0))
group.add_subsystem('comp1', ImpWithInitial())
group.add_subsystem('comp2', ImpWithInitial())
group.connect('px.x', 'comp1.x')
group.connect('comp1.y', 'comp2.x')

group.nonlinear_solver = NonlinearBlockGS()

prob = Problem(model=group)
prob.setup(check=False)

prob.run_model()
assert_rel_error(self, prob['comp2.y'], 77.)

def test_guess_nonlinear_transfer_subbed(self):
# Test that data is transfered to a component before calling guess_nonlinear.

class ImpWithInitial(ImplicitComponent):

def setup(self):
self.add_input('x', 3.0)
self.add_output('y', 4.0)

def solve_nonlinear(self, inputs, outputs):
""" Do nothing. """
pass

def apply_nonlinear(self, inputs, outputs, resids):
""" Do nothing. """
resids['y'] = 1.0
pass

def guess_nonlinear(self, inputs, outputs, resids):
# Passthrough
outputs['y'] = inputs['x']


group = Group()
sub = Group()

group.add_subsystem('px', IndepVarComp('x', 77.0))
sub.add_subsystem('comp1', ImpWithInitial())
sub.add_subsystem('comp2', ImpWithInitial())
group.connect('px.x', 'sub.comp1.x')
group.connect('sub.comp1.y', 'sub.comp2.x')

group.add_subsystem('sub', sub)

group.nonlinear_solver = NonlinearBlockGS()

prob = Problem(model=group)
prob.setup(check=False)

prob.run_model()
assert_rel_error(self, prob['sub.comp2.y'], 77.)

def test_guess_nonlinear_feature(self):

class ImpWithInitial(ImplicitComponent):
Expand Down

0 comments on commit 8357f16

Please sign in to comment.