从今天开始我们将进入一个系列 —— 偏微分方程。作为这一系列的开篇,我们以热传导方差为引子,引出:

  1. 如何提一个偏微分方程的初边值问题;
  2. 利用差分格式将偏微分方程离散化;
  3. 显示差分格式;
  4. 显示差分格式的条件稳定性。

最后一点将作为伏笔,引出我们下一天的学习:无条件稳定格式。

1. 热传导方程


我们这里使用1D热传导方程作为例子:

⎧⎩⎨⎪⎪uτ−κuxx\[3pt]u(x,0)\[3pt]u(0,τ)\[3pt]u(1,τ)=0,0≤x≤1[1]=4x(1−x),0≤x≤1[2]=0,τ≥0[3]=0,τ≥0[4]

其中:

  • κ 称为热传导系数
  • [2] 称为方程的初值条件(Initial Condition)
  • [3][4] 称为方程的边值条件 (Boundaries Condition)。这里我们使用Dirichlet条件

我们可以看一下初值条件的形状:

from matplotlib import pylab
import seaborn as sns
import numpy as np
from CAL.PyCAL import *
font.set_size(20)def initialCondition(x):return 4.0*(1.0 - x) * xxArray = np.linspace(0,1.0,50)
yArray = map(initialCondition, xArray)
pylab.figure(figsize = (12,6))
pylab.plot(xArray, yArray)
pylab.xlabel('$x$', fontsize = 15)
pylab.ylabel('$f(x)$', fontsize = 15)
pylab.title(u'一维热传导方程初值条件', fontproperties = font)

2. 显式差分格式


这里的基本思想是用差分格式替换对应的微分形式,并且期盼两种格式的"误差"在网格足够密的情况下会趋于0。我们分别在时间方向以及空间方向做差分格式:

\begin{align}\frac{\partial u(x_j, \tau_k)}{\partial\tau} &= \frac{u_{j,k+1} - u_{j,k}}{\Delta \tau} + O(\Delta \tau) \\\\\frac{\partial^2 u(x_j, \tau_k)}{\partial x^2} &= \frac{u_{j-1,k} - 2u_{j,k} + u_{j+1,k}}{\Delta x^2} + O(\Delta x^2) \\\\\end{align}

合并在一起,我们就得到了原始微分方程的差分格式:

\begin{align}u_{\tau}(x_j,\tau_k) - \kappa u_{xx}(x_j,\tau_k) &= 0 \\\\\frac{u_{j,k+1} - u_{j,k}}{\Delta \tau} - \kappa \frac{u_{j-1,k} - 2u_{j,k} + u_{j+1,k}}{\Delta x^2} &= O(\Delta \tau) + O(\Delta x^2)\end{align}

这里我们使用差分网格上的近似值Uj,k代替uj,k,得到新的方程:

\begin{align}&\frac{U_{j,k+1} - U_{j,k}}{\Delta \tau} - \kappa \frac{U_{j-1,k} - 2U_{j,k} + U_{j+1,k}}{\Delta x^2} &= 0, \\\\\Rightarrow& \quad U_{j,k+1} - U_{j,k} - \frac{\kappa\Delta \tau}{\Delta x^2}(U_{j-1,k} - 2U_{j,k} + U_{j+1,k}) &= 0, \\\\\Rightarrow& \quad U_{j,k+1} - U_{j,k} - \rho(U_{j-1,k} - 2U_{j,k} + U_{j+1,k}) &= 0.\end{align}

到这里我们得到一个迭代方程组:

Uj,k+1=ρUj−1,k+(1−2ρ)Uj,k+ρUj+1,k,1≤j≤N−1,0≤k≤M−1

其中 ρ=κΔτΔx2。下面我们使用Python代码实现上面的过程。

首先定义基本变量:

  • N 空间方向的网格数
  • M 时间方向的网格数
  • T 最大时间期限
  • X 最大空间范围
  • U 用来存储差分网格点上值得矩阵
