多重网格法-松弛迭代法-二维泊松方程-python实现(非等距网格情形)

上一篇文章写了正方形网格的情形,实际计算中常常用到非等距矩形网格,因此我把上个代码改成了非等距形式。改成非等距形式后,五点差分法将泊松方程化成方程组时,公式形式和正方形形式稍微不一样,我推了一下,没查任何文献,不保证正确。方程左边是f,右边是原函数二阶导数的差分形式。将u[i,j]移到左边,除掉系数就得到u的方程组。

在这里插入图片描述
代码如下

import numpy as np  
import matplotlib.pyplot as plt
import math
from pylab import *  
from mpl_toolkits.mplot3d import axes3d

def fine2(grid0,hx0,hy0):   #化成细网格
    nx_grid2  =  int((hx0.size)*2 + 1) #x 方向粗化后网格数量
    ny_grid2  =  int((hy0.size)*2 + 1)        
    grid2  =  np.zeros((ny_grid2,nx_grid2),  dtype   =   float)
    hx2,hy2,x2,y2 = hx_level(nx_grid2-1)
    for i in range(1, hx0.size+1):
        i2 = i*2
        for j in range(1, hy0.size+1):              #赋值中间的网格
            j2 = j*2
            grid2[j2,i2] = grid0[j,i]
            grid2[j2,i2-1] = grid0[j,i]*(hx2[i2-2]/(hx2[i2-1]+hx2[i2-1]))+grid0[j,i-1]*(hx2[i2-1]/(hx2[i2-2]+hx2[i2-1]))
            grid2[j2-1,i2] = grid0[j,i]*(hy2[j2-2]/(hy2[j2-2]+hy2[j2-1])) +grid0[j-1,i]*(hy2[j2-1]/(hy2[j2-2]+hy2[j2-1])) 
            totalweight = 1./hx2[i2-1]+1./hx2[i2-2]+1./hy2[j2-1]+1./hy2[j2-2]
            weight2 = 1./hx2[i2-1]/totalweight
            weight3 = 1./hy2[j2-2]/totalweight
            weight1 = 1./hx2[i2-2]/totalweight
            weight4 = 1./hy2[j2-1]/totalweight
            grid2[j2-1,i2-1] = grid2[j2-1,i2-2]*weight1+grid2[j2-1,i2]*weight2+grid2[j2-2,i2-1]*weight3+grid2[j2,i2-1]*weight4
    for i in range(1, hx0.size+1):#赋值边界
        i2 = i*2
        grid2[0,2*i]  =  grid0[0,i]     
        grid2[0,2*i-1]  =  hx2[i2-1]/(hx2[i2-1]+hx2[i2-2])*grid0[0,i-1]+hx2[i2-2]/(hx2[i2-1]+hx2[i2-2])*grid0[0,i]     
        grid2[-1,2*i]  =  grid0[-1,i]   
        grid2[-1,2*i-1]  = hx2[i2-1]/(hx2[i2-1]+hx2[i2-2])*grid0[-1,i-1]+hx2[i2-2]/(hx2[i2-1]+hx2[i2-2])*grid0[-1,i] 
    grid2[0,int(hx0.size*2)] =  grid0[0,hx0.size]  #边界最后一个点
    grid2[-1,int(hx0.size*2)] =  grid0[-1,hx0.size]  #边界最后一个点

    for j in range(1, hy0.size+1):#赋值边界
        j2 = j*2
        grid2[2*j,0]  =  grid0[j,0]
        grid2[2*j-1,0]  =  hy2[j2-1]/(hy2[j2-1]+hy2[j2-2])*grid0[j-1,0]+hy2[j2-2]/(hy2[j2-1]+hy2[j2-2])*grid0[j,0] 
        grid2[2*j,-1]  =  grid0[j,-1]
        grid2[2*j-1,-1]  = hy2[j2-1]/(hy2[j2-1]+hy2[j2-2])*grid0[j-1,-1]+hy2[j2-2]/(hy2[j2-1]+hy2[j2-2])*grid0[j,-1] 
    grid2[int(hy0.size*2),0] =  grid0[hy0.size,0]  #边界最后一个点
    grid2[int(hy0.size*2),-1] =  grid0[hy0.size,-1]  #边界最后一个点

    return grid2
    

def hx_level(xsize):
    level = int(math.log2((nx_grid-1)/xsize))#     计算粗化了几次
    dstep  =  int(2**(level))
    hx2_grid  =  int((hx.size)/dstep)
    hy2_grid  =  int((hy.size)/dstep)
    hx2  =  np.zeros(hx2_grid,  dtype   =   float)
    hy2  =  np.zeros(hy2_grid,  dtype   =   float)
    for  i in range(0, hx2.size):                            
        j0  =  dstep*i
        h2_step  =  0.
        for j in range(dstep):    
            h2_step  =  h2_step + hx[j0 + j]
        hx2[i]  =  h2_step

    for  i in range(0, hy2.size):                            
        j0  =  dstep*i
        h2_step  =  0.
        for j in range(dstep):    
            h2_step  =  h2_step + hy[j0 + j]
        hy2[i]  =  h2_step
    x2 = np.zeros((hx2.size+1),  dtype   =   float)
    y2 = np.zeros((hy2.size+1),  dtype   =   float)
    x2[0] = xs
    y2[0] = ys
    for i in range(1, x2.size):# 赋值x2,默认不等距网格
        x2[i] = x2[i-1]+hx2[i-1]
    for j in range(1, y2.size):# 赋值y2,默认不等距网格
        y2[j] = y2[j-1]+hy2[j-1]
    return hx2,hy2,x2,y2
    

