[关闭]
@wudawufanfan 2016-12-11T14:08:47.000000Z 字数 19511 阅读 470

Potentials and Fields

优酷录屏2016-12-10-22-14-33.gif

650421609.png

electric potential and fields:laplace's equation

In regions of space that do not contain any electric charges,the electric potential obeys Laplace's equation

Our problem is to find the function V(x,y,z) that satisfies both Laplace's equation and the specified boundary conditions.
As usual we discretize the independent variables,in the case x,y and z.Points in our space are then specified by integers i,j,k.Our goal is to determine the potential on this lattice of points.

is we set
Inserting them all into Laplace's equation and solving for V(i,j,k) we find


FIGURE:Schematic flowchart for the relaxation algorithm

the problem of calculating the electric potential inside the square box

the boundary conditions we assume that the face of the box at x=-1 is held at V=-1,while V=+1 on the face at x=1. and V(i,j,k) is independent of k.

Jacobi Method (via wikipedia):

An algorithm for determining the solutions of a diagonally dominant system of linear equations. Each diagonal element is solved for, and an approximate value is plugged in. The process is then iterated until it converges. This algorithm is a stripped-down version of the Jacobi transformation method of matrix diagonalization.
In other words, Jacobi’s method is an iterative method for solving systems of linear equations, very similar to Gauss-Seidel Method. Beginning with the standard Ax = b, where A is a known matrix and b is a known vector we can use Jacobi’s method to approximate/solve x. The one caveat being the A matrix must be diagonally dominant to ensure that the method converges, although it occasionally converges without this condition being met.

  1. import numpy as np
  2. from scipy.linalg import solve
  3. def jacobi(A, b, x, n):
  4. D = np.diag(A)
  5. R = A - np.diagflat(D)
  6. for i in range(n):
  7. x = (b - np.dot(R,x))/ D
  8. return x
  9. '''___Main___'''
  10. A = np.array([[4.0, -2.0, 1.0], [1.0, -3.0, 2.0], [-1.0, 2.0, 6.0]])
  11. b = [1.0, 2.0, 3.0]
  12. x = [1.0, 1.0, 1.0]
  13. n = 25
  14. x = jacobi(A, b, x, n)
  15. print (solve(A, b))
  16. init [1.0, 1.0, 1.0]
  17. 000 [ 0.5 0.33333333 0.33333333]
  18. 001 [ 0.33333333 -0.27777778 0.47222222]
  19. 002 [-0.00694444 -0.24074074 0.64814815]
  20. 003 [-0.03240741 -0.23688272 0.57908951]
  21. 004 [-0.01321373 -0.29140947 0.57355967]
  22. 005 [-0.03909465 -0.28869813 0.5949342 ]
  23. 006 [-0.04308262 -0.28307542 0.58971694]
  24. 007 [-0.03896694 -0.28788291 0.58717804]
  25. 008 [-0.04073597 -0.28820362 0.58946648]
  26. 009 [-0.04146843 -0.28726767 0.58927855]
  27. 010 [-0.04095347 -0.28763711 0.58884448]
  28. 011 [-0.04102968 -0.28775483 0.58905346]
  29. 012 [-0.04114078 -0.28764092 0.58908 ]
  30. 013 [-0.04109046 -0.28766026 0.58902351]
  31. 014 [-0.04108601 -0.28768115 0.58903834]
  32. 015 [-0.04110016 -0.28766977 0.58904605]
  33. 016 [-0.0410964 -0.28766935 0.5890399 ]
  34. 017 [-0.04109465 -0.2876722 0.58904039]
  35. 018 [-0.0410962 -0.28767129 0.58904162]
  36. 019 [-0.04109605 -0.28767098 0.58904107]
  37. 020 [-0.04109576 -0.28767131 0.58904099]
  38. 021 [-0.0410959 -0.28767126 0.58904114]
  39. 022 [-0.04109592 -0.2876712 0.5890411 ]
  40. 023 [-0.04109588 -0.28767124 0.58904108]
  41. 024 [-0.04109589 -0.28767124 0.5890411 ]
  42. Sol [-0.04109589 -0.28767124 0.5890411 ]
  43. Act [-0.04109589 -0.28767123 0.5890411 ]

