PCMAT seems abstraction-breaking (and the man page even admits it is "strange" :D )
The preconditioner Mat B is thought of as an approximation (maybe a perfect one) to the operator A, to be used to construct preconditioners. PCMAT uses B as an approximation to the *inverse* of A (loosely speaking). That's confusing, and worse it ruins a central feature of PETSc, which is the ability to change the preconditioner at runtime; the meaning of B changes depending on which PC implementation you use. Proposed change: Have PCMAT (like analogous object PCKSP) store its own Mat object and introduce API functions to interact with this internal Mat. To make sure that any user code which happens to use PCMAT doesn't see an unexplained change in behavior, do not set a default internal Mat, and produce an informative error if PCApply_Mat() is called without first calling the new function PCMatSetMat(). On Mon, Nov 14, 2016 at 7:04 AM, Dave May <[email protected]> wrote: > Looks like you want the contents of your mat shell, specifically the op Ax, > to define the action of the preconditioner. > > You need to either create a PCShell (rather than a MatShell), and define the > operation called by PCApply(), or keep you current shell but change > "preonly" to "mat". > > http://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/PC/PCMAT.html#PCMAT > > Thanks > Dave > > On Mon, 14 Nov 2016 at 06:36, Safin, Artur <[email protected]> wrote: >> >> Hello, >> >> >> What is the proper way to set up a shell preconditioner within a >> fielsplit? I have tried it on my own, but do not get the proper behavior. >> The relevant portion looks like this: >> >> >> __________________________________________________________________ >> >> // Global System >> KSPSetOperators(ksp, A, A); >> >> // Skipped code.. >> >> >> >> // Shell Preconditioner for the pressure sub-block >> >> KSP *subksp; >> >> PCFieldSplitGetSubKSP(pc, NULL, &subksp); >> >> Mat pressureA; >> KSPSetType(subksp[0], "preonly"); >> MatCreateShell(MPI_COMM_WORLD, n_local_P_dofs, n_local_P_dofs, , >> PETSC_DETERMINE, PETSC_DETERMINE, &pressureA); >> MatShellSetOperation(pressureA, MATOP_MULT, (void(*)(void)) >> PressureBlock); >> KSPSetOperators(subksp[0], pressureA, pressureA); >> >> // Skipped code.. >> >> >> >> KSPSetUp(ksp); >> >> KSPSolve(ksp, b, x); >> >> __________________________________________________________________ >> >> >> The fieldsplit component works fine; the solver however does not go into >> the custom function PressureBlock(), so I am curious as to what the correct >> approach is. >> >> >> Best, >> >> >> Artur