N = 25   # x方向网格数
M = 2500  # t方向网格数T = 1.0
X = 1.0xArray = np.linspace(0,X,N+1)
yArray = map(initialCondition, xArray)starValues = yArray
U = np.zeros((N+1,M+1))
U[:,0] = starValues
dx = X / N
dt = T / M
kappa = 1.0
rho = kappa * dt / dx / dx

这里我们做正向迭代:迭代时k=0,1...M−1, 代表我们从0时刻运行至T

for k in range(0, M):for j in range(1, N):U[j][k+1] = rho * U[j-1][k] + (1. - 2*rho) * U[j][k] + rho * U[j+1][k]U[0][k+1] = 0.U[N][k+1] = 0.

我们可以画出不同时间点U(,˙τk) 的结果:

pylab.figure(figsize = (12,6))
pylab.plot(xArray, U[:,0])
pylab.plot(xArray, U[:, int(0.10/ dt)])
pylab.plot(xArray, U[:, int(0.20/ dt)])
pylab.plot(xArray, U[:, int(0.50/ dt)])
pylab.xlabel('$x$', fontsize = 15)
pylab.ylabel(r'$U(\dot, \tau)$', fontsize = 15)
pylab.title(u'一维热传导方程', fontproperties = font)
pylab.legend([r'$\tau = 0.$', r'$\tau = 0.10$', r'$\tau = 0.20$', r'$\tau = 0.50$'], fontsize = 15)


也可以通过三维立体图看一下整体的热传导过程:

tArray = np.linspace(0, 0.2, int(0.2 / dt) + 1)
xGrids, tGrids = np.meshgrid(xArray, tArray)
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cmfig= pylab.figure(figsize = (16,10))
ax = fig.add_subplot(1, 1, 1, projection = '3d')
surface = ax.plot_surface(xGrids, tGrids, U[:,:int(0.2 / dt) + 1].T, cmap=cm.coolwarm)
ax.set_xlabel("$x$", fontdict={"size":18})
ax.set_ylabel(r"$\tau$", fontdict={"size":18})
ax.set_zlabel(r"$U$", fontdict={"size":18})
ax.set_title(u"热传导方程 $u_\\tau = u_{xx}$" , fontproperties = font)
fig.colorbar(surface,shrink=0.75)

3. 组装起来


就像在前一天二叉树建模中介绍的一样,我们这里会以面向对象的方式重新封装分散的代码,方便复用。首先是方程的描述:

class HeatEquation:    def __init__(self, kappa, X, T,initialConstion = lambda x:4.0*x*(1.0-x), boundaryConditionL = lambda x: 0, boundaryCondtionR = lambda x:0):self.kappa = kappaself.ic = initialConstionself.bcl = boundaryConditionLself.bcr = boundaryCondtionRself.X = Xself.T = T

下面的是显式差分格式的描述:

class ExplicitEulerScheme:    def __init__(self, M, N, equation):self.eq = equationself.dt = self.eq.T / Mself.dx = self.eq.X / Nself.U = np.zeros((N+1, M+1))self.xArray = np.linspace(0,self.eq.X,N+1)self.U[:,0] = map(self.eq.ic, self.xArray)self.rho = self.eq.kappa * self.dt / self.dx / self.dxself.M = Mself.N = Ndef roll_back(self):for k in range(0, self.M):for j in range(1, self.N):self.U[j][k+1] = self.rho * self.U[j-1][k] + (1. - 2*self.rho) * self.U[j][k] + self.rho * self.U[j+1][k]self.U[0][k+1] = self.eq.bcl(self.xArray[0])self.U[N][k+1] = self.eq.bcr(self.xArray[-1])def mesh_grids(self):tArray = np.linspace(0, self.eq.T, M+1)tGrids, xGrids = np.meshgrid(tArray, self.xArray)return tGrids, xGrids

