xref: /petsc/src/ksp/pc/impls/fieldsplit/fieldsplit.c (revision 4e278199b78715991f5c71ebbd945c1489263e6c)
1 #include <petsc/private/pcimpl.h>     /*I "petscpc.h" I*/
2 #include <petsc/private/kspimpl.h>    /*  This is needed to provide the appropriate PETSC_EXTERN for KSP_Solve_FS ....*/
3 #include <petscdm.h>
4 
5 const char *const PCFieldSplitSchurPreTypes[] = {"SELF","SELFP","A11","USER","FULL","PCFieldSplitSchurPreType","PC_FIELDSPLIT_SCHUR_PRE_",NULL};
6 const char *const PCFieldSplitSchurFactTypes[] = {"DIAG","LOWER","UPPER","FULL","PCFieldSplitSchurFactType","PC_FIELDSPLIT_SCHUR_FACT_",NULL};
7 
8 PetscLogEvent KSP_Solve_FS_0,KSP_Solve_FS_1,KSP_Solve_FS_S,KSP_Solve_FS_U,KSP_Solve_FS_L,KSP_Solve_FS_2,KSP_Solve_FS_3,KSP_Solve_FS_4;
9 
10 typedef struct _PC_FieldSplitLink *PC_FieldSplitLink;
11 struct _PC_FieldSplitLink {
12   KSP               ksp;
13   Vec               x,y,z;
14   char              *splitname;
15   PetscInt          nfields;
16   PetscInt          *fields,*fields_col;
17   VecScatter        sctx;
18   IS                is,is_col;
19   PC_FieldSplitLink next,previous;
20   PetscLogEvent     event;
21 };
22 
23 typedef struct {
24   PCCompositeType type;
25   PetscBool       defaultsplit;                    /* Flag for a system with a set of 'k' scalar fields with the same layout (and bs = k) */
26   PetscBool       splitdefined;                    /* Flag is set after the splits have been defined, to prevent more splits from being added */
27   PetscInt        bs;                              /* Block size for IS and Mat structures */
28   PetscInt        nsplits;                         /* Number of field divisions defined */
29   Vec             *x,*y,w1,w2;
30   Mat             *mat;                            /* The diagonal block for each split */
31   Mat             *pmat;                           /* The preconditioning diagonal block for each split */
32   Mat             *Afield;                         /* The rows of the matrix associated with each split */
33   PetscBool       issetup;
34 
35   /* Only used when Schur complement preconditioning is used */
36   Mat                       B;                     /* The (0,1) block */
37   Mat                       C;                     /* The (1,0) block */
38   Mat                       schur;                 /* The Schur complement S = A11 - A10 A00^{-1} A01, the KSP here, kspinner, is H_1 in [El08] */
39   Mat                       schurp;                /* Assembled approximation to S built by MatSchurComplement to be used as a preconditioning matrix when solving with S */
40   Mat                       schur_user;            /* User-provided preconditioning matrix for the Schur complement */
41   PCFieldSplitSchurPreType  schurpre;              /* Determines which preconditioning matrix is used for the Schur complement */
42   PCFieldSplitSchurFactType schurfactorization;
43   KSP                       kspschur;              /* The solver for S */
44   KSP                       kspupper;              /* The solver for A in the upper diagonal part of the factorization (H_2 in [El08]) */
45   PetscScalar               schurscale;            /* Scaling factor for the Schur complement solution with DIAG factorization */
46 
47   /* Only used when Golub-Kahan bidiagonalization preconditioning is used */
48   Mat                       H;                     /* The modified matrix H = A00 + nu*A01*A01'              */
49   PetscReal                 gkbtol;                /* Stopping tolerance for lower bound estimate            */
50   PetscInt                  gkbdelay;              /* The delay window for the stopping criterion            */
51   PetscReal                 gkbnu;                 /* Parameter for augmented Lagrangian H = A + nu*A01*A01' */
52   PetscInt                  gkbmaxit;              /* Maximum number of iterations for outer loop            */
53   PetscBool                 gkbmonitor;            /* Monitor for gkb iterations and the lower bound error   */
54   PetscViewer               gkbviewer;             /* Viewer context for gkbmonitor                          */
55   Vec                       u,v,d,Hu;              /* Work vectors for the GKB algorithm                     */
56   PetscScalar               *vecz;                 /* Contains intermediate values, eg for lower bound       */
57 
58   PC_FieldSplitLink         head;
59   PetscBool                 isrestrict;             /* indicates PCFieldSplitRestrictIS() has been last called on this object, hack */
60   PetscBool                 suboptionsset;          /* Indicates that the KSPSetFromOptions() has been called on the sub-KSPs */
61   PetscBool                 dm_splits;              /* Whether to use DMCreateFieldDecomposition() whenever possible */
62   PetscBool                 diag_use_amat;          /* Whether to extract diagonal matrix blocks from Amat, rather than Pmat (weaker than -pc_use_amat) */
63   PetscBool                 offdiag_use_amat;       /* Whether to extract off-diagonal matrix blocks from Amat, rather than Pmat (weaker than -pc_use_amat) */
64   PetscBool                 detect;                 /* Whether to form 2-way split by finding zero diagonal entries */
65 } PC_FieldSplit;
66 
67 /*
68     Notes:
69     there is no particular reason that pmat, x, and y are stored as arrays in PC_FieldSplit instead of
70    inside PC_FieldSplitLink, just historical. If you want to be able to add new fields after already using the
71    PC you could change this.
72 */
73 
74 /* This helper is so that setting a user-provided preconditioning matrix is orthogonal to choosing to use it.  This way the
75 * application-provided FormJacobian can provide this matrix without interfering with the user's (command-line) choices. */
76 static Mat FieldSplitSchurPre(PC_FieldSplit *jac)
77 {
78   switch (jac->schurpre) {
79   case PC_FIELDSPLIT_SCHUR_PRE_SELF: return jac->schur;
80   case PC_FIELDSPLIT_SCHUR_PRE_SELFP: return jac->schurp;
81   case PC_FIELDSPLIT_SCHUR_PRE_A11: return jac->pmat[1];
82   case PC_FIELDSPLIT_SCHUR_PRE_FULL: /* We calculate this and store it in schur_user */
83   case PC_FIELDSPLIT_SCHUR_PRE_USER: /* Use a user-provided matrix if it is given, otherwise diagonal block */
84   default:
85     return jac->schur_user ? jac->schur_user : jac->pmat[1];
86   }
87 }
88 
89 #include <petscdraw.h>
90 static PetscErrorCode PCView_FieldSplit(PC pc,PetscViewer viewer)
91 {
92   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
93   PetscErrorCode    ierr;
94   PetscBool         iascii,isdraw;
95   PetscInt          i,j;
96   PC_FieldSplitLink ilink = jac->head;
97 
98   PetscFunctionBegin;
99   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
100   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
101   if (iascii) {
102     if (jac->bs > 0) {
103       ierr = PetscViewerASCIIPrintf(viewer,"  FieldSplit with %s composition: total splits = %D, blocksize = %D\n",PCCompositeTypes[jac->type],jac->nsplits,jac->bs);CHKERRQ(ierr);
104     } else {
105       ierr = PetscViewerASCIIPrintf(viewer,"  FieldSplit with %s composition: total splits = %D\n",PCCompositeTypes[jac->type],jac->nsplits);CHKERRQ(ierr);
106     }
107     if (pc->useAmat) {
108       ierr = PetscViewerASCIIPrintf(viewer,"  using Amat (not Pmat) as operator for blocks\n");CHKERRQ(ierr);
109     }
110     if (jac->diag_use_amat) {
111       ierr = PetscViewerASCIIPrintf(viewer,"  using Amat (not Pmat) as operator for diagonal blocks\n");CHKERRQ(ierr);
112     }
113     if (jac->offdiag_use_amat) {
114       ierr = PetscViewerASCIIPrintf(viewer,"  using Amat (not Pmat) as operator for off-diagonal blocks\n");CHKERRQ(ierr);
115     }
116     ierr = PetscViewerASCIIPrintf(viewer,"  Solver info for each split is in the following KSP objects:\n");CHKERRQ(ierr);
117     for (i=0; i<jac->nsplits; i++) {
118       if (ilink->fields) {
119         ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Fields ",i);CHKERRQ(ierr);
120         ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
121         for (j=0; j<ilink->nfields; j++) {
122           if (j > 0) {
123             ierr = PetscViewerASCIIPrintf(viewer,",");CHKERRQ(ierr);
124           }
125           ierr = PetscViewerASCIIPrintf(viewer," %D",ilink->fields[j]);CHKERRQ(ierr);
126         }
127         ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
128         ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
129       } else {
130         ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Defined by IS\n",i);CHKERRQ(ierr);
131       }
132       ierr  = KSPView(ilink->ksp,viewer);CHKERRQ(ierr);
133       ilink = ilink->next;
134     }
135   }
136 
137  if (isdraw) {
138     PetscDraw draw;
139     PetscReal x,y,w,wd;
140 
141     ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
142     ierr = PetscDrawGetCurrentPoint(draw,&x,&y);CHKERRQ(ierr);
143     w    = 2*PetscMin(1.0 - x,x);
144     wd   = w/(jac->nsplits + 1);
145     x    = x - wd*(jac->nsplits-1)/2.0;
146     for (i=0; i<jac->nsplits; i++) {
147       ierr  = PetscDrawPushCurrentPoint(draw,x,y);CHKERRQ(ierr);
148       ierr  = KSPView(ilink->ksp,viewer);CHKERRQ(ierr);
149       ierr  = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr);
150       x    += wd;
151       ilink = ilink->next;
152     }
153   }
154   PetscFunctionReturn(0);
155 }
156 
157 static PetscErrorCode PCView_FieldSplit_Schur(PC pc,PetscViewer viewer)
158 {
159   PC_FieldSplit              *jac = (PC_FieldSplit*)pc->data;
160   PetscErrorCode             ierr;
161   PetscBool                  iascii,isdraw;
162   PetscInt                   i,j;
163   PC_FieldSplitLink          ilink = jac->head;
164   MatSchurComplementAinvType atype;
165 
166   PetscFunctionBegin;
167   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
168   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
169   if (iascii) {
170     if (jac->bs > 0) {
171       ierr = PetscViewerASCIIPrintf(viewer,"  FieldSplit with Schur preconditioner, blocksize = %D, factorization %s\n",jac->bs,PCFieldSplitSchurFactTypes[jac->schurfactorization]);CHKERRQ(ierr);
172     } else {
173       ierr = PetscViewerASCIIPrintf(viewer,"  FieldSplit with Schur preconditioner, factorization %s\n",PCFieldSplitSchurFactTypes[jac->schurfactorization]);CHKERRQ(ierr);
174     }
175     if (pc->useAmat) {
176       ierr = PetscViewerASCIIPrintf(viewer,"  using Amat (not Pmat) as operator for blocks\n");CHKERRQ(ierr);
177     }
178     switch (jac->schurpre) {
179     case PC_FIELDSPLIT_SCHUR_PRE_SELF:
180       ierr = PetscViewerASCIIPrintf(viewer,"  Preconditioner for the Schur complement formed from S itself\n");CHKERRQ(ierr);
181       break;
182     case PC_FIELDSPLIT_SCHUR_PRE_SELFP:
183       ierr = MatSchurComplementGetAinvType(jac->schur,&atype);CHKERRQ(ierr);
184       ierr = PetscViewerASCIIPrintf(viewer,"  Preconditioner for the Schur complement formed from Sp, an assembled approximation to S, which uses A00's %sdiagonal's inverse\n",atype == MAT_SCHUR_COMPLEMENT_AINV_DIAG ? "" : (atype == MAT_SCHUR_COMPLEMENT_AINV_BLOCK_DIAG ? "block " : "lumped "));CHKERRQ(ierr);break;
185     case PC_FIELDSPLIT_SCHUR_PRE_A11:
186       ierr = PetscViewerASCIIPrintf(viewer,"  Preconditioner for the Schur complement formed from A11\n");CHKERRQ(ierr);
187       break;
188     case PC_FIELDSPLIT_SCHUR_PRE_FULL:
189       ierr = PetscViewerASCIIPrintf(viewer,"  Preconditioner for the Schur complement formed from the exact Schur complement\n");CHKERRQ(ierr);
190       break;
191     case PC_FIELDSPLIT_SCHUR_PRE_USER:
192       if (jac->schur_user) {
193         ierr = PetscViewerASCIIPrintf(viewer,"  Preconditioner for the Schur complement formed from user provided matrix\n");CHKERRQ(ierr);
194       } else {
195         ierr = PetscViewerASCIIPrintf(viewer,"  Preconditioner for the Schur complement formed from A11\n");CHKERRQ(ierr);
196       }
197       break;
198     default:
199       SETERRQ1(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Invalid Schur preconditioning type: %d", jac->schurpre);
200     }
201     ierr = PetscViewerASCIIPrintf(viewer,"  Split info:\n");CHKERRQ(ierr);
202     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
203     for (i=0; i<jac->nsplits; i++) {
204       if (ilink->fields) {
205         ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Fields ",i);CHKERRQ(ierr);
206         ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
207         for (j=0; j<ilink->nfields; j++) {
208           if (j > 0) {
209             ierr = PetscViewerASCIIPrintf(viewer,",");CHKERRQ(ierr);
210           }
211           ierr = PetscViewerASCIIPrintf(viewer," %D",ilink->fields[j]);CHKERRQ(ierr);
212         }
213         ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
214         ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
215       } else {
216         ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Defined by IS\n",i);CHKERRQ(ierr);
217       }
218       ilink = ilink->next;
219     }
220     ierr = PetscViewerASCIIPrintf(viewer,"KSP solver for A00 block\n");CHKERRQ(ierr);
221     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
222     if (jac->head) {
223       ierr = KSPView(jac->head->ksp,viewer);CHKERRQ(ierr);
224     } else  {ierr = PetscViewerASCIIPrintf(viewer,"  not yet available\n");CHKERRQ(ierr);}
225     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
226     if (jac->head && jac->kspupper != jac->head->ksp) {
227       ierr = PetscViewerASCIIPrintf(viewer,"KSP solver for upper A00 in upper triangular factor \n");CHKERRQ(ierr);
228       ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
229       if (jac->kspupper) {ierr = KSPView(jac->kspupper,viewer);CHKERRQ(ierr);}
230       else {ierr = PetscViewerASCIIPrintf(viewer,"  not yet available\n");CHKERRQ(ierr);}
231       ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
232     }
233     ierr = PetscViewerASCIIPrintf(viewer,"KSP solver for S = A11 - A10 inv(A00) A01 \n");CHKERRQ(ierr);
234     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
235     if (jac->kspschur) {
236       ierr = KSPView(jac->kspschur,viewer);CHKERRQ(ierr);
237     } else {
238       ierr = PetscViewerASCIIPrintf(viewer,"  not yet available\n");CHKERRQ(ierr);
239     }
240     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
241     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
242   } else if (isdraw && jac->head) {
243     PetscDraw draw;
244     PetscReal x,y,w,wd,h;
245     PetscInt  cnt = 2;
246     char      str[32];
247 
248     ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
249     ierr = PetscDrawGetCurrentPoint(draw,&x,&y);CHKERRQ(ierr);
250     if (jac->kspupper != jac->head->ksp) cnt++;
251     w  = 2*PetscMin(1.0 - x,x);
252     wd = w/(cnt + 1);
253 
254     ierr = PetscSNPrintf(str,32,"Schur fact. %s",PCFieldSplitSchurFactTypes[jac->schurfactorization]);CHKERRQ(ierr);
255     ierr = PetscDrawStringBoxed(draw,x,y,PETSC_DRAW_RED,PETSC_DRAW_BLACK,str,NULL,&h);CHKERRQ(ierr);
256     y   -= h;
257     if (jac->schurpre == PC_FIELDSPLIT_SCHUR_PRE_USER &&  !jac->schur_user) {
258       ierr = PetscSNPrintf(str,32,"Prec. for Schur from %s",PCFieldSplitSchurPreTypes[PC_FIELDSPLIT_SCHUR_PRE_A11]);CHKERRQ(ierr);
259     } else {
260       ierr = PetscSNPrintf(str,32,"Prec. for Schur from %s",PCFieldSplitSchurPreTypes[jac->schurpre]);CHKERRQ(ierr);
261     }
262     ierr = PetscDrawStringBoxed(draw,x+wd*(cnt-1)/2.0,y,PETSC_DRAW_RED,PETSC_DRAW_BLACK,str,NULL,&h);CHKERRQ(ierr);
263     y   -= h;
264     x    = x - wd*(cnt-1)/2.0;
265 
266     ierr = PetscDrawPushCurrentPoint(draw,x,y);CHKERRQ(ierr);
267     ierr = KSPView(jac->head->ksp,viewer);CHKERRQ(ierr);
268     ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr);
269     if (jac->kspupper != jac->head->ksp) {
270       x   += wd;
271       ierr = PetscDrawPushCurrentPoint(draw,x,y);CHKERRQ(ierr);
272       ierr = KSPView(jac->kspupper,viewer);CHKERRQ(ierr);
273       ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr);
274     }
275     x   += wd;
276     ierr = PetscDrawPushCurrentPoint(draw,x,y);CHKERRQ(ierr);
277     ierr = KSPView(jac->kspschur,viewer);CHKERRQ(ierr);
278     ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr);
279   }
280   PetscFunctionReturn(0);
281 }
282 
283 static PetscErrorCode PCView_FieldSplit_GKB(PC pc,PetscViewer viewer)
284 {
285   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
286   PetscErrorCode    ierr;
287   PetscBool         iascii,isdraw;
288   PetscInt          i,j;
289   PC_FieldSplitLink ilink = jac->head;
290 
291   PetscFunctionBegin;
292   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
293   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
294   if (iascii) {
295     if (jac->bs > 0) {
296       ierr = PetscViewerASCIIPrintf(viewer,"  FieldSplit with %s composition: total splits = %D, blocksize = %D\n",PCCompositeTypes[jac->type],jac->nsplits,jac->bs);CHKERRQ(ierr);
297     } else {
298       ierr = PetscViewerASCIIPrintf(viewer,"  FieldSplit with %s composition: total splits = %D\n",PCCompositeTypes[jac->type],jac->nsplits);CHKERRQ(ierr);
299     }
300     if (pc->useAmat) {
301       ierr = PetscViewerASCIIPrintf(viewer,"  using Amat (not Pmat) as operator for blocks\n");CHKERRQ(ierr);
302     }
303     if (jac->diag_use_amat) {
304       ierr = PetscViewerASCIIPrintf(viewer,"  using Amat (not Pmat) as operator for diagonal blocks\n");CHKERRQ(ierr);
305     }
306     if (jac->offdiag_use_amat) {
307       ierr = PetscViewerASCIIPrintf(viewer,"  using Amat (not Pmat) as operator for off-diagonal blocks\n");CHKERRQ(ierr);
308     }
309 
310     ierr = PetscViewerASCIIPrintf(viewer,"  Stopping tolerance=%.1e, delay in error estimate=%D, maximum iterations=%D\n",jac->gkbtol,jac->gkbdelay,jac->gkbmaxit);CHKERRQ(ierr);
311     ierr = PetscViewerASCIIPrintf(viewer,"  Solver info for H = A00 + nu*A01*A01' matrix:\n");CHKERRQ(ierr);
312     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
313 
314     if (ilink->fields) {
315       ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Fields ",0);CHKERRQ(ierr);
316       ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
317       for (j=0; j<ilink->nfields; j++) {
318         if (j > 0) {
319           ierr = PetscViewerASCIIPrintf(viewer,",");CHKERRQ(ierr);
320         }
321         ierr = PetscViewerASCIIPrintf(viewer," %D",ilink->fields[j]);CHKERRQ(ierr);
322       }
323       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
324       ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
325     } else {
326         ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Defined by IS\n",0);CHKERRQ(ierr);
327     }
328     ierr  = KSPView(ilink->ksp,viewer);CHKERRQ(ierr);
329 
330     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
331   }
332 
333  if (isdraw) {
334     PetscDraw draw;
335     PetscReal x,y,w,wd;
336 
337     ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
338     ierr = PetscDrawGetCurrentPoint(draw,&x,&y);CHKERRQ(ierr);
339     w    = 2*PetscMin(1.0 - x,x);
340     wd   = w/(jac->nsplits + 1);
341     x    = x - wd*(jac->nsplits-1)/2.0;
342     for (i=0; i<jac->nsplits; i++) {
343       ierr  = PetscDrawPushCurrentPoint(draw,x,y);CHKERRQ(ierr);
344       ierr  = KSPView(ilink->ksp,viewer);CHKERRQ(ierr);
345       ierr  = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr);
346       x    += wd;
347       ilink = ilink->next;
348     }
349   }
350   PetscFunctionReturn(0);
351 }
352 
353 /* Precondition: jac->bs is set to a meaningful value */
354 static PetscErrorCode PCFieldSplitSetRuntimeSplits_Private(PC pc)
355 {
356   PetscErrorCode ierr;
357   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
358   PetscInt       i,nfields,*ifields,nfields_col,*ifields_col;
359   PetscBool      flg,flg_col;
360   char           optionname[128],splitname[8],optionname_col[128];
361 
362   PetscFunctionBegin;
363   ierr = PetscMalloc1(jac->bs,&ifields);CHKERRQ(ierr);
364   ierr = PetscMalloc1(jac->bs,&ifields_col);CHKERRQ(ierr);
365   for (i=0,flg=PETSC_TRUE;; i++) {
366     ierr        = PetscSNPrintf(splitname,sizeof(splitname),"%D",i);CHKERRQ(ierr);
367     ierr        = PetscSNPrintf(optionname,sizeof(optionname),"-pc_fieldsplit_%D_fields",i);CHKERRQ(ierr);
368     ierr        = PetscSNPrintf(optionname_col,sizeof(optionname_col),"-pc_fieldsplit_%D_fields_col",i);CHKERRQ(ierr);
369     nfields     = jac->bs;
370     nfields_col = jac->bs;
371     ierr        = PetscOptionsGetIntArray(((PetscObject)pc)->options,((PetscObject)pc)->prefix,optionname,ifields,&nfields,&flg);CHKERRQ(ierr);
372     ierr        = PetscOptionsGetIntArray(((PetscObject)pc)->options,((PetscObject)pc)->prefix,optionname_col,ifields_col,&nfields_col,&flg_col);CHKERRQ(ierr);
373     if (!flg) break;
374     else if (flg && !flg_col) {
375       if (!nfields) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot list zero fields");
376       ierr = PCFieldSplitSetFields(pc,splitname,nfields,ifields,ifields);CHKERRQ(ierr);
377     } else {
378       if (!nfields || !nfields_col) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot list zero fields");
379       if (nfields != nfields_col) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Number of row and column fields must match");
380       ierr = PCFieldSplitSetFields(pc,splitname,nfields,ifields,ifields_col);CHKERRQ(ierr);
381     }
382   }
383   if (i > 0) {
384     /* Makes command-line setting of splits take precedence over setting them in code.
385        Otherwise subsequent calls to PCFieldSplitSetIS() or PCFieldSplitSetFields() would
386        create new splits, which would probably not be what the user wanted. */
387     jac->splitdefined = PETSC_TRUE;
388   }
389   ierr = PetscFree(ifields);CHKERRQ(ierr);
390   ierr = PetscFree(ifields_col);CHKERRQ(ierr);
391   PetscFunctionReturn(0);
392 }
393 
394 static PetscErrorCode PCFieldSplitSetDefaults(PC pc)
395 {
396   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
397   PetscErrorCode    ierr;
398   PC_FieldSplitLink ilink = jac->head;
399   PetscBool         fieldsplit_default = PETSC_FALSE,coupling = PETSC_FALSE;
400   PetscInt          i;
401 
402   PetscFunctionBegin;
403   /*
404    Kinda messy, but at least this now uses DMCreateFieldDecomposition().
405    Should probably be rewritten.
406    */
407   if (!ilink) {
408     ierr = PetscOptionsGetBool(((PetscObject)pc)->options,((PetscObject)pc)->prefix,"-pc_fieldsplit_detect_coupling",&coupling,NULL);CHKERRQ(ierr);
409     if (pc->dm && jac->dm_splits && !jac->detect && !coupling) {
410       PetscInt  numFields, f, i, j;
411       char      **fieldNames;
412       IS        *fields;
413       DM        *dms;
414       DM        subdm[128];
415       PetscBool flg;
416 
417       ierr = DMCreateFieldDecomposition(pc->dm, &numFields, &fieldNames, &fields, &dms);CHKERRQ(ierr);
418       /* Allow the user to prescribe the splits */
419       for (i = 0, flg = PETSC_TRUE;; i++) {
420         PetscInt ifields[128];
421         IS       compField;
422         char     optionname[128], splitname[8];
423         PetscInt nfields = numFields;
424 
425         ierr = PetscSNPrintf(optionname, sizeof(optionname), "-pc_fieldsplit_%D_fields", i);CHKERRQ(ierr);
426         ierr = PetscOptionsGetIntArray(((PetscObject)pc)->options,((PetscObject)pc)->prefix, optionname, ifields, &nfields, &flg);CHKERRQ(ierr);
427         if (!flg) break;
428         if (numFields > 128) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot currently support %d > 128 fields", numFields);
429         ierr = DMCreateSubDM(pc->dm, nfields, ifields, &compField, &subdm[i]);CHKERRQ(ierr);
430         if (nfields == 1) {
431           ierr = PCFieldSplitSetIS(pc, fieldNames[ifields[0]], compField);CHKERRQ(ierr);
432         } else {
433           ierr = PetscSNPrintf(splitname, sizeof(splitname), "%D", i);CHKERRQ(ierr);
434           ierr = PCFieldSplitSetIS(pc, splitname, compField);CHKERRQ(ierr);
435         }
436         ierr = ISDestroy(&compField);CHKERRQ(ierr);
437         for (j = 0; j < nfields; ++j) {
438           f    = ifields[j];
439           ierr = PetscFree(fieldNames[f]);CHKERRQ(ierr);
440           ierr = ISDestroy(&fields[f]);CHKERRQ(ierr);
441         }
442       }
443       if (i == 0) {
444         for (f = 0; f < numFields; ++f) {
445           ierr = PCFieldSplitSetIS(pc, fieldNames[f], fields[f]);CHKERRQ(ierr);
446           ierr = PetscFree(fieldNames[f]);CHKERRQ(ierr);
447           ierr = ISDestroy(&fields[f]);CHKERRQ(ierr);
448         }
449       } else {
450         for (j=0; j<numFields; j++) {
451           ierr = DMDestroy(dms+j);CHKERRQ(ierr);
452         }
453         ierr = PetscFree(dms);CHKERRQ(ierr);
454         ierr = PetscMalloc1(i, &dms);CHKERRQ(ierr);
455         for (j = 0; j < i; ++j) dms[j] = subdm[j];
456       }
457       ierr = PetscFree(fieldNames);CHKERRQ(ierr);
458       ierr = PetscFree(fields);CHKERRQ(ierr);
459       if (dms) {
460         ierr = PetscInfo(pc, "Setting up physics based fieldsplit preconditioner using the embedded DM\n");CHKERRQ(ierr);
461         for (ilink = jac->head, i = 0; ilink; ilink = ilink->next, ++i) {
462           const char *prefix;
463           ierr = PetscObjectGetOptionsPrefix((PetscObject)(ilink->ksp),&prefix);CHKERRQ(ierr);
464           ierr = PetscObjectSetOptionsPrefix((PetscObject)(dms[i]), prefix);CHKERRQ(ierr);
465           ierr = KSPSetDM(ilink->ksp, dms[i]);CHKERRQ(ierr);
466           ierr = KSPSetDMActive(ilink->ksp, PETSC_FALSE);CHKERRQ(ierr);
467           {
468             PetscErrorCode (*func)(KSP,Mat,Mat,void*);
469             void            *ctx;
470 
471             ierr = DMKSPGetComputeOperators(pc->dm, &func, &ctx);CHKERRQ(ierr);
472             ierr = DMKSPSetComputeOperators(dms[i],  func,  ctx);CHKERRQ(ierr);
473           }
474           ierr = PetscObjectIncrementTabLevel((PetscObject)dms[i],(PetscObject)ilink->ksp,0);CHKERRQ(ierr);
475           ierr = DMDestroy(&dms[i]);CHKERRQ(ierr);
476         }
477         ierr = PetscFree(dms);CHKERRQ(ierr);
478       }
479     } else {
480       if (jac->bs <= 0) {
481         if (pc->pmat) {
482           ierr = MatGetBlockSize(pc->pmat,&jac->bs);CHKERRQ(ierr);
483         } else jac->bs = 1;
484       }
485 
486       if (jac->detect) {
487         IS       zerodiags,rest;
488         PetscInt nmin,nmax;
489 
490         ierr = MatGetOwnershipRange(pc->mat,&nmin,&nmax);CHKERRQ(ierr);
491         if (jac->diag_use_amat) {
492           ierr = MatFindZeroDiagonals(pc->mat,&zerodiags);CHKERRQ(ierr);
493         } else {
494           ierr = MatFindZeroDiagonals(pc->pmat,&zerodiags);CHKERRQ(ierr);
495         }
496         ierr = ISComplement(zerodiags,nmin,nmax,&rest);CHKERRQ(ierr);
497         ierr = PCFieldSplitSetIS(pc,"0",rest);CHKERRQ(ierr);
498         ierr = PCFieldSplitSetIS(pc,"1",zerodiags);CHKERRQ(ierr);
499         ierr = ISDestroy(&zerodiags);CHKERRQ(ierr);
500         ierr = ISDestroy(&rest);CHKERRQ(ierr);
501       } else if (coupling) {
502         IS       coupling,rest;
503         PetscInt nmin,nmax;
504 
505         ierr = MatGetOwnershipRange(pc->mat,&nmin,&nmax);CHKERRQ(ierr);
506         if (jac->offdiag_use_amat) {
507           ierr = MatFindOffBlockDiagonalEntries(pc->mat,&coupling);CHKERRQ(ierr);
508         } else {
509           ierr = MatFindOffBlockDiagonalEntries(pc->pmat,&coupling);CHKERRQ(ierr);
510         }
511         ierr = ISCreateStride(PetscObjectComm((PetscObject)pc->mat),nmax-nmin,nmin,1,&rest);CHKERRQ(ierr);
512         ierr = ISSetIdentity(rest);CHKERRQ(ierr);
513         ierr = PCFieldSplitSetIS(pc,"0",rest);CHKERRQ(ierr);
514         ierr = PCFieldSplitSetIS(pc,"1",coupling);CHKERRQ(ierr);
515         ierr = ISDestroy(&coupling);CHKERRQ(ierr);
516         ierr = ISDestroy(&rest);CHKERRQ(ierr);
517       } else {
518         ierr = PetscOptionsGetBool(((PetscObject)pc)->options,((PetscObject)pc)->prefix,"-pc_fieldsplit_default",&fieldsplit_default,NULL);CHKERRQ(ierr);
519         if (!fieldsplit_default) {
520           /* Allow user to set fields from command line,  if bs was known at the time of PCSetFromOptions_FieldSplit()
521            then it is set there. This is not ideal because we should only have options set in XXSetFromOptions(). */
522           ierr = PCFieldSplitSetRuntimeSplits_Private(pc);CHKERRQ(ierr);
523           if (jac->splitdefined) {ierr = PetscInfo(pc,"Splits defined using the options database\n");CHKERRQ(ierr);}
524         }
525         if ((fieldsplit_default || !jac->splitdefined) && !jac->isrestrict) {
526           Mat       M = pc->pmat;
527           PetscBool isnest;
528 
529           ierr = PetscInfo(pc,"Using default splitting of fields\n");CHKERRQ(ierr);
530           ierr = PetscObjectTypeCompare((PetscObject)pc->pmat,MATNEST,&isnest);CHKERRQ(ierr);
531           if (!isnest) {
532             M    = pc->mat;
533             ierr = PetscObjectTypeCompare((PetscObject)pc->mat,MATNEST,&isnest);CHKERRQ(ierr);
534           }
535           if (isnest) {
536             IS       *fields;
537             PetscInt nf;
538 
539             ierr = MatNestGetSize(M,&nf,NULL);CHKERRQ(ierr);
540             ierr = PetscMalloc1(nf,&fields);CHKERRQ(ierr);
541             ierr = MatNestGetISs(M,fields,NULL);CHKERRQ(ierr);
542             for (i=0;i<nf;i++) {
543               ierr = PCFieldSplitSetIS(pc,NULL,fields[i]);CHKERRQ(ierr);
544             }
545             ierr = PetscFree(fields);CHKERRQ(ierr);
546           } else {
547             for (i=0; i<jac->bs; i++) {
548               char splitname[8];
549               ierr = PetscSNPrintf(splitname,sizeof(splitname),"%D",i);CHKERRQ(ierr);
550               ierr = PCFieldSplitSetFields(pc,splitname,1,&i,&i);CHKERRQ(ierr);
551             }
552             jac->defaultsplit = PETSC_TRUE;
553           }
554         }
555       }
556     }
557   } else if (jac->nsplits == 1) {
558     if (ilink->is) {
559       IS       is2;
560       PetscInt nmin,nmax;
561 
562       ierr = MatGetOwnershipRange(pc->mat,&nmin,&nmax);CHKERRQ(ierr);
563       ierr = ISComplement(ilink->is,nmin,nmax,&is2);CHKERRQ(ierr);
564       ierr = PCFieldSplitSetIS(pc,"1",is2);CHKERRQ(ierr);
565       ierr = ISDestroy(&is2);CHKERRQ(ierr);
566     } else SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Must provide at least two sets of fields to PCFieldSplit()");
567   }
568 
569   if (jac->nsplits < 2) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Unhandled case, must have at least two fields, not %d", jac->nsplits);
570   PetscFunctionReturn(0);
571 }
572 
573 static PetscErrorCode MatGolubKahanComputeExplicitOperator(Mat A,Mat B,Mat C,Mat *H,PetscReal gkbnu)
574 {
575   PetscErrorCode    ierr;
576   Mat               BT,T;
577   PetscReal         nrmT,nrmB;
578 
579   PetscFunctionBegin;
580   ierr = MatHermitianTranspose(C,MAT_INITIAL_MATRIX,&T);CHKERRQ(ierr);            /* Test if augmented matrix is symmetric */
581   ierr = MatAXPY(T,-1.0,B,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
582   ierr = MatNorm(T,NORM_1,&nrmT);CHKERRQ(ierr);
583   ierr = MatNorm(B,NORM_1,&nrmB);CHKERRQ(ierr);
584   if (nrmB > 0) {
585     if (nrmT/nrmB >= PETSC_SMALL) {
586       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Matrix is not symmetric/hermitian, GKB is not applicable.");
587     }
588   }
589   /* Compute augmented Lagrangian matrix H = A00 + nu*A01*A01'. This corresponds to */
590   /* setting N := 1/nu*I in [Ar13].                                                 */
591   ierr = MatHermitianTranspose(B,MAT_INITIAL_MATRIX,&BT);CHKERRQ(ierr);
592   ierr = MatMatMult(B,BT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,H);CHKERRQ(ierr);       /* H = A01*A01'          */
593   ierr = MatAYPX(*H,gkbnu,A,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);             /* H = A00 + nu*A01*A01' */
594 
595   ierr = MatDestroy(&BT);CHKERRQ(ierr);
596   ierr = MatDestroy(&T);CHKERRQ(ierr);
597   PetscFunctionReturn(0);
598 }
599 
600 PETSC_EXTERN PetscErrorCode PetscOptionsFindPairPrefix_Private(PetscOptions,const char pre[], const char name[],const char *value[],PetscBool *flg);
601 
602 static PetscErrorCode PCSetUp_FieldSplit(PC pc)
603 {
604   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
605   PetscErrorCode    ierr;
606   PC_FieldSplitLink ilink;
607   PetscInt          i,nsplit;
608   PetscBool         sorted, sorted_col;
609 
610   PetscFunctionBegin;
611   pc->failedreason = PC_NOERROR;
612   ierr   = PCFieldSplitSetDefaults(pc);CHKERRQ(ierr);
613   nsplit = jac->nsplits;
614   ilink  = jac->head;
615 
616   /* get the matrices for each split */
617   if (!jac->issetup) {
618     PetscInt rstart,rend,nslots,bs;
619 
620     jac->issetup = PETSC_TRUE;
621 
622     /* This is done here instead of in PCFieldSplitSetFields() because may not have matrix at that point */
623     if (jac->defaultsplit || !ilink->is) {
624       if (jac->bs <= 0) jac->bs = nsplit;
625     }
626     bs     = jac->bs;
627     ierr   = MatGetOwnershipRange(pc->pmat,&rstart,&rend);CHKERRQ(ierr);
628     nslots = (rend - rstart)/bs;
629     for (i=0; i<nsplit; i++) {
630       if (jac->defaultsplit) {
631         ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),nslots,rstart+i,nsplit,&ilink->is);CHKERRQ(ierr);
632         ierr = ISDuplicate(ilink->is,&ilink->is_col);CHKERRQ(ierr);
633       } else if (!ilink->is) {
634         if (ilink->nfields > 1) {
635           PetscInt *ii,*jj,j,k,nfields = ilink->nfields,*fields = ilink->fields,*fields_col = ilink->fields_col;
636           ierr = PetscMalloc1(ilink->nfields*nslots,&ii);CHKERRQ(ierr);
637           ierr = PetscMalloc1(ilink->nfields*nslots,&jj);CHKERRQ(ierr);
638           for (j=0; j<nslots; j++) {
639             for (k=0; k<nfields; k++) {
640               ii[nfields*j + k] = rstart + bs*j + fields[k];
641               jj[nfields*j + k] = rstart + bs*j + fields_col[k];
642             }
643           }
644           ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nslots*nfields,ii,PETSC_OWN_POINTER,&ilink->is);CHKERRQ(ierr);
645           ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nslots*nfields,jj,PETSC_OWN_POINTER,&ilink->is_col);CHKERRQ(ierr);
646           ierr = ISSetBlockSize(ilink->is, nfields);CHKERRQ(ierr);
647           ierr = ISSetBlockSize(ilink->is_col, nfields);CHKERRQ(ierr);
648         } else {
649           ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),nslots,rstart+ilink->fields[0],bs,&ilink->is);CHKERRQ(ierr);
650           ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),nslots,rstart+ilink->fields_col[0],bs,&ilink->is_col);CHKERRQ(ierr);
651         }
652       }
653       ierr = ISSorted(ilink->is,&sorted);CHKERRQ(ierr);
654       if (ilink->is_col) { ierr = ISSorted(ilink->is_col,&sorted_col);CHKERRQ(ierr); }
655       if (!sorted || !sorted_col) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Fields must be sorted when creating split");
656       ilink = ilink->next;
657     }
658   }
659 
660   ilink = jac->head;
661   if (!jac->pmat) {
662     Vec xtmp;
663 
664     ierr = MatCreateVecs(pc->pmat,&xtmp,NULL);CHKERRQ(ierr);
665     ierr = PetscMalloc1(nsplit,&jac->pmat);CHKERRQ(ierr);
666     ierr = PetscMalloc2(nsplit,&jac->x,nsplit,&jac->y);CHKERRQ(ierr);
667     for (i=0; i<nsplit; i++) {
668       MatNullSpace sp;
669 
670       /* Check for preconditioning matrix attached to IS */
671       ierr = PetscObjectQuery((PetscObject) ilink->is, "pmat", (PetscObject*) &jac->pmat[i]);CHKERRQ(ierr);
672       if (jac->pmat[i]) {
673         ierr = PetscObjectReference((PetscObject) jac->pmat[i]);CHKERRQ(ierr);
674         if (jac->type == PC_COMPOSITE_SCHUR) {
675           jac->schur_user = jac->pmat[i];
676 
677           ierr = PetscObjectReference((PetscObject) jac->schur_user);CHKERRQ(ierr);
678         }
679       } else {
680         const char *prefix;
681         ierr = MatCreateSubMatrix(pc->pmat,ilink->is,ilink->is_col,MAT_INITIAL_MATRIX,&jac->pmat[i]);CHKERRQ(ierr);
682         ierr = KSPGetOptionsPrefix(ilink->ksp,&prefix);CHKERRQ(ierr);
683         ierr = MatSetOptionsPrefix(jac->pmat[i],prefix);CHKERRQ(ierr);
684         ierr = MatViewFromOptions(jac->pmat[i],NULL,"-mat_view");CHKERRQ(ierr);
685       }
686       /* create work vectors for each split */
687       ierr     = MatCreateVecs(jac->pmat[i],&jac->x[i],&jac->y[i]);CHKERRQ(ierr);
688       ilink->x = jac->x[i]; ilink->y = jac->y[i]; ilink->z = NULL;
689       /* compute scatter contexts needed by multiplicative versions and non-default splits */
690       ierr = VecScatterCreate(xtmp,ilink->is,jac->x[i],NULL,&ilink->sctx);CHKERRQ(ierr);
691       ierr = PetscObjectQuery((PetscObject) ilink->is, "nearnullspace", (PetscObject*) &sp);CHKERRQ(ierr);
692       if (sp) {
693         ierr = MatSetNearNullSpace(jac->pmat[i], sp);CHKERRQ(ierr);
694       }
695       ilink = ilink->next;
696     }
697     ierr = VecDestroy(&xtmp);CHKERRQ(ierr);
698   } else {
699     MatReuse scall;
700     if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
701       for (i=0; i<nsplit; i++) {
702         ierr = MatDestroy(&jac->pmat[i]);CHKERRQ(ierr);
703       }
704       scall = MAT_INITIAL_MATRIX;
705     } else scall = MAT_REUSE_MATRIX;
706 
707     for (i=0; i<nsplit; i++) {
708       Mat pmat;
709 
710       /* Check for preconditioning matrix attached to IS */
711       ierr = PetscObjectQuery((PetscObject) ilink->is, "pmat", (PetscObject*) &pmat);CHKERRQ(ierr);
712       if (!pmat) {
713         ierr = MatCreateSubMatrix(pc->pmat,ilink->is,ilink->is_col,scall,&jac->pmat[i]);CHKERRQ(ierr);
714       }
715       ilink = ilink->next;
716     }
717   }
718   if (jac->diag_use_amat) {
719     ilink = jac->head;
720     if (!jac->mat) {
721       ierr = PetscMalloc1(nsplit,&jac->mat);CHKERRQ(ierr);
722       for (i=0; i<nsplit; i++) {
723         ierr  = MatCreateSubMatrix(pc->mat,ilink->is,ilink->is_col,MAT_INITIAL_MATRIX,&jac->mat[i]);CHKERRQ(ierr);
724         ilink = ilink->next;
725       }
726     } else {
727       MatReuse scall;
728       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
729         for (i=0; i<nsplit; i++) {
730           ierr = MatDestroy(&jac->mat[i]);CHKERRQ(ierr);
731         }
732         scall = MAT_INITIAL_MATRIX;
733       } else scall = MAT_REUSE_MATRIX;
734 
735       for (i=0; i<nsplit; i++) {
736         ierr  = MatCreateSubMatrix(pc->mat,ilink->is,ilink->is_col,scall,&jac->mat[i]);CHKERRQ(ierr);
737         ilink = ilink->next;
738       }
739     }
740   } else {
741     jac->mat = jac->pmat;
742   }
743 
744   /* Check for null space attached to IS */
745   ilink = jac->head;
746   for (i=0; i<nsplit; i++) {
747     MatNullSpace sp;
748 
749     ierr = PetscObjectQuery((PetscObject) ilink->is, "nullspace", (PetscObject*) &sp);CHKERRQ(ierr);
750     if (sp) {
751       ierr = MatSetNullSpace(jac->mat[i], sp);CHKERRQ(ierr);
752     }
753     ilink = ilink->next;
754   }
755 
756   if (jac->type != PC_COMPOSITE_ADDITIVE  && jac->type != PC_COMPOSITE_SCHUR && jac->type != PC_COMPOSITE_GKB) {
757     /* extract the rows of the matrix associated with each field: used for efficient computation of residual inside algorithm */
758     /* FIXME: Can/should we reuse jac->mat whenever (jac->diag_use_amat) is true? */
759     ilink = jac->head;
760     if (nsplit == 2 && jac->type == PC_COMPOSITE_MULTIPLICATIVE) {
761       /* special case need where Afield[0] is not needed and only certain columns of Afield[1] are needed since update is only on those rows of the solution */
762       if (!jac->Afield) {
763         ierr = PetscCalloc1(nsplit,&jac->Afield);CHKERRQ(ierr);
764         if (jac->offdiag_use_amat) {
765           ierr = MatCreateSubMatrix(pc->mat,ilink->next->is,ilink->is,MAT_INITIAL_MATRIX,&jac->Afield[1]);CHKERRQ(ierr);
766         } else {
767           ierr = MatCreateSubMatrix(pc->pmat,ilink->next->is,ilink->is,MAT_INITIAL_MATRIX,&jac->Afield[1]);CHKERRQ(ierr);
768         }
769       } else {
770         MatReuse scall;
771 
772         if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
773           ierr  = MatDestroy(&jac->Afield[1]);CHKERRQ(ierr);
774           scall = MAT_INITIAL_MATRIX;
775         } else scall = MAT_REUSE_MATRIX;
776 
777         if (jac->offdiag_use_amat) {
778           ierr = MatCreateSubMatrix(pc->mat,ilink->next->is,ilink->is,scall,&jac->Afield[1]);CHKERRQ(ierr);
779         } else {
780           ierr = MatCreateSubMatrix(pc->pmat,ilink->next->is,ilink->is,scall,&jac->Afield[1]);CHKERRQ(ierr);
781         }
782       }
783     } else {
784       if (!jac->Afield) {
785         ierr = PetscMalloc1(nsplit,&jac->Afield);CHKERRQ(ierr);
786         for (i=0; i<nsplit; i++) {
787           if (jac->offdiag_use_amat) {
788             ierr = MatCreateSubMatrix(pc->mat,ilink->is,NULL,MAT_INITIAL_MATRIX,&jac->Afield[i]);CHKERRQ(ierr);
789           } else {
790             ierr = MatCreateSubMatrix(pc->pmat,ilink->is,NULL,MAT_INITIAL_MATRIX,&jac->Afield[i]);CHKERRQ(ierr);
791           }
792           ilink = ilink->next;
793         }
794       } else {
795         MatReuse scall;
796         if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
797           for (i=0; i<nsplit; i++) {
798             ierr = MatDestroy(&jac->Afield[i]);CHKERRQ(ierr);
799           }
800           scall = MAT_INITIAL_MATRIX;
801         } else scall = MAT_REUSE_MATRIX;
802 
803         for (i=0; i<nsplit; i++) {
804           if (jac->offdiag_use_amat) {
805             ierr = MatCreateSubMatrix(pc->mat,ilink->is,NULL,scall,&jac->Afield[i]);CHKERRQ(ierr);
806           } else {
807             ierr = MatCreateSubMatrix(pc->pmat,ilink->is,NULL,scall,&jac->Afield[i]);CHKERRQ(ierr);
808           }
809           ilink = ilink->next;
810         }
811       }
812     }
813   }
814 
815   if (jac->type == PC_COMPOSITE_SCHUR) {
816     IS          ccis;
817     PetscBool   isspd;
818     PetscInt    rstart,rend;
819     char        lscname[256];
820     PetscObject LSC_L;
821 
822     if (nsplit != 2) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_INCOMP,"To use Schur complement preconditioner you must have exactly 2 fields");
823 
824     /* If pc->mat is SPD, don't scale by -1 the Schur complement */
825     if (jac->schurscale == (PetscScalar)-1.0) {
826       ierr = MatGetOption(pc->pmat,MAT_SPD,&isspd);CHKERRQ(ierr);
827       jac->schurscale = (isspd == PETSC_TRUE) ? 1.0 : -1.0;
828     }
829 
830     /* When extracting off-diagonal submatrices, we take complements from this range */
831     ierr = MatGetOwnershipRangeColumn(pc->mat,&rstart,&rend);CHKERRQ(ierr);
832 
833     if (jac->schur) {
834       KSP      kspA = jac->head->ksp, kspInner = NULL, kspUpper = jac->kspupper;
835       MatReuse scall;
836 
837       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
838         scall = MAT_INITIAL_MATRIX;
839         ierr  = MatDestroy(&jac->B);CHKERRQ(ierr);
840         ierr  = MatDestroy(&jac->C);CHKERRQ(ierr);
841       } else scall = MAT_REUSE_MATRIX;
842 
843       ierr  = MatSchurComplementGetKSP(jac->schur, &kspInner);CHKERRQ(ierr);
844       ilink = jac->head;
845       ierr  = ISComplement(ilink->is_col,rstart,rend,&ccis);CHKERRQ(ierr);
846       if (jac->offdiag_use_amat) {
847         ierr = MatCreateSubMatrix(pc->mat,ilink->is,ccis,scall,&jac->B);CHKERRQ(ierr);
848       } else {
849         ierr = MatCreateSubMatrix(pc->pmat,ilink->is,ccis,scall,&jac->B);CHKERRQ(ierr);
850       }
851       ierr  = ISDestroy(&ccis);CHKERRQ(ierr);
852       ilink = ilink->next;
853       ierr  = ISComplement(ilink->is_col,rstart,rend,&ccis);CHKERRQ(ierr);
854       if (jac->offdiag_use_amat) {
855         ierr = MatCreateSubMatrix(pc->mat,ilink->is,ccis,scall,&jac->C);CHKERRQ(ierr);
856       } else {
857         ierr = MatCreateSubMatrix(pc->pmat,ilink->is,ccis,scall,&jac->C);CHKERRQ(ierr);
858       }
859       ierr  = ISDestroy(&ccis);CHKERRQ(ierr);
860       ierr  = MatSchurComplementUpdateSubMatrices(jac->schur,jac->mat[0],jac->pmat[0],jac->B,jac->C,jac->mat[1]);CHKERRQ(ierr);
861       if (jac->schurpre == PC_FIELDSPLIT_SCHUR_PRE_SELFP) {
862         ierr = MatDestroy(&jac->schurp);CHKERRQ(ierr);
863         ierr = MatSchurComplementGetPmat(jac->schur,MAT_INITIAL_MATRIX,&jac->schurp);CHKERRQ(ierr);
864       }
865       if (kspA != kspInner) {
866         ierr = KSPSetOperators(kspA,jac->mat[0],jac->pmat[0]);CHKERRQ(ierr);
867       }
868       if (kspUpper != kspA) {
869         ierr = KSPSetOperators(kspUpper,jac->mat[0],jac->pmat[0]);CHKERRQ(ierr);
870       }
871       ierr = KSPSetOperators(jac->kspschur,jac->schur,FieldSplitSchurPre(jac));CHKERRQ(ierr);
872     } else {
873       const char   *Dprefix;
874       char         schurprefix[256], schurmatprefix[256];
875       char         schurtestoption[256];
876       MatNullSpace sp;
877       PetscBool    flg;
878       KSP          kspt;
879 
880       /* extract the A01 and A10 matrices */
881       ilink = jac->head;
882       ierr  = ISComplement(ilink->is_col,rstart,rend,&ccis);CHKERRQ(ierr);
883       if (jac->offdiag_use_amat) {
884         ierr = MatCreateSubMatrix(pc->mat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->B);CHKERRQ(ierr);
885       } else {
886         ierr = MatCreateSubMatrix(pc->pmat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->B);CHKERRQ(ierr);
887       }
888       ierr  = ISDestroy(&ccis);CHKERRQ(ierr);
889       ilink = ilink->next;
890       ierr  = ISComplement(ilink->is_col,rstart,rend,&ccis);CHKERRQ(ierr);
891       if (jac->offdiag_use_amat) {
892         ierr = MatCreateSubMatrix(pc->mat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->C);CHKERRQ(ierr);
893       } else {
894         ierr = MatCreateSubMatrix(pc->pmat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->C);CHKERRQ(ierr);
895       }
896       ierr = ISDestroy(&ccis);CHKERRQ(ierr);
897 
898       /* Use mat[0] (diagonal block of Amat) preconditioned by pmat[0] to define Schur complement */
899       ierr = MatCreate(((PetscObject)jac->mat[0])->comm,&jac->schur);CHKERRQ(ierr);
900       ierr = MatSetType(jac->schur,MATSCHURCOMPLEMENT);CHKERRQ(ierr);
901       ierr = MatSchurComplementSetSubMatrices(jac->schur,jac->mat[0],jac->pmat[0],jac->B,jac->C,jac->mat[1]);CHKERRQ(ierr);
902       ierr = PetscSNPrintf(schurmatprefix, sizeof(schurmatprefix), "%sfieldsplit_%s_", ((PetscObject)pc)->prefix ? ((PetscObject)pc)->prefix : "", ilink->splitname);CHKERRQ(ierr);
903       ierr = MatSetOptionsPrefix(jac->schur,schurmatprefix);CHKERRQ(ierr);
904       ierr = MatSchurComplementGetKSP(jac->schur,&kspt);CHKERRQ(ierr);
905       ierr = KSPSetOptionsPrefix(kspt,schurmatprefix);CHKERRQ(ierr);
906 
907       /* Note: this is not true in general */
908       ierr = MatGetNullSpace(jac->mat[1], &sp);CHKERRQ(ierr);
909       if (sp) {
910         ierr = MatSetNullSpace(jac->schur, sp);CHKERRQ(ierr);
911       }
912 
913       ierr = PetscSNPrintf(schurtestoption, sizeof(schurtestoption), "-fieldsplit_%s_inner_", ilink->splitname);CHKERRQ(ierr);
914       ierr = PetscOptionsFindPairPrefix_Private(((PetscObject)pc)->options,((PetscObject)pc)->prefix, schurtestoption, NULL, &flg);CHKERRQ(ierr);
915       if (flg) {
916         DM  dmInner;
917         KSP kspInner;
918         PC  pcInner;
919 
920         ierr = MatSchurComplementGetKSP(jac->schur, &kspInner);CHKERRQ(ierr);
921         ierr = KSPReset(kspInner);CHKERRQ(ierr);
922         ierr = KSPSetOperators(kspInner,jac->mat[0],jac->pmat[0]);CHKERRQ(ierr);
923         ierr = PetscSNPrintf(schurprefix, sizeof(schurprefix), "%sfieldsplit_%s_inner_", ((PetscObject)pc)->prefix ? ((PetscObject)pc)->prefix : "", ilink->splitname);CHKERRQ(ierr);
924         /* Indent this deeper to emphasize the "inner" nature of this solver. */
925         ierr = PetscObjectIncrementTabLevel((PetscObject)kspInner, (PetscObject) pc, 2);CHKERRQ(ierr);
926         ierr = PetscObjectIncrementTabLevel((PetscObject)kspInner->pc, (PetscObject) pc, 2);CHKERRQ(ierr);
927         ierr = KSPSetOptionsPrefix(kspInner, schurprefix);CHKERRQ(ierr);
928 
929         /* Set DM for new solver */
930         ierr = KSPGetDM(jac->head->ksp, &dmInner);CHKERRQ(ierr);
931         ierr = KSPSetDM(kspInner, dmInner);CHKERRQ(ierr);
932         ierr = KSPSetDMActive(kspInner, PETSC_FALSE);CHKERRQ(ierr);
933 
934         /* Defaults to PCKSP as preconditioner */
935         ierr = KSPGetPC(kspInner, &pcInner);CHKERRQ(ierr);
936         ierr = PCSetType(pcInner, PCKSP);CHKERRQ(ierr);
937         ierr = PCKSPSetKSP(pcInner, jac->head->ksp);CHKERRQ(ierr);
938       } else {
939          /* Use the outer solver for the inner solve, but revert the KSPPREONLY from PCFieldSplitSetFields_FieldSplit or
940           * PCFieldSplitSetIS_FieldSplit. We don't want KSPPREONLY because it makes the Schur complement inexact,
941           * preventing Schur complement reduction to be an accurate solve. Usually when an iterative solver is used for
942           * S = D - C A_inner^{-1} B, we expect S to be defined using an accurate definition of A_inner^{-1}, so we make
943           * GMRES the default. Note that it is also common to use PREONLY for S, in which case S may not be used
944           * directly, and the user is responsible for setting an inexact method for fieldsplit's A^{-1}. */
945         ierr = KSPSetType(jac->head->ksp,KSPGMRES);CHKERRQ(ierr);
946         ierr = MatSchurComplementSetKSP(jac->schur,jac->head->ksp);CHKERRQ(ierr);
947       }
948       ierr = KSPSetOperators(jac->head->ksp,jac->mat[0],jac->pmat[0]);CHKERRQ(ierr);
949       ierr = KSPSetFromOptions(jac->head->ksp);CHKERRQ(ierr);
950       ierr = MatSetFromOptions(jac->schur);CHKERRQ(ierr);
951 
952       ierr = PetscObjectTypeCompare((PetscObject)jac->schur, MATSCHURCOMPLEMENT, &flg);CHKERRQ(ierr);
953       if (flg) { /* Need to do this otherwise PCSetUp_KSP will overwrite the amat of jac->head->ksp */
954         KSP kspInner;
955         PC  pcInner;
956 
957         ierr = MatSchurComplementGetKSP(jac->schur, &kspInner);CHKERRQ(ierr);
958         ierr = KSPGetPC(kspInner, &pcInner);CHKERRQ(ierr);
959         ierr = PetscObjectTypeCompare((PetscObject)pcInner, PCKSP, &flg);CHKERRQ(ierr);
960         if (flg) {
961           KSP ksp;
962 
963           ierr = PCKSPGetKSP(pcInner, &ksp);CHKERRQ(ierr);
964           if (ksp == jac->head->ksp) {
965             ierr = PCSetUseAmat(pcInner, PETSC_TRUE);CHKERRQ(ierr);
966           }
967         }
968       }
969       ierr = PetscSNPrintf(schurtestoption, sizeof(schurtestoption), "-fieldsplit_%s_upper_", ilink->splitname);CHKERRQ(ierr);
970       ierr = PetscOptionsFindPairPrefix_Private(((PetscObject)pc)->options,((PetscObject)pc)->prefix, schurtestoption, NULL, &flg);CHKERRQ(ierr);
971       if (flg) {
972         DM dmInner;
973 
974         ierr = PetscSNPrintf(schurprefix, sizeof(schurprefix), "%sfieldsplit_%s_upper_", ((PetscObject)pc)->prefix ? ((PetscObject)pc)->prefix : "", ilink->splitname);CHKERRQ(ierr);
975         ierr = KSPCreate(PetscObjectComm((PetscObject)pc), &jac->kspupper);CHKERRQ(ierr);
976         ierr = KSPSetErrorIfNotConverged(jac->kspupper,pc->erroriffailure);CHKERRQ(ierr);
977         ierr = KSPSetOptionsPrefix(jac->kspupper, schurprefix);CHKERRQ(ierr);
978         ierr = PetscObjectIncrementTabLevel((PetscObject)jac->kspupper, (PetscObject) pc, 1);CHKERRQ(ierr);
979         ierr = PetscObjectIncrementTabLevel((PetscObject)jac->kspupper->pc, (PetscObject) pc, 1);CHKERRQ(ierr);
980         ierr = KSPGetDM(jac->head->ksp, &dmInner);CHKERRQ(ierr);
981         ierr = KSPSetDM(jac->kspupper, dmInner);CHKERRQ(ierr);
982         ierr = KSPSetDMActive(jac->kspupper, PETSC_FALSE);CHKERRQ(ierr);
983         ierr = KSPSetFromOptions(jac->kspupper);CHKERRQ(ierr);
984         ierr = KSPSetOperators(jac->kspupper,jac->mat[0],jac->pmat[0]);CHKERRQ(ierr);
985         ierr = VecDuplicate(jac->head->x, &jac->head->z);CHKERRQ(ierr);
986       } else {
987         jac->kspupper = jac->head->ksp;
988         ierr          = PetscObjectReference((PetscObject) jac->head->ksp);CHKERRQ(ierr);
989       }
990 
991       if (jac->schurpre == PC_FIELDSPLIT_SCHUR_PRE_SELFP) {
992         ierr = MatSchurComplementGetPmat(jac->schur,MAT_INITIAL_MATRIX,&jac->schurp);CHKERRQ(ierr);
993       }
994       ierr = KSPCreate(PetscObjectComm((PetscObject)pc),&jac->kspschur);CHKERRQ(ierr);
995       ierr = KSPSetErrorIfNotConverged(jac->kspschur,pc->erroriffailure);CHKERRQ(ierr);
996       ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)jac->kspschur);CHKERRQ(ierr);
997       ierr = PetscObjectIncrementTabLevel((PetscObject)jac->kspschur,(PetscObject)pc,1);CHKERRQ(ierr);
998       if (jac->schurpre == PC_FIELDSPLIT_SCHUR_PRE_SELF) {
999         PC pcschur;
1000         ierr = KSPGetPC(jac->kspschur,&pcschur);CHKERRQ(ierr);
1001         ierr = PCSetType(pcschur,PCNONE);CHKERRQ(ierr);
1002         /* Note: This is bad if there exist preconditioners for MATSCHURCOMPLEMENT */
1003       } else if (jac->schurpre == PC_FIELDSPLIT_SCHUR_PRE_FULL) {
1004         ierr = MatSchurComplementComputeExplicitOperator(jac->schur, &jac->schur_user);CHKERRQ(ierr);
1005       }
1006       ierr = KSPSetOperators(jac->kspschur,jac->schur,FieldSplitSchurPre(jac));CHKERRQ(ierr);
1007       ierr = KSPGetOptionsPrefix(jac->head->next->ksp, &Dprefix);CHKERRQ(ierr);
1008       ierr = KSPSetOptionsPrefix(jac->kspschur,         Dprefix);CHKERRQ(ierr);
1009       /* propagate DM */
1010       {
1011         DM sdm;
1012         ierr = KSPGetDM(jac->head->next->ksp, &sdm);CHKERRQ(ierr);
1013         if (sdm) {
1014           ierr = KSPSetDM(jac->kspschur, sdm);CHKERRQ(ierr);
1015           ierr = KSPSetDMActive(jac->kspschur, PETSC_FALSE);CHKERRQ(ierr);
1016         }
1017       }
1018       /* really want setfromoptions called in PCSetFromOptions_FieldSplit(), but it is not ready yet */
1019       /* need to call this every time, since the jac->kspschur is freshly created, otherwise its options never get set */
1020       ierr = KSPSetFromOptions(jac->kspschur);CHKERRQ(ierr);
1021     }
1022     ierr = MatAssemblyBegin(jac->schur,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1023     ierr = MatAssemblyEnd(jac->schur,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1024 
1025     /* HACK: special support to forward L and Lp matrices that might be used by PCLSC */
1026     ierr = PetscSNPrintf(lscname,sizeof(lscname),"%s_LSC_L",ilink->splitname);CHKERRQ(ierr);
1027     ierr = PetscObjectQuery((PetscObject)pc->mat,lscname,(PetscObject*)&LSC_L);CHKERRQ(ierr);
1028     if (!LSC_L) {ierr = PetscObjectQuery((PetscObject)pc->pmat,lscname,(PetscObject*)&LSC_L);CHKERRQ(ierr);}
1029     if (LSC_L) {ierr = PetscObjectCompose((PetscObject)jac->schur,"LSC_L",(PetscObject)LSC_L);CHKERRQ(ierr);}
1030     ierr = PetscSNPrintf(lscname,sizeof(lscname),"%s_LSC_Lp",ilink->splitname);CHKERRQ(ierr);
1031     ierr = PetscObjectQuery((PetscObject)pc->pmat,lscname,(PetscObject*)&LSC_L);CHKERRQ(ierr);
1032     if (!LSC_L) {ierr = PetscObjectQuery((PetscObject)pc->mat,lscname,(PetscObject*)&LSC_L);CHKERRQ(ierr);}
1033     if (LSC_L) {ierr = PetscObjectCompose((PetscObject)jac->schur,"LSC_Lp",(PetscObject)LSC_L);CHKERRQ(ierr);}
1034   } else if (jac->type == PC_COMPOSITE_GKB) {
1035     IS          ccis;
1036     PetscInt    rstart,rend;
1037 
1038     if (nsplit != 2) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_INCOMP,"To use GKB preconditioner you must have exactly 2 fields");
1039 
1040     ilink = jac->head;
1041 
1042     /* When extracting off-diagonal submatrices, we take complements from this range */
1043     ierr = MatGetOwnershipRangeColumn(pc->mat,&rstart,&rend);CHKERRQ(ierr);
1044 
1045     ierr = ISComplement(ilink->is_col,rstart,rend,&ccis);CHKERRQ(ierr);
1046     if (jac->offdiag_use_amat) {
1047       ierr = MatCreateSubMatrix(pc->mat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->B);CHKERRQ(ierr);
1048     } else {
1049       ierr = MatCreateSubMatrix(pc->pmat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->B);CHKERRQ(ierr);
1050     }
1051     ierr  = ISDestroy(&ccis);CHKERRQ(ierr);
1052     /* Create work vectors for GKB algorithm */
1053     ierr  = VecDuplicate(ilink->x,&jac->u);CHKERRQ(ierr);
1054     ierr  = VecDuplicate(ilink->x,&jac->Hu);CHKERRQ(ierr);
1055     ierr  = VecDuplicate(ilink->x,&jac->w2);CHKERRQ(ierr);
1056     ilink = ilink->next;
1057     ierr  = ISComplement(ilink->is_col,rstart,rend,&ccis);CHKERRQ(ierr);
1058     if (jac->offdiag_use_amat) {
1059       ierr = MatCreateSubMatrix(pc->mat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->C);CHKERRQ(ierr);
1060     } else {
1061       ierr = MatCreateSubMatrix(pc->pmat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->C);CHKERRQ(ierr);
1062     }
1063     ierr = ISDestroy(&ccis);CHKERRQ(ierr);
1064     /* Create work vectors for GKB algorithm */
1065     ierr = VecDuplicate(ilink->x,&jac->v);CHKERRQ(ierr);
1066     ierr = VecDuplicate(ilink->x,&jac->d);CHKERRQ(ierr);
1067     ierr = VecDuplicate(ilink->x,&jac->w1);CHKERRQ(ierr);
1068     ierr = MatGolubKahanComputeExplicitOperator(jac->mat[0],jac->B,jac->C,&jac->H,jac->gkbnu);CHKERRQ(ierr);
1069     ierr = PetscCalloc1(jac->gkbdelay,&jac->vecz);CHKERRQ(ierr);
1070 
1071     ilink = jac->head;
1072     ierr  = KSPSetOperators(ilink->ksp,jac->H,jac->H);CHKERRQ(ierr);
1073     if (!jac->suboptionsset) {ierr = KSPSetFromOptions(ilink->ksp);CHKERRQ(ierr);}
1074     /* Create gkb_monitor context */
1075     if (jac->gkbmonitor) {
1076       PetscInt  tablevel;
1077       ierr = PetscViewerCreate(PETSC_COMM_WORLD,&jac->gkbviewer);CHKERRQ(ierr);
1078       ierr = PetscViewerSetType(jac->gkbviewer,PETSCVIEWERASCII);CHKERRQ(ierr);
1079       ierr = PetscObjectGetTabLevel((PetscObject)ilink->ksp,&tablevel);CHKERRQ(ierr);
1080       ierr = PetscViewerASCIISetTab(jac->gkbviewer,tablevel);CHKERRQ(ierr);
1081       ierr = PetscObjectIncrementTabLevel((PetscObject)ilink->ksp,(PetscObject)ilink->ksp,1);CHKERRQ(ierr);
1082     }
1083   } else {
1084     /* set up the individual splits' PCs */
1085     i     = 0;
1086     ilink = jac->head;
1087     while (ilink) {
1088       ierr = KSPSetOperators(ilink->ksp,jac->mat[i],jac->pmat[i]);CHKERRQ(ierr);
1089       /* really want setfromoptions called in PCSetFromOptions_FieldSplit(), but it is not ready yet */
1090       if (!jac->suboptionsset) {ierr = KSPSetFromOptions(ilink->ksp);CHKERRQ(ierr);}
1091       i++;
1092       ilink = ilink->next;
1093     }
1094   }
1095 
1096   jac->suboptionsset = PETSC_TRUE;
1097   PetscFunctionReturn(0);
1098 }
1099 
1100 #define FieldSplitSplitSolveAdd(ilink,xx,yy) \
1101   (VecScatterBegin(ilink->sctx,xx,ilink->x,INSERT_VALUES,SCATTER_FORWARD) || \
1102    VecScatterEnd(ilink->sctx,xx,ilink->x,INSERT_VALUES,SCATTER_FORWARD) || \
1103    PetscLogEventBegin(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL) ||\
1104    KSPSolve(ilink->ksp,ilink->x,ilink->y) ||                               \
1105    KSPCheckSolve(ilink->ksp,pc,ilink->y)  || \
1106    PetscLogEventEnd(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL) ||\
1107    VecScatterBegin(ilink->sctx,ilink->y,yy,ADD_VALUES,SCATTER_REVERSE) ||  \
1108    VecScatterEnd(ilink->sctx,ilink->y,yy,ADD_VALUES,SCATTER_REVERSE))
1109 
1110 static PetscErrorCode PCApply_FieldSplit_Schur(PC pc,Vec x,Vec y)
1111 {
1112   PC_FieldSplit      *jac = (PC_FieldSplit*)pc->data;
1113   PetscErrorCode     ierr;
1114   PC_FieldSplitLink  ilinkA = jac->head, ilinkD = ilinkA->next;
1115   KSP                kspA   = ilinkA->ksp, kspLower = kspA, kspUpper = jac->kspupper;
1116 
1117   PetscFunctionBegin;
1118   switch (jac->schurfactorization) {
1119   case PC_FIELDSPLIT_SCHUR_FACT_DIAG:
1120     /* [A00 0; 0 -S], positive definite, suitable for MINRES */
1121     ierr = VecScatterBegin(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1122     ierr = VecScatterBegin(ilinkD->sctx,x,ilinkD->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1123     ierr = VecScatterEnd(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1124     ierr = PetscLogEventBegin(ilinkA->event,kspA,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
1125     ierr = KSPSolve(kspA,ilinkA->x,ilinkA->y);CHKERRQ(ierr);
1126     ierr = KSPCheckSolve(kspA,pc,ilinkA->y);CHKERRQ(ierr);
1127     ierr = PetscLogEventEnd(ilinkA->event,kspA,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
1128     ierr = VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1129     ierr = VecScatterEnd(ilinkD->sctx,x,ilinkD->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1130     ierr = PetscLogEventBegin(KSP_Solve_FS_S,jac->kspschur,ilinkD->x,ilinkD->y,NULL);CHKERRQ(ierr);
1131     ierr = KSPSolve(jac->kspschur,ilinkD->x,ilinkD->y);CHKERRQ(ierr);
1132     ierr = KSPCheckSolve(jac->kspschur,pc,ilinkD->y);CHKERRQ(ierr);
1133     ierr = PetscLogEventEnd(KSP_Solve_FS_S,jac->kspschur,ilinkD->x,ilinkD->y,NULL);CHKERRQ(ierr);
1134     ierr = VecScale(ilinkD->y,jac->schurscale);CHKERRQ(ierr);
1135     ierr = VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1136     ierr = VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1137     ierr = VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1138     break;
1139   case PC_FIELDSPLIT_SCHUR_FACT_LOWER:
1140     /* [A00 0; A10 S], suitable for left preconditioning */
1141     ierr = VecScatterBegin(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1142     ierr = VecScatterEnd(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1143     ierr = PetscLogEventBegin(ilinkA->event,kspA,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
1144     ierr = KSPSolve(kspA,ilinkA->x,ilinkA->y);CHKERRQ(ierr);
1145     ierr = KSPCheckSolve(kspA,pc,ilinkA->y);CHKERRQ(ierr);
1146     ierr = PetscLogEventEnd(ilinkA->event,kspA,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
1147     ierr = MatMult(jac->C,ilinkA->y,ilinkD->x);CHKERRQ(ierr);
1148     ierr = VecScale(ilinkD->x,-1.);CHKERRQ(ierr);
1149     ierr = VecScatterBegin(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1150     ierr = VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1151     ierr = VecScatterEnd(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1152     ierr = PetscLogEventBegin(KSP_Solve_FS_S,jac->kspschur,ilinkD->x,ilinkD->y,NULL);CHKERRQ(ierr);
1153     ierr = KSPSolve(jac->kspschur,ilinkD->x,ilinkD->y);CHKERRQ(ierr);
1154     ierr = KSPCheckSolve(jac->kspschur,pc,ilinkD->y);CHKERRQ(ierr);
1155     ierr = PetscLogEventEnd(KSP_Solve_FS_S,jac->kspschur,ilinkD->x,ilinkD->y,NULL);CHKERRQ(ierr);
1156     ierr = VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1157     ierr = VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1158     ierr = VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1159     break;
1160   case PC_FIELDSPLIT_SCHUR_FACT_UPPER:
1161     /* [A00 A01; 0 S], suitable for right preconditioning */
1162     ierr = VecScatterBegin(ilinkD->sctx,x,ilinkD->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1163     ierr = VecScatterEnd(ilinkD->sctx,x,ilinkD->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1164     ierr = PetscLogEventBegin(KSP_Solve_FS_S,jac->kspschur,ilinkD->x,ilinkD->y,NULL);CHKERRQ(ierr);
1165     ierr = KSPSolve(jac->kspschur,ilinkD->x,ilinkD->y);CHKERRQ(ierr);
1166     ierr = KSPCheckSolve(jac->kspschur,pc,ilinkD->y);CHKERRQ(ierr);
1167     ierr = PetscLogEventEnd(KSP_Solve_FS_S,jac->kspschur,ilinkD->x,ilinkD->y,NULL);CHKERRQ(ierr);    ierr = MatMult(jac->B,ilinkD->y,ilinkA->x);CHKERRQ(ierr);
1168     ierr = VecScale(ilinkA->x,-1.);CHKERRQ(ierr);
1169     ierr = VecScatterBegin(ilinkA->sctx,x,ilinkA->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1170     ierr = VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1171     ierr = VecScatterEnd(ilinkA->sctx,x,ilinkA->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1172     ierr = PetscLogEventBegin(ilinkA->event,kspA,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
1173     ierr = KSPSolve(kspA,ilinkA->x,ilinkA->y);CHKERRQ(ierr);
1174     ierr = KSPCheckSolve(kspA,pc,ilinkA->y);CHKERRQ(ierr);
1175     ierr = PetscLogEventEnd(ilinkA->event,kspA,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
1176     ierr = VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1177     ierr = VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1178     ierr = VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1179     break;
1180   case PC_FIELDSPLIT_SCHUR_FACT_FULL:
1181     /* [1 0; A10 A00^{-1} 1] [A00 0; 0 S] [1 A00^{-1}A01; 0 1] */
1182     ierr = VecScatterBegin(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1183     ierr = VecScatterEnd(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1184     ierr = PetscLogEventBegin(KSP_Solve_FS_L,kspLower,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
1185     ierr = KSPSolve(kspLower,ilinkA->x,ilinkA->y);CHKERRQ(ierr);
1186     ierr = KSPCheckSolve(kspLower,pc,ilinkA->y);CHKERRQ(ierr);
1187     ierr = PetscLogEventEnd(KSP_Solve_FS_L,kspLower,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
1188     ierr = MatMult(jac->C,ilinkA->y,ilinkD->x);CHKERRQ(ierr);
1189     ierr = VecScale(ilinkD->x,-1.0);CHKERRQ(ierr);
1190     ierr = VecScatterBegin(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1191     ierr = VecScatterEnd(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1192 
1193     ierr = PetscLogEventBegin(KSP_Solve_FS_S,jac->kspschur,ilinkD->x,ilinkD->y,NULL);CHKERRQ(ierr);
1194     ierr = KSPSolve(jac->kspschur,ilinkD->x,ilinkD->y);CHKERRQ(ierr);
1195     ierr = KSPCheckSolve(jac->kspschur,pc,ilinkD->y);CHKERRQ(ierr);
1196     ierr = PetscLogEventEnd(KSP_Solve_FS_S,jac->kspschur,ilinkD->x,ilinkD->y,NULL);CHKERRQ(ierr);
1197     ierr = VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1198 
1199     if (kspUpper == kspA) {
1200       ierr = MatMult(jac->B,ilinkD->y,ilinkA->y);CHKERRQ(ierr);
1201       ierr = VecAXPY(ilinkA->x,-1.0,ilinkA->y);CHKERRQ(ierr);
1202       ierr = PetscLogEventBegin(ilinkA->event,kspA,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
1203       ierr = KSPSolve(kspA,ilinkA->x,ilinkA->y);CHKERRQ(ierr);
1204       ierr = KSPCheckSolve(kspA,pc,ilinkA->y);CHKERRQ(ierr);
1205       ierr = PetscLogEventEnd(ilinkA->event,kspA,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
1206     } else {
1207       ierr = PetscLogEventBegin(ilinkA->event,kspA,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
1208       ierr = KSPSolve(kspA,ilinkA->x,ilinkA->y);CHKERRQ(ierr);
1209       ierr = KSPCheckSolve(kspA,pc,ilinkA->y);CHKERRQ(ierr);
1210       ierr = MatMult(jac->B,ilinkD->y,ilinkA->x);CHKERRQ(ierr);
1211       ierr = PetscLogEventBegin(KSP_Solve_FS_U,kspUpper,ilinkA->x,ilinkA->z,NULL);CHKERRQ(ierr);
1212       ierr = KSPSolve(kspUpper,ilinkA->x,ilinkA->z);CHKERRQ(ierr);
1213       ierr = KSPCheckSolve(kspUpper,pc,ilinkA->z);CHKERRQ(ierr);
1214       ierr = PetscLogEventEnd(KSP_Solve_FS_U,kspUpper,ilinkA->x,ilinkA->z,NULL);CHKERRQ(ierr);
1215       ierr = VecAXPY(ilinkA->y,-1.0,ilinkA->z);CHKERRQ(ierr);
1216     }
1217     ierr = VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1218     ierr = VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1219     ierr = VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1220   }
1221   PetscFunctionReturn(0);
1222 }
1223 
1224 static PetscErrorCode PCApply_FieldSplit(PC pc,Vec x,Vec y)
1225 {
1226   PC_FieldSplit      *jac = (PC_FieldSplit*)pc->data;
1227   PetscErrorCode     ierr;
1228   PC_FieldSplitLink  ilink = jac->head;
1229   PetscInt           cnt,bs;
1230 
1231   PetscFunctionBegin;
1232   if (jac->type == PC_COMPOSITE_ADDITIVE) {
1233     if (jac->defaultsplit) {
1234       ierr = VecGetBlockSize(x,&bs);CHKERRQ(ierr);
1235       if (jac->bs > 0 && bs != jac->bs) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Blocksize of x vector %D does not match fieldsplit blocksize %D",bs,jac->bs);
1236       ierr = VecGetBlockSize(y,&bs);CHKERRQ(ierr);
1237       if (jac->bs > 0 && bs != jac->bs) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Blocksize of y vector %D does not match fieldsplit blocksize %D",bs,jac->bs);
1238       ierr = VecStrideGatherAll(x,jac->x,INSERT_VALUES);CHKERRQ(ierr);
1239       while (ilink) {
1240         ierr = PetscLogEventBegin(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
1241         ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
1242         ierr = KSPCheckSolve(ilink->ksp,pc,ilink->y);CHKERRQ(ierr);
1243         ierr = PetscLogEventEnd(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
1244         ilink = ilink->next;
1245       }
1246       ierr = VecStrideScatterAll(jac->y,y,INSERT_VALUES);CHKERRQ(ierr);
1247     } else {
1248       ierr = VecSet(y,0.0);CHKERRQ(ierr);
1249       while (ilink) {
1250         ierr = FieldSplitSplitSolveAdd(ilink,x,y);CHKERRQ(ierr);
1251         ilink = ilink->next;
1252       }
1253     }
1254   } else if (jac->type == PC_COMPOSITE_MULTIPLICATIVE && jac->nsplits == 2) {
1255     ierr = VecSet(y,0.0);CHKERRQ(ierr);
1256     /* solve on first block for first block variables */
1257     ierr = VecScatterBegin(ilink->sctx,x,ilink->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1258     ierr = VecScatterEnd(ilink->sctx,x,ilink->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1259     ierr = PetscLogEventBegin(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
1260     ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
1261     ierr = KSPCheckSolve(ilink->ksp,pc,ilink->y);CHKERRQ(ierr);
1262     ierr = PetscLogEventEnd(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
1263     ierr = VecScatterBegin(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1264     ierr = VecScatterEnd(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1265 
1266     /* compute the residual only onto second block variables using first block variables */
1267     ierr = MatMult(jac->Afield[1],ilink->y,ilink->next->x);CHKERRQ(ierr);
1268     ilink = ilink->next;
1269     ierr = VecScale(ilink->x,-1.0);CHKERRQ(ierr);
1270     ierr = VecScatterBegin(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1271     ierr = VecScatterEnd(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1272 
1273     /* solve on second block variables */
1274     ierr = PetscLogEventBegin(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
1275     ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
1276     ierr = KSPCheckSolve(ilink->ksp,pc,ilink->y);CHKERRQ(ierr);
1277     ierr = PetscLogEventEnd(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
1278     ierr = VecScatterBegin(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1279     ierr = VecScatterEnd(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1280   } else if (jac->type == PC_COMPOSITE_MULTIPLICATIVE || jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
1281     if (!jac->w1) {
1282       ierr = VecDuplicate(x,&jac->w1);CHKERRQ(ierr);
1283       ierr = VecDuplicate(x,&jac->w2);CHKERRQ(ierr);
1284     }
1285     ierr = VecSet(y,0.0);CHKERRQ(ierr);
1286     ierr = FieldSplitSplitSolveAdd(ilink,x,y);CHKERRQ(ierr);
1287     cnt  = 1;
1288     while (ilink->next) {
1289       ilink = ilink->next;
1290       /* compute the residual only over the part of the vector needed */
1291       ierr = MatMult(jac->Afield[cnt++],y,ilink->x);CHKERRQ(ierr);
1292       ierr = VecScale(ilink->x,-1.0);CHKERRQ(ierr);
1293       ierr = VecScatterBegin(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1294       ierr = VecScatterEnd(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1295       ierr = PetscLogEventBegin(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
1296       ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
1297       ierr = KSPCheckSolve(ilink->ksp,pc,ilink->y);CHKERRQ(ierr);
1298       ierr = PetscLogEventEnd(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
1299       ierr = VecScatterBegin(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1300       ierr = VecScatterEnd(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1301     }
1302     if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
1303       cnt -= 2;
1304       while (ilink->previous) {
1305         ilink = ilink->previous;
1306         /* compute the residual only over the part of the vector needed */
1307         ierr = MatMult(jac->Afield[cnt--],y,ilink->x);CHKERRQ(ierr);
1308         ierr = VecScale(ilink->x,-1.0);CHKERRQ(ierr);
1309         ierr = VecScatterBegin(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1310         ierr = VecScatterEnd(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1311         ierr = PetscLogEventBegin(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
1312         ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
1313         ierr = KSPCheckSolve(ilink->ksp,pc,ilink->y);CHKERRQ(ierr);
1314         ierr = PetscLogEventEnd(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
1315         ierr = VecScatterBegin(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1316         ierr = VecScatterEnd(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1317       }
1318     }
1319   } else SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Unsupported or unknown composition",(int) jac->type);
1320   PetscFunctionReturn(0);
1321 }
1322 
1323 static PetscErrorCode PCApply_FieldSplit_GKB(PC pc,Vec x,Vec y)
1324 {
1325   PC_FieldSplit      *jac = (PC_FieldSplit*)pc->data;
1326   PetscErrorCode     ierr;
1327   PC_FieldSplitLink  ilinkA = jac->head,ilinkD = ilinkA->next;
1328   KSP                ksp = ilinkA->ksp;
1329   Vec                u,v,Hu,d,work1,work2;
1330   PetscScalar        alpha,z,nrmz2,*vecz;
1331   PetscReal          lowbnd,nu,beta;
1332   PetscInt           j,iterGKB;
1333 
1334   PetscFunctionBegin;
1335   ierr = VecScatterBegin(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1336   ierr = VecScatterBegin(ilinkD->sctx,x,ilinkD->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1337   ierr = VecScatterEnd(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1338   ierr = VecScatterEnd(ilinkD->sctx,x,ilinkD->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1339 
1340   u     = jac->u;
1341   v     = jac->v;
1342   Hu    = jac->Hu;
1343   d     = jac->d;
1344   work1 = jac->w1;
1345   work2 = jac->w2;
1346   vecz  = jac->vecz;
1347 
1348   /* Change RHS to comply with matrix regularization H = A + nu*B*B' */
1349   /* Add q = q + nu*B*b */
1350   if (jac->gkbnu) {
1351     nu = jac->gkbnu;
1352     ierr = VecScale(ilinkD->x,jac->gkbnu);CHKERRQ(ierr);
1353     ierr = MatMultAdd(jac->B,ilinkD->x,ilinkA->x,ilinkA->x);CHKERRQ(ierr);            /* q = q + nu*B*b */
1354   } else {
1355     /* Situation when no augmented Lagrangian is used. Then we set inner  */
1356     /* matrix N = I in [Ar13], and thus nu = 1.                           */
1357     nu = 1;
1358   }
1359 
1360   /* Transform rhs from [q,tilde{b}] to [0,b] */
1361   ierr = PetscLogEventBegin(ilinkA->event,ksp,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
1362   ierr = KSPSolve(ksp,ilinkA->x,ilinkA->y);CHKERRQ(ierr);
1363   ierr = KSPCheckSolve(ksp,pc,ilinkA->y);CHKERRQ(ierr);
1364   ierr = PetscLogEventEnd(ilinkA->event,ksp,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
1365   ierr = MatMultHermitianTranspose(jac->B,ilinkA->y,work1);CHKERRQ(ierr);
1366   ierr = VecAXPBY(work1,1.0/nu,-1.0,ilinkD->x);CHKERRQ(ierr);            /* c = b - B'*x        */
1367 
1368   /* First step of algorithm */
1369   ierr  = VecNorm(work1,NORM_2,&beta);CHKERRQ(ierr);                   /* beta = sqrt(nu*c'*c)*/
1370   KSPCheckDot(ksp,beta);
1371   beta  = PetscSqrtReal(nu)*beta;
1372   ierr  = VecAXPBY(v,nu/beta,0.0,work1);CHKERRQ(ierr);                   /* v = nu/beta *c      */
1373   ierr  = MatMult(jac->B,v,work2);CHKERRQ(ierr);                       /* u = H^{-1}*B*v      */
1374   ierr  = PetscLogEventBegin(ilinkA->event,ksp,work2,u,NULL);CHKERRQ(ierr);
1375   ierr  = KSPSolve(ksp,work2,u);CHKERRQ(ierr);
1376   ierr  = KSPCheckSolve(ksp,pc,u);CHKERRQ(ierr);
1377   ierr  = PetscLogEventEnd(ilinkA->event,ksp,work2,u,NULL);CHKERRQ(ierr);
1378   ierr  = MatMult(jac->H,u,Hu);CHKERRQ(ierr);                          /* alpha = u'*H*u      */
1379   ierr  = VecDot(Hu,u,&alpha);CHKERRQ(ierr);
1380   KSPCheckDot(ksp,alpha);
1381   if (PetscRealPart(alpha) <= 0.0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_NOT_CONVERGED,"GKB preconditioner diverged, H is not positive definite");
1382   alpha = PetscSqrtReal(PetscAbsScalar(alpha));
1383   ierr  = VecScale(u,1.0/alpha);CHKERRQ(ierr);
1384   ierr  = VecAXPBY(d,1.0/alpha,0.0,v);CHKERRQ(ierr);                       /* v = nu/beta *c      */
1385 
1386   z = beta/alpha;
1387   vecz[1] = z;
1388 
1389   /* Computation of first iterate x(1) and p(1) */
1390   ierr = VecAXPY(ilinkA->y,z,u);CHKERRQ(ierr);
1391   ierr = VecCopy(d,ilinkD->y);CHKERRQ(ierr);
1392   ierr = VecScale(ilinkD->y,-z);CHKERRQ(ierr);
1393 
1394   iterGKB = 1; lowbnd = 2*jac->gkbtol;
1395   if (jac->gkbmonitor) {
1396       ierr = PetscViewerASCIIPrintf(jac->gkbviewer,"%3D GKB Lower bound estimate %14.12e\n",iterGKB,lowbnd);CHKERRQ(ierr);
1397   }
1398 
1399   while (iterGKB < jac->gkbmaxit && lowbnd > jac->gkbtol) {
1400     iterGKB += 1;
1401     ierr  = MatMultHermitianTranspose(jac->B,u,work1);CHKERRQ(ierr); /* v <- nu*(B'*u-alpha/nu*v) */
1402     ierr  = VecAXPBY(v,nu,-alpha,work1);CHKERRQ(ierr);
1403     ierr  = VecNorm(v,NORM_2,&beta);CHKERRQ(ierr);                   /* beta = sqrt(nu)*v'*v      */
1404     beta  = beta/PetscSqrtReal(nu);
1405     ierr  = VecScale(v,1.0/beta);CHKERRQ(ierr);
1406     ierr  = MatMult(jac->B,v,work2);CHKERRQ(ierr);                  /* u <- H^{-1}*(B*v-beta*H*u) */
1407     ierr  = MatMult(jac->H,u,Hu);CHKERRQ(ierr);
1408     ierr  = VecAXPY(work2,-beta,Hu);CHKERRQ(ierr);
1409     ierr  = PetscLogEventBegin(ilinkA->event,ksp,work2,u,NULL);CHKERRQ(ierr);
1410     ierr  = KSPSolve(ksp,work2,u);CHKERRQ(ierr);
1411     ierr  = KSPCheckSolve(ksp,pc,u);CHKERRQ(ierr);
1412     ierr  = PetscLogEventEnd(ilinkA->event,ksp,work2,u,NULL);CHKERRQ(ierr);
1413     ierr  = MatMult(jac->H,u,Hu);CHKERRQ(ierr);                      /* alpha = u'*H*u            */
1414     ierr  = VecDot(Hu,u,&alpha);CHKERRQ(ierr);
1415     KSPCheckDot(ksp,alpha);
1416     if (PetscRealPart(alpha) <= 0.0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_NOT_CONVERGED,"GKB preconditioner diverged, H is not positive definite");
1417     alpha = PetscSqrtReal(PetscAbsScalar(alpha));
1418     ierr  = VecScale(u,1.0/alpha);CHKERRQ(ierr);
1419 
1420     z = -beta/alpha*z;                                            /* z <- beta/alpha*z     */
1421     vecz[0] = z;
1422 
1423     /* Computation of new iterate x(i+1) and p(i+1) */
1424     ierr = VecAXPBY(d,1.0/alpha,-beta/alpha,v);CHKERRQ(ierr);       /* d = (v-beta*d)/alpha */
1425     ierr = VecAXPY(ilinkA->y,z,u);CHKERRQ(ierr);                  /* r = r + z*u          */
1426     ierr = VecAXPY(ilinkD->y,-z,d);CHKERRQ(ierr);                 /* p = p - z*d          */
1427     ierr = MatMult(jac->H,ilinkA->y,Hu);CHKERRQ(ierr);            /* ||u||_H = u'*H*u     */
1428     ierr = VecDot(Hu,ilinkA->y,&nrmz2);CHKERRQ(ierr);
1429 
1430     /* Compute Lower Bound estimate */
1431     if (iterGKB > jac->gkbdelay) {
1432       lowbnd = 0.0;
1433       for (j=0; j<jac->gkbdelay; j++) {
1434         lowbnd += PetscAbsScalar(vecz[j]*vecz[j]);
1435       }
1436       lowbnd = PetscSqrtReal(lowbnd/PetscAbsScalar(nrmz2));
1437     }
1438 
1439     for (j=0; j<jac->gkbdelay-1; j++) {
1440       vecz[jac->gkbdelay-j-1] = vecz[jac->gkbdelay-j-2];
1441     }
1442     if (jac->gkbmonitor) {
1443       ierr = PetscViewerASCIIPrintf(jac->gkbviewer,"%3D GKB Lower bound estimate %14.12e\n",iterGKB,lowbnd);CHKERRQ(ierr);
1444     }
1445   }
1446 
1447   ierr = VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1448   ierr = VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1449   ierr = VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1450   ierr = VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1451 
1452   PetscFunctionReturn(0);
1453 }
1454 
1455 #define FieldSplitSplitSolveAddTranspose(ilink,xx,yy) \
1456   (VecScatterBegin(ilink->sctx,xx,ilink->y,INSERT_VALUES,SCATTER_FORWARD) || \
1457    VecScatterEnd(ilink->sctx,xx,ilink->y,INSERT_VALUES,SCATTER_FORWARD) || \
1458    PetscLogEventBegin(ilink->event,ilink->ksp,ilink->y,ilink->x,NULL) || \
1459    KSPSolveTranspose(ilink->ksp,ilink->y,ilink->x) ||                  \
1460    KSPCheckSolve(ilink->ksp,pc,ilink->x) || \
1461    PetscLogEventEnd(ilink->event,ilink->ksp,ilink->y,ilink->x,NULL) ||   \
1462    VecScatterBegin(ilink->sctx,ilink->x,yy,ADD_VALUES,SCATTER_REVERSE) || \
1463    VecScatterEnd(ilink->sctx,ilink->x,yy,ADD_VALUES,SCATTER_REVERSE))
1464 
1465 static PetscErrorCode PCApplyTranspose_FieldSplit(PC pc,Vec x,Vec y)
1466 {
1467   PC_FieldSplit      *jac = (PC_FieldSplit*)pc->data;
1468   PetscErrorCode     ierr;
1469   PC_FieldSplitLink  ilink = jac->head;
1470   PetscInt           bs;
1471 
1472   PetscFunctionBegin;
1473   if (jac->type == PC_COMPOSITE_ADDITIVE) {
1474     if (jac->defaultsplit) {
1475       ierr = VecGetBlockSize(x,&bs);CHKERRQ(ierr);
1476       if (jac->bs > 0 && bs != jac->bs) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Blocksize of x vector %D does not match fieldsplit blocksize %D",bs,jac->bs);
1477       ierr = VecGetBlockSize(y,&bs);CHKERRQ(ierr);
1478       if (jac->bs > 0 && bs != jac->bs) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Blocksize of y vector %D does not match fieldsplit blocksize %D",bs,jac->bs);
1479       ierr = VecStrideGatherAll(x,jac->x,INSERT_VALUES);CHKERRQ(ierr);
1480       while (ilink) {
1481         ierr = PetscLogEventBegin(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
1482         ierr = KSPSolveTranspose(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
1483         ierr = KSPCheckSolve(ilink->ksp,pc,ilink->y);CHKERRQ(ierr);
1484         ierr = PetscLogEventEnd(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
1485         ilink = ilink->next;
1486       }
1487       ierr = VecStrideScatterAll(jac->y,y,INSERT_VALUES);CHKERRQ(ierr);
1488     } else {
1489       ierr = VecSet(y,0.0);CHKERRQ(ierr);
1490       while (ilink) {
1491         ierr = FieldSplitSplitSolveAddTranspose(ilink,x,y);CHKERRQ(ierr);
1492         ilink = ilink->next;
1493       }
1494     }
1495   } else {
1496     if (!jac->w1) {
1497       ierr = VecDuplicate(x,&jac->w1);CHKERRQ(ierr);
1498       ierr = VecDuplicate(x,&jac->w2);CHKERRQ(ierr);
1499     }
1500     ierr = VecSet(y,0.0);CHKERRQ(ierr);
1501     if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
1502       ierr = FieldSplitSplitSolveAddTranspose(ilink,x,y);CHKERRQ(ierr);
1503       while (ilink->next) {
1504         ilink = ilink->next;
1505         ierr  = MatMultTranspose(pc->mat,y,jac->w1);CHKERRQ(ierr);
1506         ierr  = VecWAXPY(jac->w2,-1.0,jac->w1,x);CHKERRQ(ierr);
1507         ierr  = FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);CHKERRQ(ierr);
1508       }
1509       while (ilink->previous) {
1510         ilink = ilink->previous;
1511         ierr  = MatMultTranspose(pc->mat,y,jac->w1);CHKERRQ(ierr);
1512         ierr  = VecWAXPY(jac->w2,-1.0,jac->w1,x);CHKERRQ(ierr);
1513         ierr  = FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);CHKERRQ(ierr);
1514       }
1515     } else {
1516       while (ilink->next) {   /* get to last entry in linked list */
1517         ilink = ilink->next;
1518       }
1519       ierr = FieldSplitSplitSolveAddTranspose(ilink,x,y);CHKERRQ(ierr);
1520       while (ilink->previous) {
1521         ilink = ilink->previous;
1522         ierr  = MatMultTranspose(pc->mat,y,jac->w1);CHKERRQ(ierr);
1523         ierr  = VecWAXPY(jac->w2,-1.0,jac->w1,x);CHKERRQ(ierr);
1524         ierr  = FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);CHKERRQ(ierr);
1525       }
1526     }
1527   }
1528   PetscFunctionReturn(0);
1529 }
1530 
1531 static PetscErrorCode PCReset_FieldSplit(PC pc)
1532 {
1533   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
1534   PetscErrorCode    ierr;
1535   PC_FieldSplitLink ilink = jac->head,next;
1536 
1537   PetscFunctionBegin;
1538   while (ilink) {
1539     ierr  = KSPDestroy(&ilink->ksp);CHKERRQ(ierr);
1540     ierr  = VecDestroy(&ilink->x);CHKERRQ(ierr);
1541     ierr  = VecDestroy(&ilink->y);CHKERRQ(ierr);
1542     ierr  = VecDestroy(&ilink->z);CHKERRQ(ierr);
1543     ierr  = VecScatterDestroy(&ilink->sctx);CHKERRQ(ierr);
1544     ierr  = ISDestroy(&ilink->is);CHKERRQ(ierr);
1545     ierr  = ISDestroy(&ilink->is_col);CHKERRQ(ierr);
1546     ierr  = PetscFree(ilink->splitname);CHKERRQ(ierr);
1547     ierr  = PetscFree(ilink->fields);CHKERRQ(ierr);
1548     ierr  = PetscFree(ilink->fields_col);CHKERRQ(ierr);
1549     next  = ilink->next;
1550     ierr  = PetscFree(ilink);CHKERRQ(ierr);
1551     ilink = next;
1552   }
1553   jac->head = NULL;
1554   ierr = PetscFree2(jac->x,jac->y);CHKERRQ(ierr);
1555   if (jac->mat && jac->mat != jac->pmat) {
1556     ierr = MatDestroyMatrices(jac->nsplits,&jac->mat);CHKERRQ(ierr);
1557   } else if (jac->mat) {
1558     jac->mat = NULL;
1559   }
1560   if (jac->pmat) {ierr = MatDestroyMatrices(jac->nsplits,&jac->pmat);CHKERRQ(ierr);}
1561   if (jac->Afield) {ierr = MatDestroyMatrices(jac->nsplits,&jac->Afield);CHKERRQ(ierr);}
1562   jac->nsplits = 0;
1563   ierr = VecDestroy(&jac->w1);CHKERRQ(ierr);
1564   ierr = VecDestroy(&jac->w2);CHKERRQ(ierr);
1565   ierr = MatDestroy(&jac->schur);CHKERRQ(ierr);
1566   ierr = MatDestroy(&jac->schurp);CHKERRQ(ierr);
1567   ierr = MatDestroy(&jac->schur_user);CHKERRQ(ierr);
1568   ierr = KSPDestroy(&jac->kspschur);CHKERRQ(ierr);
1569   ierr = KSPDestroy(&jac->kspupper);CHKERRQ(ierr);
1570   ierr = MatDestroy(&jac->B);CHKERRQ(ierr);
1571   ierr = MatDestroy(&jac->C);CHKERRQ(ierr);
1572   ierr = MatDestroy(&jac->H);CHKERRQ(ierr);
1573   ierr = VecDestroy(&jac->u);CHKERRQ(ierr);
1574   ierr = VecDestroy(&jac->v);CHKERRQ(ierr);
1575   ierr = VecDestroy(&jac->Hu);CHKERRQ(ierr);
1576   ierr = VecDestroy(&jac->d);CHKERRQ(ierr);
1577   ierr = PetscFree(jac->vecz);CHKERRQ(ierr);
1578   ierr = PetscViewerDestroy(&jac->gkbviewer);CHKERRQ(ierr);
1579   jac->isrestrict = PETSC_FALSE;
1580   PetscFunctionReturn(0);
1581 }
1582 
1583 static PetscErrorCode PCDestroy_FieldSplit(PC pc)
1584 {
1585   PetscErrorCode    ierr;
1586 
1587   PetscFunctionBegin;
1588   ierr = PCReset_FieldSplit(pc);CHKERRQ(ierr);
1589   ierr = PetscFree(pc->data);CHKERRQ(ierr);
1590   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSchurGetSubKSP_C",NULL);CHKERRQ(ierr);
1591   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitGetSubKSP_C",NULL);CHKERRQ(ierr);
1592   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetFields_C",NULL);CHKERRQ(ierr);
1593   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetIS_C",NULL);CHKERRQ(ierr);
1594   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetType_C",NULL);CHKERRQ(ierr);
1595   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetBlockSize_C",NULL);CHKERRQ(ierr);
1596   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetSchurPre_C",NULL);CHKERRQ(ierr);
1597   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitGetSchurPre_C",NULL);CHKERRQ(ierr);
1598   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetSchurFactType_C",NULL);CHKERRQ(ierr);
1599   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitRestrictIS_C",NULL);CHKERRQ(ierr);
1600   PetscFunctionReturn(0);
1601 }
1602 
1603 static PetscErrorCode PCSetFromOptions_FieldSplit(PetscOptionItems *PetscOptionsObject,PC pc)
1604 {
1605   PetscErrorCode  ierr;
1606   PetscInt        bs;
1607   PetscBool       flg;
1608   PC_FieldSplit   *jac = (PC_FieldSplit*)pc->data;
1609   PCCompositeType ctype;
1610 
1611   PetscFunctionBegin;
1612   ierr = PetscOptionsHead(PetscOptionsObject,"FieldSplit options");CHKERRQ(ierr);
1613   ierr = PetscOptionsBool("-pc_fieldsplit_dm_splits","Whether to use DMCreateFieldDecomposition() for splits","PCFieldSplitSetDMSplits",jac->dm_splits,&jac->dm_splits,NULL);CHKERRQ(ierr);
1614   ierr = PetscOptionsInt("-pc_fieldsplit_block_size","Blocksize that defines number of fields","PCFieldSplitSetBlockSize",jac->bs,&bs,&flg);CHKERRQ(ierr);
1615   if (flg) {
1616     ierr = PCFieldSplitSetBlockSize(pc,bs);CHKERRQ(ierr);
1617   }
1618   jac->diag_use_amat = pc->useAmat;
1619   ierr = PetscOptionsBool("-pc_fieldsplit_diag_use_amat","Use Amat (not Pmat) to extract diagonal fieldsplit blocks", "PCFieldSplitSetDiagUseAmat",jac->diag_use_amat,&jac->diag_use_amat,NULL);CHKERRQ(ierr);
1620   jac->offdiag_use_amat = pc->useAmat;
1621   ierr = PetscOptionsBool("-pc_fieldsplit_off_diag_use_amat","Use Amat (not Pmat) to extract off-diagonal fieldsplit blocks", "PCFieldSplitSetOffDiagUseAmat",jac->offdiag_use_amat,&jac->offdiag_use_amat,NULL);CHKERRQ(ierr);
1622   ierr = PetscOptionsBool("-pc_fieldsplit_detect_saddle_point","Form 2-way split by detecting zero diagonal entries", "PCFieldSplitSetDetectSaddlePoint",jac->detect,&jac->detect,NULL);CHKERRQ(ierr);
1623   ierr = PCFieldSplitSetDetectSaddlePoint(pc,jac->detect);CHKERRQ(ierr); /* Sets split type and Schur PC type */
1624   ierr = PetscOptionsEnum("-pc_fieldsplit_type","Type of composition","PCFieldSplitSetType",PCCompositeTypes,(PetscEnum)jac->type,(PetscEnum*)&ctype,&flg);CHKERRQ(ierr);
1625   if (flg) {
1626     ierr = PCFieldSplitSetType(pc,ctype);CHKERRQ(ierr);
1627   }
1628   /* Only setup fields once */
1629   if ((jac->bs > 0) && (jac->nsplits == 0)) {
1630     /* only allow user to set fields from command line if bs is already known.
1631        otherwise user can set them in PCFieldSplitSetDefaults() */
1632     ierr = PCFieldSplitSetRuntimeSplits_Private(pc);CHKERRQ(ierr);
1633     if (jac->splitdefined) {ierr = PetscInfo(pc,"Splits defined using the options database\n");CHKERRQ(ierr);}
1634   }
1635   if (jac->type == PC_COMPOSITE_SCHUR) {
1636     ierr = PetscOptionsGetEnum(((PetscObject)pc)->options,((PetscObject)pc)->prefix,"-pc_fieldsplit_schur_factorization_type",PCFieldSplitSchurFactTypes,(PetscEnum*)&jac->schurfactorization,&flg);CHKERRQ(ierr);
1637     if (flg) {ierr = PetscInfo(pc,"Deprecated use of -pc_fieldsplit_schur_factorization_type\n");CHKERRQ(ierr);}
1638     ierr = PetscOptionsEnum("-pc_fieldsplit_schur_fact_type","Which off-diagonal parts of the block factorization to use","PCFieldSplitSetSchurFactType",PCFieldSplitSchurFactTypes,(PetscEnum)jac->schurfactorization,(PetscEnum*)&jac->schurfactorization,NULL);CHKERRQ(ierr);
1639     ierr = PetscOptionsEnum("-pc_fieldsplit_schur_precondition","How to build preconditioner for Schur complement","PCFieldSplitSetSchurPre",PCFieldSplitSchurPreTypes,(PetscEnum)jac->schurpre,(PetscEnum*)&jac->schurpre,NULL);CHKERRQ(ierr);
1640     ierr = PetscOptionsScalar("-pc_fieldsplit_schur_scale","Scale Schur complement","PCFieldSplitSetSchurScale",jac->schurscale,&jac->schurscale,NULL);CHKERRQ(ierr);
1641   } else if (jac->type == PC_COMPOSITE_GKB) {
1642     ierr = PetscOptionsReal("-pc_fieldsplit_gkb_tol","The tolerance for the lower bound stopping criterion","PCFieldSplitGKBTol",jac->gkbtol,&jac->gkbtol,NULL);CHKERRQ(ierr);
1643     ierr = PetscOptionsInt("-pc_fieldsplit_gkb_delay","The delay value for lower bound criterion","PCFieldSplitGKBDelay",jac->gkbdelay,&jac->gkbdelay,NULL);CHKERRQ(ierr);
1644     ierr = PetscOptionsReal("-pc_fieldsplit_gkb_nu","Parameter in augmented Lagrangian approach","PCFieldSplitGKBNu",jac->gkbnu,&jac->gkbnu,NULL);CHKERRQ(ierr);
1645     if (jac->gkbnu < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nu cannot be less than 0: value %f",jac->gkbnu);
1646     ierr = PetscOptionsInt("-pc_fieldsplit_gkb_maxit","Maximum allowed number of iterations","PCFieldSplitGKBMaxit",jac->gkbmaxit,&jac->gkbmaxit,NULL);CHKERRQ(ierr);
1647     ierr = PetscOptionsBool("-pc_fieldsplit_gkb_monitor","Prints number of GKB iterations and error","PCFieldSplitGKB",jac->gkbmonitor,&jac->gkbmonitor,NULL);CHKERRQ(ierr);
1648   }
1649   ierr = PetscOptionsTail();CHKERRQ(ierr);
1650   PetscFunctionReturn(0);
1651 }
1652 
1653 /*------------------------------------------------------------------------------------*/
1654 
1655 static PetscErrorCode  PCFieldSplitSetFields_FieldSplit(PC pc,const char splitname[],PetscInt n,const PetscInt *fields,const PetscInt *fields_col)
1656 {
1657   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
1658   PetscErrorCode    ierr;
1659   PC_FieldSplitLink ilink,next = jac->head;
1660   char              prefix[128];
1661   PetscInt          i;
1662 
1663   PetscFunctionBegin;
1664   if (jac->splitdefined) {
1665     ierr = PetscInfo1(pc,"Ignoring new split \"%s\" because the splits have already been defined\n",splitname);CHKERRQ(ierr);
1666     PetscFunctionReturn(0);
1667   }
1668   for (i=0; i<n; i++) {
1669     if (fields[i] >= jac->bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Field %D requested but only %D exist",fields[i],jac->bs);
1670     if (fields[i] < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative field %D requested",fields[i]);
1671   }
1672   ierr = PetscNew(&ilink);CHKERRQ(ierr);
1673   if (splitname) {
1674     ierr = PetscStrallocpy(splitname,&ilink->splitname);CHKERRQ(ierr);
1675   } else {
1676     ierr = PetscMalloc1(3,&ilink->splitname);CHKERRQ(ierr);
1677     ierr = PetscSNPrintf(ilink->splitname,2,"%s",jac->nsplits);CHKERRQ(ierr);
1678   }
1679   ilink->event = jac->nsplits < 5 ? KSP_Solve_FS_0 + jac->nsplits : KSP_Solve_FS_0 + 4; /* Any split great than 4 gets logged in the 4th split */
1680   ierr = PetscMalloc1(n,&ilink->fields);CHKERRQ(ierr);
1681   ierr = PetscArraycpy(ilink->fields,fields,n);CHKERRQ(ierr);
1682   ierr = PetscMalloc1(n,&ilink->fields_col);CHKERRQ(ierr);
1683   ierr = PetscArraycpy(ilink->fields_col,fields_col,n);CHKERRQ(ierr);
1684 
1685   ilink->nfields = n;
1686   ilink->next    = NULL;
1687   ierr           = KSPCreate(PetscObjectComm((PetscObject)pc),&ilink->ksp);CHKERRQ(ierr);
1688   ierr           = KSPSetErrorIfNotConverged(ilink->ksp,pc->erroriffailure);CHKERRQ(ierr);
1689   ierr           = PetscObjectIncrementTabLevel((PetscObject)ilink->ksp,(PetscObject)pc,1);CHKERRQ(ierr);
1690   ierr           = KSPSetType(ilink->ksp,KSPPREONLY);CHKERRQ(ierr);
1691   ierr           = PetscLogObjectParent((PetscObject)pc,(PetscObject)ilink->ksp);CHKERRQ(ierr);
1692 
1693   ierr = PetscSNPrintf(prefix,sizeof(prefix),"%sfieldsplit_%s_",((PetscObject)pc)->prefix ? ((PetscObject)pc)->prefix : "",ilink->splitname);CHKERRQ(ierr);
1694   ierr = KSPSetOptionsPrefix(ilink->ksp,prefix);CHKERRQ(ierr);
1695 
1696   if (!next) {
1697     jac->head       = ilink;
1698     ilink->previous = NULL;
1699   } else {
1700     while (next->next) {
1701       next = next->next;
1702     }
1703     next->next      = ilink;
1704     ilink->previous = next;
1705   }
1706   jac->nsplits++;
1707   PetscFunctionReturn(0);
1708 }
1709 
1710 static PetscErrorCode  PCFieldSplitSchurGetSubKSP_FieldSplit(PC pc,PetscInt *n,KSP **subksp)
1711 {
1712   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
1713   PetscErrorCode ierr;
1714 
1715   PetscFunctionBegin;
1716   *subksp = NULL;
1717   if (n) *n = 0;
1718   if (jac->type == PC_COMPOSITE_SCHUR) {
1719     PetscInt nn;
1720 
1721     if (!jac->schur) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must call KSPSetUp() or PCSetUp() before calling PCFieldSplitSchurGetSubKSP()");
1722     if (jac->nsplits != 2) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Unexpected number of splits %D != 2",jac->nsplits);
1723     nn   = jac->nsplits + (jac->kspupper != jac->head->ksp ? 1 : 0);
1724     ierr = PetscMalloc1(nn,subksp);CHKERRQ(ierr);
1725     (*subksp)[0] = jac->head->ksp;
1726     (*subksp)[1] = jac->kspschur;
1727     if (jac->kspupper != jac->head->ksp) (*subksp)[2] = jac->kspupper;
1728     if (n) *n = nn;
1729   }
1730   PetscFunctionReturn(0);
1731 }
1732 
1733 static PetscErrorCode  PCFieldSplitGetSubKSP_FieldSplit_Schur(PC pc,PetscInt *n,KSP **subksp)
1734 {
1735   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
1736   PetscErrorCode ierr;
1737 
1738   PetscFunctionBegin;
1739   if (!jac->schur) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must call KSPSetUp() or PCSetUp() before calling PCFieldSplitGetSubKSP()");
1740   ierr = PetscMalloc1(jac->nsplits,subksp);CHKERRQ(ierr);
1741   ierr = MatSchurComplementGetKSP(jac->schur,*subksp);CHKERRQ(ierr);
1742 
1743   (*subksp)[1] = jac->kspschur;
1744   if (n) *n = jac->nsplits;
1745   PetscFunctionReturn(0);
1746 }
1747 
1748 static PetscErrorCode  PCFieldSplitGetSubKSP_FieldSplit(PC pc,PetscInt *n,KSP **subksp)
1749 {
1750   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
1751   PetscErrorCode    ierr;
1752   PetscInt          cnt   = 0;
1753   PC_FieldSplitLink ilink = jac->head;
1754 
1755   PetscFunctionBegin;
1756   ierr = PetscMalloc1(jac->nsplits,subksp);CHKERRQ(ierr);
1757   while (ilink) {
1758     (*subksp)[cnt++] = ilink->ksp;
1759     ilink            = ilink->next;
1760   }
1761   if (cnt != jac->nsplits) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Corrupt PCFIELDSPLIT object: number of splits in linked list %D does not match number in object %D",cnt,jac->nsplits);
1762   if (n) *n = jac->nsplits;
1763   PetscFunctionReturn(0);
1764 }
1765 
1766 /*@C
1767     PCFieldSplitRestrictIS - Restricts the fieldsplit ISs to be within a given IS.
1768 
1769     Input Parameters:
1770 +   pc  - the preconditioner context
1771 -   is - the index set that defines the indices to which the fieldsplit is to be restricted
1772 
1773     Level: advanced
1774 
1775 @*/
1776 PetscErrorCode  PCFieldSplitRestrictIS(PC pc,IS isy)
1777 {
1778   PetscErrorCode ierr;
1779 
1780   PetscFunctionBegin;
1781   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1782   PetscValidHeaderSpecific(isy,IS_CLASSID,2);
1783   ierr = PetscTryMethod(pc,"PCFieldSplitRestrictIS_C",(PC,IS),(pc,isy));CHKERRQ(ierr);
1784   PetscFunctionReturn(0);
1785 }
1786 
1787 static PetscErrorCode  PCFieldSplitRestrictIS_FieldSplit(PC pc, IS isy)
1788 {
1789   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
1790   PetscErrorCode    ierr;
1791   PC_FieldSplitLink ilink = jac->head, next;
1792   PetscInt          localsize,size,sizez,i;
1793   const PetscInt    *ind, *indz;
1794   PetscInt          *indc, *indcz;
1795   PetscBool         flg;
1796 
1797   PetscFunctionBegin;
1798   ierr = ISGetLocalSize(isy,&localsize);CHKERRQ(ierr);
1799   ierr = MPI_Scan(&localsize,&size,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)isy));CHKERRMPI(ierr);
1800   size -= localsize;
1801   while (ilink) {
1802     IS isrl,isr;
1803     PC subpc;
1804     ierr          = ISEmbed(ilink->is, isy, PETSC_TRUE, &isrl);CHKERRQ(ierr);
1805     ierr          = ISGetLocalSize(isrl,&localsize);CHKERRQ(ierr);
1806     ierr          = PetscMalloc1(localsize,&indc);CHKERRQ(ierr);
1807     ierr          = ISGetIndices(isrl,&ind);CHKERRQ(ierr);
1808     ierr          = PetscArraycpy(indc,ind,localsize);CHKERRQ(ierr);
1809     ierr          = ISRestoreIndices(isrl,&ind);CHKERRQ(ierr);
1810     ierr          = ISDestroy(&isrl);CHKERRQ(ierr);
1811     for (i=0; i<localsize; i++) *(indc+i) += size;
1812     ierr          = ISCreateGeneral(PetscObjectComm((PetscObject)isy),localsize,indc,PETSC_OWN_POINTER,&isr);CHKERRQ(ierr);
1813     ierr          = PetscObjectReference((PetscObject)isr);CHKERRQ(ierr);
1814     ierr          = ISDestroy(&ilink->is);CHKERRQ(ierr);
1815     ilink->is     = isr;
1816     ierr          = PetscObjectReference((PetscObject)isr);CHKERRQ(ierr);
1817     ierr          = ISDestroy(&ilink->is_col);CHKERRQ(ierr);
1818     ilink->is_col = isr;
1819     ierr          = ISDestroy(&isr);CHKERRQ(ierr);
1820     ierr          = KSPGetPC(ilink->ksp, &subpc);CHKERRQ(ierr);
1821     ierr          = PetscObjectTypeCompare((PetscObject)subpc,PCFIELDSPLIT,&flg);CHKERRQ(ierr);
1822     if (flg) {
1823       IS iszl,isz;
1824       MPI_Comm comm;
1825       ierr   = ISGetLocalSize(ilink->is,&localsize);CHKERRQ(ierr);
1826       comm   = PetscObjectComm((PetscObject)ilink->is);
1827       ierr   = ISEmbed(isy, ilink->is, PETSC_TRUE, &iszl);CHKERRQ(ierr);
1828       ierr   = MPI_Scan(&localsize,&sizez,1,MPIU_INT,MPI_SUM,comm);CHKERRMPI(ierr);
1829       sizez -= localsize;
1830       ierr   = ISGetLocalSize(iszl,&localsize);CHKERRQ(ierr);
1831       ierr   = PetscMalloc1(localsize,&indcz);CHKERRQ(ierr);
1832       ierr   = ISGetIndices(iszl,&indz);CHKERRQ(ierr);
1833       ierr   = PetscArraycpy(indcz,indz,localsize);CHKERRQ(ierr);
1834       ierr   = ISRestoreIndices(iszl,&indz);CHKERRQ(ierr);
1835       ierr   = ISDestroy(&iszl);CHKERRQ(ierr);
1836       for (i=0; i<localsize; i++) *(indcz+i) += sizez;
1837       ierr   = ISCreateGeneral(comm,localsize,indcz,PETSC_OWN_POINTER,&isz);CHKERRQ(ierr);
1838       ierr   = PCFieldSplitRestrictIS(subpc,isz);CHKERRQ(ierr);
1839       ierr   = ISDestroy(&isz);CHKERRQ(ierr);
1840     }
1841     next = ilink->next;
1842     ilink = next;
1843   }
1844   jac->isrestrict = PETSC_TRUE;
1845   PetscFunctionReturn(0);
1846 }
1847 
1848 static PetscErrorCode  PCFieldSplitSetIS_FieldSplit(PC pc,const char splitname[],IS is)
1849 {
1850   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
1851   PetscErrorCode    ierr;
1852   PC_FieldSplitLink ilink, next = jac->head;
1853   char              prefix[128];
1854 
1855   PetscFunctionBegin;
1856   if (jac->splitdefined) {
1857     ierr = PetscInfo1(pc,"Ignoring new split \"%s\" because the splits have already been defined\n",splitname);CHKERRQ(ierr);
1858     PetscFunctionReturn(0);
1859   }
1860   ierr = PetscNew(&ilink);CHKERRQ(ierr);
1861   if (splitname) {
1862     ierr = PetscStrallocpy(splitname,&ilink->splitname);CHKERRQ(ierr);
1863   } else {
1864     ierr = PetscMalloc1(8,&ilink->splitname);CHKERRQ(ierr);
1865     ierr = PetscSNPrintf(ilink->splitname,7,"%D",jac->nsplits);CHKERRQ(ierr);
1866   }
1867   ilink->event  = jac->nsplits < 5 ? KSP_Solve_FS_0 + jac->nsplits : KSP_Solve_FS_0 + 4; /* Any split great than 4 gets logged in the 4th split */
1868   ierr          = PetscObjectReference((PetscObject)is);CHKERRQ(ierr);
1869   ierr          = ISDestroy(&ilink->is);CHKERRQ(ierr);
1870   ilink->is     = is;
1871   ierr          = PetscObjectReference((PetscObject)is);CHKERRQ(ierr);
1872   ierr          = ISDestroy(&ilink->is_col);CHKERRQ(ierr);
1873   ilink->is_col = is;
1874   ilink->next   = NULL;
1875   ierr          = KSPCreate(PetscObjectComm((PetscObject)pc),&ilink->ksp);CHKERRQ(ierr);
1876   ierr          = KSPSetErrorIfNotConverged(ilink->ksp,pc->erroriffailure);CHKERRQ(ierr);
1877   ierr          = PetscObjectIncrementTabLevel((PetscObject)ilink->ksp,(PetscObject)pc,1);CHKERRQ(ierr);
1878   ierr          = KSPSetType(ilink->ksp,KSPPREONLY);CHKERRQ(ierr);
1879   ierr          = PetscLogObjectParent((PetscObject)pc,(PetscObject)ilink->ksp);CHKERRQ(ierr);
1880 
1881   ierr = PetscSNPrintf(prefix,sizeof(prefix),"%sfieldsplit_%s_",((PetscObject)pc)->prefix ? ((PetscObject)pc)->prefix : "",ilink->splitname);CHKERRQ(ierr);
1882   ierr = KSPSetOptionsPrefix(ilink->ksp,prefix);CHKERRQ(ierr);
1883 
1884   if (!next) {
1885     jac->head       = ilink;
1886     ilink->previous = NULL;
1887   } else {
1888     while (next->next) {
1889       next = next->next;
1890     }
1891     next->next      = ilink;
1892     ilink->previous = next;
1893   }
1894   jac->nsplits++;
1895   PetscFunctionReturn(0);
1896 }
1897 
1898 /*@C
1899     PCFieldSplitSetFields - Sets the fields for one particular split in the field split preconditioner
1900 
1901     Logically Collective on PC
1902 
1903     Input Parameters:
1904 +   pc  - the preconditioner context
1905 .   splitname - name of this split, if NULL the number of the split is used
1906 .   n - the number of fields in this split
1907 -   fields - the fields in this split
1908 
1909     Level: intermediate
1910 
1911     Notes:
1912     Use PCFieldSplitSetIS() to set a completely general set of indices as a field.
1913 
1914      The PCFieldSplitSetFields() is for defining fields as strided blocks. For example, if the block
1915      size is three then one can define a field as 0, or 1 or 2 or 0,1 or 0,2 or 1,2 which mean
1916      0xx3xx6xx9xx12 ... x1xx4xx7xx ... xx2xx5xx8xx.. 01x34x67x... 0x1x3x5x7.. x12x45x78x....
1917      where the numbered entries indicate what is in the field.
1918 
1919      This function is called once per split (it creates a new split each time).  Solve options
1920      for this split will be available under the prefix -fieldsplit_SPLITNAME_.
1921 
1922      Developer Note: This routine does not actually create the IS representing the split, that is delayed
1923      until PCSetUp_FieldSplit(), because information about the vector/matrix layouts may not be
1924      available when this routine is called.
1925 
1926 .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetBlockSize(), PCFieldSplitSetIS()
1927 
1928 @*/
1929 PetscErrorCode  PCFieldSplitSetFields(PC pc,const char splitname[],PetscInt n,const PetscInt *fields,const PetscInt *fields_col)
1930 {
1931   PetscErrorCode ierr;
1932 
1933   PetscFunctionBegin;
1934   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1935   PetscValidCharPointer(splitname,2);
1936   if (n < 1) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Provided number of fields %D in split \"%s\" not positive",n,splitname);
1937   PetscValidIntPointer(fields,4);
1938   ierr = PetscTryMethod(pc,"PCFieldSplitSetFields_C",(PC,const char[],PetscInt,const PetscInt*,const PetscInt*),(pc,splitname,n,fields,fields_col));CHKERRQ(ierr);
1939   PetscFunctionReturn(0);
1940 }
1941 
1942 /*@
1943     PCFieldSplitSetDiagUseAmat - set flag indicating whether to extract diagonal blocks from Amat (rather than Pmat)
1944 
1945     Logically Collective on PC
1946 
1947     Input Parameters:
1948 +   pc  - the preconditioner object
1949 -   flg - boolean flag indicating whether or not to use Amat to extract the diagonal blocks from
1950 
1951     Options Database:
1952 .     -pc_fieldsplit_diag_use_amat
1953 
1954     Level: intermediate
1955 
1956 .seealso: PCFieldSplitGetDiagUseAmat(), PCFieldSplitSetOffDiagUseAmat(), PCFIELDSPLIT
1957 
1958 @*/
1959 PetscErrorCode  PCFieldSplitSetDiagUseAmat(PC pc,PetscBool flg)
1960 {
1961   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
1962   PetscBool      isfs;
1963   PetscErrorCode ierr;
1964 
1965   PetscFunctionBegin;
1966   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1967   ierr = PetscObjectTypeCompare((PetscObject)pc,PCFIELDSPLIT,&isfs);CHKERRQ(ierr);
1968   if (!isfs) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"PC not of type %s",PCFIELDSPLIT);
1969   jac->diag_use_amat = flg;
1970   PetscFunctionReturn(0);
1971 }
1972 
1973 /*@
1974     PCFieldSplitGetDiagUseAmat - get the flag indicating whether to extract diagonal blocks from Amat (rather than Pmat)
1975 
1976     Logically Collective on PC
1977 
1978     Input Parameters:
1979 .   pc  - the preconditioner object
1980 
1981     Output Parameters:
1982 .   flg - boolean flag indicating whether or not to use Amat to extract the diagonal blocks from
1983 
1984     Level: intermediate
1985 
1986 .seealso: PCFieldSplitSetDiagUseAmat(), PCFieldSplitGetOffDiagUseAmat(), PCFIELDSPLIT
1987 
1988 @*/
1989 PetscErrorCode  PCFieldSplitGetDiagUseAmat(PC pc,PetscBool *flg)
1990 {
1991   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
1992   PetscBool      isfs;
1993   PetscErrorCode ierr;
1994 
1995   PetscFunctionBegin;
1996   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1997   PetscValidBoolPointer(flg,2);
1998   ierr = PetscObjectTypeCompare((PetscObject)pc,PCFIELDSPLIT,&isfs);CHKERRQ(ierr);
1999   if (!isfs) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"PC not of type %s",PCFIELDSPLIT);
2000   *flg = jac->diag_use_amat;
2001   PetscFunctionReturn(0);
2002 }
2003 
2004 /*@
2005     PCFieldSplitSetOffDiagUseAmat - set flag indicating whether to extract off-diagonal blocks from Amat (rather than Pmat)
2006 
2007     Logically Collective on PC
2008 
2009     Input Parameters:
2010 +   pc  - the preconditioner object
2011 -   flg - boolean flag indicating whether or not to use Amat to extract the off-diagonal blocks from
2012 
2013     Options Database:
2014 .     -pc_fieldsplit_off_diag_use_amat
2015 
2016     Level: intermediate
2017 
2018 .seealso: PCFieldSplitGetOffDiagUseAmat(), PCFieldSplitSetDiagUseAmat(), PCFIELDSPLIT
2019 
2020 @*/
2021 PetscErrorCode  PCFieldSplitSetOffDiagUseAmat(PC pc,PetscBool flg)
2022 {
2023   PC_FieldSplit *jac = (PC_FieldSplit*)pc->data;
2024   PetscBool      isfs;
2025   PetscErrorCode ierr;
2026 
2027   PetscFunctionBegin;
2028   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2029   ierr = PetscObjectTypeCompare((PetscObject)pc,PCFIELDSPLIT,&isfs);CHKERRQ(ierr);
2030   if (!isfs) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"PC not of type %s",PCFIELDSPLIT);
2031   jac->offdiag_use_amat = flg;
2032   PetscFunctionReturn(0);
2033 }
2034 
2035 /*@
2036     PCFieldSplitGetOffDiagUseAmat - get the flag indicating whether to extract off-diagonal blocks from Amat (rather than Pmat)
2037 
2038     Logically Collective on PC
2039 
2040     Input Parameters:
2041 .   pc  - the preconditioner object
2042 
2043     Output Parameters:
2044 .   flg - boolean flag indicating whether or not to use Amat to extract the off-diagonal blocks from
2045 
2046     Level: intermediate
2047 
2048 .seealso: PCFieldSplitSetOffDiagUseAmat(), PCFieldSplitGetDiagUseAmat(), PCFIELDSPLIT
2049 
2050 @*/
2051 PetscErrorCode  PCFieldSplitGetOffDiagUseAmat(PC pc,PetscBool *flg)
2052 {
2053   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
2054   PetscBool      isfs;
2055   PetscErrorCode ierr;
2056 
2057   PetscFunctionBegin;
2058   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2059   PetscValidBoolPointer(flg,2);
2060   ierr = PetscObjectTypeCompare((PetscObject)pc,PCFIELDSPLIT,&isfs);CHKERRQ(ierr);
2061   if (!isfs) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"PC not of type %s",PCFIELDSPLIT);
2062   *flg = jac->offdiag_use_amat;
2063   PetscFunctionReturn(0);
2064 }
2065 
2066 /*@C
2067     PCFieldSplitSetIS - Sets the exact elements for field
2068 
2069     Logically Collective on PC
2070 
2071     Input Parameters:
2072 +   pc  - the preconditioner context
2073 .   splitname - name of this split, if NULL the number of the split is used
2074 -   is - the index set that defines the vector elements in this field
2075 
2076     Notes:
2077     Use PCFieldSplitSetFields(), for fields defined by strided types.
2078 
2079     This function is called once per split (it creates a new split each time).  Solve options
2080     for this split will be available under the prefix -fieldsplit_SPLITNAME_.
2081 
2082     Level: intermediate
2083 
2084 .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetBlockSize()
2085 
2086 @*/
2087 PetscErrorCode  PCFieldSplitSetIS(PC pc,const char splitname[],IS is)
2088 {
2089   PetscErrorCode ierr;
2090 
2091   PetscFunctionBegin;
2092   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2093   if (splitname) PetscValidCharPointer(splitname,2);
2094   PetscValidHeaderSpecific(is,IS_CLASSID,3);
2095   ierr = PetscTryMethod(pc,"PCFieldSplitSetIS_C",(PC,const char[],IS),(pc,splitname,is));CHKERRQ(ierr);
2096   PetscFunctionReturn(0);
2097 }
2098 
2099 /*@C
2100     PCFieldSplitGetIS - Retrieves the elements for a field as an IS
2101 
2102     Logically Collective on PC
2103 
2104     Input Parameters:
2105 +   pc  - the preconditioner context
2106 -   splitname - name of this split
2107 
2108     Output Parameter:
2109 -   is - the index set that defines the vector elements in this field, or NULL if the field is not found
2110 
2111     Level: intermediate
2112 
2113 .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetIS()
2114 
2115 @*/
2116 PetscErrorCode PCFieldSplitGetIS(PC pc,const char splitname[],IS *is)
2117 {
2118   PetscErrorCode ierr;
2119 
2120   PetscFunctionBegin;
2121   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2122   PetscValidCharPointer(splitname,2);
2123   PetscValidPointer(is,3);
2124   {
2125     PC_FieldSplit     *jac  = (PC_FieldSplit*) pc->data;
2126     PC_FieldSplitLink ilink = jac->head;
2127     PetscBool         found;
2128 
2129     *is = NULL;
2130     while (ilink) {
2131       ierr = PetscStrcmp(ilink->splitname, splitname, &found);CHKERRQ(ierr);
2132       if (found) {
2133         *is = ilink->is;
2134         break;
2135       }
2136       ilink = ilink->next;
2137     }
2138   }
2139   PetscFunctionReturn(0);
2140 }
2141 
2142 /*@C
2143     PCFieldSplitGetISByIndex - Retrieves the elements for a given index field as an IS
2144 
2145     Logically Collective on PC
2146 
2147     Input Parameters:
2148 +   pc  - the preconditioner context
2149 -   index - index of this split
2150 
2151     Output Parameter:
2152 -   is - the index set that defines the vector elements in this field
2153 
2154     Level: intermediate
2155 
2156 .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitGetIS(), PCFieldSplitSetIS()
2157 
2158 @*/
2159 PetscErrorCode PCFieldSplitGetISByIndex(PC pc,PetscInt index,IS *is)
2160 {
2161   PetscErrorCode ierr;
2162 
2163   PetscFunctionBegin;
2164   if (index < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative field %D requested",index);
2165   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2166   PetscValidPointer(is,3);
2167   {
2168     PC_FieldSplit     *jac  = (PC_FieldSplit*) pc->data;
2169     PC_FieldSplitLink ilink = jac->head;
2170     PetscInt          i     = 0;
2171     if (index >= jac->nsplits) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Field %D requested but only %D exist",index,jac->nsplits);
2172 
2173     while (i < index) {
2174       ilink = ilink->next;
2175       ++i;
2176     }
2177     ierr = PCFieldSplitGetIS(pc,ilink->splitname,is);CHKERRQ(ierr);
2178   }
2179   PetscFunctionReturn(0);
2180 }
2181 
2182 /*@
2183     PCFieldSplitSetBlockSize - Sets the block size for defining where fields start in the
2184       fieldsplit preconditioner. If not set the matrix block size is used.
2185 
2186     Logically Collective on PC
2187 
2188     Input Parameters:
2189 +   pc  - the preconditioner context
2190 -   bs - the block size
2191 
2192     Level: intermediate
2193 
2194 .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetFields()
2195 
2196 @*/
2197 PetscErrorCode  PCFieldSplitSetBlockSize(PC pc,PetscInt bs)
2198 {
2199   PetscErrorCode ierr;
2200 
2201   PetscFunctionBegin;
2202   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2203   PetscValidLogicalCollectiveInt(pc,bs,2);
2204   ierr = PetscTryMethod(pc,"PCFieldSplitSetBlockSize_C",(PC,PetscInt),(pc,bs));CHKERRQ(ierr);
2205   PetscFunctionReturn(0);
2206 }
2207 
2208 /*@C
2209    PCFieldSplitGetSubKSP - Gets the KSP contexts for all splits
2210 
2211    Collective on KSP
2212 
2213    Input Parameter:
2214 .  pc - the preconditioner context
2215 
2216    Output Parameters:
2217 +  n - the number of splits
2218 -  subksp - the array of KSP contexts
2219 
2220    Note:
2221    After PCFieldSplitGetSubKSP() the array of KSPs is to be freed by the user with PetscFree()
2222    (not the KSP just the array that contains them).
2223 
2224    You must call PCSetUp() before calling PCFieldSplitGetSubKSP().
2225 
2226    If the fieldsplit is of type PC_COMPOSITE_SCHUR, it returns the KSP object used inside the
2227    Schur complement and the KSP object used to iterate over the Schur complement.
2228    To access all the KSP objects used in PC_COMPOSITE_SCHUR, use PCFieldSplitSchurGetSubKSP().
2229 
2230    If the fieldsplit is of type PC_COMPOSITE_GKB, it returns the KSP object used to solve the
2231    inner linear system defined by the matrix H in each loop.
2232 
2233    Fortran Usage: You must pass in a KSP array that is large enough to contain all the local KSPs.
2234       You can call PCFieldSplitGetSubKSP(pc,n,PETSC_NULL_KSP,ierr) to determine how large the
2235       KSP array must be.
2236 
2237    Level: advanced
2238 
2239 .seealso: PCFIELDSPLIT
2240 @*/
2241 PetscErrorCode  PCFieldSplitGetSubKSP(PC pc,PetscInt *n,KSP *subksp[])
2242 {
2243   PetscErrorCode ierr;
2244 
2245   PetscFunctionBegin;
2246   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2247   if (n) PetscValidIntPointer(n,2);
2248   ierr = PetscUseMethod(pc,"PCFieldSplitGetSubKSP_C",(PC,PetscInt*,KSP **),(pc,n,subksp));CHKERRQ(ierr);
2249   PetscFunctionReturn(0);
2250 }
2251 
2252 /*@C
2253    PCFieldSplitSchurGetSubKSP - Gets the KSP contexts used inside the Schur complement based PCFIELDSPLIT
2254 
2255    Collective on KSP
2256 
2257    Input Parameter:
2258 .  pc - the preconditioner context
2259 
2260    Output Parameters:
2261 +  n - the number of splits
2262 -  subksp - the array of KSP contexts
2263 
2264    Note:
2265    After PCFieldSplitSchurGetSubKSP() the array of KSPs is to be freed by the user with PetscFree()
2266    (not the KSP just the array that contains them).
2267 
2268    You must call PCSetUp() before calling PCFieldSplitSchurGetSubKSP().
2269 
2270    If the fieldsplit type is of type PC_COMPOSITE_SCHUR, it returns (in order)
2271    - the KSP used for the (1,1) block
2272    - the KSP used for the Schur complement (not the one used for the interior Schur solver)
2273    - the KSP used for the (1,1) block in the upper triangular factor (if different from that of the (1,1) block).
2274 
2275    It returns a null array if the fieldsplit is not of type PC_COMPOSITE_SCHUR; in this case, you should use PCFieldSplitGetSubKSP().
2276 
2277    Fortran Usage: You must pass in a KSP array that is large enough to contain all the local KSPs.
2278       You can call PCFieldSplitSchurGetSubKSP(pc,n,PETSC_NULL_KSP,ierr) to determine how large the
2279       KSP array must be.
2280 
2281    Level: advanced
2282 
2283 .seealso: PCFIELDSPLIT
2284 @*/
2285 PetscErrorCode  PCFieldSplitSchurGetSubKSP(PC pc,PetscInt *n,KSP *subksp[])
2286 {
2287   PetscErrorCode ierr;
2288 
2289   PetscFunctionBegin;
2290   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2291   if (n) PetscValidIntPointer(n,2);
2292   ierr = PetscUseMethod(pc,"PCFieldSplitSchurGetSubKSP_C",(PC,PetscInt*,KSP **),(pc,n,subksp));CHKERRQ(ierr);
2293   PetscFunctionReturn(0);
2294 }
2295 
2296 /*@
2297     PCFieldSplitSetSchurPre -  Indicates from what operator the preconditioner is constructucted for the Schur complement.
2298       The default is the A11 matrix.
2299 
2300     Collective on PC
2301 
2302     Input Parameters:
2303 +   pc      - the preconditioner context
2304 .   ptype   - which matrix to use for preconditioning the Schur complement: PC_FIELDSPLIT_SCHUR_PRE_A11 (default), PC_FIELDSPLIT_SCHUR_PRE_SELF, PC_FIELDSPLIT_SCHUR_PRE_USER
2305               PC_FIELDSPLIT_SCHUR_PRE_SELFP, and PC_FIELDSPLIT_SCHUR_PRE_FULL
2306 -   userpre - matrix to use for preconditioning, or NULL
2307 
2308     Options Database:
2309 +    -pc_fieldsplit_schur_precondition <self,selfp,user,a11,full> - default is a11. See notes for meaning of various arguments
2310 -    -fieldsplit_1_pc_type <pctype> - the preconditioner algorithm that is used to construct the preconditioner from the operator
2311 
2312     Notes:
2313 $    If ptype is
2314 $        a11 - the preconditioner for the Schur complement is generated from the block diagonal part of the preconditioner
2315 $        matrix associated with the Schur complement (i.e. A11), not the Schur complement matrix
2316 $        self - the preconditioner for the Schur complement is generated from the symbolic representation of the Schur complement matrix:
2317 $             The only preconditioner that currently works with this symbolic respresentation matrix object is the PCLSC
2318 $             preconditioner
2319 $        user - the preconditioner for the Schur complement is generated from the user provided matrix (pre argument
2320 $             to this function).
2321 $        selfp - the preconditioning for the Schur complement is generated from an explicitly-assembled approximation Sp = A11 - A10 inv(diag(A00)) A01
2322 $             This is only a good preconditioner when diag(A00) is a good preconditioner for A00. Optionally, A00 can be
2323 $             lumped before extracting the diagonal using the additional option -fieldsplit_1_mat_schur_complement_ainv_type lump
2324 $        full - the preconditioner for the Schur complement is generated from the exact Schur complement matrix representation computed internally by PCFIELDSPLIT (this is expensive)
2325 $             useful mostly as a test that the Schur complement approach can work for your problem
2326 
2327      When solving a saddle point problem, where the A11 block is identically zero, using a11 as the ptype only makes sense
2328     with the additional option -fieldsplit_1_pc_type none. Usually for saddle point problems one would use a ptype of self and
2329     -fieldsplit_1_pc_type lsc which uses the least squares commutator to compute a preconditioner for the Schur complement.
2330 
2331     Level: intermediate
2332 
2333 .seealso: PCFieldSplitGetSchurPre(), PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetFields(), PCFieldSplitSchurPreType,
2334           MatSchurComplementSetAinvType(), PCLSC
2335 
2336 @*/
2337 PetscErrorCode PCFieldSplitSetSchurPre(PC pc,PCFieldSplitSchurPreType ptype,Mat pre)
2338 {
2339   PetscErrorCode ierr;
2340 
2341   PetscFunctionBegin;
2342   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2343   ierr = PetscTryMethod(pc,"PCFieldSplitSetSchurPre_C",(PC,PCFieldSplitSchurPreType,Mat),(pc,ptype,pre));CHKERRQ(ierr);
2344   PetscFunctionReturn(0);
2345 }
2346 
2347 PetscErrorCode PCFieldSplitSchurPrecondition(PC pc,PCFieldSplitSchurPreType ptype,Mat pre) {return PCFieldSplitSetSchurPre(pc,ptype,pre);} /* Deprecated name */
2348 
2349 /*@
2350     PCFieldSplitGetSchurPre - For Schur complement fieldsplit, determine how the Schur complement will be
2351     preconditioned.  See PCFieldSplitSetSchurPre() for details.
2352 
2353     Logically Collective on PC
2354 
2355     Input Parameters:
2356 .   pc      - the preconditioner context
2357 
2358     Output Parameters:
2359 +   ptype   - which matrix to use for preconditioning the Schur complement: PC_FIELDSPLIT_SCHUR_PRE_A11, PC_FIELDSPLIT_SCHUR_PRE_SELF, PC_FIELDSPLIT_PRE_USER
2360 -   userpre - matrix to use for preconditioning (with PC_FIELDSPLIT_PRE_USER), or NULL
2361 
2362     Level: intermediate
2363 
2364 .seealso: PCFieldSplitSetSchurPre(), PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetFields(), PCFieldSplitSchurPreType, PCLSC
2365 
2366 @*/
2367 PetscErrorCode PCFieldSplitGetSchurPre(PC pc,PCFieldSplitSchurPreType *ptype,Mat *pre)
2368 {
2369   PetscErrorCode ierr;
2370 
2371   PetscFunctionBegin;
2372   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2373   ierr = PetscUseMethod(pc,"PCFieldSplitGetSchurPre_C",(PC,PCFieldSplitSchurPreType*,Mat*),(pc,ptype,pre));CHKERRQ(ierr);
2374   PetscFunctionReturn(0);
2375 }
2376 
2377 /*@
2378     PCFieldSplitSchurGetS -  extract the MatSchurComplement object used by this PC in case it needs to be configured separately
2379 
2380     Not collective
2381 
2382     Input Parameter:
2383 .   pc      - the preconditioner context
2384 
2385     Output Parameter:
2386 .   S       - the Schur complement matrix
2387 
2388     Notes:
2389     This matrix should not be destroyed using MatDestroy(); rather, use PCFieldSplitSchurRestoreS().
2390 
2391     Level: advanced
2392 
2393 .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSchurPreType, PCFieldSplitSetSchurPre(), MatSchurComplement, PCFieldSplitSchurRestoreS()
2394 
2395 @*/
2396 PetscErrorCode  PCFieldSplitSchurGetS(PC pc,Mat *S)
2397 {
2398   PetscErrorCode ierr;
2399   const char*    t;
2400   PetscBool      isfs;
2401   PC_FieldSplit  *jac;
2402 
2403   PetscFunctionBegin;
2404   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2405   ierr = PetscObjectGetType((PetscObject)pc,&t);CHKERRQ(ierr);
2406   ierr = PetscStrcmp(t,PCFIELDSPLIT,&isfs);CHKERRQ(ierr);
2407   if (!isfs) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Expected PC of type PCFIELDSPLIT, got %s instead",t);
2408   jac = (PC_FieldSplit*)pc->data;
2409   if (jac->type != PC_COMPOSITE_SCHUR) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Expected PCFIELDSPLIT of type SCHUR, got %D instead",jac->type);
2410   if (S) *S = jac->schur;
2411   PetscFunctionReturn(0);
2412 }
2413 
2414 /*@
2415     PCFieldSplitSchurRestoreS -  restores the MatSchurComplement object used by this PC
2416 
2417     Not collective
2418 
2419     Input Parameters:
2420 +   pc      - the preconditioner context
2421 -   S       - the Schur complement matrix
2422 
2423     Level: advanced
2424 
2425 .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSchurPreType, PCFieldSplitSetSchurPre(), MatSchurComplement, PCFieldSplitSchurGetS()
2426 
2427 @*/
2428 PetscErrorCode  PCFieldSplitSchurRestoreS(PC pc,Mat *S)
2429 {
2430   PetscErrorCode ierr;
2431   const char*    t;
2432   PetscBool      isfs;
2433   PC_FieldSplit  *jac;
2434 
2435   PetscFunctionBegin;
2436   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2437   ierr = PetscObjectGetType((PetscObject)pc,&t);CHKERRQ(ierr);
2438   ierr = PetscStrcmp(t,PCFIELDSPLIT,&isfs);CHKERRQ(ierr);
2439   if (!isfs) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Expected PC of type PCFIELDSPLIT, got %s instead",t);
2440   jac = (PC_FieldSplit*)pc->data;
2441   if (jac->type != PC_COMPOSITE_SCHUR) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Expected PCFIELDSPLIT of type SCHUR, got %D instead",jac->type);
2442   if (!S || *S != jac->schur) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"MatSchurComplement restored is not the same as gotten");
2443   PetscFunctionReturn(0);
2444 }
2445 
2446 static PetscErrorCode  PCFieldSplitSetSchurPre_FieldSplit(PC pc,PCFieldSplitSchurPreType ptype,Mat pre)
2447 {
2448   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
2449   PetscErrorCode ierr;
2450 
2451   PetscFunctionBegin;
2452   jac->schurpre = ptype;
2453   if (ptype == PC_FIELDSPLIT_SCHUR_PRE_USER && pre) {
2454     ierr            = MatDestroy(&jac->schur_user);CHKERRQ(ierr);
2455     jac->schur_user = pre;
2456     ierr            = PetscObjectReference((PetscObject)jac->schur_user);CHKERRQ(ierr);
2457   }
2458   PetscFunctionReturn(0);
2459 }
2460 
2461 static PetscErrorCode  PCFieldSplitGetSchurPre_FieldSplit(PC pc,PCFieldSplitSchurPreType *ptype,Mat *pre)
2462 {
2463   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
2464 
2465   PetscFunctionBegin;
2466   *ptype = jac->schurpre;
2467   *pre   = jac->schur_user;
2468   PetscFunctionReturn(0);
2469 }
2470 
2471 /*@
2472     PCFieldSplitSetSchurFactType -  sets which blocks of the approximate block factorization to retain in the preconditioner
2473 
2474     Collective on PC
2475 
2476     Input Parameters:
2477 +   pc  - the preconditioner context
2478 -   ftype - which blocks of factorization to retain, PC_FIELDSPLIT_SCHUR_FACT_FULL is default
2479 
2480     Options Database:
2481 .     -pc_fieldsplit_schur_fact_type <diag,lower,upper,full> default is full
2482 
2483     Level: intermediate
2484 
2485     Notes:
2486     The FULL factorization is
2487 
2488 $   (A   B)  = (1       0) (A   0) (1  Ainv*B)  = L D U
2489 $   (C   E)    (C*Ainv  1) (0   S) (0     1)
2490 
2491     where S = E - C*Ainv*B. In practice, the full factorization is applied via block triangular solves with the grouping L*(D*U). UPPER uses D*U, LOWER uses L*D,
2492     and DIAG is the diagonal part with the sign of S flipped (because this makes the preconditioner positive definite for many formulations, thus allowing the use of KSPMINRES). Sign flipping of S can be turned off with PCFieldSplitSetSchurScale().
2493 
2494 $    If A and S are solved exactly
2495 $      *) FULL factorization is a direct solver.
2496 $      *) The preconditioned operator with LOWER or UPPER has all eigenvalues equal to 1 and minimal polynomial of degree 2, so KSPGMRES converges in 2 iterations.
2497 $      *) With DIAG, the preconditioned operator has three distinct nonzero eigenvalues and minimal polynomial of degree at most 4, so KSPGMRES converges in at most 4 iterations.
2498 
2499     If the iteration count is very low, consider using KSPFGMRES or KSPGCR which can use one less preconditioner
2500     application in this case. Note that the preconditioned operator may be highly non-normal, so such fast convergence may not be observed in practice.
2501 
2502     For symmetric problems in which A is positive definite and S is negative definite, DIAG can be used with KSPMINRES.
2503 
2504     Note that a flexible method like KSPFGMRES or KSPGCR must be used if the fieldsplit preconditioner is nonlinear (e.g. a few iterations of a Krylov method is used to solve with A or S).
2505 
2506     References:
2507 +   1. - Murphy, Golub, and Wathen, A note on preconditioning indefinite linear systems, SIAM J. Sci. Comput., 21 (2000).
2508 -   2. - Ipsen, A note on preconditioning nonsymmetric matrices, SIAM J. Sci. Comput., 23 (2001).
2509 
2510 .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetFields(), PCFieldSplitSchurPreType, PCFieldSplitSetSchurScale()
2511 @*/
2512 PetscErrorCode  PCFieldSplitSetSchurFactType(PC pc,PCFieldSplitSchurFactType ftype)
2513 {
2514   PetscErrorCode ierr;
2515 
2516   PetscFunctionBegin;
2517   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2518   ierr = PetscTryMethod(pc,"PCFieldSplitSetSchurFactType_C",(PC,PCFieldSplitSchurFactType),(pc,ftype));CHKERRQ(ierr);
2519   PetscFunctionReturn(0);
2520 }
2521 
2522 static PetscErrorCode PCFieldSplitSetSchurFactType_FieldSplit(PC pc,PCFieldSplitSchurFactType ftype)
2523 {
2524   PC_FieldSplit *jac = (PC_FieldSplit*)pc->data;
2525 
2526   PetscFunctionBegin;
2527   jac->schurfactorization = ftype;
2528   PetscFunctionReturn(0);
2529 }
2530 
2531 /*@
2532     PCFieldSplitSetSchurScale -  Controls the sign flip of S for PC_FIELDSPLIT_SCHUR_FACT_DIAG.
2533 
2534     Collective on PC
2535 
2536     Input Parameters:
2537 +   pc    - the preconditioner context
2538 -   scale - scaling factor for the Schur complement
2539 
2540     Options Database:
2541 .     -pc_fieldsplit_schur_scale - default is -1.0
2542 
2543     Level: intermediate
2544 
2545 .seealso: PCFIELDSPLIT, PCFieldSplitSetFields(), PCFieldSplitSchurFactType, PCFieldSplitSetSchurScale()
2546 @*/
2547 PetscErrorCode PCFieldSplitSetSchurScale(PC pc,PetscScalar scale)
2548 {
2549   PetscErrorCode ierr;
2550 
2551   PetscFunctionBegin;
2552   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2553   PetscValidLogicalCollectiveScalar(pc,scale,2);
2554   ierr = PetscTryMethod(pc,"PCFieldSplitSetSchurScale_C",(PC,PetscScalar),(pc,scale));CHKERRQ(ierr);
2555   PetscFunctionReturn(0);
2556 }
2557 
2558 static PetscErrorCode PCFieldSplitSetSchurScale_FieldSplit(PC pc,PetscScalar scale)
2559 {
2560   PC_FieldSplit *jac = (PC_FieldSplit*)pc->data;
2561 
2562   PetscFunctionBegin;
2563   jac->schurscale = scale;
2564   PetscFunctionReturn(0);
2565 }
2566 
2567 /*@C
2568    PCFieldSplitGetSchurBlocks - Gets all matrix blocks for the Schur complement
2569 
2570    Collective on KSP
2571 
2572    Input Parameter:
2573 .  pc - the preconditioner context
2574 
2575    Output Parameters:
2576 +  A00 - the (0,0) block
2577 .  A01 - the (0,1) block
2578 .  A10 - the (1,0) block
2579 -  A11 - the (1,1) block
2580 
2581    Level: advanced
2582 
2583 .seealso: PCFIELDSPLIT
2584 @*/
2585 PetscErrorCode  PCFieldSplitGetSchurBlocks(PC pc,Mat *A00,Mat *A01,Mat *A10, Mat *A11)
2586 {
2587   PC_FieldSplit *jac = (PC_FieldSplit*) pc->data;
2588 
2589   PetscFunctionBegin;
2590   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2591   if (jac->type != PC_COMPOSITE_SCHUR) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG, "FieldSplit is not using a Schur complement approach.");
2592   if (A00) *A00 = jac->pmat[0];
2593   if (A01) *A01 = jac->B;
2594   if (A10) *A10 = jac->C;
2595   if (A11) *A11 = jac->pmat[1];
2596   PetscFunctionReturn(0);
2597 }
2598 
2599 /*@
2600     PCFieldSplitSetGKBTol -  Sets the solver tolerance for the generalized Golub-Kahan bidiagonalization preconditioner.
2601 
2602     Collective on PC
2603 
2604     Notes:
2605     The generalized GKB algorithm uses a lower bound estimate of the error in energy norm as stopping criterion.
2606     It stops once the lower bound estimate undershoots the required solver tolerance. Although the actual error might be bigger than
2607     this estimate, the stopping criterion is satisfactory in practical cases [A13].
2608 
2609 [Ar13] Generalized Golub-Kahan bidiagonalization and stopping criteria, SIAM J. Matrix Anal. Appl., Vol. 34, No. 2, pp. 571-592, 2013.
2610 
2611     Input Parameters:
2612 +   pc        - the preconditioner context
2613 -   tolerance - the solver tolerance
2614 
2615     Options Database:
2616 .     -pc_fieldsplit_gkb_tol - default is 1e-5
2617 
2618     Level: intermediate
2619 
2620 .seealso: PCFIELDSPLIT, PCFieldSplitSetGKBDelay(), PCFieldSplitSetGKBNu(), PCFieldSplitSetGKBMaxit()
2621 @*/
2622 PetscErrorCode PCFieldSplitSetGKBTol(PC pc,PetscReal tolerance)
2623 {
2624   PetscErrorCode ierr;
2625 
2626   PetscFunctionBegin;
2627   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2628   PetscValidLogicalCollectiveReal(pc,tolerance,2);
2629   ierr = PetscTryMethod(pc,"PCFieldSplitSetGKBTol_C",(PC,PetscReal),(pc,tolerance));CHKERRQ(ierr);
2630   PetscFunctionReturn(0);
2631 }
2632 
2633 static PetscErrorCode PCFieldSplitSetGKBTol_FieldSplit(PC pc,PetscReal tolerance)
2634 {
2635   PC_FieldSplit *jac = (PC_FieldSplit*)pc->data;
2636 
2637   PetscFunctionBegin;
2638   jac->gkbtol = tolerance;
2639   PetscFunctionReturn(0);
2640 }
2641 
2642 /*@
2643     PCFieldSplitSetGKBMaxit -  Sets the maximum number of iterations for the generalized Golub-Kahan bidiagonalization
2644     preconditioner.
2645 
2646     Collective on PC
2647 
2648     Input Parameters:
2649 +   pc     - the preconditioner context
2650 -   maxit  - the maximum number of iterations
2651 
2652     Options Database:
2653 .     -pc_fieldsplit_gkb_maxit - default is 100
2654 
2655     Level: intermediate
2656 
2657 .seealso: PCFIELDSPLIT, PCFieldSplitSetGKBDelay(), PCFieldSplitSetGKBTol(), PCFieldSplitSetGKBNu()
2658 @*/
2659 PetscErrorCode PCFieldSplitSetGKBMaxit(PC pc,PetscInt maxit)
2660 {
2661   PetscErrorCode ierr;
2662 
2663   PetscFunctionBegin;
2664   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2665   PetscValidLogicalCollectiveInt(pc,maxit,2);
2666   ierr = PetscTryMethod(pc,"PCFieldSplitSetGKBMaxit_C",(PC,PetscInt),(pc,maxit));CHKERRQ(ierr);
2667   PetscFunctionReturn(0);
2668 }
2669 
2670 static PetscErrorCode PCFieldSplitSetGKBMaxit_FieldSplit(PC pc,PetscInt maxit)
2671 {
2672   PC_FieldSplit *jac = (PC_FieldSplit*)pc->data;
2673 
2674   PetscFunctionBegin;
2675   jac->gkbmaxit = maxit;
2676   PetscFunctionReturn(0);
2677 }
2678 
2679 /*@
2680     PCFieldSplitSetGKBDelay -  Sets the delay in the lower bound error estimate in the generalized Golub-Kahan bidiagonalization
2681     preconditioner.
2682 
2683     Collective on PC
2684 
2685     Notes:
2686     The algorithm uses a lower bound estimate of the error in energy norm as stopping criterion. The lower bound of the error ||u-u^k||_H
2687     is expressed as a truncated sum. The error at iteration k can only be measured at iteration (k + delay), and thus the algorithm needs
2688     at least (delay + 1) iterations to stop. For more details on the generalized Golub-Kahan bidiagonalization method and its lower bound stopping criterion, please refer to
2689 
2690 [Ar13] Generalized Golub-Kahan bidiagonalization and stopping criteria, SIAM J. Matrix Anal. Appl., Vol. 34, No. 2, pp. 571-592, 2013.
2691 
2692     Input Parameters:
2693 +   pc     - the preconditioner context
2694 -   delay  - the delay window in the lower bound estimate
2695 
2696     Options Database:
2697 .     -pc_fieldsplit_gkb_delay - default is 5
2698 
2699     Level: intermediate
2700 
2701 .seealso: PCFIELDSPLIT, PCFieldSplitSetGKBNu(), PCFieldSplitSetGKBTol(), PCFieldSplitSetGKBMaxit()
2702 @*/
2703 PetscErrorCode PCFieldSplitSetGKBDelay(PC pc,PetscInt delay)
2704 {
2705   PetscErrorCode ierr;
2706 
2707   PetscFunctionBegin;
2708   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2709   PetscValidLogicalCollectiveInt(pc,delay,2);
2710   ierr = PetscTryMethod(pc,"PCFieldSplitSetGKBDelay_C",(PC,PetscInt),(pc,delay));CHKERRQ(ierr);
2711   PetscFunctionReturn(0);
2712 }
2713 
2714 static PetscErrorCode PCFieldSplitSetGKBDelay_FieldSplit(PC pc,PetscInt delay)
2715 {
2716   PC_FieldSplit *jac = (PC_FieldSplit*)pc->data;
2717 
2718   PetscFunctionBegin;
2719   jac->gkbdelay = delay;
2720   PetscFunctionReturn(0);
2721 }
2722 
2723 /*@
2724     PCFieldSplitSetGKBNu -  Sets the scalar value nu >= 0 in the transformation H = A00 + nu*A01*A01' of the (1,1) block in the Golub-Kahan bidiagonalization preconditioner.
2725 
2726     Collective on PC
2727 
2728     Notes:
2729     This shift is in general done to obtain better convergence properties for the outer loop of the algorithm. This is often achieved by chosing nu sufficiently big. However,
2730     if nu is chosen too big, the matrix H might be badly conditioned and the solution of the linear system Hx = b in the inner loop gets difficult. It is therefore
2731     necessary to find a good balance in between the convergence of the inner and outer loop.
2732 
2733     For nu = 0, no shift is done. In this case A00 has to be positive definite. The matrix N in [Ar13] is then chosen as identity.
2734 
2735 [Ar13] Generalized Golub-Kahan bidiagonalization and stopping criteria, SIAM J. Matrix Anal. Appl., Vol. 34, No. 2, pp. 571-592, 2013.
2736 
2737     Input Parameters:
2738 +   pc     - the preconditioner context
2739 -   nu     - the shift parameter
2740 
2741     Options Database:
2742 .     -pc_fieldsplit_gkb_nu - default is 1
2743 
2744     Level: intermediate
2745 
2746 .seealso: PCFIELDSPLIT, PCFieldSplitSetGKBDelay(), PCFieldSplitSetGKBTol(), PCFieldSplitSetGKBMaxit()
2747 @*/
2748 PetscErrorCode PCFieldSplitSetGKBNu(PC pc,PetscReal nu)
2749 {
2750   PetscErrorCode ierr;
2751 
2752   PetscFunctionBegin;
2753   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2754   PetscValidLogicalCollectiveReal(pc,nu,2);
2755   ierr = PetscTryMethod(pc,"PCFieldSplitSetGKBNu_C",(PC,PetscReal),(pc,nu));CHKERRQ(ierr);
2756   PetscFunctionReturn(0);
2757 }
2758 
2759 static PetscErrorCode PCFieldSplitSetGKBNu_FieldSplit(PC pc,PetscReal nu)
2760 {
2761   PC_FieldSplit *jac = (PC_FieldSplit*)pc->data;
2762 
2763   PetscFunctionBegin;
2764   jac->gkbnu = nu;
2765   PetscFunctionReturn(0);
2766 }
2767 
2768 static PetscErrorCode  PCFieldSplitSetType_FieldSplit(PC pc,PCCompositeType type)
2769 {
2770   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
2771   PetscErrorCode ierr;
2772 
2773   PetscFunctionBegin;
2774   jac->type = type;
2775 
2776   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitGetSubKSP_C",0);CHKERRQ(ierr);
2777   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetSchurPre_C",0);CHKERRQ(ierr);
2778   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitGetSchurPre_C",0);CHKERRQ(ierr);
2779   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetSchurFactType_C",0);CHKERRQ(ierr);
2780   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetSchurScale_C",0);CHKERRQ(ierr);
2781   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetGKBTol_C",0);CHKERRQ(ierr);
2782   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetGKBMaxit_C",0);CHKERRQ(ierr);
2783   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetGKBNu_C",0);CHKERRQ(ierr);
2784   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetGKBDelay_C",0);CHKERRQ(ierr);
2785 
2786   if (type == PC_COMPOSITE_SCHUR) {
2787     pc->ops->apply = PCApply_FieldSplit_Schur;
2788     pc->ops->view  = PCView_FieldSplit_Schur;
2789 
2790     ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitGetSubKSP_C",PCFieldSplitGetSubKSP_FieldSplit_Schur);CHKERRQ(ierr);
2791     ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetSchurPre_C",PCFieldSplitSetSchurPre_FieldSplit);CHKERRQ(ierr);
2792     ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitGetSchurPre_C",PCFieldSplitGetSchurPre_FieldSplit);CHKERRQ(ierr);
2793     ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetSchurFactType_C",PCFieldSplitSetSchurFactType_FieldSplit);CHKERRQ(ierr);
2794     ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetSchurScale_C",PCFieldSplitSetSchurScale_FieldSplit);CHKERRQ(ierr);
2795   } else if (type == PC_COMPOSITE_GKB){
2796     pc->ops->apply = PCApply_FieldSplit_GKB;
2797     pc->ops->view  = PCView_FieldSplit_GKB;
2798 
2799     ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitGetSubKSP_C",PCFieldSplitGetSubKSP_FieldSplit);CHKERRQ(ierr);
2800     ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetGKBTol_C",PCFieldSplitSetGKBTol_FieldSplit);CHKERRQ(ierr);
2801     ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetGKBMaxit_C",PCFieldSplitSetGKBMaxit_FieldSplit);CHKERRQ(ierr);
2802     ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetGKBNu_C",PCFieldSplitSetGKBNu_FieldSplit);CHKERRQ(ierr);
2803     ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetGKBDelay_C",PCFieldSplitSetGKBDelay_FieldSplit);CHKERRQ(ierr);
2804   } else {
2805     pc->ops->apply = PCApply_FieldSplit;
2806     pc->ops->view  = PCView_FieldSplit;
2807 
2808     ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitGetSubKSP_C",PCFieldSplitGetSubKSP_FieldSplit);CHKERRQ(ierr);
2809   }
2810   PetscFunctionReturn(0);
2811 }
2812 
2813 static PetscErrorCode  PCFieldSplitSetBlockSize_FieldSplit(PC pc,PetscInt bs)
2814 {
2815   PC_FieldSplit *jac = (PC_FieldSplit*)pc->data;
2816 
2817   PetscFunctionBegin;
2818   if (bs < 1) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Blocksize must be positive, you gave %D",bs);
2819   if (jac->bs > 0 && jac->bs != bs) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Cannot change fieldsplit blocksize from %D to %D after it has been set",jac->bs,bs);
2820   jac->bs = bs;
2821   PetscFunctionReturn(0);
2822 }
2823 
2824 /*@
2825    PCFieldSplitSetType - Sets the type of fieldsplit preconditioner.
2826 
2827    Collective on PC
2828 
2829    Input Parameter:
2830 +  pc - the preconditioner context
2831 -  type - PC_COMPOSITE_ADDITIVE, PC_COMPOSITE_MULTIPLICATIVE (default), PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE, PC_COMPOSITE_SPECIAL, PC_COMPOSITE_SCHUR
2832 
2833    Options Database Key:
2834 .  -pc_fieldsplit_type <type: one of multiplicative, additive, symmetric_multiplicative, special, schur> - Sets fieldsplit preconditioner type
2835 
2836    Level: Intermediate
2837 
2838 .seealso: PCCompositeSetType()
2839 
2840 @*/
2841 PetscErrorCode  PCFieldSplitSetType(PC pc,PCCompositeType type)
2842 {
2843   PetscErrorCode ierr;
2844 
2845   PetscFunctionBegin;
2846   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2847   ierr = PetscTryMethod(pc,"PCFieldSplitSetType_C",(PC,PCCompositeType),(pc,type));CHKERRQ(ierr);
2848   PetscFunctionReturn(0);
2849 }
2850 
2851 /*@
2852   PCFieldSplitGetType - Gets the type of fieldsplit preconditioner.
2853 
2854   Not collective
2855 
2856   Input Parameter:
2857 . pc - the preconditioner context
2858 
2859   Output Parameter:
2860 . type - PC_COMPOSITE_ADDITIVE, PC_COMPOSITE_MULTIPLICATIVE (default), PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE, PC_COMPOSITE_SPECIAL, PC_COMPOSITE_SCHUR
2861 
2862   Level: Intermediate
2863 
2864 .seealso: PCCompositeSetType()
2865 @*/
2866 PetscErrorCode PCFieldSplitGetType(PC pc, PCCompositeType *type)
2867 {
2868   PC_FieldSplit *jac = (PC_FieldSplit*) pc->data;
2869 
2870   PetscFunctionBegin;
2871   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2872   PetscValidIntPointer(type,2);
2873   *type = jac->type;
2874   PetscFunctionReturn(0);
2875 }
2876 
2877 /*@
2878    PCFieldSplitSetDMSplits - Flags whether DMCreateFieldDecomposition() should be used to define the splits, whenever possible.
2879 
2880    Logically Collective
2881 
2882    Input Parameters:
2883 +  pc   - the preconditioner context
2884 -  flg  - boolean indicating whether to use field splits defined by the DM
2885 
2886    Options Database Key:
2887 .  -pc_fieldsplit_dm_splits
2888 
2889    Level: Intermediate
2890 
2891 .seealso: PCFieldSplitGetDMSplits()
2892 
2893 @*/
2894 PetscErrorCode  PCFieldSplitSetDMSplits(PC pc,PetscBool flg)
2895 {
2896   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
2897   PetscBool      isfs;
2898   PetscErrorCode ierr;
2899 
2900   PetscFunctionBegin;
2901   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2902   PetscValidLogicalCollectiveBool(pc,flg,2);
2903   ierr = PetscObjectTypeCompare((PetscObject)pc,PCFIELDSPLIT,&isfs);CHKERRQ(ierr);
2904   if (isfs) {
2905     jac->dm_splits = flg;
2906   }
2907   PetscFunctionReturn(0);
2908 }
2909 
2910 /*@
2911    PCFieldSplitGetDMSplits - Returns flag indicating whether DMCreateFieldDecomposition() should be used to define the splits, whenever possible.
2912 
2913    Logically Collective
2914 
2915    Input Parameter:
2916 .  pc   - the preconditioner context
2917 
2918    Output Parameter:
2919 .  flg  - boolean indicating whether to use field splits defined by the DM
2920 
2921    Level: Intermediate
2922 
2923 .seealso: PCFieldSplitSetDMSplits()
2924 
2925 @*/
2926 PetscErrorCode  PCFieldSplitGetDMSplits(PC pc,PetscBool* flg)
2927 {
2928   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
2929   PetscBool      isfs;
2930   PetscErrorCode ierr;
2931 
2932   PetscFunctionBegin;
2933   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2934   PetscValidBoolPointer(flg,2);
2935   ierr = PetscObjectTypeCompare((PetscObject)pc,PCFIELDSPLIT,&isfs);CHKERRQ(ierr);
2936   if (isfs) {
2937     if (flg) *flg = jac->dm_splits;
2938   }
2939   PetscFunctionReturn(0);
2940 }
2941 
2942 /*@
2943    PCFieldSplitGetDetectSaddlePoint - Returns flag indicating whether PCFieldSplit will attempt to automatically determine fields based on zero diagonal entries.
2944 
2945    Logically Collective
2946 
2947    Input Parameter:
2948 .  pc   - the preconditioner context
2949 
2950    Output Parameter:
2951 .  flg  - boolean indicating whether to detect fields or not
2952 
2953    Level: Intermediate
2954 
2955 .seealso: PCFIELDSPLIT, PCFieldSplitSetDetectSaddlePoint()
2956 
2957 @*/
2958 PetscErrorCode PCFieldSplitGetDetectSaddlePoint(PC pc,PetscBool *flg)
2959 {
2960   PC_FieldSplit *jac = (PC_FieldSplit*)pc->data;
2961 
2962   PetscFunctionBegin;
2963   *flg = jac->detect;
2964   PetscFunctionReturn(0);
2965 }
2966 
2967 /*@
2968    PCFieldSplitSetDetectSaddlePoint - Sets flag indicating whether PCFieldSplit will attempt to automatically determine fields based on zero diagonal entries.
2969 
2970    Logically Collective
2971 
2972    Notes:
2973    Also sets the split type to PC_COMPOSITE_SCHUR (see PCFieldSplitSetType()) and the Schur preconditioner type to PC_FIELDSPLIT_SCHUR_PRE_SELF (see PCFieldSplitSetSchurPre()).
2974 
2975    Input Parameter:
2976 .  pc   - the preconditioner context
2977 
2978    Output Parameter:
2979 .  flg  - boolean indicating whether to detect fields or not
2980 
2981    Options Database Key:
2982 .  -pc_fieldsplit_detect_saddle_point
2983 
2984    Level: Intermediate
2985 
2986 .seealso: PCFIELDSPLIT, PCFieldSplitSetDetectSaddlePoint(), PCFieldSplitSetType(), PCFieldSplitSetSchurPre()
2987 
2988 @*/
2989 PetscErrorCode PCFieldSplitSetDetectSaddlePoint(PC pc,PetscBool flg)
2990 {
2991   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
2992   PetscErrorCode ierr;
2993 
2994   PetscFunctionBegin;
2995   jac->detect = flg;
2996   if (jac->detect) {
2997     ierr = PCFieldSplitSetType(pc,PC_COMPOSITE_SCHUR);CHKERRQ(ierr);
2998     ierr = PCFieldSplitSetSchurPre(pc,PC_FIELDSPLIT_SCHUR_PRE_SELF,NULL);CHKERRQ(ierr);
2999   }
3000   PetscFunctionReturn(0);
3001 }
3002 
3003 /* -------------------------------------------------------------------------------------*/
3004 /*MC
3005    PCFIELDSPLIT - Preconditioner created by combining separate preconditioners for individual
3006                   fields or groups of fields. See the users manual section "Solving Block Matrices" for more details.
3007 
3008      To set options on the solvers for each block append -fieldsplit_ to all the PC
3009         options database keys. For example, -fieldsplit_pc_type ilu -fieldsplit_pc_factor_levels 1
3010 
3011      To set the options on the solvers separate for each block call PCFieldSplitGetSubKSP()
3012          and set the options directly on the resulting KSP object
3013 
3014    Level: intermediate
3015 
3016    Options Database Keys:
3017 +   -pc_fieldsplit_%d_fields <a,b,..> - indicates the fields to be used in the %d'th split
3018 .   -pc_fieldsplit_default - automatically add any fields to additional splits that have not
3019                               been supplied explicitly by -pc_fieldsplit_%d_fields
3020 .   -pc_fieldsplit_block_size <bs> - size of block that defines fields (i.e. there are bs fields)
3021 .   -pc_fieldsplit_type <additive,multiplicative,symmetric_multiplicative,schur,gkb> - type of relaxation or factorization splitting
3022 .   -pc_fieldsplit_schur_precondition <self,selfp,user,a11,full> - default is a11; see PCFieldSplitSetSchurPre()
3023 .   -pc_fieldsplit_schur_fact_type <diag,lower,upper,full> - set factorization type when using -pc_fieldsplit_type schur; see PCFieldSplitSetSchurFactType()
3024 -   -pc_fieldsplit_detect_saddle_point - automatically finds rows with zero diagonal and uses Schur complement with no preconditioner as the solver
3025 
3026      Options prefixes for inner solvers when using the Schur complement preconditioner are -fieldsplit_0_ and -fieldsplit_1_ .
3027      For all other solvers they are -fieldsplit_%d_ for the dth field; use -fieldsplit_ for all fields.
3028      The options prefix for the inner solver when using the Golub-Kahan biadiagonalization preconditioner is -fieldsplit_0_
3029 
3030    Notes:
3031     Use PCFieldSplitSetFields() to set fields defined by "strided" entries and PCFieldSplitSetIS()
3032      to define a field by an arbitrary collection of entries.
3033 
3034       If no fields are set the default is used. The fields are defined by entries strided by bs,
3035       beginning at 0 then 1, etc to bs-1. The block size can be set with PCFieldSplitSetBlockSize(),
3036       if this is not called the block size defaults to the blocksize of the second matrix passed
3037       to KSPSetOperators()/PCSetOperators().
3038 
3039 $     For the Schur complement preconditioner if J = [ A00 A01]
3040 $                                                    [ A10 A11]
3041 $     the preconditioner using full factorization is
3042 $              [ I   -ksp(A00) A01] [ inv(A00)    0  ] [     I          0]
3043 $              [ 0         I      ] [   0      ksp(S)] [ -A10 ksp(A00)  I]
3044      where the action of inv(A00) is applied using the KSP solver with prefix -fieldsplit_0_.  S is the Schur complement
3045 $              S = A11 - A10 ksp(A00) A01
3046      which is usually dense and not stored explicitly.  The action of ksp(S) is computed using the KSP solver with prefix -fieldsplit_splitname_ (where splitname was given
3047      in providing the SECOND split or 1 if not give). For PCFieldSplitGetSubKSP() when field number is 0,
3048      it returns the KSP associated with -fieldsplit_0_ while field number 1 gives -fieldsplit_1_ KSP. By default
3049      A11 is used to construct a preconditioner for S, use PCFieldSplitSetSchurPre() for all the possible ways to construct the preconditioner for S.
3050 
3051      The factorization type is set using -pc_fieldsplit_schur_fact_type <diag, lower, upper, full>. The full is shown above,
3052      diag gives
3053 $              [ inv(A00)     0 ]
3054 $              [   0      -ksp(S)]
3055      note that slightly counter intuitively there is a negative in front of the ksp(S) so that the preconditioner is positive definite. For SPD matrices J, the sign flip
3056      can be turned off with PCFieldSplitSetSchurScale() or by command line -pc_fieldsplit_schur_scale 1.0. The lower factorization is the inverse of
3057 $              [  A00   0]
3058 $              [  A10   S]
3059      where the inverses of A00 and S are applied using KSPs. The upper factorization is the inverse of
3060 $              [ A00 A01]
3061 $              [  0   S ]
3062      where again the inverses of A00 and S are applied using KSPs.
3063 
3064      If only one set of indices (one IS) is provided with PCFieldSplitSetIS() then the complement of that IS
3065      is used automatically for a second block.
3066 
3067      The fieldsplit preconditioner cannot currently be used with the BAIJ or SBAIJ data formats if the blocksize is larger than 1.
3068      Generally it should be used with the AIJ format.
3069 
3070      The forms of these preconditioners are closely related if not identical to forms derived as "Distributive Iterations", see,
3071      for example, page 294 in "Principles of Computational Fluid Dynamics" by Pieter Wesseling. Note that one can also use PCFIELDSPLIT
3072      inside a smoother resulting in "Distributive Smoothers".
3073 
3074      References:
3075        A taxonomy and comparison of parallel block multi-level preconditioners for the incompressible Navier-Stokes equations
3076        Howard Elman, V.E. Howle, John Shadid, Robert Shuttleworth, Ray Tuminaro, Journal of Computational Physics 227 (2008) 1790--1808
3077        http://chess.cs.umd.edu/~elman/papers/tax.pdf
3078 
3079    The Constrained Pressure Preconditioner (CPR) can be implemented using PCCOMPOSITE with PCGALERKIN. CPR first solves an R A P subsystem, updates the
3080    residual on all variables (PCCompositeSetType(pc,PC_COMPOSITE_MULTIPLICATIVE)), and then applies a simple ILU like preconditioner on all the variables.
3081 
3082    The generalized Golub-Kahan bidiagonalization preconditioner (gkb) can be applied to symmetric 2x2 block matrices of the shape
3083 $        [ A00  A01]
3084 $        [ A01' 0  ]
3085    with A00 positive semi-definite. The implementation follows [Ar13]. Therein, we choose N := 1/nu * I and the (1,1)-block of the matrix is modified to H = A00 + nu*A01*A01'.
3086    A linear system Hx = b has to be solved in each iteration of the GKB algorithm. This solver is chosen with the option prefix -fieldsplit_0_.
3087 
3088 [Ar13] Generalized Golub-Kahan bidiagonalization and stopping criteria, SIAM J. Matrix Anal. Appl., Vol. 34, No. 2, pp. 571-592, 2013.
3089 
3090 .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC, PCLSC,
3091            PCFieldSplitGetSubKSP(), PCFieldSplitSchurGetSubKSP(), PCFieldSplitSetFields(),
3092            PCFieldSplitSetType(), PCFieldSplitSetIS(), PCFieldSplitSetSchurPre(), PCFieldSplitSetSchurFactType(),
3093            MatSchurComplementSetAinvType(), PCFieldSplitSetSchurScale(), PCFieldSplitSetDetectSaddlePoint()
3094 M*/
3095 
3096 PETSC_EXTERN PetscErrorCode PCCreate_FieldSplit(PC pc)
3097 {
3098   PetscErrorCode ierr;
3099   PC_FieldSplit  *jac;
3100 
3101   PetscFunctionBegin;
3102   ierr = PetscNewLog(pc,&jac);CHKERRQ(ierr);
3103 
3104   jac->bs                 = -1;
3105   jac->nsplits            = 0;
3106   jac->type               = PC_COMPOSITE_MULTIPLICATIVE;
3107   jac->schurpre           = PC_FIELDSPLIT_SCHUR_PRE_USER; /* Try user preconditioner first, fall back on diagonal */
3108   jac->schurfactorization = PC_FIELDSPLIT_SCHUR_FACT_FULL;
3109   jac->schurscale         = -1.0;
3110   jac->dm_splits          = PETSC_TRUE;
3111   jac->detect             = PETSC_FALSE;
3112   jac->gkbtol             = 1e-5;
3113   jac->gkbdelay           = 5;
3114   jac->gkbnu              = 1;
3115   jac->gkbmaxit           = 100;
3116   jac->gkbmonitor         = PETSC_FALSE;
3117 
3118   pc->data = (void*)jac;
3119 
3120   pc->ops->apply           = PCApply_FieldSplit;
3121   pc->ops->applytranspose  = PCApplyTranspose_FieldSplit;
3122   pc->ops->setup           = PCSetUp_FieldSplit;
3123   pc->ops->reset           = PCReset_FieldSplit;
3124   pc->ops->destroy         = PCDestroy_FieldSplit;
3125   pc->ops->setfromoptions  = PCSetFromOptions_FieldSplit;
3126   pc->ops->view            = PCView_FieldSplit;
3127   pc->ops->applyrichardson = NULL;
3128 
3129   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSchurGetSubKSP_C",PCFieldSplitSchurGetSubKSP_FieldSplit);CHKERRQ(ierr);
3130   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitGetSubKSP_C",PCFieldSplitGetSubKSP_FieldSplit);CHKERRQ(ierr);
3131   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetFields_C",PCFieldSplitSetFields_FieldSplit);CHKERRQ(ierr);
3132   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetIS_C",PCFieldSplitSetIS_FieldSplit);CHKERRQ(ierr);
3133   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetType_C",PCFieldSplitSetType_FieldSplit);CHKERRQ(ierr);
3134   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetBlockSize_C",PCFieldSplitSetBlockSize_FieldSplit);CHKERRQ(ierr);
3135   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitRestrictIS_C",PCFieldSplitRestrictIS_FieldSplit);CHKERRQ(ierr);
3136   PetscFunctionReturn(0);
3137 }
3138