Best way to solve my implicit equation

25 ビュー (過去 30 日間)
Simone Pavan
Simone Pavan 2020 年 3 月 27 日
編集済み: Simone Pavan 2020 年 4 月 20 日
I'm looking for a way to solve my implicit equation without using syms. The reason is that I want to compile an application with this equation and I can't do it because Matlab Compiler doesn't work with symbolic math toolbox.
This is my equation:
syms R
g = ((1+nu)*(1-2*nu)*(1-1/(R/b0)^2))/((alpha-1)-(1-2*nu)*(1+alpha)/(R/b0)^2);
omega = -(2*(1-2*nu)*(1-nu^2))/(delta*(alpha-1))*((alpha+1/beta)-(nu/(1-nu))*(1+alpha/beta))/((alpha-1)-((1-2*nu)*(1+alpha)/(R/b0)^2))/(R/b0)^2;
S1 = 0;
for n=0:1:10
if n==gam
S = k*omega^n/factorial(n)*log(R/a);
else
S = (omega^n/(factorial(n)*(n-gam))*((R/a)^(k*(n-gam))-1));
end
S1=S1+S;
end
eqn = (nn/gam)*((1-g/delta)^((beta+1)/beta)-(a0/R)^((beta+1)/beta)) == S1;
sol_R = vpasolve(eqn, R, [a0 Rpl_max]);

採用された回答

Walter Roberson
Walter Roberson 2020 年 3 月 27 日
In an interactive session:
syms any of the names corresponding to variables you will need to change. Calculate lhs(eqn)-rhs(eqn) and assign that to a variable.
Now call matlabFunction on the variable. Pass it the 'file' option and a file name. For example EQN.m . Pass it the 'vars' option using a cell array. In the first entry of the cell array put a vector of variable names of the variables you want solved for, in the order you want returned. The rest of the variables, the ones that will be provided as numeric parameters rather than solved for, you can either put into a vector in the second cell entry, or you can list them one at a time as cell entries.
That done, switch to the code you will be using for building the compiled application. In it, build an anonymous function that takes a single parameter, and calls EQN passing that parameter straight through, and then passing the numeric values in the same order as you specified in the 'vars' option.
Now you can pass that function handle to fsolve.
Notice that the symbolic work is done only at the interactive session, and is used to write an m file that does not use the symbolic toolbox. Notice that the code to be compiled does not use the symbolic toolbox: it only calls the m file and that file is purely numeric.
By the way, it is safer if your interactive session code initializes S1 to sym(0) instead of 0.
  3 件のコメント
Walter Roberson
Walter Roberson 2020 年 3 月 27 日
編集済み: Walter Roberson 2020 年 3 月 27 日
An interactive session is just the MATLAB application rather than something compiled.
Most of the complication of the generated code comes from not knowing gam ahead of time.
Note: if gam is a fixed constant rather than a parameter, then you would need to switch back from piecewise() to if/else like you had.
%in MATLAB, desktop or command line only, do not compile this part
syms a a0 alpha b0 beta delta gam k nn nu
syms R
g = ((1+nu)*(1-2*nu)*(1-1/(R/b0)^2))/((alpha-1)-(1-2*nu)*(1+alpha)/(R/b0)^2);
omega = -(2*(1-2*nu)*(1-nu^2))/(delta*(alpha-1))*((alpha+1/beta)-(nu/(1-nu))*(1+alpha/beta))/((alpha-1)-((1-2*nu)*(1+alpha)/(R/b0)^2))/(R/b0)^2;
S1 = sym(0);
for n=0:1:10
%piecewise is needed to test against a value to be determined later
S = piecewise(n == gam, ...
k*omega^n/factorial(n)*log(R/a), ...
(omega^n/(factorial(n)*(n-gam))*((R/a)^(k*(n-gam))-1)) );
S1=S1+S;
end
EQN = (nn/gam)*((1-g/delta)^((beta+1)/beta)-(a0/R)^((beta+1)/beta)) - S1;
matlabFunction(EQN, 'file', 'EQN.m', 'vars', {R, [a, a0, alpha, b0, beta, delta, gam, k, nn, nu]})
Now you can switch to the function that used to contain the code to build eqn, the one that had the vpasolve() call in it. Rewrite it:
%his section can be compiled, but you have to have created EQN.m first.
%assign the parameters. None of the below can involve symbolic computation!
a = whatever
a0 = whatever
alpha = whatever
b0 = whatever
beta = whatever
delta = whatever
gam = whatever
k = whatever
nn = whatever
nu = whatever
Rpl_max = whatever %not a parameter
parameters = [a, a0, alpha, b0, beta, delta, gam, k, nn, nu]; %do not include RPL_max
obj = @(R) EQN(R, parameters);
%The function to be solved has a single variable. We can use fzero, which
%permits us to pass in a range of values to solve over.
%notice that nothing here uses the Symbolic Toolbox
R = fzero(obj, [a0, Rpl_max]);
if isempty(R) || isnan(R)
%suppose there was no solution in that range?
end
Simone Pavan
Simone Pavan 2020 年 4 月 20 日
編集済み: Simone Pavan 2020 年 4 月 20 日
Sorry Walter,
fzero works only if my function changes sign.
If this doesn't happen, i.e. R is empty, how can I solve my equation?
Using original algorithm and vpasolve I can find my solution.

サインインしてコメントする。

その他の回答 (1 件)

Torsten
Torsten 2020 年 3 月 27 日
Use "fzero" or "fsolve".

カテゴリ

Help Center および File ExchangeCalculus についてさらに検索

Community Treasure Hunt

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

Start Hunting!

Translated by