xref: /petsc/src/ksp/pc/impls/fieldsplit/fieldsplit.c (revision 07c0461f92f2c1aea27ba8cc5bb53c8785e502d5)
1 
2 
3 #include <petsc/private/pcimpl.h>     /*I "petscpc.h" I*/
4 #include <petsc/private/kspimpl.h>    /*  This is needed to provide the appropriate PETSC_EXTERN for KSP_Solve_FS ....*/
5 #include <petscdm.h>
6 
7 const char *const PCFieldSplitSchurPreTypes[] = {"SELF","SELFP","A11","USER","FULL","PCFieldSplitSchurPreType","PC_FIELDSPLIT_SCHUR_PRE_",0};
8 const char *const PCFieldSplitSchurFactTypes[] = {"DIAG","LOWER","UPPER","FULL","PCFieldSplitSchurFactType","PC_FIELDSPLIT_SCHUR_FACT_",0};
9 
10 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;
11 
12 typedef struct _PC_FieldSplitLink *PC_FieldSplitLink;
13 struct _PC_FieldSplitLink {
14   KSP               ksp;
15   Vec               x,y,z;
16   char              *splitname;
17   PetscInt          nfields;
18   PetscInt          *fields,*fields_col;
19   VecScatter        sctx;
20   IS                is,is_col;
21   PC_FieldSplitLink next,previous;
22   PetscLogEvent     event;
23 };
24 
25 typedef struct {
26   PCCompositeType type;
27   PetscBool       defaultsplit;                    /* Flag for a system with a set of 'k' scalar fields with the same layout (and bs = k) */
28   PetscBool       splitdefined;                    /* Flag is set after the splits have been defined, to prevent more splits from being added */
29   PetscInt        bs;                              /* Block size for IS and Mat structures */
30   PetscInt        nsplits;                         /* Number of field divisions defined */
31   Vec             *x,*y,w1,w2;
32   Mat             *mat;                            /* The diagonal block for each split */
33   Mat             *pmat;                           /* The preconditioning diagonal block for each split */
34   Mat             *Afield;                         /* The rows of the matrix associated with each split */
35   PetscBool       issetup;
36 
37   /* Only used when Schur complement preconditioning is used */
38   Mat                       B;                     /* The (0,1) block */
39   Mat                       C;                     /* The (1,0) block */
40   Mat                       schur;                 /* The Schur complement S = A11 - A10 A00^{-1} A01, the KSP here, kspinner, is H_1 in [El08] */
41   Mat                       schurp;                /* Assembled approximation to S built by MatSchurComplement to be used as a preconditioning matrix when solving with S */
42   Mat                       schur_user;            /* User-provided preconditioning matrix for the Schur complement */
43   PCFieldSplitSchurPreType  schurpre;              /* Determines which preconditioning matrix is used for the Schur complement */
44   PCFieldSplitSchurFactType schurfactorization;
45   KSP                       kspschur;              /* The solver for S */
46   KSP                       kspupper;              /* The solver for A in the upper diagonal part of the factorization (H_2 in [El08]) */
47   PC_FieldSplitLink         head;
48   PetscBool                 isrestrict;             /* indicates PCFieldSplitRestrictIS() has been last called on this object, hack */
49   PetscBool                 suboptionsset;          /* Indicates that the KSPSetFromOptions() has been called on the sub-KSPs */
50   PetscBool                 dm_splits;              /* Whether to use DMCreateFieldDecomposition() whenever possible */
51   PetscBool                 diag_use_amat;          /* Whether to extract diagonal matrix blocks from Amat, rather than Pmat (weaker than -pc_use_amat) */
52   PetscBool                 offdiag_use_amat;       /* Whether to extract off-diagonal matrix blocks from Amat, rather than Pmat (weaker than -pc_use_amat) */
53 } PC_FieldSplit;
54 
55 /*
56     Notes: there is no particular reason that pmat, x, and y are stored as arrays in PC_FieldSplit instead of
57    inside PC_FieldSplitLink, just historical. If you want to be able to add new fields after already using the
58    PC you could change this.
59 */
60 
61 /* This helper is so that setting a user-provided preconditioning matrix is orthogonal to choosing to use it.  This way the
62 * application-provided FormJacobian can provide this matrix without interfering with the user's (command-line) choices. */
63 static Mat FieldSplitSchurPre(PC_FieldSplit *jac)
64 {
65   switch (jac->schurpre) {
66   case PC_FIELDSPLIT_SCHUR_PRE_SELF: return jac->schur;
67   case PC_FIELDSPLIT_SCHUR_PRE_SELFP: return jac->schurp;
68   case PC_FIELDSPLIT_SCHUR_PRE_A11: return jac->pmat[1];
69   case PC_FIELDSPLIT_SCHUR_PRE_FULL: /* We calculate this and store it in schur_user */
70   case PC_FIELDSPLIT_SCHUR_PRE_USER: /* Use a user-provided matrix if it is given, otherwise diagonal block */
71   default:
72     return jac->schur_user ? jac->schur_user : jac->pmat[1];
73   }
74 }
75 
76 
77 #include <petscdraw.h>
78 static PetscErrorCode PCView_FieldSplit(PC pc,PetscViewer viewer)
79 {
80   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
81   PetscErrorCode    ierr;
82   PetscBool         iascii,isdraw;
83   PetscInt          i,j;
84   PC_FieldSplitLink ilink = jac->head;
85 
86   PetscFunctionBegin;
87   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
88   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
89   if (iascii) {
90     if (jac->bs > 0) {
91       ierr = PetscViewerASCIIPrintf(viewer,"  FieldSplit with %s composition: total splits = %D, blocksize = %D\n",PCCompositeTypes[jac->type],jac->nsplits,jac->bs);CHKERRQ(ierr);
92     } else {
93       ierr = PetscViewerASCIIPrintf(viewer,"  FieldSplit with %s composition: total splits = %D\n",PCCompositeTypes[jac->type],jac->nsplits);CHKERRQ(ierr);
94     }
95     if (pc->useAmat) {
96       ierr = PetscViewerASCIIPrintf(viewer,"  using Amat (not Pmat) as operator for blocks\n");CHKERRQ(ierr);
97     }
98     if (jac->diag_use_amat) {
99       ierr = PetscViewerASCIIPrintf(viewer,"  using Amat (not Pmat) as operator for diagonal blocks\n");CHKERRQ(ierr);
100     }
101     if (jac->offdiag_use_amat) {
102       ierr = PetscViewerASCIIPrintf(viewer,"  using Amat (not Pmat) as operator for off-diagonal blocks\n");CHKERRQ(ierr);
103     }
104     ierr = PetscViewerASCIIPrintf(viewer,"  Solver info for each split is in the following KSP objects:\n");CHKERRQ(ierr);
105     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
106     for (i=0; i<jac->nsplits; i++) {
107       if (ilink->fields) {
108         ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Fields ",i);CHKERRQ(ierr);
109         ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
110         for (j=0; j<ilink->nfields; j++) {
111           if (j > 0) {
112             ierr = PetscViewerASCIIPrintf(viewer,",");CHKERRQ(ierr);
113           }
114           ierr = PetscViewerASCIIPrintf(viewer," %D",ilink->fields[j]);CHKERRQ(ierr);
115         }
116         ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
117         ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
118       } else {
119         ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Defined by IS\n",i);CHKERRQ(ierr);
120       }
121       ierr  = KSPView(ilink->ksp,viewer);CHKERRQ(ierr);
122       ilink = ilink->next;
123     }
124     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
125   }
126 
127  if (isdraw) {
128     PetscDraw draw;
129     PetscReal x,y,w,wd;
130 
131     ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
132     ierr = PetscDrawGetCurrentPoint(draw,&x,&y);CHKERRQ(ierr);
133     w    = 2*PetscMin(1.0 - x,x);
134     wd   = w/(jac->nsplits + 1);
135     x    = x - wd*(jac->nsplits-1)/2.0;
136     for (i=0; i<jac->nsplits; i++) {
137       ierr  = PetscDrawPushCurrentPoint(draw,x,y);CHKERRQ(ierr);
138       ierr  = KSPView(ilink->ksp,viewer);CHKERRQ(ierr);
139       ierr  = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr);
140       x    += wd;
141       ilink = ilink->next;
142     }
143   }
144   PetscFunctionReturn(0);
145 }
146 
147 static PetscErrorCode PCView_FieldSplit_Schur(PC pc,PetscViewer viewer)
148 {
149   PC_FieldSplit              *jac = (PC_FieldSplit*)pc->data;
150   PetscErrorCode             ierr;
151   PetscBool                  iascii,isdraw;
152   PetscInt                   i,j;
153   PC_FieldSplitLink          ilink = jac->head;
154   MatSchurComplementAinvType atype;
155 
156   PetscFunctionBegin;
157   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
158   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
159   if (iascii) {
160     if (jac->bs > 0) {
161       ierr = PetscViewerASCIIPrintf(viewer,"  FieldSplit with Schur preconditioner, blocksize = %D, factorization %s\n",jac->bs,PCFieldSplitSchurFactTypes[jac->schurfactorization]);CHKERRQ(ierr);
162     } else {
163       ierr = PetscViewerASCIIPrintf(viewer,"  FieldSplit with Schur preconditioner, factorization %s\n",PCFieldSplitSchurFactTypes[jac->schurfactorization]);CHKERRQ(ierr);
164     }
165     if (pc->useAmat) {
166       ierr = PetscViewerASCIIPrintf(viewer,"  using Amat (not Pmat) as operator for blocks\n");CHKERRQ(ierr);
167     }
168     switch (jac->schurpre) {
169     case PC_FIELDSPLIT_SCHUR_PRE_SELF:
170       ierr = PetscViewerASCIIPrintf(viewer,"  Preconditioner for the Schur complement formed from S itself\n");CHKERRQ(ierr);
171       break;
172     case PC_FIELDSPLIT_SCHUR_PRE_SELFP:
173       ierr = MatSchurComplementGetAinvType(jac->schur,&atype);CHKERRQ(ierr);
174       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 ? "" : "lumped ");CHKERRQ(ierr);break;
175     case PC_FIELDSPLIT_SCHUR_PRE_A11:
176       ierr = PetscViewerASCIIPrintf(viewer,"  Preconditioner for the Schur complement formed from A11\n");CHKERRQ(ierr);
177       break;
178     case PC_FIELDSPLIT_SCHUR_PRE_FULL:
179       ierr = PetscViewerASCIIPrintf(viewer,"  Preconditioner for the Schur complement formed from the exact Schur complement\n");CHKERRQ(ierr);
180       break;
181     case PC_FIELDSPLIT_SCHUR_PRE_USER:
182       if (jac->schur_user) {
183         ierr = PetscViewerASCIIPrintf(viewer,"  Preconditioner for the Schur complement formed from user provided matrix\n");CHKERRQ(ierr);
184       } else {
185         ierr = PetscViewerASCIIPrintf(viewer,"  Preconditioner for the Schur complement formed from A11\n");CHKERRQ(ierr);
186       }
187       break;
188     default:
189       SETERRQ1(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Invalid Schur preconditioning type: %d", jac->schurpre);
190     }
191     ierr = PetscViewerASCIIPrintf(viewer,"  Split info:\n");CHKERRQ(ierr);
192     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
193     for (i=0; i<jac->nsplits; i++) {
194       if (ilink->fields) {
195         ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Fields ",i);CHKERRQ(ierr);
196         ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
197         for (j=0; j<ilink->nfields; j++) {
198           if (j > 0) {
199             ierr = PetscViewerASCIIPrintf(viewer,",");CHKERRQ(ierr);
200           }
201           ierr = PetscViewerASCIIPrintf(viewer," %D",ilink->fields[j]);CHKERRQ(ierr);
202         }
203         ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
204         ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
205       } else {
206         ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Defined by IS\n",i);CHKERRQ(ierr);
207       }
208       ilink = ilink->next;
209     }
210     ierr = PetscViewerASCIIPrintf(viewer,"KSP solver for A00 block\n");CHKERRQ(ierr);
211     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
212     if (jac->head) {
213       ierr = KSPView(jac->head->ksp,viewer);CHKERRQ(ierr);
214     } else  {ierr = PetscViewerASCIIPrintf(viewer,"  not yet available\n");CHKERRQ(ierr);}
215     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
216     if (jac->head && jac->kspupper != jac->head->ksp) {
217       ierr = PetscViewerASCIIPrintf(viewer,"KSP solver for upper A00 in upper triangular factor \n");CHKERRQ(ierr);
218       ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
219       if (jac->kspupper) {ierr = KSPView(jac->kspupper,viewer);CHKERRQ(ierr);}
220       else {ierr = PetscViewerASCIIPrintf(viewer,"  not yet available\n");CHKERRQ(ierr);}
221       ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
222     }
223     ierr = PetscViewerASCIIPrintf(viewer,"KSP solver for S = A11 - A10 inv(A00) A01 \n");CHKERRQ(ierr);
224     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
225     if (jac->kspschur) {
226       ierr = KSPView(jac->kspschur,viewer);CHKERRQ(ierr);
227     } else {
228       ierr = PetscViewerASCIIPrintf(viewer,"  not yet available\n");CHKERRQ(ierr);
229     }
230     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
231     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
232   } else if (isdraw && jac->head) {
233     PetscDraw draw;
234     PetscReal x,y,w,wd,h;
235     PetscInt  cnt = 2;
236     char      str[32];
237 
238     ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
239     ierr = PetscDrawGetCurrentPoint(draw,&x,&y);CHKERRQ(ierr);
240     if (jac->kspupper != jac->head->ksp) cnt++;
241     w  = 2*PetscMin(1.0 - x,x);
242     wd = w/(cnt + 1);
243 
244     ierr = PetscSNPrintf(str,32,"Schur fact. %s",PCFieldSplitSchurFactTypes[jac->schurfactorization]);CHKERRQ(ierr);
245     ierr = PetscDrawStringBoxed(draw,x,y,PETSC_DRAW_RED,PETSC_DRAW_BLACK,str,NULL,&h);CHKERRQ(ierr);
246     y   -= h;
247     if (jac->schurpre == PC_FIELDSPLIT_SCHUR_PRE_USER &&  !jac->schur_user) {
248       ierr = PetscSNPrintf(str,32,"Prec. for Schur from %s",PCFieldSplitSchurPreTypes[PC_FIELDSPLIT_SCHUR_PRE_A11]);CHKERRQ(ierr);
249     } else {
250       ierr = PetscSNPrintf(str,32,"Prec. for Schur from %s",PCFieldSplitSchurPreTypes[jac->schurpre]);CHKERRQ(ierr);
251     }
252     ierr = PetscDrawStringBoxed(draw,x+wd*(cnt-1)/2.0,y,PETSC_DRAW_RED,PETSC_DRAW_BLACK,str,NULL,&h);CHKERRQ(ierr);
253     y   -= h;
254     x    = x - wd*(cnt-1)/2.0;
255 
256     ierr = PetscDrawPushCurrentPoint(draw,x,y);CHKERRQ(ierr);
257     ierr = KSPView(jac->head->ksp,viewer);CHKERRQ(ierr);
258     ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr);
259     if (jac->kspupper != jac->head->ksp) {
260       x   += wd;
261       ierr = PetscDrawPushCurrentPoint(draw,x,y);CHKERRQ(ierr);
262       ierr = KSPView(jac->kspupper,viewer);CHKERRQ(ierr);
263       ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr);
264     }
265     x   += wd;
266     ierr = PetscDrawPushCurrentPoint(draw,x,y);CHKERRQ(ierr);
267     ierr = KSPView(jac->kspschur,viewer);CHKERRQ(ierr);
268     ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr);
269   }
270   PetscFunctionReturn(0);
271 }
272 
273 /* Precondition: jac->bs is set to a meaningful value */
274 static PetscErrorCode PCFieldSplitSetRuntimeSplits_Private(PC pc)
275 {
276   PetscErrorCode ierr;
277   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
278   PetscInt       i,nfields,*ifields,nfields_col,*ifields_col;
279   PetscBool      flg,flg_col;
280   char           optionname[128],splitname[8],optionname_col[128];
281 
282   PetscFunctionBegin;
283   ierr = PetscMalloc1(jac->bs,&ifields);CHKERRQ(ierr);
284   ierr = PetscMalloc1(jac->bs,&ifields_col);CHKERRQ(ierr);
285   for (i=0,flg=PETSC_TRUE;; i++) {
286     ierr        = PetscSNPrintf(splitname,sizeof(splitname),"%D",i);CHKERRQ(ierr);
287     ierr        = PetscSNPrintf(optionname,sizeof(optionname),"-pc_fieldsplit_%D_fields",i);CHKERRQ(ierr);
288     ierr        = PetscSNPrintf(optionname_col,sizeof(optionname_col),"-pc_fieldsplit_%D_fields_col",i);CHKERRQ(ierr);
289     nfields     = jac->bs;
290     nfields_col = jac->bs;
291     ierr        = PetscOptionsGetIntArray(((PetscObject)pc)->options,((PetscObject)pc)->prefix,optionname,ifields,&nfields,&flg);CHKERRQ(ierr);
292     ierr        = PetscOptionsGetIntArray(((PetscObject)pc)->options,((PetscObject)pc)->prefix,optionname_col,ifields_col,&nfields_col,&flg_col);CHKERRQ(ierr);
293     if (!flg) break;
294     else if (flg && !flg_col) {
295       if (!nfields) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot list zero fields");
296       ierr = PCFieldSplitSetFields(pc,splitname,nfields,ifields,ifields);CHKERRQ(ierr);
297     } else {
298       if (!nfields || !nfields_col) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot list zero fields");
299       if (nfields != nfields_col) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Number of row and column fields must match");
300       ierr = PCFieldSplitSetFields(pc,splitname,nfields,ifields,ifields_col);CHKERRQ(ierr);
301     }
302   }
303   if (i > 0) {
304     /* Makes command-line setting of splits take precedence over setting them in code.
305        Otherwise subsequent calls to PCFieldSplitSetIS() or PCFieldSplitSetFields() would
306        create new splits, which would probably not be what the user wanted. */
307     jac->splitdefined = PETSC_TRUE;
308   }
309   ierr = PetscFree(ifields);CHKERRQ(ierr);
310   ierr = PetscFree(ifields_col);CHKERRQ(ierr);
311   PetscFunctionReturn(0);
312 }
313 
314 static PetscErrorCode PCFieldSplitSetDefaults(PC pc)
315 {
316   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
317   PetscErrorCode    ierr;
318   PC_FieldSplitLink ilink = jac->head;
319   PetscBool         fieldsplit_default = PETSC_FALSE,stokes = PETSC_FALSE,coupling = PETSC_FALSE;
320   PetscInt          i;
321 
322   PetscFunctionBegin;
323   /*
324    Kinda messy, but at least this now uses DMCreateFieldDecomposition().
325    Should probably be rewritten.
326    */
327   if (!ilink) {
328     ierr = PetscOptionsGetBool(((PetscObject)pc)->options,((PetscObject)pc)->prefix,"-pc_fieldsplit_detect_saddle_point",&stokes,NULL);CHKERRQ(ierr);
329     ierr = PetscOptionsGetBool(((PetscObject)pc)->options,((PetscObject)pc)->prefix,"-pc_fieldsplit_detect_coupling",&coupling,NULL);CHKERRQ(ierr);
330     if (pc->dm && jac->dm_splits && !stokes && !coupling) {
331       PetscInt  numFields, f, i, j;
332       char      **fieldNames;
333       IS        *fields;
334       DM        *dms;
335       DM        subdm[128];
336       PetscBool flg;
337 
338       ierr = DMCreateFieldDecomposition(pc->dm, &numFields, &fieldNames, &fields, &dms);CHKERRQ(ierr);
339       /* Allow the user to prescribe the splits */
340       for (i = 0, flg = PETSC_TRUE;; i++) {
341         PetscInt ifields[128];
342         IS       compField;
343         char     optionname[128], splitname[8];
344         PetscInt nfields = numFields;
345 
346         ierr = PetscSNPrintf(optionname, sizeof(optionname), "-pc_fieldsplit_%D_fields", i);CHKERRQ(ierr);
347         ierr = PetscOptionsGetIntArray(((PetscObject)pc)->options,((PetscObject)pc)->prefix, optionname, ifields, &nfields, &flg);CHKERRQ(ierr);
348         if (!flg) break;
349         if (numFields > 128) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot currently support %d > 128 fields", numFields);
350         ierr = DMCreateSubDM(pc->dm, nfields, ifields, &compField, &subdm[i]);CHKERRQ(ierr);
351         if (nfields == 1) {
352           ierr = PCFieldSplitSetIS(pc, fieldNames[ifields[0]], compField);CHKERRQ(ierr);
353         } else {
354           ierr = PetscSNPrintf(splitname, sizeof(splitname), "%D", i);CHKERRQ(ierr);
355           ierr = PCFieldSplitSetIS(pc, splitname, compField);CHKERRQ(ierr);
356         }
357         ierr = ISDestroy(&compField);CHKERRQ(ierr);
358         for (j = 0; j < nfields; ++j) {
359           f    = ifields[j];
360           ierr = PetscFree(fieldNames[f]);CHKERRQ(ierr);
361           ierr = ISDestroy(&fields[f]);CHKERRQ(ierr);
362         }
363       }
364       if (i == 0) {
365         for (f = 0; f < numFields; ++f) {
366           ierr = PCFieldSplitSetIS(pc, fieldNames[f], fields[f]);CHKERRQ(ierr);
367           ierr = PetscFree(fieldNames[f]);CHKERRQ(ierr);
368           ierr = ISDestroy(&fields[f]);CHKERRQ(ierr);
369         }
370       } else {
371         for (j=0; j<numFields; j++) {
372           ierr = DMDestroy(dms+j);CHKERRQ(ierr);
373         }
374         ierr = PetscFree(dms);CHKERRQ(ierr);
375         ierr = PetscMalloc1(i, &dms);CHKERRQ(ierr);
376         for (j = 0; j < i; ++j) dms[j] = subdm[j];
377       }
378       ierr = PetscFree(fieldNames);CHKERRQ(ierr);
379       ierr = PetscFree(fields);CHKERRQ(ierr);
380       if (dms) {
381         ierr = PetscInfo(pc, "Setting up physics based fieldsplit preconditioner using the embedded DM\n");CHKERRQ(ierr);
382         for (ilink = jac->head, i = 0; ilink; ilink = ilink->next, ++i) {
383           const char *prefix;
384           ierr = PetscObjectGetOptionsPrefix((PetscObject)(ilink->ksp),&prefix);CHKERRQ(ierr);
385           ierr = PetscObjectSetOptionsPrefix((PetscObject)(dms[i]), prefix);CHKERRQ(ierr);
386           ierr = KSPSetDM(ilink->ksp, dms[i]);CHKERRQ(ierr);
387           ierr = KSPSetDMActive(ilink->ksp, PETSC_FALSE);CHKERRQ(ierr);
388           ierr = PetscObjectIncrementTabLevel((PetscObject)dms[i],(PetscObject)ilink->ksp,0);CHKERRQ(ierr);
389           ierr = DMDestroy(&dms[i]);CHKERRQ(ierr);
390         }
391         ierr = PetscFree(dms);CHKERRQ(ierr);
392       }
393     } else {
394       if (jac->bs <= 0) {
395         if (pc->pmat) {
396           ierr = MatGetBlockSize(pc->pmat,&jac->bs);CHKERRQ(ierr);
397         } else jac->bs = 1;
398       }
399 
400       if (stokes) {
401         IS       zerodiags,rest;
402         PetscInt nmin,nmax;
403 
404         ierr = MatGetOwnershipRange(pc->mat,&nmin,&nmax);CHKERRQ(ierr);
405         ierr = MatFindZeroDiagonals(pc->mat,&zerodiags);CHKERRQ(ierr);
406         ierr = ISComplement(zerodiags,nmin,nmax,&rest);CHKERRQ(ierr);
407         ierr = PCFieldSplitSetIS(pc,"0",rest);CHKERRQ(ierr);
408         ierr = PCFieldSplitSetIS(pc,"1",zerodiags);CHKERRQ(ierr);
409         ierr = ISDestroy(&zerodiags);CHKERRQ(ierr);
410         ierr = ISDestroy(&rest);CHKERRQ(ierr);
411       } else if (coupling) {
412         IS       coupling,rest;
413         PetscInt nmin,nmax;
414 
415         ierr = MatGetOwnershipRange(pc->mat,&nmin,&nmax);CHKERRQ(ierr);
416         ierr = MatFindOffBlockDiagonalEntries(pc->mat,&coupling);CHKERRQ(ierr);
417         ierr = ISCreateStride(PetscObjectComm((PetscObject)pc->mat),nmax-nmin,nmin,1,&rest);CHKERRQ(ierr);
418         ierr = ISSetIdentity(rest);CHKERRQ(ierr);
419         ierr = PCFieldSplitSetIS(pc,"0",rest);CHKERRQ(ierr);
420         ierr = PCFieldSplitSetIS(pc,"1",coupling);CHKERRQ(ierr);
421         ierr = ISDestroy(&coupling);CHKERRQ(ierr);
422         ierr = ISDestroy(&rest);CHKERRQ(ierr);
423       } else {
424         ierr = PetscOptionsGetBool(((PetscObject)pc)->options,((PetscObject)pc)->prefix,"-pc_fieldsplit_default",&fieldsplit_default,NULL);CHKERRQ(ierr);
425         if (!fieldsplit_default) {
426           /* Allow user to set fields from command line,  if bs was known at the time of PCSetFromOptions_FieldSplit()
427            then it is set there. This is not ideal because we should only have options set in XXSetFromOptions(). */
428           ierr = PCFieldSplitSetRuntimeSplits_Private(pc);CHKERRQ(ierr);
429           if (jac->splitdefined) {ierr = PetscInfo(pc,"Splits defined using the options database\n");CHKERRQ(ierr);}
430         }
431         if ((fieldsplit_default || !jac->splitdefined) && !jac->isrestrict) {
432           ierr = PetscInfo(pc,"Using default splitting of fields\n");CHKERRQ(ierr);
433           for (i=0; i<jac->bs; i++) {
434             char splitname[8];
435             ierr = PetscSNPrintf(splitname,sizeof(splitname),"%D",i);CHKERRQ(ierr);
436             ierr = PCFieldSplitSetFields(pc,splitname,1,&i,&i);CHKERRQ(ierr);
437           }
438           jac->defaultsplit = PETSC_TRUE;
439         }
440       }
441     }
442   } else if (jac->nsplits == 1) {
443     if (ilink->is) {
444       IS       is2;
445       PetscInt nmin,nmax;
446 
447       ierr = MatGetOwnershipRange(pc->mat,&nmin,&nmax);CHKERRQ(ierr);
448       ierr = ISComplement(ilink->is,nmin,nmax,&is2);CHKERRQ(ierr);
449       ierr = PCFieldSplitSetIS(pc,"1",is2);CHKERRQ(ierr);
450       ierr = ISDestroy(&is2);CHKERRQ(ierr);
451     } else SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Must provide at least two sets of fields to PCFieldSplit()");
452   }
453 
454   if (jac->nsplits < 2) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Unhandled case, must have at least two fields, not %d", jac->nsplits);
455   PetscFunctionReturn(0);
456 }
457 
458 PETSC_EXTERN PetscErrorCode PetscOptionsFindPairPrefix_Private(PetscOptions,const char pre[], const char name[], char *value[], PetscBool *flg);
459 
460 static PetscErrorCode PCSetUp_FieldSplit(PC pc)
461 {
462   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
463   PetscErrorCode    ierr;
464   PC_FieldSplitLink ilink;
465   PetscInt          i,nsplit;
466   PetscBool         sorted, sorted_col;
467 
468   PetscFunctionBegin;
469   ierr   = PCFieldSplitSetDefaults(pc);CHKERRQ(ierr);
470   nsplit = jac->nsplits;
471   ilink  = jac->head;
472 
473   /* get the matrices for each split */
474   if (!jac->issetup) {
475     PetscInt rstart,rend,nslots,bs;
476 
477     jac->issetup = PETSC_TRUE;
478 
479     /* This is done here instead of in PCFieldSplitSetFields() because may not have matrix at that point */
480     if (jac->defaultsplit || !ilink->is) {
481       if (jac->bs <= 0) jac->bs = nsplit;
482     }
483     bs     = jac->bs;
484     ierr   = MatGetOwnershipRange(pc->pmat,&rstart,&rend);CHKERRQ(ierr);
485     nslots = (rend - rstart)/bs;
486     for (i=0; i<nsplit; i++) {
487       if (jac->defaultsplit) {
488         ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),nslots,rstart+i,nsplit,&ilink->is);CHKERRQ(ierr);
489         ierr = ISDuplicate(ilink->is,&ilink->is_col);CHKERRQ(ierr);
490       } else if (!ilink->is) {
491         if (ilink->nfields > 1) {
492           PetscInt *ii,*jj,j,k,nfields = ilink->nfields,*fields = ilink->fields,*fields_col = ilink->fields_col;
493           ierr = PetscMalloc1(ilink->nfields*nslots,&ii);CHKERRQ(ierr);
494           ierr = PetscMalloc1(ilink->nfields*nslots,&jj);CHKERRQ(ierr);
495           for (j=0; j<nslots; j++) {
496             for (k=0; k<nfields; k++) {
497               ii[nfields*j + k] = rstart + bs*j + fields[k];
498               jj[nfields*j + k] = rstart + bs*j + fields_col[k];
499             }
500           }
501           ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nslots*nfields,ii,PETSC_OWN_POINTER,&ilink->is);CHKERRQ(ierr);
502           ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nslots*nfields,jj,PETSC_OWN_POINTER,&ilink->is_col);CHKERRQ(ierr);
503           ierr = ISSetBlockSize(ilink->is, nfields);CHKERRQ(ierr);
504           ierr = ISSetBlockSize(ilink->is_col, nfields);CHKERRQ(ierr);
505         } else {
506           ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),nslots,rstart+ilink->fields[0],bs,&ilink->is);CHKERRQ(ierr);
507           ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),nslots,rstart+ilink->fields_col[0],bs,&ilink->is_col);CHKERRQ(ierr);
508        }
509       }
510       ierr = ISSorted(ilink->is,&sorted);CHKERRQ(ierr);
511       if (ilink->is_col) { ierr = ISSorted(ilink->is_col,&sorted_col);CHKERRQ(ierr); }
512       if (!sorted || !sorted_col) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Fields must be sorted when creating split");
513       ilink = ilink->next;
514     }
515   }
516 
517   ilink = jac->head;
518   if (!jac->pmat) {
519     Vec xtmp;
520 
521     ierr = MatCreateVecs(pc->pmat,&xtmp,NULL);CHKERRQ(ierr);
522     ierr = PetscMalloc1(nsplit,&jac->pmat);CHKERRQ(ierr);
523     ierr = PetscMalloc2(nsplit,&jac->x,nsplit,&jac->y);CHKERRQ(ierr);
524     for (i=0; i<nsplit; i++) {
525       MatNullSpace sp;
526 
527       /* Check for preconditioning matrix attached to IS */
528       ierr = PetscObjectQuery((PetscObject) ilink->is, "pmat", (PetscObject*) &jac->pmat[i]);CHKERRQ(ierr);
529       if (jac->pmat[i]) {
530         ierr = PetscObjectReference((PetscObject) jac->pmat[i]);CHKERRQ(ierr);
531         if (jac->type == PC_COMPOSITE_SCHUR) {
532           jac->schur_user = jac->pmat[i];
533 
534           ierr = PetscObjectReference((PetscObject) jac->schur_user);CHKERRQ(ierr);
535         }
536       } else {
537         const char *prefix;
538         ierr = MatCreateSubMatrix(pc->pmat,ilink->is,ilink->is_col,MAT_INITIAL_MATRIX,&jac->pmat[i]);CHKERRQ(ierr);
539         ierr = KSPGetOptionsPrefix(ilink->ksp,&prefix);CHKERRQ(ierr);
540         ierr = MatSetOptionsPrefix(jac->pmat[i],prefix);CHKERRQ(ierr);
541         ierr = MatViewFromOptions(jac->pmat[i],NULL,"-mat_view");CHKERRQ(ierr);
542       }
543       /* create work vectors for each split */
544       ierr     = MatCreateVecs(jac->pmat[i],&jac->x[i],&jac->y[i]);CHKERRQ(ierr);
545       ilink->x = jac->x[i]; ilink->y = jac->y[i]; ilink->z = NULL;
546       /* compute scatter contexts needed by multiplicative versions and non-default splits */
547       ierr = VecScatterCreate(xtmp,ilink->is,jac->x[i],NULL,&ilink->sctx);CHKERRQ(ierr);
548       ierr = PetscObjectQuery((PetscObject) ilink->is, "nearnullspace", (PetscObject*) &sp);CHKERRQ(ierr);
549       if (sp) {
550         ierr = MatSetNearNullSpace(jac->pmat[i], sp);CHKERRQ(ierr);
551       }
552       ilink = ilink->next;
553     }
554     ierr = VecDestroy(&xtmp);CHKERRQ(ierr);
555   } else {
556     for (i=0; i<nsplit; i++) {
557       Mat pmat;
558 
559       /* Check for preconditioning matrix attached to IS */
560       ierr = PetscObjectQuery((PetscObject) ilink->is, "pmat", (PetscObject*) &pmat);CHKERRQ(ierr);
561       if (!pmat) {
562         ierr = MatCreateSubMatrix(pc->pmat,ilink->is,ilink->is_col,MAT_REUSE_MATRIX,&jac->pmat[i]);CHKERRQ(ierr);
563       }
564       ilink = ilink->next;
565     }
566   }
567   if (jac->diag_use_amat) {
568     ilink = jac->head;
569     if (!jac->mat) {
570       ierr = PetscMalloc1(nsplit,&jac->mat);CHKERRQ(ierr);
571       for (i=0; i<nsplit; i++) {
572         ierr  = MatCreateSubMatrix(pc->mat,ilink->is,ilink->is_col,MAT_INITIAL_MATRIX,&jac->mat[i]);CHKERRQ(ierr);
573         ilink = ilink->next;
574       }
575     } else {
576       for (i=0; i<nsplit; i++) {
577         if (jac->mat[i]) {ierr = MatCreateSubMatrix(pc->mat,ilink->is,ilink->is_col,MAT_REUSE_MATRIX,&jac->mat[i]);CHKERRQ(ierr);}
578         ilink = ilink->next;
579       }
580     }
581   } else {
582     jac->mat = jac->pmat;
583   }
584 
585   /* Check for null space attached to IS */
586   ilink = jac->head;
587   for (i=0; i<nsplit; i++) {
588     MatNullSpace sp;
589 
590     ierr = PetscObjectQuery((PetscObject) ilink->is, "nullspace", (PetscObject*) &sp);CHKERRQ(ierr);
591     if (sp) {
592       ierr = MatSetNullSpace(jac->mat[i], sp);CHKERRQ(ierr);
593     }
594     ilink = ilink->next;
595   }
596 
597   if (jac->type != PC_COMPOSITE_ADDITIVE  && jac->type != PC_COMPOSITE_SCHUR) {
598     /* extract the rows of the matrix associated with each field: used for efficient computation of residual inside algorithm */
599     /* FIXME: Can/should we reuse jac->mat whenever (jac->diag_use_amat) is true? */
600     ilink = jac->head;
601     if (nsplit == 2 && jac->type == PC_COMPOSITE_MULTIPLICATIVE) {
602       /* 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 */
603       if (!jac->Afield) {
604         ierr = PetscCalloc1(nsplit,&jac->Afield);CHKERRQ(ierr);
605         if (jac->offdiag_use_amat) {
606           ierr  = MatCreateSubMatrix(pc->mat,ilink->next->is,ilink->is,MAT_INITIAL_MATRIX,&jac->Afield[1]);CHKERRQ(ierr);
607         } else {
608           ierr  = MatCreateSubMatrix(pc->pmat,ilink->next->is,ilink->is,MAT_INITIAL_MATRIX,&jac->Afield[1]);CHKERRQ(ierr);
609         }
610       } else {
611         if (jac->offdiag_use_amat) {
612           ierr  = MatCreateSubMatrix(pc->mat,ilink->next->is,ilink->is,MAT_REUSE_MATRIX,&jac->Afield[1]);CHKERRQ(ierr);
613         } else {
614           ierr  = MatCreateSubMatrix(pc->pmat,ilink->next->is,ilink->is,MAT_REUSE_MATRIX,&jac->Afield[1]);CHKERRQ(ierr);
615         }
616       }
617     } else {
618       if (!jac->Afield) {
619         ierr = PetscMalloc1(nsplit,&jac->Afield);CHKERRQ(ierr);
620         for (i=0; i<nsplit; i++) {
621           if (jac->offdiag_use_amat) {
622             ierr  = MatCreateSubMatrix(pc->mat,ilink->is,NULL,MAT_INITIAL_MATRIX,&jac->Afield[i]);CHKERRQ(ierr);
623           } else {
624             ierr  = MatCreateSubMatrix(pc->pmat,ilink->is,NULL,MAT_INITIAL_MATRIX,&jac->Afield[i]);CHKERRQ(ierr);
625           }
626           ilink = ilink->next;
627         }
628       } else {
629         for (i=0; i<nsplit; i++) {
630           if (jac->offdiag_use_amat) {
631             ierr  = MatCreateSubMatrix(pc->mat,ilink->is,NULL,MAT_REUSE_MATRIX,&jac->Afield[i]);CHKERRQ(ierr);
632           } else {
633             ierr  = MatCreateSubMatrix(pc->pmat,ilink->is,NULL,MAT_REUSE_MATRIX,&jac->Afield[i]);CHKERRQ(ierr);
634           }
635           ilink = ilink->next;
636         }
637       }
638     }
639   }
640 
641   if (jac->type == PC_COMPOSITE_SCHUR) {
642     IS          ccis;
643     PetscInt    rstart,rend;
644     char        lscname[256];
645     PetscObject LSC_L;
646 
647     if (nsplit != 2) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_INCOMP,"To use Schur complement preconditioner you must have exactly 2 fields");
648 
649     /* When extracting off-diagonal submatrices, we take complements from this range */
650     ierr = MatGetOwnershipRangeColumn(pc->mat,&rstart,&rend);CHKERRQ(ierr);
651 
652     /* need to handle case when one is resetting up the preconditioner */
653     if (jac->schur) {
654       KSP kspA = jac->head->ksp, kspInner = NULL, kspUpper = jac->kspupper;
655 
656       ierr  = MatSchurComplementGetKSP(jac->schur, &kspInner);CHKERRQ(ierr);
657       ilink = jac->head;
658       ierr  = ISComplement(ilink->is_col,rstart,rend,&ccis);CHKERRQ(ierr);
659       if (jac->offdiag_use_amat) {
660 	ierr  = MatCreateSubMatrix(pc->mat,ilink->is,ccis,MAT_REUSE_MATRIX,&jac->B);CHKERRQ(ierr);
661       } else {
662 	ierr  = MatCreateSubMatrix(pc->pmat,ilink->is,ccis,MAT_REUSE_MATRIX,&jac->B);CHKERRQ(ierr);
663       }
664       ierr  = ISDestroy(&ccis);CHKERRQ(ierr);
665       ilink = ilink->next;
666       ierr  = ISComplement(ilink->is_col,rstart,rend,&ccis);CHKERRQ(ierr);
667       if (jac->offdiag_use_amat) {
668 	ierr  = MatCreateSubMatrix(pc->mat,ilink->is,ccis,MAT_REUSE_MATRIX,&jac->C);CHKERRQ(ierr);
669       } else {
670 	ierr  = MatCreateSubMatrix(pc->pmat,ilink->is,ccis,MAT_REUSE_MATRIX,&jac->C);CHKERRQ(ierr);
671       }
672       ierr  = ISDestroy(&ccis);CHKERRQ(ierr);
673       ierr  = MatSchurComplementUpdateSubMatrices(jac->schur,jac->mat[0],jac->pmat[0],jac->B,jac->C,jac->mat[1]);CHKERRQ(ierr);
674       if (jac->schurpre == PC_FIELDSPLIT_SCHUR_PRE_SELFP) {
675 	ierr = MatDestroy(&jac->schurp);CHKERRQ(ierr);
676 	ierr = MatSchurComplementGetPmat(jac->schur,MAT_INITIAL_MATRIX,&jac->schurp);CHKERRQ(ierr);
677       }
678       if (kspA != kspInner) {
679         ierr = KSPSetOperators(kspA,jac->mat[0],jac->pmat[0]);CHKERRQ(ierr);
680       }
681       if (kspUpper != kspA) {
682         ierr = KSPSetOperators(kspUpper,jac->mat[0],jac->pmat[0]);CHKERRQ(ierr);
683       }
684       ierr = KSPSetOperators(jac->kspschur,jac->schur,FieldSplitSchurPre(jac));CHKERRQ(ierr);
685     } else {
686       const char   *Dprefix;
687       char         schurprefix[256], schurmatprefix[256];
688       char         schurtestoption[256];
689       MatNullSpace sp;
690       PetscBool    flg;
691 
692       /* extract the A01 and A10 matrices */
693       ilink = jac->head;
694       ierr  = ISComplement(ilink->is_col,rstart,rend,&ccis);CHKERRQ(ierr);
695       if (jac->offdiag_use_amat) {
696 	ierr  = MatCreateSubMatrix(pc->mat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->B);CHKERRQ(ierr);
697       } else {
698 	ierr  = MatCreateSubMatrix(pc->pmat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->B);CHKERRQ(ierr);
699       }
700       ierr  = ISDestroy(&ccis);CHKERRQ(ierr);
701       ilink = ilink->next;
702       ierr  = ISComplement(ilink->is_col,rstart,rend,&ccis);CHKERRQ(ierr);
703       if (jac->offdiag_use_amat) {
704 	ierr  = MatCreateSubMatrix(pc->mat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->C);CHKERRQ(ierr);
705       } else {
706 	ierr  = MatCreateSubMatrix(pc->pmat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->C);CHKERRQ(ierr);
707       }
708       ierr  = ISDestroy(&ccis);CHKERRQ(ierr);
709 
710       /* Use mat[0] (diagonal block of Amat) preconditioned by pmat[0] to define Schur complement */
711       ierr = MatCreate(((PetscObject)jac->mat[0])->comm,&jac->schur);CHKERRQ(ierr);
712       ierr = MatSetType(jac->schur,MATSCHURCOMPLEMENT);CHKERRQ(ierr);
713       ierr = MatSchurComplementSetSubMatrices(jac->schur,jac->mat[0],jac->pmat[0],jac->B,jac->C,jac->mat[1]);CHKERRQ(ierr);
714       ierr = PetscSNPrintf(schurmatprefix, sizeof(schurmatprefix), "%sfieldsplit_%s_", ((PetscObject)pc)->prefix ? ((PetscObject)pc)->prefix : "", ilink->splitname);CHKERRQ(ierr);
715       /* Note that the inner KSP is NOT going to inherit this prefix, and if it did, it would be reset just below.  Is that what we want? */
716       ierr = MatSetOptionsPrefix(jac->schur,schurmatprefix);CHKERRQ(ierr);
717       ierr = MatSetFromOptions(jac->schur);CHKERRQ(ierr);
718       ierr = MatGetNullSpace(jac->mat[1], &sp);CHKERRQ(ierr);
719       if (sp) {
720         ierr = MatSetNullSpace(jac->schur, sp);CHKERRQ(ierr);
721       }
722 
723       ierr = PetscSNPrintf(schurtestoption, sizeof(schurtestoption), "-fieldsplit_%s_inner_", ilink->splitname);CHKERRQ(ierr);
724       ierr = PetscOptionsFindPairPrefix_Private(((PetscObject)pc)->options,((PetscObject)pc)->prefix, schurtestoption, NULL, &flg);CHKERRQ(ierr);
725       if (flg) {
726         DM  dmInner;
727         KSP kspInner;
728 
729         ierr = MatSchurComplementGetKSP(jac->schur, &kspInner);CHKERRQ(ierr);
730         ierr = PetscSNPrintf(schurprefix, sizeof(schurprefix), "%sfieldsplit_%s_inner_", ((PetscObject)pc)->prefix ? ((PetscObject)pc)->prefix : "", ilink->splitname);CHKERRQ(ierr);
731         /* Indent this deeper to emphasize the "inner" nature of this solver. */
732         ierr = PetscObjectIncrementTabLevel((PetscObject)kspInner, (PetscObject) pc, 2);CHKERRQ(ierr);
733         ierr = KSPSetOptionsPrefix(kspInner, schurprefix);CHKERRQ(ierr);
734 
735         /* Set DM for new solver */
736         ierr = KSPGetDM(jac->head->ksp, &dmInner);CHKERRQ(ierr);
737         ierr = KSPSetDM(kspInner, dmInner);CHKERRQ(ierr);
738         ierr = KSPSetDMActive(kspInner, PETSC_FALSE);CHKERRQ(ierr);
739       } else {
740          /* Use the outer solver for the inner solve, but revert the KSPPREONLY from PCFieldSplitSetFields_FieldSplit or
741           * PCFieldSplitSetIS_FieldSplit. We don't want KSPPREONLY because it makes the Schur complement inexact,
742           * preventing Schur complement reduction to be an accurate solve. Usually when an iterative solver is used for
743           * S = D - C A_inner^{-1} B, we expect S to be defined using an accurate definition of A_inner^{-1}, so we make
744           * GMRES the default. Note that it is also common to use PREONLY for S, in which case S may not be used
745           * directly, and the user is responsible for setting an inexact method for fieldsplit's A^{-1}. */
746         ierr = KSPSetType(jac->head->ksp,KSPGMRES);CHKERRQ(ierr);
747         ierr = MatSchurComplementSetKSP(jac->schur,jac->head->ksp);CHKERRQ(ierr);
748       }
749       ierr = KSPSetOperators(jac->head->ksp,jac->mat[0],jac->pmat[0]);CHKERRQ(ierr);
750       ierr = KSPSetFromOptions(jac->head->ksp);CHKERRQ(ierr);
751       ierr = MatSetFromOptions(jac->schur);CHKERRQ(ierr);
752 
753       ierr = PetscSNPrintf(schurtestoption, sizeof(schurtestoption), "-fieldsplit_%s_upper_", ilink->splitname);CHKERRQ(ierr);
754       ierr = PetscOptionsFindPairPrefix_Private(((PetscObject)pc)->options,((PetscObject)pc)->prefix, schurtestoption, NULL, &flg);CHKERRQ(ierr);
755       if (flg) {
756         DM dmInner;
757 
758         ierr = PetscSNPrintf(schurprefix, sizeof(schurprefix), "%sfieldsplit_%s_upper_", ((PetscObject)pc)->prefix ? ((PetscObject)pc)->prefix : "", ilink->splitname);CHKERRQ(ierr);
759         ierr = KSPCreate(PetscObjectComm((PetscObject)pc), &jac->kspupper);CHKERRQ(ierr);
760         ierr = KSPSetErrorIfNotConverged(jac->kspupper,pc->erroriffailure);CHKERRQ(ierr);
761         ierr = KSPSetOptionsPrefix(jac->kspupper, schurprefix);CHKERRQ(ierr);
762         ierr = KSPGetDM(jac->head->ksp, &dmInner);CHKERRQ(ierr);
763         ierr = KSPSetDM(jac->kspupper, dmInner);CHKERRQ(ierr);
764         ierr = KSPSetDMActive(jac->kspupper, PETSC_FALSE);CHKERRQ(ierr);
765         ierr = KSPSetFromOptions(jac->kspupper);CHKERRQ(ierr);
766         ierr = KSPSetOperators(jac->kspupper,jac->mat[0],jac->pmat[0]);CHKERRQ(ierr);
767         ierr = VecDuplicate(jac->head->x, &jac->head->z);CHKERRQ(ierr);
768       } else {
769         jac->kspupper = jac->head->ksp;
770         ierr          = PetscObjectReference((PetscObject) jac->head->ksp);CHKERRQ(ierr);
771       }
772 
773       if (jac->schurpre == PC_FIELDSPLIT_SCHUR_PRE_SELFP) {
774 	ierr = MatSchurComplementGetPmat(jac->schur,MAT_INITIAL_MATRIX,&jac->schurp);CHKERRQ(ierr);
775       }
776       ierr = KSPCreate(PetscObjectComm((PetscObject)pc),&jac->kspschur);CHKERRQ(ierr);
777       ierr = KSPSetErrorIfNotConverged(jac->kspschur,pc->erroriffailure);CHKERRQ(ierr);
778       ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)jac->kspschur);CHKERRQ(ierr);
779       ierr = PetscObjectIncrementTabLevel((PetscObject)jac->kspschur,(PetscObject)pc,1);CHKERRQ(ierr);
780       if (jac->schurpre == PC_FIELDSPLIT_SCHUR_PRE_SELF) {
781         PC pcschur;
782         ierr = KSPGetPC(jac->kspschur,&pcschur);CHKERRQ(ierr);
783         ierr = PCSetType(pcschur,PCNONE);CHKERRQ(ierr);
784         /* Note: This is bad if there exist preconditioners for MATSCHURCOMPLEMENT */
785       } else if (jac->schurpre == PC_FIELDSPLIT_SCHUR_PRE_FULL) {
786         ierr = MatSchurComplementComputeExplicitOperator(jac->schur, &jac->schur_user);CHKERRQ(ierr);
787       }
788       ierr = KSPSetOperators(jac->kspschur,jac->schur,FieldSplitSchurPre(jac));CHKERRQ(ierr);
789       ierr = KSPGetOptionsPrefix(jac->head->next->ksp, &Dprefix);CHKERRQ(ierr);
790       ierr = KSPSetOptionsPrefix(jac->kspschur,         Dprefix);CHKERRQ(ierr);
791       /* propogate DM */
792       {
793         DM sdm;
794         ierr = KSPGetDM(jac->head->next->ksp, &sdm);CHKERRQ(ierr);
795         if (sdm) {
796           ierr = KSPSetDM(jac->kspschur, sdm);CHKERRQ(ierr);
797           ierr = KSPSetDMActive(jac->kspschur, PETSC_FALSE);CHKERRQ(ierr);
798         }
799       }
800       /* really want setfromoptions called in PCSetFromOptions_FieldSplit(), but it is not ready yet */
801       /* need to call this every time, since the jac->kspschur is freshly created, otherwise its options never get set */
802       ierr = KSPSetFromOptions(jac->kspschur);CHKERRQ(ierr);
803     }
804 
805     /* HACK: special support to forward L and Lp matrices that might be used by PCLSC */
806     ierr = PetscSNPrintf(lscname,sizeof(lscname),"%s_LSC_L",ilink->splitname);CHKERRQ(ierr);
807     ierr = PetscObjectQuery((PetscObject)pc->mat,lscname,(PetscObject*)&LSC_L);CHKERRQ(ierr);
808     if (!LSC_L) {ierr = PetscObjectQuery((PetscObject)pc->pmat,lscname,(PetscObject*)&LSC_L);CHKERRQ(ierr);}
809     if (LSC_L) {ierr = PetscObjectCompose((PetscObject)jac->schur,"LSC_L",(PetscObject)LSC_L);CHKERRQ(ierr);}
810     ierr = PetscSNPrintf(lscname,sizeof(lscname),"%s_LSC_Lp",ilink->splitname);CHKERRQ(ierr);
811     ierr = PetscObjectQuery((PetscObject)pc->pmat,lscname,(PetscObject*)&LSC_L);CHKERRQ(ierr);
812     if (!LSC_L) {ierr = PetscObjectQuery((PetscObject)pc->mat,lscname,(PetscObject*)&LSC_L);CHKERRQ(ierr);}
813     if (LSC_L) {ierr = PetscObjectCompose((PetscObject)jac->schur,"LSC_Lp",(PetscObject)LSC_L);CHKERRQ(ierr);}
814   } else {
815     /* set up the individual splits' PCs */
816     i     = 0;
817     ilink = jac->head;
818     while (ilink) {
819       ierr = KSPSetOperators(ilink->ksp,jac->mat[i],jac->pmat[i]);CHKERRQ(ierr);
820       /* really want setfromoptions called in PCSetFromOptions_FieldSplit(), but it is not ready yet */
821       if (!jac->suboptionsset) {ierr = KSPSetFromOptions(ilink->ksp);CHKERRQ(ierr);}
822       i++;
823       ilink = ilink->next;
824     }
825   }
826 
827   jac->suboptionsset = PETSC_TRUE;
828   PetscFunctionReturn(0);
829 }
830 
831 #define FieldSplitSplitSolveAdd(ilink,xx,yy) \
832   (VecScatterBegin(ilink->sctx,xx,ilink->x,INSERT_VALUES,SCATTER_FORWARD) || \
833    VecScatterEnd(ilink->sctx,xx,ilink->x,INSERT_VALUES,SCATTER_FORWARD) || \
834    PetscLogEventBegin(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL) ||\
835    KSPSolve(ilink->ksp,ilink->x,ilink->y) ||                               \
836    PetscLogEventEnd(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL) ||\
837    VecScatterBegin(ilink->sctx,ilink->y,yy,ADD_VALUES,SCATTER_REVERSE) ||  \
838    VecScatterEnd(ilink->sctx,ilink->y,yy,ADD_VALUES,SCATTER_REVERSE))
839 
840 static PetscErrorCode PCApply_FieldSplit_Schur(PC pc,Vec x,Vec y)
841 {
842   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
843   PetscErrorCode    ierr;
844   PC_FieldSplitLink ilinkA = jac->head, ilinkD = ilinkA->next;
845   KSP               kspA   = ilinkA->ksp, kspLower = kspA, kspUpper = jac->kspupper;
846 
847   PetscFunctionBegin;
848   switch (jac->schurfactorization) {
849   case PC_FIELDSPLIT_SCHUR_FACT_DIAG:
850     /* [A00 0; 0 -S], positive definite, suitable for MINRES */
851     ierr = VecScatterBegin(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
852     ierr = VecScatterBegin(ilinkD->sctx,x,ilinkD->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
853     ierr = VecScatterEnd(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
854     ierr = PetscLogEventBegin(ilinkA->event,kspA,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
855     ierr = KSPSolve(kspA,ilinkA->x,ilinkA->y);CHKERRQ(ierr);
856     ierr = PetscLogEventEnd(ilinkA->event,kspA,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
857     ierr = VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
858     ierr = VecScatterEnd(ilinkD->sctx,x,ilinkD->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
859     ierr = PetscLogEventBegin(KSP_Solve_FS_S,jac->kspschur,ilinkD->x,ilinkD->y,NULL);CHKERRQ(ierr);
860     ierr = KSPSolve(jac->kspschur,ilinkD->x,ilinkD->y);CHKERRQ(ierr);
861     ierr = PetscLogEventEnd(KSP_Solve_FS_S,jac->kspschur,ilinkD->x,ilinkD->y,NULL);CHKERRQ(ierr);
862     ierr = VecScale(ilinkD->y,-1.);CHKERRQ(ierr);
863     ierr = VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
864     ierr = VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
865     ierr = VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
866     break;
867   case PC_FIELDSPLIT_SCHUR_FACT_LOWER:
868     /* [A00 0; A10 S], suitable for left preconditioning */
869     ierr = VecScatterBegin(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
870     ierr = VecScatterEnd(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
871     ierr = PetscLogEventBegin(ilinkA->event,kspA,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
872     ierr = KSPSolve(kspA,ilinkA->x,ilinkA->y);CHKERRQ(ierr);
873     ierr = PetscLogEventEnd(ilinkA->event,kspA,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
874     ierr = MatMult(jac->C,ilinkA->y,ilinkD->x);CHKERRQ(ierr);
875     ierr = VecScale(ilinkD->x,-1.);CHKERRQ(ierr);
876     ierr = VecScatterBegin(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
877     ierr = VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
878     ierr = VecScatterEnd(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
879     ierr = PetscLogEventBegin(KSP_Solve_FS_S,jac->kspschur,ilinkD->x,ilinkD->y,NULL);CHKERRQ(ierr);
880     ierr = KSPSolve(jac->kspschur,ilinkD->x,ilinkD->y);CHKERRQ(ierr);
881     ierr = PetscLogEventEnd(KSP_Solve_FS_S,jac->kspschur,ilinkD->x,ilinkD->y,NULL);CHKERRQ(ierr);
882     ierr = VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
883     ierr = VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
884     ierr = VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
885     break;
886   case PC_FIELDSPLIT_SCHUR_FACT_UPPER:
887     /* [A00 A01; 0 S], suitable for right preconditioning */
888     ierr = VecScatterBegin(ilinkD->sctx,x,ilinkD->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
889     ierr = VecScatterEnd(ilinkD->sctx,x,ilinkD->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
890     ierr = PetscLogEventBegin(KSP_Solve_FS_S,jac->kspschur,ilinkD->x,ilinkD->y,NULL);CHKERRQ(ierr);
891     ierr = KSPSolve(jac->kspschur,ilinkD->x,ilinkD->y);CHKERRQ(ierr);
892     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);
893     ierr = VecScale(ilinkA->x,-1.);CHKERRQ(ierr);
894     ierr = VecScatterBegin(ilinkA->sctx,x,ilinkA->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
895     ierr = VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
896     ierr = VecScatterEnd(ilinkA->sctx,x,ilinkA->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
897     ierr = PetscLogEventBegin(ilinkA->event,kspA,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
898     ierr = KSPSolve(kspA,ilinkA->x,ilinkA->y);CHKERRQ(ierr);
899     ierr = PetscLogEventEnd(ilinkA->event,kspA,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
900     ierr = VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
901     ierr = VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
902     ierr = VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
903     break;
904   case PC_FIELDSPLIT_SCHUR_FACT_FULL:
905     /* [1 0; A10 A00^{-1} 1] [A00 0; 0 S] [1 A00^{-1}A01; 0 1], an exact solve if applied exactly, needs one extra solve with A */
906     ierr = VecScatterBegin(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
907     ierr = VecScatterEnd(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
908     ierr = PetscLogEventBegin(KSP_Solve_FS_L,kspLower,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
909     ierr = KSPSolve(kspLower,ilinkA->x,ilinkA->y);CHKERRQ(ierr);
910     ierr = PetscLogEventEnd(KSP_Solve_FS_L,kspLower,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
911     ierr = MatMult(jac->C,ilinkA->y,ilinkD->x);CHKERRQ(ierr);
912     ierr = VecScale(ilinkD->x,-1.0);CHKERRQ(ierr);
913     ierr = VecScatterBegin(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
914     ierr = VecScatterEnd(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
915 
916     ierr = PetscLogEventBegin(KSP_Solve_FS_S,jac->kspschur,ilinkD->x,ilinkD->y,NULL);CHKERRQ(ierr);
917     ierr = KSPSolve(jac->kspschur,ilinkD->x,ilinkD->y);CHKERRQ(ierr);
918     ierr = PetscLogEventEnd(KSP_Solve_FS_S,jac->kspschur,ilinkD->x,ilinkD->y,NULL);CHKERRQ(ierr);
919     ierr = VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
920     ierr = VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
921 
922     if (kspUpper == kspA) {
923       ierr = MatMult(jac->B,ilinkD->y,ilinkA->y);CHKERRQ(ierr);
924       ierr = VecAXPY(ilinkA->x,-1.0,ilinkA->y);CHKERRQ(ierr);
925       ierr = PetscLogEventBegin(ilinkA->event,kspA,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
926       ierr = KSPSolve(kspA,ilinkA->x,ilinkA->y);CHKERRQ(ierr);
927       ierr = PetscLogEventEnd(ilinkA->event,kspA,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
928     } else {
929       ierr = PetscLogEventBegin(ilinkA->event,kspA,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
930       ierr = KSPSolve(kspA,ilinkA->x,ilinkA->y);CHKERRQ(ierr);
931       ierr = PetscLogEventEnd(ilinkA->event,kspA,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
932       ierr = MatMult(jac->B,ilinkD->y,ilinkA->x);CHKERRQ(ierr);
933       ierr = PetscLogEventBegin(KSP_Solve_FS_U,kspUpper,ilinkA->x,ilinkA->z,NULL);CHKERRQ(ierr);
934       ierr = KSPSolve(kspUpper,ilinkA->x,ilinkA->z);CHKERRQ(ierr);
935       ierr = PetscLogEventEnd(KSP_Solve_FS_U,kspUpper,ilinkA->x,ilinkA->z,NULL);CHKERRQ(ierr);
936       ierr = VecAXPY(ilinkA->y,-1.0,ilinkA->z);CHKERRQ(ierr);
937     }
938     ierr = VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
939     ierr = VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
940   }
941   PetscFunctionReturn(0);
942 }
943 
944 static PetscErrorCode PCApply_FieldSplit(PC pc,Vec x,Vec y)
945 {
946   PC_FieldSplit      *jac = (PC_FieldSplit*)pc->data;
947   PetscErrorCode     ierr;
948   PC_FieldSplitLink  ilink = jac->head;
949   PetscInt           cnt,bs;
950   KSPConvergedReason reason;
951 
952   PetscFunctionBegin;
953   if (jac->type == PC_COMPOSITE_ADDITIVE) {
954     if (jac->defaultsplit) {
955       ierr = VecGetBlockSize(x,&bs);CHKERRQ(ierr);
956       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);
957       ierr = VecGetBlockSize(y,&bs);CHKERRQ(ierr);
958       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);
959       ierr = VecStrideGatherAll(x,jac->x,INSERT_VALUES);CHKERRQ(ierr);
960       while (ilink) {
961         ierr  = PetscLogEventBegin(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
962         ierr  = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
963         ierr  = PetscLogEventEnd(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
964         ierr = KSPGetConvergedReason(ilink->ksp,&reason);CHKERRQ(ierr);
965         if (reason == KSP_DIVERGED_PCSETUP_FAILED) {
966           pc->failedreason = PC_SUBPC_ERROR;
967         }
968         ilink = ilink->next;
969       }
970       ierr = VecStrideScatterAll(jac->y,y,INSERT_VALUES);CHKERRQ(ierr);
971     } else {
972       ierr = VecSet(y,0.0);CHKERRQ(ierr);
973       while (ilink) {
974         ierr  = FieldSplitSplitSolveAdd(ilink,x,y);CHKERRQ(ierr);
975         ierr = KSPGetConvergedReason(ilink->ksp,&reason);CHKERRQ(ierr);
976         if (reason == KSP_DIVERGED_PCSETUP_FAILED) {
977           pc->failedreason = PC_SUBPC_ERROR;
978         }
979         ilink = ilink->next;
980       }
981     }
982   } else if (jac->type == PC_COMPOSITE_MULTIPLICATIVE && jac->nsplits == 2) {
983     ierr = VecSet(y,0.0);CHKERRQ(ierr);
984     /* solve on first block for first block variables */
985     ierr = VecScatterBegin(ilink->sctx,x,ilink->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
986     ierr = VecScatterEnd(ilink->sctx,x,ilink->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
987     ierr = PetscLogEventBegin(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
988     ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
989     ierr = PetscLogEventEnd(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
990     ierr = KSPGetConvergedReason(ilink->ksp,&reason);CHKERRQ(ierr);
991     if (reason == KSP_DIVERGED_PCSETUP_FAILED) {
992       pc->failedreason = PC_SUBPC_ERROR;
993     }
994     ierr = VecScatterBegin(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
995     ierr = VecScatterEnd(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
996 
997     /* compute the residual only onto second block variables using first block variables */
998     ierr = MatMult(jac->Afield[1],ilink->y,ilink->next->x);CHKERRQ(ierr);
999     ilink = ilink->next;
1000     ierr = VecScale(ilink->x,-1.0);CHKERRQ(ierr);
1001     ierr = VecScatterBegin(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1002     ierr = VecScatterEnd(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1003 
1004     /* solve on second block variables */
1005     ierr = PetscLogEventBegin(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
1006     ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
1007     ierr = PetscLogEventEnd(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
1008     ierr = KSPGetConvergedReason(ilink->ksp,&reason);CHKERRQ(ierr);
1009     if (reason == KSP_DIVERGED_PCSETUP_FAILED) {
1010       pc->failedreason = PC_SUBPC_ERROR;
1011     }
1012     ierr = VecScatterBegin(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1013     ierr = VecScatterEnd(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1014   } else if (jac->type == PC_COMPOSITE_MULTIPLICATIVE || jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
1015     if (!jac->w1) {
1016       ierr = VecDuplicate(x,&jac->w1);CHKERRQ(ierr);
1017       ierr = VecDuplicate(x,&jac->w2);CHKERRQ(ierr);
1018     }
1019     ierr = VecSet(y,0.0);CHKERRQ(ierr);
1020     ierr = FieldSplitSplitSolveAdd(ilink,x,y);CHKERRQ(ierr);
1021     ierr = KSPGetConvergedReason(ilink->ksp,&reason);CHKERRQ(ierr);
1022     if (reason == KSP_DIVERGED_PCSETUP_FAILED) {
1023       pc->failedreason = PC_SUBPC_ERROR;
1024     }
1025     cnt  = 1;
1026     while (ilink->next) {
1027       ilink = ilink->next;
1028       /* compute the residual only over the part of the vector needed */
1029       ierr = MatMult(jac->Afield[cnt++],y,ilink->x);CHKERRQ(ierr);
1030       ierr = VecScale(ilink->x,-1.0);CHKERRQ(ierr);
1031       ierr = VecScatterBegin(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1032       ierr = VecScatterEnd(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1033       ierr = PetscLogEventBegin(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
1034       ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
1035       ierr = PetscLogEventEnd(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
1036       ierr = KSPGetConvergedReason(ilink->ksp,&reason);CHKERRQ(ierr);
1037       if (reason == KSP_DIVERGED_PCSETUP_FAILED) {
1038         pc->failedreason = PC_SUBPC_ERROR;
1039       }
1040       ierr = VecScatterBegin(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1041       ierr = VecScatterEnd(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1042     }
1043     if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
1044       cnt -= 2;
1045       while (ilink->previous) {
1046         ilink = ilink->previous;
1047         /* compute the residual only over the part of the vector needed */
1048         ierr = MatMult(jac->Afield[cnt--],y,ilink->x);CHKERRQ(ierr);
1049         ierr = VecScale(ilink->x,-1.0);CHKERRQ(ierr);
1050         ierr = VecScatterBegin(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1051         ierr = VecScatterEnd(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1052         ierr = PetscLogEventBegin(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
1053         ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
1054         ierr = PetscLogEventEnd(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
1055         ierr = KSPGetConvergedReason(ilink->ksp,&reason);CHKERRQ(ierr);
1056         if (reason == KSP_DIVERGED_PCSETUP_FAILED) {
1057           pc->failedreason = PC_SUBPC_ERROR;
1058         }
1059         ierr = VecScatterBegin(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1060         ierr = VecScatterEnd(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1061       }
1062     }
1063   } else SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Unsupported or unknown composition",(int) jac->type);
1064   PetscFunctionReturn(0);
1065 }
1066 
1067 #define FieldSplitSplitSolveAddTranspose(ilink,xx,yy) \
1068   (VecScatterBegin(ilink->sctx,xx,ilink->y,INSERT_VALUES,SCATTER_FORWARD) || \
1069    VecScatterEnd(ilink->sctx,xx,ilink->y,INSERT_VALUES,SCATTER_FORWARD) || \
1070    PetscLogEventBegin(ilink->event,ilink->ksp,ilink->y,ilink->x,NULL) || \
1071    KSPSolveTranspose(ilink->ksp,ilink->y,ilink->x) ||                  \
1072    PetscLogEventBegin(ilink->event,ilink->ksp,ilink->y,ilink->x,NULL) || \
1073    VecScatterBegin(ilink->sctx,ilink->x,yy,ADD_VALUES,SCATTER_REVERSE) || \
1074    VecScatterEnd(ilink->sctx,ilink->x,yy,ADD_VALUES,SCATTER_REVERSE))
1075 
1076 static PetscErrorCode PCApplyTranspose_FieldSplit(PC pc,Vec x,Vec y)
1077 {
1078   PC_FieldSplit      *jac = (PC_FieldSplit*)pc->data;
1079   PetscErrorCode     ierr;
1080   PC_FieldSplitLink  ilink = jac->head;
1081   PetscInt           bs;
1082   KSPConvergedReason reason;
1083 
1084   PetscFunctionBegin;
1085   if (jac->type == PC_COMPOSITE_ADDITIVE) {
1086     if (jac->defaultsplit) {
1087       ierr = VecGetBlockSize(x,&bs);CHKERRQ(ierr);
1088       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);
1089       ierr = VecGetBlockSize(y,&bs);CHKERRQ(ierr);
1090       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);
1091       ierr = VecStrideGatherAll(x,jac->x,INSERT_VALUES);CHKERRQ(ierr);
1092       while (ilink) {
1093         ierr = PetscLogEventBegin(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
1094         ierr  = KSPSolveTranspose(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
1095         ierr = PetscLogEventEnd(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
1096         ierr = KSPGetConvergedReason(ilink->ksp,&reason);CHKERRQ(ierr);
1097         if (reason == KSP_DIVERGED_PCSETUP_FAILED) {
1098           pc->failedreason = PC_SUBPC_ERROR;
1099         }
1100         ilink = ilink->next;
1101       }
1102       ierr = VecStrideScatterAll(jac->y,y,INSERT_VALUES);CHKERRQ(ierr);
1103     } else {
1104       ierr = VecSet(y,0.0);CHKERRQ(ierr);
1105       while (ilink) {
1106         ierr = FieldSplitSplitSolveAddTranspose(ilink,x,y);CHKERRQ(ierr);
1107         ierr = KSPGetConvergedReason(ilink->ksp,&reason);CHKERRQ(ierr);
1108         if (reason == KSP_DIVERGED_PCSETUP_FAILED) {
1109           pc->failedreason = PC_SUBPC_ERROR;
1110         }
1111         ilink = ilink->next;
1112       }
1113     }
1114   } else {
1115     if (!jac->w1) {
1116       ierr = VecDuplicate(x,&jac->w1);CHKERRQ(ierr);
1117       ierr = VecDuplicate(x,&jac->w2);CHKERRQ(ierr);
1118     }
1119     ierr = VecSet(y,0.0);CHKERRQ(ierr);
1120     if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
1121       ierr = FieldSplitSplitSolveAddTranspose(ilink,x,y);CHKERRQ(ierr);
1122       ierr = KSPGetConvergedReason(ilink->ksp,&reason);CHKERRQ(ierr);
1123       if (reason == KSP_DIVERGED_PCSETUP_FAILED) {
1124         pc->failedreason = PC_SUBPC_ERROR;
1125       }
1126       while (ilink->next) {
1127         ilink = ilink->next;
1128         ierr  = MatMultTranspose(pc->mat,y,jac->w1);CHKERRQ(ierr);
1129         ierr  = VecWAXPY(jac->w2,-1.0,jac->w1,x);CHKERRQ(ierr);
1130         ierr  = FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);CHKERRQ(ierr);
1131       }
1132       while (ilink->previous) {
1133         ilink = ilink->previous;
1134         ierr  = MatMultTranspose(pc->mat,y,jac->w1);CHKERRQ(ierr);
1135         ierr  = VecWAXPY(jac->w2,-1.0,jac->w1,x);CHKERRQ(ierr);
1136         ierr  = FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);CHKERRQ(ierr);
1137       }
1138     } else {
1139       while (ilink->next) {   /* get to last entry in linked list */
1140         ilink = ilink->next;
1141       }
1142       ierr = FieldSplitSplitSolveAddTranspose(ilink,x,y);CHKERRQ(ierr);
1143       ierr = KSPGetConvergedReason(ilink->ksp,&reason);CHKERRQ(ierr);
1144       if (reason == KSP_DIVERGED_PCSETUP_FAILED) {
1145         pc->failedreason = PC_SUBPC_ERROR;
1146       }
1147       while (ilink->previous) {
1148         ilink = ilink->previous;
1149         ierr  = MatMultTranspose(pc->mat,y,jac->w1);CHKERRQ(ierr);
1150         ierr  = VecWAXPY(jac->w2,-1.0,jac->w1,x);CHKERRQ(ierr);
1151         ierr  = FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);CHKERRQ(ierr);
1152       }
1153     }
1154   }
1155   PetscFunctionReturn(0);
1156 }
1157 
1158 static PetscErrorCode PCReset_FieldSplit(PC pc)
1159 {
1160   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
1161   PetscErrorCode    ierr;
1162   PC_FieldSplitLink ilink = jac->head,next;
1163 
1164   PetscFunctionBegin;
1165   while (ilink) {
1166     ierr  = KSPDestroy(&ilink->ksp);CHKERRQ(ierr);
1167     ierr  = VecDestroy(&ilink->x);CHKERRQ(ierr);
1168     ierr  = VecDestroy(&ilink->y);CHKERRQ(ierr);
1169     ierr  = VecDestroy(&ilink->z);CHKERRQ(ierr);
1170     ierr  = VecScatterDestroy(&ilink->sctx);CHKERRQ(ierr);
1171     ierr  = ISDestroy(&ilink->is);CHKERRQ(ierr);
1172     ierr  = ISDestroy(&ilink->is_col);CHKERRQ(ierr);
1173     ierr  = PetscFree(ilink->splitname);CHKERRQ(ierr);
1174     ierr  = PetscFree(ilink->fields);CHKERRQ(ierr);
1175     ierr  = PetscFree(ilink->fields_col);CHKERRQ(ierr);
1176     next  = ilink->next;
1177     ierr  = PetscFree(ilink);CHKERRQ(ierr);
1178     ilink = next;
1179   }
1180   jac->head = NULL;
1181   ierr = PetscFree2(jac->x,jac->y);CHKERRQ(ierr);
1182   if (jac->mat && jac->mat != jac->pmat) {
1183     ierr = MatDestroyMatrices(jac->nsplits,&jac->mat);CHKERRQ(ierr);
1184   } else if (jac->mat) {
1185     jac->mat = NULL;
1186   }
1187   if (jac->pmat) {ierr = MatDestroyMatrices(jac->nsplits,&jac->pmat);CHKERRQ(ierr);}
1188   if (jac->Afield) {ierr = MatDestroyMatrices(jac->nsplits,&jac->Afield);CHKERRQ(ierr);}
1189   jac->nsplits = 0;
1190   ierr       = VecDestroy(&jac->w1);CHKERRQ(ierr);
1191   ierr       = VecDestroy(&jac->w2);CHKERRQ(ierr);
1192   ierr       = MatDestroy(&jac->schur);CHKERRQ(ierr);
1193   ierr       = MatDestroy(&jac->schurp);CHKERRQ(ierr);
1194   ierr       = MatDestroy(&jac->schur_user);CHKERRQ(ierr);
1195   ierr       = KSPDestroy(&jac->kspschur);CHKERRQ(ierr);
1196   ierr       = KSPDestroy(&jac->kspupper);CHKERRQ(ierr);
1197   ierr       = MatDestroy(&jac->B);CHKERRQ(ierr);
1198   ierr       = MatDestroy(&jac->C);CHKERRQ(ierr);
1199   jac->isrestrict = PETSC_FALSE;
1200   PetscFunctionReturn(0);
1201 }
1202 
1203 static PetscErrorCode PCDestroy_FieldSplit(PC pc)
1204 {
1205   PetscErrorCode    ierr;
1206 
1207   PetscFunctionBegin;
1208   ierr = PCReset_FieldSplit(pc);CHKERRQ(ierr);
1209   ierr = PetscFree(pc->data);CHKERRQ(ierr);
1210   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitGetSubKSP_C",NULL);CHKERRQ(ierr);
1211   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetFields_C",NULL);CHKERRQ(ierr);
1212   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetIS_C",NULL);CHKERRQ(ierr);
1213   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetType_C",NULL);CHKERRQ(ierr);
1214   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetBlockSize_C",NULL);CHKERRQ(ierr);
1215   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetSchurPre_C",NULL);CHKERRQ(ierr);
1216   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitGetSchurPre_C",NULL);CHKERRQ(ierr);
1217   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetSchurFactType_C",NULL);CHKERRQ(ierr);
1218   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitRestrictIS_C",NULL);CHKERRQ(ierr);
1219   PetscFunctionReturn(0);
1220 }
1221 
1222 static PetscErrorCode PCSetFromOptions_FieldSplit(PetscOptionItems *PetscOptionsObject,PC pc)
1223 {
1224   PetscErrorCode  ierr;
1225   PetscInt        bs;
1226   PetscBool       flg,stokes = PETSC_FALSE;
1227   PC_FieldSplit   *jac = (PC_FieldSplit*)pc->data;
1228   PCCompositeType ctype;
1229 
1230   PetscFunctionBegin;
1231   ierr = PetscOptionsHead(PetscOptionsObject,"FieldSplit options");CHKERRQ(ierr);
1232   ierr = PetscOptionsBool("-pc_fieldsplit_dm_splits","Whether to use DMCreateFieldDecomposition() for splits","PCFieldSplitSetDMSplits",jac->dm_splits,&jac->dm_splits,NULL);CHKERRQ(ierr);
1233   ierr = PetscOptionsInt("-pc_fieldsplit_block_size","Blocksize that defines number of fields","PCFieldSplitSetBlockSize",jac->bs,&bs,&flg);CHKERRQ(ierr);
1234   if (flg) {
1235     ierr = PCFieldSplitSetBlockSize(pc,bs);CHKERRQ(ierr);
1236   }
1237   jac->diag_use_amat = pc->useAmat;
1238   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);
1239   jac->offdiag_use_amat = pc->useAmat;
1240   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);
1241   /* FIXME: No programmatic equivalent to the following. */
1242   ierr = PetscOptionsGetBool(((PetscObject)pc)->options,((PetscObject)pc)->prefix,"-pc_fieldsplit_detect_saddle_point",&stokes,NULL);CHKERRQ(ierr);
1243   if (stokes) {
1244     ierr          = PCFieldSplitSetType(pc,PC_COMPOSITE_SCHUR);CHKERRQ(ierr);
1245     jac->schurpre = PC_FIELDSPLIT_SCHUR_PRE_SELF;
1246   }
1247 
1248   ierr = PetscOptionsEnum("-pc_fieldsplit_type","Type of composition","PCFieldSplitSetType",PCCompositeTypes,(PetscEnum)jac->type,(PetscEnum*)&ctype,&flg);CHKERRQ(ierr);
1249   if (flg) {
1250     ierr = PCFieldSplitSetType(pc,ctype);CHKERRQ(ierr);
1251   }
1252   /* Only setup fields once */
1253   if ((jac->bs > 0) && (jac->nsplits == 0)) {
1254     /* only allow user to set fields from command line if bs is already known.
1255        otherwise user can set them in PCFieldSplitSetDefaults() */
1256     ierr = PCFieldSplitSetRuntimeSplits_Private(pc);CHKERRQ(ierr);
1257     if (jac->splitdefined) {ierr = PetscInfo(pc,"Splits defined using the options database\n");CHKERRQ(ierr);}
1258   }
1259   if (jac->type == PC_COMPOSITE_SCHUR) {
1260     ierr = PetscOptionsGetEnum(((PetscObject)pc)->options,((PetscObject)pc)->prefix,"-pc_fieldsplit_schur_factorization_type",PCFieldSplitSchurFactTypes,(PetscEnum*)&jac->schurfactorization,&flg);CHKERRQ(ierr);
1261     if (flg) {ierr = PetscInfo(pc,"Deprecated use of -pc_fieldsplit_schur_factorization_type\n");CHKERRQ(ierr);}
1262     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);
1263     ierr = PetscOptionsEnum("-pc_fieldsplit_schur_precondition","How to build preconditioner for Schur complement","PCFieldSplitSetSchurPre",PCFieldSplitSchurPreTypes,(PetscEnum)jac->schurpre,(PetscEnum*)&jac->schurpre,NULL);CHKERRQ(ierr);
1264   }
1265   ierr = PetscOptionsTail();CHKERRQ(ierr);
1266   PetscFunctionReturn(0);
1267 }
1268 
1269 /*------------------------------------------------------------------------------------*/
1270 
1271 static PetscErrorCode  PCFieldSplitSetFields_FieldSplit(PC pc,const char splitname[],PetscInt n,const PetscInt *fields,const PetscInt *fields_col)
1272 {
1273   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
1274   PetscErrorCode    ierr;
1275   PC_FieldSplitLink ilink,next = jac->head;
1276   char              prefix[128];
1277   PetscInt          i;
1278 
1279   PetscFunctionBegin;
1280   if (jac->splitdefined) {
1281     ierr = PetscInfo1(pc,"Ignoring new split \"%s\" because the splits have already been defined\n",splitname);CHKERRQ(ierr);
1282     PetscFunctionReturn(0);
1283   }
1284   for (i=0; i<n; i++) {
1285     if (fields[i] >= jac->bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Field %D requested but only %D exist",fields[i],jac->bs);
1286     if (fields[i] < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative field %D requested",fields[i]);
1287   }
1288   ierr = PetscNew(&ilink);CHKERRQ(ierr);
1289   if (splitname) {
1290     ierr = PetscStrallocpy(splitname,&ilink->splitname);CHKERRQ(ierr);
1291   } else {
1292     ierr = PetscMalloc1(3,&ilink->splitname);CHKERRQ(ierr);
1293     ierr = PetscSNPrintf(ilink->splitname,2,"%s",jac->nsplits);CHKERRQ(ierr);
1294   }
1295   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 */
1296   ierr = PetscMalloc1(n,&ilink->fields);CHKERRQ(ierr);
1297   ierr = PetscMemcpy(ilink->fields,fields,n*sizeof(PetscInt));CHKERRQ(ierr);
1298   ierr = PetscMalloc1(n,&ilink->fields_col);CHKERRQ(ierr);
1299   ierr = PetscMemcpy(ilink->fields_col,fields_col,n*sizeof(PetscInt));CHKERRQ(ierr);
1300 
1301   ilink->nfields = n;
1302   ilink->next    = NULL;
1303   ierr           = KSPCreate(PetscObjectComm((PetscObject)pc),&ilink->ksp);CHKERRQ(ierr);
1304   ierr           = KSPSetErrorIfNotConverged(ilink->ksp,pc->erroriffailure);CHKERRQ(ierr);
1305   ierr           = PetscObjectIncrementTabLevel((PetscObject)ilink->ksp,(PetscObject)pc,1);CHKERRQ(ierr);
1306   ierr           = KSPSetType(ilink->ksp,KSPPREONLY);CHKERRQ(ierr);
1307   ierr           = PetscLogObjectParent((PetscObject)pc,(PetscObject)ilink->ksp);CHKERRQ(ierr);
1308 
1309   ierr = PetscSNPrintf(prefix,sizeof(prefix),"%sfieldsplit_%s_",((PetscObject)pc)->prefix ? ((PetscObject)pc)->prefix : "",ilink->splitname);CHKERRQ(ierr);
1310   ierr = KSPSetOptionsPrefix(ilink->ksp,prefix);CHKERRQ(ierr);
1311 
1312   if (!next) {
1313     jac->head       = ilink;
1314     ilink->previous = NULL;
1315   } else {
1316     while (next->next) {
1317       next = next->next;
1318     }
1319     next->next      = ilink;
1320     ilink->previous = next;
1321   }
1322   jac->nsplits++;
1323   PetscFunctionReturn(0);
1324 }
1325 
1326 static PetscErrorCode  PCFieldSplitGetSubKSP_FieldSplit_Schur(PC pc,PetscInt *n,KSP **subksp)
1327 {
1328   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
1329   PetscErrorCode ierr;
1330 
1331   PetscFunctionBegin;
1332   if (!jac->schur) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must call KSPSetUp() or PCSetUp() before calling PCFieldSplitGetSubKSP()");
1333   ierr = PetscMalloc1(jac->nsplits,subksp);CHKERRQ(ierr);
1334   ierr = MatSchurComplementGetKSP(jac->schur,*subksp);CHKERRQ(ierr);
1335 
1336   (*subksp)[1] = jac->kspschur;
1337   if (n) *n = jac->nsplits;
1338   PetscFunctionReturn(0);
1339 }
1340 
1341 static PetscErrorCode  PCFieldSplitGetSubKSP_FieldSplit(PC pc,PetscInt *n,KSP **subksp)
1342 {
1343   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
1344   PetscErrorCode    ierr;
1345   PetscInt          cnt   = 0;
1346   PC_FieldSplitLink ilink = jac->head;
1347 
1348   PetscFunctionBegin;
1349   ierr = PetscMalloc1(jac->nsplits,subksp);CHKERRQ(ierr);
1350   while (ilink) {
1351     (*subksp)[cnt++] = ilink->ksp;
1352     ilink            = ilink->next;
1353   }
1354   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);
1355   if (n) *n = jac->nsplits;
1356   PetscFunctionReturn(0);
1357 }
1358 
1359 /*@C
1360     PCFieldSplitRestrictIS - Restricts the fieldsplit ISs to be within a given IS.
1361 
1362     Input Parameters:
1363 +   pc  - the preconditioner context
1364 +   is - the index set that defines the indices to which the fieldsplit is to be restricted
1365 
1366     Level: advanced
1367 
1368 @*/
1369 PetscErrorCode  PCFieldSplitRestrictIS(PC pc,IS isy)
1370 {
1371   PetscErrorCode ierr;
1372 
1373   PetscFunctionBegin;
1374   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1375   PetscValidHeaderSpecific(isy,IS_CLASSID,2);
1376   ierr = PetscTryMethod(pc,"PCFieldSplitRestrictIS_C",(PC,IS),(pc,isy));CHKERRQ(ierr);
1377   PetscFunctionReturn(0);
1378 }
1379 
1380 
1381 static PetscErrorCode  PCFieldSplitRestrictIS_FieldSplit(PC pc, IS isy)
1382 {
1383   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
1384   PetscErrorCode    ierr;
1385   PC_FieldSplitLink ilink = jac->head, next;
1386   PetscInt          localsize,size,sizez,i;
1387   const PetscInt    *ind, *indz;
1388   PetscInt          *indc, *indcz;
1389   PetscBool         flg;
1390 
1391   PetscFunctionBegin;
1392   ierr = ISGetLocalSize(isy,&localsize);CHKERRQ(ierr);
1393   ierr = MPI_Scan(&localsize,&size,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)isy));CHKERRQ(ierr);
1394   size -= localsize;
1395   while(ilink) {
1396     IS isrl,isr;
1397     PC subpc;
1398     ierr          = ISEmbed(ilink->is, isy, PETSC_TRUE, &isrl);CHKERRQ(ierr);
1399     ierr          = ISGetLocalSize(isrl,&localsize);CHKERRQ(ierr);
1400     ierr          = PetscMalloc1(localsize,&indc);CHKERRQ(ierr);
1401     ierr          = ISGetIndices(isrl,&ind);CHKERRQ(ierr);
1402     ierr          = PetscMemcpy(indc,ind,localsize*sizeof(PetscInt));CHKERRQ(ierr);
1403     ierr          = ISRestoreIndices(isrl,&ind);CHKERRQ(ierr);
1404     ierr          = ISDestroy(&isrl);CHKERRQ(ierr);
1405     for (i=0; i<localsize; i++) *(indc+i) += size;
1406     ierr          = ISCreateGeneral(PetscObjectComm((PetscObject)isy),localsize,indc,PETSC_OWN_POINTER,&isr);CHKERRQ(ierr);
1407     ierr          = PetscObjectReference((PetscObject)isr);CHKERRQ(ierr);
1408     ierr          = ISDestroy(&ilink->is);CHKERRQ(ierr);
1409     ilink->is     = isr;
1410     ierr          = PetscObjectReference((PetscObject)isr);CHKERRQ(ierr);
1411     ierr          = ISDestroy(&ilink->is_col);CHKERRQ(ierr);
1412     ilink->is_col = isr;
1413     ierr          = ISDestroy(&isr);CHKERRQ(ierr);
1414     ierr          = KSPGetPC(ilink->ksp, &subpc);CHKERRQ(ierr);
1415     ierr          = PetscObjectTypeCompare((PetscObject)subpc,PCFIELDSPLIT,&flg);CHKERRQ(ierr);
1416     if(flg) {
1417       IS iszl,isz;
1418       MPI_Comm comm;
1419       ierr   = ISGetLocalSize(ilink->is,&localsize);CHKERRQ(ierr);
1420       comm   = PetscObjectComm((PetscObject)ilink->is);
1421       ierr   = ISEmbed(isy, ilink->is, PETSC_TRUE, &iszl);CHKERRQ(ierr);
1422       ierr   = MPI_Scan(&localsize,&sizez,1,MPIU_INT,MPI_SUM,comm);CHKERRQ(ierr);
1423       sizez -= localsize;
1424       ierr   = ISGetLocalSize(iszl,&localsize);CHKERRQ(ierr);
1425       ierr   = PetscMalloc1(localsize,&indcz);CHKERRQ(ierr);
1426       ierr   = ISGetIndices(iszl,&indz);CHKERRQ(ierr);
1427       ierr   = PetscMemcpy(indcz,indz,localsize*sizeof(PetscInt));CHKERRQ(ierr);
1428       ierr   = ISRestoreIndices(iszl,&indz);CHKERRQ(ierr);
1429       ierr   = ISDestroy(&iszl);CHKERRQ(ierr);
1430       for (i=0; i<localsize; i++) *(indcz+i) += sizez;
1431       ierr   = ISCreateGeneral(comm,localsize,indcz,PETSC_OWN_POINTER,&isz);CHKERRQ(ierr);
1432       ierr   = PCFieldSplitRestrictIS(subpc,isz);CHKERRQ(ierr);
1433       ierr   = ISDestroy(&isz);CHKERRQ(ierr);
1434     }
1435     next = ilink->next;
1436     ilink = next;
1437   }
1438   jac->isrestrict = PETSC_TRUE;
1439   PetscFunctionReturn(0);
1440 }
1441 
1442 static PetscErrorCode  PCFieldSplitSetIS_FieldSplit(PC pc,const char splitname[],IS is)
1443 {
1444   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
1445   PetscErrorCode    ierr;
1446   PC_FieldSplitLink ilink, next = jac->head;
1447   char              prefix[128];
1448 
1449   PetscFunctionBegin;
1450   if (jac->splitdefined) {
1451     ierr = PetscInfo1(pc,"Ignoring new split \"%s\" because the splits have already been defined\n",splitname);CHKERRQ(ierr);
1452     PetscFunctionReturn(0);
1453   }
1454   ierr = PetscNew(&ilink);CHKERRQ(ierr);
1455   if (splitname) {
1456     ierr = PetscStrallocpy(splitname,&ilink->splitname);CHKERRQ(ierr);
1457   } else {
1458     ierr = PetscMalloc1(8,&ilink->splitname);CHKERRQ(ierr);
1459     ierr = PetscSNPrintf(ilink->splitname,7,"%D",jac->nsplits);CHKERRQ(ierr);
1460   }
1461   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 */
1462   ierr          = PetscObjectReference((PetscObject)is);CHKERRQ(ierr);
1463   ierr          = ISDestroy(&ilink->is);CHKERRQ(ierr);
1464   ilink->is     = is;
1465   ierr          = PetscObjectReference((PetscObject)is);CHKERRQ(ierr);
1466   ierr          = ISDestroy(&ilink->is_col);CHKERRQ(ierr);
1467   ilink->is_col = is;
1468   ilink->next   = NULL;
1469   ierr          = KSPCreate(PetscObjectComm((PetscObject)pc),&ilink->ksp);CHKERRQ(ierr);
1470   ierr          = KSPSetErrorIfNotConverged(ilink->ksp,pc->erroriffailure);CHKERRQ(ierr);
1471   ierr          = PetscObjectIncrementTabLevel((PetscObject)ilink->ksp,(PetscObject)pc,1);CHKERRQ(ierr);
1472   ierr          = KSPSetType(ilink->ksp,KSPPREONLY);CHKERRQ(ierr);
1473   ierr          = PetscLogObjectParent((PetscObject)pc,(PetscObject)ilink->ksp);CHKERRQ(ierr);
1474 
1475   ierr = PetscSNPrintf(prefix,sizeof(prefix),"%sfieldsplit_%s_",((PetscObject)pc)->prefix ? ((PetscObject)pc)->prefix : "",ilink->splitname);CHKERRQ(ierr);
1476   ierr = KSPSetOptionsPrefix(ilink->ksp,prefix);CHKERRQ(ierr);
1477 
1478   if (!next) {
1479     jac->head       = ilink;
1480     ilink->previous = NULL;
1481   } else {
1482     while (next->next) {
1483       next = next->next;
1484     }
1485     next->next      = ilink;
1486     ilink->previous = next;
1487   }
1488   jac->nsplits++;
1489   PetscFunctionReturn(0);
1490 }
1491 
1492 /*@C
1493     PCFieldSplitSetFields - Sets the fields for one particular split in the field split preconditioner
1494 
1495     Logically Collective on PC
1496 
1497     Input Parameters:
1498 +   pc  - the preconditioner context
1499 .   splitname - name of this split, if NULL the number of the split is used
1500 .   n - the number of fields in this split
1501 -   fields - the fields in this split
1502 
1503     Level: intermediate
1504 
1505     Notes: Use PCFieldSplitSetIS() to set a completely general set of indices as a field.
1506 
1507      The PCFieldSplitSetFields() is for defining fields as strided blocks. For example, if the block
1508      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
1509      0xx3xx6xx9xx12 ... x1xx4xx7xx ... xx2xx5xx8xx.. 01x34x67x... 0x1x3x5x7.. x12x45x78x....
1510      where the numbered entries indicate what is in the field.
1511 
1512      This function is called once per split (it creates a new split each time).  Solve options
1513      for this split will be available under the prefix -fieldsplit_SPLITNAME_.
1514 
1515      Developer Note: This routine does not actually create the IS representing the split, that is delayed
1516      until PCSetUp_FieldSplit(), because information about the vector/matrix layouts may not be
1517      available when this routine is called.
1518 
1519 .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetBlockSize(), PCFieldSplitSetIS()
1520 
1521 @*/
1522 PetscErrorCode  PCFieldSplitSetFields(PC pc,const char splitname[],PetscInt n,const PetscInt *fields,const PetscInt *fields_col)
1523 {
1524   PetscErrorCode ierr;
1525 
1526   PetscFunctionBegin;
1527   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1528   PetscValidCharPointer(splitname,2);
1529   if (n < 1) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Provided number of fields %D in split \"%s\" not positive",n,splitname);
1530   PetscValidIntPointer(fields,3);
1531   ierr = PetscTryMethod(pc,"PCFieldSplitSetFields_C",(PC,const char[],PetscInt,const PetscInt*,const PetscInt*),(pc,splitname,n,fields,fields_col));CHKERRQ(ierr);
1532   PetscFunctionReturn(0);
1533 }
1534 
1535 /*@
1536     PCFieldSplitSetDiagUseAmat - set flag indicating whether to extract diagonal blocks from Amat (rather than Pmat)
1537 
1538     Logically Collective on PC
1539 
1540     Input Parameters:
1541 +   pc  - the preconditioner object
1542 -   flg - boolean flag indicating whether or not to use Amat to extract the diagonal blocks from
1543 
1544     Options Database:
1545 .     -pc_fieldsplit_diag_use_amat
1546 
1547     Level: intermediate
1548 
1549 .seealso: PCFieldSplitGetDiagUseAmat(), PCFieldSplitSetOffDiagUseAmat(), PCFIELDSPLIT
1550 
1551 @*/
1552 PetscErrorCode  PCFieldSplitSetDiagUseAmat(PC pc,PetscBool flg)
1553 {
1554   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
1555   PetscBool      isfs;
1556   PetscErrorCode ierr;
1557 
1558   PetscFunctionBegin;
1559   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1560   ierr = PetscObjectTypeCompare((PetscObject)pc,PCFIELDSPLIT,&isfs);CHKERRQ(ierr);
1561   if (!isfs) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"PC not of type %s",PCFIELDSPLIT);
1562   jac->diag_use_amat = flg;
1563   PetscFunctionReturn(0);
1564 }
1565 
1566 /*@
1567     PCFieldSplitGetDiagUseAmat - get the flag indicating whether to extract diagonal blocks from Amat (rather than Pmat)
1568 
1569     Logically Collective on PC
1570 
1571     Input Parameters:
1572 .   pc  - the preconditioner object
1573 
1574     Output Parameters:
1575 .   flg - boolean flag indicating whether or not to use Amat to extract the diagonal blocks from
1576 
1577 
1578     Level: intermediate
1579 
1580 .seealso: PCFieldSplitSetDiagUseAmat(), PCFieldSplitGetOffDiagUseAmat(), PCFIELDSPLIT
1581 
1582 @*/
1583 PetscErrorCode  PCFieldSplitGetDiagUseAmat(PC pc,PetscBool *flg)
1584 {
1585   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
1586   PetscBool      isfs;
1587   PetscErrorCode ierr;
1588 
1589   PetscFunctionBegin;
1590   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1591   PetscValidPointer(flg,2);
1592   ierr = PetscObjectTypeCompare((PetscObject)pc,PCFIELDSPLIT,&isfs);CHKERRQ(ierr);
1593   if (!isfs) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"PC not of type %s",PCFIELDSPLIT);
1594   *flg = jac->diag_use_amat;
1595   PetscFunctionReturn(0);
1596 }
1597 
1598 /*@
1599     PCFieldSplitSetOffDiagUseAmat - set flag indicating whether to extract off-diagonal blocks from Amat (rather than Pmat)
1600 
1601     Logically Collective on PC
1602 
1603     Input Parameters:
1604 +   pc  - the preconditioner object
1605 -   flg - boolean flag indicating whether or not to use Amat to extract the off-diagonal blocks from
1606 
1607     Options Database:
1608 .     -pc_fieldsplit_off_diag_use_amat
1609 
1610     Level: intermediate
1611 
1612 .seealso: PCFieldSplitGetOffDiagUseAmat(), PCFieldSplitSetDiagUseAmat(), PCFIELDSPLIT
1613 
1614 @*/
1615 PetscErrorCode  PCFieldSplitSetOffDiagUseAmat(PC pc,PetscBool flg)
1616 {
1617   PC_FieldSplit *jac = (PC_FieldSplit*)pc->data;
1618   PetscBool      isfs;
1619   PetscErrorCode ierr;
1620 
1621   PetscFunctionBegin;
1622   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1623   ierr = PetscObjectTypeCompare((PetscObject)pc,PCFIELDSPLIT,&isfs);CHKERRQ(ierr);
1624   if (!isfs) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"PC not of type %s",PCFIELDSPLIT);
1625   jac->offdiag_use_amat = flg;
1626   PetscFunctionReturn(0);
1627 }
1628 
1629 /*@
1630     PCFieldSplitGetOffDiagUseAmat - get the flag indicating whether to extract off-diagonal blocks from Amat (rather than Pmat)
1631 
1632     Logically Collective on PC
1633 
1634     Input Parameters:
1635 .   pc  - the preconditioner object
1636 
1637     Output Parameters:
1638 .   flg - boolean flag indicating whether or not to use Amat to extract the off-diagonal blocks from
1639 
1640 
1641     Level: intermediate
1642 
1643 .seealso: PCFieldSplitSetOffDiagUseAmat(), PCFieldSplitGetDiagUseAmat(), PCFIELDSPLIT
1644 
1645 @*/
1646 PetscErrorCode  PCFieldSplitGetOffDiagUseAmat(PC pc,PetscBool *flg)
1647 {
1648   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
1649   PetscBool      isfs;
1650   PetscErrorCode ierr;
1651 
1652   PetscFunctionBegin;
1653   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1654   PetscValidPointer(flg,2);
1655   ierr = PetscObjectTypeCompare((PetscObject)pc,PCFIELDSPLIT,&isfs);CHKERRQ(ierr);
1656   if (!isfs) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"PC not of type %s",PCFIELDSPLIT);
1657   *flg = jac->offdiag_use_amat;
1658   PetscFunctionReturn(0);
1659 }
1660 
1661 
1662 
1663 /*@C
1664     PCFieldSplitSetIS - Sets the exact elements for field
1665 
1666     Logically Collective on PC
1667 
1668     Input Parameters:
1669 +   pc  - the preconditioner context
1670 .   splitname - name of this split, if NULL the number of the split is used
1671 -   is - the index set that defines the vector elements in this field
1672 
1673 
1674     Notes:
1675     Use PCFieldSplitSetFields(), for fields defined by strided types.
1676 
1677     This function is called once per split (it creates a new split each time).  Solve options
1678     for this split will be available under the prefix -fieldsplit_SPLITNAME_.
1679 
1680     Level: intermediate
1681 
1682 .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetBlockSize()
1683 
1684 @*/
1685 PetscErrorCode  PCFieldSplitSetIS(PC pc,const char splitname[],IS is)
1686 {
1687   PetscErrorCode ierr;
1688 
1689   PetscFunctionBegin;
1690   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1691   if (splitname) PetscValidCharPointer(splitname,2);
1692   PetscValidHeaderSpecific(is,IS_CLASSID,3);
1693   ierr = PetscTryMethod(pc,"PCFieldSplitSetIS_C",(PC,const char[],IS),(pc,splitname,is));CHKERRQ(ierr);
1694   PetscFunctionReturn(0);
1695 }
1696 
1697 /*@C
1698     PCFieldSplitGetIS - Retrieves the elements for a field as an IS
1699 
1700     Logically Collective on PC
1701 
1702     Input Parameters:
1703 +   pc  - the preconditioner context
1704 -   splitname - name of this split
1705 
1706     Output Parameter:
1707 -   is - the index set that defines the vector elements in this field, or NULL if the field is not found
1708 
1709     Level: intermediate
1710 
1711 .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetIS()
1712 
1713 @*/
1714 PetscErrorCode PCFieldSplitGetIS(PC pc,const char splitname[],IS *is)
1715 {
1716   PetscErrorCode ierr;
1717 
1718   PetscFunctionBegin;
1719   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1720   PetscValidCharPointer(splitname,2);
1721   PetscValidPointer(is,3);
1722   {
1723     PC_FieldSplit     *jac  = (PC_FieldSplit*) pc->data;
1724     PC_FieldSplitLink ilink = jac->head;
1725     PetscBool         found;
1726 
1727     *is = NULL;
1728     while (ilink) {
1729       ierr = PetscStrcmp(ilink->splitname, splitname, &found);CHKERRQ(ierr);
1730       if (found) {
1731         *is = ilink->is;
1732         break;
1733       }
1734       ilink = ilink->next;
1735     }
1736   }
1737   PetscFunctionReturn(0);
1738 }
1739 
1740 /*@
1741     PCFieldSplitSetBlockSize - Sets the block size for defining where fields start in the
1742       fieldsplit preconditioner. If not set the matrix block size is used.
1743 
1744     Logically Collective on PC
1745 
1746     Input Parameters:
1747 +   pc  - the preconditioner context
1748 -   bs - the block size
1749 
1750     Level: intermediate
1751 
1752 .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetFields()
1753 
1754 @*/
1755 PetscErrorCode  PCFieldSplitSetBlockSize(PC pc,PetscInt bs)
1756 {
1757   PetscErrorCode ierr;
1758 
1759   PetscFunctionBegin;
1760   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1761   PetscValidLogicalCollectiveInt(pc,bs,2);
1762   ierr = PetscTryMethod(pc,"PCFieldSplitSetBlockSize_C",(PC,PetscInt),(pc,bs));CHKERRQ(ierr);
1763   PetscFunctionReturn(0);
1764 }
1765 
1766 /*@C
1767    PCFieldSplitGetSubKSP - Gets the KSP contexts for all splits
1768 
1769    Collective on KSP
1770 
1771    Input Parameter:
1772 .  pc - the preconditioner context
1773 
1774    Output Parameters:
1775 +  n - the number of splits
1776 -  subksp - the array of KSP contexts
1777 
1778    Note:
1779    After PCFieldSplitGetSubKSP() the array of KSPs is to be freed by the user with PetscFree()
1780    (not the KSP just the array that contains them).
1781 
1782    You must call KSPSetUp() before calling PCFieldSplitGetSubKSP().
1783 
1784    Fortran Usage: You must pass in a KSP array that is large enough to contain all the local KSPs.
1785       You can call PCFieldSplitGetSubKSP(pc,n,PETSC_NULL_KSP,ierr) to determine how large the
1786       KSP array must be.
1787 
1788 
1789    Level: advanced
1790 
1791 .seealso: PCFIELDSPLIT
1792 @*/
1793 PetscErrorCode  PCFieldSplitGetSubKSP(PC pc,PetscInt *n,KSP *subksp[])
1794 {
1795   PetscErrorCode ierr;
1796 
1797   PetscFunctionBegin;
1798   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1799   if (n) PetscValidIntPointer(n,2);
1800   ierr = PetscUseMethod(pc,"PCFieldSplitGetSubKSP_C",(PC,PetscInt*,KSP **),(pc,n,subksp));CHKERRQ(ierr);
1801   PetscFunctionReturn(0);
1802 }
1803 
1804 /*@
1805     PCFieldSplitSetSchurPre -  Indicates what operator is used to construct the preconditioner for the Schur complement.
1806       A11 matrix. Otherwise no preconditioner is used.
1807 
1808     Collective on PC
1809 
1810     Input Parameters:
1811 +   pc      - the preconditioner context
1812 .   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
1813               PC_FIELDSPLIT_SCHUR_PRE_SELFP, and PC_FIELDSPLIT_SCHUR_PRE_FULL
1814 -   userpre - matrix to use for preconditioning, or NULL
1815 
1816     Options Database:
1817 .     -pc_fieldsplit_schur_precondition <self,selfp,user,a11,full> - default is a11. See notes for meaning of various arguments
1818 
1819     Notes:
1820 $    If ptype is
1821 $        a11 then the preconditioner for the Schur complement is generated from the block diagonal part of the preconditioner
1822 $             matrix associated with the Schur complement (i.e. A11), not the Schur complement matrix
1823 $        self the preconditioner for the Schur complement is generated from the symbolic representation of the Schur complement matrix:
1824 $             The only preconditioner that currently works with this symbolic respresentation matrix object is the PCLSC
1825 $             preconditioner
1826 $        user then the preconditioner for the Schur complement is generated from the user provided matrix (pre argument
1827 $             to this function).
1828 $        selfp then the preconditioning for the Schur complement is generated from an explicitly-assembled approximation Sp = A11 - A10 inv(diag(A00)) A01
1829 $             This is only a good preconditioner when diag(A00) is a good preconditioner for A00. Optionally, A00 can be
1830 $             lumped before extracting the diagonal using the additional option -fieldsplit_1_mat_schur_complement_ainv_type lump
1831 $        full then the preconditioner for the Schur complement is generated from the exact Schur complement matrix representation computed internally by PFIELDSPLIT (this is expensive)
1832 $             useful mostly as a test that the Schur complement approach can work for your problem
1833 
1834      When solving a saddle point problem, where the A11 block is identically zero, using a11 as the ptype only makes sense
1835     with the additional option -fieldsplit_1_pc_type none. Usually for saddle point problems one would use a ptype of self and
1836     -fieldsplit_1_pc_type lsc which uses the least squares commutator to compute a preconditioner for the Schur complement.
1837 
1838     Level: intermediate
1839 
1840 .seealso: PCFieldSplitGetSchurPre(), PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetFields(), PCFieldSplitSchurPreType,
1841           MatSchurComplementSetAinvType(), PCLSC
1842 
1843 @*/
1844 PetscErrorCode PCFieldSplitSetSchurPre(PC pc,PCFieldSplitSchurPreType ptype,Mat pre)
1845 {
1846   PetscErrorCode ierr;
1847 
1848   PetscFunctionBegin;
1849   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1850   ierr = PetscTryMethod(pc,"PCFieldSplitSetSchurPre_C",(PC,PCFieldSplitSchurPreType,Mat),(pc,ptype,pre));CHKERRQ(ierr);
1851   PetscFunctionReturn(0);
1852 }
1853 PetscErrorCode PCFieldSplitSchurPrecondition(PC pc,PCFieldSplitSchurPreType ptype,Mat pre) {return PCFieldSplitSetSchurPre(pc,ptype,pre);} /* Deprecated name */
1854 
1855 /*@
1856     PCFieldSplitGetSchurPre - For Schur complement fieldsplit, determine how the Schur complement will be
1857     preconditioned.  See PCFieldSplitSetSchurPre() for details.
1858 
1859     Logically Collective on PC
1860 
1861     Input Parameters:
1862 .   pc      - the preconditioner context
1863 
1864     Output Parameters:
1865 +   ptype   - which matrix to use for preconditioning the Schur complement: PC_FIELDSPLIT_SCHUR_PRE_A11, PC_FIELDSPLIT_SCHUR_PRE_SELF, PC_FIELDSPLIT_PRE_USER
1866 -   userpre - matrix to use for preconditioning (with PC_FIELDSPLIT_PRE_USER), or NULL
1867 
1868     Level: intermediate
1869 
1870 .seealso: PCFieldSplitSetSchurPre(), PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetFields(), PCFieldSplitSchurPreType, PCLSC
1871 
1872 @*/
1873 PetscErrorCode PCFieldSplitGetSchurPre(PC pc,PCFieldSplitSchurPreType *ptype,Mat *pre)
1874 {
1875   PetscErrorCode ierr;
1876 
1877   PetscFunctionBegin;
1878   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1879   ierr = PetscUseMethod(pc,"PCFieldSplitGetSchurPre_C",(PC,PCFieldSplitSchurPreType*,Mat*),(pc,ptype,pre));CHKERRQ(ierr);
1880   PetscFunctionReturn(0);
1881 }
1882 
1883 /*@
1884     PCFieldSplitSchurGetS -  extract the MatSchurComplement object used by this PC in case it needs to be configured separately
1885 
1886     Not collective
1887 
1888     Input Parameter:
1889 .   pc      - the preconditioner context
1890 
1891     Output Parameter:
1892 .   S       - the Schur complement matrix
1893 
1894     Notes:
1895     This matrix should not be destroyed using MatDestroy(); rather, use PCFieldSplitSchurRestoreS().
1896 
1897     Level: advanced
1898 
1899 .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSchurPreType, PCFieldSplitSetSchurPre(), MatSchurComplement, PCFieldSplitSchurRestoreS()
1900 
1901 @*/
1902 PetscErrorCode  PCFieldSplitSchurGetS(PC pc,Mat *S)
1903 {
1904   PetscErrorCode ierr;
1905   const char*    t;
1906   PetscBool      isfs;
1907   PC_FieldSplit  *jac;
1908 
1909   PetscFunctionBegin;
1910   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1911   ierr = PetscObjectGetType((PetscObject)pc,&t);CHKERRQ(ierr);
1912   ierr = PetscStrcmp(t,PCFIELDSPLIT,&isfs);CHKERRQ(ierr);
1913   if (!isfs) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Expected PC of type PCFIELDSPLIT, got %s instead",t);
1914   jac = (PC_FieldSplit*)pc->data;
1915   if (jac->type != PC_COMPOSITE_SCHUR) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Expected PCFIELDSPLIT of type SCHUR, got %D instead",jac->type);
1916   if (S) *S = jac->schur;
1917   PetscFunctionReturn(0);
1918 }
1919 
1920 /*@
1921     PCFieldSplitSchurRestoreS -  restores the MatSchurComplement object used by this PC
1922 
1923     Not collective
1924 
1925     Input Parameters:
1926 +   pc      - the preconditioner context
1927 .   S       - the Schur complement matrix
1928 
1929     Level: advanced
1930 
1931 .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSchurPreType, PCFieldSplitSetSchurPre(), MatSchurComplement, PCFieldSplitSchurGetS()
1932 
1933 @*/
1934 PetscErrorCode  PCFieldSplitSchurRestoreS(PC pc,Mat *S)
1935 {
1936   PetscErrorCode ierr;
1937   const char*    t;
1938   PetscBool      isfs;
1939   PC_FieldSplit  *jac;
1940 
1941   PetscFunctionBegin;
1942   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1943   ierr = PetscObjectGetType((PetscObject)pc,&t);CHKERRQ(ierr);
1944   ierr = PetscStrcmp(t,PCFIELDSPLIT,&isfs);CHKERRQ(ierr);
1945   if (!isfs) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Expected PC of type PCFIELDSPLIT, got %s instead",t);
1946   jac = (PC_FieldSplit*)pc->data;
1947   if (jac->type != PC_COMPOSITE_SCHUR) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Expected PCFIELDSPLIT of type SCHUR, got %D instead",jac->type);
1948   if (!S || *S != jac->schur) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"MatSchurComplement restored is not the same as gotten");
1949   PetscFunctionReturn(0);
1950 }
1951 
1952 
1953 static PetscErrorCode  PCFieldSplitSetSchurPre_FieldSplit(PC pc,PCFieldSplitSchurPreType ptype,Mat pre)
1954 {
1955   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
1956   PetscErrorCode ierr;
1957 
1958   PetscFunctionBegin;
1959   jac->schurpre = ptype;
1960   if (ptype == PC_FIELDSPLIT_SCHUR_PRE_USER && pre) {
1961     ierr            = MatDestroy(&jac->schur_user);CHKERRQ(ierr);
1962     jac->schur_user = pre;
1963     ierr            = PetscObjectReference((PetscObject)jac->schur_user);CHKERRQ(ierr);
1964   }
1965   PetscFunctionReturn(0);
1966 }
1967 
1968 static PetscErrorCode  PCFieldSplitGetSchurPre_FieldSplit(PC pc,PCFieldSplitSchurPreType *ptype,Mat *pre)
1969 {
1970   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
1971 
1972   PetscFunctionBegin;
1973   *ptype = jac->schurpre;
1974   *pre   = jac->schur_user;
1975   PetscFunctionReturn(0);
1976 }
1977 
1978 /*@
1979     PCFieldSplitSetSchurFactType -  sets which blocks of the approximate block factorization to retain
1980 
1981     Collective on PC
1982 
1983     Input Parameters:
1984 +   pc  - the preconditioner context
1985 -   ftype - which blocks of factorization to retain, PC_FIELDSPLIT_SCHUR_FACT_FULL is default
1986 
1987     Options Database:
1988 .     -pc_fieldsplit_schur_fact_type <diag,lower,upper,full> default is full
1989 
1990 
1991     Level: intermediate
1992 
1993     Notes:
1994     The FULL factorization is
1995 
1996 $   (A   B)  = (1       0) (A   0) (1  Ainv*B)
1997 $   (C   D)    (C*Ainv  1) (0   S) (0     1  )
1998 
1999     where S = D - 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,
2000     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).
2001 
2002     If applied exactly, FULL factorization is a direct solver. The preconditioned operator with LOWER or UPPER has all eigenvalues equal to 1 and minimal polynomial
2003     of degree 2, so KSPGMRES converges in 2 iterations. If the iteration count is very low, consider using KSPFGMRES or KSPGCR which can use one less preconditioner
2004     application in this case. Note that the preconditioned operator may be highly non-normal, so such fast convergence may not be observed in practice. With DIAG,
2005     the preconditioned operator has three distinct nonzero eigenvalues and minimal polynomial of degree at most 4, so KSPGMRES converges in at most 4 iterations.
2006 
2007     For symmetric problems in which A is positive definite and S is negative definite, DIAG can be used with KSPMINRES. Note that a flexible method like KSPFGMRES
2008     or KSPGCR must be used if the fieldsplit preconditioner is nonlinear (e.g. a few iterations of a Krylov method is used inside a split).
2009 
2010     References:
2011 +   1. - Murphy, Golub, and Wathen, A note on preconditioning indefinite linear systems, SIAM J. Sci. Comput., 21 (2000).
2012 -   2. - Ipsen, A note on preconditioning nonsymmetric matrices, SIAM J. Sci. Comput., 23 (2001).
2013 
2014 .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetFields(), PCFieldSplitSchurPreType
2015 @*/
2016 PetscErrorCode  PCFieldSplitSetSchurFactType(PC pc,PCFieldSplitSchurFactType ftype)
2017 {
2018   PetscErrorCode ierr;
2019 
2020   PetscFunctionBegin;
2021   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2022   ierr = PetscTryMethod(pc,"PCFieldSplitSetSchurFactType_C",(PC,PCFieldSplitSchurFactType),(pc,ftype));CHKERRQ(ierr);
2023   PetscFunctionReturn(0);
2024 }
2025 
2026 static PetscErrorCode PCFieldSplitSetSchurFactType_FieldSplit(PC pc,PCFieldSplitSchurFactType ftype)
2027 {
2028   PC_FieldSplit *jac = (PC_FieldSplit*)pc->data;
2029 
2030   PetscFunctionBegin;
2031   jac->schurfactorization = ftype;
2032   PetscFunctionReturn(0);
2033 }
2034 
2035 /*@C
2036    PCFieldSplitGetSchurBlocks - Gets all matrix blocks for the Schur complement
2037 
2038    Collective on KSP
2039 
2040    Input Parameter:
2041 .  pc - the preconditioner context
2042 
2043    Output Parameters:
2044 +  A00 - the (0,0) block
2045 .  A01 - the (0,1) block
2046 .  A10 - the (1,0) block
2047 -  A11 - the (1,1) block
2048 
2049    Level: advanced
2050 
2051 .seealso: PCFIELDSPLIT
2052 @*/
2053 PetscErrorCode  PCFieldSplitGetSchurBlocks(PC pc,Mat *A00,Mat *A01,Mat *A10, Mat *A11)
2054 {
2055   PC_FieldSplit *jac = (PC_FieldSplit*) pc->data;
2056 
2057   PetscFunctionBegin;
2058   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2059   if (jac->type != PC_COMPOSITE_SCHUR) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG, "FieldSplit is not using a Schur complement approach.");
2060   if (A00) *A00 = jac->pmat[0];
2061   if (A01) *A01 = jac->B;
2062   if (A10) *A10 = jac->C;
2063   if (A11) *A11 = jac->pmat[1];
2064   PetscFunctionReturn(0);
2065 }
2066 
2067 static PetscErrorCode  PCFieldSplitSetType_FieldSplit(PC pc,PCCompositeType type)
2068 {
2069   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
2070   PetscErrorCode ierr;
2071 
2072   PetscFunctionBegin;
2073   jac->type = type;
2074   if (type == PC_COMPOSITE_SCHUR) {
2075     pc->ops->apply = PCApply_FieldSplit_Schur;
2076     pc->ops->view  = PCView_FieldSplit_Schur;
2077 
2078     ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitGetSubKSP_C",PCFieldSplitGetSubKSP_FieldSplit_Schur);CHKERRQ(ierr);
2079     ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetSchurPre_C",PCFieldSplitSetSchurPre_FieldSplit);CHKERRQ(ierr);
2080     ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitGetSchurPre_C",PCFieldSplitGetSchurPre_FieldSplit);CHKERRQ(ierr);
2081     ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetSchurFactType_C",PCFieldSplitSetSchurFactType_FieldSplit);CHKERRQ(ierr);
2082 
2083   } else {
2084     pc->ops->apply = PCApply_FieldSplit;
2085     pc->ops->view  = PCView_FieldSplit;
2086 
2087     ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitGetSubKSP_C",PCFieldSplitGetSubKSP_FieldSplit);CHKERRQ(ierr);
2088     ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetSchurPre_C",0);CHKERRQ(ierr);
2089     ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitGetSchurPre_C",0);CHKERRQ(ierr);
2090     ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetSchurFactType_C",0);CHKERRQ(ierr);
2091   }
2092   PetscFunctionReturn(0);
2093 }
2094 
2095 static PetscErrorCode  PCFieldSplitSetBlockSize_FieldSplit(PC pc,PetscInt bs)
2096 {
2097   PC_FieldSplit *jac = (PC_FieldSplit*)pc->data;
2098 
2099   PetscFunctionBegin;
2100   if (bs < 1) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Blocksize must be positive, you gave %D",bs);
2101   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);
2102   jac->bs = bs;
2103   PetscFunctionReturn(0);
2104 }
2105 
2106 /*@
2107    PCFieldSplitSetType - Sets the type of fieldsplit preconditioner.
2108 
2109    Collective on PC
2110 
2111    Input Parameter:
2112 .  pc - the preconditioner context
2113 .  type - PC_COMPOSITE_ADDITIVE, PC_COMPOSITE_MULTIPLICATIVE (default), PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE, PC_COMPOSITE_SPECIAL, PC_COMPOSITE_SCHUR
2114 
2115    Options Database Key:
2116 .  -pc_fieldsplit_type <type: one of multiplicative, additive, symmetric_multiplicative, special, schur> - Sets fieldsplit preconditioner type
2117 
2118    Level: Intermediate
2119 
2120 .keywords: PC, set, type, composite preconditioner, additive, multiplicative
2121 
2122 .seealso: PCCompositeSetType()
2123 
2124 @*/
2125 PetscErrorCode  PCFieldSplitSetType(PC pc,PCCompositeType type)
2126 {
2127   PetscErrorCode ierr;
2128 
2129   PetscFunctionBegin;
2130   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2131   ierr = PetscTryMethod(pc,"PCFieldSplitSetType_C",(PC,PCCompositeType),(pc,type));CHKERRQ(ierr);
2132   PetscFunctionReturn(0);
2133 }
2134 
2135 /*@
2136   PCFieldSplitGetType - Gets the type of fieldsplit preconditioner.
2137 
2138   Not collective
2139 
2140   Input Parameter:
2141 . pc - the preconditioner context
2142 
2143   Output Parameter:
2144 . type - PC_COMPOSITE_ADDITIVE, PC_COMPOSITE_MULTIPLICATIVE (default), PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE, PC_COMPOSITE_SPECIAL, PC_COMPOSITE_SCHUR
2145 
2146   Level: Intermediate
2147 
2148 .keywords: PC, set, type, composite preconditioner, additive, multiplicative
2149 .seealso: PCCompositeSetType()
2150 @*/
2151 PetscErrorCode PCFieldSplitGetType(PC pc, PCCompositeType *type)
2152 {
2153   PC_FieldSplit *jac = (PC_FieldSplit*) pc->data;
2154 
2155   PetscFunctionBegin;
2156   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2157   PetscValidIntPointer(type,2);
2158   *type = jac->type;
2159   PetscFunctionReturn(0);
2160 }
2161 
2162 /*@
2163    PCFieldSplitSetDMSplits - Flags whether DMCreateFieldDecomposition() should be used to define the splits, whenever possible.
2164 
2165    Logically Collective
2166 
2167    Input Parameters:
2168 +  pc   - the preconditioner context
2169 -  flg  - boolean indicating whether to use field splits defined by the DM
2170 
2171    Options Database Key:
2172 .  -pc_fieldsplit_dm_splits
2173 
2174    Level: Intermediate
2175 
2176 .keywords: PC, DM, composite preconditioner, additive, multiplicative
2177 
2178 .seealso: PCFieldSplitGetDMSplits()
2179 
2180 @*/
2181 PetscErrorCode  PCFieldSplitSetDMSplits(PC pc,PetscBool flg)
2182 {
2183   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
2184   PetscBool      isfs;
2185   PetscErrorCode ierr;
2186 
2187   PetscFunctionBegin;
2188   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2189   PetscValidLogicalCollectiveBool(pc,flg,2);
2190   ierr = PetscObjectTypeCompare((PetscObject)pc,PCFIELDSPLIT,&isfs);CHKERRQ(ierr);
2191   if (isfs) {
2192     jac->dm_splits = flg;
2193   }
2194   PetscFunctionReturn(0);
2195 }
2196 
2197 
2198 /*@
2199    PCFieldSplitGetDMSplits - Returns flag indicating whether DMCreateFieldDecomposition() should be used to define the splits, whenever possible.
2200 
2201    Logically Collective
2202 
2203    Input Parameter:
2204 .  pc   - the preconditioner context
2205 
2206    Output Parameter:
2207 .  flg  - boolean indicating whether to use field splits defined by the DM
2208 
2209    Level: Intermediate
2210 
2211 .keywords: PC, DM, composite preconditioner, additive, multiplicative
2212 
2213 .seealso: PCFieldSplitSetDMSplits()
2214 
2215 @*/
2216 PetscErrorCode  PCFieldSplitGetDMSplits(PC pc,PetscBool* flg)
2217 {
2218   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
2219   PetscBool      isfs;
2220   PetscErrorCode ierr;
2221 
2222   PetscFunctionBegin;
2223   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2224   PetscValidPointer(flg,2);
2225   ierr = PetscObjectTypeCompare((PetscObject)pc,PCFIELDSPLIT,&isfs);CHKERRQ(ierr);
2226   if (isfs) {
2227     if(flg) *flg = jac->dm_splits;
2228   }
2229   PetscFunctionReturn(0);
2230 }
2231 
2232 /* -------------------------------------------------------------------------------------*/
2233 /*MC
2234    PCFIELDSPLIT - Preconditioner created by combining separate preconditioners for individual
2235                   fields or groups of fields. See the users manual section "Solving Block Matrices" for more details.
2236 
2237      To set options on the solvers for each block append -fieldsplit_ to all the PC
2238         options database keys. For example, -fieldsplit_pc_type ilu -fieldsplit_pc_factor_levels 1
2239 
2240      To set the options on the solvers separate for each block call PCFieldSplitGetSubKSP()
2241          and set the options directly on the resulting KSP object
2242 
2243    Level: intermediate
2244 
2245    Options Database Keys:
2246 +   -pc_fieldsplit_%d_fields <a,b,..> - indicates the fields to be used in the %d'th split
2247 .   -pc_fieldsplit_default - automatically add any fields to additional splits that have not
2248                               been supplied explicitly by -pc_fieldsplit_%d_fields
2249 .   -pc_fieldsplit_block_size <bs> - size of block that defines fields (i.e. there are bs fields)
2250 .   -pc_fieldsplit_type <additive,multiplicative,symmetric_multiplicative,schur> - type of relaxation or factorization splitting
2251 .   -pc_fieldsplit_schur_precondition <self,selfp,user,a11,full> - default is a11; see PCFieldSplitSetSchurPre()
2252 .   -pc_fieldsplit_detect_saddle_point - automatically finds rows with zero or negative diagonal and uses Schur complement with no preconditioner as the solver
2253 
2254 -    Options prefix for inner solvers when using Schur complement preconditioner are -fieldsplit_0_ and -fieldsplit_1_
2255      for all other solvers they are -fieldsplit_%d_ for the dth field, use -fieldsplit_ for all fields
2256 
2257    Notes:
2258     Use PCFieldSplitSetFields() to set fields defined by "strided" entries and PCFieldSplitSetIS()
2259      to define a field by an arbitrary collection of entries.
2260 
2261       If no fields are set the default is used. The fields are defined by entries strided by bs,
2262       beginning at 0 then 1, etc to bs-1. The block size can be set with PCFieldSplitSetBlockSize(),
2263       if this is not called the block size defaults to the blocksize of the second matrix passed
2264       to KSPSetOperators()/PCSetOperators().
2265 
2266 $     For the Schur complement preconditioner if J = ( A00 A01 )
2267 $                                                    ( A10 A11 )
2268 $     the preconditioner using full factorization is
2269 $              ( I   -ksp(A00) A01 ) ( inv(A00)     0  ) (     I          0  )
2270 $              ( 0         I       ) (   0      ksp(S) ) ( -A10 ksp(A00)  I  )
2271      where the action of inv(A00) is applied using the KSP solver with prefix -fieldsplit_0_.  S is the Schur complement
2272 $              S = A11 - A10 ksp(A00) A01
2273      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
2274      in providing the SECOND split or 1 if not give). For PCFieldSplitGetKSP() when field number is 0,
2275      it returns the KSP associated with -fieldsplit_0_ while field number 1 gives -fieldsplit_1_ KSP. By default
2276      A11 is used to construct a preconditioner for S, use PCFieldSplitSetSchurPre() for all the possible ways to construct the preconditioner for S.
2277 
2278      The factorization type is set using -pc_fieldsplit_schur_fact_type <diag, lower, upper, full>. The full is shown above,
2279      diag gives
2280 $              ( inv(A00)     0   )
2281 $              (   0      -ksp(S) )
2282      note that slightly counter intuitively there is a negative in front of the ksp(S) so that the preconditioner is positive definite. The lower factorization is the inverse of
2283 $              (  A00   0 )
2284 $              (  A10   S )
2285      where the inverses of A00 and S are applied using KSPs. The upper factorization is the inverse of
2286 $              ( A00 A01 )
2287 $              (  0   S  )
2288      where again the inverses of A00 and S are applied using KSPs.
2289 
2290      If only one set of indices (one IS) is provided with PCFieldSplitSetIS() then the complement of that IS
2291      is used automatically for a second block.
2292 
2293      The fieldsplit preconditioner cannot currently be used with the BAIJ or SBAIJ data formats if the blocksize is larger than 1.
2294      Generally it should be used with the AIJ format.
2295 
2296      The forms of these preconditioners are closely related if not identical to forms derived as "Distributive Iterations", see,
2297      for example, page 294 in "Principles of Computational Fluid Dynamics" by Pieter Wesseling. Note that one can also use PCFIELDSPLIT
2298      inside a smoother resulting in "Distributive Smoothers".
2299 
2300    Concepts: physics based preconditioners, block preconditioners
2301 
2302    There is a nice discussion of block preconditioners in
2303 
2304 [El08] A taxonomy and comparison of parallel block multi-level preconditioners for the incompressible Navier-Stokes equations
2305        Howard Elman, V.E. Howle, John Shadid, Robert Shuttleworth, Ray Tuminaro, Journal of Computational Physics 227 (2008) 1790--1808
2306        http://chess.cs.umd.edu/~elman/papers/tax.pdf
2307 
2308    The Constrained Pressure Preconditioner (CPR) can be implemented using PCCOMPOSITE with PCGALERKIN. CPR first solves an R A P subsystem, updates the
2309    residual on all variables (PCCompositeSetType(pc,PC_COMPOSITE_MULTIPLICATIVE)), and then applies a simple ILU like preconditioner on all the variables.
2310 
2311 .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC, Block_Preconditioners, PCLSC,
2312            PCFieldSplitGetSubKSP(), PCFieldSplitSetFields(), PCFieldSplitSetType(), PCFieldSplitSetIS(), PCFieldSplitSetSchurPre(),
2313 	   MatSchurComplementSetAinvType()
2314 M*/
2315 
2316 PETSC_EXTERN PetscErrorCode PCCreate_FieldSplit(PC pc)
2317 {
2318   PetscErrorCode ierr;
2319   PC_FieldSplit  *jac;
2320 
2321   PetscFunctionBegin;
2322   ierr = PetscNewLog(pc,&jac);CHKERRQ(ierr);
2323 
2324   jac->bs                 = -1;
2325   jac->nsplits            = 0;
2326   jac->type               = PC_COMPOSITE_MULTIPLICATIVE;
2327   jac->schurpre           = PC_FIELDSPLIT_SCHUR_PRE_USER; /* Try user preconditioner first, fall back on diagonal */
2328   jac->schurfactorization = PC_FIELDSPLIT_SCHUR_FACT_FULL;
2329   jac->dm_splits          = PETSC_TRUE;
2330 
2331   pc->data = (void*)jac;
2332 
2333   pc->ops->apply           = PCApply_FieldSplit;
2334   pc->ops->applytranspose  = PCApplyTranspose_FieldSplit;
2335   pc->ops->setup           = PCSetUp_FieldSplit;
2336   pc->ops->reset           = PCReset_FieldSplit;
2337   pc->ops->destroy         = PCDestroy_FieldSplit;
2338   pc->ops->setfromoptions  = PCSetFromOptions_FieldSplit;
2339   pc->ops->view            = PCView_FieldSplit;
2340   pc->ops->applyrichardson = 0;
2341 
2342   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitGetSubKSP_C",PCFieldSplitGetSubKSP_FieldSplit);CHKERRQ(ierr);
2343   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetFields_C",PCFieldSplitSetFields_FieldSplit);CHKERRQ(ierr);
2344   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetIS_C",PCFieldSplitSetIS_FieldSplit);CHKERRQ(ierr);
2345   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetType_C",PCFieldSplitSetType_FieldSplit);CHKERRQ(ierr);
2346   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetBlockSize_C",PCFieldSplitSetBlockSize_FieldSplit);CHKERRQ(ierr);
2347   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitRestrictIS_C",PCFieldSplitRestrictIS_FieldSplit);CHKERRQ(ierr);
2348   PetscFunctionReturn(0);
2349 }
2350 
2351 
2352 
2353