Actual source code: fieldsplit.c

petsc-3.3-p0 2012-06-05
  2: #include <petsc-private/pcimpl.h>     /*I "petscpc.h" I*/
  3: #include <petscdmcomposite.h>   /*I "petscdmcomposite.h" I*/

  5: const char *const PCFieldSplitSchurPreTypes[] = {"SELF","DIAG","USER","PCFieldSplitSchurPreType","PC_FIELDSPLIT_SCHUR_PRE_",0};
  6: const char *const PCFieldSplitSchurFactTypes[] = {"DIAG","LOWER","UPPER","FULL","PCFieldSplitSchurFactType","PC_FIELDSPLIT_SCHUR_FACT_",0};

  8: typedef struct _PC_FieldSplitLink *PC_FieldSplitLink;
  9: struct _PC_FieldSplitLink {
 10:   KSP               ksp;
 11:   Vec               x,y;
 12:   char              *splitname;
 13:   PetscInt          nfields;
 14:   PetscInt          *fields,*fields_col;
 15:   VecScatter        sctx;
 16:   IS                is,is_col;
 17:   PC_FieldSplitLink next,previous;
 18: };

 20: typedef struct {
 21:   PCCompositeType                    type;
 22:   PetscBool                          defaultsplit; /* Flag for a system with a set of 'k' scalar fields with the same layout (and bs = k) */
 23:   PetscBool                          splitdefined; /* Flag is set after the splits have been defined, to prevent more splits from being added */
 24:   PetscBool                          realdiagonal; /* Flag to use the diagonal blocks of mat preconditioned by pmat, instead of just pmat */
 25:   PetscInt                           bs;           /* Block size for IS and Mat structures */
 26:   PetscInt                           nsplits;      /* Number of field divisions defined */
 27:   Vec                                *x,*y,w1,w2;
 28:   Mat                                *mat;         /* The diagonal block for each split */
 29:   Mat                                *pmat;        /* The preconditioning diagonal block for each split */
 30:   Mat                                *Afield;      /* The rows of the matrix associated with each split */
 31:   PetscBool                          issetup;
 32:   /* Only used when Schur complement preconditioning is used */
 33:   Mat                                B;            /* The (0,1) block */
 34:   Mat                                C;            /* The (1,0) block */
 35:   Mat                                schur;        /* The Schur complement S = A11 - A10 A00^{-1} A01 */
 36:   Mat                                schur_user;   /* User-provided preconditioning matrix for the Schur complement */
 37:   PCFieldSplitSchurPreType           schurpre; /* Determines which preconditioning matrix is used for the Schur complement */
 38:   PCFieldSplitSchurFactType schurfactorization;
 39:   KSP                                kspschur;     /* The solver for S */
 40:   PC_FieldSplitLink                  head;
 41:   PetscBool                          reset;         /* indicates PCReset() has been last called on this object, hack */
 42:   PetscBool                          suboptionsset; /* Indicates that the KSPSetFromOptions() has been called on the sub-KSPs */
 43: } PC_FieldSplit;

 45: /* 
 46:     Notes: there is no particular reason that pmat, x, and y are stored as arrays in PC_FieldSplit instead of 
 47:    inside PC_FieldSplitLink, just historical. If you want to be able to add new fields after already using the 
 48:    PC you could change this.
 49: */

 51: /* This helper is so that setting a user-provided preconditioning matrix is orthogonal to choosing to use it.  This way the
 52: * application-provided FormJacobian can provide this matrix without interfering with the user's (command-line) choices. */
 53: static Mat FieldSplitSchurPre(PC_FieldSplit *jac)
 54: {
 55:   switch (jac->schurpre) {
 56:     case PC_FIELDSPLIT_SCHUR_PRE_SELF: return jac->schur;
 57:     case PC_FIELDSPLIT_SCHUR_PRE_DIAG: return jac->pmat[1];
 58:     case PC_FIELDSPLIT_SCHUR_PRE_USER: /* Use a user-provided matrix if it is given, otherwise diagonal block */
 59:     default:
 60:       return jac->schur_user ? jac->schur_user : jac->pmat[1];
 61:   }
 62: }


 67: static PetscErrorCode PCView_FieldSplit(PC pc,PetscViewer viewer)
 68: {
 69:   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
 70:   PetscErrorCode    ierr;
 71:   PetscBool         iascii;
 72:   PetscInt          i,j;
 73:   PC_FieldSplitLink ilink = jac->head;

 76:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
 77:   if (iascii) {
 78:     if (jac->bs > 0) {
 79:       PetscViewerASCIIPrintf(viewer,"  FieldSplit with %s composition: total splits = %D, blocksize = %D\n",PCCompositeTypes[jac->type],jac->nsplits,jac->bs);
 80:     } else {
 81:       PetscViewerASCIIPrintf(viewer,"  FieldSplit with %s composition: total splits = %D\n",PCCompositeTypes[jac->type],jac->nsplits);
 82:     }
 83:     if (jac->realdiagonal) {
 84:       PetscViewerASCIIPrintf(viewer,"  using actual matrix for blocks rather than preconditioner matrix\n");
 85:     }
 86:     PetscViewerASCIIPrintf(viewer,"  Solver info for each split is in the following KSP objects:\n");
 87:     PetscViewerASCIIPushTab(viewer);
 88:     for (i=0; i<jac->nsplits; i++) {
 89:       if (ilink->fields) {
 90:         PetscViewerASCIIPrintf(viewer,"Split number %D Fields ",i);
 91:         PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);
 92:         for (j=0; j<ilink->nfields; j++) {
 93:           if (j > 0) {
 94:             PetscViewerASCIIPrintf(viewer,",");
 95:           }
 96:           PetscViewerASCIIPrintf(viewer," %D",ilink->fields[j]);
 97:         }
 98:         PetscViewerASCIIPrintf(viewer,"\n");
 99:         PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);
100:       } else {
101:         PetscViewerASCIIPrintf(viewer,"Split number %D Defined by IS\n",i);
102:       }
103:       KSPView(ilink->ksp,viewer);
104:       ilink = ilink->next;
105:     }
106:     PetscViewerASCIIPopTab(viewer);
107:   } else {
108:     SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_SUP,"Viewer type %s not supported for PCFieldSplit",((PetscObject)viewer)->type_name);
109:   }
110:   return(0);
111: }

115: static PetscErrorCode PCView_FieldSplit_Schur(PC pc,PetscViewer viewer)
116: {
117:   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
118:   PetscErrorCode    ierr;
119:   PetscBool         iascii;
120:   PetscInt          i,j;
121:   PC_FieldSplitLink ilink = jac->head;
122:   KSP               ksp;

125:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
126:   if (iascii) {
127:     if (jac->bs > 0) {
128:       PetscViewerASCIIPrintf(viewer,"  FieldSplit with Schur preconditioner, blocksize = %D, factorization %s\n",jac->bs,PCFieldSplitSchurFactTypes[jac->schurfactorization]);
129:     } else {
130:       PetscViewerASCIIPrintf(viewer,"  FieldSplit with Schur preconditioner, factorization %s\n",PCFieldSplitSchurFactTypes[jac->schurfactorization]);
131:     }
132:     if (jac->realdiagonal) {
133:       PetscViewerASCIIPrintf(viewer,"  using actual matrix for blocks rather than preconditioner matrix\n");
134:     }
135:     switch(jac->schurpre) {
136:     case PC_FIELDSPLIT_SCHUR_PRE_SELF:
137:       PetscViewerASCIIPrintf(viewer,"  Preconditioner for the Schur complement formed from S itself\n");break;
138:     case PC_FIELDSPLIT_SCHUR_PRE_DIAG:
139:       PetscViewerASCIIPrintf(viewer,"  Preconditioner for the Schur complement formed from the block diagonal part of A11\n");break;
140:     case PC_FIELDSPLIT_SCHUR_PRE_USER:
141:       if (jac->schur_user) {
142:         PetscViewerASCIIPrintf(viewer,"  Preconditioner for the Schur complement formed from user provided matrix\n");
143:       } else {
144:       PetscViewerASCIIPrintf(viewer,"  Preconditioner for the Schur complement formed from the block diagonal part of A11\n");
145:       }
146:       break;
147:     default:
148:       SETERRQ1(((PetscObject) pc)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid Schur preconditioning type: %d", jac->schurpre);
149:     }
150:     PetscViewerASCIIPrintf(viewer,"  Split info:\n");
151:     PetscViewerASCIIPushTab(viewer);
152:     for (i=0; i<jac->nsplits; i++) {
153:       if (ilink->fields) {
154:         PetscViewerASCIIPrintf(viewer,"Split number %D Fields ",i);
155:         PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);
156:         for (j=0; j<ilink->nfields; j++) {
157:           if (j > 0) {
158:             PetscViewerASCIIPrintf(viewer,",");
159:           }
160:           PetscViewerASCIIPrintf(viewer," %D",ilink->fields[j]);
161:         }
162:         PetscViewerASCIIPrintf(viewer,"\n");
163:         PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);
164:       } else {
165:         PetscViewerASCIIPrintf(viewer,"Split number %D Defined by IS\n",i);
166:       }
167:       ilink = ilink->next;
168:     }
169:     PetscViewerASCIIPrintf(viewer,"KSP solver for A00 block \n");
170:     PetscViewerASCIIPushTab(viewer);
171:     if (jac->schur) {
172:       MatSchurComplementGetKSP(jac->schur,&ksp);
173:       KSPView(ksp,viewer);
174:     } else {
175:       PetscViewerASCIIPrintf(viewer,"  not yet available\n");
176:     }
177:     PetscViewerASCIIPopTab(viewer);
178:     PetscViewerASCIIPrintf(viewer,"KSP solver for S = A11 - A10 inv(A00) A01 \n");
179:     PetscViewerASCIIPushTab(viewer);
180:     if (jac->kspschur) {
181:       KSPView(jac->kspschur,viewer);
182:     } else {
183:       PetscViewerASCIIPrintf(viewer,"  not yet available\n");
184:     }
185:     PetscViewerASCIIPopTab(viewer);
186:     PetscViewerASCIIPopTab(viewer);
187:   } else {
188:     SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_SUP,"Viewer type %s not supported for PCFieldSplit",((PetscObject)viewer)->type_name);
189:   }
190:   return(0);
191: }

