<jupyter_start><jupyter_text>Setting Nonlinear and Linear SolversA nonlinear solver, like [NonlinearBlockGS](../../../_srcdocs/packages/solvers.nonlinear/nonlinear_block_gs) or [Newton](../../../_srcdocs/packages/solvers.nonlinear/newton),is used to converge the nonlinear analysis. A nonlinear solver is needed whenever there is a cyclic dependency between components in your model.It might also be needed if you have an [ImplicitComponent](../../../_srcdocs/packages/core/implicitcomponent) in your model that expects the framework to handle its convergence.Whenever you use a nonlinear solver on a [Group](../../../_srcdocs/packages/core/group) or [Component](../../../_srcdocs/packages/core/component), if you're going to be working with analytic derivatives,you will also need a linear solver.A linear solver, like [LinearBlockGS](../../../_srcdocs/packages/solvers.linear/linear_block_gs) or [DirectSolver](../../../_srcdocs/packages/solvers.linear/direct),is used to solve the linear system that provides total derivatives across the model.You can add nonlinear and linear solvers at any level of the model hierarchy,letting you build a hierarchical solver setup to efficiently converge your model and solve for total derivatives across it. Solvers for the Sellar ProblemThe Sellar Problem has two components with a cyclic dependency, so the appropriate nonlinear solver is necessary.We'll use the [Newton](../../../_srcdocs/packages/solvers.nonlinear/newton) nonlinear solver,which requires derivatives, so we'll also use the [DirectSolver](../../../_srcdocs/packages/solvers.linear/direct) linear solver.<jupyter_code>from openmdao.test_suite.components.sellar import SellarDerivatives

prob = om.Problem()
model = prob.model = SellarDerivatives()

model.nonlinear_solver = newton = om.NewtonSolver(solve_subsystems=False)

# using a different linear solver for Newton with a looser tolerance
newton.linear_solver = om.ScipyKrylov(atol=1e-4)

# used for analytic derivatives
model.linear_solver = om.DirectSolver()

prob.setup()
prob.run_model()

print(prob.get_val('y1'))
print(prob.get_val('y2'))
from openmdao.utils.assert_utils import assert_near_equal

assert_near_equal(prob.get_val('y1'), 25.58830273, .00001)
assert_near_equal(prob.get_val('y2'), 12.05848819, .00001)<jupyter_output><empty_output><jupyter_text>Some models have more complex coupling. There could be top-level cycles between groups as well aslower-level groups that have cycles of their own. [openmdao.test_suite.components.double_sellar.DoubleSellar](https://github.com/OpenMDAO/OpenMDAO/blob/4e329d76c687336e2efd3a1f484ff735dbd219d6/openmdao/test_suite/components/double_sellar.py) is a simple example of this kind of model structure. In these problems, you might want to specify a more complex hierarchical solver structure for both nonlinear and linear solvers.<jupyter_code>from openmdao.test_suite.components.double_sellar import DoubleSellar

prob = om.Problem()
model = prob.model = DoubleSellar()

# each SubSellar group converges itself
g1 = model.g1
g1.nonlinear_solver = om.NewtonSolver(solve_subsystems=False)
g1.linear_solver = om.DirectSolver()  # used for derivatives

g2 = model.g2
g2.nonlinear_solver = om.NewtonSolver(solve_subsystems=False)
g2.linear_solver = om.DirectSolver()

# Converge the outer loop with Gauss Seidel, with a looser tolerance.
model.nonlinear_solver = om.NonlinearBlockGS(rtol=1.0e-5)
model.linear_solver = om.ScipyKrylov()
model.linear_solver.precon = om.LinearBlockGS()

prob.setup()
prob.run_model()

print(prob.get_val('g1.y1'))
print(prob.get_val('g1.y2'))
print(prob.get_val('g2.y1'))
print(prob.get_val('g2.y2'))
assert_near_equal(prob.get_val('g1.y1'), 0.64, .00001)
assert_near_equal(prob.get_val('g1.y2'), 0.80, .00001)
assert_near_equal(prob.get_val('g2.y1'), 0.64, .00001)
assert_near_equal(prob.get_val('g2.y2'), 0.80, .00001)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11350796096558809, 'fraction_numerical': 0.030816640986132512, 'mean_word_length': 5.703958691910499, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '2', 'dir': 'jupyter-structured-clean-dedup', 'id': '75349', 'license': 'Apache-2.0', 'n_tokens_mistral': 1348, 'n_tokens_neox': 1230, 'n_words': 324, 'path': 'openmdao/docs/openmdao_book/features/core_features/controlling_solver_behavior/set_solvers.ipynb', 'repo_name': 'sebasgo/OpenMDAO', 'size': '3894'}