def coarsen2(grid0,hx0,hy0):
    #dstep  =  int(2**(level-1))
    nx_grid2  =  int((hx0.size)/2 + 1) #x 方向粗化后网格数量
    ny_grid2  =  int((hy0.size)/2 + 1)
    grid2  =  np.zeros((ny_grid2,nx_grid2),  dtype   =   float)
    hx2 = np.zeros((nx_grid2-1),  dtype   =   float)
    hy2 = np.zeros((ny_grid2-1),  dtype   =   float)
    x2 = np.zeros((nx_grid2),  dtype   =   float)
    y2 = np.zeros((ny_grid2),  dtype   =   float)
    x2[0] = xs
    y2[0] = ys
    for i in range(1, nx_grid2-1):
        for j in range(1, ny_grid2-1):              #赋值中间的网格
           i2  =  2*i
           j2  =  2*j
           weight_total = 1./hx0[i2-1]+1./hx0[i2]+1./hy0[j2-1]+1./hy0[j2]
           weight1 = (1./hx0[i2-1])/weight_total     # 周边四个网格的权重
           weight2 = (1./hx0[i2])/weight_total
           weight3 = (1./hy0[j2-1])/weight_total
           weight4 = (1./hy0[j2])/weight_total
           grid2[j,i]  =  0.4*grid0[j2,i2] +  0.6*weight1*grid0[j2,i2-1] + 0.6*weight2*grid0[j2,i2+1]+0.6*weight3*grid0[j2-1,i2]+0.6*weight4*grid0[j2+1,i2]
    for j in range(0, ny_grid2):#赋值边界
        grid2[j,0]  =  grid0[2*j,0]
        grid2[j,-1]  =  grid0[2*j,-1]
    for i in range(0, nx_grid2):
        grid2[0,i]  =  grid0[0,2*i]
        grid2[-1,i]  =  grid0[-1,2*i]
    
    return grid2#,hx2,hy2,x2,y2      

def Relax2(b2, phi0,  hx0,hy0,x1,x2):#
    omig = 1.85 #松弛迭代法
    leveli = int(round(math.log2((nx_grid-1)/hx0.size)))# 四舍五入后不容易出错
    print('level',leveli)
    ite  =  2*((leveli)*leveli*leveli*leveli)
    k = -2            #k 取负)值可保证至少迭代一定次数
    while(k <ite):
        print(k)
        for j in range(0,hy0.size+1):  #向上
            for i in range(1,hx0.size):       #沿着横坐标。      非均匀网格要改这里
                
                if j   ==  0:                     #最低下一行
                    phi0[j,i] = np.copy(phi0[j+1,i])
                elif j  == hy0.size:
                    phi0[j,i] = np.copy(phi0[j-1,i])#最上一行
                else:#五点差分法
                    #phi0[j,i] = (1-omig)*np.copy(phi0[j,i])+omig*(np.copy(phi0[j,i-1])+np.copy(phi0[j,i+1])+np.copy(phi0[j-1,i])+np.copy(phi0[j+1,i])+h[i]*h[i]* b2[i,j])/4.

                    
                    cofficient1 = 2./(hx0[i]+hx0[i-1])
                    cofficient2 = 2./(hy0[j]+hy0[j-1])
                    cofficient_u = cofficient1/hx0[i]+cofficient1/hx0[i-1]+cofficient2/hy0[j]+cofficient2/hy0[j-1]
                    point_l = cofficient1*np.copy(phi0[j,i-1])/hx0[i-1]

                    point_r = cofficient1*np.copy(phi0[j,i+1])/hx0[i]
                    point_u = cofficient2*np.copy(phi0[j+1,i])/hy0[j]
                    point_d = cofficient2*np.copy(phi0[j-1,i])/hy0[j-1]
                    phi0[j,i] = (1-omig)*np.copy(phi0[j,i])+omig*(point_l+point_r+point_u+point_d+ b2[j,i])/cofficient_u  
                          
        k = k+1
    return phi0
def b2hxy(x1,x2):
    b2  =  np.zeros((x2.size,x1.size),  dtype   =   float)
    for j in range(0, x2.size):# y
        for i in range(0,x1.size):#x
            b2[j,i] = bxy(x2[j],x1[i])
    return b2



