3

我已经使用有限元方法来近似拉普拉斯方程$-u_{xx} = sin(\pi*x)$,因此将其转换为矩阵系统 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()
4

1 回答 1

2

评论1:

我添加了一条Stiffness_Matrix = Stiffness_Matrix.tocsr()语句以避免出现效率警告。FE 计算非常复杂,我必须先打印出一些中间值,然后才能确定发生了什么。

评论2:

plt.plot(rich_x,A_rich.dot(Solver(rich_x)))情节不错。U_rich你得到的噪音是内插和真实解决方案之间差异的结果: U_rich-Solver(rich_x).

评论3:

我认为您的代码没有问题。问题在于您可以通过这种方式测试插值。我对有限元理论很生疏,但我认为您需要使用形状函数进行插值,而不是简单的线性函数。

评论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),每个节点的幅度就越小。

于 2015-09-06T01:26:13.390 回答