Hello,
Below is a MWE I created to show an issue with PETSc.SNES on a mixed formulation. The vector F_vec below is created with F_vec = dolfinx.fem.petsc.create_vector(F) and therefore receives the attribute _blocks. However this attribute is somehow lost. An error is then raised in function_fbecause dolfinx.fem.petsc.assemble_vector requires the attribute.
import dolfinx
import scifem
import ufl
from mpi4py import MPI
from petsc4py import PETSc
msh = dolfinx.mesh.create_unit_square(MPI.COMM_WORLD, 4, 4)
Vspace = dolfinx.fem.functionspace(msh, ("DG", 2))
f = dolfinx.fem.Function(Vspace)
f_test = ufl.TestFunction(Vspace)
Rspace = scifem.create_real_functionspace(msh)
r = dolfinx.fem.Function(Rspace)
r_test = ufl.TestFunction(Rspace)
form = ufl.inner(f, f_test) * ufl.dx
form_r = ufl.inner(r, r_test) * ufl.dx
J = dolfinx.fem.form(ufl.derivative(form, f))
form_block = [form, form_r]
Jff = ufl.derivative(form, f)
Jfr = ufl.derivative(form, r)
Jrf = ufl.derivative(form_r, f)
Jrr = ufl.derivative(form_r, r)
J_block = [[Jff, Jfr], [Jrf, Jrr]]
F = dolfinx.fem.form(form_block)
J = dolfinx.fem.form(J_block)
F_vec = dolfinx.fem.petsc.create_vector(F)
J_mat = dolfinx.fem.petsc.assemble_matrix(J)
def function_f(solver, x, F_vec) -> None:
"""Assemble the residual."""
print('Attribute blocks ',F_vec.getAttr('_blocks'))
dolfinx.fem.petsc.assemble_vector(F_vec, F)
F_vec.set(1.0)
return
def function_j(solver, x, J, P):
"""Assemble the Jacobian matrix."""
J.zeroEntries() # ensure it's zero
J.assemble()
J.shift(1.0) # A = A + 1 * I
return
solution = dolfinx.fem.petsc.create_vector(F)
snes = PETSc.SNES().create(msh.comm)
snes.setFunction(function_f, F_vec)
snes.setJacobian(function_j, J=J_mat, P=None)
snes.setObjective(lambda x,y : 1.0)
snes.solve(None, solution)
The output is:
Attribute blocks ((0, 192, 193), (193, 193, 193))
Attribute blocks None
Traceback (most recent call last):
File "petsc4py/PETSc/PETSc.pyx", line 348, in petsc4py.PETSc.PetscPythonErrorHandler
File "petsc4py/PETSc/PETSc.pyx", line 348, in petsc4py.PETSc.PetscPythonErrorHandler
File "petsc4py/PETSc/PETSc.pyx", line 348, in petsc4py.PETSc.PetscPythonErrorHandler
[Previous line repeated 2 more times]
File "petsc4py/PETSc/petscsnes.pxi", line 334, in petsc4py.PETSc.SNES_Function
File "/stck/fpascal/Python/Code/FENICS/PbBlocks/issue.py", line 38, in function_f
dolfinx.fem.petsc.assemble_vector(F_vec, F)
File "/opt/tools/python/3.10.8-gnu831/lib/python3.10/functools.py", line 889, in wrapper
return dispatch(args[0].__class__)(*args, **kw)
File "/opt/Softwares/FE_libraries/dolfinx/Dist/real/lib/python3.10/site-packages/dolfinx/fem/petsc.py", line 339, in _
offset0, offset1 = b.getAttr("_blocks")
TypeError: cannot unpack non-iterable NoneType object
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/stck/fpascal/Python/Code/FENICS/PbBlocks/issue.py", line 52, in <module>
snes.solve(None, solution)
File "petsc4py/PETSc/SNES.pyx", line 1724, in petsc4py.PETSc.SNES.solve
petsc4py.PETSc.Error: error code -1
[0] SNESSolve() at /opt/Softwares/petsc/src/snes/interface/snes.c:4846
[0] SNESSolve_NEWTONLS() at /opt/Softwares/petsc/src/snes/impls/ls/ls.c:235
[0] SNESLineSearchApply() at /opt/Softwares/petsc/src/snes/linesearch/interface/linesearch.c:643
[0] SNESLineSearchApply_BT() at /opt/Softwares/petsc/src/snes/linesearch/impls/bt/linesearchbt.c:333
[0] SNESComputeFunction() at /opt/Softwares/petsc/src/snes/interface/snes.c:2490
The two first lines show that the attribute is removed at some point.
PS : The ugly fix is to add this code at the beginning of function_f:
F_vec.setAttr('_blocks', solver.getFunction()[0].getAttr('_blocks'))
But maybe we don’t want to have to use this fix.