有了以上的部分,现在整个过程可以简单的通过初始化和一行关于roll_back的调用完成:

ht = HeatEquation(1.,1.,1.)
scheme = ExplicitEulerScheme(2500,25, ht)
scheme.roll_back()

我们可以获取与之前相同的图像:

tGrids, xGrids = scheme.mesh_grids()
fig= pylab.figure(figsize = (16,10))
ax = fig.add_subplot(1, 1, 1, projection = '3d')
cutoff = int(0.2 / scheme.dt) + 1
surface = ax.plot_surface(xGrids[:,:cutoff], tGrids[:,:cutoff], scheme.U[:,:cutoff], cmap=cm.coolwarm)
ax.set_xlabel("$x$", fontdict={"size":18})
ax.set_ylabel(r"$\tau$", fontdict={"size":18})
ax.set_zlabel(r"$U$", fontdict={"size":18})
ax.set_title(u"热传导方程 $u_\\tau = u_{xx}$" , fontproperties = font)
fig.colorbar(surface,shrink=0.75)

4. 什么时候显式格式会失败?


显式格式不能任意取时间和空间的网格点数,即MN不能随意取值。我们称显式格式为条件稳定。特别地,需要满足所谓CFL条件(Courant–Friedrichs–Lewy):

0≤ρ=κΔτΔx2≤0.5

例如:

  • M = 2500
  • N = 25

则:

ρ=κΔτΔx2=0.25≤0.5
  • M = 1200
  • N = 25

则:

ρ=κΔτΔx2=0.521≥0.5

下面的代码计算在第二种情形下的网格点计算过程:

ht = HeatEquation(1.,1.,1.)
scheme = ExplicitEulerScheme(1200,25, ht)
scheme.roll_back()

我们可以通过下图看到,在CFL条件无法满足的情况下,数值误差累计的结果(特别注意后面的锯齿):

tGrids, xGrids = scheme.mesh_grids()
fig= pylab.figure(figsize = (16,10))
ax = fig.add_subplot(1, 1, 1, projection = '3d')
cutoff = int(0.2 / scheme.dt) + 1
surface = ax.plot_surface(xGrids[:,:cutoff], tGrids[:,:cutoff], scheme.U[:,:cutoff], cmap=cm.coolwarm)
ax.set_xlabel("$x$", fontdict={"size":18})
ax.set_ylabel(r"$\tau$", fontdict={"size":18})
ax.set_zlabel(r"$U$", fontdict={"size":18})
ax.set_title(u"热传导方程 $u_\\tau = u_{xx}$, $\\rho = 0.521$" , fontproperties = font)
fig.colorbar(surface,shrink=0.75)

今天的日记到此为止,还想继续了解的请戳

我们会在下一篇中进行讨论,引出无条件稳定格式:隐式差分格式(Implicit)。

