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