基于Python编写求解抛物型pde方程的经典数值格式模拟

2023-10-19 13:59

本文主要是介绍基于Python编写求解抛物型pde方程的经典数值格式模拟,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

基于Python编写求解抛物型pde方程的经典数值格式模拟

    • 前言
    • 一:一维热传导方程简介
    • 二:差分格式
    • 三:代码实现
    • 四:数值结果
    • 五:总结

前言

热方程的在很多领域都有所应用,熟知的在金融领域求解期权定价公式之Black-Scholes方程,就可以用数值格式求解此类方程,因为很多复杂的期权定价公式很难有显式解,数值方法在这方面就有很多优越性。本文将基于Python编写常见的三种数值格式来求解传统的初-边值一维热方程问题。

岁月如云,匪我思存,写作不易,望路过的朋友们点赞收藏加关注哈,在此表示感谢!

一:一维热传导方程简介

一维热传导方程如下:
ϑ u ϑ t = a ϑ 2 u ϑ x 2 + f ( x ) , 0 < t ≤ T . ( 1 ) \frac{\vartheta u}{\vartheta t}=a\frac{\vartheta^2u}{\vartheta x^2}+f(x),0< t\leq T.(1) ϑtϑu=aϑx2ϑ2u+f(x),0<tT.1
其中 a 是正常数, f(x) 是给定的连续函数,对于初-边值问题的描述为,对于有一定阶偏导微商函数 u ( x , t ) u(x,t) u(x,t) ,满足方程(1)的初始条件: u ( x , 0 ) = Φ ( x ) , 0 < x < l u(x,0)=\Phi(x),0<x<l u(x,0)=Φ(x),0<x<l 以及边界条件 u ( 0 , t ) = u ( l , t ) = 0 , 0 ≤ t ≤ T u(0,t)=u(l,t)=0,0\leq t\leq T u(0,t)=u(l,t)=0,0tT

特别提示:由于本文不是纯粹的数学推理文章,所以会涉及到一些条件和假设的简化,如果从纯粹数学角度考虑,一个条件的成立往往需要很多假设和前提,以及精准的定义,这一点跟工业中算法成立还是有很大区别的。

对于光滑 f ( x ) f(x) f(x) Φ ( x ) \Phi(x) Φ(x) ,我们从初-边值考虑差分逼近。取空间步长 h = l / J h=l/J h=l/J 和时间步长 τ = T / N \tau=T/N τ=T/N ,其中 J 、 N J、N JN 都是自然数。用两族平行直线 x = x j = j h ( j = 0 , 1 , . . . , J ) x=x_j=jh(j=0,1,...,J) x=xj=jh(j=0,1,...,J) t = t n = n τ ( n = 0 , 1 , . . . N ) t=t_n=n\tau(n=0,1,...N) t=tn=nτ(n=0,1,...N) 将如下矩形分割成网格,网格节点设为 ( x j , t n ) (x_j,t_n) (xj,tn)
在这里插入图片描述

我们用 u j n u_j^n ujn 表示定义在网点 ( x j , t n ) (x_j,t_n) (xj,tn) 上的函数,接着用差商代替上述(1)方程,接下来介绍几种简便的经典差分格式。

二:差分格式

  • 向前差分格式(显式格式)

u j n + 1 − u j n τ = a u j + 1 n − 2 u j n + u j − 1 n h 2 + f j \frac{u_j^{n+1}-u_j^n}{\tau}=a\frac{u_{j+1}^{n}-2u_j^n+u_{j-1}^n}{h^2}+f_j τujn+1ujn=ah2uj+1n2ujn+uj1n+fj ,其中 j = 1 , 2 , . . . , J − 1 , n = 0 , 1 , . . . , N − 1 j=1,2,...,J-1,n=0,1,...,N-1 j=1,2,...,J1,n=0,1,...,N1 ,以 α = a τ / h 2 \alpha=a\tau/h^2 α=aτ/h2 表示网格比,上式我们变形可得: u j n + 1 = α u j + 1 n + ( 1 − 2 α ) u j n + r u j − 1 n + τ f j u_j^{n+1}=\alpha u_{j+1}^n+(1-2\alpha)u_j^n+ru_{j-1}^n+\tau f_j ujn+1=αuj+1n+(12α)ujn+ruj1n+τfj ,取 n = 0 n=0 n=0 ,利用初值 u j 0 = φ j u_j^0=\varphi_j uj0=φj 和边值 u 0 n = u J n = 0 u_0^n=u_J^n=0 u0n=uJn=0 可以通过变形式算出 u j 1 u_j^1 uj1 ,同理下去可以算出 u j 2 . . . . u_j^2.... uj2....,此格式不需要求解线性方程组,所以此格式视为显式格式,但显式格式并不是无条件稳定的,只有当 α ≤ 1 / 2 \alpha\leq1/2 α1/2 时,格式才是稳定的通过泰勒公式与截断误差定义,我们能证明出此格式基于时间步长 τ \tau τ 是一阶收敛的(由于此文不是存粹数学文章,这里涉及到的一些结论不再过多深入,有兴趣的朋友可以参考相关文献)。

  • 向后差分格式(隐式格式)

