EDA365电子论坛网
标题:
请问怎样用MATLAB求解微分方程组并画出解函数图?
[打印本页]
作者:
greensmile
时间:
2020-4-20 10:27
标题:
请问怎样用MATLAB求解微分方程组并画出解函数图?
求解微分方程组,画出解函数图。
! x, v2 `* A: ] ?7 `" X4 y
* y( l5 K$ J0 X0 T2 M
x'= -x^3-y, x(0)=1
5 |: ]& S: ~7 c n; w
y'= x-y^3, y(0)=0.5 0<t<30
, x% n6 R r' j6 X u
请教高手指点给出程序与结果,谢谢
+ c2 u; a$ ^5 N1 `+ Y+ R
作者:
yin123
时间:
2020-4-20 13:34
本帖最后由 yin123 于 2020-4-20 13:36 编辑
D/ H2 A0 K( a0 \. R' _5 s' S
9 |6 e3 O* H" j
碰巧正好学习了微分方程解法
$ X$ e0 L4 q8 |' z7 j$ T
matlab内置的函数(数值解法)有ode系列,help一下就可以了
" r6 S8 l u0 n9 h Z$ s/ J" C
如果你上的是有关数字分析的课程,我猜老师的意思应该让你自己写代码
# K, f+ Z$ O$ t* I& M, {
我分别尝试了Euler法 梯形法 四阶RK法 代码如下:
! [; Q& ?' I) M( X- n
以y‘=|sin2x、,y(0)=1为例:
" _1 W7 r) P" o. m, K
$ c" x; s8 _' Y% T
编写一阶导数m文件:
; U$ d F) Q @- P. F% x4 J: _
`7 G" f) p! d9 i0 o
%一阶常微分方程的m文件
2 A0 D2 W- ~: y( P3 _' C; Y
function y1=myfun(x,y)
! A( F, T% {$ m( i
y1=abs(sin(2*x));
+ Z2 K0 k5 c9 f O& }# [0 }7 Z
- Q# X0 P$ s3 b2 W( _
" N( ?) _0 n! w7 L" H: P( j, `
4 R; y) x, E1 C2 m
Euler法:
! ]( s! m/ ]) Z1 a! J
0 f6 M" |0 i- ?" ]& _' g
%向前差分Euler法解常微分方程
1 d1 o6 s9 `( H" J$ H
%fun:f(x)的一阶导数m文件
) w8 C. k2 z) x* T- S4 \2 ^, c
%x0,xt:自变量的初值和终值
. i( G% K+ ?" y+ M
%y0:f(x)在x0处的值
) H% Q/ t( Z$ b1 H7 J# `! k
%h:步长
7 D9 `( k( |6 Y6 N
function [Eulerx,Eulery]=MyEuler(myfun,x0,xt,y0,h)
% W: ?9 j& w: }6 _
x=(x0:h:xt)';%定义自变量数组
& j* m8 f7 { f e# a
y(1,: )=y0;%初始化因变量数组
% U( K( B( b& P, M, J. Z
for k = 1:length(x)-1
/ e" I9 H' h$ }9 _, w2 R ?
f=feval(myfun,x(k),y(k,: ));%计算每个迭代点的一阶导数值
# k S& g2 C8 T! u3 e8 s' ?
f=f(: )';
% g5 P. n3 s9 |& w4 P* d; w% K3 }
y(k+1,: )=y(k,: )+h*f; %向前迭代
4 A' Y3 |6 I3 N8 \0 n8 M& n" h
end
. w, V& t' ^6 U8 Q7 ?
Eulerx=x;
4 [: C$ g0 U9 I) i5 k4 T& p
Eulery=y;
$ ?6 g& y9 V: f3 I5 w! f) m- |
) |% n- j' ~& e* ~# V- s! u
7 P( G) n; M+ G H2 G7 j
梯形法:
$ ?% `3 X% k( A+ \2 P! u( q
% Z4 Y5 A) L' r' m
%梯形法解常微分方程
; d) ~8 q$ j* o
%fun:f(x)的一阶导数m文件
# B+ L z0 A" ?# |) K1 z
%x0,xt:自变量的初值和终值
( I: C0 m# e+ {0 T2 b$ z6 T3 @
%y0:f(x)在x0处的值
" J# _% `6 ^/ @1 y) G% ~- i5 i
%h:步长
' |# S9 Y; I! Z% @
function [Tixingx,Tixingy]=MyTixing(myfun,x0,xt,y0,h)
0 k7 _% i0 P$ `/ D
x=(x0:h:xt)';%定义自变量数组
$ q G* ]* }+ W' U7 C- z6 g4 N
y(1,: )=y0;%初始化因变量数组
& ?* w% n9 _" X, W i9 [8 a v
Y(1,: )=y0;%中间量
1 O$ }: C. p3 ]0 X- g- D
for k=1:length(x)-1
5 d) a8 ?. i* I, N. X
f=feval(myfun,x(k),y(k,: ) );%计算每个迭代点的一阶导数值
1 ~' c: }" j1 z( E$ v* j7 d
f=f(: )';
2 X+ X" a2 [2 d" }3 E N
Y(k+1,: )=y(k,: )+h*f; %y0(n+1)
5 P% T6 A9 ]" X4 o
F=feval(myfun,x(k+1),Y(k+1,: ));%计算每个迭代点的一阶导数值
/ G @$ B& v h4 G( n/ d7 Y
F=F(: )';
9 I, e# q8 i3 B5 p/ D
y(k+1,: )=y(k,: )+0.5*h*(f+F); %y(n+1)
0 o) j" {3 Z+ r
end
' K7 J1 s+ x3 ^- ]: g
Tixingx=x;
' C/ H7 E5 ]* q( k( G) E
Tixingy=y;
# R& C. T" a8 n
1 i1 P/ ^. y+ F% y
. G( R- s. Q- N0 F2 e& ]( y
四阶RK法:
; _# b( A# j u7 m" x0 p
9 Z: Y4 t+ v: B u2 }, r% Y/ a
%四阶Runge-Kutta法解常微分方程
2 s) x4 l* E, d" |
%fun:f(x)的一阶导数m文件
$ R2 G5 h* H! w: p- R
%x0,xt:自变量的初值和终值
* _$ X; o9 @. ^, U
%y0:f(x)在x0处的值
+ i$ d k: }$ q* S' c% v3 F. z5 Y
%h:步长
! J* c2 v9 N6 z; O6 l5 [0 O' M( P
function [RK4x,RK4y]=RK4(myfun,x0,xt,y0,h)
7 @7 s; N7 Z: s9 ]$ S# K- H- Q0 `
x=(x0:h:xt)';%定义自变量数组[code]clear all;clc;
# N2 r/ m" z3 X! s' `$ l
x0=0;xt=2*pi;%x0,xt:自变量的初值和终值
( c; X) P' k- a6 a
y0=1;%y0:f(x)在x0处的值
+ \' A3 @$ L, B- D) Z% g' g3 U! [
h=0.2;%h:步长
4 } x3 j- \' e7 a- j
[Eulerx,Eulery]=MyEuler(@myfun,x0,xt,y0,h);%欧拉法
& |' R- O g! P0 |( v
a=fliplr(Eulery');%求算f(22*pi)
2 S/ W- ]7 V2 D- r. r% V& i& \
y_Euler=a(1);
8 j2 d+ G' p$ A% t& U
[Tixingx,Tixingy]=MyTixing(@myfun,x0,xt,y0,h);%梯形法
1 w! B, I' A+ b( q' y! Y
a=fliplr(Tixingy');%求算f(22*pi)
$ G# A# x* [8 t0 E- r
y_Tixing=a(1);
) _: K1 A" ?7 a" E* S% }
[RK4x,RK4y]=RK4(@myfun,x0,xt,y0,h);%四阶Runge-Kutta法法
2 x3 X. q0 }7 H3 \8 A, o
a=fliplr(RK4y');%求算f(22*pi)
( e8 }# S, C+ @+ |
y_RK4=a(1);
& [9 E* u: F3 Z" |) ]7 }
[ode45x,ode45y]=ode45(@myfun,[x0:h:xt],[1]);%matlab内置函数
6 [' `' N$ b4 k( ^4 w
a=fliplr(ode45y');%求算f(22*pi)
* Z3 n" M/ W* A( o/ A- q# y5 N6 B
y_ode45=a(1);
. @9 {- k% e$ }% W+ u
figure;
4 @; F" f' j" |% v8 x/ ~
figure_FontSize=18; %修改字体
0 Z) l" x% H: w$ V8 `
plot(Eulerx,Eulery,'ro',Tixingx,Tixingy,'g*',RK4x,RK4y,'bd',ode45x,ode45y,'ks','LineWidth',2);%做图
, R$ D+ h- u$ S* d! v
legend('Euler','Tixing','RK4','ode45');%图例
5 G6 @& v, ^; x ?# c
Y=[y_Euler,y_Tixing,y_RK4,y_ode45];
2 C1 d1 k9 J; S8 Z
axis([x0 xt y0 max(Y)]); %定义坐标轴范围
# W# P) Q- a& u+ j% h
label1={'方法';'Euler';'Tixing';'RK4';'ode45'};
! [: D! Q, U# s) U
label2={'y(2π)';y_Euler;y_Tixing;y_RK4;y_ode45};
" K7 j4 O: ^* _! a. o% ]4 ~" I
% label=[label1,label2];
7 g" e G0 w3 x+ ]7 Q& S8 I, c2 n
text(x0+0.1*(xt-x0),0.8*max(Y),label1); %显示y(2π)
: y; K( D& b/ ]1 ^$ w0 P- S
text(x0+0.3*(xt-x0),0.8*max(Y),label2);
7 |# ?- y0 j2 l3 c$ F- W6 l- Y2 i
$ W! {6 {$ Z' g2 \: R" D
% P: p. ~; ` r" Q0 a" k7 l
y(1,: )=y0;%初始化因变量数组
& i* {) U! G% u' Y
for k=1:length(x)-1
5 ?2 E t! E$ u8 U% c9 Y
K1=feval(myfun,x(k),y(k,: ));%计算系数
0 @% {: @9 G0 D
K2=feval(myfun,x(k)+0.5*h,y(k,: )+0.5*K1');
y; {2 |/ N4 } Y3 H1 ?
K3=feval(myfun,x(k)+0.5*h,y(k,: )+0.5*K2');
0 c$ q7 U. K8 u, A1 \
K4=feval(myfun,x(k)+h,y(k,: )+h*K3');
. o! _( T8 r& e! t' }5 [3 \ N" g
y(k+1,: )=y(k,: )+(1/6)*h*(K1'+2*K2'+2*K3'+K4');%迭代
9 w" o; S1 r$ x9 U, r! D/ K# _, e! ]5 @
end
4 A+ [' j X; T2 v7 Y
RK4x=x;
6 p9 h2 X* |4 U% o, ~5 w7 f7 M, K
RK4y=y;
作者:
CCxiaom
时间:
2020-4-20 13:39
+ ~7 B+ w/ Z; `9 p, U6 N1 A6 M$ I
楼主的图用Forcal绘制,代码:
!using["XSLSF"]; //使用命名空间XSLSF
//数组xArray存放x的值;ti为当前有效值的个数;tmax为ti对应的时间;tmin为起始时间。
xt(t:k:xArray,ti,tmax,tmin)=
{
k=(t-tmin)/(tmax-tmin)*ti-1,
if[k<0, k=0], if[k>=ti, k=ti-1],
xArray.getrai[k]
};
//数组yArray存放y的值;ti为当前有效值的个数;tmax为ti对应的时间;tmin为起始时间。
yt(t:k:yArray,ti,tmax,tmin)=
{
k=(t-tmin)/(tmax-tmin)*ti-1,
if[k<0, k=0], if[k>=ti, k=ti-1],
yArray.getrai[k]
};
//函数定义,用于计算微分方程组中各方程右端函数值,连分式法对微分方程组积分一步函数pbs1将调用该函数f。
//t为自变量,x,y为函数值,dx,dy为右端函数值(即微分方程的值)。
f(t,x,y,dx,dy)=
{
dx=-(x^3)-y,
dy=x-y^3
};
//用连分式法对微分方程组进行积分,获得理论值。
//t1,t2为积分的起点和终点。
//h,s为自动变量。
//模块变量:hf为函数f的句柄,要预先获得该句柄;Array为工作数组;step为积分步长;eps为积分精度。
积分(t1,t2:h,s:hf,Array,step,eps)=
{
s=ceil[(t2-t1)/step], //计算积分步数
h=(t2-t1)/s, //重新计算积分步长
{ pbs1[hf,t1,Array,h,eps], //对微分方程组积分一步
t1=t1+h //积分步长增加
}.until[abs(t1-t2)<h/2] //连续积分至t2
};
数据(:i,h,t1,t2,x,y,static,free:hf,Array,step,eps,max,xArray,yArray,ti,tmax,tmin)= //微分方程组积分获得数据
{
if[free,delete(Array),delete(xArray),delete(yArray),return(0)],
hf=HFor("f"), //模块变量hf保存函数f的句柄,预先用函数HFor获得该句柄
step=0.01,eps=1e-6, //积分步长step要合适,积分精度eps越小越精确,用于对微分方程组积分一步函数pbs1
Array=new[rtoi(real_s),rtoi(2*15)], //申请工作数组
max=1001,
xArray=new[rtoi(real_s),rtoi(max)], //申请工作数组
yArray=new[rtoi(real_s),rtoi(max)], //申请工作数组
Array.setra(0,1,0.5), //设置积分初值,通过模块变量Array传递,Array是一个数组
xArray.setra(0,1), //设置xArray的第一个值
yArray.setra(0,0.5), //设置yArray的第一个值
ti=1, h=step*3, tmin=0, tmax=0, t1=0, t2=h,
i=1,(i<max).while{
积分(&t1,t2), //从t1积分到t2
Array.getra(0,&x,&y), //从数组Array获得t2时的积分值
xArray.setra(i,x), yArray.setra(i,y), //将积分值保存到数组
ti=i+1, tmax=t1, t2=t2+h,
i++
}
};
//绘制函数图形
(::hxt,hyt)= hxt=HFor("xt"), hyt=HFor("yt"); //获得函数xt和yt的句柄,保存在模块变量中
gleDrawScene[HFor("Scene")],stop(); //设置场景绘制函数后退出
Scene(::hxt,hyt,tmax,tmin)=
{
glClear[], //清除屏幕以及深度缓存
glLoadIdentity[], //重置视图
glTranslated[0,0,-20], //移动坐标,向屏幕里移动10个单元
glColor3d[0,0,1], //设置颜色
fgPlot[hxt,tmin,tmax,FG_Y,-1,2], //绘制一元函数图象
glColor3d[1,0,0], //设置颜色
fgPlot[hyt,tmin,tmax,FG_Y,-1,2] //绘制一元函数图象
};
! l# {3 Y) t2 A4 N6 V$ E) l
5 U' b* R2 F9 G
. A+ ~; a9 W4 m0 V6 E8 ^3 y8 ~ g+ s
9 L; D2 _8 ^! ^) p% p' O
* T2 n6 }4 d# O
17.jpg
(12.06 KB, 下载次数: 7)
下载附件
保存到相册
2020-4-20 13:38 上传
L9 v8 T4 c. f+ _4 s
/ E9 C- O1 B. r
% k$ o+ u9 Y/ n5 R
. f% [, O# c9 w7 F& X; y, |! p
! S/ `! E6 h: k: q) B
作者:
ExxNEN
时间:
2020-4-20 13:39
用1stOpt更简单:
3 }. a" b6 K0 d
Variable t=[0:0.2:30],x=1,y=0.5;
Plot x,y;
ODEFunction x'= -x^3-y, y'= x-y^3;
& D1 _ Z6 g4 p
1 G; k& `; G0 S, H: ^8 E
% Y( T+ ]1 u# k" N
& K u2 w5 n+ g8 c
欢迎光临 EDA365电子论坛网 (https://bbs.eda365.com/)
Powered by Discuz! X3.2