195: /* Precondition: jac->bs is set to a meaningful value */
196: static PetscErrorCode PCFieldSplitSetRuntimeSplits_Private(PC pc)
197: {
199:   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
200:   PetscInt       i,nfields,*ifields,nfields_col,*ifields_col;
201:   PetscBool      flg,flg_col;
202:   char           optionname[128],splitname[8],optionname_col[128];

205:   PetscMalloc(jac->bs*sizeof(PetscInt),&ifields);
206:   PetscMalloc(jac->bs*sizeof(PetscInt),&ifields_col);
207:   for (i=0,flg=PETSC_TRUE; ; i++) {
208:     PetscSNPrintf(splitname,sizeof splitname,"%D",i);
209:     PetscSNPrintf(optionname,sizeof optionname,"-pc_fieldsplit_%D_fields",i);
210:     PetscSNPrintf(optionname_col,sizeof optionname_col,"-pc_fieldsplit_%D_fields_col",i);
211:     nfields = jac->bs;
212:     nfields_col = jac->bs;
213:     PetscOptionsGetIntArray(((PetscObject)pc)->prefix,optionname,ifields,&nfields,&flg);
214:     PetscOptionsGetIntArray(((PetscObject)pc)->prefix,optionname_col,ifields_col,&nfields_col,&flg_col);
215:     if (!flg) break;
216:     else if (flg && !flg_col) {
217:       if (!nfields) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot list zero fields");
218:       PCFieldSplitSetFields(pc,splitname,nfields,ifields,ifields);
219:     }
220:     else {
221:       if (!nfields || !nfields_col) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot list zero fields");
222:       if (nfields != nfields_col) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Number of row and column fields must match");
223:       PCFieldSplitSetFields(pc,splitname,nfields,ifields,ifields_col);
224:     }
225:   }
226:   if (i > 0) {
227:     /* Makes command-line setting of splits take precedence over setting them in code.
228:        Otherwise subsequent calls to PCFieldSplitSetIS() or PCFieldSplitSetFields() would
229:        create new splits, which would probably not be what the user wanted. */
230:     jac->splitdefined = PETSC_TRUE;
231:   }
232:   PetscFree(ifields);
233:   PetscFree(ifields_col);
234:   return(0);
235: }

239: static PetscErrorCode PCFieldSplitSetDefaults(PC pc)
240: {
241:   PC_FieldSplit     *jac  = (PC_FieldSplit*)pc->data;
242:   PetscErrorCode    ierr;
243:   PC_FieldSplitLink ilink = jac->head;
244:   PetscBool         flg = PETSC_FALSE,stokes = PETSC_FALSE;
245:   PetscInt          i;

248:   if (!ilink) {
249:     PetscOptionsGetBool(((PetscObject)pc)->prefix,"-pc_fieldsplit_detect_saddle_point",&stokes,PETSC_NULL);
250:     if (pc->dm && !stokes) {
251:       PetscInt     numFields, f;
252:       char         **fieldNames;
253:       IS          *fields;
254:       DM          *dms;
255:       DMCreateFieldDecomposition(pc->dm, &numFields, &fieldNames, &fields, &dms);
256:       for(f = 0; f < numFields; ++f) {
257:         PCFieldSplitSetIS(pc, fieldNames[f], fields[f]);
258:         PetscFree(fieldNames[f]);
259:         ISDestroy(&fields[f]);
260:       }
261:       PetscFree(fieldNames);
262:       PetscFree(fields);
263:       if(dms) {
264:         PetscInfo(pc,"Setting up physics based fieldsplit preconditioner using the embedded DM\n");
265:         for (ilink=jac->head,i=0; ilink; ilink=ilink->next,i++) {
266:           KSPSetDM(ilink->ksp, dms[i]);
267:           KSPSetDMActive(ilink->ksp, PETSC_FALSE);
268:           DMDestroy(&dms[i]);
269:         }
270:         PetscFree(dms);
271:       }
272:     } else {
273:       if (jac->bs <= 0) {
274:         if (pc->pmat) {
275:           MatGetBlockSize(pc->pmat,&jac->bs);
276:         } else {
277:           jac->bs = 1;
278:         }
279:       }

281:       PetscOptionsGetBool(((PetscObject)pc)->prefix,"-pc_fieldsplit_default",&flg,PETSC_NULL);
282:       if (stokes) {
283:         IS       zerodiags,rest;
284:         PetscInt nmin,nmax;

286:         MatGetOwnershipRange(pc->mat,&nmin,&nmax);
287:         MatFindZeroDiagonals(pc->mat,&zerodiags);
288:         ISComplement(zerodiags,nmin,nmax,&rest);
289:         PCFieldSplitSetIS(pc,"0",rest);
290:         PCFieldSplitSetIS(pc,"1",zerodiags);
291:         ISDestroy(&zerodiags);
292:         ISDestroy(&rest);
293:       } else {
294:         if (!flg) {
295:           /* Allow user to set fields from command line,  if bs was known at the time of PCSetFromOptions_FieldSplit()
296:            then it is set there. This is not ideal because we should only have options set in XXSetFromOptions(). */
297:           PCFieldSplitSetRuntimeSplits_Private(pc);
298:           if (jac->splitdefined) {PetscInfo(pc,"Splits defined using the options database\n");}
299:         }
300:         if (flg || !jac->splitdefined) {
301:           PetscInfo(pc,"Using default splitting of fields\n");
302:           for (i=0; i<jac->bs; i++) {
303:             char splitname[8];
304:             PetscSNPrintf(splitname,sizeof splitname,"%D",i);
305:             PCFieldSplitSetFields(pc,splitname,1,&i,&i);
306:           }
307:           jac->defaultsplit = PETSC_TRUE;
308:         }
309:       }
310:     }
311:   } else if (jac->nsplits == 1) {
312:     if (ilink->is) {
313:       IS       is2;
314:       PetscInt nmin,nmax;

316:       MatGetOwnershipRange(pc->mat,&nmin,&nmax);
317:       ISComplement(ilink->is,nmin,nmax,&is2);
318:       PCFieldSplitSetIS(pc,"1",is2);
319:       ISDestroy(&is2);
320:     } else SETERRQ(((PetscObject) pc)->comm,PETSC_ERR_SUP,"Must provide at least two sets of fields to PCFieldSplit()");
321:   } else if (jac->reset) {
322:     /* PCReset() has been called on this PC, ilink exists but all IS and Vec data structures in it must be rebuilt 
323:        This is basically the !ilink portion of code above copied from above and the allocation of the ilinks removed
324:        since they already exist. This should be totally rewritten */
325:     PetscOptionsGetBool(((PetscObject)pc)->prefix,"-pc_fieldsplit_detect_saddle_point",&stokes,PETSC_NULL);
326:     if (pc->dm && !stokes) {
327:       PetscBool dmcomposite;
328:       PetscObjectTypeCompare((PetscObject)pc->dm,DMCOMPOSITE,&dmcomposite);
329:       if (dmcomposite) {
330:         PetscInt nDM;
331:         IS       *fields;
332:         DM       *dms;
333:         PetscInfo(pc,"Setting up physics based fieldsplit preconditioner using the embedded DM\n");
334:         DMCompositeGetNumberDM(pc->dm,&nDM);
335:         DMCompositeGetGlobalISs(pc->dm,&fields);
336:         PetscMalloc(nDM*sizeof(DM),&dms);
337:         DMCompositeGetEntriesArray(pc->dm,dms);
338:         for (i=0; i<nDM; i++) {
339:           KSPSetDM(ilink->ksp,dms[i]);
340:           KSPSetDMActive(ilink->ksp,PETSC_FALSE);
341:           ilink->is = fields[i];
342:           ilink     = ilink->next;
343:         }
344:         PetscFree(fields);
345:         PetscFree(dms);
346:       }
347:     } else {
348:       PetscOptionsGetBool(((PetscObject)pc)->prefix,"-pc_fieldsplit_default",&flg,PETSC_NULL);
349:       if (stokes) {
350:         IS       zerodiags,rest;
351:         PetscInt nmin,nmax;

353:         MatGetOwnershipRange(pc->mat,&nmin,&nmax);
354:         MatFindZeroDiagonals(pc->mat,&zerodiags);
355:         ISComplement(zerodiags,nmin,nmax,&rest);
356:         ISDestroy(&ilink->is);
357:         ISDestroy(&ilink->next->is);
358:         ilink->is       = rest;
359:         ilink->next->is = zerodiags;
360:       } else SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_SUP,"Cases not yet handled when PCReset() was used");
361:     }
362:   }

364:   if (jac->nsplits < 2) SETERRQ1(((PetscObject) pc)->comm,PETSC_ERR_PLIB,"Unhandled case, must have at least two fields, not %d", jac->nsplits);
365:   return(0);
366: }