u j n + 1 − u j n τ = a u j + 1 n + 1 − 2 u j n + 1 + u j − 1 n + 1 h 2 + f j \frac{u_j^{n+1}-u_j^n}{\tau}=a\frac{u_{j+1}^{n+1}-2u_j^{n+1}+u_{j-1}^{n+1}}{h^2}+f_j τujn+1ujn=ah2uj+1n+12ujn+1+uj1n+1+fj ,其中 j = 1 , 2 , . . . , J − 1 , n = 0 , 1 , . . . , N − 1 j=1,2,...,J-1,n=0,1,...,N-1 j=1,2,...,J1,n=0,1,...,N1 ,同理我们改写上式为: − α u j + 1 n + 1 + ( 1 + 2 α ) u j n + 1 − α u j − 1 n + 1 = u j n + τ f j -\alpha u_{j+1}^{n+1}+(1+2\alpha)u_j^{n+1}-\alpha u_{j-1}^{n+1}=u_j^n+\tau f_j αuj+1n+1+(1+2α)ujn+1αuj1n+1=ujn+τfj ,令 $n=0,1,2,… $,则可利用 u j 0 u_j^0 uj0 和边值确定 u j 1 u_j^1 uj1 ,利用 u j 1 u_j^1 uj1 和边值确定 u j 2 u_j^2 uj2 等,现在第 n + 1 n+1 n+1 层的值不能用第 n n n 层值明显表示,而是由线性方程组求解。由于变形式左端系数矩阵是严格对角占优的,所以方程肯定有解的,且该格式是无条件稳定的。同样此格式也是基于时间步长 τ \tau τ 一阶收敛的

  • 六点对称格式(Crank-Nicolson 格式)

即向前差分格式和向后差分格式做算术平均,即可得到CN格式如下:
u j n + 1 − u j n τ = a 2 [ u j + 1 n + 1 − 2 u j n + 1 + u j − 1 n + 1 h 2 + u j + 1 n − 2 u j n + u j − 1 n h 2 ] + f i \frac{u_j^{n+1}-u_j^n}{\tau}=\frac{a}{2}\left[ \frac{u_{j+1}^{n+1}-2u_j^{n+1}+u_{j-1}^{n+1}}{h^2}+\frac{u_{j+1}^n-2u_j^n+u_{j-1}^n}{h^2} \right]+f_i τujn+1ujn=2a[h2uj+1n+12ujn+1+uj1n+1+h2uj+1n2ujn+uj1n]+fi
其中 j = 1 , 2 , . . . , J − 1 , n = 0 , 1 , . . . , N − 1 j=1,2,...,J-1,n=0,1,...,N-1 j=1,2,...,J1,n=0,1,...,N1,同理上式我们可以改写为 − α 2 u j + 1 n + 1 + ( 1 + α ) u j n + 1 − α 2 u j − 1 n + 1 = r 2 u j + 1 n + ( 1 − α ) u j n + α 2 u j − 1 n + τ f j -\frac{\alpha}{2}u_{j+1}^{n+1}+(1+\alpha)u_j^{n+1}-\frac{\alpha}{2}u_{j-1}^{n+1}=\frac{r}{2}u_{j+1}^n+(1-\alpha)u_j^n+\frac{\alpha}{2}u_{j-1}^n+\tau f_j 2αuj+1n+1+(1+α)ujn+12αuj1n+1=2ruj+1n+(1α)ujn+2αuj1n+τfj ,利用 u j 0 u_j^0 uj0 和边值便可以逐层求解到 u j n u_j^n ujn同样 C N CN CN格式是隐式格式,无条件稳定的,由第 n 层计算第 n+1 层时,需要求解线性方程组,但此格式基于时间步长 τ \tau τ 能达到二阶收敛

三:代码实现

接下来我们通过python的面向对象编程,逐一实现上面的三种数值格式。

