I’m trying to implement a version of the SIMPLE algorithm in FEniCS (interested in comparing to a Newton solver for steady state). One of the steps involves solving a Poisson-type system of the form C*D^{-1}*B*p = C*u
, where C
is basically a discretized divergence and B
is a gradient. D
is the diagonal of a separate A
matrix, which is derived from the linearized Navier-Stokes equations.
Obviously the standard approach to something like a Poisson problem would be to construct the bilinear operator like assemble(inner(grad(p), grad(q))*dx)
, but the problem in this case is the diagonal term. As far as I can tell there’s no way to do that in the usual variational form, since it gets pulled out of the already-assembled matrix A
.
My approach was to construct the operators separately and then do a matrix-matrix product:
from fenics import *
mesh = UnitSquareMesh(16, 16)
V = VectorFunctionSpace(mesh, 'P', 2) # Velocity vector space
Q = FunctionSpace(mesh, 'P', 1) # Pressure vector space
bc = DirichletBC(Q, Constant(0), 'near(x[0], 1)')
u, v = TrialFunction(V), TestFunction(V)
p, q = TrialFunction(Q), TestFunction(Q)
B = assemble( -inner(grad(p), v)*dx )
C = assemble( div(u)*q*dx )
L = Matrix( PETScMatrix(
as_backend_type(C).mat().matMult(
as_backend_type(B).mat() ) ) )
bc.apply(L)
From there it’s relatively straightforward to include the D^{-1}
term. The problem I’m having is in the final line, which throws an error:
*** -------------------------------------------------------------------------
*** DOLFIN encountered an error. If you are not able to resolve this issue
*** using the information listed below, you can ask for help at
***
*** fenics-support@googlegroups.com
***
*** Remember to include the error message listed below and, if possible,
*** include a *minimal* running example to reproduce the error.
***
*** -------------------------------------------------------------------------
*** Error: Unable to set given (local) rows to identity matrix.
*** Reason: some diagonal elements not preallocated (try assembler option keep_diagonal).
*** Where: This error was encountered inside PETScMatrix.cpp.
*** Process: 0
***
*** DOLFIN version: 2019.1.0
*** Git changeset: 74d7efe1e84d65e9433fd96c50f1d278fa3e3f3f
*** -------------------------------------------------------------------------
I can’t really make sense of this; assembling B
and C
with keep_diagonal
doesn’t fix it, and the diagonal is dense:
>>> min(abs(np.diag(L.array())))
0.00021701388888888739
I’ve tried using the same order of elements for pressure and velocity rather than Taylor-Hood, but that doesn’t seem to be the issue. Also tried using a mixed FunctionSpace
but that doesn’t help either. Does anyone know what’s going wrong here? Is there a problem with composing operators like this?
Also, this is a bit off-topic, but I’m also open to suggestions if SIMPLE is a bad idea. It just seemed like the Newton solver was starting to use a lot of memory in 3D, and a lot of commercial codes use SIMPLE.