Using petsc4py.PETSc.SNES directly

Ok, in case someone else arrives: the problem is that SNES moves function evaluation in the ‘x’ vector, whereas the residuals depend on ‘u’, so the solution is to update things correspondingly:

    def F(self, snes, x, F):
        x = PETScVector(x)
        F  = PETScVector(F)
        x.vec().copy(self.u.vector().vec())
        self.u.vector().apply("")
        assemble(self.L, tensor=F)
        for bc in self.bcs:
            bc.apply(F, x)
            bc.apply(F, self.u.vector())



    def J(self, snes, x, J, P):
        J = PETScMatrix(J)
        x.copy(self.u.vector().vec())
        self.u.vector().apply("")
        assemble(self.a, tensor=J)
        for bc in self.bcs:
            bc.apply(J)

The ‘apply’ lines are required to update ghost dofs in parallel… you can actually remove that if your code will only be run in serial.

Best!

4 Likes