基于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: 多模块(.py)中全局变量的导入

文章目录 global关键字可变类型和不可变类型数据的内存地址单模块(单个py文件)的全局变量示例总结 多模块(多个py文件)的全局变量from x import x导入全局变量示例 import x导入全局变量示例 总结 global关键字 global 的作用范围是模块(.py)级别: 当你在一个模块(文件)中使用 global 声明变量时,这个变量只在该模块的全局命名空

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

usaco 1.2 Transformations(模拟)

我的做法就是一个一个情况枚举出来 注意计算公式: ( 变换后的矩阵记为C) 顺时针旋转90°:C[i] [j]=A[n-j-1] [i] (旋转180°和270° 可以多转几个九十度来推) 对称:C[i] [n-j-1]=A[i] [j] 代码有点长 。。。 /*ID: who jayLANG: C++TASK: transform*/#include<

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

【生成模型系列(初级)】嵌入(Embedding)方程——自然语言处理的数学灵魂【通俗理解】

【通俗理解】嵌入(Embedding)方程——自然语言处理的数学灵魂 关键词提炼 #嵌入方程 #自然语言处理 #词向量 #机器学习 #神经网络 #向量空间模型 #Siri #Google翻译 #AlexNet 第一节:嵌入方程的类比与核心概念【尽可能通俗】 嵌入方程可以被看作是自然语言处理中的“翻译机”,它将文本中的单词或短语转换成计算机能够理解的数学形式,即向量。 正如翻译机将一种语言

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学

nudepy,一个有趣的 Python 库!

更多资料获取 📚 个人网站:ipengtao.com 大家好,今天为大家分享一个有趣的 Python 库 - nudepy。 Github地址:https://github.com/hhatto/nude.py 在图像处理和计算机视觉应用中,检测图像中的不适当内容(例如裸露图像)是一个重要的任务。nudepy 是一个基于 Python 的库,专门用于检测图像中的不适当内容。该

pip-tools:打造可重复、可控的 Python 开发环境,解决依赖关系,让代码更稳定

在 Python 开发中,管理依赖关系是一项繁琐且容易出错的任务。手动更新依赖版本、处理冲突、确保一致性等等,都可能让开发者感到头疼。而 pip-tools 为开发者提供了一套稳定可靠的解决方案。 什么是 pip-tools? pip-tools 是一组命令行工具,旨在简化 Python 依赖关系的管理,确保项目环境的稳定性和可重复性。它主要包含两个核心工具:pip-compile 和 pip

hdu4431麻将模拟

给13张牌。问增加哪些牌可以胡牌。 胡牌有以下几种情况: 1、一个对子 + 4组 3个相同的牌或者顺子。 2、7个不同的对子。 3、13幺 贪心的思想: 对于某张牌>=3个,先减去3个相同,再组合顺子。 import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOExcepti