Solving Non-linear Equations in Simulink Code Generation (looking for syms replacement)

3 次查看(过去 30 天)
I have nine equations with nine unknowns (all x and y variables) as a nonlinear system of equations:
eq1 = Q1 == x1 *(c * T1 - c * y1);
eq2 = Q2 == x2 *(c * T2 - c * y1);
eq3 = Q3 == x3 *(c * y2 - c * T4 );
eq4 = Q4 == x4 *(c * y2 - c * T5 );
eq5 = - x2 *(T2 - y3 ) == x1 *(T1 - y3 );
eq6 = - x3 *(T4 - y4) == + x4 *(T5 - y4);
eq7 = x1 * y1 == - x2 * y1 + x3 * y4 +x4 * y4 + x5 * T6;
eq8 = x1 * y3 == - x2 * y3 + x3 * y2 +x4 * y2 + x5 * T3;
eq9 = x5 == x1 +x2 -x3 - x4;
There are always at least two different unknowns per equations. All other variables (c,Q1, T1 etc.) will be given for each simulation step.
In the Workspace i can simply type:
%example input:
c = 4; T1 = 80; T2 = 80; T4 = 30; T5 = 30; T6 = 60; T3 = 100; Q1 = 50; Q2 = 50; Q3 = 20; Q4 = 25;
% unknowns:
syms x1 x2 x3 x4 x5 y1 y2 y3 y4
%solve
a=solve(eq1,eq2,eq3,eq4,eq5,eq6,eq7,eq8,eq9,x1, x2, x3, x4, x5, y1, y2, y3, y4);
That gets solved easily and correct. But how do I get this logic in simulink code generator without the symbolic toolbox? Ideally it should be executed each simulation step with different inputs for c, T1, T2, T3, T4, T5, T6, Q1, Q2, Q3, Q4.
What I tried so far:
Solving symbolically and then simplifying it: I gave the Matlab Workspace only all variables without any numeric inputs and tried to let it solve for my desired unknowns. This returned (after a long time) only Empty sym: 0-by-1 for all my unknowns. I tried this with solve() and vpasolve():
syms x1 x2 x3 x4 x5 y1 y2 y3 y4 c T1 T2 T3 T4 T5 T6 Q1 Q2 Q3 Q4
a=solve(eq1,eq2,eq3,eq4,eq5,eq6,eq7,eq8,eq9,x1, x2, x3, x4, x5, y1, y2, y3, y4);
a1 = [simplify(a.x1); simplify(a.x2);simplify(a.x3);simplify(a.x4);simplify(a.x5); simplify(a.y1);simplify(a.y2);simplify(a.y3);simplify(a.y4);]
Getting rid of syms through Code Generation: matlabFunctionBlock .This creates a simulink block, where my unknowns are input ports. But I don't know what I should connect to those Ports, since I want to solve for them. If I try to define them as followed:
matlabFunctionBlock('mysystem/my_block',eq1,eq2,eq3,eq4,eq5,eq6,eq7,eq8,eq9,...
'Vars', [c T1 T2 T3 T4 T5 T6 Q1 Q2 Q3 Q4 x1 x2 x3 x4 x5 y1 y2 y3 y4 c T1 T2 T3 T4 T5 T6 Q1 Q2 Q3 Q4]);
I also looked at matlabFunction, handles and anonymus functions, but if I understand correctly those are also not suitable for storeing functions with unknowns.
I tried defining my unknowns as empty variable in the form of: x1 = [ ] , but then the solver can't handle it:
Error using solve>getEqns (line 404)
Input argument contains an empty equation or variable.
Error in solve (line 226) [eqns,vars,options] = getEqns(varargin{:});
I also looked at the Optimization Toolbox but the needed optimvar() is also not supported in code generation.
I'm really at a loss right now and would appriciate any input. (I also have Simscape. Could that be of any help?)
Thanks in advance!

回答(1 个)

Githin George
Githin George 2023-12-27
It is my understanding that you would like to solve a system of equations in Simulink and perform code generation for the same. The symbolic toolbox does not support C/C++ code generation and hence you cannot use it to solve a system of equations in Simulink. But in case of a normal/accelerated simulation mode this task can be achieved by using the “coder.extrinsic” function. The MATLAB engine executes the calls to functions in the Symbolic Toolbox.
You can look at the below code snippets to understand how this function can be used.
You will need to write an external function that uses “solve” to find the solution to the system of equations. The output type must be of “double” format when using this method. As an example, I’ve returned the unknown variable “x1” as “out”.
function out = solveSyms() % add necessary inputs and outputs
syms x1 x2 x3 x4 x5 y1 y2 y3 y4
c = 4; T1 = 80; T2 = 80; T4 = 30; T5 = 30; T6 = 60; T3 = 100; Q1 = 50; Q2 = 50; Q3 = 20; Q4 = 25;
eq1 = Q1 == x1 *(c * T1 - c * y1);
eq2 = Q2 == x2 *(c * T2 - c * y1);
eq3 = Q3 == x3 *(c * y2 - c * T4 );
eq4 = Q4 == x4 *(c * y2 - c * T5 );
eq5 = - x2 *(T2 - y3 ) == x1 *(T1 - y3 );
eq6 = - x3 *(T4 - y4) == + x4 *(T5 - y4);
eq7 = x1 * y1 == - x2 * y1 + x3 * y4 +x4 * y4 + x5 * T6;
eq8 = x1 * y3 == - x2 * y3 + x3 * y2 +x4 * y2 + x5 * T3;
eq9 = x5 == x1 +x2 -x3 - x4;
a=solve(eq1,eq2,eq3,eq4,eq5,eq6,eq7,eq8,eq9,x1, x2, x3, x4, x5, y1, y2, y3, y4);
out = double(a.x1);
end
In your Simulink model call the “coder.extrinsic” function in a MATLAB function block to access the custom function.
function out = fcn(c,T1,T2,T4,T5,T6,T3,Q1,Q2,Q3,Q4)
coder.extrinsic('solveSyms');
out = 0;
out = solveSyms(c,T1,T2,T4,T5,T6,T3,Q1,Q2,Q3,Q4);
You can provide the known values as input to MATLAB function block and define output for each of the unknown variables (x1-x5 and y1-y4) to solve the complete equation using Simulink.
Please have a look at below links for more information.
I hope this helps.

类别

Help CenterFile Exchange 中查找有关 Symbolic Math Toolbox 的更多信息

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by