OpenMDAO Solvers#
Every OpenMDAO solver is either a linear solver, inheriting from the LinearSolver
class, or
a nonlinear solver, inheriting from the NonlinearSolver
class. A solver can be either monolithic
or recursive in behavior. Monolithic solvers treat the associated system as a single block. Recursive
solvers, as the name suggests, recurse down through their system hierarchy asking each sub-system to
operate on itself.
The following is a list of available OpenMDAO solvers separated by type:
Linear
Monolithic
DirectSolver
PETScKrylov
ScipyKrylov
LinearUserDefined
Recursive
LinearBlockGS
LinearBlockJac
LinearRunOnce
Nonlinear
Monolithic
Newton (options[‘solve_subsystems’] = False)
Broyden (options[‘solve_subsystems’] = False)
BoundsEnforceLS (options[‘solve_subsystems’] = False)
ArmijoGoldsteinLS (options[‘solve_subsystems’] = False)
Recursive
NonlinearBlockGS
NonlinearBlockJac
NonlinearRunOnce
Newton (options[‘solve_subsystems’] = True)
BoundsEnforceLS (options[‘solve_subsystems’] = True)
ArmijoGoldsteinLS (options[‘solve_subsystems’] = True)
Below is a figure depicting how a model containing both recursive and monolithic solvers would function. The numbered circles represent the order of calls to subsystems in the model.
Writing Custom Solvers#
If your solver will be linear, you’ll need to inherit from LinearSolver
, or perhaps from
BlockLinearSolver
. If your solver will be nonlinear, inherit from NonlinearSolver
.
If your solver will be monolithic, you’ll most likely override the entire solve
function,
and if your solver will be recursive, you may be able to get away with only overriding a couple of
lower level functions like _iter_initialize
and _single_iteration
. The best thing
to do is to start with the OpenMDAO solver that is most similar to what you want to do and go from
there.
Some solvers, especially recursive ones, can have confusing calling structures, because it’s
not always obvious which class is the owner of a given method. A command line tool,
openmdao call_tree
was developed to help clarify what the actual call structure is. So, for
example, if we wanted to see the call structure of NonlinearBlockGS.solve
, we could do the
following:
openmdao call_tree openmdao.api.NonlinearBlockGS.solve
The output above shows that NonlinearBlockGS
does not override the solve
method,
but instead overrides some lower level methods like _iter_initialize
, _run_apply
,
and _single_iteration
and relies on the Solver._solve
method to provide the main
skeleton for the entire solve including the iteration loop.