@@ -873,6 +873,11 @@ def __init__(
873873 self ._solver = PETSc .KSP ().create (self .A .comm ) # type: ignore[attr-defined]
874874 self .solver .setOperators (self .A , self .P_mat )
875875
876+ # Attach problem information
877+ dm = self .solver .getDM ()
878+ dm .setCreateFieldDecomposition (partial (create_field_decomposition , u , self .L ))
879+ self .solver .getPC ().setDM (dm )
880+
876881 if petsc_options_prefix == "" :
877882 raise ValueError ("PETSc options prefix cannot be empty." )
878883
@@ -1344,6 +1349,11 @@ def __init__(
13441349 )
13451350 self .solver .setFunction (partial (assemble_residual , u , self .F , self .J , bcs ), self .b )
13461351
1352+ # Attach problem information
1353+ dm = self .solver .getDM ()
1354+ dm .setCreateFieldDecomposition (partial (create_field_decomposition , u , self .F ))
1355+ self .solver .getKSP ().setDM (dm )
1356+
13471357 if petsc_options_prefix == "" :
13481358 raise ValueError ("PETSc options prefix cannot be empty." )
13491359
@@ -1708,3 +1718,36 @@ def _(x: PETSc.Vec, u: typing.Union[_Function, Sequence[_Function]]): # type: i
17081718 dolfinx .la .petsc .assign (x , data0 + data1 )
17091719 else :
17101720 dolfinx .la .petsc .assign (x , u .x .array )
1721+
1722+
1723+ def create_field_decomposition (
1724+ u : typing .Union [Sequence [_Function ], _Function ],
1725+ form : typing .Union [Form , Sequence [Form ]],
1726+ _dm : PETSc .DM , # type: ignore[name-defined]
1727+ ):
1728+ """Return index sets of the fields and their associated names.
1729+
1730+ Args:
1731+ u: Function tied to the solution vector.
1732+ form: Form of the residual or of the right-hand side.
1733+ It can be a sequence of forms.
1734+ _dm: The DM instance.
1735+
1736+ Returns:
1737+ names: field names
1738+ ises: list of index sets
1739+ dms: list of subDMs. This function returns `None`
1740+ """
1741+
1742+
1743+ if not isinstance (form , Sequence ):
1744+ form = [form ]
1745+ spaces = _extract_function_spaces (form )
1746+ ises = _cpp .la .petsc .create_index_sets (
1747+ [(V .dofmaps (0 ).index_map , V .dofmaps (0 ).index_map_bs ) for V in spaces ] # type: ignore[union-attr]
1748+ )
1749+ if isinstance (u , Sequence ):
1750+ names = [f"{ v .name + '_' if v .name != 'f' else '' } { i } " for i , v in enumerate (u )]
1751+ else :
1752+ names = [f"dolfinx_field_{ i } " for i in range (len (form ))]
1753+ return names , ises , None
0 commit comments