Search for decoupled blocks in systems of equations
[
identifies subsets (blocks) of equations that can be used to define subsets of variables.
The number of variables eqsBlocks
,varsBlocks
]
= findDecoupledBlocks(eqs
,vars
)vars
must coincide with the number of equations
eqs
.
The ith block is the set of equations determining the variables in
vars(varsBlocks{i})
. The variables in
vars([varsBlocks{1},…,varsBlocks{i-1}])
are determined recursively by
the previous blocks of equations. After you solve the first block of equations for the first
block of variables, the second block of equations, given by
eqs(eqsBlocks{2})
, defines a decoupled subset of equations containing
only the subset of variables given by the second block of variables,
vars(varsBlock{2})
, plus the variables from the first block (these
variables are known at this time). Thus, if a nontrivial block decomposition is possible,
you can split the solution process for a large system of equations involving many variables
into several steps, where each step involves a smaller subsystem.
The number of blocks length(eqsBlocks)
coincides with
length(varsBlocks)
. If length(eqsBlocks) = length(varsBlocks)
= 1
, then a nontrivial block decomposition of the equations is not
possible.
Compute a block lower triangular decomposition (BLT decomposition) of a symbolic system of differential algebraic equations (DAEs).
Create the following system of four differential algebraic equations. Here, the symbolic
function calls x1(t)
, x2(t)
, x3(t)
,
and x4(t)
represent the state variables of the system. The system also
contains symbolic parameters c1
, c2
,
c3
, c4
, and functions f(t,x,y)
and g(t,x,y)
.
syms x1(t) x2(t) x3(t) x4(t) syms c1 c2 c3 c4 syms f(t,x,y) g(t,x,y) eqs = [c1*diff(x1(t),t)+c2*diff(x3(t),t)==c3*f(t,x1(t),x3(t));... c2*diff(x1(t),t)+c1*diff(x3(t),t)==c4*g(t,x3(t),x4(t));... x1(t)==g(t,x1(t),x3(t));... x2(t)==f(t,x3(t),x4(t))]; vars = [x1(t), x2(t), x3(t), x4(t)];
Use findDecoupledBlocks
to find the block structure of the
system.
[eqsBlocks, varsBlocks] = findDecoupledBlocks(eqs, vars)
eqsBlocks = 1×3 cell array {1×2 double} {[2]} {[4]} varsBlocks = 1×3 cell array {1×2 double} {[4]} {[2]}
The first block contains two equations in two variables.
eqs(eqsBlocks{1})
ans = c1*diff(x1(t), t) + c2*diff(x3(t), t) == c3*f(t, x1(t), x3(t)) x1(t) == g(t, x1(t), x3(t))
vars(varsBlocks{1})
ans = [ x1(t), x3(t)]
After you solve this block for the variables x1(t)
,
x3(t)
, you can solve the next block of equations. This block consists
of one equation.
eqs(eqsBlocks{2})
ans = c2*diff(x1(t), t) + c1*diff(x3(t), t) == c4*g(t, x3(t), x4(t))
The block involves one variable.
vars(varsBlocks{2})
ans = x4(t)
After you solve the equation from block 2 for the variable x4(t)
, the
remaining block of equations, eqs(eqsBlocks{3})
, defines the remaining
variable, vars(varsBlocks{3})
.
eqs(eqsBlocks{3}) vars(varsBlocks{3})
ans = x2(t) == f(t, x3(t), x4(t)) ans = x2(t)
Find the permutations that convert the system to a block lower triangular form.
eqsPerm = [eqsBlocks{:}] varsPerm = [varsBlocks{:}]
eqsPerm = 1 3 2 4 varsPerm = 1 3 4 2
Convert the system to a block lower triangular system of equations.
eqs = eqs(eqsPerm) vars = vars(varsPerm)
eqs = c1*diff(x1(t), t) + c2*diff(x3(t), t) == c3*f(t, x1(t), x3(t)) x1(t) == g(t, x1(t), x3(t)) c2*diff(x1(t), t) + c1*diff(x3(t), t) == c4*g(t, x3(t), x4(t)) x2(t) == f(t, x3(t), x4(t)) vars = [ x1(t), x3(t), x4(t), x2(t)]
Find the incidence matrix of the resulting system. The incidence matrix shows that the
system of permuted equations has three diagonal blocks of size
2
-by-2
,
1
-by-1
, and
1
-by-1
.
incidenceMatrix(eqs, vars)
ans = 1 1 0 0 1 1 0 0 1 1 1 0 0 1 1 1
Find blocks of equations in a linear algebraic system, and then solve the system by sequentially solving each block of equations starting from the first one.
Create the following system of linear algebraic equations.
syms x1 x2 x3 x4 x5 x6 c1 c2 c3 eqs = [c1*x1 + x3 + x5 == c1 + c2 + 1;... x1 + x3 + x4 + 2*x6 == 4 + c2;... x1 + 2*x3 + c3*x5 == 1 + 2*c2 + c3;... x2 + x3 + x4 + x5 == 2 + c2;... x1 - c2*x3 + x5 == 2 - c2^2;... x1 - x3 + x4 - x6 == 1 - c2]; vars = [x1, x2, x3, x4, x5, x6];
Use findDecoupledBlocks
to convert the system to a lower triangular
form. For this system, findDecoupledBlocks
identifies three blocks of
equations and corresponding variables.
[eqsBlocks, varsBlocks] = findDecoupledBlocks(eqs, vars)
eqsBlocks = 1×3 cell array {1×3 double} {1×2 double} {[4]} varsBlocks = 1×3 cell array {1×3 double} {1×2 double} {[2]}
Identify the variables in the first block. This block consists of three equations in three variables.
vars(varsBlocks{1})
ans = [ x1, x3, x5]
Solve the first block of equations for the first block of variables assigning the solutions to the corresponding variables.
[x1,x3,x5] = solve(eqs(eqsBlocks{1}), vars(varsBlocks{1}))
x1 = 1 x3 = c2 x5 = 1
Identify the variables in the second block. This block consists of two equations in two variables.
vars(varsBlocks{2})
ans = [ x4, x6]
Solve this block of equations assigning the solutions to the corresponding variables.
[x4, x6] = solve(eqs(eqsBlocks{2}), vars(varsBlocks{2}))
x4 = x3/3 - x1 - c2/3 + 2 x6 = (2*c2)/3 - (2*x3)/3 + 1
Use subs
to evaluate the result for the already known values of
variables x1
, x3
, and x5
.
x4 = subs(x4) x6 = subs(x6)
x4 = 1 x6 = 1
Identify the variables in the third block. This block consists of one equation in one variable.
vars(varsBlocks{3})
ans = x2
Solve this equation assigning the solution to x2
.
x2 = solve(eqs(eqsBlocks{3}), vars(varsBlocks{3}))
x2 = c2 - x3 - x4 - x5 + 2
Use subs
to evaluate the result for the already known values of all
other variables of this system.
x2 = subs(x2)
x2 = 0
Alternatively, you can rewrite this example using the for
-loop. This
approach lets you use the example for larger systems of equations.
syms x1 x2 x3 x4 x5 x6 c1 c2 c3 eqs = [c1*x1 + x3 + x5 == c1 + c2 + 1;... x1 + x3 + x4 + 2*x6 == 4 + c2;... x1 + 2*x3 + c3*x5 == 1 + 2*c2 + c3;... x2 + x3 + x4 + x5 == 2 + c2;... x1 - c2*x3 + x5 == 2 - c2^2 x1 - x3 + x4 - x6 == 1 - c2]; vars = [x1, x2, x3, x4, x5, x6]; [eqsBlocks, varsBlocks] = findDecoupledBlocks(eqs, vars); vars_sol = vars; for i = 1:numel(eqsBlocks) sol = solve(eqs(eqsBlocks{i}), vars(varsBlocks{i})); vars_sol_per_block = subs(vars(varsBlocks{i}), sol); for k=1:i-1 vars_sol_per_block = subs(vars_sol_per_block, vars(varsBlocks{k}),... vars_sol(varsBlocks{k})); end vars_sol(varsBlocks{i}) = vars_sol_per_block end
vars_sol = [ 1, x2, c2, x4, 1, x6] vars_sol = [ 1, x2, c2, 1, 1, 1] vars_sol = [ 1, 0, c2, 1, 1, 1]
The implemented algorithm requires that for each variable in vars
there must be at least one matching equation in eqs
involving this
variable. The same equation cannot also be matched to another variable. If the system does
not satisfy this condition, then findDecoupledBlocks
throws an error.
In particular, findDecoupledBlocks
requires that length(eqs)
= length(vars)
.
Applying the permutations e = [eqsBlocks{:}]
to the vector
eqs
and v = [varsBlocks{:}]
to the vector
vars
produces an incidence matrix incidenceMatrix(eqs(e),
vars(v))
that has a block lower triangular sparsity pattern.
daeFunction
| decic
| diag
| incidenceMatrix
| isLowIndexDAE
| massMatrixForm
| odeFunction
| reduceDAEIndex
| reduceDAEToODE
| reduceDifferentialOrder
| reduceRedundancies
| tril
| triu