Substitute the nonlinearity in the linear system

3 ビュー (過去 30 日間)
Ivan Khomich
Ivan Khomich 2020 年 7 月 30 日
コメント済み: Ivan Khomich 2020 年 7 月 31 日
Hello everyone! I have a question about possibility of substituting some nonlinear function in system of lode’s.
For example, I have a system:
iN=1;%line
jN=2;%row
Nonlinearity=@(x) x^2;
[T,X]=ode45(@(t,x) odesys(t,x,Nonlinearity,iN,jN), [0 2],[0 0.1]
function RPF=odesys(t,x,Nonlinearity, iN, jN)
A=[0 1;0 -1];
B=[0 1];
A(iN,jN)=A(iN,jN)*Nonlinearity(x(jN))/x(jN);
RPF=A*x+B;
end
Obviously this works only if x(jN) does’nt equal zero during the integration progress, and I may suppose that this will produce some calculating errors because of dividing.
So I want to know is there better way to do this.
Thank you in advance!

採用された回答

Walter Roberson
Walter Roberson 2020 年 7 月 30 日
If you do encounter a division by 0 during calculations, then odesys will end up returning a value that includes either infinite or nan (or both). That will typically not be noticed immediately, but instead the next call to odesys will very likely end up returning mostly or all nan. Everything will fall apart from there.
There are narrow circumstances under which ode45() will notice the big value and recover smoothly, just saying "Oh, I guess that step failed" -- but for that to happen, you have to get lucky enough that the division by 0 was on the very last of the 6 odefun calls per iteration that ode45 makes. Much more typical is that you just start going haywire and figuring out why can be a pain.
So... What you should can is a test such as
RPF(~isfinite(RPF)) = 1e100; %some big value that is going to be far from normal values
This will eliminate some of the problems, allowing for a cleaner recover.
You should also, however, add an event function through the options structure, and the event function should be marked as Terminal, and Both Directions, and the value to test should be x(2) . An event function such as that will go as close to the border where x(2) becomes 0 as it can, and then will exit ode45 early. You can tell that the exit was early by checking the last time returned.
This particular exception is probably not "removable": if x(jN) becomes 0 because it must due to the initial conditions, then there is not much you can do except quit. There are a lot of other cases where when the exception is detected, that you want to change the boundary conditions. I recommend Mathwork's example ballode which shows how to use events to cause a ball to "bounce" when it hits the floor (it reverses the velocity and then restarts ode45() )
  7 件のコメント
Walter Roberson
Walter Roberson 2020 年 7 月 30 日
If your nonlinear function is continuous and twice differentiable, then if you have the Symbolic Toolbox, you could probably construct the forms symbolically and then use odeFunction() to create the anonymous function.
This will not work without a bit of twisting if the function includes min() or max() or mod() : the symbolic versions of those usually do not do what is desired. (On the other hand, those are not differentiable.)
If the nonlinear function has iteration based upon getting down to some particular absolute or relative error, then there could be a problem using symbolic variables with it.
If the nonlinear function compares the inputs to values then a bit of redesign could be needed (but such cases are typically not twice differentiable unless they are carefully constructed.)
Ivan Khomich
Ivan Khomich 2020 年 7 月 30 日
The functions I need to consider are “good”, so the only problem is constructing the system.

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

その他の回答 (1 件)

Ivan Khomich
Ivan Khomich 2020 年 7 月 30 日
I solve this problem by Symbolic Toolbox, as Walter Roberson suggested, so if anyone someday will need this I post my solution:
function fuf
Nonlin=@(x) x^2;
SysOrder=2;
iN=1;
jN=2;
syms xs [1 SysOrder]
A=[0 1;0 -1];
B=[0 ;1];
LinearSystem=A*xs.'+B;
LinearSystem(iN)=subs(LinearSystem(iN), xs(jN),Nonlin(xs(jN)));
[~,X]=ode45(@(t,x) odesys(t,x,LinearSystem, SysOrder), [0 2], [0 0]);
function RPF= odesys(t,x,LinearSystem,SysOrder)
syms xs [1 SysOrder]
RPF=double(subs(LinearSystem, xs(1:SysOrder).', x(1:SysOrder)));
But question partially still open: Is there another way to do this, because of time that code needs to operate with symbolic variables is extremely high(For example, my main programm without this novelty requires 0.5-1s, and 190s with it).
  3 件のコメント
Ivan Khomich
Ivan Khomich 2020 年 7 月 31 日
編集済み: Walter Roberson 2020 年 7 月 31 日
Thank you very much, Walter!
I tried to do what I‘ve done in last example, but before the ode45 function and get the success in the mobile version. So, I’ll try this later on PC and expect it will work faster.
function fuf
Nonlin=@(x) x^2;
SysOrder=2;
iN=1;
jN=2;
syms xs [1 SysOrder]
A=[0 1;0 -1];
B=[0 ;1];
LinearSystem=A*xs.'+B;
LinearSystem(iN)=subs(LinearSystem(iN), xs(jN),Nonlin(xs(jN)));
NonlinearSystem=@(x) double(subs(LinearSystem, xs(1:SysOrder).', x(1:SysOrder)));
[~,X]=ode45(@(t,x) odesys(t,x, NonlinearSystem, SysOrder), [0 2], [0 0]);
[~,X1]=ode45(@(t,x) [(x(2))^2;1-x(2)],[0 2],[0 0]);
sum((X-X1).^2)
function RPF= odesys(t,x, NonlinearSystem,SysOrder)
RPF= NonlinearSystem(x);
Ivan Khomich
Ivan Khomich 2020 年 7 月 31 日
The new attempt faster three times, but it still requires a lot of time for calculations(~50 s).
I don't really understand why this happen, beacuse I do not see the difference between numeric system created from symbolic and numeric system handwritten.
If it will not bother you, can you explain why this happen and maybe suggest other way to approach the problem?

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

カテゴリ

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

Community Treasure Hunt

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

Start Hunting!

Translated by