I am trying to solve the same PDE repeatedly, with slightly different parameters. This results in the problem $Ax = B$ where $A = C + dD_i$ which I solve for plenty of different parameters $d$ and their corresponding matrix $D_i$.
The nonzero pattern of these $D_i$ is the same, however, and I wanted to use this to my advantage. The nonzero pattern of C and the D's are different. I tried:
# C and all D's have been assembled at this point and are matrices
# initialize the nonzero pattern of A as the combination of C and D
D1 = Ds[0]
A = C.copy()
A.axpy(1.0, D1, False) # `False` here refers to same_nonzero_pattern
for d, D in zip(ds, Ds):
A.zero()
A.axpy(1.0, C, True)
A.axpy(d, D, True)
solve(A, solution.vector(), B)
At this point I get the error
*** -------------------------------------------------------------------------
*** Error: Unable to successfully call PETSc function 'KSPSolve'.
*** Reason: PETSc error code is: 72.
*** Where: This error was encountered inside <path>/dolfin-1.4.0/dolfin/la/PETScLUSolver.cpp.
*** Process: unknown
***
*** DOLFIN version: 1.4.0
*** Git changeset:
*** -------------------------------------------------------------------------
EDIT
Here is a small example. Did I misunderstand something, because I would expect A and C to be the same at the end.
from dolfin import *
# setup
mesh = UnitSquareMesh(1, 1)
V = FunctionSpace(mesh, "Lagrange", 1)
class LeftBoundary(SubDomain):
def inside(self, x, on_boundary):
return near(x[0], 0.0)
lbnd = LeftBoundary()
class RightBoundary(SubDomain):
def inside(self, x, on_boundary):
return near(x[0], 1.0)
rbnd = RightBoundary()
boundaries = FacetFunction('size_t', mesh)
boundaries.set_all(0)
lbnd.mark(boundaries, 1)
rbnd.mark(boundaries, 2)
ds = Measure('ds')[boundaries]
u = TrialFunction(V)
v = TestFunction(V)
# the interesting part
c = u * v * ds(1)
d = u * v * ds(2)
# dolfin API
C = assemble(c)
D = assemble(d)
A = assemble(c + d)
A.zero()
A.axpy(1.0, C, True) # wrong
print A.array(), '\n'
# petsc4py API
Cp = as_backend_type(C).mat()
Dp = as_backend_type(D).mat()
Ap = as_backend_type(A).mat()
Ap.zeroEntries()
# Ap.axpy(1.0, Cp, structure=0) # correct
Ap.axpy(1.0, Cp, structure=1) # also correct but faster
# Ap.axpy(1.0, Cp, structure=2) # wrong, same as `A` above
print PETScMatrix(Ap).array(), '\n'
print C.array()
From PETSc documentation ( http://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/Mat/MatAXPY.html ) the structure can be
either SAME_NONZERO_PATTERN, DIFFERENT_NONZERO_PATTERN or
SUBSET_NONZERO_PATTERN (nonzeros of X is a subset of Y's)
I believe that this corresponds to the structure=
keyword argument of the petsc4py wrapping, but I haven't found which corresponds to which, neither why one doesn't work.