LinearSystemComp#

The LinearSystemComp solves the linear system Ax = b where A and b are inputs, and x is the output.

LinearSystemComp Options#

OptionDefaultAcceptable ValuesAcceptable TypesDescription
always_optFalse[True, False]['bool']If True, force nonlinear operations on this component to be included in the optimization loop even if this component is not relevant to the design variables and responses.
assembled_jac_typecsc['csc', 'dense']N/ALinear solver(s) in this group or implicit component, if using an assembled jacobian, will use this type.
distributedFalse[True, False]['bool']If True, set all variables in this component as distributed across multiple processes
run_root_onlyFalse[True, False]['bool']If True, call compute, compute_partials, linearize, apply_linear, apply_nonlinear, and compute_jacvec_product only on rank 0 and broadcast the results to the other ranks.
size1N/A['int']The size of the linear system.
vec_size1N/A['int']Number of linear systems to solve.
vectorize_AFalse[True, False]['bool']Set to True to vectorize the A matrix.

LinearSystemComp Constructor#

The call signature for the LinearSystemComp constructor is:

LinearSystemComp.__init__(**kwargs)[source]

Intialize the LinearSystemComp component.

LinearSystemComp Example#

import numpy as np
import openmdao.api as om

model = om.Group()

A = np.array([[5.0, -3.0, 2.0], [1.0, 7.0, -4.0], [1.0, 0.0, 8.0]])
b = np.array([1.0, 2.0, -3.0])

lingrp = model.add_subsystem('lingrp', om.Group(), promotes=['*'])
lingrp.add_subsystem('lin', om.LinearSystemComp(size=3))

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

prob.set_val('lin.A', A)
prob.set_val('lin.b', b)

lingrp.linear_solver = om.ScipyKrylov()

prob.run_model()

print(prob.get_val('lin.x'))
[ 0.36423841 -0.00662252 -0.4205298 ]

This component can also be vectorized to either solve a single linear system with multiple right hand sides, or to solve multiple independent linear systems.

You can solve multiple right hand sides by setting the “vec_size” argument, giving it the number of right hand sides. When you do this, the LinearSystemComp creates an input for “b” such that each row of b is solved independently.

model = om.Group()

A = np.array([[5.0, -3.0, 2.0], [1.0, 7.0, -4.0], [1.0, 0.0, 8.0]])
b = np.array([[2.0, -3.0, 4.0], [1.0, 0.0, -1.0]])

lingrp = model.add_subsystem('lingrp', om.Group(), promotes=['*'])
lingrp.add_subsystem('lin', om.LinearSystemComp(size=3, vec_size=2))

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

prob.set_val('lin.A', A)
prob.set_val('lin.b', b)

lingrp.linear_solver = om.ScipyKrylov()

prob.run_model()

print(prob.get_val('lin.x'))
[[ 0.10596026 -0.16556291  0.48675497]
 [ 0.19205298 -0.11258278 -0.14900662]]

To solve multiple linear systems, you just need to set the “vectorize_A” option or argument to True. The A matrix is now a 3-dimensional matrix where the first dimension is the number of linear systems to solve.

model = om.Group()

A = np.array([[[5.0, -3.0, 2.0], [1.0, 7.0, -4.0], [1.0, 0.0, 8.0]],
              [[2.0, 3.0, 4.0], [1.0, -1.0, -2.0], [3.0, 2.0, -2.0]]])
b = np.array([[-5.0, 2.0, 3.0], [-1.0, 1.0, -3.0]])

lingrp = model.add_subsystem('lingrp', om.Group(), promotes=['*'])
lingrp.add_subsystem('lin', om.LinearSystemComp(size=3, vec_size=2, vectorize_A=True))

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

prob.set_val('lin.A', A)
prob.set_val('lin.b', b)

lingrp.linear_solver = om.ScipyKrylov()

prob.run_model()

print(prob.get_val('lin.x'))
[[-0.78807947  0.66887417  0.47350993]
 [ 0.7        -1.8         0.75      ]]