美文网首页
FEniCS中如何提取出刚度矩阵

FEniCS中如何提取出刚度矩阵

作者: jjx323 | 来源:发表于2019-02-20 16:43 被阅读0次

    我在https://fenicsproject.org/qa/12488/jacobian-matrix-extracted-array-sparsity-pattern-visualized/中找到了类似的解答,整理下来方便以后查阅。

    网页中所提问题是:

    Hello. In my code, I compute a Jacobian using the following command:
    J = derivative(F_sys,current_sol)
    where F_sys is the system of equations to solve and current_sol is the solution at the current time step.
    How can I:
    Extract the Jacobian matrix as a numpy array, and
    Visualize its sparsity pattern (preferably with a built-in FEniCS command if one exists)?
    Thank you for helping. Let me know if you need any additional info.

    其他人给出的回答:
    代码1,代码1给出的是一个非稀疏的矩阵

    from dolfin import *
    import matplotlib.pyplot as plt
    
    mesh = UnitSquareMesh(4, 4)
    V = FunctionSpace(mesh, 'CG', 1)
    u, v = Function(V), TestFunction(V)
    
    F = dot(grad(u), grad(v))*dx - Constant(1.0)*v*dx
    J = derivative(F, u)
    
    J_mat = assemble(J)
    J_array = J_mat.array()
    print J_array
    plt.spy(J_array)
    plt.show()
    

    代码2,代码2给出了如何输出稀疏矩阵的方法

    from dolfin import *
    import ufl
    import scipy.sparse as sp
    import matplotlib.pyplot as plt
    
    
    def spy_form_matrix(A, l=None, bcs=None, marker_size=2.0, show=True, pattern_only=True, **kwargs):
        assert isinstance(A, ufl.form.Form)
        if l: assert isinstance(l, ufl.form.Form)
        eigen_matrix = EigenMatrix()
        if not l:
            assemble(A, tensor=eigen_matrix)
            if not bcs is None:
                for bc in bcs: bc.apply(eigen_matrix)
        else:
            SystemAssembler(A, l, bcs).assemble(eigen_matrix)
        A = eigen_matrix
    
        row, col, data = A.data()
        if pattern_only:
            data[:] = 1.0
    
        sp_mat = sp.csr_matrix((data, col, row), dtype='float')
        plt.spy(sp_mat, markersize=marker_size, precision=0, **kwargs)
        if show: plt.show()
    
    
    mesh = UnitSquareMesh(4, 4)
    V = FunctionSpace(mesh, 'CG', 1)
    u, v = Function(V), TestFunction(V)
    
    F = dot(grad(u), grad(v))*dx - Constant(1.0)*v*dx
    J = derivative(F, u)
    
    spy_form_matrix(J)
    

    下面的代码可以直接从assemble后得到的矩阵变成python里的稀疏矩阵:

    fe.parameters['linear_algebra_backend'] = 'Eigen'
    def tran2SparseMatrix(A):
        row,col,val = fe.as_backend_type(A).data()
        return sps.csr_matrix((val,col,row))
    

    下面的代码给出了导出numpy矩阵后和直接用FEniCS计算的对比

    import numpy as np 
    import matplotlib.pyplot as plt 
    import fenics as fe 
    import scipy.sparse as sps
    import scipy.sparse.linalg as spsl
    import time
    
    fe.parameters['linear_algebra_backend'] = 'Eigen'
    def tran2SparseMatrix(A):
        row,col,val = fe.as_backend_type(A).data()
        return sps.csr_matrix((val,col,row))
    
    mesh = fe.UnitSquareMesh(100, 100)
    V = fe.FunctionSpace(mesh, 'P', 2)
    
    def boundary(x, on_boundary):
        return on_boundary
    
    du, v = fe.TrialFunction(V), fe.TestFunction(V)
    f = fe.Constant(1.0)
    
    af = fe.inner(fe.grad(du), fe.grad(v))*fe.dx
    bf = fe.inner(f, v)*fe.dx
    A_c = fe.assemble(af)
    b_c = fe.assemble(bf)
    bc = fe.DirichletBC(V, fe.Constant(0.0), boundary)
    bc.apply(A_c, b_c)
    
    u = fe.Function(V)
    start = time.time()
    fe.solve(A_c, u.vector(), b_c)
    end = time.time()
    print(end-start)
    
    uu1 = fe.Function(V)
    uu2 = fe.Function(V)
    start = time.time()
    A = tran2SparseMatrix(A_c)
    b = np.array([b_c[:], b_c[:]]).T
    temp = spsl.spsolve(A, b)
    end = time.time()
    print(end-start)
    uu1.vector()[:] = temp[:, 0]
    uu2.vector()[:] = temp[:, 1]
    
    en = fe.assemble(fe.inner(u-uu1, u-uu1)*fe.dx)
    print('Error is ', en)
    en = fe.assemble(fe.inner(u-uu2, u-uu2)*fe.dx)
    print('Error is ', en)
    

    相关文章

      网友评论

          本文标题:FEniCS中如何提取出刚度矩阵

          本文链接:https://www.haomeiwen.com/subject/mxbhyqtx.html