xref: /petsc/src/ksp/pc/impls/fieldsplit/fieldsplit.c (revision 47c6ae997ffd1b2afd66b6474dff5950ae8613d1)
1 #define PETSCKSP_DLL
2 
3 #include "private/pcimpl.h"     /*I "petscpc.h" I*/
4 
5 const char *const PCFieldSplitSchurPreTypes[] = {"SELF","DIAG","USER","PCFieldSplitSchurPreType","PC_FIELDSPLIT_SCHUR_PRE_",0};
6 const char *const PCFieldSplitSchurFactorizationTypes[] = {"DIAG","LOWER","UPPER","FULL","PCFieldSplitSchurFactorizationType","PC_FIELDSPLIT_SCHUR_FACTORIZATION_",0};
7 
8 typedef enum {
9   PC_FIELDSPLIT_SCHUR_FACTORIZATION_DIAG,
10   PC_FIELDSPLIT_SCHUR_FACTORIZATION_LOWER,
11   PC_FIELDSPLIT_SCHUR_FACTORIZATION_UPPER,
12   PC_FIELDSPLIT_SCHUR_FACTORIZATION_FULL
13 } PCFieldSplitSchurFactorizationType;
14 
15 typedef struct _PC_FieldSplitLink *PC_FieldSplitLink;
16 struct _PC_FieldSplitLink {
17   KSP               ksp;
18   Vec               x,y;
19   char              *splitname;
20   PetscInt          nfields;
21   PetscInt          *fields;
22   VecScatter        sctx;
23   IS                is;
24   PC_FieldSplitLink next,previous;
25 };
26 
27 typedef struct {
28   PCCompositeType   type;
29   PetscBool         defaultsplit; /* Flag for a system with a set of 'k' scalar fields with the same layout (and bs = k) */
30   PetscBool         splitdefined; /* Flag is set after the splits have been defined, to prevent more splits from being added */
31   PetscBool         realdiagonal; /* Flag to use the diagonal blocks of mat preconditioned by pmat, instead of just pmat */
32   PetscInt          bs;           /* Block size for IS and Mat structures */
33   PetscInt          nsplits;      /* Number of field divisions defined */
34   Vec               *x,*y,w1,w2;
35   Mat               *mat;         /* The diagonal block for each split */
36   Mat               *pmat;        /* The preconditioning diagonal block for each split */
37   Mat               *Afield;      /* The rows of the matrix associated with each split */
38   PetscBool         issetup;
39   /* Only used when Schur complement preconditioning is used */
40   Mat               B;            /* The (0,1) block */
41   Mat               C;            /* The (1,0) block */
42   Mat               schur;        /* The Schur complement S = D - C A^{-1} B */
43   Mat               schur_user;   /* User-provided preconditioning matrix for the Schur complement */
44   PCFieldSplitSchurPreType schurpre; /* Determines which preconditioning matrix is used for the Schur complement */
45   PCFieldSplitSchurFactorizationType schurfactorization;
46   KSP               kspschur;     /* The solver for S */
47   PC_FieldSplitLink head;
48 } PC_FieldSplit;
49 
50 /*
51     Notes: there is no particular reason that pmat, x, and y are stored as arrays in PC_FieldSplit instead of
52    inside PC_FieldSplitLink, just historical. If you want to be able to add new fields after already using the
53    PC you could change this.
54 */
55 
56 /* This helper is so that setting a user-provided preconditioning matrix is orthogonal to choosing to use it.  This way the
57 * application-provided FormJacobian can provide this matrix without interfering with the user's (command-line) choices. */
58 static Mat FieldSplitSchurPre(PC_FieldSplit *jac)
59 {
60   switch (jac->schurpre) {
61     case PC_FIELDSPLIT_SCHUR_PRE_SELF: return jac->schur;
62     case PC_FIELDSPLIT_SCHUR_PRE_DIAG: return jac->pmat[1];
63     case PC_FIELDSPLIT_SCHUR_PRE_USER: /* Use a user-provided matrix if it is given, otherwise diagonal block */
64     default:
65       return jac->schur_user ? jac->schur_user : jac->pmat[1];
66   }
67 }
68 
69 
70 #undef __FUNCT__
71 #define __FUNCT__ "PCView_FieldSplit"
72 static PetscErrorCode PCView_FieldSplit(PC pc,PetscViewer viewer)
73 {
74   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
75   PetscErrorCode    ierr;
76   PetscBool         iascii;
77   PetscInt          i,j;
78   PC_FieldSplitLink ilink = jac->head;
79 
80   PetscFunctionBegin;
81   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
82   if (iascii) {
83     ierr = PetscViewerASCIIPrintf(viewer,"  FieldSplit with %s composition: total splits = %D, blocksize = %D\n",PCCompositeTypes[jac->type],jac->nsplits,jac->bs);CHKERRQ(ierr);
84     ierr = PetscViewerASCIIPrintf(viewer,"  Solver info for each split is in the following KSP objects:\n");CHKERRQ(ierr);
85     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
86     for (i=0; i<jac->nsplits; i++) {
87       if (ilink->fields) {
88 	ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Fields ",i);CHKERRQ(ierr);
89 	ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
90 	for (j=0; j<ilink->nfields; j++) {
91 	  if (j > 0) {
92 	    ierr = PetscViewerASCIIPrintf(viewer,",");CHKERRQ(ierr);
93 	  }
94 	  ierr = PetscViewerASCIIPrintf(viewer," %D",ilink->fields[j]);CHKERRQ(ierr);
95 	}
96 	ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
97         ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
98       } else {
99 	ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Defined by IS\n",i);CHKERRQ(ierr);
100       }
101       ierr = KSPView(ilink->ksp,viewer);CHKERRQ(ierr);
102       ilink = ilink->next;
103     }
104     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
105   } else {
106     SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_SUP,"Viewer type %s not supported for PCFieldSplit",((PetscObject)viewer)->type_name);
107   }
108   PetscFunctionReturn(0);
109 }
110 
111 #undef __FUNCT__
112 #define __FUNCT__ "PCView_FieldSplit_Schur"
113 static PetscErrorCode PCView_FieldSplit_Schur(PC pc,PetscViewer viewer)
114 {
115   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
116   PetscErrorCode    ierr;
117   PetscBool         iascii;
118   PetscInt          i,j;
119   PC_FieldSplitLink ilink = jac->head;
120   KSP               ksp;
121 
122   PetscFunctionBegin;
123   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
124   if (iascii) {
125     ierr = PetscViewerASCIIPrintf(viewer,"  FieldSplit with Schur preconditioner, blocksize = %D, factorization %s\n",jac->bs,PCFieldSplitSchurFactorizationTypes[jac->schurfactorization]);CHKERRQ(ierr);
126     ierr = PetscViewerASCIIPrintf(viewer,"  Split info:\n");CHKERRQ(ierr);
127     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
128     for (i=0; i<jac->nsplits; i++) {
129       if (ilink->fields) {
130 	ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Fields ",i);CHKERRQ(ierr);
131 	ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
132 	for (j=0; j<ilink->nfields; j++) {
133 	  if (j > 0) {
134 	    ierr = PetscViewerASCIIPrintf(viewer,",");CHKERRQ(ierr);
135 	  }
136 	  ierr = PetscViewerASCIIPrintf(viewer," %D",ilink->fields[j]);CHKERRQ(ierr);
137 	}
138 	ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
139         ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
140       } else {
141 	ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Defined by IS\n",i);CHKERRQ(ierr);
142       }
143       ilink = ilink->next;
144     }
145     ierr = PetscViewerASCIIPrintf(viewer,"KSP solver for A block \n");CHKERRQ(ierr);
146     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
147     if (jac->schur) {
148       ierr = MatSchurComplementGetKSP(jac->schur,&ksp);CHKERRQ(ierr);
149       ierr = KSPView(ksp,viewer);CHKERRQ(ierr);
150     } else {
151       ierr = PetscViewerASCIIPrintf(viewer,"  not yet available\n");CHKERRQ(ierr);
152     }
153     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
154     ierr = PetscViewerASCIIPrintf(viewer,"KSP solver for S = D - C inv(A) B \n");CHKERRQ(ierr);
155     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
156     if (jac->kspschur) {
157       ierr = KSPView(jac->kspschur,viewer);CHKERRQ(ierr);
158     } else {
159       ierr = PetscViewerASCIIPrintf(viewer,"  not yet available\n");CHKERRQ(ierr);
160     }
161     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
162     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
163   } else {
164     SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_SUP,"Viewer type %s not supported for PCFieldSplit",((PetscObject)viewer)->type_name);
165   }
166   PetscFunctionReturn(0);
167 }
168 
169 #undef __FUNCT__
170 #define __FUNCT__ "PCFieldSplitSetRuntimeSplits_Private"
171 /* Precondition: jac->bs is set to a meaningful value */
172 static PetscErrorCode PCFieldSplitSetRuntimeSplits_Private(PC pc)
173 {
174   PetscErrorCode ierr;
175   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
176   PetscInt       i,nfields,*ifields;
177   PetscBool      flg;
178   char           optionname[128],splitname[8];
179 
180   PetscFunctionBegin;
181   ierr = PetscMalloc(jac->bs*sizeof(PetscInt),&ifields);CHKERRQ(ierr);
182   for (i=0,flg=PETSC_TRUE; ; i++) {
183     ierr = PetscSNPrintf(splitname,sizeof splitname,"%D",i);CHKERRQ(ierr);
184     ierr = PetscSNPrintf(optionname,sizeof optionname,"-pc_fieldsplit_%D_fields",i);CHKERRQ(ierr);
185     nfields = jac->bs;
186     ierr    = PetscOptionsGetIntArray(((PetscObject)pc)->prefix,optionname,ifields,&nfields,&flg);CHKERRQ(ierr);
187     if (!flg) break;
188     if (!nfields) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot list zero fields");
189     ierr = PCFieldSplitSetFields(pc,splitname,nfields,ifields);CHKERRQ(ierr);
190   }
191   if (i > 0) {
192     /* Makes command-line setting of splits take precedence over setting them in code.
193        Otherwise subsequent calls to PCFieldSplitSetIS() or PCFieldSplitSetFields() would
194        create new splits, which would probably not be what the user wanted. */
195     jac->splitdefined = PETSC_TRUE;
196   }
197   ierr = PetscFree(ifields);CHKERRQ(ierr);
198   PetscFunctionReturn(0);
199 }
200 
201 #undef __FUNCT__
202 #define __FUNCT__ "PCFieldSplitSetDefaults"
203 static PetscErrorCode PCFieldSplitSetDefaults(PC pc)
204 {
205   PC_FieldSplit     *jac  = (PC_FieldSplit*)pc->data;
206   PetscErrorCode    ierr;
207   PC_FieldSplitLink ilink = jac->head;
208   PetscBool         flg = PETSC_FALSE;
209   PetscInt          i;
210 
211   PetscFunctionBegin;
212   if (!ilink) {
213 
214     if (jac->bs <= 0) {
215       if (pc->pmat) {
216         ierr   = MatGetBlockSize(pc->pmat,&jac->bs);CHKERRQ(ierr);
217       } else {
218         jac->bs = 1;
219       }
220     }
221 
222     ierr = PetscOptionsGetTruth(((PetscObject)pc)->prefix,"-pc_fieldsplit_default",&flg,PETSC_NULL);CHKERRQ(ierr);
223     if (!flg) {
224       /* Allow user to set fields from command line,  if bs was known at the time of PCSetFromOptions_FieldSplit()
225          then it is set there. This is not ideal because we should only have options set in XXSetFromOptions(). */
226       ierr = PCFieldSplitSetRuntimeSplits_Private(pc);CHKERRQ(ierr);
227       if (jac->splitdefined) {ierr = PetscInfo(pc,"Splits defined using the options database\n");CHKERRQ(ierr);}
228     }
229     if (flg || !jac->splitdefined) {
230       ierr = PetscInfo(pc,"Using default splitting of fields\n");CHKERRQ(ierr);
231       for (i=0; i<jac->bs; i++) {
232         char splitname[8];
233         ierr = PetscSNPrintf(splitname,sizeof splitname,"%D",i);CHKERRQ(ierr);
234         ierr = PCFieldSplitSetFields(pc,splitname,1,&i);CHKERRQ(ierr);
235       }
236       jac->defaultsplit = PETSC_TRUE;
237     }
238   } else if (jac->nsplits == 1) {
239     if (ilink->is) {
240       IS       is2;
241       PetscInt nmin,nmax;
242 
243       ierr = MatGetOwnershipRange(pc->mat,&nmin,&nmax);CHKERRQ(ierr);
244       ierr = ISComplement(ilink->is,nmin,nmax,&is2);CHKERRQ(ierr);
245       ierr = PCFieldSplitSetIS(pc,"1",is2);CHKERRQ(ierr);
246       ierr = ISDestroy(is2);CHKERRQ(ierr);
247     } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Must provide at least two sets of fields to PCFieldSplit()");
248   }
249   if (jac->nsplits < 2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unhandled case, must have at least two fields");
250   PetscFunctionReturn(0);
251 }
252 
253 
254 #undef __FUNCT__
255 #define __FUNCT__ "PCSetUp_FieldSplit"
256 static PetscErrorCode PCSetUp_FieldSplit(PC pc)
257 {
258   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
259   PetscErrorCode    ierr;
260   PC_FieldSplitLink ilink;
261   PetscInt          i,nsplit,ccsize;
262   MatStructure      flag = pc->flag;
263   PetscBool         sorted;
264 
265   PetscFunctionBegin;
266   ierr   = PCFieldSplitSetDefaults(pc);CHKERRQ(ierr);
267   nsplit = jac->nsplits;
268   ilink  = jac->head;
269 
270   /* get the matrices for each split */
271   if (!jac->issetup) {
272     PetscInt rstart,rend,nslots,bs;
273 
274     jac->issetup = PETSC_TRUE;
275 
276     /* This is done here instead of in PCFieldSplitSetFields() because may not have matrix at that point */
277     bs     = jac->bs;
278     ierr   = MatGetOwnershipRange(pc->pmat,&rstart,&rend);CHKERRQ(ierr);
279     ierr   = MatGetLocalSize(pc->pmat,PETSC_NULL,&ccsize);CHKERRQ(ierr);
280     nslots = (rend - rstart)/bs;
281     for (i=0; i<nsplit; i++) {
282       if (jac->defaultsplit) {
283         ierr = ISCreateStride(((PetscObject)pc)->comm,nslots,rstart+i,nsplit,&ilink->is);CHKERRQ(ierr);
284       } else if (!ilink->is) {
285         if (ilink->nfields > 1) {
286           PetscInt   *ii,j,k,nfields = ilink->nfields,*fields = ilink->fields;
287           ierr = PetscMalloc(ilink->nfields*nslots*sizeof(PetscInt),&ii);CHKERRQ(ierr);
288           for (j=0; j<nslots; j++) {
289             for (k=0; k<nfields; k++) {
290               ii[nfields*j + k] = rstart + bs*j + fields[k];
291             }
292           }
293           ierr = ISCreateGeneral(((PetscObject)pc)->comm,nslots*nfields,ii,PETSC_OWN_POINTER,&ilink->is);CHKERRQ(ierr);
294         } else {
295           ierr = ISCreateStride(((PetscObject)pc)->comm,nslots,rstart+ilink->fields[0],bs,&ilink->is);CHKERRQ(ierr);
296         }
297       }
298       ierr = ISSorted(ilink->is,&sorted);CHKERRQ(ierr);
299       if (!sorted) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Fields must be sorted when creating split");
300       ilink = ilink->next;
301     }
302   }
303 
304   ilink  = jac->head;
305   if (!jac->pmat) {
306     ierr = PetscMalloc(nsplit*sizeof(Mat),&jac->pmat);CHKERRQ(ierr);
307     for (i=0; i<nsplit; i++) {
308       ierr = MatGetSubMatrix(pc->pmat,ilink->is,ilink->is,MAT_INITIAL_MATRIX,&jac->pmat[i]);CHKERRQ(ierr);
309       ilink = ilink->next;
310     }
311   } else {
312     for (i=0; i<nsplit; i++) {
313       ierr = MatGetSubMatrix(pc->pmat,ilink->is,ilink->is,MAT_REUSE_MATRIX,&jac->pmat[i]);CHKERRQ(ierr);
314       ilink = ilink->next;
315     }
316   }
317   if (jac->realdiagonal) {
318     ilink = jac->head;
319     if (!jac->mat) {
320       ierr = PetscMalloc(nsplit*sizeof(Mat),&jac->mat);CHKERRQ(ierr);
321       for (i=0; i<nsplit; i++) {
322         ierr = MatGetSubMatrix(pc->mat,ilink->is,ilink->is,MAT_INITIAL_MATRIX,&jac->mat[i]);CHKERRQ(ierr);
323         ilink = ilink->next;
324       }
325     } else {
326       for (i=0; i<nsplit; i++) {
327         ierr = MatGetSubMatrix(pc->mat,ilink->is,ilink->is,MAT_REUSE_MATRIX,&jac->mat[i]);CHKERRQ(ierr);
328         ilink = ilink->next;
329       }
330     }
331   } else {
332     jac->mat = jac->pmat;
333   }
334 
335   if (jac->type != PC_COMPOSITE_ADDITIVE  && jac->type != PC_COMPOSITE_SCHUR) {
336     /* extract the rows of the matrix associated with each field: used for efficient computation of residual inside algorithm */
337     ilink  = jac->head;
338     if (!jac->Afield) {
339       ierr = PetscMalloc(nsplit*sizeof(Mat),&jac->Afield);CHKERRQ(ierr);
340       for (i=0; i<nsplit; i++) {
341         ierr = MatGetSubMatrix(pc->mat,ilink->is,PETSC_NULL,MAT_INITIAL_MATRIX,&jac->Afield[i]);CHKERRQ(ierr);
342         ilink = ilink->next;
343       }
344     } else {
345       for (i=0; i<nsplit; i++) {
346         ierr = MatGetSubMatrix(pc->mat,ilink->is,PETSC_NULL,MAT_REUSE_MATRIX,&jac->Afield[i]);CHKERRQ(ierr);
347         ilink = ilink->next;
348       }
349     }
350   }
351 
352   if (jac->type == PC_COMPOSITE_SCHUR) {
353     IS       ccis;
354     PetscInt rstart,rend;
355     if (nsplit != 2) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ARG_INCOMP,"To use Schur complement preconditioner you must have exactly 2 fields");
356 
357     /* When extracting off-diagonal submatrices, we take complements from this range */
358     ierr  = MatGetOwnershipRangeColumn(pc->mat,&rstart,&rend);CHKERRQ(ierr);
359 
360     /* need to handle case when one is resetting up the preconditioner */
361     if (jac->schur) {
362       ilink = jac->head;
363       ierr  = ISComplement(ilink->is,rstart,rend,&ccis);CHKERRQ(ierr);
364       ierr  = MatGetSubMatrix(pc->mat,ilink->is,ccis,MAT_REUSE_MATRIX,&jac->B);CHKERRQ(ierr);
365       ierr  = ISDestroy(ccis);CHKERRQ(ierr);
366       ilink = ilink->next;
367       ierr  = ISComplement(ilink->is,rstart,rend,&ccis);CHKERRQ(ierr);
368       ierr  = MatGetSubMatrix(pc->mat,ilink->is,ccis,MAT_REUSE_MATRIX,&jac->C);CHKERRQ(ierr);
369       ierr  = ISDestroy(ccis);CHKERRQ(ierr);
370       ierr  = MatSchurComplementUpdate(jac->schur,jac->mat[0],jac->pmat[0],jac->B,jac->C,jac->pmat[1],pc->flag);CHKERRQ(ierr);
371       ierr  = KSPSetOperators(jac->kspschur,jac->schur,FieldSplitSchurPre(jac),pc->flag);CHKERRQ(ierr);
372 
373      } else {
374       KSP ksp;
375       char schurprefix[256];
376 
377       /* extract the B and C matrices */
378       ilink = jac->head;
379       ierr  = ISComplement(ilink->is,rstart,rend,&ccis);CHKERRQ(ierr);
380       ierr  = MatGetSubMatrix(pc->mat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->B);CHKERRQ(ierr);
381       ierr  = ISDestroy(ccis);CHKERRQ(ierr);
382       ilink = ilink->next;
383       ierr  = ISComplement(ilink->is,rstart,rend,&ccis);CHKERRQ(ierr);
384       ierr  = MatGetSubMatrix(pc->mat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->C);CHKERRQ(ierr);
385       ierr  = ISDestroy(ccis);CHKERRQ(ierr);
386       /* Better would be to use 'mat[0]' (diagonal block of the real matrix) preconditioned by pmat[0] */
387       ierr  = MatCreateSchurComplement(jac->mat[0],jac->pmat[0],jac->B,jac->C,jac->mat[1],&jac->schur);CHKERRQ(ierr);
388       ierr  = MatSchurComplementGetKSP(jac->schur,&ksp);CHKERRQ(ierr);
389       ierr  = PetscObjectIncrementTabLevel((PetscObject)ksp,(PetscObject)pc,2);CHKERRQ(ierr);
390       ierr  = MatSetFromOptions(jac->schur);CHKERRQ(ierr);
391 
392       ierr  = KSPCreate(((PetscObject)pc)->comm,&jac->kspschur);CHKERRQ(ierr);
393       ierr  = PetscLogObjectParent((PetscObject)pc,(PetscObject)jac->kspschur);CHKERRQ(ierr);
394       ierr  = PetscObjectIncrementTabLevel((PetscObject)jac->kspschur,(PetscObject)pc,1);CHKERRQ(ierr);
395       ierr  = KSPSetOperators(jac->kspschur,jac->schur,FieldSplitSchurPre(jac),DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
396       if (jac->schurpre == PC_FIELDSPLIT_SCHUR_PRE_SELF) {
397         PC pc;
398         ierr = KSPGetPC(jac->kspschur,&pc);CHKERRQ(ierr);
399         ierr = PCSetType(pc,PCNONE);CHKERRQ(ierr);
400         /* Note: This is bad if there exist preconditioners for MATSCHURCOMPLEMENT */
401       }
402       ierr = PetscSNPrintf(schurprefix,sizeof schurprefix,"%sfieldsplit_%s_",((PetscObject)pc)->prefix?((PetscObject)pc)->prefix:"",ilink->splitname);CHKERRQ(ierr);
403       ierr  = KSPSetOptionsPrefix(jac->kspschur,schurprefix);CHKERRQ(ierr);
404       /* really want setfromoptions called in PCSetFromOptions_FieldSplit(), but it is not ready yet */
405       ierr = KSPSetFromOptions(jac->kspschur);CHKERRQ(ierr);
406 
407       ierr = PetscMalloc2(2,Vec,&jac->x,2,Vec,&jac->y);CHKERRQ(ierr);
408       ierr = MatGetVecs(jac->pmat[0],&jac->x[0],&jac->y[0]);CHKERRQ(ierr);
409       ierr = MatGetVecs(jac->pmat[1],&jac->x[1],&jac->y[1]);CHKERRQ(ierr);
410       ilink = jac->head;
411       ilink->x = jac->x[0]; ilink->y = jac->y[0];
412       ilink = ilink->next;
413       ilink->x = jac->x[1]; ilink->y = jac->y[1];
414     }
415   } else {
416     /* set up the individual PCs */
417     i    = 0;
418     ilink = jac->head;
419     while (ilink) {
420       ierr = KSPSetOperators(ilink->ksp,jac->mat[i],jac->pmat[i],flag);CHKERRQ(ierr);
421       /* really want setfromoptions called in PCSetFromOptions_FieldSplit(), but it is not ready yet */
422       ierr = KSPSetFromOptions(ilink->ksp);CHKERRQ(ierr);
423       ierr = KSPSetUp(ilink->ksp);CHKERRQ(ierr);
424       i++;
425       ilink = ilink->next;
426     }
427 
428     /* create work vectors for each split */
429     if (!jac->x) {
430       ierr = PetscMalloc2(nsplit,Vec,&jac->x,nsplit,Vec,&jac->y);CHKERRQ(ierr);
431       ilink = jac->head;
432       for (i=0; i<nsplit; i++) {
433         Vec *vl,*vr;
434 
435         ierr      = KSPGetVecs(ilink->ksp,1,&vr,1,&vl);CHKERRQ(ierr);
436         ilink->x  = *vr;
437         ilink->y  = *vl;
438         ierr      = PetscFree(vr);CHKERRQ(ierr);
439         ierr      = PetscFree(vl);CHKERRQ(ierr);
440         jac->x[i] = ilink->x;
441         jac->y[i] = ilink->y;
442         ilink     = ilink->next;
443       }
444     }
445   }
446 
447 
448   if (!jac->head->sctx) {
449     Vec xtmp;
450 
451     /* compute scatter contexts needed by multiplicative versions and non-default splits */
452 
453     ilink = jac->head;
454     ierr = MatGetVecs(pc->pmat,&xtmp,PETSC_NULL);CHKERRQ(ierr);
455     for (i=0; i<nsplit; i++) {
456       ierr = VecScatterCreate(xtmp,ilink->is,jac->x[i],PETSC_NULL,&ilink->sctx);CHKERRQ(ierr);
457       ilink = ilink->next;
458     }
459     ierr = VecDestroy(xtmp);CHKERRQ(ierr);
460   }
461   PetscFunctionReturn(0);
462 }
463 
464 #define FieldSplitSplitSolveAdd(ilink,xx,yy) \
465     (VecScatterBegin(ilink->sctx,xx,ilink->x,INSERT_VALUES,SCATTER_FORWARD) || \
466      VecScatterEnd(ilink->sctx,xx,ilink->x,INSERT_VALUES,SCATTER_FORWARD) || \
467      KSPSolve(ilink->ksp,ilink->x,ilink->y) || \
468      VecScatterBegin(ilink->sctx,ilink->y,yy,ADD_VALUES,SCATTER_REVERSE) || \
469      VecScatterEnd(ilink->sctx,ilink->y,yy,ADD_VALUES,SCATTER_REVERSE))
470 
471 #undef __FUNCT__
472 #define __FUNCT__ "PCApply_FieldSplit_Schur"
473 static PetscErrorCode PCApply_FieldSplit_Schur(PC pc,Vec x,Vec y)
474 {
475   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
476   PetscErrorCode    ierr;
477   KSP               ksp;
478   PC_FieldSplitLink ilinkA = jac->head, ilinkD = ilinkA->next;
479 
480   PetscFunctionBegin;
481   ierr = MatSchurComplementGetKSP(jac->schur,&ksp);CHKERRQ(ierr);
482 
483   switch (jac->schurfactorization) {
484     case PC_FIELDSPLIT_SCHUR_FACTORIZATION_DIAG:
485       /* [A 0; 0 -S], positive definite, suitable for MINRES */
486       ierr = VecScatterBegin(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
487       ierr = VecScatterBegin(ilinkD->sctx,x,ilinkD->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
488       ierr = VecScatterEnd(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
489       ierr = KSPSolve(ksp,ilinkA->x,ilinkA->y);CHKERRQ(ierr);
490       ierr = VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
491       ierr = VecScatterEnd(ilinkD->sctx,x,ilinkD->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
492       ierr = KSPSolve(jac->kspschur,ilinkD->x,ilinkD->y);CHKERRQ(ierr);
493       ierr = VecScale(ilinkD->y,-1.);CHKERRQ(ierr);
494       ierr = VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
495       ierr = VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
496       ierr = VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
497       break;
498     case PC_FIELDSPLIT_SCHUR_FACTORIZATION_LOWER:
499       /* [A 0; C S], suitable for left preconditioning */
500       ierr = VecScatterBegin(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
501       ierr = VecScatterEnd(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
502       ierr = KSPSolve(ksp,ilinkA->x,ilinkA->y);CHKERRQ(ierr);
503       ierr = MatMult(jac->C,ilinkA->y,ilinkD->x);CHKERRQ(ierr);
504       ierr = VecScale(ilinkD->x,-1.);CHKERRQ(ierr);
505       ierr = VecScatterBegin(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
506       ierr = VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
507       ierr = VecScatterEnd(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
508       ierr = KSPSolve(jac->kspschur,ilinkD->x,ilinkD->y);CHKERRQ(ierr);
509       ierr = VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
510       ierr = VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
511       ierr = VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
512       break;
513     case PC_FIELDSPLIT_SCHUR_FACTORIZATION_UPPER:
514       /* [A B; 0 S], suitable for right preconditioning */
515       ierr = VecScatterBegin(ilinkD->sctx,x,ilinkD->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
516       ierr = VecScatterEnd(ilinkD->sctx,x,ilinkD->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
517       ierr = KSPSolve(jac->kspschur,ilinkD->x,ilinkD->y);CHKERRQ(ierr);
518       ierr = MatMult(jac->B,ilinkD->y,ilinkA->x);CHKERRQ(ierr);
519       ierr = VecScale(ilinkA->x,-1.);CHKERRQ(ierr);
520       ierr = VecScatterBegin(ilinkA->sctx,x,ilinkA->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
521       ierr = VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
522       ierr = VecScatterEnd(ilinkA->sctx,x,ilinkA->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
523       ierr = KSPSolve(ksp,ilinkA->x,ilinkA->y);CHKERRQ(ierr);
524       ierr = VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
525       ierr = VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
526       ierr = VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
527       break;
528     case PC_FIELDSPLIT_SCHUR_FACTORIZATION_FULL:
529       /* [1 0; CA^{-1} 1] [A 0; 0 S] [1 A^{-1}B; 0 1], an exact solve if applied exactly, needs one extra solve with A */
530       ierr = VecScatterBegin(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
531       ierr = VecScatterEnd(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
532       ierr = KSPSolve(ksp,ilinkA->x,ilinkA->y);CHKERRQ(ierr);
533       ierr = MatMult(jac->C,ilinkA->y,ilinkD->x);CHKERRQ(ierr);
534       ierr = VecScale(ilinkD->x,-1.0);CHKERRQ(ierr);
535       ierr = VecScatterBegin(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
536       ierr = VecScatterEnd(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
537 
538       ierr = KSPSolve(jac->kspschur,ilinkD->x,ilinkD->y);CHKERRQ(ierr);
539       ierr = VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
540       ierr = VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
541 
542       ierr = MatMult(jac->B,ilinkD->y,ilinkA->y);CHKERRQ(ierr);
543       ierr = VecAXPY(ilinkA->x,-1.0,ilinkA->y);CHKERRQ(ierr);
544       ierr = KSPSolve(ksp,ilinkA->x,ilinkA->y);CHKERRQ(ierr);
545       ierr = VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
546       ierr = VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
547   }
548   PetscFunctionReturn(0);
549 }
550 
551 #undef __FUNCT__
552 #define __FUNCT__ "PCApply_FieldSplit"
553 static PetscErrorCode PCApply_FieldSplit(PC pc,Vec x,Vec y)
554 {
555   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
556   PetscErrorCode    ierr;
557   PC_FieldSplitLink ilink = jac->head;
558   PetscInt          cnt;
559 
560   PetscFunctionBegin;
561   CHKMEMQ;
562   ierr = VecSetBlockSize(x,jac->bs);CHKERRQ(ierr);
563   ierr = VecSetBlockSize(y,jac->bs);CHKERRQ(ierr);
564 
565   if (jac->type == PC_COMPOSITE_ADDITIVE) {
566     if (jac->defaultsplit) {
567       ierr = VecStrideGatherAll(x,jac->x,INSERT_VALUES);CHKERRQ(ierr);
568       while (ilink) {
569         ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
570         ilink = ilink->next;
571       }
572       ierr = VecStrideScatterAll(jac->y,y,INSERT_VALUES);CHKERRQ(ierr);
573     } else {
574       ierr = VecSet(y,0.0);CHKERRQ(ierr);
575       while (ilink) {
576         ierr = FieldSplitSplitSolveAdd(ilink,x,y);CHKERRQ(ierr);
577         ilink = ilink->next;
578       }
579     }
580   } else if (jac->type == PC_COMPOSITE_MULTIPLICATIVE || jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
581     if (!jac->w1) {
582       ierr = VecDuplicate(x,&jac->w1);CHKERRQ(ierr);
583       ierr = VecDuplicate(x,&jac->w2);CHKERRQ(ierr);
584     }
585     ierr = VecSet(y,0.0);CHKERRQ(ierr);
586     ierr = FieldSplitSplitSolveAdd(ilink,x,y);CHKERRQ(ierr);
587     cnt = 1;
588     while (ilink->next) {
589       ilink = ilink->next;
590       /* compute the residual only over the part of the vector needed */
591       ierr = MatMult(jac->Afield[cnt++],y,ilink->x);CHKERRQ(ierr);
592       ierr = VecScale(ilink->x,-1.0);CHKERRQ(ierr);
593       ierr = VecScatterBegin(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
594       ierr = VecScatterEnd(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
595       ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
596       ierr = VecScatterBegin(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
597       ierr = VecScatterEnd(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
598     }
599     if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
600       cnt -= 2;
601       while (ilink->previous) {
602         ilink = ilink->previous;
603         /* compute the residual only over the part of the vector needed */
604         ierr = MatMult(jac->Afield[cnt--],y,ilink->x);CHKERRQ(ierr);
605         ierr = VecScale(ilink->x,-1.0);CHKERRQ(ierr);
606         ierr = VecScatterBegin(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
607         ierr = VecScatterEnd(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
608         ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
609         ierr = VecScatterBegin(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
610         ierr = VecScatterEnd(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
611       }
612     }
613   } else SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_SUP,"Unsupported or unknown composition",(int) jac->type);
614   CHKMEMQ;
615   PetscFunctionReturn(0);
616 }
617 
618 #define FieldSplitSplitSolveAddTranspose(ilink,xx,yy) \
619     (VecScatterBegin(ilink->sctx,xx,ilink->y,INSERT_VALUES,SCATTER_FORWARD) || \
620      VecScatterEnd(ilink->sctx,xx,ilink->y,INSERT_VALUES,SCATTER_FORWARD) || \
621      KSPSolveTranspose(ilink->ksp,ilink->y,ilink->x) || \
622      VecScatterBegin(ilink->sctx,ilink->x,yy,ADD_VALUES,SCATTER_REVERSE) || \
623      VecScatterEnd(ilink->sctx,ilink->x,yy,ADD_VALUES,SCATTER_REVERSE))
624 
625 #undef __FUNCT__
626 #define __FUNCT__ "PCApply_FieldSplit"
627 static PetscErrorCode PCApplyTranspose_FieldSplit(PC pc,Vec x,Vec y)
628 {
629   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
630   PetscErrorCode    ierr;
631   PC_FieldSplitLink ilink = jac->head;
632 
633   PetscFunctionBegin;
634   CHKMEMQ;
635   ierr = VecSetBlockSize(x,jac->bs);CHKERRQ(ierr);
636   ierr = VecSetBlockSize(y,jac->bs);CHKERRQ(ierr);
637 
638   if (jac->type == PC_COMPOSITE_ADDITIVE) {
639     if (jac->defaultsplit) {
640       ierr = VecStrideGatherAll(x,jac->x,INSERT_VALUES);CHKERRQ(ierr);
641       while (ilink) {
642 	ierr = KSPSolveTranspose(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
643 	ilink = ilink->next;
644       }
645       ierr = VecStrideScatterAll(jac->y,y,INSERT_VALUES);CHKERRQ(ierr);
646     } else {
647       ierr = VecSet(y,0.0);CHKERRQ(ierr);
648       while (ilink) {
649         ierr = FieldSplitSplitSolveAddTranspose(ilink,x,y);CHKERRQ(ierr);
650 	ilink = ilink->next;
651       }
652     }
653   } else {
654     if (!jac->w1) {
655       ierr = VecDuplicate(x,&jac->w1);CHKERRQ(ierr);
656       ierr = VecDuplicate(x,&jac->w2);CHKERRQ(ierr);
657     }
658     ierr = VecSet(y,0.0);CHKERRQ(ierr);
659     if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
660       ierr = FieldSplitSplitSolveAddTranspose(ilink,x,y);CHKERRQ(ierr);
661       while (ilink->next) {
662         ilink = ilink->next;
663         ierr  = MatMultTranspose(pc->mat,y,jac->w1);CHKERRQ(ierr);
664         ierr  = VecWAXPY(jac->w2,-1.0,jac->w1,x);CHKERRQ(ierr);
665         ierr  = FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);CHKERRQ(ierr);
666       }
667       while (ilink->previous) {
668         ilink = ilink->previous;
669         ierr  = MatMultTranspose(pc->mat,y,jac->w1);CHKERRQ(ierr);
670         ierr  = VecWAXPY(jac->w2,-1.0,jac->w1,x);CHKERRQ(ierr);
671         ierr  = FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);CHKERRQ(ierr);
672       }
673     } else {
674       while (ilink->next) {   /* get to last entry in linked list */
675 	ilink = ilink->next;
676       }
677       ierr = FieldSplitSplitSolveAddTranspose(ilink,x,y);CHKERRQ(ierr);
678       while (ilink->previous) {
679 	ilink = ilink->previous;
680 	ierr  = MatMultTranspose(pc->mat,y,jac->w1);CHKERRQ(ierr);
681 	ierr  = VecWAXPY(jac->w2,-1.0,jac->w1,x);CHKERRQ(ierr);
682 	ierr  = FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);CHKERRQ(ierr);
683       }
684     }
685   }
686   CHKMEMQ;
687   PetscFunctionReturn(0);
688 }
689 
690 #undef __FUNCT__
691 #define __FUNCT__ "PCDestroy_FieldSplit"
692 static PetscErrorCode PCDestroy_FieldSplit(PC pc)
693 {
694   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
695   PetscErrorCode    ierr;
696   PC_FieldSplitLink ilink = jac->head,next;
697 
698   PetscFunctionBegin;
699   while (ilink) {
700     ierr = KSPDestroy(ilink->ksp);CHKERRQ(ierr);
701     if (ilink->x) {ierr = VecDestroy(ilink->x);CHKERRQ(ierr);}
702     if (ilink->y) {ierr = VecDestroy(ilink->y);CHKERRQ(ierr);}
703     if (ilink->sctx) {ierr = VecScatterDestroy(ilink->sctx);CHKERRQ(ierr);}
704     if (ilink->is) {ierr = ISDestroy(ilink->is);CHKERRQ(ierr);}
705     next = ilink->next;
706     ierr = PetscFree(ilink->splitname);CHKERRQ(ierr);
707     ierr = PetscFree(ilink->fields);CHKERRQ(ierr);
708     ierr = PetscFree(ilink);CHKERRQ(ierr);
709     ilink = next;
710   }
711   ierr = PetscFree2(jac->x,jac->y);CHKERRQ(ierr);
712   if (jac->mat && jac->mat != jac->pmat) {ierr = MatDestroyMatrices(jac->nsplits,&jac->mat);CHKERRQ(ierr);}
713   if (jac->pmat) {ierr = MatDestroyMatrices(jac->nsplits,&jac->pmat);CHKERRQ(ierr);}
714   if (jac->Afield) {ierr = MatDestroyMatrices(jac->nsplits,&jac->Afield);CHKERRQ(ierr);}
715   if (jac->w1) {ierr = VecDestroy(jac->w1);CHKERRQ(ierr);}
716   if (jac->w2) {ierr = VecDestroy(jac->w2);CHKERRQ(ierr);}
717   if (jac->schur) {ierr = MatDestroy(jac->schur);CHKERRQ(ierr);}
718   if (jac->schur_user) {ierr = MatDestroy(jac->schur_user);CHKERRQ(ierr);}
719   if (jac->kspschur) {ierr = KSPDestroy(jac->kspschur);CHKERRQ(ierr);}
720   if (jac->B) {ierr = MatDestroy(jac->B);CHKERRQ(ierr);}
721   if (jac->C) {ierr = MatDestroy(jac->C);CHKERRQ(ierr);}
722   ierr = PetscFree(jac);CHKERRQ(ierr);
723   PetscFunctionReturn(0);
724 }
725 
726 #undef __FUNCT__
727 #define __FUNCT__ "PCSetFromOptions_FieldSplit"
728 static PetscErrorCode PCSetFromOptions_FieldSplit(PC pc)
729 {
730   PetscErrorCode  ierr;
731   PetscInt        bs;
732   PetscBool       flg;
733   PC_FieldSplit   *jac = (PC_FieldSplit*)pc->data;
734   PCCompositeType ctype;
735 
736   PetscFunctionBegin;
737   ierr = PetscOptionsHead("FieldSplit options");CHKERRQ(ierr);
738   ierr = PetscOptionsTruth("-pc_fieldsplit_real_diagonal","Use diagonal blocks of the operator","PCFieldSplitSetRealDiagonal",jac->realdiagonal,&jac->realdiagonal,PETSC_NULL);CHKERRQ(ierr);
739   ierr = PetscOptionsInt("-pc_fieldsplit_block_size","Blocksize that defines number of fields","PCFieldSplitSetBlockSize",jac->bs,&bs,&flg);CHKERRQ(ierr);
740   if (flg) {
741     ierr = PCFieldSplitSetBlockSize(pc,bs);CHKERRQ(ierr);
742   }
743 
744   ierr = PetscOptionsEnum("-pc_fieldsplit_type","Type of composition","PCFieldSplitSetType",PCCompositeTypes,(PetscEnum)jac->type,(PetscEnum*)&ctype,&flg);CHKERRQ(ierr);
745   if (flg) {
746     ierr = PCFieldSplitSetType(pc,ctype);CHKERRQ(ierr);
747   }
748 
749   /* Only setup fields once */
750   if ((jac->bs > 0) && (jac->nsplits == 0)) {
751     /* only allow user to set fields from command line if bs is already known.
752        otherwise user can set them in PCFieldSplitSetDefaults() */
753     ierr = PCFieldSplitSetRuntimeSplits_Private(pc);CHKERRQ(ierr);
754     if (jac->splitdefined) {ierr = PetscInfo(pc,"Splits defined using the options database\n");CHKERRQ(ierr);}
755   }
756   if (jac->type == PC_COMPOSITE_SCHUR) {
757     ierr = PetscOptionsEnum("-pc_fieldsplit_schur_factorization_type","Factorization to use","None",PCFieldSplitSchurFactorizationTypes,(PetscEnum)jac->schurfactorization,(PetscEnum*)&jac->schurfactorization,PETSC_NULL);CHKERRQ(ierr);
758     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);
759   }
760   ierr = PetscOptionsTail();CHKERRQ(ierr);
761   PetscFunctionReturn(0);
762 }
763 
764 /*------------------------------------------------------------------------------------*/
765 
766 EXTERN_C_BEGIN
767 #undef __FUNCT__
768 #define __FUNCT__ "PCFieldSplitSetFields_FieldSplit"
769 PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetFields_FieldSplit(PC pc,const char splitname[],PetscInt n,const PetscInt *fields)
770 {
771   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
772   PetscErrorCode    ierr;
773   PC_FieldSplitLink ilink,next = jac->head;
774   char              prefix[128];
775   PetscInt          i;
776 
777   PetscFunctionBegin;
778   if (jac->splitdefined) {
779     ierr = PetscInfo1(pc,"Ignoring new split \"%s\" because the splits have already been defined\n",splitname);CHKERRQ(ierr);
780     PetscFunctionReturn(0);
781   }
782   for (i=0; i<n; i++) {
783     if (fields[i] >= jac->bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Field %D requested but only %D exist",fields[i],jac->bs);
784     if (fields[i] < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative field %D requested",fields[i]);
785   }
786   ierr = PetscNew(struct _PC_FieldSplitLink,&ilink);CHKERRQ(ierr);
787   ierr = PetscStrallocpy(splitname,&ilink->splitname);CHKERRQ(ierr);
788   ierr = PetscMalloc(n*sizeof(PetscInt),&ilink->fields);CHKERRQ(ierr);
789   ierr = PetscMemcpy(ilink->fields,fields,n*sizeof(PetscInt));CHKERRQ(ierr);
790   ilink->nfields = n;
791   ilink->next    = PETSC_NULL;
792   ierr           = KSPCreate(((PetscObject)pc)->comm,&ilink->ksp);CHKERRQ(ierr);
793   ierr           = PetscObjectIncrementTabLevel((PetscObject)ilink->ksp,(PetscObject)pc,1);CHKERRQ(ierr);
794   ierr           = KSPSetType(ilink->ksp,KSPPREONLY);CHKERRQ(ierr);
795   ierr           = PetscLogObjectParent((PetscObject)pc,(PetscObject)ilink->ksp);CHKERRQ(ierr);
796 
797   ierr = PetscSNPrintf(prefix,sizeof prefix,"%sfieldsplit_%s_",((PetscObject)pc)->prefix?((PetscObject)pc)->prefix:"",splitname);CHKERRQ(ierr);
798   ierr = KSPSetOptionsPrefix(ilink->ksp,prefix);CHKERRQ(ierr);
799 
800   if (!next) {
801     jac->head       = ilink;
802     ilink->previous = PETSC_NULL;
803   } else {
804     while (next->next) {
805       next = next->next;
806     }
807     next->next      = ilink;
808     ilink->previous = next;
809   }
810   jac->nsplits++;
811   PetscFunctionReturn(0);
812 }
813 EXTERN_C_END
814 
815 EXTERN_C_BEGIN
816 #undef __FUNCT__
817 #define __FUNCT__ "PCFieldSplitGetSubKSP_FieldSplit_Schur"
818 PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitGetSubKSP_FieldSplit_Schur(PC pc,PetscInt *n,KSP **subksp)
819 {
820   PC_FieldSplit *jac = (PC_FieldSplit*)pc->data;
821   PetscErrorCode ierr;
822 
823   PetscFunctionBegin;
824   ierr = PetscMalloc(jac->nsplits*sizeof(KSP),subksp);CHKERRQ(ierr);
825   ierr = MatSchurComplementGetKSP(jac->schur,*subksp);CHKERRQ(ierr);
826   (*subksp)[1] = jac->kspschur;
827   *n = jac->nsplits;
828   PetscFunctionReturn(0);
829 }
830 EXTERN_C_END
831 
832 EXTERN_C_BEGIN
833 #undef __FUNCT__
834 #define __FUNCT__ "PCFieldSplitGetSubKSP_FieldSplit"
835 PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitGetSubKSP_FieldSplit(PC pc,PetscInt *n,KSP **subksp)
836 {
837   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
838   PetscErrorCode    ierr;
839   PetscInt          cnt = 0;
840   PC_FieldSplitLink ilink = jac->head;
841 
842   PetscFunctionBegin;
843   ierr = PetscMalloc(jac->nsplits*sizeof(KSP*),subksp);CHKERRQ(ierr);
844   while (ilink) {
845     (*subksp)[cnt++] = ilink->ksp;
846     ilink = ilink->next;
847   }
848   if (cnt != jac->nsplits) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Corrupt PCFIELDSPLIT object: number splits in linked list %D in object %D",cnt,jac->nsplits);
849   *n = jac->nsplits;
850   PetscFunctionReturn(0);
851 }
852 EXTERN_C_END
853 
854 EXTERN_C_BEGIN
855 #undef __FUNCT__
856 #define __FUNCT__ "PCFieldSplitSetIS_FieldSplit"
857 PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetIS_FieldSplit(PC pc,const char splitname[],IS is)
858 {
859   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
860   PetscErrorCode    ierr;
861   PC_FieldSplitLink ilink, next = jac->head;
862   char              prefix[128];
863 
864   PetscFunctionBegin;
865   if (jac->splitdefined) {
866     ierr = PetscInfo1(pc,"Ignoring new split \"%s\" because the splits have already been defined\n",splitname);CHKERRQ(ierr);
867     PetscFunctionReturn(0);
868   }
869   ierr = PetscNew(struct _PC_FieldSplitLink,&ilink);CHKERRQ(ierr);
870   ierr = PetscStrallocpy(splitname,&ilink->splitname);CHKERRQ(ierr);
871   ilink->is      = is;
872   ierr           = PetscObjectReference((PetscObject)is);CHKERRQ(ierr);
873   ilink->next    = PETSC_NULL;
874   ierr           = KSPCreate(((PetscObject)pc)->comm,&ilink->ksp);CHKERRQ(ierr);
875   ierr           = PetscObjectIncrementTabLevel((PetscObject)ilink->ksp,(PetscObject)pc,1);CHKERRQ(ierr);
876   ierr           = KSPSetType(ilink->ksp,KSPPREONLY);CHKERRQ(ierr);
877   ierr           = PetscLogObjectParent((PetscObject)pc,(PetscObject)ilink->ksp);CHKERRQ(ierr);
878 
879   ierr = PetscSNPrintf(prefix,sizeof prefix,"%sfieldsplit_%s_",((PetscObject)pc)->prefix?((PetscObject)pc)->prefix:"",splitname);CHKERRQ(ierr);
880   ierr = KSPSetOptionsPrefix(ilink->ksp,prefix);CHKERRQ(ierr);
881 
882   if (!next) {
883     jac->head       = ilink;
884     ilink->previous = PETSC_NULL;
885   } else {
886     while (next->next) {
887       next = next->next;
888     }
889     next->next      = ilink;
890     ilink->previous = next;
891   }
892   jac->nsplits++;
893 
894   PetscFunctionReturn(0);
895 }
896 EXTERN_C_END
897 
898 #undef __FUNCT__
899 #define __FUNCT__ "PCFieldSplitSetFields"
900 /*@
901     PCFieldSplitSetFields - Sets the fields for one particular split in the field split preconditioner
902 
903     Logically Collective on PC
904 
905     Input Parameters:
906 +   pc  - the preconditioner context
907 .   splitname - name of this split
908 .   n - the number of fields in this split
909 -   fields - the fields in this split
910 
911     Level: intermediate
912 
913     Notes: Use PCFieldSplitSetIS() to set a completely general set of indices as a field.
914 
915      The PCFieldSplitSetFields() is for defining fields as a strided blocks. For example, if the block
916      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
917      0xx3xx6xx9xx12 ... x1xx4xx7xx ... xx2xx5xx8xx.. 01x34x67x... 0x1x3x5x7.. x12x45x78x....
918      where the numbered entries indicate what is in the field.
919 
920      This function is called once per split (it creates a new split each time).  Solve options
921      for this split will be available under the prefix -fieldsplit_SPLITNAME_.
922 
923 .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetBlockSize(), PCFieldSplitSetIS()
924 
925 @*/
926 PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetFields(PC pc,const char splitname[],PetscInt n,const PetscInt *fields)
927 {
928   PetscErrorCode ierr;
929 
930   PetscFunctionBegin;
931   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
932   PetscValidCharPointer(splitname,2);
933   if (n < 1) SETERRQ2(((PetscObject)pc)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Provided number of fields %D in split \"%s\" not positive",n,splitname);
934   PetscValidIntPointer(fields,3);
935   ierr = PetscTryMethod(pc,"PCFieldSplitSetFields_C",(PC,const char[],PetscInt,const PetscInt *),(pc,splitname,n,fields));CHKERRQ(ierr);
936   PetscFunctionReturn(0);
937 }
938 
939 #undef __FUNCT__
940 #define __FUNCT__ "PCFieldSplitSetIS"
941 /*@
942     PCFieldSplitSetIS - Sets the exact elements for field
943 
944     Logically Collective on PC
945 
946     Input Parameters:
947 +   pc  - the preconditioner context
948 .   splitname - name of this split
949 -   is - the index set that defines the vector elements in this field
950 
951 
952     Notes:
953     Use PCFieldSplitSetFields(), for fields defined by strided types.
954 
955     This function is called once per split (it creates a new split each time).  Solve options
956     for this split will be available under the prefix -fieldsplit_SPLITNAME_.
957 
958     Level: intermediate
959 
960 .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetBlockSize()
961 
962 @*/
963 PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetIS(PC pc,const char splitname[],IS is)
964 {
965   PetscErrorCode ierr;
966 
967   PetscFunctionBegin;
968   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
969   PetscValidCharPointer(splitname,2);
970   PetscValidHeaderSpecific(is,IS_CLASSID,3);
971   ierr = PetscTryMethod(pc,"PCFieldSplitSetIS_C",(PC,const char[],IS),(pc,splitname,is));CHKERRQ(ierr);
972   PetscFunctionReturn(0);
973 }
974 
975 #undef __FUNCT__
976 #define __FUNCT__ "PCFieldSplitSetBlockSize"
977 /*@
978     PCFieldSplitSetBlockSize - Sets the block size for defining where fields start in the
979       fieldsplit preconditioner. If not set the matrix block size is used.
980 
981     Logically Collective on PC
982 
983     Input Parameters:
984 +   pc  - the preconditioner context
985 -   bs - the block size
986 
987     Level: intermediate
988 
989 .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetFields()
990 
991 @*/
992 PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetBlockSize(PC pc,PetscInt bs)
993 {
994   PetscErrorCode ierr;
995 
996   PetscFunctionBegin;
997   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
998   PetscValidLogicalCollectiveInt(pc,bs,2);
999   ierr = PetscTryMethod(pc,"PCFieldSplitSetBlockSize_C",(PC,PetscInt),(pc,bs));CHKERRQ(ierr);
1000   PetscFunctionReturn(0);
1001 }
1002 
1003 #undef __FUNCT__
1004 #define __FUNCT__ "PCFieldSplitGetSubKSP"
1005 /*@C
1006    PCFieldSplitGetSubKSP - Gets the KSP contexts for all splits
1007 
1008    Collective on KSP
1009 
1010    Input Parameter:
1011 .  pc - the preconditioner context
1012 
1013    Output Parameters:
1014 +  n - the number of split
1015 -  pc - the array of KSP contexts
1016 
1017    Note:
1018    After PCFieldSplitGetSubKSP() the array of KSPs IS to be freed by the user
1019    (not the KSP just the array that contains them).
1020 
1021    You must call KSPSetUp() before calling PCFieldSplitGetSubKSP().
1022 
1023    Level: advanced
1024 
1025 .seealso: PCFIELDSPLIT
1026 @*/
1027 PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitGetSubKSP(PC pc,PetscInt *n,KSP *subksp[])
1028 {
1029   PetscErrorCode ierr;
1030 
1031   PetscFunctionBegin;
1032   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1033   PetscValidIntPointer(n,2);
1034   ierr = PetscUseMethod(pc,"PCFieldSplitGetSubKSP_C",(PC,PetscInt*,KSP **),(pc,n,subksp));CHKERRQ(ierr);
1035   PetscFunctionReturn(0);
1036 }
1037 
1038 #undef __FUNCT__
1039 #define __FUNCT__ "PCFieldSplitSchurPrecondition"
1040 /*@
1041     PCFieldSplitSchurPrecondition -  Indicates if the Schur complement is preconditioned by a preconditioner constructed by the
1042       D matrix. Otherwise no preconditioner is used.
1043 
1044     Collective on PC
1045 
1046     Input Parameters:
1047 +   pc  - the preconditioner context
1048 .   ptype - which matrix to use for preconditioning the Schur complement
1049 -   userpre - matrix to use for preconditioning, or PETSC_NULL
1050 
1051     Notes:
1052     The default is to use the block on the diagonal of the preconditioning matrix.  This is D, in the (1,1) position.
1053     There are currently no preconditioners that work directly with the Schur complement so setting
1054     PC_FIELDSPLIT_SCHUR_PRE_SELF is observationally equivalent to -fieldsplit_1_pc_type none.
1055 
1056     Options Database:
1057 .     -pc_fieldsplit_schur_precondition <self,user,diag> default is diag
1058 
1059     Level: intermediate
1060 
1061 .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetFields(), PCFieldSplitSchurPreType
1062 
1063 @*/
1064 PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSchurPrecondition(PC pc,PCFieldSplitSchurPreType ptype,Mat pre)
1065 {
1066   PetscErrorCode ierr;
1067 
1068   PetscFunctionBegin;
1069   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1070   ierr = PetscTryMethod(pc,"PCFieldSplitSchurPrecondition_C",(PC,PCFieldSplitSchurPreType,Mat),(pc,ptype,pre));CHKERRQ(ierr);
1071   PetscFunctionReturn(0);
1072 }
1073 
1074 EXTERN_C_BEGIN
1075 #undef __FUNCT__
1076 #define __FUNCT__ "PCFieldSplitSchurPrecondition_FieldSplit"
1077 PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSchurPrecondition_FieldSplit(PC pc,PCFieldSplitSchurPreType ptype,Mat pre)
1078 {
1079   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
1080   PetscErrorCode  ierr;
1081 
1082   PetscFunctionBegin;
1083   jac->schurpre = ptype;
1084   if (pre) {
1085     if (jac->schur_user) {ierr = MatDestroy(jac->schur_user);CHKERRQ(ierr);}
1086     jac->schur_user = pre;
1087     ierr = PetscObjectReference((PetscObject)jac->schur_user);CHKERRQ(ierr);
1088   }
1089   PetscFunctionReturn(0);
1090 }
1091 EXTERN_C_END
1092 
1093 #undef __FUNCT__
1094 #define __FUNCT__ "PCFieldSplitGetSchurBlocks"
1095 /*@C
1096    PCFieldSplitGetSchurBlocks - Gets the all matrix blocks for the Schur complement
1097 
1098    Collective on KSP
1099 
1100    Input Parameter:
1101 .  pc - the preconditioner context
1102 
1103    Output Parameters:
1104 +  A - the (0,0) block
1105 .  B - the (0,1) block
1106 .  C - the (1,0) block
1107 -  D - the (1,1) block
1108 
1109    Level: advanced
1110 
1111 .seealso: PCFIELDSPLIT
1112 @*/
1113 PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitGetSchurBlocks(PC pc,Mat *A,Mat *B,Mat *C, Mat *D)
1114 {
1115   PC_FieldSplit *jac = (PC_FieldSplit *) pc->data;
1116 
1117   PetscFunctionBegin;
1118   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1119   if (jac->type != PC_COMPOSITE_SCHUR) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ARG_WRONG, "FieldSplit is not using a Schur complement approach.");
1120   if (A) *A = jac->pmat[0];
1121   if (B) *B = jac->B;
1122   if (C) *C = jac->C;
1123   if (D) *D = jac->pmat[1];
1124   PetscFunctionReturn(0);
1125 }
1126 
1127 EXTERN_C_BEGIN
1128 #undef __FUNCT__
1129 #define __FUNCT__ "PCFieldSplitSetType_FieldSplit"
1130 PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetType_FieldSplit(PC pc,PCCompositeType type)
1131 {
1132   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
1133   PetscErrorCode ierr;
1134 
1135   PetscFunctionBegin;
1136   jac->type = type;
1137   if (type == PC_COMPOSITE_SCHUR) {
1138     pc->ops->apply = PCApply_FieldSplit_Schur;
1139     pc->ops->view  = PCView_FieldSplit_Schur;
1140     ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitGetSubKSP_C","PCFieldSplitGetSubKSP_FieldSplit_Schur",PCFieldSplitGetSubKSP_FieldSplit_Schur);CHKERRQ(ierr);
1141     ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSchurPrecondition_C","PCFieldSplitSchurPrecondition_FieldSplit",PCFieldSplitSchurPrecondition_FieldSplit);CHKERRQ(ierr);
1142 
1143   } else {
1144     pc->ops->apply = PCApply_FieldSplit;
1145     pc->ops->view  = PCView_FieldSplit;
1146     ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitGetSubKSP_C","PCFieldSplitGetSubKSP_FieldSplit",PCFieldSplitGetSubKSP_FieldSplit);CHKERRQ(ierr);
1147     ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSchurPrecondition_C","",0);CHKERRQ(ierr);
1148   }
1149   PetscFunctionReturn(0);
1150 }
1151 EXTERN_C_END
1152 
1153 EXTERN_C_BEGIN
1154 #undef __FUNCT__
1155 #define __FUNCT__ "PCFieldSplitSetBlockSize_FieldSplit"
1156 PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetBlockSize_FieldSplit(PC pc,PetscInt bs)
1157 {
1158   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
1159 
1160   PetscFunctionBegin;
1161   if (bs < 1) SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Blocksize must be positive, you gave %D",bs);
1162   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);
1163   jac->bs = bs;
1164   PetscFunctionReturn(0);
1165 }
1166 EXTERN_C_END
1167 
1168 #undef __FUNCT__
1169 #define __FUNCT__ "PCFieldSplitSetType"
1170 /*@
1171    PCFieldSplitSetType - Sets the type of fieldsplit preconditioner.
1172 
1173    Collective on PC
1174 
1175    Input Parameter:
1176 .  pc - the preconditioner context
1177 .  type - PC_COMPOSITE_ADDITIVE, PC_COMPOSITE_MULTIPLICATIVE (default), PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE, PC_COMPOSITE_SPECIAL, PC_COMPOSITE_SCHUR
1178 
1179    Options Database Key:
1180 .  -pc_fieldsplit_type <type: one of multiplicative, additive, symmetric_multiplicative, special, schur> - Sets fieldsplit preconditioner type
1181 
1182    Level: Developer
1183 
1184 .keywords: PC, set, type, composite preconditioner, additive, multiplicative
1185 
1186 .seealso: PCCompositeSetType()
1187 
1188 @*/
1189 PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetType(PC pc,PCCompositeType type)
1190 {
1191   PetscErrorCode ierr;
1192 
1193   PetscFunctionBegin;
1194   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1195   ierr = PetscTryMethod(pc,"PCFieldSplitSetType_C",(PC,PCCompositeType),(pc,type));CHKERRQ(ierr);
1196   PetscFunctionReturn(0);
1197 }
1198 
1199 /* -------------------------------------------------------------------------------------*/
1200 /*MC
1201    PCFIELDSPLIT - Preconditioner created by combining separate preconditioners for individual
1202                   fields or groups of fields
1203 
1204 
1205      To set options on the solvers for each block append -fieldsplit_ to all the PC
1206         options database keys. For example, -fieldsplit_pc_type ilu -fieldsplit_pc_factor_levels 1
1207 
1208      To set the options on the solvers separate for each block call PCFieldSplitGetSubKSP()
1209          and set the options directly on the resulting KSP object
1210 
1211    Level: intermediate
1212 
1213    Options Database Keys:
1214 +   -pc_fieldsplit_%d_fields <a,b,..> - indicates the fields to be used in the %d'th split
1215 .   -pc_fieldsplit_default - automatically add any fields to additional splits that have not
1216                               been supplied explicitly by -pc_fieldsplit_%d_fields
1217 .   -pc_fieldsplit_block_size <bs> - size of block that defines fields (i.e. there are bs fields)
1218 .    -pc_fieldsplit_type <additive,multiplicative,schur,symmetric_multiplicative>
1219 .    -pc_fieldsplit_schur_precondition <true,false> default is true
1220 
1221 -    Options prefix for inner solvers when using Schur complement preconditioner are -fieldsplit_0_ and -fieldsplit_1_
1222      for all other solvers they are -fieldsplit_%d_ for the dth field, use -fieldsplit_ for all fields
1223 
1224 
1225    Notes: use PCFieldSplitSetFields() to set fields defined by "strided" entries and PCFieldSplitSetIS()
1226      to define a field by an arbitrary collection of entries.
1227 
1228       If no fields are set the default is used. The fields are defined by entries strided by bs,
1229       beginning at 0 then 1, etc to bs-1. The block size can be set with PCFieldSplitSetBlockSize(),
1230       if this is not called the block size defaults to the blocksize of the second matrix passed
1231       to KSPSetOperators()/PCSetOperators().
1232 
1233       Currently for the multiplicative version, the updated residual needed for the next field
1234      solve is computed via a matrix vector product over the entire array. An optimization would be
1235      to update the residual only for the part of the right hand side associated with the next field
1236      solve. (This would involve more MatGetSubMatrix() calls or some other mechanism to compute the
1237      part of the matrix needed to just update part of the residual).
1238 
1239      For the Schur complement preconditioner if J = ( A B )
1240                                                     ( C D )
1241      the preconditioner is
1242               (I   -B inv(A)) ( inv(A)   0    ) (I         0  )
1243               (0    I       ) (   0    inv(S) ) (-C inv(A) I  )
1244      where the action of inv(A) is applied using the KSP solver with prefix -fieldsplit_0_. The action of
1245      inv(S) is computed using the KSP solver with prefix -schur_. For PCFieldSplitGetKSP() when field number is
1246      0 it returns the KSP associated with -fieldsplit_0_ while field number 1 gives -fieldsplit_1_ KSP. By default
1247      D is used to construct a preconditioner for S, use PCFieldSplitSchurPrecondition() to turn on or off this
1248      option.
1249 
1250      If only one set of indices (one IS) is provided with PCFieldSplitSetIS() then the complement of that IS
1251      is used automatically for a second block.
1252 
1253    Concepts: physics based preconditioners, block preconditioners
1254 
1255 .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC, Block_Preconditioners
1256            PCFieldSplitGetSubKSP(), PCFieldSplitSetFields(), PCFieldSplitSetType(), PCFieldSplitSetIS(), PCFieldSplitSchurPrecondition()
1257 M*/
1258 
1259 EXTERN_C_BEGIN
1260 #undef __FUNCT__
1261 #define __FUNCT__ "PCCreate_FieldSplit"
1262 PetscErrorCode PETSCKSP_DLLEXPORT PCCreate_FieldSplit(PC pc)
1263 {
1264   PetscErrorCode ierr;
1265   PC_FieldSplit  *jac;
1266 
1267   PetscFunctionBegin;
1268   ierr = PetscNewLog(pc,PC_FieldSplit,&jac);CHKERRQ(ierr);
1269   jac->bs        = -1;
1270   jac->nsplits   = 0;
1271   jac->type      = PC_COMPOSITE_MULTIPLICATIVE;
1272   jac->schurpre  = PC_FIELDSPLIT_SCHUR_PRE_USER; /* Try user preconditioner first, fall back on diagonal */
1273   jac->schurfactorization = PC_FIELDSPLIT_SCHUR_FACTORIZATION_FULL;
1274 
1275   pc->data     = (void*)jac;
1276 
1277   pc->ops->apply             = PCApply_FieldSplit;
1278   pc->ops->applytranspose    = PCApplyTranspose_FieldSplit;
1279   pc->ops->setup             = PCSetUp_FieldSplit;
1280   pc->ops->destroy           = PCDestroy_FieldSplit;
1281   pc->ops->setfromoptions    = PCSetFromOptions_FieldSplit;
1282   pc->ops->view              = PCView_FieldSplit;
1283   pc->ops->applyrichardson   = 0;
1284 
1285   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitGetSubKSP_C","PCFieldSplitGetSubKSP_FieldSplit",
1286                     PCFieldSplitGetSubKSP_FieldSplit);CHKERRQ(ierr);
1287   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetFields_C","PCFieldSplitSetFields_FieldSplit",
1288                     PCFieldSplitSetFields_FieldSplit);CHKERRQ(ierr);
1289   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetIS_C","PCFieldSplitSetIS_FieldSplit",
1290                     PCFieldSplitSetIS_FieldSplit);CHKERRQ(ierr);
1291   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetType_C","PCFieldSplitSetType_FieldSplit",
1292                     PCFieldSplitSetType_FieldSplit);CHKERRQ(ierr);
1293   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetBlockSize_C","PCFieldSplitSetBlockSize_FieldSplit",
1294                     PCFieldSplitSetBlockSize_FieldSplit);CHKERRQ(ierr);
1295   PetscFunctionReturn(0);
1296 }
1297 EXTERN_C_END
1298 
1299 
1300 /*MC
1301    Block_Preconditioners - PETSc provides support for a variety of "block preconditioners", this provides an
1302           overview of these methods.
1303 
1304       Consider the solution to ( A B ) (x_1)  =  (b_1)
1305                                ( C D ) (x_2)     (b_2)
1306 
1307       Important special cases, the Stokes equation: C = B' and D = 0  (A   B) (x_1) = (b_1)
1308                                                                        B'  0) (x_2)   (b_2)
1309 
1310       One of the goals of the PCFieldSplit preconditioner in PETSc is to provide a variety of preconditioners
1311       for this block system.
1312 
1313       Consider an additional matrix (Ap  Bp)
1314                                     (Cp  Dp) where some or all of the entries may be the same as
1315       in the original matrix (for example Ap == A).
1316 
1317       In the following, A^ denotes the approximate application of the inverse of A, possibly using Ap in the
1318       approximation. In PETSc this simply means one has called KSPSetOperators(ksp,A,Ap,...) or KSPSetOperators(ksp,Ap,Ap,...)
1319 
1320       Block Jacobi:   x_1 = A^ b_1
1321                       x_2 = D^ b_2
1322 
1323       Lower block Gauss-Seidel:   x_1 = A^ b_1
1324                             x_2 = D^ (b_2 - C x_1)       variant x_2 = D^ (b_2 - Cp x_1)
1325 
1326       Symmetric Gauss-Seidel:  x_1 = x_1 + A^(b_1 - A x_1 - B x_2)    variant  x_1 = x_1 + A^(b_1 - Ap x_1 - Bp x_2)
1327           Interestingly this form is not actually a symmetric matrix, the symmetric version is
1328                               x_1 = A^(b_1 - B x_2)      variant x_1 = A^(b_1 - Bp x_2)
1329 
1330    Level: intermediate
1331 
1332 .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC, PCFIELDSPLIT
1333            PCFieldSplitGetSubKSP(), PCFieldSplitSetFields(), PCFieldSplitSetType(), PCFieldSplitSetIS(), PCFieldSplitSchurPrecondition()
1334 M*/
1335