Fenics:多次求解同一个 PDE

计算科学 有限元 Python 芬尼克斯
2021-12-21 02:53:37

我是 Fenics 的新手,刚开始阅读使用Python 求解 PDE的教程。为简单起见,我们可以参考最简单的示例,第 17 页(线性泊松方程),尽管没有必要。

我的问题是:给定一个固定的 PDE,用不同的参数多次求解。(例如,改变上述例子中的常数 f)。

我的 30 秒尝试(如上面链接中的符号):

samples = 10

def solver(x, y):
   #x is the parameter to vary,
   #y the variable containing my solution
    f = Constant(x)
    L = f*v*dx
    u = Function(V)
    solve(a == L, u, bc)
   #write part of the solution in y

for i in range(samples):
    #set x, y as appropriate
    solver(x,y)

完成这项工作,但是当样本达到 100.000 左右(我需要的数量)时,它需要大量的时间和内存(通常进程结束被杀死)。我的问题是:我怎样才能加快速度?

我的想法是:由于 PDE 总是相同的,因此必须有一种方法,例如存储一次刚度矩阵,然后每次都使用它,将“求解器”简化为线性代数乘法。另一方面,我不知道如何与 fenics 正确交互。任何建议都将不胜感激。

解决方案 cpraveen给出的答案解决了这个问题。这里有一个原始但有效的代码,可能对其他读者有用。

from fenics import *
import numpy as np

## Commets omitted for simplicity: standard introduction
mesh = UnitSquareMesh(8,8)
V = FunctionSpace(mesh, 'P', 1)
u_D = Expression('1 + x[0]*x[0] + 2*x[1]*x[1]', degree=2)

def boundary(x, on_boundary):
        return on_boundary

bc = DirichletBC(V, u_D, boundary)
u = TrialFunction(V)
v = TestFunction(V)
a = dot(grad(u), grad(v))*dx

print("1")

# New suggested trick
A = assemble(a)
bc.apply(A)
solver = LUSolver(A)
#solver.parameters['reuse_factorization'] = True # <- deprecated!

print("2")

# ...and define the solver accordingly
def my_solver(x):
    f = Constant(x[0])
    b = assemble(f*v*dx)
    bc.apply(b)
    L = f*v*dx
    u = Function(V)
    solver.solve(u.vector(), b)

# Start multiple resolutions
print("Go!")
samples = 10
for i in range(10):
        my_solver([i])
        print(i)
1个回答

以下方法应该有效。

A = assemble(a)
bc.apply(A)
solver = LUSolver(A)
solver.parameters['reuse_factorization'] = True # maybe not needed

现在你可以求解任何右手边 f

b = assemble(f*v*dx)
bc.apply(b)
u = Function(V)
solver.solve(u.vector(),b)

这避免了每次求解中的装配和 LU 分解。只需进行 LU 求解。

当然,如果问题的规模足够小,LU 是可行的,这将是可行的。