Now we consider two complicated cases where an analytic solution is difficult.
A long infinitely long,hollow prism,with metallic walls and a square cross-section.The prism and inner conductor are presumed to be infinite in extent along z,The inner conductor is held at V=1 and the walls of the prism at V=0QQ截图20161210235455.jpg

Another example is two capacitor plates held at V=1(left plate) and V=-1(right plate).The square boundary surrounding the plates is held at V=0
QQ截图20161211000250.jpg


images.jpg

  1. from numpy import *
  2. import mpl_toolkits.mplot3d
  3. import matplotlib.pyplot as plt
  4. from matplotlib import cm
  5. from matplotlib.ticker import LinearLocator, FormatStrFormatter
  6. '''
  7. class Electric_Field
  8. this class solves the potential euation of capacitor
  9. where:
  10. V1: potential of the left plate
  11. V2: potential of the right palte
  12. n: size of one side
  13. '''
  14. class ELECTRIC_FIELD(object):
  15. def __init__(self, V1=1, V2=-1, V_boundary=0, n=30):
  16. self.V1=float(V1)
  17. self.V2=float(V2)
  18. self.V_boundary=float(V_boundary)
  19. self.n=int(n)
  20. self.s1, self.s3=int(n/3), int(n/3)
  21. self.s2, self.s4=int(self.n-2-2*self.s1), int(self.n-2*self.s3)
  22. self.V=[]
  23. for j in range(self.n):
  24. self.V.append([0.0]*self.n)
  25. for j in [0,self.n-1]:
  26. self.V[j]=[self.V_boundary]*self.n
  27. for j in range(self.s3,self.s3+self.s4):
  28. self.V[j][self.s1]=self.V1
  29. self.V[j][self.s1+self.s2+1]=self.V2
  30. def update_V_SOR(self): # use SOR method solve the potential
  31. self.alpha=2./(1.+pi/self.n)
  32. self.counter=0
  33. while True:
  34. self.delta_V=0.
  35. for j in range(1,self.n-1):
  36. for i in range(1,self.n-1):
  37. if (j in range(self.s3,self.s3+self.s4)) and (i in [self.s1,self.s1+self.s2+1]):
  38. continue
  39. self.next_V=1./4.*(self.V[j-1][i]+self.V[j+1][i]+self.V[j][i-1]+self.V[j][i+1])
  40. self.V[j][i]=self.alpha*(self.next_V-self.V[j][i])+self.V[j][i]
  41. self.delta_V=self.delta_V+abs(self.alpha*(self.next_V-self.V[j][i]))
  42. self.counter=self.counter+1
  43. if (self.delta_V < abs(self.V2-self.V1)*(1.0E-5)*self.n*self.n and self.counter >= 10):
  44. break
  45. print ('itertion length n=',self.n,' ',self.counter,' times')
  46. def Ele_field(self,x1,x2,y1,y2): # calculate the Electirc field
  47. self.dx=abs(x1-x2)/float(self.n-1)
  48. self.Ex=[]
  49. self.Ey=[]
  50. for j in range(self.n):
  51. self.Ex.append([0.0]*self.n)
  52. self.Ey.append([0.0]*self.n)
  53. for j in range(1,self.n-1,1):
  54. for i in range(1,self.n-1,1):
  55. self.Ex[j][i]=-(self.V[j][i+1]-self.V[j][i-1])/(2*self.dx)
  56. self.Ey[j][i]=-(self.V[j-1][i]-self.V[j+1][i])/(2*self.dx)
  57. def plot_3d(self,ax,x1,x2,y1,y2): # give 3d plot the potential
  58. self.x=linspace(x1,x2,self.n)
  59. self.y=linspace(y2,y1,self.n)
  60. self.x,self.y=meshgrid(self.x,self.y)
  61. self.surf=ax.plot_surface(self.x,self.y,self.V, rstride=1, cstride=1, cmap=cm.coolwarm)
  62. ax.set_xlim(x1,x2)
  63. ax.set_ylim(y1,y2)
  64. ax.zaxis.set_major_locator(LinearLocator(10))
  65. ax.zaxis.set_major_formatter(FormatStrFormatter('%.01f'))
  66. ax.set_xlabel('x (m)',fontsize=14)
  67. ax.set_ylabel('y (m)',fontsize=14)
  68. ax.set_zlabel('Electric potential (V)',fontsize=14)
  69. ax.set_title('Potential near capacitor',fontsize=18)
  70. def plot_2d(self,ax1,ax2,x1,x2,y1,y2): # give 2d plot of potential and electric field
  71. self.x=linspace(x1,x2,self.n)
  72. self.y=linspace(y2,y1,self.n)
  73. self.x,self.y=meshgrid(self.x,self.y)
  74. cs=ax1.contour(self.x,self.y,self.V)
  75. plt.clabel(cs, inline=1, fontsize=10)
  76. ax1.set_title('Equipotential lines',fontsize=18)
  77. ax1.set_xlabel('x (m)',fontsize=14)
  78. ax1.set_ylabel('y (m)',fontsize=14)
  79. for j in range(1,self.n-1,1):
  80. for i in range(1,self.n-1,1):
  81. ax2.arrow(self.x[j][i],self.y[j][i],self.Ex[j][i]/40,self.Ey[j][i]/40,fc='k', ec='k')
  82. ax2.set_xlim(-1.,1.)
  83. ax2.set_ylim(-1.,1.)
  84. ax2.set_title('Electric field',fontsize=18)
  85. ax2.set_xlabel('x (m)',fontsize=14)
  86. ax2.set_ylabel('y (m)',fontsize=14)
  87. def export_data(self,x1,x2,y1,y2):
  88. self.mfile=open(r'd:\data.txt','w')
  89. self.x=linspace(x1,x2,self.n)
  90. self.y=linspace(y2,y1,self.n)
  91. self.x,self.y=meshgrid(self.x,self.y)
  92. for j in range(self.n):
  93. for i in range(self.n):
  94. print >> self.mfile, self.x[j][i],self.y[j][i],self.V[j][i]
  95. self.mfile.close()
  96. # give plot of potential and electric field
  97. fig=plt.figure(figsize=(10,5))
  98. ax1=plt.axes([0.1,0.1,0.35,0.8])
  99. ax2=plt.axes([0.55,0.1,0.35,0.8])
  100. cmp=ELECTRIC_FIELD(1,-1,0,20)
  101. cmp.update_V_SOR()
  102. cmp.Ele_field(-1,1,-1,1)
  103. cmp.plot_2d(ax1,ax2,-1.,1.,-1.,1.)
  104. plt.show()
  105. # give 3d plot of potential
  106. fig=plt.figure(figsize=(14,7))
  107. ax1= plt.subplot(1,2,1,projection='3d')
  108. cmp=ELECTRIC_FIELD()
  109. cmp.update_V_SOR()
  110. cmp.plot_3d(ax1,-1.,1.,-1.,1.)
  111. fig.colorbar(cmp.surf, shrink=0.5, aspect=5)
  112. ax2= plt.subplot(1,2,2,projection='3d')
  113. cmp=ELECTRIC_FIELD(5,-0.5,0,20)
  114. cmp.update_V_SOR()
  115. cmp.plot_3d(ax2,-1.,1.,-1.,1.)
  116. fig.colorbar(cmp.surf, shrink=0.5, aspect=5)
  117. plt.show(fig)

figure_1.png

  1. from __future__ import division
  2. import matplotlib
  3. import numpy as np
  4. import matplotlib.cm as cm
  5. import matplotlib.mlab as mlab
  6. import matplotlib.pyplot as plt
  7. from mpl_toolkits.mplot3d import Axes3D
  8. # initialize the grid
  9. grid = []
  10. for i in range(201):
  11. row_i = []
  12. for j in range(201):
  13. if i == 0 or i == 200 or j == 0 or j == 200:
  14. voltage = 0
  15. elif 70<=i<=130 and j == 70:
  16. voltage = 1
  17. elif 70<=i<=130 and j == 130:
  18. voltage = -1
  19. else:
  20. voltage = 0
  21. row_i.append(voltage)
  22. grid.append(row_i)
  23. # define the update_V function (Gauss-Seidel method)
  24. def update_V(grid):
  25. delta_V = 0
  26. for i in range(201):
  27. for j in range(201):
  28. if i == 0 or i == 200 or j == 0 or j == 200:
  29. pass
  30. elif 70<=i<=130 and j == 70:
  31. pass
  32. elif 70<=i<=130 and j == 130:
  33. pass
  34. else:
  35. voltage_new = (grid[i+1][j]+grid[i-1][j]+grid[i][j+1]+grid[i][j-1])/4
  36. voltage_old = grid[i][j]
  37. delta_V += abs(voltage_new - voltage_old)
  38. grid[i][j] = voltage_new
  39. return grid, delta_V
  40. # define the Laplace_calculate function
  41. def Laplace_calculate(grid):
  42. epsilon = 10**(-5)*200**2
  43. grid_init = grid
  44. delta_V = 0
  45. N_iter = 0
  46. while delta_V >= epsilon or N_iter <= 10:
  47. grid_impr, delta_V = update_V(grid_init)
  48. grid_new, delta_V = update_V(grid_impr)
  49. grid_init = grid_new
  50. N_iter += 1
  51. return grid_new
  52. matplotlib.rcParams['xtick.direction'] = 'out'
  53. matplotlib.rcParams['ytick.direction'] = 'out'
  54. x = np.linspace(0,200,201)
  55. y = np.linspace(0,200,201)
  56. X, Y = np.meshgrid(x, y)
  57. Z = Laplace_calculate(grid)
  58. plt.figure()
  59. CS = plt.contour(X,Y,Z,10)
  60. plt.clabel(CS, inline=1, fontsize=12)
  61. plt.title('voltage near capacitor')
  62. plt.xlabel('x(m)')
  63. plt.ylabel('y(m)')
  64. fig = plt.figure()
  65. ax = fig.add_subplot(111, projection='3d')
  66. ax.plot_surface(X, Y, Z)
  67. ax.set_xlabel('x(m)')
  68. ax.set_ylabel('y(m)')
  69. ax.set_zlabel('voltage(V)')
  70. ax.set_title('voltage distribution')
  71. plt.show()

