关于求解微分方程——初学Matlab里的 ODE求解器

学习背景

        最近想挖掘一下自己项目的理论深度,于是找到了老师。在老师的建议下,我们开始了漫长的研读老师的论文的旅程(论文名:Optimal Design of Adaptive Robust Control for Fuzzy Swarm Robot Systems 模糊群自适应鲁棒控制的优化设计机器人系统)。这篇文章写的是关于群体智能控制在机器人群中的运用,提到了许多控制理论。诸如李雅普诺夫方程,模糊群分析,优化理论等等。作为一个理论白痴我选择将这些理论的东西的学习理解交给我的大佬队友。然后我选择了学习最后的simulation(实验仿真)。这里面的simulation用到了一种求解隐式微分方程的方法。于是就有了这篇文章的由来。

求解常微分方程组的方法

1、dsolve 函数

dsolve函数用于求常微分方程组的精确解,也称为常微分方程的符号解。如果没有初始条件或边界条件,则求出通解;如果有,则求出特解。

1)函数格式  

Y = dsolve(‘eq1,eq2,…’ , ’cond1,cond2,…’ , ’Name’)

其中,‘eq1,eq2,…’:表示微分方程或微分方程组;

            ’cond1,cond2,…’:表示初始条件或边界条件;

            ‘Name’:表示变量。没有指定变量时,matlab默认的变量为t;

2)例程

例1.1(dsolve 求解微分方程)

        求解微分方程:

        \frac{dy}{dx}=3x^{2}

在命令行输入: dsolve('Dy=3*x^2','x') ,摁下enter键后输出运行结果。

例1.2(加上初始条件)

求解微分方程:

只需要在命令行添加初始条件即可,此时求出的即为方程的特解。可以看到上例中的C9变为了2。

 

例2(dsolve 求解微分方程组)

求解微分方程组: 

由于x,y均为t的导数,所以不需要在末尾添加’t’。

2、ode函数

在上文中我们介绍了dsolve函数。但有大量的常微分方程,虽然从理论上讲,其解是存在的,但我们却无法求出其解析解,此时,我们需要寻求方程的数值解。

怎么理解数值求解呢?数值分析是一门专门的学科,在此不过多介绍。我主要想通过一个简单的例子来向大家阐述数值求解的思想。

比如,求解微分方程  。我们就可以转化为,那么。因此,我们可以通过迭代的方式来求解y。即可理解为步长。

ode是Matlab专门用于解微分方程的功能函数。该求解器有变步长(variable-step)和定步长(fixed-step)两种类型。不同类型有着不同的求解器。

然后我又从其他大佬那ctrl+v了一份具体点的ODE求解器的整理。

在工程实践中,我们经常遇到一些ODEs,其中某些解变换缓慢,另一些变化很快,且相差悬殊的微分方程,这就是所谓的刚性问题(Stiff),对于所有解的变化相当我们则称为非刚性问题(Nonstiff)。
变步长模式解法器有:ode45,ode23,ode113,ode15s,ode23s,ode23t,ode23tb和discrete。

a) ode45:缺省值,四/五阶龙格-库塔法,适用于大多数连续或离散系统,但不适用于刚性(stiff)系统。它是单步解法器,也就是,在计算y(tn)时,它仅需要最近处理时刻的结果y(tn-1)。一般来说,面对一个仿真问题最好是首先试试ode45。
b) ode23:二/三阶龙格-库塔法,它在误差限要求不高和求解的问题不太难的情况下,可能会比ode45更有效。也是一个单步解法器。
c) ode113:是一种阶数可变的解法器,它在误差容许要求严格的情况下通常比ode45有效。ode113是一种多步解法器,也就是在计算当前时刻输出时,它需要以前多个时刻的解。
d) ode15s:是一种基于数字微分公式的解法器(NDFs)。也是一种多步解法器。适用于刚性系统,当用户估计要解决的问题是比较困难的,或者不能使用ode45,或者即使使用效果也不好,就可以用ode15s。
e) ode23s:它是一种单步解法器,专门应用于刚性系统,在弱误差允许下的效果好于ode15s。它能解决某些ode15s所不能有效解决的stiff问题。
f) ode23t:是梯形规则的一种自由插值实现。这种解法器适用于求解适度stiff的问题而用户又需要一个无数字振荡的解法器的情况。
g)ode23tb:是TR-BDF2的一种实现, TR-BDF2 是具有两个阶段的隐式龙格-库塔公式。 
h)discrtet:当Simulink检查到模型没有连续状态时使用它。
固定步长模式解法器有:ode5,ode4,ode3,ode2,ode1和discrete。
a) ode5:缺省值,是ode45的固定步长版本,适用于大多数连续或离散系统,不适用于刚性系统。
b) ode4:四阶龙格-库塔法,具有一定的计算精度。
c) ode3:固定步长的二/三阶龙格-库塔法。
d) ode2:改进的欧拉法。
e) ode1:欧拉法。
f) discrete:是一个实现积分的固定步长解法器,它适合于离散无连续状态的系统。

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^分割线^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

