Python 3.x 非规则网格上的离散拉普拉斯算子(python)

Python 3.x 非规则网格上的离散拉普拉斯算子(python),python-3.x,numpy,scipy-spatial,laplacian,Python 3.x,Numpy,Scipy Spatial,Laplacian,我为非规则网格(使用scipy.spatial.Delaunay函数创建)编写了laplacien函数。 我没有错误,但是结果是不正确的:特征向量是正确的,但是特征值是正确的​​太高(绝对值) 将numpy导入为np 将matplotlib.pyplot作为plt导入 从mpl_toolkits.mplot3d导入Axes3D 导入scipy.spatial def直筒(L、H、U): VAL=[] val=0 k=1 l=1 而val>=-U: 而val>=-U: val=-np.pi**2*

我为非规则网格(使用scipy.spatial.Delaunay函数创建)编写了laplacien函数。 我没有错误,但是结果是不正确的:特征向量是正确的,但是特征值是正确的​​太高(绝对值)

将numpy导入为np
将matplotlib.pyplot作为plt导入
从mpl_toolkits.mplot3d导入Axes3D
导入scipy.spatial
def直筒(L、H、U):
VAL=[]
val=0
k=1
l=1
而val>=-U:
而val>=-U:
val=-np.pi**2*((k/L)**2+(L/H)**2)
如果val>=-U:
val.append(val)
l+=1
l=1
k+=1
val=-np.pi**2*((k/L)**2+(L/H)**2)
返回np.数组(VAL)
def计数vp(选项卡,U):
#计算n个特征值​​大于等于数组选项卡中的-U
返回选项卡[选项卡>=-U]
def in_曲线(f、fargs、形状、a):
点=[]#曲线内的点
对于范围内的j(形状[0]):
对于范围内的i(形状[1]):
如果f(i*a,j*a,*fargs)<0:
points.append([i*a,j*a])
返回np.数组(点)
def三角形(点、a、f、fargs、bord):
tri_points=points.copy()
三点[:,1]*=np.sqrt(3)
tri_points2=np.vstack((点,bord))
三点2[:,1]*=np.sqrt(3)
三点2[:,0]+=a/2
三点2[:,1]+=np.sqrt(3)/2*a
fin=np.vstack((三点,三点2))
i=0
每股收益=0.01
而我0:
fin=np.删除(fin,i,0)
i-=1
i+=1
返回np.vstack((fin,bord)),len(fin),len(bord)
def Triu_ang(点、索引、p0):
#按三角顺序对点进行排序
vec=np.arctan2((点-p0)[:,1],(点-p0)[:,0])
值=[]
数据类型=[('val',float),('n',int)]
对于范围内的i(len(vec)):
values.append((vec[i],i))
values=np.sort(np.array(value,dtype),order='val')
新的_点=[]
新索引=[]
对于tup in值:
新增点。追加(点[tup[1]])
新的索引追加(ind[tup[1]])
返回np.array(new_points),np.array(new_ind)
def M(点数、三位数、九位数):
indptr,ind=tri.vertex\u neighbor\u顶点
W=np.零((Nint,Nint))#余切矩阵
A=np.zeros((Nint,1))#曲面每个点i的顶点数组(A[i])
对于范围内的i(第九个):
tot=0
nhb_ind=ind[indptr[i]:indptr[i+1]#靠近索引k点的点的索引
nhb=点[nhb_ind]#其坐标
nhb,nhb_ind=tri_ang(nhb,nhb_ind,点[i])#i的每个相邻点的坐标(nhb)和(nhb_ind)
对于范围内的j(len(nhb_ind)):
vec=nhb[j]-点[i]#将点连接到其索引为0的邻居的向量
vec_av=nhb[j-1]-指向[i]#另一个向量,但前面有Vosin
如果j+1>=len(nhb_ind):
k=0
其他:
k=j+1
vec_ap=nhb[k]-指向[i]#另一个向量,但与下一个相邻向量
#另一个向量,但与下一个相邻
A[i]+=0.5/3*np.linalg.norm(np.cross(vec,vec_av))
如果nhb_ind[j]如果0我已经解决了我的问题:这是一个信号和一个边缘问题

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import scipy.spatial

def rect_drum(L,H,U):
    vals = []
    val = 0
    k = 1
    l = 1
    while val >= -U:
        while val >= -U:
            val = -np.pi**2*((k/L)**2+(l/H)**2)
            if val >= -U:
                vals.append(val)
            l += 1
        l = 1
        k += 1
        val = -np.pi**2*((k/L)**2+(l/H)**2)
    return np.array(vals)


def count_vp(tab,U):
    #count the n eigenvalues ​​greater than equal to -U in the array tab
    return tab[tab>=-U]

def in_curve(f,fargs,shape,a):
    points = [] # the points inside the curve
    for j in range(shape[0]):
        for i in range(shape[1]):
            if f(i*a,j*a,*fargs) < 0:
                points.append([i*a,j*a])

    return np.array(points)

def triang(points,a,f,fargs,bord):
    tri_points = points.copy()
    tri_points[:,1] *= np.sqrt(3)
    tri_points2 = np.vstack((points,bord))
    tri_points2[:,1] *= np.sqrt(3)
    tri_points2[:,0] += a/2
    tri_points2[:,1] += np.sqrt(3)/2*a
    fin = np.vstack((tri_points,tri_points2))
    i = 0
    eps = 0.01
    while i < len(fin):
        if f(fin[i,0]+eps,fin[i,1]+eps,*fargs) > 0:
            fin = np.delete(fin,i,0)
            i -= 1
        i += 1
    return np.vstack((fin,bord)),len(fin),len(bord)


def tri_ang(points,ind,p0):
    # sort the points in trigonometric order
    vec=np.arctan2((points-p0)[:,1],(points-p0)[:,0])
    values = []
    dtype = [('val',float),('n',int)]
    
    for i in range(len(vec)):
        values.append((vec[i],i))
    values = np.sort(np.array(values,dtype),order='val') 
    new_points = []
    new_ind = []
    for tup in values:
        new_points.append(points[tup[1]])
        new_ind.append(ind[tup[1]])
    return np.array(new_points),np.array(new_ind)


def Laplacian(points,tri,Nint):
    
    indptr,ind = tri.vertex_neighbor_vertices
    W = np.zeros((Nint,Nint)) # cotangents matrix
    A = np.zeros((Nint,1)) # surfacesvertex aray of point i (A[i])
    
    for i in range(Nint):
        tot = 0
        nhb_ind = ind[indptr[i]:indptr[i+1]] # indices of the points close to the point of index k
        nhb = points[nhb_ind] # their coordinates
        nhb,nhb_ind = tri_ang(nhb,nhb_ind,points[i]) #the coordinates (nhb) and  (nhb_ind) of each neighbor of i
        
        for j in range(len(nhb_ind)):
            vec = nhb[j]-points[i] # a vector connecting the point to his neighbor of index 0
            vec_av = nhb[j-1]-points[i] # another vector but with the Vosin from before
            if j+1 >= len(nhb_ind):
                k = 0
            else:
                k = j+1
            vec_ap = nhb[k]-points[i] # another vector but with the next neighbor
            
            # we use the cross product to calculate the areas of the triangles: ||AxB||/2:
            A[i] += 0.5/3*np.linalg.norm(np.cross(vec,vec_av))
            
            # we use the cross product and scalar product to calculate the cotangents: A.B/||AxB||
            cotan_alpha = np.dot(vec_av,vec_av-vec)/np.linalg.norm(np.cross(vec_av,vec_av-vec))
            cotan_beta = np.dot(vec_ap,vec_ap-vec)/np.linalg.norm(np.cross(vec_ap,vec_ap-vec))
            
            tot += cotan_alpha+cotan_beta
            
            if nhb_ind[j] < Nint:
                W[i,nhb_ind[j]] = 0.5*(cotan_alpha+cotan_beta)
        
        W[i,i] = -0.5*tot # diagonal values
    
    return (1/A)*W


def rect(x,y,L,H,x0=0,y0=0):
    if 0<x-x0<L and 0<y-y0<H:
        return -1
    else:
        return 1

def rect_rim(L,H,a,x0=0,y0=0):
    tab1 = np.arange(x0,L+x0,a)[:,np.newaxis]
    h = np.hstack((tab1,H*np.ones((len(tab1),1))+y0))
    b = np.hstack((tab1,np.zeros((len(tab1),1))+y0))
    tab2 = np.arange(y0+a,H+y0,a)[:,np.newaxis]
    g = np.hstack((np.zeros((len(tab2),1))+x0,tab2))
    d = np.hstack((L*np.ones((len(tab2),1))+x0,tab2))
    hp = np.array([[L+x0,H+y0]])
    bp = np.array([[L+x0,0]])
    return np.vstack((h,b,g,d,hp,bp))
    



# sample with a square 1*1

L = 1
H = 1

dl = 0.04
sol = in_curve(rect,[L,H],(100,100),dl)
sol_tri,Nint,Nbord = triang(sol,dl,rect,[L,H],rect_rim(L,H,dl))

# triangulation
tri = scipy.spatial.Delaunay(sol_tri)

M = Laplacian(sol_tri,tri,Nint)

valp,vecp = np.linalg.eig(M) # eigenvalues and eigenvectors
vecp = np.real(vecp)

# comparison with the exact solution:
T = 1000
U = np.arange(0,T,1)
NUsim = np.array([len(count_vp(valp,u)) for u in U])
NU = np.array([len(rect_drum(L,H,u)) for u in U])
plt.plot(U,NUsim,label='simulation')
plt.plot(U,NU,label='exacts')
plt.legend()
plt.show()


# 3D plot of an eigenvector
mode = 0 # change this for an another mode
vecp_tot = np.vstack((vecp,np.zeros((Nbord,Nint))))
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.plot_trisurf(sol_tri[:,0],sol_tri[:,1],vecp_tot[:,mode],triangles=tri.simplices)
plt.show()
将numpy导入为np
将matplotlib.pyplot作为plt导入
从mpl_toolkits.mplot3d导入Axes3D
导入scipy.spatial
def直筒(L、H、U):
VAL=[]
val=0
k=1
l=1
而val>=-U:
而val>=-U:
val=-np.pi**2*((k/L)**2+(L/H)**2)
如果val>=-U:
val.append(val)
l+=1
l=1
k+=1
val=-np.pi**2*((k/L)**2+(L/H)**2)
返回np.数组(VAL)
def计数vp(选项卡,U):
#计算n个特征值​​大于等于数组选项卡中的-U
返回选项卡[选项卡>=-U]
def in_曲线(f、fargs、形状、a):
点=[]#曲线内的点
对于范围内的j(形状[0]):
对于范围内的i(形状[1]):
如果f(i*a,j*a,*fargs)<0:
points.append([i*a,j*a])
返回np.数组(点)
def三角形(点、a、f、fargs、bord):
tri_points=points.copy()
三点[:,1]*=np.sqrt(3)
tri_points2=np.vstack((点,bord))
三点2[:,1]*=np.sqrt(3)
三点2[:,0]+=a/2
三点2[:,1]+=np.sqrt(3)/2*a
fin=np.vstack((三点,三点2))
i=0
每股收益=0.01
而我0:
fin=np.删除(fin,i,0)
i-=1
i+=1
返回np.vstack((fin,bord)),len(fin),len(bord)
def Triu_ang(点、索引、p0):
#按三角顺序对点进行排序
vec=np.arctan2((点-p0)[:,1],(点-p0)[:,0])
值=[]
数据类型=[('val',float),('n',int)]
对于范围内的i(len(vec)):
values.append((vec[i],i))
values=np.sort(np.array(value,dtype),order='val')
新的_点=[]
新索引=[]
对于tup in值:
新增点。追加(点[tup[1]])
新的索引追加(ind[tup[1]])
返回np.array(new_points),np.array(new_ind)
def拉普拉斯(点、三点、九点):
indptr,ind=tri.vertex\u neighbor\u顶点
W=np.零((Nint,Nint))#余切矩阵
A=np.zeros((Nint,1))#点i(A[i])的曲面顶点aray
对于范围内的i(第九个):
tot=0
nhb_ind=ind[indptr[i]:indptr[i+1
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import scipy.spatial

def rect_drum(L,H,U):
    vals = []
    val = 0
    k = 1
    l = 1
    while val >= -U:
        while val >= -U:
            val = -np.pi**2*((k/L)**2+(l/H)**2)
            if val >= -U:
                vals.append(val)
            l += 1
        l = 1
        k += 1
        val = -np.pi**2*((k/L)**2+(l/H)**2)
    return np.array(vals)


def count_vp(tab,U):
    #count the n eigenvalues ​​greater than equal to -U in the array tab
    return tab[tab>=-U]

def in_curve(f,fargs,shape,a):
    points = [] # the points inside the curve
    for j in range(shape[0]):
        for i in range(shape[1]):
            if f(i*a,j*a,*fargs) < 0:
                points.append([i*a,j*a])

    return np.array(points)

def triang(points,a,f,fargs,bord):
    tri_points = points.copy()
    tri_points[:,1] *= np.sqrt(3)
    tri_points2 = np.vstack((points,bord))
    tri_points2[:,1] *= np.sqrt(3)
    tri_points2[:,0] += a/2
    tri_points2[:,1] += np.sqrt(3)/2*a
    fin = np.vstack((tri_points,tri_points2))
    i = 0
    eps = 0.01
    while i < len(fin):
        if f(fin[i,0]+eps,fin[i,1]+eps,*fargs) > 0:
            fin = np.delete(fin,i,0)
            i -= 1
        i += 1
    return np.vstack((fin,bord)),len(fin),len(bord)


def tri_ang(points,ind,p0):
    # sort the points in trigonometric order
    vec=np.arctan2((points-p0)[:,1],(points-p0)[:,0])
    values = []
    dtype = [('val',float),('n',int)]
    
    for i in range(len(vec)):
        values.append((vec[i],i))
    values = np.sort(np.array(values,dtype),order='val') 
    new_points = []
    new_ind = []
    for tup in values:
        new_points.append(points[tup[1]])
        new_ind.append(ind[tup[1]])
    return np.array(new_points),np.array(new_ind)


def Laplacian(points,tri,Nint):
    
    indptr,ind = tri.vertex_neighbor_vertices
    W = np.zeros((Nint,Nint)) # cotangents matrix
    A = np.zeros((Nint,1)) # surfacesvertex aray of point i (A[i])
    
    for i in range(Nint):
        tot = 0
        nhb_ind = ind[indptr[i]:indptr[i+1]] # indices of the points close to the point of index k
        nhb = points[nhb_ind] # their coordinates
        nhb,nhb_ind = tri_ang(nhb,nhb_ind,points[i]) #the coordinates (nhb) and  (nhb_ind) of each neighbor of i
        
        for j in range(len(nhb_ind)):
            vec = nhb[j]-points[i] # a vector connecting the point to his neighbor of index 0
            vec_av = nhb[j-1]-points[i] # another vector but with the Vosin from before
            if j+1 >= len(nhb_ind):
                k = 0
            else:
                k = j+1
            vec_ap = nhb[k]-points[i] # another vector but with the next neighbor
            
            # we use the cross product to calculate the areas of the triangles: ||AxB||/2:
            A[i] += 0.5/3*np.linalg.norm(np.cross(vec,vec_av))
            
            # we use the cross product and scalar product to calculate the cotangents: A.B/||AxB||
            cotan_alpha = np.dot(vec_av,vec_av-vec)/np.linalg.norm(np.cross(vec_av,vec_av-vec))
            cotan_beta = np.dot(vec_ap,vec_ap-vec)/np.linalg.norm(np.cross(vec_ap,vec_ap-vec))
            
            tot += cotan_alpha+cotan_beta
            
            if nhb_ind[j] < Nint:
                W[i,nhb_ind[j]] = 0.5*(cotan_alpha+cotan_beta)
        
        W[i,i] = -0.5*tot # diagonal values
    
    return (1/A)*W


def rect(x,y,L,H,x0=0,y0=0):
    if 0<x-x0<L and 0<y-y0<H:
        return -1
    else:
        return 1

def rect_rim(L,H,a,x0=0,y0=0):
    tab1 = np.arange(x0,L+x0,a)[:,np.newaxis]
    h = np.hstack((tab1,H*np.ones((len(tab1),1))+y0))
    b = np.hstack((tab1,np.zeros((len(tab1),1))+y0))
    tab2 = np.arange(y0+a,H+y0,a)[:,np.newaxis]
    g = np.hstack((np.zeros((len(tab2),1))+x0,tab2))
    d = np.hstack((L*np.ones((len(tab2),1))+x0,tab2))
    hp = np.array([[L+x0,H+y0]])
    bp = np.array([[L+x0,0]])
    return np.vstack((h,b,g,d,hp,bp))
    



# sample with a square 1*1

L = 1
H = 1

dl = 0.04
sol = in_curve(rect,[L,H],(100,100),dl)
sol_tri,Nint,Nbord = triang(sol,dl,rect,[L,H],rect_rim(L,H,dl))

# triangulation
tri = scipy.spatial.Delaunay(sol_tri)

M = Laplacian(sol_tri,tri,Nint)

valp,vecp = np.linalg.eig(M) # eigenvalues and eigenvectors
vecp = np.real(vecp)

# comparison with the exact solution:
T = 1000
U = np.arange(0,T,1)
NUsim = np.array([len(count_vp(valp,u)) for u in U])
NU = np.array([len(rect_drum(L,H,u)) for u in U])
plt.plot(U,NUsim,label='simulation')
plt.plot(U,NU,label='exacts')
plt.legend()
plt.show()


# 3D plot of an eigenvector
mode = 0 # change this for an another mode
vecp_tot = np.vstack((vecp,np.zeros((Nbord,Nint))))
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.plot_trisurf(sol_tri[:,0],sol_tri[:,1],vecp_tot[:,mode],triangles=tri.simplices)
plt.show()