370: static PetscErrorCode PCSetUp_FieldSplit(PC pc)
371: {
372:   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
373:   PetscErrorCode    ierr;
374:   PC_FieldSplitLink ilink;
375:   PetscInt          i,nsplit;
376:   MatStructure      flag = pc->flag;
377:   PetscBool         sorted, sorted_col;

380:   PCFieldSplitSetDefaults(pc);
381:   nsplit = jac->nsplits;
382:   ilink  = jac->head;

384:   /* get the matrices for each split */
385:   if (!jac->issetup) {
386:     PetscInt rstart,rend,nslots,bs;

388:     jac->issetup = PETSC_TRUE;

390:     /* This is done here instead of in PCFieldSplitSetFields() because may not have matrix at that point */
391:     if (jac->defaultsplit || !ilink->is) {
392:       if (jac->bs <= 0) jac->bs = nsplit;
393:     }
394:     bs     = jac->bs;
395:     MatGetOwnershipRange(pc->pmat,&rstart,&rend);
396:     nslots = (rend - rstart)/bs;
397:     for (i=0; i<nsplit; i++) {
398:       if (jac->defaultsplit) {
399:         ISCreateStride(((PetscObject)pc)->comm,nslots,rstart+i,nsplit,&ilink->is);
400:         ISDuplicate(ilink->is,&ilink->is_col);
401:       } else if (!ilink->is) {
402:         if (ilink->nfields > 1) {
403:           PetscInt   *ii,*jj,j,k,nfields = ilink->nfields,*fields = ilink->fields,*fields_col = ilink->fields_col;
404:           PetscMalloc(ilink->nfields*nslots*sizeof(PetscInt),&ii);
405:           PetscMalloc(ilink->nfields*nslots*sizeof(PetscInt),&jj);
406:           for (j=0; j<nslots; j++) {
407:             for (k=0; k<nfields; k++) {
408:               ii[nfields*j + k] = rstart + bs*j + fields[k];
409:               jj[nfields*j + k] = rstart + bs*j + fields_col[k];
410:             }
411:           }
412:           ISCreateGeneral(((PetscObject)pc)->comm,nslots*nfields,ii,PETSC_OWN_POINTER,&ilink->is);
413:           ISCreateGeneral(((PetscObject)pc)->comm,nslots*nfields,jj,PETSC_OWN_POINTER,&ilink->is_col);
414:         } else {
415:           ISCreateStride(((PetscObject)pc)->comm,nslots,rstart+ilink->fields[0],bs,&ilink->is);
416:           ISCreateStride(((PetscObject)pc)->comm,nslots,rstart+ilink->fields_col[0],bs,&ilink->is_col);
417:        }
418:       }
419:       ISSorted(ilink->is,&sorted);
420:       if (ilink->is_col) { ISSorted(ilink->is_col,&sorted_col); }
421:       if (!sorted || !sorted_col) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Fields must be sorted when creating split");
422:       ilink = ilink->next;
423:     }
424:   }

426:   ilink  = jac->head;
427:   if (!jac->pmat) {
428:     Vec xtmp;

430:     MatGetVecs(pc->pmat,&xtmp,PETSC_NULL);
431:     PetscMalloc(nsplit*sizeof(Mat),&jac->pmat);
432:     PetscMalloc2(nsplit,Vec,&jac->x,nsplit,Vec,&jac->y);
433:     for (i=0; i<nsplit; i++) {
434:       MatNullSpace sp;

436:       /* Check for preconditioning matrix attached to IS */
437:       PetscObjectQuery((PetscObject) ilink->is, "pmat", (PetscObject *) &jac->pmat[i]);
438:       if (jac->pmat[i]) {
439:         PetscObjectReference((PetscObject) jac->pmat[i]);
440:         if (jac->type == PC_COMPOSITE_SCHUR) {
441:           jac->schur_user = jac->pmat[i];
442:           PetscObjectReference((PetscObject) jac->schur_user);
443:         }
444:       } else {
445:         MatGetSubMatrix(pc->pmat,ilink->is,ilink->is_col,MAT_INITIAL_MATRIX,&jac->pmat[i]);
446:       }
447:       /* create work vectors for each split */
448:       MatGetVecs(jac->pmat[i],&jac->x[i],&jac->y[i]);
449:       ilink->x = jac->x[i]; ilink->y = jac->y[i];
450:       /* compute scatter contexts needed by multiplicative versions and non-default splits */
451:       VecScatterCreate(xtmp,ilink->is,jac->x[i],PETSC_NULL,&ilink->sctx);
452:       /* HACK: Check for the constant null space */
453:       MatGetNullSpace(pc->pmat, &sp);
454:       if (sp) {
455:         MatNullSpace subsp;
456:         Vec          ftmp, gtmp;
457:         PetscReal    norm;
458:         PetscInt     N;

460:         MatGetVecs(pc->pmat,     &gtmp, PETSC_NULL);
461:         MatGetVecs(jac->pmat[i], &ftmp, PETSC_NULL);
462:         VecGetSize(ftmp, &N);
463:         VecSet(ftmp, 1.0/N);
464:         VecScatterBegin(ilink->sctx, ftmp, gtmp, INSERT_VALUES, SCATTER_REVERSE);
465:         VecScatterEnd(ilink->sctx, ftmp, gtmp, INSERT_VALUES, SCATTER_REVERSE);
466:         MatNullSpaceRemove(sp, gtmp, PETSC_NULL);
467:         VecNorm(gtmp, NORM_2, &norm);
468:         if (norm < 1.0e-10) {
469:           MatNullSpaceCreate(((PetscObject)pc)->comm, PETSC_TRUE, 0, PETSC_NULL, &subsp);
470:           MatSetNullSpace(jac->pmat[i], subsp);
471:           MatNullSpaceDestroy(&subsp);
472:         }
473:         VecDestroy(&ftmp);
474:         VecDestroy(&gtmp);
475:       }
476:       /* Check for null space attached to IS */
477:       PetscObjectQuery((PetscObject) ilink->is, "nearnullspace", (PetscObject *) &sp);
478:       if (sp) {
479:         MatSetNearNullSpace(jac->pmat[i], sp);
480:       }
481:       ilink = ilink->next;
482:     }
483:     VecDestroy(&xtmp);
484:   } else {
485:     for (i=0; i<nsplit; i++) {
486:       Mat pmat;

488:       /* Check for preconditioning matrix attached to IS */
489:       PetscObjectQuery((PetscObject) ilink->is, "pmat", (PetscObject *) &pmat);
490:       if (!pmat) {
491:         MatGetSubMatrix(pc->pmat,ilink->is,ilink->is_col,MAT_REUSE_MATRIX,&jac->pmat[i]);
492:       }
493:       ilink = ilink->next;
494:     }
495:   }
496:   if (jac->realdiagonal) {
497:     ilink = jac->head;
498:     if (!jac->mat) {
499:       PetscMalloc(nsplit*sizeof(Mat),&jac->mat);
500:       for (i=0; i<nsplit; i++) {
501:         MatGetSubMatrix(pc->mat,ilink->is,ilink->is_col,MAT_INITIAL_MATRIX,&jac->mat[i]);
502:         ilink = ilink->next;
503:       }
504:     } else {
505:       for (i=0; i<nsplit; i++) {
506:         if (jac->mat[i]) {MatGetSubMatrix(pc->mat,ilink->is,ilink->is_col,MAT_REUSE_MATRIX,&jac->mat[i]);}
507:         ilink = ilink->next;
508:       }
509:     }
510:   } else {
511:     jac->mat = jac->pmat;
512:   }

514:   if (jac->type != PC_COMPOSITE_ADDITIVE  && jac->type != PC_COMPOSITE_SCHUR) {
515:     /* extract the rows of the matrix associated with each field: used for efficient computation of residual inside algorithm */
516:     ilink  = jac->head;
517:     if (!jac->Afield) {
518:       PetscMalloc(nsplit*sizeof(Mat),&jac->Afield);
519:       for (i=0; i<nsplit; i++) {
520:         MatGetSubMatrix(pc->mat,ilink->is,PETSC_NULL,MAT_INITIAL_MATRIX,&jac->Afield[i]);
521:         ilink = ilink->next;
522:       }
523:     } else {
524:       for (i=0; i<nsplit; i++) {
525:         MatGetSubMatrix(pc->mat,ilink->is,PETSC_NULL,MAT_REUSE_MATRIX,&jac->Afield[i]);
526:         ilink = ilink->next;
527:       }
528:     }
529:   }

531:   if (jac->type == PC_COMPOSITE_SCHUR) {
532:     IS       ccis;
533:     PetscInt rstart,rend;
534:     char     lscname[256];
535:     PetscObject LSC_L;
536:     if (nsplit != 2) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ARG_INCOMP,"To use Schur complement preconditioner you must have exactly 2 fields");

538:     /* When extracting off-diagonal submatrices, we take complements from this range */
539:     MatGetOwnershipRangeColumn(pc->mat,&rstart,&rend);

541:     /* need to handle case when one is resetting up the preconditioner */
542:     if (jac->schur) {
543:       ilink = jac->head;
544:       ISComplement(ilink->is_col,rstart,rend,&ccis);
545:       MatGetSubMatrix(pc->mat,ilink->is,ccis,MAT_REUSE_MATRIX,&jac->B);
546:       ISDestroy(&ccis);
547:       ilink = ilink->next;
548:       ISComplement(ilink->is_col,rstart,rend,&ccis);
549:       MatGetSubMatrix(pc->mat,ilink->is,ccis,MAT_REUSE_MATRIX,&jac->C);
550:       ISDestroy(&ccis);
551:       MatSchurComplementUpdate(jac->schur,jac->mat[0],jac->pmat[0],jac->B,jac->C,jac->mat[1],pc->flag);
552:       KSPSetOperators(jac->kspschur,jac->schur,FieldSplitSchurPre(jac),pc->flag);

554:      } else {
555:       KSP ksp;
556:       char schurprefix[256];
557:       MatNullSpace sp;

559:       /* extract the A01 and A10 matrices */
560:       ilink = jac->head;
561:       ISComplement(ilink->is_col,rstart,rend,&ccis);
562:       MatGetSubMatrix(pc->mat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->B);
563:       ISDestroy(&ccis);
564:       ilink = ilink->next;
565:       ISComplement(ilink->is_col,rstart,rend,&ccis);
566:       MatGetSubMatrix(pc->mat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->C);
567:       ISDestroy(&ccis);
568:       /* Use mat[0] (diagonal block of the real matrix) preconditioned by pmat[0] */
569:       MatCreateSchurComplement(jac->mat[0],jac->pmat[0],jac->B,jac->C,jac->mat[1],&jac->schur);
570:       MatGetNullSpace(jac->pmat[1], &sp);
571:       if (sp) {MatSetNullSpace(jac->schur, sp);}
572:       /* set tabbing and options prefix of KSP inside the MatSchur */
573:       MatSchurComplementGetKSP(jac->schur,&ksp);
574:       PetscObjectIncrementTabLevel((PetscObject)ksp,(PetscObject)pc,2);
575:       PetscSNPrintf(schurprefix,sizeof schurprefix,"%sfieldsplit_%s_",((PetscObject)pc)->prefix?((PetscObject)pc)->prefix:"",jac->head->splitname);
576:       KSPSetOptionsPrefix(ksp,schurprefix);
577:       /* Need to call this everytime because new matrix is being created */
578:       MatSetFromOptions(jac->schur);
579:       MatSetUp(jac->schur);

581:       KSPCreate(((PetscObject)pc)->comm,&jac->kspschur);
582:       PetscLogObjectParent((PetscObject)pc,(PetscObject)jac->kspschur);
583:       PetscObjectIncrementTabLevel((PetscObject)jac->kspschur,(PetscObject)pc,1);
584:       KSPSetOperators(jac->kspschur,jac->schur,FieldSplitSchurPre(jac),DIFFERENT_NONZERO_PATTERN);
585:       if (jac->schurpre == PC_FIELDSPLIT_SCHUR_PRE_SELF) {
586:         PC pc;
587:         KSPGetPC(jac->kspschur,&pc);
588:         PCSetType(pc,PCNONE);
589:         /* Note: This is bad if there exist preconditioners for MATSCHURCOMPLEMENT */
590:       }
591:       PetscSNPrintf(schurprefix,sizeof schurprefix,"%sfieldsplit_%s_",((PetscObject)pc)->prefix?((PetscObject)pc)->prefix:"",ilink->splitname);
592:       KSPSetOptionsPrefix(jac->kspschur,schurprefix);
593:       /* really want setfromoptions called in PCSetFromOptions_FieldSplit(), but it is not ready yet */
594:       /* need to call this every time, since the jac->kspschur is freshly created, otherwise its options never get set */
595:       KSPSetFromOptions(jac->kspschur);
596:     }

598:     /* HACK: special support to forward L and Lp matrices that might be used by PCLSC */
599:     PetscSNPrintf(lscname,sizeof lscname,"%s_LSC_L",ilink->splitname);
600:     PetscObjectQuery((PetscObject)pc->mat,lscname,(PetscObject*)&LSC_L);
601:     if (!LSC_L) {PetscObjectQuery((PetscObject)pc->pmat,lscname,(PetscObject*)&LSC_L);}
602:     if (LSC_L) {PetscObjectCompose((PetscObject)jac->schur,"LSC_L",(PetscObject)LSC_L);}
603:     PetscSNPrintf(lscname,sizeof lscname,"%s_LSC_Lp",ilink->splitname);
604:     PetscObjectQuery((PetscObject)pc->pmat,lscname,(PetscObject*)&LSC_L);
605:     if (!LSC_L) {PetscObjectQuery((PetscObject)pc->mat,lscname,(PetscObject*)&LSC_L);}
606:     if (LSC_L) {PetscObjectCompose((PetscObject)jac->schur,"LSC_Lp",(PetscObject)LSC_L);}
607:   } else {
608:     /* set up the individual PCs */
609:     i    = 0;
610:     ilink = jac->head;
611:     while (ilink) {
612:       KSPSetOperators(ilink->ksp,jac->mat[i],jac->pmat[i],flag);
613:       /* really want setfromoptions called in PCSetFromOptions_FieldSplit(), but it is not ready yet */
614:       if (!jac->suboptionsset) {KSPSetFromOptions(ilink->ksp);}
615:       KSPSetUp(ilink->ksp);
616:       i++;
617:       ilink = ilink->next;
618:     }
619:   }

