多重網格法(multigrid)求解1d泊松方程--python

多重網格法(multigrid)求解1d泊松方程


多重網格法可能是目前已知最快的求解泊松方程的算法,特別是在邊界複雜的情況下,實用性遠高於快速傅里葉算法。 我寫裏寫了一個一維求解泊松方程的程序,有時間的話再寫個二維的。
教程參考
http://bender.astro.sunysb.edu/classes/numerical_methods/lectures/elliptic-multigrid.pdf
直接上代碼

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

def coarsen2(grid0):
    #dstep = int(2**(level-1))
    n_grid = int((grid0.size-1)/2 + 1) #int((grid0.size-1)/dstep + 1) 
    grid1 = np.zeros(n_grid,  dtype  =  float)
    
    for i in range(1, grid1.size-1):
        i2 = 2*i
        grid1[i] = 0.5*grid0[i2] + 0.25*grid0[i2-1] + 0.25*grid0[i2 + 1]

    grid1[0] = grid0[0]
    grid1[-1] = grid0[-1]
    return grid1

def h_level(level):
    h0 = h
    dstep = int(2**(level-1))
    h2_grid = int((h0.size)/dstep)
    h2 = np.zeros(h2_grid,  dtype  =  float)
    for  i in range(0, h2.size):                            
        j0 = dstep*i
        h2_step = 0.
        for j in range(dstep):
            h2_step = h2_step + h0[j0 + j]
        h2[i] = h2_step
    return h2

def Relax2( b,  phi,  h, level_total, leveli):
    om = 1.85
    ite = 4**leveli      # the iteration increase with the level to get higher precision
    j  =  0
    print("relax method")
    n2 = int(b.size/2)        #   choose the middle point to compare the err in each iteration
    while(j <ite): #控制迭代次數
        i  =  1                    # when the boundary is known,  set i  =  1
        while( i < phi.size-1):  
            phi_1 = np.copy(phi[i])
            phi[i] =  om*0.5*(phi[i + 1] + phi[i-1]-(h[i]*h[i])*b[i]) + (1.-om)*phi_1# Inhomogeneous grid
            i  =  i + 1
        j  =  j + 1
    return phi

def residual(f, v, h):
    r = np.zeros(f.size,  dtype  =  float)
    for i in range(1, v.size-1):
        r[i] = f[i]-2*(v[i + 1]-2.*v[i] + v[i-1])/(h[i]*h[i] + h[i-1]*h[i-1])
    return r

def fine(grid_orig, level): # h is the step of the fine grid
    h = h_level(level)#      要被處理的網格所在的level
    h2 = h_level(level-1)    #需要生成的網格所在的level
    n_fine =  (grid_orig.size-1)*2 + 1
    grid_fine  =  np.zeros(n_fine,  dtype  =  float)

    for i in range(0, grid_orig.size-1):

        i2 = int(i*2)
        grid_fine[i2] = grid_orig[i]
        grid_fine[i2 + 1] = grid_orig[i]*(h2[i2 + 1]/h[i]) + grid_orig[i + 1]*(h2[i2]/h[i])
    grid_fine[-1] = grid_orig[-1]
    return grid_fine

def MG(phi, x, b, h):
    level_total = int(math.log2(phi.size-1))-5  #at least 2**5 grids to capture small fluctuation
    print(level_total)
    h0 = h_level(1)
    vh = Relax2(b, phi, h, level_total, 1)
    rh = residual(b, vh, h0)
    eh =  np.zeros(b.size,  dtype  =  float) # 初始化

    for i in range (1, level_total):   #coarse and iterate
        print(i)
        h1  =  h_level(i + 1)
        r2h  =  coarsen2(rh) 
        e2h0  =  coarsen2(eh)
        e2h  =  Relax2(r2h, e2h0, h1, level_total, i)
        v2h  =  coarsen2(vh) + e2h
        b2h = coarsen2(b)
        r2h = residual(b2h, v2h, h1)
        rh  =  r2h
        eh  =  e2h
        vh  =  v2h
        b = b2h

    for i in range (1, level_total):  # fine and itearate
        print(i)
        leveli = level_total-i + 1
        h1 = h_level(leveli)
        h2 = h_level(leveli-1)
        r2h  =  fine(rh, leveli)
        e2h0  =  fine(eh, leveli)
        e2h  =  Relax2(r2h, e2h0, h2, level_total, leveli)
        b2h = fine(b, leveli)
        v2h  =  fine(vh, leveli) + e2h
        r2h = residual(b2h, v2h, h2)
        rh  =  r2h
        eh  =  e2h
        vh  =  v2h
        b = b2h

    return vh


n_grid = 1025  #at least 512 grids to reach enough depth
xs = 0.0
xe = math.pi
h = (xe-xs)/(n_grid-1)* np.ones(n_grid-1,  dtype  =  float)

x = np.zeros(n_grid,  dtype  =  float)
x[0] = xs
x[-1] = xe
for i in range(1, n_grid-1):
    x[i] = x[i-1] + h[i-1]

phi  =  np.ones(x.size,  dtype  =  float)*0.1
phi[0] = 0.
phi[-1] = 0.

b = -16*np.sin(4*x)
result2 = np.sin(4*x)   #precise solution
result =   MG(phi, x, b, h)


plt.figure(1)
plt.plot(x, result, label = 'numerical')
plt.plot(x, result2, label = 'real')
plt.legend()
plt.show()
plt.close()



結果如圖
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章