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