621:   jac->suboptionsset = PETSC_TRUE;
622:   return(0);
623: }

625: #define FieldSplitSplitSolveAdd(ilink,xx,yy) \
626:     (VecScatterBegin(ilink->sctx,xx,ilink->x,INSERT_VALUES,SCATTER_FORWARD) || \
627:      VecScatterEnd(ilink->sctx,xx,ilink->x,INSERT_VALUES,SCATTER_FORWARD) || \
628:      KSPSolve(ilink->ksp,ilink->x,ilink->y) || \
629:      VecScatterBegin(ilink->sctx,ilink->y,yy,ADD_VALUES,SCATTER_REVERSE) || \
630:      VecScatterEnd(ilink->sctx,ilink->y,yy,ADD_VALUES,SCATTER_REVERSE))

634: static PetscErrorCode PCApply_FieldSplit_Schur(PC pc,Vec x,Vec y)
635: {
636:   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
637:   PetscErrorCode    ierr;
638:   KSP               ksp;
639:   PC_FieldSplitLink ilinkA = jac->head, ilinkD = ilinkA->next;

642:   MatSchurComplementGetKSP(jac->schur,&ksp);

644:   switch (jac->schurfactorization) {
645:     case PC_FIELDSPLIT_SCHUR_FACT_DIAG:
646:       /* [A00 0; 0 -S], positive definite, suitable for MINRES */
647:       VecScatterBegin(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);
648:       VecScatterBegin(ilinkD->sctx,x,ilinkD->x,INSERT_VALUES,SCATTER_FORWARD);
649:       VecScatterEnd(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);
650:       KSPSolve(ksp,ilinkA->x,ilinkA->y);
651:       VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);
652:       VecScatterEnd(ilinkD->sctx,x,ilinkD->x,INSERT_VALUES,SCATTER_FORWARD);
653:       KSPSolve(jac->kspschur,ilinkD->x,ilinkD->y);
654:       VecScale(ilinkD->y,-1.);
655:       VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);
656:       VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);
657:       VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);
658:       break;
659:     case PC_FIELDSPLIT_SCHUR_FACT_LOWER:
660:       /* [A00 0; A10 S], suitable for left preconditioning */
661:       VecScatterBegin(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);
662:       VecScatterEnd(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);
663:       KSPSolve(ksp,ilinkA->x,ilinkA->y);
664:       MatMult(jac->C,ilinkA->y,ilinkD->x);
665:       VecScale(ilinkD->x,-1.);
666:       VecScatterBegin(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);
667:       VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);
668:       VecScatterEnd(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);
669:       KSPSolve(jac->kspschur,ilinkD->x,ilinkD->y);
670:       VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);
671:       VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);
672:       VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);
673:       break;
674:     case PC_FIELDSPLIT_SCHUR_FACT_UPPER:
675:       /* [A00 A01; 0 S], suitable for right preconditioning */
676:       VecScatterBegin(ilinkD->sctx,x,ilinkD->x,INSERT_VALUES,SCATTER_FORWARD);
677:       VecScatterEnd(ilinkD->sctx,x,ilinkD->x,INSERT_VALUES,SCATTER_FORWARD);
678:       KSPSolve(jac->kspschur,ilinkD->x,ilinkD->y);
679:       MatMult(jac->B,ilinkD->y,ilinkA->x);
680:       VecScale(ilinkA->x,-1.);
681:       VecScatterBegin(ilinkA->sctx,x,ilinkA->x,ADD_VALUES,SCATTER_FORWARD);
682:       VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);
683:       VecScatterEnd(ilinkA->sctx,x,ilinkA->x,ADD_VALUES,SCATTER_FORWARD);
684:       KSPSolve(ksp,ilinkA->x,ilinkA->y);
685:       VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);
686:       VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);
687:       VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);
688:       break;
689:     case PC_FIELDSPLIT_SCHUR_FACT_FULL:
690:       /* [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 */
691:       VecScatterBegin(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);
692:       VecScatterEnd(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);
693:       KSPSolve(ksp,ilinkA->x,ilinkA->y);
694:       MatMult(jac->C,ilinkA->y,ilinkD->x);
695:       VecScale(ilinkD->x,-1.0);
696:       VecScatterBegin(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);
697:       VecScatterEnd(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);

699:       KSPSolve(jac->kspschur,ilinkD->x,ilinkD->y);
700:       VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);
701:       VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);

703:       MatMult(jac->B,ilinkD->y,ilinkA->y);
704:       VecAXPY(ilinkA->x,-1.0,ilinkA->y);
705:       KSPSolve(ksp,ilinkA->x,ilinkA->y);
706:       VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);
707:       VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);
708:   }
709:   return(0);
710: }