其中,ode45求解器属于变步长的一种,采用Runge-Kutta算法;其他采用相同算法的变步长求解器还有ode23。ode45表示采用四阶-五阶Runge-Kutta算法,它用4阶方法提供候选解,5阶方法控制误差,是一种自适应步长(变步长)的常微分方程数值解法,其整体截断误差为(Δx)^5。解决的是Nonstiff(非刚性)常微分方程。

ode45是解决数值解问题的首选方法,若长时间没结果,应该就是刚性的,可换用ode15s试试。

下面将以ode45为例具体介绍函数的使用方法。

1)函数格式  

[T,Y] = ode45(‘odefun’,tspan,y0)

[T,Y] = ode45(‘odefun’,tspan,y0,options)

[T,Y,TE,YE,IE] = ode45(‘odefun’,tspan,y0,options)

sol = ode45(‘odefun’,[t0 tf],y0...)

其中: odefun是函数句柄,可以是函数文件名,匿名函数句柄或内联函数名;

          tspan 是求解区间 [t0 tf],或者一系列散点[t0,t1,...,tf];

          y0 是初始值向量

          T 返回列向量的时间点

          Y 返回对应T的求解列向量

          options 是求解参数设置,可以用odeset在计算前设定误差,输出参数,事件等

           TE 事件发生时间

           YE 事件发生时之答案

            IE 事件函数消失时之指针i

2)微分方程标准化

利用ode45求解高阶微分方程时,需要做变量替换。下面说明替换的基本思路。

微分方程为

初始条件

首先做变量替换 

原微分方程可以转换为下面的微分方程组的格式:

下面就可以利用转换好的微分方程组来编写odefun函数。

实战运用

例3.1(编写odefun函数)

在matlab中新建脚本文件,编写函数如下:

关于求解微分方程——初学Matlab里的 ODE求解器_第1张图片

 

本例中只需在例3.1的基础上编写主函数,加上求解区间和边值条件即可。需要注意的是,ode45的运行结果以列向量形式给出。因此在本例中,x的第一列为y,第二列为y’。如果遇到变量不是列向量形式的,可以考虑利用reshape函数做矩阵变换。

则,plot(t,x(:,1))画出来的是x的第一列数据,即为y;

        plot(t,x(:,2))画出来的是x的第二列数据,即为y’;

关于求解微分方程——初学Matlab里的 ODE求解器_第2张图片

 得到的结果如下:关于求解微分方程——初学Matlab里的 ODE求解器_第3张图片

 这算是ode45的一个小实战了吧

那么这个时候咱们来看看ode15s。

关于求解微分方程——初学Matlab里的 ODE求解器_第4张图片

 咱就是说,对于一个理论白痴而言,这个ode15s的用法不就跟ode45的用法一样嘛(后来我看了下好像好几个ode求解器的用法都一个样子)。想要运用这个那还不简单hhh。直接开搞

还是用上面那个例子:

关于求解微分方程——初学Matlab里的 ODE求解器_第5张图片

关于求解微分方程——初学Matlab里的 ODE求解器_第6张图片

 没错,就是把ode45更改成ode15s就行了(其余求解器同理hhh)。

对比一下两个图像,发现仅仅就是点集的密集程度不同,还没有很大的差别。

然后感觉这个小例子不太好玩,想玩点更高级的。

混沌

混沌运动的直观形象,在随能量不断耗散而自由度降低的耗散系统中看得更清楚。1963年美国气象学家E.洛伦茨在研究对天气至关紧要的热对流问题时,把包含无穷多自由度的热对流偏微分方程简化为三个变量的一阶非线性常微分方程组:

dx/dt=-σx+σy

dy/dt=rxyxz

dz/dt=bz+xy

