xref: /petsc/src/ksp/pc/impls/fieldsplit/fieldsplit.c (revision a0ec5c43ece1365714ee687686ab385707c7cfeb)
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,PETSC_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,PETSC_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,PETSC_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, PETSC_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, PETSC_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,PETSC_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,PETSC_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 = PETSC_NULL;
528       /* compute scatter contexts needed by multiplicative versions and non-default splits */
529       ierr = VecScatterCreate(xtmp,ilink->is,jac->x[i],PETSC_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,PETSC_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,PETSC_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 = PETSC_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, PETSC_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, PETSC_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   x->map->bs = jac->bs;
835   y->map->bs = jac->bs;
836   CHKMEMQ;
837   if (jac->type == PC_COMPOSITE_ADDITIVE) {
838     if (jac->defaultsplit) {
839       ierr = VecGetBlockSize(x,&bs);CHKERRQ(ierr);
840       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);
841       ierr = VecGetBlockSize(y,&bs);CHKERRQ(ierr);
842       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);
843       ierr = VecStrideGatherAll(x,jac->x,INSERT_VALUES);CHKERRQ(ierr);
844       while (ilink) {
845         ierr  = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
846         ilink = ilink->next;
847       }
848       ierr = VecStrideScatterAll(jac->y,y,INSERT_VALUES);CHKERRQ(ierr);
849     } else {
850       ierr = VecSet(y,0.0);CHKERRQ(ierr);
851       while (ilink) {
852         ierr  = FieldSplitSplitSolveAdd(ilink,x,y);CHKERRQ(ierr);
853         ilink = ilink->next;
854       }
855     }
856   } else if (jac->type == PC_COMPOSITE_MULTIPLICATIVE || jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
857     if (!jac->w1) {
858       ierr = VecDuplicate(x,&jac->w1);CHKERRQ(ierr);
859       ierr = VecDuplicate(x,&jac->w2);CHKERRQ(ierr);
860     }
861     ierr = VecSet(y,0.0);CHKERRQ(ierr);
862     ierr = FieldSplitSplitSolveAdd(ilink,x,y);CHKERRQ(ierr);
863     cnt  = 1;
864     while (ilink->next) {
865       ilink = ilink->next;
866       /* compute the residual only over the part of the vector needed */
867       ierr = MatMult(jac->Afield[cnt++],y,ilink->x);CHKERRQ(ierr);
868       ierr = VecScale(ilink->x,-1.0);CHKERRQ(ierr);
869       ierr = VecScatterBegin(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
870       ierr = VecScatterEnd(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
871       ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
872       ierr = VecScatterBegin(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
873       ierr = VecScatterEnd(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
874     }
875     if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
876       cnt -= 2;
877       while (ilink->previous) {
878         ilink = ilink->previous;
879         /* compute the residual only over the part of the vector needed */
880         ierr = MatMult(jac->Afield[cnt--],y,ilink->x);CHKERRQ(ierr);
881         ierr = VecScale(ilink->x,-1.0);CHKERRQ(ierr);
882         ierr = VecScatterBegin(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
883         ierr = VecScatterEnd(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
884         ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
885         ierr = VecScatterBegin(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
886         ierr = VecScatterEnd(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
887       }
888     }
889   } else SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_SUP,"Unsupported or unknown composition",(int) jac->type);
890   CHKMEMQ;
891   PetscFunctionReturn(0);
892 }
893 
894 #define FieldSplitSplitSolveAddTranspose(ilink,xx,yy) \
895   (VecScatterBegin(ilink->sctx,xx,ilink->y,INSERT_VALUES,SCATTER_FORWARD) || \
896    VecScatterEnd(ilink->sctx,xx,ilink->y,INSERT_VALUES,SCATTER_FORWARD) || \
897    KSPSolveTranspose(ilink->ksp,ilink->y,ilink->x) || \
898    VecScatterBegin(ilink->sctx,ilink->x,yy,ADD_VALUES,SCATTER_REVERSE) || \
899    VecScatterEnd(ilink->sctx,ilink->x,yy,ADD_VALUES,SCATTER_REVERSE))
900 
901 #undef __FUNCT__
902 #define __FUNCT__ "PCApplyTranspose_FieldSplit"
903 static PetscErrorCode PCApplyTranspose_FieldSplit(PC pc,Vec x,Vec y)
904 {
905   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
906   PetscErrorCode    ierr;
907   PC_FieldSplitLink ilink = jac->head;
908   PetscInt          bs;
909 
910   PetscFunctionBegin;
911   CHKMEMQ;
912   if (jac->type == PC_COMPOSITE_ADDITIVE) {
913     if (jac->defaultsplit) {
914       ierr = VecGetBlockSize(x,&bs);CHKERRQ(ierr);
915       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);
916       ierr = VecGetBlockSize(y,&bs);CHKERRQ(ierr);
917       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);
918       ierr = VecStrideGatherAll(x,jac->x,INSERT_VALUES);CHKERRQ(ierr);
919       while (ilink) {
920         ierr  = KSPSolveTranspose(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
921         ilink = ilink->next;
922       }
923       ierr = VecStrideScatterAll(jac->y,y,INSERT_VALUES);CHKERRQ(ierr);
924     } else {
925       ierr = VecSet(y,0.0);CHKERRQ(ierr);
926       while (ilink) {
927         ierr  = FieldSplitSplitSolveAddTranspose(ilink,x,y);CHKERRQ(ierr);
928         ilink = ilink->next;
929       }
930     }
931   } else {
932     if (!jac->w1) {
933       ierr = VecDuplicate(x,&jac->w1);CHKERRQ(ierr);
934       ierr = VecDuplicate(x,&jac->w2);CHKERRQ(ierr);
935     }
936     ierr = VecSet(y,0.0);CHKERRQ(ierr);
937     if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
938       ierr = FieldSplitSplitSolveAddTranspose(ilink,x,y);CHKERRQ(ierr);
939       while (ilink->next) {
940         ilink = ilink->next;
941         ierr  = MatMultTranspose(pc->mat,y,jac->w1);CHKERRQ(ierr);
942         ierr  = VecWAXPY(jac->w2,-1.0,jac->w1,x);CHKERRQ(ierr);
943         ierr  = FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);CHKERRQ(ierr);
944       }
945       while (ilink->previous) {
946         ilink = ilink->previous;
947         ierr  = MatMultTranspose(pc->mat,y,jac->w1);CHKERRQ(ierr);
948         ierr  = VecWAXPY(jac->w2,-1.0,jac->w1,x);CHKERRQ(ierr);
949         ierr  = FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);CHKERRQ(ierr);
950       }
951     } else {
952       while (ilink->next) {   /* get to last entry in linked list */
953         ilink = ilink->next;
954       }
955       ierr = FieldSplitSplitSolveAddTranspose(ilink,x,y);CHKERRQ(ierr);
956       while (ilink->previous) {
957         ilink = ilink->previous;
958         ierr  = MatMultTranspose(pc->mat,y,jac->w1);CHKERRQ(ierr);
959         ierr  = VecWAXPY(jac->w2,-1.0,jac->w1,x);CHKERRQ(ierr);
960         ierr  = FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);CHKERRQ(ierr);
961       }
962     }
963   }
964   CHKMEMQ;
965   PetscFunctionReturn(0);
966 }
967 
968 #undef __FUNCT__
969 #define __FUNCT__ "PCReset_FieldSplit"
970 static PetscErrorCode PCReset_FieldSplit(PC pc)
971 {
972   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
973   PetscErrorCode    ierr;
974   PC_FieldSplitLink ilink = jac->head,next;
975 
976   PetscFunctionBegin;
977   while (ilink) {
978     ierr  = KSPReset(ilink->ksp);CHKERRQ(ierr);
979     ierr  = VecDestroy(&ilink->x);CHKERRQ(ierr);
980     ierr  = VecDestroy(&ilink->y);CHKERRQ(ierr);
981     ierr  = VecDestroy(&ilink->z);CHKERRQ(ierr);
982     ierr  = VecScatterDestroy(&ilink->sctx);CHKERRQ(ierr);
983     ierr  = ISDestroy(&ilink->is);CHKERRQ(ierr);
984     ierr  = ISDestroy(&ilink->is_col);CHKERRQ(ierr);
985     next  = ilink->next;
986     ilink = next;
987   }
988   ierr = PetscFree2(jac->x,jac->y);CHKERRQ(ierr);
989   if (jac->mat && jac->mat != jac->pmat) {
990     ierr = MatDestroyMatrices(jac->nsplits,&jac->mat);CHKERRQ(ierr);
991   } else if (jac->mat) {
992     jac->mat = PETSC_NULL;
993   }
994   if (jac->pmat) {ierr = MatDestroyMatrices(jac->nsplits,&jac->pmat);CHKERRQ(ierr);}
995   if (jac->Afield) {ierr = MatDestroyMatrices(jac->nsplits,&jac->Afield);CHKERRQ(ierr);}
996   ierr       = VecDestroy(&jac->w1);CHKERRQ(ierr);
997   ierr       = VecDestroy(&jac->w2);CHKERRQ(ierr);
998   ierr       = MatDestroy(&jac->schur);CHKERRQ(ierr);
999   ierr       = MatDestroy(&jac->schur_user);CHKERRQ(ierr);
1000   ierr       = KSPDestroy(&jac->kspschur);CHKERRQ(ierr);
1001   ierr       = KSPDestroy(&jac->kspupper);CHKERRQ(ierr);
1002   ierr       = MatDestroy(&jac->B);CHKERRQ(ierr);
1003   ierr       = MatDestroy(&jac->C);CHKERRQ(ierr);
1004   jac->reset = PETSC_TRUE;
1005   PetscFunctionReturn(0);
1006 }
1007 
1008 #undef __FUNCT__
1009 #define __FUNCT__ "PCDestroy_FieldSplit"
1010 static PetscErrorCode PCDestroy_FieldSplit(PC pc)
1011 {
1012   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
1013   PetscErrorCode    ierr;
1014   PC_FieldSplitLink ilink = jac->head,next;
1015 
1016   PetscFunctionBegin;
1017   ierr = PCReset_FieldSplit(pc);CHKERRQ(ierr);
1018   while (ilink) {
1019     ierr  = KSPDestroy(&ilink->ksp);CHKERRQ(ierr);
1020     next  = ilink->next;
1021     ierr  = PetscFree(ilink->splitname);CHKERRQ(ierr);
1022     ierr  = PetscFree(ilink->fields);CHKERRQ(ierr);
1023     ierr  = PetscFree(ilink->fields_col);CHKERRQ(ierr);
1024     ierr  = PetscFree(ilink);CHKERRQ(ierr);
1025     ilink = next;
1026   }
1027   ierr = PetscFree2(jac->x,jac->y);CHKERRQ(ierr);
1028   ierr = PetscFree(pc->data);CHKERRQ(ierr);
1029   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitGetSubKSP_C","",PETSC_NULL);CHKERRQ(ierr);
1030   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetFields_C","",PETSC_NULL);CHKERRQ(ierr);
1031   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetIS_C","",PETSC_NULL);CHKERRQ(ierr);
1032   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetType_C","",PETSC_NULL);CHKERRQ(ierr);
1033   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetBlockSize_C","",PETSC_NULL);CHKERRQ(ierr);
1034   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSchurPrecondition_C","",PETSC_NULL);CHKERRQ(ierr);
1035   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetSchurFactType_C","",PETSC_NULL);CHKERRQ(ierr);
1036   PetscFunctionReturn(0);
1037 }
1038 
1039 #undef __FUNCT__
1040 #define __FUNCT__ "PCSetFromOptions_FieldSplit"
1041 static PetscErrorCode PCSetFromOptions_FieldSplit(PC pc)
1042 {
1043   PetscErrorCode  ierr;
1044   PetscInt        bs;
1045   PetscBool       flg,stokes = PETSC_FALSE;
1046   PC_FieldSplit   *jac = (PC_FieldSplit*)pc->data;
1047   PCCompositeType ctype;
1048   DM              ddm;
1049   char            ddm_name[1025];
1050 
1051   PetscFunctionBegin;
1052   ierr = PetscOptionsHead("FieldSplit options");CHKERRQ(ierr);
1053   if (pc->dm) {
1054     /* Allow the user to request a decomposition DM by name */
1055     ierr = PetscStrncpy(ddm_name, "", 1024);CHKERRQ(ierr);
1056     ierr = PetscOptionsString("-pc_fieldsplit_decomposition", "Name of the DM defining the composition", "PCSetDM", ddm_name, ddm_name,1024,&flg);CHKERRQ(ierr);
1057     if (flg) {
1058       ierr = DMCreateFieldDecompositionDM(pc->dm, ddm_name, &ddm);CHKERRQ(ierr);
1059       if (!ddm) SETERRQ1(((PetscObject)pc)->comm, PETSC_ERR_ARG_WRONGSTATE, "Uknown field decomposition name %s", ddm_name);
1060       ierr = PetscInfo(pc,"Using field decomposition DM defined using options database\n");CHKERRQ(ierr);
1061       ierr = PCSetDM(pc,ddm);CHKERRQ(ierr);
1062     }
1063   }
1064   ierr = PetscOptionsBool("-pc_fieldsplit_real_diagonal","Use diagonal blocks of the operator","PCFieldSplitSetRealDiagonal",jac->realdiagonal,&jac->realdiagonal,PETSC_NULL);CHKERRQ(ierr);
1065   ierr = PetscOptionsInt("-pc_fieldsplit_block_size","Blocksize that defines number of fields","PCFieldSplitSetBlockSize",jac->bs,&bs,&flg);CHKERRQ(ierr);
1066   if (flg) {
1067     ierr = PCFieldSplitSetBlockSize(pc,bs);CHKERRQ(ierr);
1068   }
1069 
1070   ierr = PetscOptionsGetBool(((PetscObject)pc)->prefix,"-pc_fieldsplit_detect_saddle_point",&stokes,PETSC_NULL);CHKERRQ(ierr);
1071   if (stokes) {
1072     ierr          = PCFieldSplitSetType(pc,PC_COMPOSITE_SCHUR);CHKERRQ(ierr);
1073     jac->schurpre = PC_FIELDSPLIT_SCHUR_PRE_SELF;
1074   }
1075 
1076   ierr = PetscOptionsEnum("-pc_fieldsplit_type","Type of composition","PCFieldSplitSetType",PCCompositeTypes,(PetscEnum)jac->type,(PetscEnum*)&ctype,&flg);CHKERRQ(ierr);
1077   if (flg) {
1078     ierr = PCFieldSplitSetType(pc,ctype);CHKERRQ(ierr);
1079   }
1080   /* Only setup fields once */
1081   if ((jac->bs > 0) && (jac->nsplits == 0)) {
1082     /* only allow user to set fields from command line if bs is already known.
1083        otherwise user can set them in PCFieldSplitSetDefaults() */
1084     ierr = PCFieldSplitSetRuntimeSplits_Private(pc);CHKERRQ(ierr);
1085     if (jac->splitdefined) {ierr = PetscInfo(pc,"Splits defined using the options database\n");CHKERRQ(ierr);}
1086   }
1087   if (jac->type == PC_COMPOSITE_SCHUR) {
1088     ierr = PetscOptionsGetEnum(((PetscObject)pc)->prefix,"-pc_fieldsplit_schur_factorization_type",PCFieldSplitSchurFactTypes,(PetscEnum*)&jac->schurfactorization,&flg);CHKERRQ(ierr);
1089     if (flg) {ierr = PetscInfo(pc,"Deprecated use of -pc_fieldsplit_schur_factorization_type\n");CHKERRQ(ierr);}
1090     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,PETSC_NULL);CHKERRQ(ierr);
1091     ierr = PetscOptionsEnum("-pc_fieldsplit_schur_precondition","How to build preconditioner for Schur complement","PCFieldSplitSchurPrecondition",PCFieldSplitSchurPreTypes,(PetscEnum)jac->schurpre,(PetscEnum*)&jac->schurpre,PETSC_NULL);CHKERRQ(ierr);
1092   }
1093   ierr = PetscOptionsTail();CHKERRQ(ierr);
1094   PetscFunctionReturn(0);
1095 }
1096 
1097 /*------------------------------------------------------------------------------------*/
1098 
1099 EXTERN_C_BEGIN
1100 #undef __FUNCT__
1101 #define __FUNCT__ "PCFieldSplitSetFields_FieldSplit"
1102 PetscErrorCode  PCFieldSplitSetFields_FieldSplit(PC pc,const char splitname[],PetscInt n,const PetscInt *fields,const PetscInt *fields_col)
1103 {
1104   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
1105   PetscErrorCode    ierr;
1106   PC_FieldSplitLink ilink,next = jac->head;
1107   char              prefix[128];
1108   PetscInt          i;
1109 
1110   PetscFunctionBegin;
1111   if (jac->splitdefined) {
1112     ierr = PetscInfo1(pc,"Ignoring new split \"%s\" because the splits have already been defined\n",splitname);CHKERRQ(ierr);
1113     PetscFunctionReturn(0);
1114   }
1115   for (i=0; i<n; i++) {
1116     if (fields[i] >= jac->bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Field %D requested but only %D exist",fields[i],jac->bs);
1117     if (fields[i] < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative field %D requested",fields[i]);
1118   }
1119   ierr = PetscNew(struct _PC_FieldSplitLink,&ilink);CHKERRQ(ierr);
1120   if (splitname) {
1121     ierr = PetscStrallocpy(splitname,&ilink->splitname);CHKERRQ(ierr);
1122   } else {
1123     ierr = PetscMalloc(3*sizeof(char),&ilink->splitname);CHKERRQ(ierr);
1124     ierr = PetscSNPrintf(ilink->splitname,2,"%s",jac->nsplits);CHKERRQ(ierr);
1125   }
1126   ierr = PetscMalloc(n*sizeof(PetscInt),&ilink->fields);CHKERRQ(ierr);
1127   ierr = PetscMemcpy(ilink->fields,fields,n*sizeof(PetscInt));CHKERRQ(ierr);
1128   ierr = PetscMalloc(n*sizeof(PetscInt),&ilink->fields_col);CHKERRQ(ierr);
1129   ierr = PetscMemcpy(ilink->fields_col,fields_col,n*sizeof(PetscInt));CHKERRQ(ierr);
1130 
1131   ilink->nfields = n;
1132   ilink->next    = PETSC_NULL;
1133   ierr           = KSPCreate(((PetscObject)pc)->comm,&ilink->ksp);CHKERRQ(ierr);
1134   ierr           = PetscObjectIncrementTabLevel((PetscObject)ilink->ksp,(PetscObject)pc,1);CHKERRQ(ierr);
1135   ierr           = KSPSetType(ilink->ksp,KSPPREONLY);CHKERRQ(ierr);
1136   ierr           = PetscLogObjectParent((PetscObject)pc,(PetscObject)ilink->ksp);CHKERRQ(ierr);
1137 
1138   ierr = PetscSNPrintf(prefix,sizeof(prefix),"%sfieldsplit_%s_",((PetscObject)pc)->prefix ? ((PetscObject)pc)->prefix : "",ilink->splitname);CHKERRQ(ierr);
1139   ierr = KSPSetOptionsPrefix(ilink->ksp,prefix);CHKERRQ(ierr);
1140 
1141   if (!next) {
1142     jac->head       = ilink;
1143     ilink->previous = PETSC_NULL;
1144   } else {
1145     while (next->next) {
1146       next = next->next;
1147     }
1148     next->next      = ilink;
1149     ilink->previous = next;
1150   }
1151   jac->nsplits++;
1152   PetscFunctionReturn(0);
1153 }
1154 EXTERN_C_END
1155 
1156 EXTERN_C_BEGIN
1157 #undef __FUNCT__
1158 #define __FUNCT__ "PCFieldSplitGetSubKSP_FieldSplit_Schur"
1159 PetscErrorCode  PCFieldSplitGetSubKSP_FieldSplit_Schur(PC pc,PetscInt *n,KSP **subksp)
1160 {
1161   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
1162   PetscErrorCode ierr;
1163 
1164   PetscFunctionBegin;
1165   ierr = PetscMalloc(jac->nsplits*sizeof(KSP),subksp);CHKERRQ(ierr);
1166   ierr = MatSchurComplementGetKSP(jac->schur,*subksp);CHKERRQ(ierr);
1167 
1168   (*subksp)[1] = jac->kspschur;
1169   if (n) *n = jac->nsplits;
1170   PetscFunctionReturn(0);
1171 }
1172 EXTERN_C_END
1173 
1174 EXTERN_C_BEGIN
1175 #undef __FUNCT__
1176 #define __FUNCT__ "PCFieldSplitGetSubKSP_FieldSplit"
1177 PetscErrorCode  PCFieldSplitGetSubKSP_FieldSplit(PC pc,PetscInt *n,KSP **subksp)
1178 {
1179   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
1180   PetscErrorCode    ierr;
1181   PetscInt          cnt   = 0;
1182   PC_FieldSplitLink ilink = jac->head;
1183 
1184   PetscFunctionBegin;
1185   ierr = PetscMalloc(jac->nsplits*sizeof(KSP),subksp);CHKERRQ(ierr);
1186   while (ilink) {
1187     (*subksp)[cnt++] = ilink->ksp;
1188     ilink            = ilink->next;
1189   }
1190   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);
1191   if (n) *n = jac->nsplits;
1192   PetscFunctionReturn(0);
1193 }
1194 EXTERN_C_END
1195 
1196 EXTERN_C_BEGIN
1197 #undef __FUNCT__
1198 #define __FUNCT__ "PCFieldSplitSetIS_FieldSplit"
1199 PetscErrorCode  PCFieldSplitSetIS_FieldSplit(PC pc,const char splitname[],IS is)
1200 {
1201   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
1202   PetscErrorCode    ierr;
1203   PC_FieldSplitLink ilink, next = jac->head;
1204   char              prefix[128];
1205 
1206   PetscFunctionBegin;
1207   if (jac->splitdefined) {
1208     ierr = PetscInfo1(pc,"Ignoring new split \"%s\" because the splits have already been defined\n",splitname);CHKERRQ(ierr);
1209     PetscFunctionReturn(0);
1210   }
1211   ierr = PetscNew(struct _PC_FieldSplitLink,&ilink);CHKERRQ(ierr);
1212   if (splitname) {
1213     ierr = PetscStrallocpy(splitname,&ilink->splitname);CHKERRQ(ierr);
1214   } else {
1215     ierr = PetscMalloc(8*sizeof(char),&ilink->splitname);CHKERRQ(ierr);
1216     ierr = PetscSNPrintf(ilink->splitname,7,"%D",jac->nsplits);CHKERRQ(ierr);
1217   }
1218   ierr          = PetscObjectReference((PetscObject)is);CHKERRQ(ierr);
1219   ierr          = ISDestroy(&ilink->is);CHKERRQ(ierr);
1220   ilink->is     = is;
1221   ierr          = PetscObjectReference((PetscObject)is);CHKERRQ(ierr);
1222   ierr          = ISDestroy(&ilink->is_col);CHKERRQ(ierr);
1223   ilink->is_col = is;
1224   ilink->next   = PETSC_NULL;
1225   ierr          = KSPCreate(((PetscObject)pc)->comm,&ilink->ksp);CHKERRQ(ierr);
1226   ierr          = PetscObjectIncrementTabLevel((PetscObject)ilink->ksp,(PetscObject)pc,1);CHKERRQ(ierr);
1227   ierr          = KSPSetType(ilink->ksp,KSPPREONLY);CHKERRQ(ierr);
1228   ierr          = PetscLogObjectParent((PetscObject)pc,(PetscObject)ilink->ksp);CHKERRQ(ierr);
1229 
1230   ierr = PetscSNPrintf(prefix,sizeof(prefix),"%sfieldsplit_%s_",((PetscObject)pc)->prefix ? ((PetscObject)pc)->prefix : "",ilink->splitname);CHKERRQ(ierr);
1231   ierr = KSPSetOptionsPrefix(ilink->ksp,prefix);CHKERRQ(ierr);
1232 
1233   if (!next) {
1234     jac->head       = ilink;
1235     ilink->previous = PETSC_NULL;
1236   } else {
1237     while (next->next) {
1238       next = next->next;
1239     }
1240     next->next      = ilink;
1241     ilink->previous = next;
1242   }
1243   jac->nsplits++;
1244   PetscFunctionReturn(0);
1245 }
1246 EXTERN_C_END
1247 
1248 #undef __FUNCT__
1249 #define __FUNCT__ "PCFieldSplitSetFields"
1250 /*@
1251     PCFieldSplitSetFields - Sets the fields for one particular split in the field split preconditioner
1252 
1253     Logically Collective on PC
1254 
1255     Input Parameters:
1256 +   pc  - the preconditioner context
1257 .   splitname - name of this split, if PETSC_NULL the number of the split is used
1258 .   n - the number of fields in this split
1259 -   fields - the fields in this split
1260 
1261     Level: intermediate
1262 
1263     Notes: Use PCFieldSplitSetIS() to set a completely general set of indices as a field.
1264 
1265      The PCFieldSplitSetFields() is for defining fields as strided blocks. For example, if the block
1266      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
1267      0xx3xx6xx9xx12 ... x1xx4xx7xx ... xx2xx5xx8xx.. 01x34x67x... 0x1x3x5x7.. x12x45x78x....
1268      where the numbered entries indicate what is in the field.
1269 
1270      This function is called once per split (it creates a new split each time).  Solve options
1271      for this split will be available under the prefix -fieldsplit_SPLITNAME_.
1272 
1273      Developer Note: This routine does not actually create the IS representing the split, that is delayed
1274      until PCSetUp_FieldSplit(), because information about the vector/matrix layouts may not be
1275      available when this routine is called.
1276 
1277 .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetBlockSize(), PCFieldSplitSetIS()
1278 
1279 @*/
1280 PetscErrorCode  PCFieldSplitSetFields(PC pc,const char splitname[],PetscInt n,const PetscInt *fields,const PetscInt *fields_col)
1281 {
1282   PetscErrorCode ierr;
1283 
1284   PetscFunctionBegin;
1285   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1286   PetscValidCharPointer(splitname,2);
1287   if (n < 1) SETERRQ2(((PetscObject)pc)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Provided number of fields %D in split \"%s\" not positive",n,splitname);
1288   PetscValidIntPointer(fields,3);
1289   ierr = PetscTryMethod(pc,"PCFieldSplitSetFields_C",(PC,const char[],PetscInt,const PetscInt*,const PetscInt*),(pc,splitname,n,fields,fields_col));CHKERRQ(ierr);
1290   PetscFunctionReturn(0);
1291 }
1292 
1293 #undef __FUNCT__
1294 #define __FUNCT__ "PCFieldSplitSetIS"
1295 /*@
1296     PCFieldSplitSetIS - Sets the exact elements for field
1297 
1298     Logically Collective on PC
1299 
1300     Input Parameters:
1301 +   pc  - the preconditioner context
1302 .   splitname - name of this split, if PETSC_NULL the number of the split is used
1303 -   is - the index set that defines the vector elements in this field
1304 
1305 
1306     Notes:
1307     Use PCFieldSplitSetFields(), for fields defined by strided types.
1308 
1309     This function is called once per split (it creates a new split each time).  Solve options
1310     for this split will be available under the prefix -fieldsplit_SPLITNAME_.
1311 
1312     Level: intermediate
1313 
1314 .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetBlockSize()
1315 
1316 @*/
1317 PetscErrorCode  PCFieldSplitSetIS(PC pc,const char splitname[],IS is)
1318 {
1319   PetscErrorCode ierr;
1320 
1321   PetscFunctionBegin;
1322   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1323   if (splitname) PetscValidCharPointer(splitname,2);
1324   PetscValidHeaderSpecific(is,IS_CLASSID,3);
1325   ierr = PetscTryMethod(pc,"PCFieldSplitSetIS_C",(PC,const char[],IS),(pc,splitname,is));CHKERRQ(ierr);
1326   PetscFunctionReturn(0);
1327 }
1328 
1329 #undef __FUNCT__
1330 #define __FUNCT__ "PCFieldSplitGetIS"
1331 /*@
1332     PCFieldSplitGetIS - Retrieves the elements for a field as an IS
1333 
1334     Logically Collective on PC
1335 
1336     Input Parameters:
1337 +   pc  - the preconditioner context
1338 -   splitname - name of this split
1339 
1340     Output Parameter:
1341 -   is - the index set that defines the vector elements in this field, or PETSC_NULL if the field is not found
1342 
1343     Level: intermediate
1344 
1345 .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetIS()
1346 
1347 @*/
1348 PetscErrorCode PCFieldSplitGetIS(PC pc,const char splitname[],IS *is)
1349 {
1350   PetscErrorCode ierr;
1351 
1352   PetscFunctionBegin;
1353   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1354   PetscValidCharPointer(splitname,2);
1355   PetscValidPointer(is,3);
1356   {
1357     PC_FieldSplit     *jac  = (PC_FieldSplit*) pc->data;
1358     PC_FieldSplitLink ilink = jac->head;
1359     PetscBool         found;
1360 
1361     *is = PETSC_NULL;
1362     while (ilink) {
1363       ierr = PetscStrcmp(ilink->splitname, splitname, &found);CHKERRQ(ierr);
1364       if (found) {
1365         *is = ilink->is;
1366         break;
1367       }
1368       ilink = ilink->next;
1369     }
1370   }
1371   PetscFunctionReturn(0);
1372 }
1373 
1374 #undef __FUNCT__
1375 #define __FUNCT__ "PCFieldSplitSetBlockSize"
1376 /*@
1377     PCFieldSplitSetBlockSize - Sets the block size for defining where fields start in the
1378       fieldsplit preconditioner. If not set the matrix block size is used.
1379 
1380     Logically Collective on PC
1381 
1382     Input Parameters:
1383 +   pc  - the preconditioner context
1384 -   bs - the block size
1385 
1386     Level: intermediate
1387 
1388 .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetFields()
1389 
1390 @*/
1391 PetscErrorCode  PCFieldSplitSetBlockSize(PC pc,PetscInt bs)
1392 {
1393   PetscErrorCode ierr;
1394 
1395   PetscFunctionBegin;
1396   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1397   PetscValidLogicalCollectiveInt(pc,bs,2);
1398   ierr = PetscTryMethod(pc,"PCFieldSplitSetBlockSize_C",(PC,PetscInt),(pc,bs));CHKERRQ(ierr);
1399   PetscFunctionReturn(0);
1400 }
1401 
1402 #undef __FUNCT__
1403 #define __FUNCT__ "PCFieldSplitGetSubKSP"
1404 /*@C
1405    PCFieldSplitGetSubKSP - Gets the KSP contexts for all splits
1406 
1407    Collective on KSP
1408 
1409    Input Parameter:
1410 .  pc - the preconditioner context
1411 
1412    Output Parameters:
1413 +  n - the number of splits
1414 -  pc - the array of KSP contexts
1415 
1416    Note:
1417    After PCFieldSplitGetSubKSP() the array of KSPs IS to be freed by the user
1418    (not the KSP just the array that contains them).
1419 
1420    You must call KSPSetUp() before calling PCFieldSplitGetSubKSP().
1421 
1422    Fortran Usage: You must pass in a KSP array that is large enough to contain all the local KSPs.
1423       You can call PCFieldSplitGetSubKSP(pc,n,PETSC_NULL_OBJECT,ierr) to determine how large the
1424       KSP array must be.
1425 
1426 
1427    Level: advanced
1428 
1429 .seealso: PCFIELDSPLIT
1430 @*/
1431 PetscErrorCode  PCFieldSplitGetSubKSP(PC pc,PetscInt *n,KSP *subksp[])
1432 {
1433   PetscErrorCode ierr;
1434 
1435   PetscFunctionBegin;
1436   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1437   if (n) PetscValidIntPointer(n,2);
1438   ierr = PetscUseMethod(pc,"PCFieldSplitGetSubKSP_C",(PC,PetscInt*,KSP **),(pc,n,subksp));CHKERRQ(ierr);
1439   PetscFunctionReturn(0);
1440 }
1441 
1442 #undef __FUNCT__
1443 #define __FUNCT__ "PCFieldSplitSchurPrecondition"
1444 /*@
1445     PCFieldSplitSchurPrecondition -  Indicates if the Schur complement is preconditioned by a preconditioner constructed by the
1446       A11 matrix. Otherwise no preconditioner is used.
1447 
1448     Collective on PC
1449 
1450     Input Parameters:
1451 +   pc  - the preconditioner context
1452 .   ptype - which matrix to use for preconditioning the Schur complement, PC_FIELDSPLIT_SCHUR_PRE_A11 (diag) is default
1453 -   userpre - matrix to use for preconditioning, or PETSC_NULL
1454 
1455     Options Database:
1456 .     -pc_fieldsplit_schur_precondition <self,user,a11> default is a11
1457 
1458     Notes:
1459 $    If ptype is
1460 $        user then the preconditioner for the Schur complement is generated by the provided matrix (pre argument
1461 $             to this function).
1462 $        a11 then the preconditioner for the Schur complement is generated by the block diagonal part of the original
1463 $             matrix associated with the Schur complement (i.e. A11)
1464 $        self the preconditioner for the Schur complement is generated from the Schur complement matrix itself:
1465 $             The only preconditioner that currently works directly with the Schur complement matrix object is the PCLSC
1466 $             preconditioner
1467 
1468      When solving a saddle point problem, where the A11 block is identically zero, using a11 as the ptype only makes sense
1469     with the additional option -fieldsplit_1_pc_type none. Usually for saddle point problems one would use a ptype of self and
1470     -fieldsplit_1_pc_type lsc which uses the least squares commutator compute a preconditioner for the Schur complement.
1471 
1472     Developer Notes: This is a terrible name, gives no good indication of what the function does and should also have Set in
1473      the name since it sets a proceedure to use.
1474 
1475     Level: intermediate
1476 
1477 .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetFields(), PCFieldSplitSchurPreType, PCLSC
1478 
1479 @*/
1480 PetscErrorCode  PCFieldSplitSchurPrecondition(PC pc,PCFieldSplitSchurPreType ptype,Mat pre)
1481 {
1482   PetscErrorCode ierr;
1483 
1484   PetscFunctionBegin;
1485   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1486   ierr = PetscTryMethod(pc,"PCFieldSplitSchurPrecondition_C",(PC,PCFieldSplitSchurPreType,Mat),(pc,ptype,pre));CHKERRQ(ierr);
1487   PetscFunctionReturn(0);
1488 }
1489 
1490 EXTERN_C_BEGIN
1491 #undef __FUNCT__
1492 #define __FUNCT__ "PCFieldSplitSchurPrecondition_FieldSplit"
1493 PetscErrorCode  PCFieldSplitSchurPrecondition_FieldSplit(PC pc,PCFieldSplitSchurPreType ptype,Mat pre)
1494 {
1495   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
1496   PetscErrorCode ierr;
1497 
1498   PetscFunctionBegin;
1499   jac->schurpre = ptype;
1500   if (pre) {
1501     ierr            = MatDestroy(&jac->schur_user);CHKERRQ(ierr);
1502     jac->schur_user = pre;
1503     ierr            = PetscObjectReference((PetscObject)jac->schur_user);CHKERRQ(ierr);
1504   }
1505   PetscFunctionReturn(0);
1506 }
1507 EXTERN_C_END
1508 
1509 #undef __FUNCT__
1510 #define __FUNCT__ "PCFieldSplitSetSchurFactType"
1511 /*@
1512     PCFieldSplitSetSchurFactType -  sets which blocks of the approximate block factorization to retain
1513 
1514     Collective on PC
1515 
1516     Input Parameters:
1517 +   pc  - the preconditioner context
1518 -   ftype - which blocks of factorization to retain, PC_FIELDSPLIT_SCHUR_FACT_FULL is default
1519 
1520     Options Database:
1521 .     -pc_fieldsplit_schur_fact_type <diag,lower,upper,full> default is full
1522 
1523 
1524     Level: intermediate
1525 
1526     Notes:
1527     The FULL factorization is
1528 
1529 $   (A   B)  = (1       0) (A   0) (1  Ainv*B)
1530 $   (C   D)    (C*Ainv  1) (0   S) (0     1  )
1531 
1532     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,
1533     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).
1534 
1535     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
1536     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
1537     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,
1538     the preconditioned operator has three distinct nonzero eigenvalues and minimal polynomial of degree at most 4, so KSPGMRES converges in at most 4 iterations.
1539 
1540     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
1541     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).
1542 
1543     References:
1544     Murphy, Golub, and Wathen, A note on preconditioning indefinite linear systems, SIAM J. Sci. Comput., 21 (2000) pp. 1969-1972.
1545 
1546     Ipsen, A note on preconditioning nonsymmetric matrices, SIAM J. Sci. Comput., 23 (2001), pp. 1050-1051.
1547 
1548 .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetFields(), PCFieldSplitSchurPreType
1549 @*/
1550 PetscErrorCode  PCFieldSplitSetSchurFactType(PC pc,PCFieldSplitSchurFactType ftype)
1551 {
1552   PetscErrorCode ierr;
1553 
1554   PetscFunctionBegin;
1555   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1556   ierr = PetscTryMethod(pc,"PCFieldSplitSetSchurFactType_C",(PC,PCFieldSplitSchurFactType),(pc,ftype));CHKERRQ(ierr);
1557   PetscFunctionReturn(0);
1558 }
1559 
1560 #undef __FUNCT__
1561 #define __FUNCT__ "PCFieldSplitSetSchurFactType_FieldSplit"
1562 PETSC_EXTERN_C PetscErrorCode PCFieldSplitSetSchurFactType_FieldSplit(PC pc,PCFieldSplitSchurFactType ftype)
1563 {
1564   PC_FieldSplit *jac = (PC_FieldSplit*)pc->data;
1565 
1566   PetscFunctionBegin;
1567   jac->schurfactorization = ftype;
1568   PetscFunctionReturn(0);
1569 }
1570 
1571 #undef __FUNCT__
1572 #define __FUNCT__ "PCFieldSplitGetSchurBlocks"
1573 /*@C
1574    PCFieldSplitGetSchurBlocks - Gets all matrix blocks for the Schur complement
1575 
1576    Collective on KSP
1577 
1578    Input Parameter:
1579 .  pc - the preconditioner context
1580 
1581    Output Parameters:
1582 +  A00 - the (0,0) block
1583 .  A01 - the (0,1) block
1584 .  A10 - the (1,0) block
1585 -  A11 - the (1,1) block
1586 
1587    Level: advanced
1588 
1589 .seealso: PCFIELDSPLIT
1590 @*/
1591 PetscErrorCode  PCFieldSplitGetSchurBlocks(PC pc,Mat *A00,Mat *A01,Mat *A10, Mat *A11)
1592 {
1593   PC_FieldSplit *jac = (PC_FieldSplit*) pc->data;
1594 
1595   PetscFunctionBegin;
1596   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1597   if (jac->type != PC_COMPOSITE_SCHUR) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ARG_WRONG, "FieldSplit is not using a Schur complement approach.");
1598   if (A00) *A00 = jac->pmat[0];
1599   if (A01) *A01 = jac->B;
1600   if (A10) *A10 = jac->C;
1601   if (A11) *A11 = jac->pmat[1];
1602   PetscFunctionReturn(0);
1603 }
1604 
1605 EXTERN_C_BEGIN
1606 #undef __FUNCT__
1607 #define __FUNCT__ "PCFieldSplitSetType_FieldSplit"
1608 PetscErrorCode  PCFieldSplitSetType_FieldSplit(PC pc,PCCompositeType type)
1609 {
1610   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
1611   PetscErrorCode ierr;
1612 
1613   PetscFunctionBegin;
1614   jac->type = type;
1615   if (type == PC_COMPOSITE_SCHUR) {
1616     pc->ops->apply = PCApply_FieldSplit_Schur;
1617     pc->ops->view  = PCView_FieldSplit_Schur;
1618 
1619     ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitGetSubKSP_C","PCFieldSplitGetSubKSP_FieldSplit_Schur",PCFieldSplitGetSubKSP_FieldSplit_Schur);CHKERRQ(ierr);
1620     ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSchurPrecondition_C","PCFieldSplitSchurPrecondition_FieldSplit",PCFieldSplitSchurPrecondition_FieldSplit);CHKERRQ(ierr);
1621     ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetSchurFactType_C","PCFieldSplitSetSchurFactType_FieldSplit",PCFieldSplitSetSchurFactType_FieldSplit);CHKERRQ(ierr);
1622 
1623   } else {
1624     pc->ops->apply = PCApply_FieldSplit;
1625     pc->ops->view  = PCView_FieldSplit;
1626 
1627     ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitGetSubKSP_C","PCFieldSplitGetSubKSP_FieldSplit",PCFieldSplitGetSubKSP_FieldSplit);CHKERRQ(ierr);
1628     ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSchurPrecondition_C","",0);CHKERRQ(ierr);
1629     ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetSchurFactType_C","",0);CHKERRQ(ierr);
1630   }
1631   PetscFunctionReturn(0);
1632 }
1633 EXTERN_C_END
1634 
1635 EXTERN_C_BEGIN
1636 #undef __FUNCT__
1637 #define __FUNCT__ "PCFieldSplitSetBlockSize_FieldSplit"
1638 PetscErrorCode  PCFieldSplitSetBlockSize_FieldSplit(PC pc,PetscInt bs)
1639 {
1640   PC_FieldSplit *jac = (PC_FieldSplit*)pc->data;
1641 
1642   PetscFunctionBegin;
1643   if (bs < 1) SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Blocksize must be positive, you gave %D",bs);
1644   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);
1645   jac->bs = bs;
1646   PetscFunctionReturn(0);
1647 }
1648 EXTERN_C_END
1649 
1650 #undef __FUNCT__
1651 #define __FUNCT__ "PCFieldSplitSetType"
1652 /*@
1653    PCFieldSplitSetType - Sets the type of fieldsplit preconditioner.
1654 
1655    Collective on PC
1656 
1657    Input Parameter:
1658 .  pc - the preconditioner context
1659 .  type - PC_COMPOSITE_ADDITIVE, PC_COMPOSITE_MULTIPLICATIVE (default), PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE, PC_COMPOSITE_SPECIAL, PC_COMPOSITE_SCHUR
1660 
1661    Options Database Key:
1662 .  -pc_fieldsplit_type <type: one of multiplicative, additive, symmetric_multiplicative, special, schur> - Sets fieldsplit preconditioner type
1663 
1664    Level: Intermediate
1665 
1666 .keywords: PC, set, type, composite preconditioner, additive, multiplicative
1667 
1668 .seealso: PCCompositeSetType()
1669 
1670 @*/
1671 PetscErrorCode  PCFieldSplitSetType(PC pc,PCCompositeType type)
1672 {
1673   PetscErrorCode ierr;
1674 
1675   PetscFunctionBegin;
1676   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1677   ierr = PetscTryMethod(pc,"PCFieldSplitSetType_C",(PC,PCCompositeType),(pc,type));CHKERRQ(ierr);
1678   PetscFunctionReturn(0);
1679 }
1680 
1681 #undef __FUNCT__
1682 #define __FUNCT__ "PCFieldSplitGetType"
1683 /*@
1684   PCFieldSplitGetType - Gets the type of fieldsplit preconditioner.
1685 
1686   Not collective
1687 
1688   Input Parameter:
1689 . pc - the preconditioner context
1690 
1691   Output Parameter:
1692 . type - PC_COMPOSITE_ADDITIVE, PC_COMPOSITE_MULTIPLICATIVE (default), PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE, PC_COMPOSITE_SPECIAL, PC_COMPOSITE_SCHUR
1693 
1694   Level: Intermediate
1695 
1696 .keywords: PC, set, type, composite preconditioner, additive, multiplicative
1697 .seealso: PCCompositeSetType()
1698 @*/
1699 PetscErrorCode PCFieldSplitGetType(PC pc, PCCompositeType *type)
1700 {
1701   PC_FieldSplit *jac = (PC_FieldSplit*) pc->data;
1702 
1703   PetscFunctionBegin;
1704   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1705   PetscValidIntPointer(type,2);
1706   *type = jac->type;
1707   PetscFunctionReturn(0);
1708 }
1709 
1710 /* -------------------------------------------------------------------------------------*/
1711 /*MC
1712    PCFIELDSPLIT - Preconditioner created by combining separate preconditioners for individual
1713                   fields or groups of fields. See the users manual section "Solving Block Matrices" for more details.
1714 
1715      To set options on the solvers for each block append -fieldsplit_ to all the PC
1716         options database keys. For example, -fieldsplit_pc_type ilu -fieldsplit_pc_factor_levels 1
1717 
1718      To set the options on the solvers separate for each block call PCFieldSplitGetSubKSP()
1719          and set the options directly on the resulting KSP object
1720 
1721    Level: intermediate
1722 
1723    Options Database Keys:
1724 +   -pc_fieldsplit_%d_fields <a,b,..> - indicates the fields to be used in the %d'th split
1725 .   -pc_fieldsplit_default - automatically add any fields to additional splits that have not
1726                               been supplied explicitly by -pc_fieldsplit_%d_fields
1727 .   -pc_fieldsplit_block_size <bs> - size of block that defines fields (i.e. there are bs fields)
1728 .   -pc_fieldsplit_type <additive,multiplicative,symmetric_multiplicative,schur> - type of relaxation or factorization splitting
1729 .   -pc_fieldsplit_schur_precondition <self,user,a11> - default is a11
1730 .   -pc_fieldsplit_detect_saddle_point - automatically finds rows with zero or negative diagonal and uses Schur complement with no preconditioner as the solver
1731 
1732 -    Options prefix for inner solvers when using Schur complement preconditioner are -fieldsplit_0_ and -fieldsplit_1_
1733      for all other solvers they are -fieldsplit_%d_ for the dth field, use -fieldsplit_ for all fields
1734 
1735    Notes:
1736     Use PCFieldSplitSetFields() to set fields defined by "strided" entries and PCFieldSplitSetIS()
1737      to define a field by an arbitrary collection of entries.
1738 
1739       If no fields are set the default is used. The fields are defined by entries strided by bs,
1740       beginning at 0 then 1, etc to bs-1. The block size can be set with PCFieldSplitSetBlockSize(),
1741       if this is not called the block size defaults to the blocksize of the second matrix passed
1742       to KSPSetOperators()/PCSetOperators().
1743 
1744 $     For the Schur complement preconditioner if J = ( A00 A01 )
1745 $                                                    ( A10 A11 )
1746 $     the preconditioner using full factorization is
1747 $              ( I   -A10 ksp(A00) ) ( inv(A00)     0  ) (     I          0  )
1748 $              ( 0         I       ) (   0      ksp(S) ) ( -A10 ksp(A00)  I  )
1749      where the action of inv(A00) is applied using the KSP solver with prefix -fieldsplit_0_. The action of
1750      ksp(S) is computed using the KSP solver with prefix -fieldsplit_splitname_ (where splitname was given
1751      in providing the SECOND split or 1 if not give). For PCFieldSplitGetKSP() when field number is 0,
1752      it returns the KSP associated with -fieldsplit_0_ while field number 1 gives -fieldsplit_1_ KSP. By default
1753      A11 is used to construct a preconditioner for S, use PCFieldSplitSchurPrecondition() to turn on or off this
1754      option. You can use the preconditioner PCLSC to precondition the Schur complement with -fieldsplit_1_pc_type lsc. The
1755      factorization type is set using -pc_fieldsplit_schur_fact_type <diag, lower, upper, full>. The full is shown above,
1756      diag gives
1757 $              ( inv(A00)     0   )
1758 $              (   0      -ksp(S) )
1759      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
1760 $              (  A00   0 )
1761 $              (  A10   S )
1762      where the inverses of A00 and S are applied using KSPs. The upper factorization is the inverse of
1763 $              ( A00 A01 )
1764 $              (  0   S  )
1765      where again the inverses of A00 and S are applied using KSPs.
1766 
1767      If only one set of indices (one IS) is provided with PCFieldSplitSetIS() then the complement of that IS
1768      is used automatically for a second block.
1769 
1770      The fieldsplit preconditioner cannot currently be used with the BAIJ or SBAIJ data formats if the blocksize is larger than 1.
1771      Generally it should be used with the AIJ format.
1772 
1773      The forms of these preconditioners are closely related if not identical to forms derived as "Distributive Iterations", see,
1774      for example, page 294 in "Principles of Computational Fluid Dynamics" by Pieter Wesseling. Note that one can also use PCFIELDSPLIT
1775      inside a smoother resulting in "Distributive Smoothers".
1776 
1777    Concepts: physics based preconditioners, block preconditioners
1778 
1779 .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC, Block_Preconditioners, PCLSC,
1780            PCFieldSplitGetSubKSP(), PCFieldSplitSetFields(), PCFieldSplitSetType(), PCFieldSplitSetIS(), PCFieldSplitSchurPrecondition()
1781 M*/
1782 
1783 EXTERN_C_BEGIN
1784 #undef __FUNCT__
1785 #define __FUNCT__ "PCCreate_FieldSplit"
1786 PetscErrorCode  PCCreate_FieldSplit(PC pc)
1787 {
1788   PetscErrorCode ierr;
1789   PC_FieldSplit  *jac;
1790 
1791   PetscFunctionBegin;
1792   ierr = PetscNewLog(pc,PC_FieldSplit,&jac);CHKERRQ(ierr);
1793 
1794   jac->bs                 = -1;
1795   jac->nsplits            = 0;
1796   jac->type               = PC_COMPOSITE_MULTIPLICATIVE;
1797   jac->schurpre           = PC_FIELDSPLIT_SCHUR_PRE_USER; /* Try user preconditioner first, fall back on diagonal */
1798   jac->schurfactorization = PC_FIELDSPLIT_SCHUR_FACT_FULL;
1799 
1800   pc->data = (void*)jac;
1801 
1802   pc->ops->apply           = PCApply_FieldSplit;
1803   pc->ops->applytranspose  = PCApplyTranspose_FieldSplit;
1804   pc->ops->setup           = PCSetUp_FieldSplit;
1805   pc->ops->reset           = PCReset_FieldSplit;
1806   pc->ops->destroy         = PCDestroy_FieldSplit;
1807   pc->ops->setfromoptions  = PCSetFromOptions_FieldSplit;
1808   pc->ops->view            = PCView_FieldSplit;
1809   pc->ops->applyrichardson = 0;
1810 
1811   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitGetSubKSP_C","PCFieldSplitGetSubKSP_FieldSplit",
1812                                            PCFieldSplitGetSubKSP_FieldSplit);CHKERRQ(ierr);
1813   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetFields_C","PCFieldSplitSetFields_FieldSplit",
1814                                            PCFieldSplitSetFields_FieldSplit);CHKERRQ(ierr);
1815   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetIS_C","PCFieldSplitSetIS_FieldSplit",
1816                                            PCFieldSplitSetIS_FieldSplit);CHKERRQ(ierr);
1817   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetType_C","PCFieldSplitSetType_FieldSplit",
1818                                            PCFieldSplitSetType_FieldSplit);CHKERRQ(ierr);
1819   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetBlockSize_C","PCFieldSplitSetBlockSize_FieldSplit",
1820                                            PCFieldSplitSetBlockSize_FieldSplit);CHKERRQ(ierr);
1821   PetscFunctionReturn(0);
1822 }
1823 EXTERN_C_END
1824 
1825 
1826 
1827