Matlab:非线性高阶常微分方程的几种解法

一、隐式Euler:

函数文件1:

1 function b=F(t,x0,u,h)
2       b(1,1)=x0(1)-h*x0(2)-u(1);
3       b(2,1)=x0(2)+2*h*x0(2)/t+4*h*(2*exp(x0(1))+exp(x0(1)/2))-u(2);

函数文件2:

1 function g=Jacobian(x0,t,h)
2   g(1,1)=1;
3   g(1,2)=-h;
4   g(2,1)=4*h*(2*exp(x0(1))+0.5*exp(x0(1)/2));
5   g(2,2)=1+2*h/t; 

函数文件3:

 1 function x=newton_Iterative_method(t,u,h)
 2  % u:上一节点的数值解或者初值
 3  % x0 每次迭代的上一节点的数值
 4  % x1 每次的迭代数值
 5  % tol 允许误差
 6  % f 右端函数
 7 x0=u;
 8 tol=1e-14;
 9 x1=x0-Jacobian(x0,t,h)\F(t,x0,u,h);
10 while (norm(x1-x0,inf)>tol)
11     %数值解的2范数是否在误差范围内
12     x0=x1;
13     x1=x0-Jacobian(x0,t,h)\F(t,x0,u,h);
14 end
15 x=x1;%不动点

脚本文件:

 1 tic;
 2 clear all
 3 clc
 4 N=[128 64 32 16 8 4];
 5 for j=1:length(N)
 6 h=1/N(j);
 7 x=0:h:1;
 8 y=inline('-2*log(1+x.^2)','x');
 9 Accurate=y(x);
10 Numerical=zeros(2,N(j)+1);
11 for i=1:N(j)
12  Numerical(1:2,i+1)=newton_Iterative_method(x(i+1),Numerical(1:2,i),h);
13 end
14 error(1:N(j)+1,j)=Numerical(1,:)-Accurate;
15 figure(j)
16 subplot(1,3,1)
17 plot(x,Accurate);
18 xlabel('x');
19 ylabel('Accurate');
20 grid on
21 subplot(1,3,2)
22 plot(x,Numerical(1,:));
23 xlabel('x');
24 ylabel('Numerical');
25 grid on
26 subplot(1,3,3)
27 plot(x,error(1:N(j)+1,j));
28 xlabel('x');
29 ylabel('error');
30 title(1/N(j));
31 grid on
32 end
33 for k=2:length(N)
34     X=norm(error(:,k),inf)/norm(error(:,1),inf);
35     H=N(1)/N(k);
36 Y(k-1)=log(X)/log(H);
37 end
38 figure(length(N)+1)
39 plot(1:length(N)-1,Y,'-r v');
40 ylabel('误差阶数');
41 title('误差阶数');
42 toc;

效果图:

 

 二、变步长的隐式Euler方法:

函数文件1:

1 function b=F(t,x0,u,h)
2       b(1,1)=x0(1)-h*x0(2)-u(1);
3       b(2,1)=t*x0(2)+2*h*x0(2)+4*h*t*(2*exp(x0(1))+exp(x0(1)/2))-t*u(2);

函数文件2:

1 function g=Jacobian(x0,t,h)
2   g(1,1)=1;
3   g(1,2)=-h;
4   g(2,1)=4*h*t*(2*exp(x0(1))+0.5*exp(x0(1)/2));
5   g(2,2)=t+2*h; 

函数文件3:

 1 function x=Euler(t,u,h)
 2  % u:上一节点的数值解或者初值
 3  % x0 每次迭代的上一节点的数值
 4  % x1 每次的迭代数值
 5  % tol 允许误差
 6  % f 右端函数
 7 x0=u;
 8 tol=1e-5;
 9 x1=x0-Jacobian(x0,t,h)\F(t,x0,u,h);
10 while (norm(x1-x0,inf)>tol)
11     %数值解的2范数是否在误差范围内
12     x0=x1;
13     x1=x0-Jacobian(x0,t,h)\F(t,x0,u,h);
14 end
15 x=x1;%不动点

脚本文件:

 1 tic;
 2 clear 
 3 clc
 4 y(1:2,1)=[0;0];%初值
 5 e=1e-5;%误差过小
 6 tol=1e-5;%指定的误差
 7 N=16;%节点的步数
 8 h=1/N;%初始步长
 9 t=0:h:1;