式中变量x表示大气对流强度,y表示上升流与下降流温差,z表示垂直温度剖面变化。系数σ为普朗特数,r为瑞利数,b为量度水平温度结构与垂直温度结构衰减率之差异。洛伦茨选定σ=10,r=28,b=8/3,然后数值求解方程组。结果发现,这极度简化了的系统,出现了极为复杂的运动形式。起始值的细微变化,足以使轨道全然改观。把数值计算结果在由x,y,z支撑的三维相空间中画出来。这是一条在三维空间似乎无序地左右回旋的连续光滑曲线,它并不自我相交,呈现复杂的结构纹样。无论初始值选取在哪里,系统轨道有同一归宿,形成所谓奇异吸引子。在奇异吸引子上,如果选取任意接近的两个点为初始值,其运动轨迹以指数方式迅速分离,表现出对初值的极端敏感。具体的是,轨道左右跳动的顺序和次数完全不同。计算表明,初始位置几乎会聚在一起的10,000个点,稍后便会在图中所示的吸引子上到处分布,说明这样的系统中,由于初值的细微不同,运动是不可预测的。(更多的在这)

看不懂没关系,因为我也看不太懂hhh(不愧是理论白痴),咱就来看看这个微分方程,自己用求解器解着玩一玩呗。

        \frac{dx}{dt}=\delta (y-x)         (1)

        \frac{dy}{dt} = rx-y-xz (2)

        \frac{dz}{dt}=xy-bz        (3)

(咱就是说,百度百科里的这个式子少了个负号,我跑matlab发现没负号是跑不出来的。无论哪个求解器都不行。然后看了看其他地方的混沌理论的式子,确实是-bz)

没问题了那就跑呗。

关于求解微分方程——初学Matlab里的 ODE求解器_第7张图片

为啥代这几个值(我看的视频),不过我查了一下hhh这几个参数是来源于某个地方: 奇异吸引子(Strange Attractor)——非线性系统的一大杰作(这是我看的资料来源)

然后接着敲代码:

关于求解微分方程——初学Matlab里的 ODE求解器_第8张图片

 先跑一跑一阶的x。

关于求解微分方程——初学Matlab里的 ODE求解器_第9张图片

 已经有点混沌的影子了;

二阶:

关于求解微分方程——初学Matlab里的 ODE求解器_第10张图片

关于求解微分方程——初学Matlab里的 ODE求解器_第11张图片

 这里是用y和z跑的图像。用x,y;x,z跑出来又不一样:

关于求解微分方程——初学Matlab里的 ODE求解器_第12张图片 关于求解微分方程——初学Matlab里的 ODE求解器_第13张图片

有点内味了叭!

下面将隆重推出三阶最终的图像:

关于求解微分方程——初学Matlab里的 ODE求解器_第14张图片

 有没有感觉像一个蝴蝶?哈哈,没错。告诉大家一个秘密,其实这才是蝴蝶效应名字的由来。

以上代码是用ode45跑的,用另外一个求解器同理。

总结

 真没啥总结。整理下来证明了自己还是学了东西的hhh。老师说,我们后面在跑证明的时候会出现用ode45解不出来的式子,而用ode15s和其他几个求解器能跑出来。这是由于不同的求解器内部都有不同的算法,能求解不同的式子,达到不同的精度。就是说有点子好奇与期待了!

放一张老师论文里的仿真图:

关于求解微分方程——初学Matlab里的 ODE求解器_第15张图片

 下次文章如果大家能看到我把以上4个图里的3个参数变成5个,那就说明我对于自己项目的理论的仿真部分算是成功了哈哈哈!

——————————————再来个分割线——————————————————————

        能读到这的友友那说明真的是真爱了hhh(不管你是划到这来看还是读完全文看到这来的嘿嘿)。作为一个应用党而不是理论钻研党,其实对很多知识的掌握仅仅是浮在表面上罢了。可那又如何?应用也是同样重要的哇!同时,善于总结,才能收获新知。有的东西如果自己不留点痕迹,也许用完就会忘掉。最后,希望大家都能学有所获叭!

参考文献:

1、计算群体智能算法——粒子群算法(PSO) - 知乎

2、李亚普诺夫方程_百度百科

3、https://blog.csdn.net/lynn15600693998/article/details/86597068

4、matlab求解器区别_邓肯的博客-CSDN博客

5、混沌(非线性科学概念)_百度百科

你可能感兴趣的:(matlab,算法)