当前位置:   article > 正文

二维Poisson方程五点差分格式与Python实现_用有限差分方法(五点差分格式)求解正方形域上的poisson方程边值问题

用有限差分方法(五点差分格式)求解正方形域上的poisson方程边值问题
  • 最近没怎么写新文章,主要在学抽象代数
  • 下学期还有凸分析
  • 好累的一学期
  • 哦对,我不是数学系的,我是物理系的。而且博主需要澄清一下,博主没有对象,至少现在还没有。


  • 好,兄弟们,好习惯,先上代码后说话!

Python 实现

  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. from mpl_toolkits.mplot3d import Axes3D
  4. import scipy.sparse as ss
  5. from scipy.sparse.linalg import spsolve
  6. class PDE2DModel:
  7. #均应该传入一个一维二元数组,表示起止值
  8. def __init__(self,x,y):
  9. assert len(x)==len(y)==2,"ERROR:UNEXPECTED SV and EV!!"
  10. self.x = x
  11. self.y = y
  12. #hx表示X上的步长
  13. #hy表示Y上的步长
  14. def space_grid(self,hx,hy):
  15. M = int(round((self.x[1]-self.x[0])/hx,0))
  16. N = int(round((self.y[1]-self.y[0])/hy,0))
  17. assert M==N>=3,"至少网格数是合理的"
  18. X = np.linspace(self.x[0],self.x[1],M+1)
  19. Y = np.linspace(self.y[0],self.y[1],N+1)
  20. return M,N,X,Y
  21. def f(self,X,Y):
  22. return 6*X*Y**3+6*X**3*Y+np.e**X*np.sin(Y)-np.e**X*np.sin(Y)
  23. def solution(self,X,Y):
  24. return np.e**X*np.sin(Y)-X**3*Y**3
  25. #左边界
  26. def left(self,Y):
  27. return np.sin(Y)
  28. #右边界
  29. def right(self,Y):
  30. return np.e**3*np.sin(Y)-27*Y**3
  31. #上边界
  32. def up(self,X):
  33. return np.sin(1)*np.e**X-X**3
  34. #下边界
  35. def down(self,X):
  36. return 0*X
  37. #解算核心
  38. def NDM5_2D(PDE2DModel,hx,hy):
  39. M,N,X0,Y0 = PDE2DModel.space_grid(hx,hy)
  40. Y,X = np.meshgrid(Y0,X0)
  41. ## print("X0",X0)
  42. ## print("Y0",Y0)
  43. ## #数值结果保存在U中 从0到N共N+1
  44. ## print("M",M)
  45. ## print("N",N)
  46. U = np.zeros((M+1,N+1))
  47. U[0,:] = PDE2DModel.left(Y0)
  48. U[-1,:] = PDE2DModel.right(Y0)
  49. U[:,0] = PDE2DModel.down(X0)
  50. U[:,-1] = PDE2DModel.up(X0)
  51. D = np.diag([-1/(hy**2) for i in range(M-1)])
  52. C = np.zeros((N-1,N-1),dtype="float64")
  53. for i in range(N-1):
  54. C[i][i] = 2*(1/hx**2+1/hy**2)
  55. if i<N-2:
  56. C[i][i+1] = -1/hx**2
  57. C[i+1][i] = -1/hx**2
  58. u0 = np.array([[PDE2DModel.down(X0[i])] for i in range(1,M)])
  59. un = np.array([[PDE2DModel.up(X0[i])] for i in range(1,M)])
  60. F = np.zeros((M-1)*(N-1))
  61. for j in range(1,N):
  62. #for i in range(1,M):
  63. F[(N-1)*(j-1):(N-1)*(j)] = PDE2DModel.f(X0[1:M],np.array([Y0[j] for i in range(N-1)]))
  64. F[(N-1)*(j-1)] += PDE2DModel.left(Y0[j])/hx**2
  65. F[(N-1)*(j)-1] += PDE2DModel.right(Y0[j])/hx**2
  66. F[:N-1] -= np.dot(D,u0).T[0]
  67. F[(M-1)*(N-2):] -= np.dot(D,un).T[0]
  68. F = np.mat(F).T
  69. ## print(F)
  70. Dnew = np.zeros(((M-1)*(N-1),(N-1)*(M-1)))
  71. for i in range((N-1)*(N-1)):
  72. Dnew[i][i] = 2*(1/hx**2+1/hy**2)
  73. if i<(N-2)*(N-1):
  74. Dnew[i][i+N-1] = -1/hy**2
  75. Dnew[i+N-1][i] = -1/hy**2
  76. for i in range(N-1):
  77. for j in range(N-2):
  78. Dnew[(N-1)*i+j][(N-1)*i+j+1] = -1/hx**2
  79. Dnew[(N-1)*i+j+1][(N-1)*i+j] = -1/hx**2
  80. print("差分方程构造完成!解算开始!")
  81. Unew = np.linalg.solve(Dnew,F)
  82. #print(Unew)
  83. U[1:-1,1:-1] = Unew[:,0].reshape((N-1,N-1)).T
  84. return X,Y,U
  85. #数据可视化
  86. def Visualized():
  87. x = np.array([0,3])
  88. y = np.array([0,1])
  89. pde = PDE2DModel(x,y)
  90. X,Y,U = NDM5_2D(pde,0.03,0.01)
  91. u = pde.solution(X,Y)
  92. print("解算完成!绘图已开始!")
  93. plt.figure(figsize=(15,5))
  94. ax1 = plt.subplot(131,projection="3d")
  95. ax2 = plt.subplot(132,projection="3d")
  96. ax3 = plt.subplot(133,projection="3d")
  97. ax1.set_title("Numeric Solution")
  98. ax1.set_xlabel("x")
  99. ax1.set_ylabel("y")
  100. ax1.plot_surface(X,Y,U,cmap="gist_ncar")
  101. ax2.set_title("Exact Solution")
  102. ax2.set_xlabel("x")
  103. ax2.set_ylabel("y")
  104. ax2.plot_surface(X,Y,u,cmap="gist_ncar")
  105. e = np.abs(U-u)
  106. ax3.set_title("Error")
  107. ax3.set_xlabel("x")
  108. ax3.set_ylabel("y")
  109. ax3.plot_surface(X,Y,e,cmap="gist_ncar")
  110. plt.show()
  111. return U,u,X,Y
  112. U,u,X,Y = Visualized()

  • 好习惯2,效果图

