Matlab - 微分方程求解器Ode45的意外结果

时间:2014-09-09 21:29:00

标签: matlab ode differential-equations

我试图用MATLAB求解ode求解器ode45的微分方程。我已经尝试将它与其他更简单的函数一起使用,并让它绘制函数。它们看起来都是正确的,但是当我插入我需要解决的功能时,它就失败了。该图从y(0)= 1开始,但是在它应该是一直增加的函数直到其临界点的某个时刻开始减小。

function [xpts,soln] = diffsolver(p1x,p2x,p3x,p1rr,y0)
syms x y
yp = matlabFunction((p3x/p1x) - (p2x/p1x) * y); 
[xpts,soln] = ode45(yp,[0 p1rr],y0); 

p1x,p2x和p3x是多项式,它们作为参数传递到此diffsolver函数中。

p1rr这是关键点。该函数应该在临界点之后发散,所以我想将它集成到那一点。

编辑:这是我在使用diffsolver之前的代码,上面的函数。我做pade近似以找到多项式p1,p2和p3。然后我找到临界点,它是最接近目标的p1的根(目标由用户指定)。

我检查临界点是否为空(有时在某些功能中可能没有临界点)。如果它不为空,那么它使用上述函数来求解微分方程。然后它基本上绘制了从上述函数返回的x和y点。

function error = padeapprox(m,n,j)
global f df p1 p2 p3 N target

error = 0;
size = m + n + j + 2;

A = zeros(size,size);
for i = 1:m
    A((i + 1):size,i) = df(1:(size - i));
end
for i = (m + 1):(m + n + 1)
    A((i - m):size,i) = f(1:(size + 1 - i + m));
end
for i = (m + n + 2):size
    A(i - (m + n + 1),i) = -1;
end

if det(A) == 0
    error = 1;
    fprintf('Warning: Matrix is singular.\n');
end

V = -A\df(1:size); 

p1 = [1];
for i = 1:m
    p1 = [p1; V(i)];
end

p2 = [];
for i = (m + 1):(m + n + 1)
    p2 = [p2; V(i)];
end

p3 = [];
for i = (m + n + 2):size
    p3 = [p3; V(i)];
end

fx = poly2sym(f(end:-1:1)); 
dfx = poly2sym(df(end:-1:1));
p1x = poly2sym(p1(end:-1:1)); 
p2x = poly2sym(p2(end:-1:1)); 
p3x = poly2sym(p3(end:-1:1)); 
p3fullx = p1x * dfx + p2x * fx; 
p3full = sym2poly(p3fullx); p3full = p3full(end:-1:1); 

p1r = roots(p1(end:-1:1));
p1rr = findroots(p1r,target); % findroots eliminates unreal roots and chooses the one closest to the target

if ~isempty(p1rr)
    [xpts,soln] = diffsolver(p1x,p2x,p3fullx,p1rr,f(1));
    if rcond(A) >= 1e-10
        plot(xpts,soln); axis([0 p1rr 0 5]); hold all
    end
end

我看到一些使用另一个函数生成微分方程的例子,但我尝试使用matlabFunction()方法和其他更简单的函数,看起来它的工作原理。只是当我尝试解决这个功能时,它失败了。当它们都应该是正数时,解决的值开始变为负值。

我也尝试过使用另一个解算器dsolve()。但它一直给我一个隐含的解决方案......

有谁知道为什么会这样?任何建议表示赞赏。谢谢!

1 个答案:

答案 0 :(得分:0)

由于您的代码似乎适用于更简单的函数,您可以尝试增加ode45解算器的精度选项。

这可以通过使用 odeset

来实现
 options = odeset('RelTol',1e-10,'AbsTol',1e-10);
 [T,Y] = ode45(@function,[tspan],[y0],options);