[英]Matrix vector multiplication where the vector has been interpolated - Python
我已经使用有限元方法来近似拉普拉斯方程 因此把它变成了一个矩阵系统AU = F,其中A是刚度向量并求解为U(对我的问题来说并不重要)。
我现在得到了我的逼近U,当我发现AU时我应该得到向量F(或至少类似),其中F是:
AU给出了x = 0到x = 1的以下图(例如,对于20个节点):
然后我需要将U插值为更长的向量并找到AU(对于更大的A也是如此,但不是插值)。 我通过以下内容插入U:
U_inter = interp1d(x,U)
U_rich = U_inter(longer_x)
这似乎工作正常,直到我将它与较长的A矩阵相乘:
似乎每个尖峰都在x的节点(即原始U的节点)。 有人知道是什么原因引起的吗? 以下是我找到A,U和F的代码。
import numpy as np
import math
import scipy
from scipy.sparse import diags
import scipy.sparse.linalg
from scipy.interpolate import interp1d
import matplotlib
import matplotlib.pyplot as plt
def Poisson_Stiffness(x0):
"""Finds the Poisson equation stiffness matrix with any non uniform mesh x0"""
x0 = np.array(x0)
N = len(x0) - 1 # The amount of elements; x0, x1, ..., xN
h = x0[1:] - x0[:-1]
a = np.zeros(N+1)
a[0] = 1 #BOUNDARY CONDITIONS
a[1:-1] = 1/h[1:] + 1/h[:-1]
a[-1] = 1/h[-1]
a[N] = 1 #BOUNDARY CONDITIONS
b = -1/h
b[0] = 0 #BOUNDARY CONDITIONS
c = -1/h
c[N-1] = 0 #BOUNDARY CONDITIONS: DIRICHLET
data = [a.tolist(), b.tolist(), c.tolist()]
Positions = [0, 1, -1]
Stiffness_Matrix = diags(data, Positions, (N+1,N+1))
return Stiffness_Matrix
def NodalQuadrature(x0):
"""Finds the Nodal Quadrature Approximation of sin(pi x)"""
x0 = np.array(x0)
h = x0[1:] - x0[:-1]
N = len(x0) - 1
approx = np.zeros(len(x0))
approx[0] = 0 #BOUNDARY CONDITIONS
for i in range(1,N):
approx[i] = math.sin(math.pi*x0[i])
approx[i] = (approx[i]*h[i-1] + approx[i]*h[i])/2
approx[N] = 0 #BOUNDARY CONDITIONS
return approx
def Solver(x0):
Stiff_Matrix = Poisson_Stiffness(x0)
NodalApproximation = NodalQuadrature(x0)
NodalApproximation[0] = 0
U = scipy.sparse.linalg.spsolve(Stiff_Matrix, NodalApproximation)
return U
x = np.linspace(0,1,10)
rich_x = np.linspace(0,1,50)
U = Solver(x)
A_rich = Poisson_Stiffness(rich_x)
U_inter = interp1d(x,U)
U_rich = U_inter(rich_x)
AUrich = A_rich.dot(U_rich)
plt.plot(rich_x,AUrich)
plt.show()
评论1:
我添加了一个Stiffness_Matrix = Stiffness_Matrix.tocsr()
语句以避免效率警告。 有限元计算非常复杂,我必须打印出一些中间值才能确定正在发生的事情。
评论2:
plt.plot(rich_x,A_rich.dot(Solver(rich_x)))
情节很好。 你得到的噪音是由于inperpolated U_rich
和真正的解决方案之间的差异: U_rich-Solver(rich_x)
。
评论3:
我不认为你的代码有问题。 问题在于您可以通过这种方式测试插值。 我对FE理论很生疏,但我认为你需要使用形状函数进行插值,而不是简单的线性函数。
评论4:
直觉上, A_rich.dot(U_rich)
你在问,什么样的强迫F
会产生U_rich
。 与Solver(rich_x)
相比, U_rich
具有平坦的斑点,其值小于真实解决方案的区域。 F
会产生什么? 一个尖尖的, NodalQuadrature(x)
在x
点,但在两者之间接近零值。 这就是你的情节所显示的。
更高阶的插值将消除平点,并产生更平滑的反向计算F
但你真的需要重新审视有限元理论。
你可能会发现看起来很有启发性
plt.plot(x,NodalQuadrature(x))
plt.plot(rich_x, NodalQuadrature(rich_x))
第二个图更顺畅,但只有约1/5的高度。
更好的是看:
plt.plot(rich_x,AUrich,'-*') # the spikes
plt.plot(x,NodalQuadrature(x),'o') # original forcing
plt.plot(rich_x, NodalQuadrature(rich_x),'+') # new forcing
在模型中,强制不是连续的,它是每个节点的值。 随着更多节点( rich_x
),每个节点的幅度更小。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.