def residual(br, v, h,x1,x2):  #计算残差, 后来感觉这步多余就删掉了

    r  =  np.zeros((h.size+1,h.size+1),  dtype   =   float)
    for j in range(1,h.size):  #向上
        for i in range(1,h.size):       #沿着横坐标
            r[j,i] = br[i,j]-(4.*np.copy(v[j,i])-np.copy(v[j,i-1])-np.copy(v[j,i+1])-np.copy(v[j-1,i])-np.copy(v[j+1,i]))/h[i]/h[i]
    return r

def MG(b_mg,phi0, x121, y121, hx0,hy0,level_total):
    vh = Relax2(b_mg,phi0,  hx0,hy0, x121, y121)     
    hx2,hy2,x12,x22 = hx_level(int(vh.shape[1]-1))

    for i in range (1, level_total):   #coarse and iterate
        print(i)
        v2h0   =   coarsen2(vh,hx2,hy2)
        b2h0   =  coarsen2(b_mg,hx2,hy2)
        hx2,hy2,x12,x22 = hx_level(int(v2h0.shape[1]-1))
        v2h = Relax2(b2h0,v2h0,  hx2,hy2, x12, x22)
        vh   =   v2h
        b_mg  =  b2h0
     
    for i in range (1, level_total):  # fine and itearate
        print(i)
        v2h0   =   fine2(vh,hx2,hy2)
        b2h0   =  fine2(b_mg,hx2,hy2)
        hx2,hy2,x12,x22 = hx_level(int(v2h0.shape[1]-1))
        v2h = Relax2(b2h0,v2h0,  hx2,hy2, x12, x22)
        vh   =   v2h
        b_mg  =  b2h0
    return vh,x12,x22 

def init(nx_grid,ny_grid,xs,xe,ys,ye,xleft_boundary_value,xright_boundary_value,dyleft_boundary_value,dyright_boundary_value):
    hx  =  (xe-xs)/(nx_grid-1)* np.ones(nx_grid-1,  dtype   =   float)   #x 方向步长,可以是非等距
    hy  =  (ye-ys)/(ny_grid-1)* np.ones(ny_grid-1,  dtype   =   float)   #y 方向步长
    x  =  np.zeros(nx_grid,  dtype   =   float)
    x[0]  =  xs
    x[-1]  =  xe
    for i in range(1, nx_grid-1):
        x[i]  =  x[i-1] + hx[i-1]
    y  =  np.zeros(ny_grid,  dtype   =   float)
    y[0]  =  ys
    y[-1]  =  ye
    for i in range(1, ny_grid-1):             # initialize x and y
        y[i]  =  y[i-1] + hy[i-1]

    phi   =   np.ones((y.size,x.size),  dtype   =   float)*0.1   # initialize results
    phi[:,0]  =  xleft_boundary_value
    phi[:,-1]  =  xright_boundary_value

    b  =  np.zeros((y.size,x.size),  dtype   =   float)#        initialize b
    for i in range(0, nx_grid):
        for j in range(0, ny_grid):
            b[j,i] = bxy(x[i],y[j])
    return x,y,hx,hy,phi,b

def bxy(x0,y0):#方程右边的函数
    return -2.*math.pi*math.pi*math.sin(math.pi*x0)*math.cos(math.pi*y0)

nx_grid  =  513 #at least 512 grids to reach enough depth
xs  =  -1.
xe  =  1.

ny_grid  =  65 #at least 512 grids to reach enough depth
ys  =  -1.
ye  =  1.
level_total = 4#  4重网格

xleft_boundary_value = 0.     # u(x = -1) = u(x = 1) = 0
xright_boundary_value = 0.
dyleft_boundary_value = 0.    # du(y = -1) = u(y = 1) = 0
dyright_boundary_value = 0.

x,y,hx,hy,phi,b =  init(nx_grid,ny_grid,xs,xe,ys,ye,xleft_boundary_value,xright_boundary_value,dyleft_boundary_value,dyright_boundary_value)
grid2  = coarsen2(b,hx,hy)
hx2,hy2,x2,y2 = hx_level(grid2.shape[1]-1)

grid3 = fine2(grid2,hx2,hy2)
hx3,hy3,x3,y3 = hx_level(grid3.shape[1]-1)

#print('hx',hx)
#hxlevel2,hylevel2,x22,y22 = hx_level(hx2.size)

#phi2 = Relax2(b,phi,  hx,x,y)
result,x121,y121 = MG(b,phi, x, y, hx,hy,level_total)
#result = Relax2(b, phi,  hx,hy,x,y)
#hxr,hyr,xr,yr = hx_level(result.shape[1])
print(result.max(),result.min())
X,Y = np.meshgrid(x121,y121)
fig1 = plt.figure(1)
ax = fig1.gca(projection = '3d')
#contourf(x121,y121,  result, 80,  cmap  =  'seismic')  
ax.plot_surface(X,Y,  result,cmap = plt.get_cmap('jet'))  
#plt.colorbar()

plt.figure(2)
contourf(x,  y,  b, 80,  cmap  =  'seismic')  

plt.colorbar()

plt.show()
plt.close()

结果如下

``在这里插入图片描述`

  • 2
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值