finite-element-analysis - 初级有限元代码无法正确求解方程

标签 finite-element-analysis

我正在尝试编写解决极其困难的微分方程的代码: x' = 1 用有限元法。 据我了解,我可以获得解 u

enter image description here

利用基函数phi_i(x),我可以得到u_i作为线性方程组的解:

enter image description here

与微分算子D(这里只有一阶导数)。作为基础,我使用帐篷功能:

    def tent(l, r, x):
    m = (l + r) / 2 
    if x >= l and x <= m:
        return (x - l) / (m - l)
    elif x < r and x > m:
        return (r - x) / (r - m)
    else:
        return 0

def tent_half_down(l,r,x):
    if x >= l and x <= r:
        return (r - x) / (r - l)
    else:
        return 0

def tent_half_up(l,r,x):
    if x >= l and x <= r:
        return (x - l) / (r - l)
    else:
        return 0

def tent_prime(l, r, x):
    m = (l + r) / 2 
    if x >= l and x <= m:
        return 1 / (m - l)
    elif x < r and x > m:
        return 1 / (m - r)
    else:
        return 0

def tent_half_prime_down(l,r,x):
    if x >= l and x <= r:
        return - 1 / (r - l)
    else:
        return 0

def tent_half_prime_up(l, r, x):
    if x >= l and x <= r:
        return 1 / (r - l)
    else:
        return 0

def sources(x):
    return 1

离散我的空间:

n_vertex = 30
n_points = (n_vertex-1) * 40
space = (0,5)
x_space = np.linspace(space[0],space[1],n_points)
vertx_list = np.linspace(space[0],space[1], n_vertex)
tent_list = np.zeros((n_vertex, n_points))
tent_prime_list = np.zeros((n_vertex, n_points))

tent_list[0,:] = [tent_half_down(vertx_list[0],vertx_list[1],x) for x in x_space]
tent_list[-1,:] = [tent_half_up(vertx_list[-2],vertx_list[-1],x) for x in x_space]
tent_prime_list[0,:] = [tent_half_prime_down(vertx_list[0],vertx_list[1],x) for x in x_space]
tent_prime_list[-1,:] = [tent_half_prime_up(vertx_list[-2],vertx_list[-1],x) for x in x_space]
for i in range(1,n_vertex-1):
    tent_list[i, :] = [tent(vertx_list[i-1],vertx_list[i+1],x) for x in x_space]
    tent_prime_list[i, :] = [tent_prime(vertx_list[i-1],vertx_list[i+1],x) for x in x_space]

计算线性方程组:

b = np.zeros((n_vertex))
A = np.zeros((n_vertex,n_vertex))
for i in range(n_vertex):
    b[i] = np.trapz(tent_list[i,:]*sources(x_space))
    for j in range(n_vertex):
        A[j, i] = np.trapz(tent_prime_list[j] * tent_list[i])

然后求解并重构它

u = np.linalg.solve(A,b)
sol = tent_list.T.dot(u)

但这不起作用,我只得到一些上下模式。我究竟做错了什么?

最佳答案

首先,对术语和符号的一些评论:

1) 您正在使用弱公式,尽管您已经隐式地这样做了。一个“弱”的公式与所涉及的导数的顺序无关。它很弱,因为您没有在每个位置都完全满足微分方程。有限元最小化解的加权残差,在域上积分。函数 phi_j 实际上离散了加权函数。当您只有一阶导数时,不同之处在于您不必应用高斯散度定理(该定理简化为一维的分部积分)来消除二阶导数。您可以看出这没有完成,因为 phi_j 在 LHS 中没有区分。

2) 我建议不要使用“A”作为微分运算符。您还将此符号用于全局系统矩阵,因此您的表示法不一致。人们经常使用“D”,因为这更适合用于区分的想法。

其次,关于您的实现:

3) 您使用的集成点数量超出了必要的数量。您的元素使用线性插值函数,这意味着您只需要位于元素中心的一个积分点即可准确计算积分。查看高斯求积的详细信息以了解原因。此外,您还指定了集成点的数量作为节点数量的倍数。这应该以元素数量的倍数来完成(在您的例子中为 n_vertex-1),因为元素是您要集成的域。

4) 您只需从公式中删除两个端节点即可构建系统。这不是指定边界条件的正确方法。我建议首先构建完整的系统,并使用应用狄利克雷边界条件的典型方法之一。另外,请考虑约束两个节点对于您要求解的微分方程意味着什么。存在什么函数满足 x' = 1、x(0) = 0、x(5) = 0?您尝试将 2 个边界条件应用于一阶微分方程,从而对系统产生了过度约束。

不幸的是,无法进行任何小调整来使代码正常工作,但我希望上面的评论可以帮助您重新考虑您的方法。

编辑以解决您的更改:

1) 假设矩阵 A 用 A[row,col] 寻址,那么你的索引是向后的。您应该与 A[i,j] = ... 集成

2) 应用约束的一种简单方法是将一行替换为所需的约束。例如,如果您希望 x(0) = 0,则为所有 j 设置 A[0,j] = 0,然后设置 A[0,0] = 1 并设置 b[0] = 0。这将替换其中之一u_0 = 0 的方程。积分后执行此操作。

关于finite-element-analysis - 初级有限元代码无法正确求解方程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49132684/

相关文章:

python - 尝试将 matplotlib 与 ABAQUS 结合使用。收到涉及 dateutil 的错误

python - 即时编写多列列表

python - 关于 Gmsh Python API 的问题

multithreading - 线性系统求解器在 Julia 中是否也像在 Matlab 中一样是多线程的?以及如何在 Julia 中对其进行 "multithread"处理?

matlab - 我的六面体单元刚度矩阵计算有什么问题?我正在使用有限元方法。 Matlab 中的 MWE

optimization - CAD 中的自动化设计、FEA 中的分析和优化

python - 寻找更好的算法或数据结构来改进从 ID 到索引的连接转换

python - 自适应网格细化 - Python

python - 给定一个点和大量的四面体,如何高效判断该点在哪个四面体中