量化分析师的Python日记【Q Quant兵器谱 -之偏微分方程1】相关推荐

  1. 量化分析师的Python日记 系列

    量化分析师的Python日记 系列 转发,原作者 薛昆Kelvin 为方便学习,整理一下学习材料.持续更新. [第1天:谁来给我讲讲Python?] https://uqer.io/community ...

  2. 量化分析师的Python日记-CSDN公开课-专题视频课程

    量化分析师的Python日记-7882人已学习 课程介绍         以完全初学者的角度入手来认识Python这个在量化领域日益重要的语言. 课程收益     课程先从介绍Python本身一些基本 ...

  3. 量化分析师的Python日记【Q Quant兵器谱之偏微分方程2】

    这是量化分析师的偏微分方程系列的第二篇,在这一篇中我们将解决上一篇显式格式留下的稳定性问题.本篇将引入隐式差分算法,读者可以学到: 隐式差分格式描述 三对角矩阵求解 如何使用scipy加速算法实现 在 ...

  4. 量化分析师的Python日记【Q Quant兵器谱之二叉树】

    通过之前几天的学习,Q Quant们应该已经熟悉了Python的基本语法,也了解了Python中常用数值库的算法.到这里为止,小Q们也许早就对之前简单的例子不满意,希望能在Python里面玩票大的!O ...

  5. 量化分析师的Python日记【Q Quant 之初出江湖】

    本篇中,作为Quant中的Q宗(P Quant 和 Q Quant 到底哪个是未来?),我们将尝试把之前的介绍的工具串联起来,小试牛刀. 您将可以体验到: 如何使用python内置的数学函数计算期权的 ...

  6. python量化分析系列(第一篇)_量化分析师的 Python 日记 [第 1 天:谁来给我讲讲 Python?]...

    45 条回复 • 2016-05-25 11:10:23 +08:00 1 2015-04-08 21:42:42 +08:00 这里竟然有Quant 2 2015-04-08 22:49:51 +0 ...

  7. 量化分析师的Python日记【Q Quant兵器谱之函数插值】

    在本篇中,我们将介绍Q宽客常用工具之一:函数插值.接着将函数插值应用于一个实际的金融建模场景中:波动率曲面构造. 通过本篇的学习您将学习到: 如何在scipy中使用函数插值模块:interpolate ...

  8. 量化分析师的Python日记【Q Quant兵器谱之偏微分方程3的具体金融学运用】

    欢迎来到 Black - Scholes - Merton 的世界!本篇中我们将把第11天学习到的知识应用到这个金融学的具体方程之上! import numpy as np import math i ...

  9. 量化分析师的python日记_量化分析师的Python日记【第1天:谁来给我讲讲Python?】...

    "谁来给我讲讲Python?" 作为无基础的初学者,只想先大概了解一下Python,随便编个小程序,并能看懂一般的程序,那些什么JAVA啊.C啊.继承啊.异常啊通通不懂怎么办,于是 ...

最新文章

  1. x3650m5不自动进系统_自动起停系统不工作?可能有这几种情况
  2. 并发安全Context包的使用
  3. 【struts2+hibernate+spring项目实战】统一异常处理(ssh)
  4. 【转载】优酷网首席执行官兼创始人古永锵演讲
  5. 计算机二级学习考试题,全国计算机等级考试一级Window复习题及答案
  6. 关于Adapter的The content of the adapter has changed but ListView did not receive a notification.问题分析
  7. 客户说发货慢怎么回复_女生微信说身体不舒服怎么回复关心她?
  8. 企业微信加密消息体_微信公众平台开发者中心安全模式消息体加解密实现
  9. 【AI视野·今日CV 计算机视觉论文速览 第212期】Thu, 3 Jun 2021
  10. C++初学之 3. ASCII数值的应用(大小写变换)
  11. mysql服务器的字符集
  12. php ajax可编辑表格,jquerAjax+php实现表格的增删改查(带数据库)
  13. 几种常用的键盘钩子技术
  14. Webservice接口之CXF框架及Axis框架
  15. 记一次Maya入门之材质和模型的导出
  16. Quantal Response Equilibrium调研
  17. TensorFlow 2 和 Keras 高级深度学习:11~13
  18. JAVA简单实现坦克对战(只有坦克和子弹)
  19. Python 学习笔记本一一
  20. Java 程序如何正确地打日志

热门文章

  1. 计算机R5,IT教程:电脑r5和r7是什么意思
  2. SOD算法:PoolNet
  3. **R语言中的%in% 用法**
  4. Zephyr启动过程与中断响应
  5. 【第一周】数学作业(贷款问题)
  6. 什么是可调CAP策略?为什么需要可调CAP策略?
  7. pdf 生成文件工具类
  8. 机器学习中的数据归一化、最值归一化、均值方差归一化(标准化)
  9. 【Python】Windows:PyCharm 旧版卸载与新版安装汉化参考(专业版试用期/社区版)
  10. python主页_主页 - Python 宽客之道