10 i=1;
11 while t(i)<=1
12     k=1;
13     while k==1
14     y(1:2,i+1)=Euler(t(i)+h,y(1:2,i),h);%符合误差的数值解
15 % y1_half=Euler(h/2,y(1:2,i));%半步长的中点数值解
16  y1_half=Euler(t(i)+h,y(1:2,i),h/2);%半步长的右端点的数值解
17  y1_one=Euler(t(i)+h,y1_half,h/2);
18 Estimate_error=2*norm(y(1:2,i+1)-y1_one);%中间估计误差
19 if Estimate_error<tol%指定误差
20     k=0;%步长相差不大,或者说正好在指定的误差范围内,则确定选择h作为步长。
21 elseif Estimate_error<e%误差过小
22     h=2*h;
23 else%近似估计误差大于指定误差
24     h=h/2;
25 end
26     end
27    t(i+1)=t(i)+h;
28    i=i+1;
29 end
30 f=inline('-2*log(1+x.^2)','x');
31 Accurate=f(t);
32 subplot(1,3,1)
33 plot(t,y(1,:));
34 xlabel('t');ylabel('numerical');
35 title('the image of numerical solution');
36 grid on ;
37 subplot(1,3,2)
38 plot(t,Accurate);
39 xlabel('t');ylabel('Accurate');
40 title('the image of Accurate solution');
41 grid on ;
42 subplot(1,3,3)
43 plot(t,y(1,:)-Accurate);
44 xlabel('t');ylabel('error');
45 title('the image of error solution');
46 grid on ;
47 toc;

效果图:

中心差分法:

 

 函数文件1:

1 function b=F(t,x0,h,N)
2 b(1,1)=4*x0(1)-x0(2);
3 b(2,1)=-2*x0(1)+4*h^2*(2*exp(x0(1))+exp(x0(1)/2))+(1+h/t(2))*x0(2);
4 for i=2:N-1
5     b(i+1,1)=(1-h/t(i+1))*x0(i-1)-2*x0(i)+4*h^2*(2*exp(x0(i))+exp(x0(i)/2))+(1+h/t(i+1))*x0(i+1);
6 end


函数文件2:

 1 function g=Jacobian(t,x0,h,N)
 2 g(1,1)=4;
 3 g(1,2)=-1;
 4 g(2,1)=-2+4*h^2*(2*exp(x0(1))+1/2*exp(x0(1)/2));
 5 g(2,2)=1+h/t(2);
 6 for i=2:N-1
 7 g(i+1,i-1)=1-h/t(i+1);
 8 g(i+1,i)=-2+4*h^2*(2*exp(x0(i))+1/2*exp(x0(i)/2));
 9 g(i+1,i+1)=1+h/t(i+1);
10 end

函数文件3:

 1 function x=newton_Iterative_method(t,u,h,N)
 2  % u:上一节点的数值解或者初值
 3  % x0 每次迭代的上一节点的数值
 4  % x1 每次的迭代数值
 5  % tol 允许误差
 6  % f 右端函数
 7 x0=u;
 8 tol=1e-11;
 9 x1=x0-Jacobian(t,x0,h,N)\F(t,x0,h,N);
10 while (norm(x1-x0,inf)>tol)
11     %数值解的2范数是否在误差范围内
12     x0=x1;
13     x1=x0-Jacobian(t,x0,h,N)\F(t,x0,h,N);
14 end
15 x=x1;%不动点

脚本文件:

 1 tic;
 2 clear
 3 clc
 4 N=[10,20,40,80,160,320,640];
 5 for k=1:length(N)
 6 h=1/N(k);
 7 x=0:h:1;
 8 fun1=inline('-2*log(1+x.^2)');
 9 for i=1:length(x)
10 Accurate(i,1)=fun1(x(i));
11 end
12 Numerical=zeros(N(k)+1,1);
13 Numerical(2:end,1)=newton_Iterative_method(x,Numerical(2:end,1),h,N(k));
14 error=Numerical-Accurate;
15 error_inf(k)=norm(error,inf);
16 figure(k)
17 subplot(1,3,1)
18 plot(x,Accurate);
19 xlabel('x');
20 ylabel('Accurate');
21 grid on
22 subplot(1,3,2)
23 plot(x,Numerical);
24 xlabel('x');
25 ylabel('Numerical');
26 grid on
27 subplot(1,3,3)
28 plot(x,error);
29 xlabel('x');
30 ylabel('error');
31 grid on
32 end
33 for i=2:length(N)
34 INF(i-1)=log2(error_inf(i-1)/error_inf(i));
35 end
36 figure(length(N)+1)
37 plot(1:length(N)-1,INF,'-rh');
38 xlabel('x');
39 ylabel('误差阶数');
40 title('非线性高阶常微分差分格式误差阶');
41 grid on
42 toc;

效果图:

 

posted @ 2017-03-14 20:40  胡冬冬  阅读(14188)  评论(0编辑  收藏  举报