InputResidsComp#

InputResidsComp is a specialized implementation of ImplicitComponent that is intended to allow the user to simply add residuals to a system by treating any inputs to the components as the value of the associated residual.

Unlike BalanceComp, implicit outputs do not map one-to-one with the inputs. That is, the number of output variables for InputResidsComp does not have to match the number of input variables, but the total size of the inputs and outputs must be the same.

InputResidsComp can make it easier to convert an MDO problem from a “SAND” (simultaneous analysis and design) formumlation to an “MDF” (multiple design feasible) formulation by adding zero-valued equality constraints to it as inputs, and the associated design variables to it as implicit outputs.

InputResidsComp Constructor#

The call signature for the InputResidsComp constructor is:

InputResidsComp.__init__()[source]

Initialize the InputResidsComp.

Parameters:
**kwargsdict

Keyword arguments passed to the __init__ method of ImplicitComponent

Example: Single state vector, multiple equations of constraint#

The following example uses a InputResidsComp to implicitly solve the equations:

()#\[\begin{align} x_0 + x_1 &= 5 \\ x_2 + x_3 &= 10 \\ x_0 &= x_3 \\ \left\Vert \bar{x} \right\Vert &= 9 \end{align}\]
import openmdao.api as om

prob = om.Problem()

bal = om.BalanceComp()
bal.add_balance('x', use_mult=True)

exec_comp = om.ExecComp(['y[0]=x[0] + x[1] - 5',
                         'y[1]=x[2] + x[3] - 10',
                         'y[2]=x[0] - x[3]',
                         'z=dot(x, x)**0.5 - 9'],
                        x={'shape': (4,)},
                        y={'val': [1., 1., 1.]},
                        z={'val': 2.})

prob.model.add_subsystem(name='exec', subsys=exec_comp)
resids = prob.model.add_subsystem(name='resids', subsys=om.InputResidsComp())

resids.add_output('x', shape_by_conn=True)
resids.add_input('res_0', shape_by_conn=True)
resids.add_input('res_1', shape_by_conn=True)

prob.model.connect('resids.x', 'exec.x')
prob.model.connect('exec.y', 'resids.res_0')
prob.model.connect('exec.z', 'resids.res_1')

prob.model.linear_solver = om.DirectSolver(assemble_jac=True)
prob.model.nonlinear_solver = om.NewtonSolver(solve_subsystems=False, maxiter=100, iprint=0)
prob.set_solver_print(2)


prob.setup()

prob.set_val('resids.x', [1., 1., 10, 5])

prob.final_setup()

prob.run_model()

prob.model.list_vars(print_arrays=True);
NL: Newton 0 ; 8.00453567 1
NL: Newton 1 ; 1.27590224 0.159397408
NL: Newton 2 ; 0.167205529 0.020888848
NL: Newton 3 ; 0.00698219699 0.000872280077
NL: Newton 4 ; 1.504573e-05 1.87965056e-06
NL: Newton 5 ; 7.05764336e-11 8.81705529e-12
NL: Newton Converged
6 Variables(s) in 'model'

varname  val                  io      prom_name   
-------  -------------------  ------  ------------
exec
  x      |9.0|                input   exec.x      
         val:
         array([2., 3., 8., 2.])
  y      |0.0|                output  exec.y      
         val:
         array([0., 0., 0.])
  z      [0.]                 output  exec.z      
resids
  res_0  |0.0|                input   resids.res_0
         val:
         array([0., 0., 0.])
  res_1  [0.]                 input   resids.res_1
  x      |9.0|                output  resids.x    
         val:
         array([2., 3., 8., 2.])
/usr/share/miniconda/envs/test/lib/python3.11/site-packages/openmdao/utils/coloring.py:409: DerivativesWarning:'exec' <class ExecComp>: Coloring was deactivated.  Improvement of 0.0% was less than min allowed (5.0%).