714: static PetscErrorCode PCApply_FieldSplit(PC pc,Vec x,Vec y)
715: {
716:   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
717:   PetscErrorCode    ierr;
718:   PC_FieldSplitLink ilink = jac->head;
719:   PetscInt          cnt,bs;

722:   CHKMEMQ;
723:   if (jac->type == PC_COMPOSITE_ADDITIVE) {
724:     if (jac->defaultsplit) {
725:       VecGetBlockSize(x,&bs);
726:       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);
727:       VecGetBlockSize(y,&bs);
728:       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);
729:       VecStrideGatherAll(x,jac->x,INSERT_VALUES);
730:       while (ilink) {
731:         KSPSolve(ilink->ksp,ilink->x,ilink->y);
732:         ilink = ilink->next;
733:       }
734:       VecStrideScatterAll(jac->y,y,INSERT_VALUES);
735:     } else {
736:       VecSet(y,0.0);
737:       while (ilink) {
738:         FieldSplitSplitSolveAdd(ilink,x,y);
739:         ilink = ilink->next;
740:       }
741:     }
742:   } else if (jac->type == PC_COMPOSITE_MULTIPLICATIVE || jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
743:     if (!jac->w1) {
744:       VecDuplicate(x,&jac->w1);
745:       VecDuplicate(x,&jac->w2);
746:     }
747:     VecSet(y,0.0);
748:     FieldSplitSplitSolveAdd(ilink,x,y);
749:     cnt = 1;
750:     while (ilink->next) {
751:       ilink = ilink->next;
752:       /* compute the residual only over the part of the vector needed */
753:       MatMult(jac->Afield[cnt++],y,ilink->x);
754:       VecScale(ilink->x,-1.0);
755:       VecScatterBegin(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);
756:       VecScatterEnd(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);
757:       KSPSolve(ilink->ksp,ilink->x,ilink->y);
758:       VecScatterBegin(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);
759:       VecScatterEnd(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);
760:     }
761:     if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
762:       cnt -= 2;
763:       while (ilink->previous) {
764:         ilink = ilink->previous;
765:         /* compute the residual only over the part of the vector needed */
766:         MatMult(jac->Afield[cnt--],y,ilink->x);
767:         VecScale(ilink->x,-1.0);
768:         VecScatterBegin(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);
769:         VecScatterEnd(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);
770:         KSPSolve(ilink->ksp,ilink->x,ilink->y);
771:         VecScatterBegin(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);
772:         VecScatterEnd(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);
773:       }
774:     }
775:   } else SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_SUP,"Unsupported or unknown composition",(int) jac->type);
776:   CHKMEMQ;
777:   return(0);
778: }

780: #define FieldSplitSplitSolveAddTranspose(ilink,xx,yy) \
781:     (VecScatterBegin(ilink->sctx,xx,ilink->y,INSERT_VALUES,SCATTER_FORWARD) || \
782:      VecScatterEnd(ilink->sctx,xx,ilink->y,INSERT_VALUES,SCATTER_FORWARD) || \
783:      KSPSolveTranspose(ilink->ksp,ilink->y,ilink->x) || \
784:      VecScatterBegin(ilink->sctx,ilink->x,yy,ADD_VALUES,SCATTER_REVERSE) || \
785:      VecScatterEnd(ilink->sctx,ilink->x,yy,ADD_VALUES,SCATTER_REVERSE))

789: static PetscErrorCode PCApplyTranspose_FieldSplit(PC pc,Vec x,Vec y)
790: {
791:   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
792:   PetscErrorCode    ierr;
793:   PC_FieldSplitLink ilink = jac->head;
794:   PetscInt          bs;

797:   CHKMEMQ;
798:   if (jac->type == PC_COMPOSITE_ADDITIVE) {
799:     if (jac->defaultsplit) {
800:       VecGetBlockSize(x,&bs);
801:       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);
802:       VecGetBlockSize(y,&bs);
803:       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);
804:       VecStrideGatherAll(x,jac->x,INSERT_VALUES);
805:       while (ilink) {
806:         KSPSolveTranspose(ilink->ksp,ilink->x,ilink->y);
807:         ilink = ilink->next;
808:       }
809:       VecStrideScatterAll(jac->y,y,INSERT_VALUES);
810:     } else {
811:       VecSet(y,0.0);
812:       while (ilink) {
813:         FieldSplitSplitSolveAddTranspose(ilink,x,y);
814:         ilink = ilink->next;
815:       }
816:     }
817:   } else {
818:     if (!jac->w1) {
819:       VecDuplicate(x,&jac->w1);
820:       VecDuplicate(x,&jac->w2);
821:     }
822:     VecSet(y,0.0);
823:     if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
824:       FieldSplitSplitSolveAddTranspose(ilink,x,y);
825:       while (ilink->next) {
826:         ilink = ilink->next;
827:         MatMultTranspose(pc->mat,y,jac->w1);
828:         VecWAXPY(jac->w2,-1.0,jac->w1,x);
829:         FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);
830:       }
831:       while (ilink->previous) {
832:         ilink = ilink->previous;
833:         MatMultTranspose(pc->mat,y,jac->w1);
834:         VecWAXPY(jac->w2,-1.0,jac->w1,x);
835:         FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);
836:       }
837:     } else {
838:       while (ilink->next) {   /* get to last entry in linked list */
839:         ilink = ilink->next;
840:       }
841:       FieldSplitSplitSolveAddTranspose(ilink,x,y);
842:       while (ilink->previous) {
843:         ilink = ilink->previous;
844:         MatMultTranspose(pc->mat,y,jac->w1);
845:         VecWAXPY(jac->w2,-1.0,jac->w1,x);
846:         FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);
847:       }
848:     }
849:   }
850:   CHKMEMQ;
851:   return(0);
852: }

856: static PetscErrorCode PCReset_FieldSplit(PC pc)
857: {
858:   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
859:   PetscErrorCode    ierr;
860:   PC_FieldSplitLink ilink = jac->head,next;

863:   while (ilink) {
864:     KSPReset(ilink->ksp);
865:     VecDestroy(&ilink->x);
866:     VecDestroy(&ilink->y);
867:     VecScatterDestroy(&ilink->sctx);
868:     ISDestroy(&ilink->is);
869:     ISDestroy(&ilink->is_col);
870:     next = ilink->next;
871:     ilink = next;
872:   }
873:   PetscFree2(jac->x,jac->y);
874:   if (jac->mat && jac->mat != jac->pmat) {
875:     MatDestroyMatrices(jac->nsplits,&jac->mat);
876:   } else if (jac->mat) {
877:     jac->mat = PETSC_NULL;
878:   }
879:   if (jac->pmat) {MatDestroyMatrices(jac->nsplits,&jac->pmat);}
880:   if (jac->Afield) {MatDestroyMatrices(jac->nsplits,&jac->Afield);}
881:   VecDestroy(&jac->w1);
882:   VecDestroy(&jac->w2);
883:   MatDestroy(&jac->schur);
884:   MatDestroy(&jac->schur_user);
885:   KSPDestroy(&jac->kspschur);
886:   MatDestroy(&jac->B);
887:   MatDestroy(&jac->C);
888:   jac->reset = PETSC_TRUE;
889:   return(0);
890: }

894: static PetscErrorCode PCDestroy_FieldSplit(PC pc)
895: {
896:   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
897:   PetscErrorCode    ierr;
898:   PC_FieldSplitLink ilink = jac->head,next;

901:   PCReset_FieldSplit(pc);
902:   while (ilink) {
903:     KSPDestroy(&ilink->ksp);
904:     next = ilink->next;
905:     PetscFree(ilink->splitname);
906:     PetscFree(ilink->fields);
907:     PetscFree(ilink->fields_col);
908:     PetscFree(ilink);
909:     ilink = next;
910:   }
911:   PetscFree2(jac->x,jac->y);
912:   PetscFree(pc->data);
913:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitGetSubKSP_C","",PETSC_NULL);
914:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetFields_C","",PETSC_NULL);
915:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetIS_C","",PETSC_NULL);
916:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetType_C","",PETSC_NULL);
917:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetBlockSize_C","",PETSC_NULL);
918:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSchurPrecondition_C","",PETSC_NULL);
919:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetSchurFactType_C","",PETSC_NULL);
920:   return(0);
921: }

925: static PetscErrorCode PCSetFromOptions_FieldSplit(PC pc)
926: {
927:   PetscErrorCode  ierr;
928:   PetscInt        bs;
929:   PetscBool       flg,stokes = PETSC_FALSE;
930:   PC_FieldSplit   *jac = (PC_FieldSplit*)pc->data;
931:   PCCompositeType ctype;
932:   DM              ddm;
933:   char            ddm_name[1025];

936:   PetscOptionsHead("FieldSplit options");
937:   if(pc->dm) {
938:     /* Allow the user to request a decomposition DM by name */
939:     PetscStrncpy(ddm_name, "", 1024);
940:     PetscOptionsString("-pc_fieldsplit_decomposition", "Name of the DM defining the composition", "PCSetDM", ddm_name, ddm_name,1024,&flg);
941:     if(flg) {
942:       DMCreateFieldDecompositionDM(pc->dm, ddm_name, &ddm);
943:       if(!ddm) {
944:         SETERRQ1(((PetscObject)pc)->comm, PETSC_ERR_ARG_WRONGSTATE, "Uknown field decomposition name %s", ddm_name);
945:       }
946:       PetscInfo(pc,"Using field decomposition DM defined using options database\n");
947:       PCSetDM(pc,ddm);
948:     }
949:   }
950:   PetscOptionsBool("-pc_fieldsplit_real_diagonal","Use diagonal blocks of the operator","PCFieldSplitSetRealDiagonal",jac->realdiagonal,&jac->realdiagonal,PETSC_NULL);
951:   PetscOptionsInt("-pc_fieldsplit_block_size","Blocksize that defines number of fields","PCFieldSplitSetBlockSize",jac->bs,&bs,&flg);
952:   if (flg) {
953:     PCFieldSplitSetBlockSize(pc,bs);
954:   }

956:   PetscOptionsGetBool(((PetscObject)pc)->prefix,"-pc_fieldsplit_detect_saddle_point",&stokes,PETSC_NULL);
957:   if (stokes) {
958:     PCFieldSplitSetType(pc,PC_COMPOSITE_SCHUR);
959:     jac->schurpre = PC_FIELDSPLIT_SCHUR_PRE_SELF;
960:   }

962:   PetscOptionsEnum("-pc_fieldsplit_type","Type of composition","PCFieldSplitSetType",PCCompositeTypes,(PetscEnum)jac->type,(PetscEnum*)&ctype,&flg);
963:   if (flg) {
964:     PCFieldSplitSetType(pc,ctype);
965:   }
966:   /* Only setup fields once */
967:   if ((jac->bs > 0) && (jac->nsplits == 0)) {
968:     /* only allow user to set fields from command line if bs is already known.
969:        otherwise user can set them in PCFieldSplitSetDefaults() */
970:     PCFieldSplitSetRuntimeSplits_Private(pc);
971:     if (jac->splitdefined) {PetscInfo(pc,"Splits defined using the options database\n");}
972:   }
973:   if (jac->type == PC_COMPOSITE_SCHUR) {
974:     PetscOptionsGetEnum(((PetscObject)pc)->prefix,"-pc_fieldsplit_schur_factorization_type",PCFieldSplitSchurFactTypes,(PetscEnum*)&jac->schurfactorization,&flg);
975:     if (flg) {PetscInfo(pc,"Deprecated use of -pc_fieldsplit_schur_factorization_type\n");}
976:     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);
977:     PetscOptionsEnum("-pc_fieldsplit_schur_precondition","How to build preconditioner for Schur complement","PCFieldSplitSchurPrecondition",PCFieldSplitSchurPreTypes,(PetscEnum)jac->schurpre,(PetscEnum*)&jac->schurpre,PETSC_NULL);
978:   }
979:   PetscOptionsTail();
980:   return(0);
981: }