很好,接下去接着讲

五点差分格式

  •  这里我要用截图,截的我的小论文.没办法,CSDN写作太麻烦了,没有Latex好用.我记得这个好像可以调整,但我没学会

 

 很好,结束了.

注意事项

  • 你在写代码的时候,容易犯几个错误.
  • 在纸上图画出来了,然后呢,纸上是右手系,写进数组了,就忘了是啥系了!
  • 比如:
    Y,X = np.meshgrid(Y0,X0)
  • 我们需要重点看一下np.meshgrid问题.这才是大家想要的数据结构.....
  1. import numpy as np
  2. x = np.array([1,2,3,4,5,6,7,8,9,10])
  3. y = np.array([11,12,13,14,15,16,17,18,19,20])
  4. Y,X = np.meshgrid(y,x)

  •  其实这个还涉及到稀疏矩阵的问题,稀疏矩阵解决不了的话,你的运算量会变得超大!一定要用系数矩阵优化才能解决问题!!

所以,优化之后!

用稀疏矩阵优化

  1. import numpy as np
  2. import scipy as sp
  3. from scipy.sparse.linalg import spsolve
  4. from scipy.sparse import csr_matrix,csc_matrix
  5. import matplotlib.pyplot as plt
  6. from mpl_toolkits.mplot3d import Axes3D
  7. import scipy.sparse as ss
  8. from scipy.sparse.linalg import spsolve
  9. import time
  10. class PDE2DModel:
  11. def __init__(self):
  12. self.x = np.array([0,3])
  13. self.y = np.array([0,1])
  14. def space_grid(self,hx,hy):
  15. M = int(round((self.x[1]-self.x[0])/hx,0))
  16. N = int(round((self.y[1]-self.y[0])/hy,0))
  17. assert M==N>=3,"ERROR:UNECPECTED GRIDS M:"+str(M)+" N:"+str(N)
  18. X = np.linspace(self.x[0],self.x[1],M+1)
  19. Y = np.linspace(self.y[0],self.y[1],N+1)
  20. return M,N,X,Y
  21. def f(self,X,Y):
  22. return 6*X*Y**3+6*X**3*Y+np.e**X*np.sin(Y)-np.e**X*np.sin(Y)
  23. #左边界
  24. def left(self,Y):
  25. return np.sin(Y)
  26. #右边界
  27. def right(self,Y):
  28. return np.e**3*np.sin(Y)-27*Y**3
  29. #上边界
  30. def up(self,X):
  31. return np.sin(1)*np.e**X-X**3
  32. #下边界
  33. def down(self,X):
  34. return 0*X
  35. def NDM5_2D(PDE2DModel,hx,hy):
  36. M,N,X0,Y0 = PDE2DModel.space_grid(hx,hy)
  37. Y,X = np.meshgrid(Y0,X0)
  38. U = np.zeros((M+1,N+1))
  39. U[0,:] = PDE2DModel.left(Y0)
  40. U[-1,:] = PDE2DModel.right(Y0)
  41. U[:,0] = PDE2DModel.down(X0)
  42. U[:,-1] = PDE2DModel.up(X0)
  43. D = np.diag([-1/(hy**2) for i in range(M-1)])
  44. C = np.zeros((N-1,N-1),dtype="float64")
  45. for i in range(N-1):
  46. C[i][i] = 2*(1/hx**2+1/hy**2)
  47. if i<N-2:
  48. C[i][i+1] = -1/hx**2
  49. C[i+1][i] = -1/hx**2
  50. u0 = np.array([[PDE2DModel.down(X0[i])] for i in range(1,M)])
  51. un = np.array([[PDE2DModel.up(X0[i])] for i in range(1,M)])
  52. F = np.zeros((M-1)*(N-1))
  53. for j in range(1,N):
  54. F[(N-1)*(j-1):(N-1)*(j)] = PDE2DModel.f(X0[1:M],np.array([Y0[j] for i in range(N-1)]))
  55. F[(N-1)*(j-1)] += PDE2DModel.left(Y0[j])/hx**2
  56. F[(N-1)*(j)-1] += PDE2DModel.right(Y0[j])/hx**2
  57. F[:N-1] -= np.dot(D,u0).T[0]
  58. F[(M-1)*(N-2):] -= np.dot(D,un).T[0]
  59. F = np.mat(F).T
  60. Dnew = np.zeros(((M-1)*(N-1),(N-1)*(M-1)))
  61. for i in range((N-1)*(N-1)):
  62. Dnew[i][i] = 2*(1/hx**2+1/hy**2)
  63. if i<(N-2)*(N-1):
  64. Dnew[i][i+N-1] = -1/hy**2
  65. Dnew[i+N-1][i] = -1/hy**2
  66. for i in range(N-1):
  67. for j in range(N-2):
  68. Dnew[(N-1)*i+j][(N-1)*i+j+1] = -1/hx**2
  69. Dnew[(N-1)*i+j+1][(N-1)*i+j] = -1/hx**2
  70. print("差分方程构造完成!解算开始!")
  71. ## start = time.time()
  72. ## Unew = np.linalg.solve(Dnew,F)
  73. ## U[1:-1,1:-1] = Unew[:,0].reshape((N-1,N-1)).T
  74. ## end = time.time()
  75. ## t = end-start
  76. start = time.time()
  77. SDnew = csr_matrix(Dnew)
  78. SF = csr_matrix(F)
  79. SUnew = spsolve(SDnew,SF)
  80. U[1:-1,1:-1] = SUnew.reshape((N-1,N-1)).T
  81. end = time.time()
  82. t = end-start
  83. return X,Y,U,t
  84. def Visualized(X,Y,U):
  85. print("解算完成!绘图已开始!")
  86. plt.figure(figsize=(15,5))
  87. ax1 = plt.subplot(111,projection="3d")
  88. ax1.set_title("Numeric Solution")
  89. ax1.set_xlabel("x")
  90. ax1.set_ylabel("y")
  91. ax1.plot_surface(X,Y,U,cmap="gist_ncar")
  92. plt.show()
  93. pde = PDE2DModel()
  94. X,Y,U,t = NDM5_2D(pde,0.03,0.01)
  95. print(t)
  96. Visualized(X,Y,U)