以下代码经过本人调试,没任何bug,直接复制即可,有兴趣需要的朋友别忘记点赞关注加收藏哦!!谢谢!!

##############导入相应模块
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3Dplt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

编写差分格式类如下:

class diff_schemes:def __init__(self,dt,dx,r,x,t):##定义内置初始化函数self.dt = dtself.dx = dxself.r = rself.x = xself.t = tdef make_figure(self,matx,title_msg):###作图fig = plt.figure()ax = fig.gca(projection='3d')x, y = np.meshgrid(self.x, self.t)z = matxax.plot_surface(x, y, z, cmap=cm.coolwarm, linewidth=0, antialiased=False)ax.set_xlabel('X Label')ax.set_ylabel('Y Label')ax.set_zlabel('Z Label')plt.title(title_msg)plt.show()def init_condition(self):##定义初值函数,这里选择混个三角函数return np.sin(self.x) + np.cos(self.x)  ###也可以选择其他函数如指数函数exp(x)等等def forward_diff_scheme(self):##向前差分格式(显式)matx = np.zeros([len(self.t),len(self.x)])###默认边值都为0matx[0,:] = icmatx[:,0] = 0matx[:,-1] = 0for i in range(1,len(self.t)):for j in range(1,len(self.x)-1):matx[i,j] = self.r * matx[i - 1,j - 1] + (1 - 2 * self.r) * matx[i - 1,j] + self.r * matx[i - 1,j + 1]print(matx)return matxdef backward_diff_scheme(self):matx = np.zeros([len(self.t), len(self.x)])matx[0, :] = icmatx[:, 0] = 0matx[:, -1] = 0matxa = np.zeros([len(self.x) - 2,len(self.x) - 2 ])for j in range(len(self.x) - 2):matxa[j, j] = 1 + 2 * self.rif j >= 1:matxa[j - 1, j] = - self.rmatxa[j, j - 1] = - self.riv = ic[1:-1]matxa_t = np.linalg.inv(matxa)##求解线性方程组for i in range(1, len(self.t)):res = np.dot(matxa_t,iv)matx[i,1:-1] = resiv = resprint(matx)return matxdef CN_diff_scheme(self):r1 = 1 + self.rr2 = 1 - self.rmatx = np.zeros([len(self.t), len(self.x)])matx[0, :] = icmatx[:, 0] = 0matx[:, -1] = 0matxp = np.zeros([len(self.x) - 2, len(self.x) - 2])matxq = np.zeros([len(self.x) - 2, len(self.x) - 2])for j in range(len(self.x) - 2):matxp[j, j] = r1matxq[j, j] = r2if j >= 1:matxp[j - 1, j] = - self.r / 2matxp[j, j - 1] = - self.r / 2matxq[j - 1, j] = self.r / 2matxq[j, j - 1] = self.r / 2iv = np.dot(matxq,ic[1:-1])matxa_t = np.linalg.inv(matxp)for i in range(1, len(self.t)):res = np.dot(matxa_t, iv)matx[i, 1:-1] = resiv = np.dot(matxq,res)print(matx)return matx

调用相关类中方法展示实验结果

dt = 0.01##时间步长
dx = 0.01##空间步长
a = 0.5##网格比的取值,且显式格式时a的取值不能大于0.5
X_array = np.arange(-2.5,2.5 + dx,dx)
T_array = np.arange(0,1 + dt,dt)
res = diff_schemes(dt,dx,a,X_array,T_array)
ic = res.init_condition()###初始条件
rfd = res.forward_diff_scheme()
rbd = res.backward_diff_scheme()
rcnd = res.CN_diff_scheme()res.make_figure(rfd,'网格比a=%s时,显式格式求解'%a)
res.make_figure(rbd,'网格比a=%s时,隐式格式求解'%a)
res.make_figure(rcnd,'网格比a=%s时,CN格式求解'%a)

四:数值结果

1

图1

在这里插入图片描述

图2

在这里插入图片描述

图3

在这里插入图片描述

图4(显式格式求解值)

在这里插入图片描述

图5(隐式格式求解值)

在这里插入图片描述

图6(CN格式求解值)

从上面所有图中结果可知,三种格式最终在末端位置(时间末端和空间末端)的运算结果很接近(如果深入从收敛阶角度出发,其实CN格式的精度更高更接近真解,收敛速率最快)。

在这里插入图片描述

图7

当我们网格比取值大于0.5时,显式格式符合理论上的结果,明显不稳定收敛了,但两种隐式格式还是依旧很稳定,从图7很明显能发掘到这一点。