983: /*------------------------------------------------------------------------------------*/

985: EXTERN_C_BEGIN
988: PetscErrorCode  PCFieldSplitSetFields_FieldSplit(PC pc,const char splitname[],PetscInt n,const PetscInt *fields,const PetscInt *fields_col)
989: {
990:   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
991:   PetscErrorCode    ierr;
992:   PC_FieldSplitLink ilink,next = jac->head;
993:   char              prefix[128];
994:   PetscInt          i;

997:   if (jac->splitdefined) {
998:     PetscInfo1(pc,"Ignoring new split \"%s\" because the splits have already been defined\n",splitname);
999:     return(0);
1000:   }
1001:   for (i=0; i<n; i++) {
1002:     if (fields[i] >= jac->bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Field %D requested but only %D exist",fields[i],jac->bs);
1003:     if (fields[i] < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative field %D requested",fields[i]);
1004:   }
1005:   PetscNew(struct _PC_FieldSplitLink,&ilink);
1006:   if (splitname) {
1007:     PetscStrallocpy(splitname,&ilink->splitname);
1008:   } else {
1009:     PetscMalloc(3*sizeof(char),&ilink->splitname);
1010:     PetscSNPrintf(ilink->splitname,2,"%s",jac->nsplits);
1011:   }
1012:   PetscMalloc(n*sizeof(PetscInt),&ilink->fields);
1013:   PetscMemcpy(ilink->fields,fields,n*sizeof(PetscInt));
1014:   PetscMalloc(n*sizeof(PetscInt),&ilink->fields_col);
1015:   PetscMemcpy(ilink->fields_col,fields_col,n*sizeof(PetscInt));
1016:   ilink->nfields = n;
1017:   ilink->next    = PETSC_NULL;
1018:   KSPCreate(((PetscObject)pc)->comm,&ilink->ksp);
1019:   PetscObjectIncrementTabLevel((PetscObject)ilink->ksp,(PetscObject)pc,1);
1020:   KSPSetType(ilink->ksp,KSPPREONLY);
1021:   PetscLogObjectParent((PetscObject)pc,(PetscObject)ilink->ksp);

1023:   PetscSNPrintf(prefix,sizeof prefix,"%sfieldsplit_%s_",((PetscObject)pc)->prefix?((PetscObject)pc)->prefix:"",ilink->splitname);
1024:   KSPSetOptionsPrefix(ilink->ksp,prefix);

1026:   if (!next) {
1027:     jac->head       = ilink;
1028:     ilink->previous = PETSC_NULL;
1029:   } else {
1030:     while (next->next) {
1031:       next = next->next;
1032:     }
1033:     next->next      = ilink;
1034:     ilink->previous = next;
1035:   }
1036:   jac->nsplits++;
1037:   return(0);
1038: }
1039: EXTERN_C_END

1041: EXTERN_C_BEGIN
1044: PetscErrorCode  PCFieldSplitGetSubKSP_FieldSplit_Schur(PC pc,PetscInt *n,KSP **subksp)
1045: {
1046:   PC_FieldSplit *jac = (PC_FieldSplit*)pc->data;

1050:   PetscMalloc(jac->nsplits*sizeof(KSP),subksp);
1051:   MatSchurComplementGetKSP(jac->schur,*subksp);
1052:   (*subksp)[1] = jac->kspschur;
1053:   if (n) *n = jac->nsplits;
1054:   return(0);
1055: }
1056: EXTERN_C_END

1058: EXTERN_C_BEGIN
1061: PetscErrorCode  PCFieldSplitGetSubKSP_FieldSplit(PC pc,PetscInt *n,KSP **subksp)
1062: {
1063:   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
1064:   PetscErrorCode    ierr;
1065:   PetscInt          cnt = 0;
1066:   PC_FieldSplitLink ilink = jac->head;

1069:   PetscMalloc(jac->nsplits*sizeof(KSP),subksp);
1070:   while (ilink) {
1071:     (*subksp)[cnt++] = ilink->ksp;
1072:     ilink = ilink->next;
1073:   }
1074:   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);
1075:   if (n) *n = jac->nsplits;
1076:   return(0);
1077: }
1078: EXTERN_C_END

1080: EXTERN_C_BEGIN
1083: PetscErrorCode  PCFieldSplitSetIS_FieldSplit(PC pc,const char splitname[],IS is)
1084: {
1085:   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
1086:   PetscErrorCode    ierr;
1087:   PC_FieldSplitLink ilink, next = jac->head;
1088:   char              prefix[128];

1091:   if (jac->splitdefined) {
1092:     PetscInfo1(pc,"Ignoring new split \"%s\" because the splits have already been defined\n",splitname);
1093:     return(0);
1094:   }
1095:   PetscNew(struct _PC_FieldSplitLink,&ilink);
1096:   if (splitname) {
1097:     PetscStrallocpy(splitname,&ilink->splitname);
1098:   } else {
1099:     PetscMalloc(8*sizeof(char),&ilink->splitname);
1100:     PetscSNPrintf(ilink->splitname,7,"%D",jac->nsplits);
1101:   }
1102:   PetscObjectReference((PetscObject)is);
1103:   ISDestroy(&ilink->is);
1104:   ilink->is      = is;
1105:   PetscObjectReference((PetscObject)is);
1106:   ISDestroy(&ilink->is_col);
1107:   ilink->is_col  = is;
1108:   ilink->next    = PETSC_NULL;
1109:   KSPCreate(((PetscObject)pc)->comm,&ilink->ksp);
1110:   PetscObjectIncrementTabLevel((PetscObject)ilink->ksp,(PetscObject)pc,1);
1111:   KSPSetType(ilink->ksp,KSPPREONLY);
1112:   PetscLogObjectParent((PetscObject)pc,(PetscObject)ilink->ksp);

1114:   PetscSNPrintf(prefix,sizeof prefix,"%sfieldsplit_%s_",((PetscObject)pc)->prefix?((PetscObject)pc)->prefix:"",ilink->splitname);
1115:   KSPSetOptionsPrefix(ilink->ksp,prefix);

1117:   if (!next) {
1118:     jac->head       = ilink;
1119:     ilink->previous = PETSC_NULL;
1120:   } else {
1121:     while (next->next) {
1122:       next = next->next;
1123:     }
1124:     next->next      = ilink;
1125:     ilink->previous = next;
1126:   }
1127:   jac->nsplits++;

1129:   return(0);
1130: }
1131: EXTERN_C_END

1135: /*@
1136:     PCFieldSplitSetFields - Sets the fields for one particular split in the field split preconditioner

1138:     Logically Collective on PC

1140:     Input Parameters:
1141: +   pc  - the preconditioner context
1142: .   splitname - name of this split, if PETSC_NULL the number of the split is used
1143: .   n - the number of fields in this split
1144: -   fields - the fields in this split

1146:     Level: intermediate

1148:     Notes: Use PCFieldSplitSetIS() to set a completely general set of indices as a field. 

1150:      The PCFieldSplitSetFields() is for defining fields as a strided blocks. For example, if the block
1151:      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
1152:      0xx3xx6xx9xx12 ... x1xx4xx7xx ... xx2xx5xx8xx.. 01x34x67x... 0x1x3x5x7.. x12x45x78x....
1153:      where the numbered entries indicate what is in the field. 

1155:      This function is called once per split (it creates a new split each time).  Solve options
1156:      for this split will be available under the prefix -fieldsplit_SPLITNAME_.

1158:      Developer Note: This routine does not actually create the IS representing the split, that is delayed 
1159:      until PCSetUp_FieldSplit(), because information about the vector/matrix layouts may not be 
1160:      available when this routine is called.

1162: .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetBlockSize(), PCFieldSplitSetIS()

1164: @*/
1165: PetscErrorCode  PCFieldSplitSetFields(PC pc,const char splitname[],PetscInt n,const PetscInt *fields,const PetscInt *fields_col)
1166: {

1172:   if (n < 1) SETERRQ2(((PetscObject)pc)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Provided number of fields %D in split \"%s\" not positive",n,splitname);
1174:   PetscTryMethod(pc,"PCFieldSplitSetFields_C",(PC,const char[],PetscInt,const PetscInt *,const PetscInt *),(pc,splitname,n,fields,fields_col));
1175:   return(0);
1176: }

1180: /*@
1181:     PCFieldSplitSetIS - Sets the exact elements for field

1183:     Logically Collective on PC

1185:     Input Parameters:
1186: +   pc  - the preconditioner context
1187: .   splitname - name of this split, if PETSC_NULL the number of the split is used
1188: -   is - the index set that defines the vector elements in this field


1191:     Notes:
1192:     Use PCFieldSplitSetFields(), for fields defined by strided types.

1194:     This function is called once per split (it creates a new split each time).  Solve options
1195:     for this split will be available under the prefix -fieldsplit_SPLITNAME_.

1197:     Level: intermediate

1199: .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetBlockSize()

1201: @*/
1202: PetscErrorCode  PCFieldSplitSetIS(PC pc,const char splitname[],IS is)
1203: {

1210:   PetscTryMethod(pc,"PCFieldSplitSetIS_C",(PC,const char[],IS),(pc,splitname,is));
1211:   return(0);
1212: }

1216: /*@
1217:     PCFieldSplitGetIS - Retrieves the elements for a field as an IS

1219:     Logically Collective on PC

1221:     Input Parameters:
1222: +   pc  - the preconditioner context
1223: -   splitname - name of this split

1225:     Output Parameter:
1226: -   is - the index set that defines the vector elements in this field, or PETSC_NULL if the field is not found

1228:     Level: intermediate

1230: .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetIS()

1232: @*/
1233: PetscErrorCode PCFieldSplitGetIS(PC pc,const char splitname[],IS *is)
1234: {

1241:   {
1242:     PC_FieldSplit    *jac   = (PC_FieldSplit *) pc->data;
1243:     PC_FieldSplitLink ilink = jac->head;
1244:     PetscBool         found;

1246:     *is = PETSC_NULL;
1247:     while(ilink) {
1248:       PetscStrcmp(ilink->splitname, splitname, &found);
1249:       if (found) {
1250:         *is = ilink->is;
1251:         break;
1252:       }
1253:       ilink = ilink->next;
1254:     }
1255:   }
1256:   return(0);
1257: }

1261: /*@
1262:     PCFieldSplitSetBlockSize - Sets the block size for defining where fields start in the 
1263:       fieldsplit preconditioner. If not set the matrix block size is used.

1265:     Logically Collective on PC

1267:     Input Parameters:
1268: +   pc  - the preconditioner context
1269: -   bs - the block size

1271:     Level: intermediate

1273: .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetFields()

1275: @*/
1276: PetscErrorCode  PCFieldSplitSetBlockSize(PC pc,PetscInt bs)
1277: {

1283:   PetscTryMethod(pc,"PCFieldSplitSetBlockSize_C",(PC,PetscInt),(pc,bs));
1284:   return(0);
1285: }

1289: /*@C
1290:    PCFieldSplitGetSubKSP - Gets the KSP contexts for all splits
1291:    
1292:    Collective on KSP

1294:    Input Parameter:
1295: .  pc - the preconditioner context

1297:    Output Parameters:
1298: +  n - the number of splits
1299: -  pc - the array of KSP contexts

1301:    Note:  
1302:    After PCFieldSplitGetSubKSP() the array of KSPs IS to be freed by the user
1303:    (not the KSP just the array that contains them).

1305:    You must call KSPSetUp() before calling PCFieldSplitGetSubKSP().

1307:    Level: advanced

1309: .seealso: PCFIELDSPLIT
1310: @*/
1311: PetscErrorCode  PCFieldSplitGetSubKSP(PC pc,PetscInt *n,KSP *subksp[])
1312: {

1318:   PetscUseMethod(pc,"PCFieldSplitGetSubKSP_C",(PC,PetscInt*,KSP **),(pc,n,subksp));
1319:   return(0);
1320: }

1324: /*@
1325:     PCFieldSplitSchurPrecondition -  Indicates if the Schur complement is preconditioned by a preconditioner constructed by the
1326:       A11 matrix. Otherwise no preconditioner is used.

1328:     Collective on PC

1330:     Input Parameters:
1331: +   pc  - the preconditioner context
1332: .   ptype - which matrix to use for preconditioning the Schur complement, PC_FIELDSPLIT_SCHUR_PRE_DIAG (diag) is default
1333: -   userpre - matrix to use for preconditioning, or PETSC_NULL

1335:     Options Database:
1336: .     -pc_fieldsplit_schur_precondition <self,user,diag> default is diag

1338:     Notes:
1339: $    If ptype is 
1340: $        user then the preconditioner for the Schur complement is generated by the provided matrix (pre argument
1341: $             to this function). 
1342: $        diag then the preconditioner for the Schur complement is generated by the block diagonal part of the original
1343: $             matrix associated with the Schur complement (i.e. A11)
1344: $        self the preconditioner for the Schur complement is generated from the Schur complement matrix itself:
1345: $             The only preconditioner that currently works directly with the Schur complement matrix object is the PCLSC 
1346: $             preconditioner

1348:      When solving a saddle point problem, where the A11 block is identically zero, using diag as the ptype only makes sense
1349:     with the additional option -fieldsplit_1_pc_type none. Usually for saddle point problems one would use a ptype of self and 
1350:     -fieldsplit_1_pc_type lsc which uses the least squares commutator compute a preconditioner for the Schur complement.
1351:     
1352:     Developer Notes: This is a terrible name, gives no good indication of what the function does and should also have Set in 
1353:      the name since it sets a proceedure to use.
1354:     
1355:     Level: intermediate

1357: .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetFields(), PCFieldSplitSchurPreType, PCLSC

1359: @*/
1360: PetscErrorCode  PCFieldSplitSchurPrecondition(PC pc,PCFieldSplitSchurPreType ptype,Mat pre)
1361: {

1366:   PetscTryMethod(pc,"PCFieldSplitSchurPrecondition_C",(PC,PCFieldSplitSchurPreType,Mat),(pc,ptype,pre));
1367:   return(0);
1368: }

1370: EXTERN_C_BEGIN
1373: PetscErrorCode  PCFieldSplitSchurPrecondition_FieldSplit(PC pc,PCFieldSplitSchurPreType ptype,Mat pre)
1374: {
1375:   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
1376:   PetscErrorCode  ierr;

1379:   jac->schurpre = ptype;
1380:   if (pre) {
1381:     MatDestroy(&jac->schur_user);
1382:     jac->schur_user = pre;
1383:     PetscObjectReference((PetscObject)jac->schur_user);
1384:   }
1385:   return(0);
1386: }
1387: EXTERN_C_END

1391: /*@
1392:     PCFieldSplitSetSchurFactType -  sets which blocks of the approximate block factorization to retain

1394:     Collective on PC

1396:     Input Parameters:
1397: +   pc  - the preconditioner context
1398: -   ftype - which blocks of factorization to retain, PC_FIELDSPLIT_SCHUR_FACT_FULL is default

1400:     Options Database:
1401: .     -pc_fieldsplit_schur_fact_type <diag,lower,upper,full> default is full


1404:     Level: intermediate

1406:     Notes:
1407:     The FULL factorization is

1409: $   (A   B)  = (1       0) (A   0) (1  Ainv*B)
1410: $   (C   D)    (C*Ainv  1) (0   S) (0     1  )

1412:     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, 
1413:     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).

1415:     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 
1416:     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 
1417:     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, 
1418:     the preconditioned operator has three distinct nonzero eigenvalues and minimal polynomial of degree at most 4, so KSPGMRES converges in at most 4 iterations.

1420:     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 
1421:     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).

1423:     References:
1424:     Murphy, Golub, and Wathen, A note on preconditioning indefinite linear systems, SIAM J. Sci. Comput., 21 (2000) pp. 1969-1972.

1426:     Ipsen, A note on preconditioning nonsymmetric matrices, SIAM J. Sci. Comput., 23 (2001), pp. 1050-1051.

1428: .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetFields(), PCFieldSplitSchurPreType
1429: @*/
1430: PetscErrorCode  PCFieldSplitSetSchurFactType(PC pc,PCFieldSplitSchurFactType ftype)
1431: {

1436:   PetscTryMethod(pc,"PCFieldSplitSetSchurFactType_C",(PC,PCFieldSplitSchurFactType),(pc,ftype));
1437:   return(0);
1438: }

1443: {
1444:   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;

1447:   jac->schurfactorization = ftype;
1448:   return(0);
1449: }

1453: /*@C
1454:    PCFieldSplitGetSchurBlocks - Gets all matrix blocks for the Schur complement
1455:    
1456:    Collective on KSP

1458:    Input Parameter:
1459: .  pc - the preconditioner context

1461:    Output Parameters:
1462: +  A00 - the (0,0) block
1463: .  A01 - the (0,1) block
1464: .  A10 - the (1,0) block
1465: -  A11 - the (1,1) block

1467:    Level: advanced

1469: .seealso: PCFIELDSPLIT
1470: @*/
1471: PetscErrorCode  PCFieldSplitGetSchurBlocks(PC pc,Mat *A00,Mat *A01,Mat *A10, Mat *A11)
1472: {
1473:   PC_FieldSplit *jac = (PC_FieldSplit *) pc->data;

1477:   if (jac->type != PC_COMPOSITE_SCHUR) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ARG_WRONG, "FieldSplit is not using a Schur complement approach.");
1478:   if (A00) *A00 = jac->pmat[0];
1479:   if (A01) *A01 = jac->B;
1480:   if (A10) *A10 = jac->C;
1481:   if (A11) *A11 = jac->pmat[1];
1482:   return(0);
1483: }

