Python小白的数学建模课-10 微分方程边值问题

Posted youcans

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python小白的数学建模课-10 微分方程边值问题相关的知识,希望对你有一定的参考价值。


小白往往听到微分方程就觉得害怕,其实数学建模中的微分方程模型不仅没那么复杂,而且很容易写出高水平的数模论文。

本文介绍微分方程模型边值问题的建模与求解,不涉及算法推导和编程,只探讨如何使用 Python 的工具包,零基础求解微分方程模型边值问题。

通过 3个 BVP 案例层层深入,手把手教你搞定微分方程边值问题。

欢迎关注『Python小白的数学建模课 @ Youcans』系列,每周持续更新



1. 常微分方程的边值问题(BVP)

1.1 基本概念

微分方程是指含有未知函数及其导数的关系式。

微分方程是描述系统的状态随时间和空间演化的数学工具。物理中许多涉及变力的运动学、动力学问题,如空气的阻力为速度函数的落体运动等问题,很多可以用微分方程求解。微分方程在化学、工程学、经济学和人口统计等领域也有广泛应用。

微分方程分为初值问题和边值问题。初值问题是已知微分方程的初始条件,即自变量为零时的函数值,一般可以用欧拉法、龙哥库塔法来求解。边值问题则是已知微分方程的边界条件,即自变量在边界点时的函数值。

边值问题的提出和发展,与流体力学、材料力学、波动力学以及核物理学等密切相关,并且在现代控制理论等学科中有重要应用。例如,力学问题中的悬链线问题、弹簧振动问题,热学问题中的导热细杆问题、细杆端点冷却问题,流体力学问题、结构强度问题。

上节我们介绍的常微分方程,主要是微分方程的初值问题。本节介绍二阶常微分方程边值问题的建模与求解。

欢迎关注『Python小白的数学建模课 @ Youcans』系列,每周持续更新
Python小白的数学建模课-01.新手必读
Python小白的数学建模课-02.数据导入
Python小白的数学建模课-03.线性规划
Python小白的数学建模课-04.整数规划
Python小白的数学建模课-05.0-1规划
Python小白的数学建模课-06.固定费用问题
Python小白的数学建模课-07.选址问题
Python小白的数学建模课-09.微分方程模型
Python小白的数学建模课-10.微分方程边值问题

1.2 常微分方程边值问题的数学模型

只含边界条件作为定解条件的常微分方程求解问题,称为常微分方程的边值问题(boundary value problem)。

一般形式的二阶常微分方程边值问题:
y   ′ ′ = f ( x , y , y   ′ ) ,    a < x < b y{\\ ''} = f(x,y,y{\\ '}),\\; a<x<b y =f(x,y,y )a<x<b

有三种情况的边界条件:

(1)第一类边界条件(两点边值问题):

y ( a ) = y a , y ( b ) = y b y(a)=ya,y(b)=yb y(a)=yay(b)=yb

(2)第二类边界条件:

y   ′ ( a ) = y a , y   ′ ( b ) = y b y\\ '(a)=ya,y\\ '(b)=yb y (a)=yay (b)=yb

(3)第三类边界条件:
{ y   ′ ( a ) − a 0   y ( a ) = a 1 y   ′ ( b ) − b 0   y ( b ) = b 1 \\begin{cases} y\\ '(a)-a_0\\ y(a) = a_1\\\\ y\\ '(b)-b_0\\ y(b) = b_1 \\end{cases} {y (a)a0 y(a)=a1y (b)b0 y(b)=b1

其中: a 0 ≥ 0 , b 0 ≥ 0 , a 0 + b 0 > 0 a_0 \\geq 0,b_0 \\geq 0,a_0+b_0>0 a00b00a0+b0>0


1.3 常微分方程边值问题的数值解法

简单介绍求解常微分方程边值问题的数值解法,常用方法有:打靶算法、有限差分法和有限元法。打靶算法把边值问题转化为初值问题求解,是根据边界条件反复迭代调整初始点的斜率,使初值问题的数值解在边界上“命中”问题的边值条件。有限差分法把空间离散为网格节点,用差商代替微商,将微分方程离散化为线性或非线性方程组来求解。 有限元法将微分方程离散化,有限元就是指近似连续域的离散单元,对每一单元假定一个近似解,然后推导求解域满足条件,从而得到问题的解。

按照本系列“编程方案”的概念,不涉及这些算法的具体内容,只探讨如何使用 Python 的工具包、库函数,零基础求解微分方程模型边值问题。我们的选择还是 Python 常用工具包三剑客:Scipy、Numpy 和 Matplotlib。



2. SciPy 求解常微分方程边值问题

2.1 BVP 问题的标准形式

Scipy 用 solve_bvp() 函数求解常微分方程的边值问题,定义微分方程的标准形式为:
{ y   ′ = f ( x , y ) ,    a < x < b g ( y ( a ) , y ( b ) = 0 ) \\begin{cases} y{\\ '} = f(x,y),\\; a<x<b\\\\ g(y(a),y(b)=0) \\end{cases} {y =f(x,y)a<x<bg(y(a),y(b)=0)

因此要将第一类边界条件 y ( a ) = y a , y ( b ) = y b y(a)=ya,y(b)=yb y(a)=yay(b)=yb 改写为:
{ y ( a ) − y a = 0 y ( b ) − y b = 0 \\begin{cases} y(a)-ya=0\\\\ y(b)-yb=0 \\end{cases} {y(a)ya=0y(b)yb=0

2.2 scipy.integrate.solve_bvp() 函数

**scipy.integrate.solve_bvp() **是求解微分方程边值问题的具体方法,可以求解一阶微分方程(组)的两点边值问题(第一类边界条件)。在 odeint 函数内部使用 FORTRAN 库 odepack 中的 lsoda,可以求解一阶刚性系统和非刚性系统的初值问题。官网介绍详见: scipy.integrate.solve_bvp — SciPy v1.7.0 Manual

scipy.integrate.solve_bvp(fun, bc, x, y, p=None, S=None, fun_jac=None, bc_jac=None, tol=0.001, max_nodes=1000, verbose=0, bc_tol=None)

solve_bvp 的主要参数:

求解标准形式的微分方程(组)主要使用前 4 个参数:

  • func: callable fun(x, y, …)   导数函数 f ( y , x ) f(y,x) f(y,x) , y 在 x 处的导数,以函数的形式表示。可以带有参数 p。
  • bc: callable bc(ya, yb, …)   边界条件,y 在两点边界的函数,以函数的形式表示。可以带有参数 p。
  • x: array:  初始网格的序列,shape (m,)。必须是单调递增的实数序列,起止于两点边界值 xa,xb。
  • y: array:  网格节点处函数值的初值,shape (n,m),第 i 列对应于 x[i]。
  • p: array:  可选项,向导数函数 func、边界条件函数 bc 传递参数。

其它参数用于控制求解算法的参数,一般情况可以忽略。

solve_bvp 的主要返回值:

  • sol: PPoly   通过 PPoly (如三次连续样条函数)插值求出网格节点处的 y 值。
  • x: array   数组,形状为 (m,),最终输出的网格节点。
  • y: array   二维数组,形状为 (n,m),输出的网格节点处的 y 值。
  • yp: array   二维数组,形状为 (n,m),输出的网格节点处的 y’ 值。


3. 实例 1:一阶常微分方程边值问题

3.1 例题 1:一阶常微分方程边值问题

求常微分方程边值问题的数值解。

{ y   ′ ′ + ∣ y ∣ = 0 y ( x = 0 ) = 0.5 y ( x = 4 ) = − 1.5 \\begin{cases} \\begin{aligned} &y\\ ''+ \\left| y \\right| = 0\\\\ &y(x=0) = 0.5\\\\ &y(x=4) = -1.5 \\end{aligned} \\end{cases} y +y=0y(x=0)=0.5y(x=4)=1.5

引入变量 y 0 = y , y 1 = y   ′ y0 = y,y1 = y\\ ' y0=yy1=y ,通过变量替换就把原方程化为如下的标准形式的微分方程组:

{ y 0 ′ = y 1 y 1 ′ = − ∣ y 0 ∣ y ( x = 0 ) − 0.5 = 0 y ( x = 4 ) + 1.5 = 0 \\begin{cases} y_0^{'} = y_1\\\\ y_1^{'} = -\\left| y_0 \\right| \\\\ y(x=0) - 0.5 = 0\\\\ y(x=4) + 1.5 = 0 \\end{cases} y0=y1y1=y0y(x=0)0.5=0y(x=4)+1.5=0

这样就可以用 solve_bvp() 求解该常微分方程的边值问题。


3.2 常微分方程的编程步骤

以该题为例讲解scipy.integrate.solve_bvp 求解常微分方程边值问题的步骤:

  1. 导入 scipy、numpy、matplotlib 包;

  2. 定义导数函数 dydx(x,y)

    注意本问题中 y 表示向量,记为 y = [ y 0 , y 1 ] y=[y_0,y_1] y=[y0,以上是关于Python小白的数学建模课-10 微分方程边值问题的主要内容,如果未能解决你的问题,请参考以下文章

    Python小白的数学建模课-11.偏微分方程数值解法

    Python小白的数学建模课-A1.国赛赛题类型分析

    Python小白的数学建模课-A1.国赛赛题类型分析

    Python小白的数学建模课-B5. 新冠疫情 SEIR模型

    Python小白的数学建模课-B5. 新冠疫情 SEIR模型

    Python小白的数学建模课-B6. 新冠疫情 SEIR 改进模型