figure4.png

下载.png
Mathematically the Jacobi method can be expressed as


the simple improvement is the Gasuss-Seidel method.


and we can think of
to speed up convergence we will change potential by a larger amount calculated according to

where is a factor that measures how much we "over-relax"

  1. from numpy import *
  2. import mpl_toolkits.mplot3d
  3. import matplotlib.pyplot as plt
  4. from matplotlib import cm
  5. from matplotlib.ticker import LinearLocator, FormatStrFormatter
  6. import time
  7. '''
  8. class Electric_Field
  9. this class solves the potential euation of capacitor
  10. where:
  11. V1: potential of the left plate
  12. V2: potential of the right palte
  13. n: size of one side
  14. '''
  15. class ELECTRIC_FIELD(object):
  16. def __init__(self, V1=1, V2=-1, V_boundary=0, n=30):
  17. self.V1=float(V1)
  18. self.V2=float(V2)
  19. self.V_boundary=float(V_boundary)
  20. self.n=int(n)
  21. self.s1, self.s3=int(n/3), int(n/3)
  22. self.s2, self.s4=int(self.n-2-2*self.s1), int(self.n-2*self.s3)
  23. self.V=[]
  24. for j in range(self.n):
  25. self.V.append([0.0]*self.n)
  26. for j in [0,self.n-1]:
  27. self.V[j]=[self.V_boundary]*self.n
  28. for j in range(self.s3,self.s3+self.s4):
  29. self.V[j][self.s1]=self.V1
  30. self.V[j][self.s1+self.s2+1]=self.V2
  31. def update_V_Jacobi(self):
  32. self.counter=0 # use Jacobi method solve the potential
  33. while True:
  34. self.V_next=[]
  35. for j in range(self.n):
  36. self.V_next.append([0.0]*self.n)
  37. for j in range(self.n):
  38. for i in range(self.n):
  39. self.V_next[j][i]=self.V[j][i]
  40. self.delta_V=0.
  41. for j in range(1,self.n-1):
  42. for i in range(1,self.n-1):
  43. if (j in range(self.s3,self.s3+self.s4)) and (i in [self.s1,self.s1+self.s2+1]):
  44. continue
  45. self.V_next[j][i]=1./4.*(self.V[j-1][i]+self.V[j+1][i]+self.V[j][i-1]+self.V[j][i+1])
  46. self.delta_V=self.delta_V+abs(self.V_next[j][i]-self.V[j][i])
  47. self.counter=self.counter+1
  48. for j in range(self.n):
  49. for i in range(self.n):
  50. self.V[j][i]=self.V_next[j][i]
  51. if (self.delta_V < abs(self.V2-self.V1)*(1.0E-5)*self.n*self.n and self.counter >= 10):
  52. break
  53. print ('jacobi itertion length n=',self.n,' ',self.counter,' times')
  54. return self.counter
  55. def update_V_Gauss(self): # use Gauss-Seidel method solve the potential
  56. self.counter=0
  57. while True:
  58. self.delta_V=0.
  59. for j in range(1,self.n-1):
  60. for i in range(1,self.n-1):
  61. if (j in range(self.s3,self.s3+self.s4)) and (i in [self.s1,self.s1+self.s2+1]):
  62. continue
  63. self.next_V=1./4.*(self.V[j-1][i]+self.V[j+1][i]+self.V[j][i-1]+self.V[j][i+1])
  64. self.delta_V=self.delta_V+abs(self.next_V-self.V[j][i])
  65. self.V[j][i]=self.next_V
  66. self.counter=self.counter+1
  67. if (self.delta_V < abs(self.V2-self.V1)*(1.0E-5)*self.n*self.n and self.counter >= 10):
  68. break
  69. print ('gauss itertion length n=',self.n,' ',self.counter,' times')
  70. return self.counter
  71. def update_V_SOR(self): # use SOR method solve the potential
  72. self.alpha=2./(1.+pi/self.n)
  73. self.counter=0
  74. while True:
  75. self.delta_V=0.
  76. for j in range(1,self.n-1):
  77. for i in range(1,self.n-1):
  78. if (j in range(self.s3,self.s3+self.s4)) and (i in [self.s1,self.s1+self.s2+1]):
  79. continue
  80. self.next_V=1./4.*(self.V[j-1][i]+self.V[j+1][i]+self.V[j][i-1]+self.V[j][i+1])
  81. self.V[j][i]=self.alpha*(self.next_V-self.V[j][i])+self.V[j][i]
  82. self.delta_V=self.delta_V+abs(self.alpha*(self.next_V-self.V[j][i]))
  83. self.counter=self.counter+1
  84. if (self.delta_V < abs(self.V2-self.V1)*(1.0E-5)*self.n*self.n and self.counter >= 10):
  85. break
  86. print( 'SOR itertion length n=',self.n,' ',self.counter,' times')
  87. return self.counter
  88. def Ele_field(self,x1,x2,y1,y2): # calculate the Electirc field
  89. self.dx=abs(x1-x2)/float(self.n-1)
  90. self.Ex=[]
  91. self.Ey=[]
  92. for j in range(self.n):
  93. self.Ex.append([0.0]*self.n)
  94. self.Ey.append([0.0]*self.n)
  95. for j in range(1,self.n-1,1):
  96. for i in range(1,self.n-1,1):
  97. self.Ex[j][i]=-(self.V[j][i+1]-self.V[j][i-1])/(2*self.dx)
  98. self.Ey[j][i]=-(self.V[j-1][i]-self.V[j+1][i])/(2*self.dx)
  99. def plot_3d(self,ax,x1,x2,y1,y2): # give 3d plot the potential
  100. self.x=linspace(x1,x2,self.n)
  101. self.y=linspace(y2,y1,self.n)
  102. self.x,self.y=meshgrid(self.x,self.y)
  103. self.surf=ax.plot_surface(self.x,self.y,self.V, rstride=1, cstride=1, cmap=cm.coolwarm)
  104. ax.set_xlim(x1,x2)
  105. ax.set_ylim(y1,y2)
  106. ax.zaxis.set_major_locator(LinearLocator(10))
  107. ax.zaxis.set_major_formatter(FormatStrFormatter('%.01f'))
  108. ax.set_xlabel('x (m)',fontsize=14)
  109. ax.set_ylabel('y (m)',fontsize=14)
  110. ax.set_zlabel('Electric potential (V)',fontsize=14)
  111. ax.set_title('Potential near capacitor',fontsize=18)
  112. def plot_2d(self,ax1,ax2,x1,x2,y1,y2): # give 2d plot of potential and electric field
  113. self.x=linspace(x1,x2,self.n)
  114. self.y=linspace(y2,y1,self.n)
  115. self.x,self.y=meshgrid(self.x,self.y)
  116. cs=ax1.contour(self.x,self.y,self.V)
  117. plt.clabel(cs, inline=1, fontsize=10)
  118. ax1.set_title('Equipotential lines',fontsize=18)
  119. ax1.set_xlabel('x (m)',fontsize=14)
  120. ax1.set_ylabel('y (m)',fontsize=14)
  121. for j in range(1,self.n-1,1):
  122. for i in range(1,self.n-1,1):
  123. ax2.arrow(self.x[j][i],self.y[j][i],self.Ex[j][i]/40,self.Ey[j][i]/40,fc='k', ec='k')
  124. ax2.set_xlim(-1.,1.)
  125. ax2.set_ylim(-1.,1.)
  126. ax2.set_title('Electric field',fontsize=18)
  127. ax2.set_xlabel('x (m)',fontsize=14)
  128. ax2.set_ylabel('y (m)',fontsize=14)
  129. def export_data(self,x1,x2,y1,y2): # export data
  130. self.mfile=open(r'd:\data.txt','w')
  131. self.x=linspace(x1,x2,self.n)
  132. self.y=linspace(y2,y1,self.n)
  133. self.x,self.y=meshgrid(self.x,self.y)
  134. for j in range(self.n):
  135. for i in range(self.n):
  136. print >> self.mfile, self.x[j][i],self.y[j][i],self.V[j][i]
  137. self.mfile.close()
  138. # compare three method
  139. n_min=10 # Jacobi method
  140. n_max=50
  141. n_jacobi=[]
  142. iters_jacobi=[]
  143. time_jacobi=[]
  144. for i in range(n_min,n_max,2):
  145. start=time.clock()
  146. cmp=ELECTRIC_FIELD(1,-1,0,i)
  147. iters_jacobi.append(cmp.update_V_Jacobi())
  148. end=time.clock()
  149. time_jacobi.append(end-start)
  150. n_jacobi.append(i)
  151. n_gauss=[] # Gauss Seidel method
  152. iters_gauss=[]
  153. time_gauss=[]
  154. for i in range(n_min,n_max,2):
  155. start=time.clock()
  156. cmp=ELECTRIC_FIELD(1,-1,0,i)
  157. iters_gauss.append(cmp.update_V_Gauss())
  158. end=time.clock()
  159. time_gauss.append(end-start)
  160. n_gauss.append(i)
  161. n_SOR=[] # SOR method
  162. iters_SOR=[]
  163. time_SOR=[]
  164. for i in range(n_min,n_max,2):
  165. start=time.clock()
  166. cmp=ELECTRIC_FIELD(1,-1,0,i)
  167. iters_SOR.append(cmp.update_V_SOR())
  168. end=time.clock()
  169. time_SOR.append(end-start)
  170. n_SOR.append(i)
  171. print( time_SOR)
  172. # export data
  173. mfile=open(r'd:\data.txt','w')
  174. for i in range(len(n_jacobi)):
  175. print ( n_jacobi[i], time_jacobi[i], time_gauss[i], time_SOR[i],file=mfile)
  176. mfile.close()
  177. # give a simple plot
  178. fig=plt.figure(figsize=(14,7))
  179. ax1=plt.axes([0.1,0.1,0.35,0.8])
  180. ax2=plt.axes([0.55,0.1,0.35,0.8])
  181. ax1.plot(n_jacobi,iters_jacobi,'or',markersize=5)
  182. ax1.plot(n_gauss,iters_gauss,'ob',markersize=5)
  183. ax1.plot(n_SOR,iters_SOR,'oy',markersize=5)
  184. ax2.plot(n_jacobi,time_jacobi,'or',markersize=5)
  185. ax2.plot(n_gauss,time_gauss,'ob',markersize=5)
  186. ax2.plot(n_SOR,time_SOR,'oy',markersize=5)
  187. plt.show(fig)