1485: EXTERN_C_BEGIN
1488: PetscErrorCode  PCFieldSplitSetType_FieldSplit(PC pc,PCCompositeType type)
1489: {
1490:   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;

1494:   jac->type = type;
1495:   if (type == PC_COMPOSITE_SCHUR) {
1496:     pc->ops->apply = PCApply_FieldSplit_Schur;
1497:     pc->ops->view  = PCView_FieldSplit_Schur;
1498:     PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitGetSubKSP_C","PCFieldSplitGetSubKSP_FieldSplit_Schur",PCFieldSplitGetSubKSP_FieldSplit_Schur);
1499:     PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSchurPrecondition_C","PCFieldSplitSchurPrecondition_FieldSplit",PCFieldSplitSchurPrecondition_FieldSplit);
1500:     PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetSchurFactType_C","PCFieldSplitSetSchurFactType_FieldSplit",PCFieldSplitSetSchurFactType_FieldSplit);

1502:   } else {
1503:     pc->ops->apply = PCApply_FieldSplit;
1504:     pc->ops->view  = PCView_FieldSplit;
1505:     PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitGetSubKSP_C","PCFieldSplitGetSubKSP_FieldSplit",PCFieldSplitGetSubKSP_FieldSplit);
1506:     PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSchurPrecondition_C","",0);
1507:     PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetSchurFactType_C","",0);
1508:   }
1509:   return(0);
1510: }
1511: EXTERN_C_END

