我试图用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()。但它一直给我一个隐含的解决方案......
有谁知道为什么会这样?任何建议表示赞赏。谢谢!
答案 0 :(得分:0)
由于您的代码似乎适用于更简单的函数,您可以尝试增加ode45解算器的精度选项。
这可以通过使用 odeset :
来实现 options = odeset('RelTol',1e-10,'AbsTol',1e-10);
[T,Y] = ode45(@function,[tspan],[y0],options);