Python技巧

map

  1. f = lambda x:x+5
  2. X = [1,2,3,4,5]
  3. map(f,X)
  4. <map object at 0x00000246B5CE6110>
  5. list(map(f,X))
  6. [6, 7, 8, 9, 10]

Python自制警告

  • Python 自制警告是很有必要的.
  • 自制的警告与自制的错误不一样,不会打断程序运行(显然废话)
  1. import warnings
  2. a = 0
  3. if a==0:
  4. warnings.warn("IGNORE!")
  5. print(a+3)
  1. Warning (from warnings module):
  2. File "C:\Users\LX\Desktop\新建 文本文档.py", line 34
  3. warnings.warn("IGNORE!")
  4. UserWarning: IGNORE THIS WARNING!
  5. 3

Python matplotlib技巧

##import matplotlib
##import matplotlib.pyplot as plt
##from mpl_toolkits.mplot3d import Axes3D
##matplotlib.rcParams["font.sans-serif"] = ["SimHei"]
##matplotlib.rcParams["axes.unicode_minus"] = False
##
##import numpy as np
##
##x = np.linspace(1,2,6)
##y = np.linspace(3,9,13)
##Y,X = np.meshgrid(y,x)
##X2,Y2 = np.meshgrid(x,y)
##
##plt.figure(figsize=(15,5))
##ax1 = plt.subplot(121,projection="3d")
##ax2 = plt.subplot(122,projection="3d")
##
##ax1.set_title("Inverse order")
##ax2.set_title("Ordinary order")
##ax1.set_xlabel("x")
##ax2.set_xlabel("x")
##
##f = lambda x,y:x*2+y*3
##ax1.plot_surface(X,Y,f(X,Y))
##
##ax2.plot_surface(X2,Y2,f(X2,Y2))
##
##plt.show()

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/434020
推荐阅读
相关标签
  

闽ICP备14008679号