1513: EXTERN_C_BEGIN
1516: PetscErrorCode  PCFieldSplitSetBlockSize_FieldSplit(PC pc,PetscInt bs)
1517: {
1518:   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;

1521:   if (bs < 1) SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Blocksize must be positive, you gave %D",bs);
1522:   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);
1523:   jac->bs = bs;
1524:   return(0);
1525: }
1526: EXTERN_C_END

1530: /*@
1531:    PCFieldSplitSetType - Sets the type of fieldsplit preconditioner.
1532:    
1533:    Collective on PC

1535:    Input Parameter:
1536: .  pc - the preconditioner context
1537: .  type - PC_COMPOSITE_ADDITIVE, PC_COMPOSITE_MULTIPLICATIVE (default), PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE, PC_COMPOSITE_SPECIAL, PC_COMPOSITE_SCHUR

1539:    Options Database Key:
1540: .  -pc_fieldsplit_type <type: one of multiplicative, additive, symmetric_multiplicative, special, schur> - Sets fieldsplit preconditioner type

1542:    Level: Intermediate

1544: .keywords: PC, set, type, composite preconditioner, additive, multiplicative

1546: .seealso: PCCompositeSetType()

1548: @*/
1549: PetscErrorCode  PCFieldSplitSetType(PC pc,PCCompositeType type)
1550: {

1555:   PetscTryMethod(pc,"PCFieldSplitSetType_C",(PC,PCCompositeType),(pc,type));
1556:   return(0);
1557: }

1561: /*@
1562:   PCFieldSplitGetType - Gets the type of fieldsplit preconditioner.

1564:   Not collective

1566:   Input Parameter:
1567: . pc - the preconditioner context

1569:   Output Parameter:
1570: . type - PC_COMPOSITE_ADDITIVE, PC_COMPOSITE_MULTIPLICATIVE (default), PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE, PC_COMPOSITE_SPECIAL, PC_COMPOSITE_SCHUR

1572:   Level: Intermediate

1574: .keywords: PC, set, type, composite preconditioner, additive, multiplicative
1575: .seealso: PCCompositeSetType()
1576: @*/
1577: PetscErrorCode PCFieldSplitGetType(PC pc, PCCompositeType *type)
1578: {
1579:   PC_FieldSplit *jac = (PC_FieldSplit *) pc->data;

1584:   *type = jac->type;
1585:   return(0);
1586: }

1588: /* -------------------------------------------------------------------------------------*/
1589: /*MC
1590:    PCFIELDSPLIT - Preconditioner created by combining separate preconditioners for individual
1591:                   fields or groups of fields. See the users manual section "Solving Block Matrices" for more details.

1593:      To set options on the solvers for each block append -fieldsplit_ to all the PC
1594:         options database keys. For example, -fieldsplit_pc_type ilu -fieldsplit_pc_factor_levels 1
1595:         
1596:      To set the options on the solvers separate for each block call PCFieldSplitGetSubKSP()
1597:          and set the options directly on the resulting KSP object

1599:    Level: intermediate

1601:    Options Database Keys:
1602: +   -pc_fieldsplit_%d_fields <a,b,..> - indicates the fields to be used in the %d'th split
1603: .   -pc_fieldsplit_default - automatically add any fields to additional splits that have not
1604:                               been supplied explicitly by -pc_fieldsplit_%d_fields
1605: .   -pc_fieldsplit_block_size <bs> - size of block that defines fields (i.e. there are bs fields)
1606: .   -pc_fieldsplit_type <additive,multiplicative,symmetric_multiplicative,schur> - type of relaxation or factorization splitting
1607: .   -pc_fieldsplit_schur_precondition <self,user,diag> - default is diag
1608: .   -pc_fieldsplit_detect_saddle_point - automatically finds rows with zero or negative diagonal and uses Schur complement with no preconditioner as the solver

1610: -    Options prefix for inner solvers when using Schur complement preconditioner are -fieldsplit_0_ and -fieldsplit_1_
1611:      for all other solvers they are -fieldsplit_%d_ for the dth field, use -fieldsplit_ for all fields

1613:    Notes:
1614:     Use PCFieldSplitSetFields() to set fields defined by "strided" entries and PCFieldSplitSetIS()
1615:      to define a field by an arbitrary collection of entries.

1617:       If no fields are set the default is used. The fields are defined by entries strided by bs,
1618:       beginning at 0 then 1, etc to bs-1. The block size can be set with PCFieldSplitSetBlockSize(),
1619:       if this is not called the block size defaults to the blocksize of the second matrix passed
1620:       to KSPSetOperators()/PCSetOperators().

1622: $     For the Schur complement preconditioner if J = ( A00 A01 )
1623: $                                                    ( A10 A11 )
1624: $     the preconditioner using full factorization is
1625: $              ( I   -A10 ksp(A00) ) ( inv(A00)     0  ) (     I          0  )
1626: $              ( 0         I       ) (   0      ksp(S) ) ( -A10 ksp(A00)  I  )
1627:      where the action of inv(A00) is applied using the KSP solver with prefix -fieldsplit_0_. The action of
1628:      ksp(S) is computed using the KSP solver with prefix -fieldsplit_splitname_ (where splitname was given
1629:      in providing the SECOND split or 1 if not give). For PCFieldSplitGetKSP() when field number is 0,
1630:      it returns the KSP associated with -fieldsplit_0_ while field number 1 gives -fieldsplit_1_ KSP. By default
1631:      A11 is used to construct a preconditioner for S, use PCFieldSplitSchurPrecondition() to turn on or off this
1632:      option. You can use the preconditioner PCLSC to precondition the Schur complement with -fieldsplit_1_pc_type lsc. The
1633:      factorization type is set using -pc_fieldsplit_schur_fact_type <diag, lower, upper, full>. The full is shown above,
1634:      diag gives
1635: $              ( inv(A00)     0   )
1636: $              (   0      -ksp(S) )
1637:      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
1638: $              (  A00   0 )
1639: $              (  A10   S )
1640:      where the inverses of A00 and S are applied using KSPs. The upper factorization is the inverse of
1641: $              ( A00 A01 )
1642: $              (  0   S  )
1643:      where again the inverses of A00 and S are applied using KSPs.

1645:      If only one set of indices (one IS) is provided with PCFieldSplitSetIS() then the complement of that IS
1646:      is used automatically for a second block.

1648:      The fieldsplit preconditioner cannot currently be used with the BAIJ or SBAIJ data formats if the blocksize is larger than 1. 
1649:      Generally it should be used with the AIJ format.

1651:      The forms of these preconditioners are closely related if not identical to forms derived as "Distributive Iterations", see, 
1652:      for example, page 294 in "Principles of Computational Fluid Dynamics" by Pieter Wesseling. Note that one can also use PCFIELDSPLIT 
1653:      inside a smoother resulting in "Distributive Smoothers".

1655:    Concepts: physics based preconditioners, block preconditioners

1657: .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC, Block_Preconditioners, PCLSC,
1658:            PCFieldSplitGetSubKSP(), PCFieldSplitSetFields(), PCFieldSplitSetType(), PCFieldSplitSetIS(), PCFieldSplitSchurPrecondition()
1659: M*/

1661: EXTERN_C_BEGIN
1664: PetscErrorCode  PCCreate_FieldSplit(PC pc)
1665: {
1667:   PC_FieldSplit  *jac;

1670:   PetscNewLog(pc,PC_FieldSplit,&jac);
1671:   jac->bs        = -1;
1672:   jac->nsplits   = 0;
1673:   jac->type      = PC_COMPOSITE_MULTIPLICATIVE;
1674:   jac->schurpre  = PC_FIELDSPLIT_SCHUR_PRE_USER; /* Try user preconditioner first, fall back on diagonal */
1675:   jac->schurfactorization = PC_FIELDSPLIT_SCHUR_FACT_FULL;

1677:   pc->data     = (void*)jac;

1679:   pc->ops->apply             = PCApply_FieldSplit;
1680:   pc->ops->applytranspose    = PCApplyTranspose_FieldSplit;
1681:   pc->ops->setup             = PCSetUp_FieldSplit;
1682:   pc->ops->reset             = PCReset_FieldSplit;
1683:   pc->ops->destroy           = PCDestroy_FieldSplit;
1684:   pc->ops->setfromoptions    = PCSetFromOptions_FieldSplit;
1685:   pc->ops->view              = PCView_FieldSplit;
1686:   pc->ops->applyrichardson   = 0;

1688:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitGetSubKSP_C","PCFieldSplitGetSubKSP_FieldSplit",
1689:                     PCFieldSplitGetSubKSP_FieldSplit);
1690:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetFields_C","PCFieldSplitSetFields_FieldSplit",
1691:                     PCFieldSplitSetFields_FieldSplit);
1692:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetIS_C","PCFieldSplitSetIS_FieldSplit",
1693:                     PCFieldSplitSetIS_FieldSplit);
1694:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetType_C","PCFieldSplitSetType_FieldSplit",
1695:                     PCFieldSplitSetType_FieldSplit);
1696:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetBlockSize_C","PCFieldSplitSetBlockSize_FieldSplit",
1697:                     PCFieldSplitSetBlockSize_FieldSplit);
1698:   return(0);
1699: }
1700: EXTERN_C_END