五:总结

本文主要是数值模拟实验类文章,也是学习数值求解偏微分方程的基础性文章。偏微分方程的理论是非常广且深,另外,它跟随机微分方程也有这千丝万缕的联系。如果有兴趣的小伙伴可以多多交流。

写作不易,望路过的朋友们点赞收藏加关注哈,在此表示感谢!
在这里插入图片描述

这篇关于基于Python编写求解抛物型pde方程的经典数值格式模拟的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/240273

相关文章

Python基于wxPython和FFmpeg开发一个视频标签工具

《Python基于wxPython和FFmpeg开发一个视频标签工具》在当今数字媒体时代,视频内容的管理和标记变得越来越重要,无论是研究人员需要对实验视频进行时间点标记,还是个人用户希望对家庭视频进行... 目录引言1. 应用概述2. 技术栈分析2.1 核心库和模块2.2 wxpython作为GUI选择的优

Python如何使用__slots__实现节省内存和性能优化

《Python如何使用__slots__实现节省内存和性能优化》你有想过,一个小小的__slots__能让你的Python类内存消耗直接减半吗,没错,今天咱们要聊的就是这个让人眼前一亮的技巧,感兴趣的... 目录背景:内存吃得满满的类__slots__:你的内存管理小助手举个大概的例子:看看效果如何?1.

Python+PyQt5实现多屏幕协同播放功能

《Python+PyQt5实现多屏幕协同播放功能》在现代会议展示、数字广告、展览展示等场景中,多屏幕协同播放已成为刚需,下面我们就来看看如何利用Python和PyQt5开发一套功能强大的跨屏播控系统吧... 目录一、项目概述:突破传统播放限制二、核心技术解析2.1 多屏管理机制2.2 播放引擎设计2.3 专

Python中随机休眠技术原理与应用详解

《Python中随机休眠技术原理与应用详解》在编程中,让程序暂停执行特定时间是常见需求,当需要引入不确定性时,随机休眠就成为关键技巧,下面我们就来看看Python中随机休眠技术的具体实现与应用吧... 目录引言一、实现原理与基础方法1.1 核心函数解析1.2 基础实现模板1.3 整数版实现二、典型应用场景2

Python实现无痛修改第三方库源码的方法详解

《Python实现无痛修改第三方库源码的方法详解》很多时候,我们下载的第三方库是不会有需求不满足的情况,但也有极少的情况,第三方库没有兼顾到需求,本文将介绍几个修改源码的操作,大家可以根据需求进行选择... 目录需求不符合模拟示例 1. 修改源文件2. 继承修改3. 猴子补丁4. 追踪局部变量需求不符合很

python+opencv处理颜色之将目标颜色转换实例代码

《python+opencv处理颜色之将目标颜色转换实例代码》OpenCV是一个的跨平台计算机视觉库,可以运行在Linux、Windows和MacOS操作系统上,:本文主要介绍python+ope... 目录下面是代码+ 效果 + 解释转HSV: 关于颜色总是要转HSV的掩膜再标注总结 目标:将红色的部分滤

Python 中的异步与同步深度解析(实践记录)

《Python中的异步与同步深度解析(实践记录)》在Python编程世界里,异步和同步的概念是理解程序执行流程和性能优化的关键,这篇文章将带你深入了解它们的差异,以及阻塞和非阻塞的特性,同时通过实际... 目录python中的异步与同步:深度解析与实践异步与同步的定义异步同步阻塞与非阻塞的概念阻塞非阻塞同步

Python Dash框架在数据可视化仪表板中的应用与实践记录

《PythonDash框架在数据可视化仪表板中的应用与实践记录》Python的PlotlyDash库提供了一种简便且强大的方式来构建和展示互动式数据仪表板,本篇文章将深入探讨如何使用Dash设计一... 目录python Dash框架在数据可视化仪表板中的应用与实践1. 什么是Plotly Dash?1.1

在C#中调用Python代码的两种实现方式

《在C#中调用Python代码的两种实现方式》:本文主要介绍在C#中调用Python代码的两种实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C#调用python代码的方式1. 使用 Python.NET2. 使用外部进程调用 Python 脚本总结C#调

Python下载Pandas包的步骤

《Python下载Pandas包的步骤》:本文主要介绍Python下载Pandas包的步骤,在python中安装pandas库,我采取的方法是用PIP的方法在Python目标位置进行安装,本文给大... 目录安装步骤1、首先找到我们安装python的目录2、使用命令行到Python安装目录下3、我们回到Py