偏微分方程数值解法python_Python数值计算----------求解简单的偏微分方程

偏微分方程数值解法python_Python数值计算----------求解简单的偏微分方程_第1张图片

很多物理现象的都可以用方程来描述,比如热传导与物质扩散可以用扩散方程来描述,流体的流动可以用NS方程描述等等。如果能够将这些偏微分方程求解出来,就可以来对很多物理现象进行仿真,现在工程中的仿真软件都是通过程序数值求解一类偏微分方程。今天我们尝试求解一类偏微分方程,为了简单起见,我们以一个简单的平流方程为例,方程形式如下:

偏微分方程数值解法python_Python数值计算----------求解简单的偏微分方程_第2张图片
平流方程

求解偏微分方程的数值解法非常多,这里也是采用一种较为直白的方法--------有限差分法,将上述的偏微分方程离散为差分方程,这里采用一种迎风格式的差分方法,首先我们可以看出这个平流方程由两个维度,一个空间维度x,一个时间维度t,我们对这两个维度进行离散:

偏微分方程数值解法python_Python数值计算----------求解简单的偏微分方程_第3张图片
差分网格

差分方程

偏微分方程数值解法python_Python数值计算----------求解简单的偏微分方程_第4张图片

将差分方程简化一下

偏微分方程数值解法python_Python数值计算----------求解简单的偏微分方程_第5张图片

通过上述的差分方程我们可以通过上一个时间步的结果推进得到下一个时间步的结果:

偏微分方程数值解法python_Python数值计算----------求解简单的偏微分方程_第6张图片

这里我们边界条件是周期边界如下图,周期边界的好处就是我们可以一直看到在我们的求解域内看到波的移动:

偏微分方程数值解法python_Python数值计算----------求解简单的偏微分方程_第7张图片

方程的初始条件我们给空间维度上一个指数函数的波形:

48ffe9260cb73700d39b773f8fb9e3da.png

下面我们通过一段简单(其实挺长的,但是很容易理解)的Python代码对上述差分方程进行求解:

"""
This code solves the advection equation
    U_t + vU_x = 0

over the spatial domain of 0 <= x <= 1 that is discretized 
into 103 nodes, with dx=0.01, using the First-Order Upwind (FOU) 
scheme with Forward difference in Eq. 
for an initial profile of a Gaussian curve, defined by 
    U(x,t) = exp(-200*(x-xc-v*t).^2)

where xc=0.25 is the center of the curve at t=0.

The periodic boundary conditions are applied either end of the domain.
The velocity is v=1. The solution is iterated until t=1.5 seconds.
"""


import numpy as np
import matplotlib.pyplot as plt
import time

start =time.clock()

class UpwindMethod1:
    
    def __init__(self, N, tmax):
        self.N = N # number of nodes
        self.tmax = tmax
        self.xmin = 0
        self.xmax = 1
        self.dt = 0.009 # timestep
        self.v = 1 # velocity
        self.xc = 0.25
        self.initializeDomain()
        self.initializeU()
        self.initializeParams()
            
    def initializeDomain(self):
        self.dx = (self.xmax - self.xmin)/self.N
        self.x = np.arange(self.xmin-self.dx, self.xmax+(2*self.dx), self.dx)
        
        
    def initializeU(self):
        u0 = np.exp(-200*(self.x-self.xc)**2)
        self.u = u0.copy()
        self.unp1 = u0.copy()
        
        
    def initializeParams(self):
        self.nsteps = round(self.tmax/self.dt)
        
   
    def solve_and_plot(self):
        tc = 0
        
        for i in range(self.nsteps):
            plt.clf()
            
            # The FOU scheme, Eq. (18.21)
            for j in range(self.N+2):
                self.unp1[j] = self.u[j] - (self.v*self.dt/(self.dx))*(self.u[j]-self.u[j-1]) 
                
            self.u = self.unp1.copy()
            
            # Periodic boundary conditions
            self.u[0] = self.u[self.N+1]
            self.u[self.N+2] = self.u[1]
            
           
            plt.plot(self.x, self.u, 'bo-', label="First-order Upwind")
            plt.axis((self.xmin-0.12, self.xmax+0.12, -0.2, 1.4))
            plt.grid(True)
            plt.xlabel("Distance (x)")
            plt.ylabel("u")
            plt.legend(loc=1, fontsize=12)
            plt.suptitle("Time = %1.3f" % (tc+self.dt))
            plt.pause(0.01)
            tc += self.dt


def main():
  
    sim = UpwindMethod1(100, 1.5)
    sim.solve_and_plot()
    plt.show()
    
    
if __name__ == "__main__":
    main()

end = time.clock()

print('Running time: %s Seconds'%(end-start))

运行程序大家就可以看到一个波在来回移动。这里以一个简单平流方程为例,然后构造了其迎风格式的差分方程,然后用我们可爱的python语言进行求解,这里再次说明了计算机语言是一个工具,有了这个工具我们可以用它来做我们想做的事,对我来言Python做科学计算非常的Nice。

你可能感兴趣的:(偏微分方程数值解法python)