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