figure_2.png
the relation of side length and number of interations(left) time
consuming(right)

        

  1. from numpy import *
  2. import mpl_toolkits.mplot3d
  3. import matplotlib.pyplot as plt
  4. from matplotlib import cm
  5. from matplotlib.ticker import LinearLocator, FormatStrFormatter
  6. import time
  7. '''
  8. class Electric_Field
  9. this class solves the potential euation of capacitor
  10. where:
  11. V1: potential of the left plate
  12. V2: potential of the right palte
  13. n: size of one side
  14. '''
  15. class ELECTRIC_FIELD(object):
  16. def __init__(self, V1=1, V2=-1, V_boundary=0, n=30):
  17. self.V1=float(V1)
  18. self.V2=float(V2)
  19. self.V_boundary=float(V_boundary)
  20. self.n=int(n)
  21. self.s1, self.s3=int(n/3), int(n/3)
  22. self.s2, self.s4=int(self.n-2-2*self.s1), int(self.n-2*self.s3)
  23. self.V=[]
  24. for j in range(self.n):
  25. self.V.append([0.0]*self.n)
  26. for j in [0,self.n-1]:
  27. self.V[j]=[self.V_boundary]*self.n
  28. for j in range(self.s3,self.s3+self.s4):
  29. self.V[j][self.s1]=self.V1
  30. self.V[j][self.s1+self.s2+1]=self.V2
  31. def update_V_SOR(self,alpha): # use SOR method solve the potential
  32. self.alpha=float(alpha)
  33. self.counter=0
  34. while True:
  35. self.delta_V=0.
  36. for j in range(1,self.n-1):
  37. for i in range(1,self.n-1):
  38. if (j in range(self.s3,self.s3+self.s4)) and (i in [self.s1,self.s1+self.s2+1]):
  39. continue
  40. self.next_V=1./4.*(self.V[j-1][i]+self.V[j+1][i]+self.V[j][i-1]+self.V[j][i+1])
  41. self.delta_V=self.delta_V+abs(self.alpha*(self.next_V-self.V[j][i]))
  42. self.V[j][i]=self.alpha*(self.next_V-self.V[j][i])+self.V[j][i]
  43. self.counter=self.counter+1
  44. if (self.delta_V < abs(self.V2-self.V1)*(1.0E-5)*self.n*self.n and self.counter >= 10):
  45. break
  46. print ('SOR itertion alpha= ',self.alpha,' ',self.counter,' times')
  47. return self.counter
  48. def Ele_field(self,x1,x2,y1,y2): # calculate the Electirc field
  49. self.dx=abs(x1-x2)/float(self.n-1)
  50. self.Ex=[]
  51. self.Ey=[]
  52. for j in range(self.n):
  53. self.Ex.append([0.0]*self.n)
  54. self.Ey.append([0.0]*self.n)
  55. for j in range(1,self.n-1,1):
  56. for i in range(1,self.n-1,1):
  57. self.Ex[j][i]=-(self.V[j][i+1]-self.V[j][i-1])/(2*self.dx)
  58. self.Ey[j][i]=-(self.V[j-1][i]-self.V[j+1][i])/(2*self.dx)
  59. def plot_3d(self,ax,x1,x2,y1,y2): # give 3d plot the potential
  60. self.x=linspace(x1,x2,self.n)
  61. self.y=linspace(y2,y1,self.n)
  62. self.x,self.y=meshgrid(self.x,self.y)
  63. self.surf=ax.plot_surface(self.x,self.y,self.V, rstride=1, cstride=1, cmap=cm.coolwarm)
  64. ax.set_xlim(x1,x2)
  65. ax.set_ylim(y1,y2)
  66. ax.zaxis.set_major_locator(LinearLocator(10))
  67. ax.zaxis.set_major_formatter(FormatStrFormatter('%.01f'))
  68. ax.set_xlabel('x (m)',fontsize=14)
  69. ax.set_ylabel('y (m)',fontsize=14)
  70. ax.set_zlabel('Electric potential (V)',fontsize=14)
  71. ax.set_title('Potential near capacitor',fontsize=18)
  72. def plot_2d(self,ax1,ax2,x1,x2,y1,y2): # give 2d plot of potential and electric field
  73. self.x=linspace(x1,x2,self.n)
  74. self.y=linspace(y2,y1,self.n)
  75. self.x,self.y=meshgrid(self.x,self.y)
  76. cs=ax1.contour(self.x,self.y,self.V)
  77. plt.clabel(cs, inline=1, fontsize=10)
  78. ax1.set_title('Equipotential lines',fontsize=18)
  79. ax1.set_xlabel('x (m)',fontsize=14)
  80. ax1.set_ylabel('y (m)',fontsize=14)
  81. for j in range(1,self.n-1,1):
  82. for i in range(1,self.n-1,1):
  83. ax2.arrow(self.x[j][i],self.y[j][i],self.Ex[j][i]/40,self.Ey[j][i]/40,fc='k', ec='k')
  84. ax2.set_xlim(-1.,1.)
  85. ax2.set_ylim(-1.,1.)
  86. ax2.set_title('Electric field',fontsize=18)
  87. ax2.set_xlabel('x (m)',fontsize=14)
  88. ax2.set_ylabel('y (m)',fontsize=14)
  89. def export_data(self,x1,x2,y1,y2):
  90. self.mfile=open(r'd:\data.txt','w')
  91. self.x=linspace(x1,x2,self.n)
  92. self.y=linspace(y2,y1,self.n)
  93. self.x,self.y=meshgrid(self.x,self.y)
  94. for j in range(self.n):
  95. for i in range(self.n):
  96. print >> self.mfile, self.x[j][i],self.y[j][i],self.V[j][i]
  97. self.mfile.close()
  98. # change alpha and determine the number of iterations
  99. iters=[]
  100. alpha=[]
  101. for j in linspace(0.19,0.9,30):
  102. cmp=ELECTRIC_FIELD()
  103. alpha.append(j)
  104. iters.append(cmp.update_V_SOR(j))
  105. for j in linspace(0.91,1.3,20):
  106. cmp=ELECTRIC_FIELD()
  107. alpha.append(j)
  108. iters.append(cmp.update_V_SOR(j))
  109. for j in linspace(1.3,1.79,30):
  110. cmp=ELECTRIC_FIELD()
  111. alpha.append(j)
  112. iters.append(cmp.update_V_SOR(j))
  113. for j in linspace(1.8,1.98,30):
  114. cmp=ELECTRIC_FIELD()
  115. alpha.append(j)
  116. iters.append(cmp.update_V_SOR(j))
  117. mfile=open(r'd:\data.txt','w')
  118. for i in range(len(alpha)):
  119. print(alpha[i],iters[i],file=mfile)
  120. mfile.close()
  121. fig=plt.figure(figsize=(8,8))
  122. ax1=plt.subplot(111)
  123. ax1.plot(alpha,iters,'ob')
  124. ax1.set_xlabel('alpha')
  125. ax1.set_ylabel('number of iterations')
  126. plt.show(fig)

figure_3.png
the relation between alpha and number of interations
we can find when is around 1.5 to 2,we need the least work.

Thanks

Wu yuqiao and chengyaoyang's codes
Computational physics by Nicholas J.Giordano,Hisao Nakanishi

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注