TransWikia.com

RBF-FD laplacian solver on python

Computational Science Asked by Alex97 on July 31, 2021

I am trying to find a laplacian of the function explicitly using the RBF-FD approach The function is sin(pi*x)*cos(pi*z/2) and its analytical solution of the Laplacian is -5/4*(pi^2)*sin(pi*x)*cos(pi*z/2)
The parameters are:

nx = 101         
nz = nx
dx = 0.01
dz = dx
x    = np.linspace(0, 1, nx)
z    = np.linspace(0, 1, nz)
d2px = np.zeros((nz, nx)) 
d2pz = np.zeros((nz, nx))
X, Z = np.meshgrid(x, z)
points = np.column_stack([X.ravel(), Z.ravel()])
stencil = 5
size = len(points)
def func(x,z):
    return np.sin(np.pi*x)*np.cos(np.pi*z/2)
f = func(points[:, 0], points[:, 1]).reshape(nx, nz)
def laplace_abs(x, z):
    return -5/4*(np.pi**2)*np.sin(np.pi*x)*np.cos(np.pi*z/2)
laplace_abs = laplace_abs(points[:, 0], points[:, 1]).reshape(nx, nz)

Then, I am trying to find RBF-FD coefficients for the 5-points-stencil like in FDM. After finding coefficients the Laplacian value should be represented as a weighted sum. The relevant formulas are represented here:
enter image description here

The main part of code is:

def get_fd_indices():
    nbrs = NearestNeighbors(n_neighbors=stencil, algorithm='ball_tree', metric='euclidean').fit(points)
    return nbrs.kneighbors(points)
distances, indices = get_fd_indices()
r = distances
RHS = np.where(distances != 0, r**2*(16*np.log(r)+8), 0)
def LHS(x, xi):
    R = np.zeros((size,stencil,stencil))
    for i in range(size):
        R[i] = distance.cdist(x[i], x[i], 'euclidean')
    LHS = np.where(R != 0, R**4*np.log(R), 0)
    return LHS
LHS = LHS(points[indices], points[indices])
def get_coef(LHS, RHS):
    c = np.zeros((size, stencil, 1))
    for i in range(size):
        Left = LHS[i]
        Right = RHS[i].reshape((stencil,1))
        c[i] = LA.pinv(Left).dot(Right)
    return c
c = get_coef(LHS, RHS)
values = f.ravel()
laplaceRBF = np.zeros(size) 
for i in range(size):
    index = indices[i]
    laplaceRBF[i] = np.sum(values[index]*c[i])
laplaceRBF = laplaceRBF.reshape(nx, nz)

I expect to obtain results similar to the FDM solution

def FDM(f, dx):
    for i in range(1, nx - 1):
        d2px[i, :] = (f[i - 1, :] - 2 * f[i, :] + f[i + 1, :]) / dx ** 2 
    for j in range(1, nz - 1):
        d2pz[:, j] = (f[:, j - 1] - 2 * f[:, j] + f[:, j + 1]) / dz ** 2 
    return d2px+d2pz
FDM = FDM(f, dx)

Right now the results of the RBF-FD are totally different from an FDM. Some error in RBF-FD realization. Please, tell me, what’s wrong.

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP