zoukankan      html  css  js  c++  java
  • 2D Wave Equation

    • 二维波动方程初边值问题:
      egin{equation}
      egin{cases}
      frac{partial^2u}{partial t^2} = D(frac{partial^2u}{partial x^2} + frac{partial^2u}{partial y^2}), quad (x, y) in Omega = (0, 2)^2, t in (0, 6)   \
      u(x, y, 0) = 0.1mathrm{e}^{-((x - x_c)^2 + (y - y_c)^2) / 0.001}, u_t(x, y, 0) = 0, quad (x, y) in Omega   \
      u(x, y, t) = 0, quad (x, y) in partialOmega, t in [0, 6]
      label{eq_1}
      end{cases}
      end{equation}
    • 连续型系统的离散化:
      采用中心差分对波动方程离散化,
      egin{equation}
      frac{u_{i, j}^{k+1} + u_{i, j}^{k-1} - 2u_{i, j}^k}{h_t^2} = Dleft(frac{u_{i+1, j}^k + u_{i-1, j}^k - 2u_{i, j}^k}{h_x^2} + frac{u_{i, j+1}^k + u_{i, j-1}^k - 2u_{i, j}^k}{h_y^2} ight)
      label{eq_2}
      end{equation}
      由于该差分格式在时间上是多步法, 启动时需要给定前两层时间步上的数值才能构造迭代数列. 初值条件仅提供第0层时间步数值, 需要手动计算第1层时间步数值, 以填充迭代数列之启动数组.
      根据初值条件, 采用中心差分离散之,
      egin{equation}
      frac{u_{i, j}^1 - u_{i, j}^{-1}}{2h_t} = 0
      label{eq_3}
      end{equation}
      根据式( ef{eq_2}), 令$k = 0$有,
      egin{equation}
      frac{u_{i, j}^{1} + u_{i, j}^{-1} - 2u_{i, j}^0}{h_t^2} = Dleft(frac{u_{i+1, j}^0 + u_{i-1, j}^0 - 2u_{i, j}^0}{h_x^2} + frac{u_{i, j+1}^0 + u_{i, j-1}^0 - 2u_{i, j}^0}{h_y^2} ight)
      label{eq_4}
      end{equation}
      结合式( ef{eq_3})、式( ef{eq_4})可得第1层时间步数值,
      egin{equation}
      u_{i, j}^1 = frac{Dh_t^2}{2}left( frac{u_{i+1, j}^0 + u_{i-1, j}^0 - 2u_{i, j}^0}{h_x^2} + frac{u_{i, j+1}^0 + u_{i, j-1}^0 - 2u_{i, j}^0}{h_y^2} ight) + u_{i, j}^0
      label{eq_5}
      end{equation}
    • 离散型方程的数值求解(代码实现):
        1 # 2D Wave Equation - Finite Difference之实现
        2 
        3 import os
        4 import shutil
        5 import numpy
        6 from matplotlib import pyplot as plt
        7 from PIL import Image
        8 
        9 
       10 # 波动方程求解
       11 class WaveEq(object):
       12     
       13     def __init__(self, nx, ny, nt, D=0.1, xc=1, yc=1):
       14         self.__nx = nx                 # x轴网格数
       15         self.__ny = ny                 # y轴网格数
       16         self.__nt = nt                 # t轴网格数
       17         self.__D = D
       18         self.__xc = xc
       19         self.__yc = yc
       20         
       21         self.__init_grid()             # 网格初始化
       22         
       23     
       24     def __init_grid(self):
       25         xMin, xMax = 0, 2
       26         yMin, yMax = 0, 2
       27         tMin, tMax = 0, 6
       28         self.__hx = (xMax - xMin) / self.__nx
       29         self.__hy = (yMax - yMin) / self.__ny
       30         self.__ht = (tMax - tMin) / self.__nt
       31         self.__X = numpy.linspace(xMin, xMax, self.__nx + 1)
       32         self.__Y = numpy.linspace(yMin, yMax, self.__ny + 1)
       33         self.__T = numpy.linspace(tMin, tMax, self.__nt + 1)
       34         self.__X, self.__Y = numpy.meshgrid(self.__X, self.__Y)
       35 
       36 
       37     def get_solu(self):
       38         U0 = self.__calc_U0()
       39         yield self.__X, self.__Y, U0
       40         U1 = self.__calc_U1(U0)
       41         yield self.__X, self.__Y, U1
       42         Uk_1, Uk_2 = U1, U0
       43         for i in range(2, self.__nt+1):
       44             Uk = self.__calc_Uk(Uk_1, Uk_2)
       45             yield self.__X, self.__Y, Uk
       46             Uk_1, Uk_2 = Uk, Uk_1
       47         
       48         
       49     def __calc_Uk(self, Uk_1, Uk_2):
       50         '''
       51         计算第k层时间步数值
       52         '''
       53         Uk = numpy.zeros(Uk_1.shape)
       54         for i in range(1, self.__nx):
       55             for j in range(1, self.__ny):
       56                 term1 = (Uk_1[j, i+1] + Uk_1[j, i-1] - 2 * Uk_1[j, i]) / self.__hx ** 2
       57                 term2 = (Uk_1[j+1, i] + Uk_1[j-1, i] - 2 * Uk_1[j, i]) / self.__hy ** 2
       58                 Uk[j, i] = (term1 + term2) * self.__D * self.__ht ** 2 + 2 * Uk_1[j, i] - Uk_2[j, i]
       59         return Uk        
       60     
       61     
       62     def __calc_U1(self, U0):
       63         '''
       64         计算第1层时间步数值
       65         '''
       66         U1 = numpy.zeros(U0.shape)
       67         for i in range(1, self.__nx):
       68             for j in range(1, self.__ny):
       69                 term1 = (U0[j, i+1] + U0[j, i-1] - 2 * U0[j, i]) / self.__hx ** 2
       70                 term2 = (U0[j+1, i] + U0[j-1, i] - 2 * U0[j, i]) / self.__hy ** 2
       71                 U1[j, i] = (term1 + term2) * self.__D * self.__ht ** 2 / 2 + U0[j, i]
       72         return U1
       73     
       74         
       75     def __calc_U0(self):
       76         '''
       77         计算第0层时间步数值
       78         '''
       79         U0 = self.__calc_u0(self.__X, self.__Y)
       80         self.__fill_boundary(U0)                                 # 填充边界条件
       81         return U0
       82         
       83         
       84     def __fill_boundary(self, mat):
       85         mat[0, :] = 0
       86         mat[-1, :] = 0
       87         mat[:, 0] = 0
       88         mat[:, -1] = 0
       89                 
       90         
       91     def __calc_u0(self, x, y):
       92         '''
       93         计算初始profile
       94         '''
       95         u0 = 0.1 * numpy.exp(-((x - self.__xc) ** 2 + (y - self.__yc) ** 2) / 0.001)
       96         return u0
       97         
       98         
       99     def __calc_v0(self, x, y):
      100         '''
      101         计算初始velocity
      102         '''
      103         v0 = 0 * x
      104         return v0
      105         
      106         
      107 # 动态图绘制
      108 class WavePlot(object):
      109     
      110     def __init__(self, waveObj):
      111         self.__waveObj = waveObj
      112         
      113     
      114     def ani_plot(self, aniPath):
      115         if not os.path.exists(aniPath):
      116             os.mkdir(aniPath)
      117         
      118         imgs = list()
      119         for idx, solu in enumerate(self.__waveObj.get_solu()):
      120             print(idx)
      121             if (idx % 5 == 0):
      122                 X, Y, Uk = solu
      123                 fig = plt.figure(figsize=(8, 8))
      124                 ax1 = plt.subplot()
      125                 ax1.pcolor(X, Y, Uk[:-1, :-1], cmap="jet", vmin=0)
      126                 filename = "{}/{}.png".format(aniPath, idx)
      127                 fig.savefig("{}".format(filename), dpi=80)
      128                 plt.close()
      129                 img = Image.open(filename)
      130                 imgs.append(img)
      131         img.save("wave_plot.gif", save_all=True, append_images=imgs, duration=5)
      132         shutil.rmtree(aniPath)
      133 
      134 
      135 
      136 if __name__ == "__main__":
      137     waveObj = WaveEq(300, 300, 1000, 0.1)
      138     wpltObj = WavePlot(waveObj)
      139     wpltObj.ani_plot("./wave_plot")
      View Code
    • 结果展示:
    • 参考文档:
      https://zhuanlan.zhihu.com/p/111640958
  • 相关阅读:
    大型web系统数据缓存设计-l转载
    HDFS 原理、架构与特性介绍--转载
    golang函数——可以为类型(包括内置数据类型)定义函数,类似类方法,同时支持多返回值
    Hadoop之父Doug Cutting:Lucene到Hadoop的开源之路
    ES mapping可以修改include_in_all,也可以修改index_options,norm,但是无法修改_all属性!
    换npm yarn的源让install超时去死吧
    nodejs Yarn替代npm的包管理——快速、安全、可靠性高的依赖管理
    Faas 典型场景——应用负载有显著的波峰波谷,典型用例-基于事件的数据处理
    docker run Influxdb
    在Docker Hub上你可以很轻松下载到大量已经容器化的应用镜像,即拉即用——daocloud国内镜像加速
  • 原文地址:https://www.cnblogs.com/xxhbdk/p/13237034.html
Copyright © 2011-2022 走看看