Actual source code: fieldsplit.c

  1: #define PETSCKSP_DLL

  3: /*

  5: */
 6:  #include private/pcimpl.h

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

 20: typedef struct {
 21:   PCCompositeType   type;
 22:   PetscTruth        defaultsplit; /* Flag for a system with a set of 'k' scalar fields with the same layout (and bs = k) */
 23:   PetscInt          bs;           /* Block size for IS and Mat structures */
 24:   PetscInt          nsplits;      /* Number of field divisions defined */
 25:   Vec               *x,*y,w1,w2;
 26:   Mat               *pmat;        /* The diagonal block for each split */
 27:   Mat               *Afield;      /* The rows of the matrix associated with each split */
 28:   PetscTruth        issetup;
 29:   /* Only used when Schur complement preconditioning is used */
 30:   Mat               B;            /* The (0,1) block */
 31:   Mat               C;            /* The (1,0) block */
 32:   Mat               schur;        /* The Schur complement S = D - C A^{-1} B */
 33:   KSP               kspschur;     /* The solver for S */
 34:   PetscTruth        schurpre;     /* preconditioner for the Schur complement is built from pmat[1] == D */
 35:   PC_FieldSplitLink head;
 36: } PC_FieldSplit;

 38: /* 
 39:     Notes: there is no particular reason that pmat, x, and y are stored as arrays in PC_FieldSplit instead of 
 40:    inside PC_FieldSplitLink, just historical. If you want to be able to add new fields after already using the 
 41:    PC you could change this.
 42: */
 45: static PetscErrorCode PCView_FieldSplit(PC pc,PetscViewer viewer)
 46: {
 47:   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
 48:   PetscErrorCode    ierr;
 49:   PetscTruth        iascii;
 50:   PetscInt          i,j;
 51:   PC_FieldSplitLink ilink = jac->head;

 54:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
 55:   if (iascii) {
 56:     PetscViewerASCIIPrintf(viewer,"  FieldSplit with %s composition: total splits = %D, blocksize = %D\n",PCCompositeTypes[jac->type],jac->nsplits,jac->bs);
 57:     PetscViewerASCIIPrintf(viewer,"  Solver info for each split is in the following KSP objects:\n");
 58:     PetscViewerASCIIPushTab(viewer);
 59:     for (i=0; i<jac->nsplits; i++) {
 60:       if (ilink->fields) {
 61:         PetscViewerASCIIPrintf(viewer,"Split number %D Fields ",i);
 62:         PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);
 63:         for (j=0; j<ilink->nfields; j++) {
 64:           if (j > 0) {
 65:             PetscViewerASCIIPrintf(viewer,",");
 66:           }
 67:           PetscViewerASCIIPrintf(viewer," %D",ilink->fields[j]);
 68:         }
 69:         PetscViewerASCIIPrintf(viewer,"\n");
 70:         PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);
 71:       } else {
 72:         PetscViewerASCIIPrintf(viewer,"Split number %D Defined by IS\n",i);
 73:       }
 74:       KSPView(ilink->ksp,viewer);
 75:       ilink = ilink->next;
 76:     }
 77:     PetscViewerASCIIPopTab(viewer);
 78:   } else {
 79:     SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported for PCFieldSplit",((PetscObject)viewer)->type_name);
 80:   }
 81:   return(0);
 82: }

 86: static PetscErrorCode PCView_FieldSplit_Schur(PC pc,PetscViewer viewer)
 87: {
 88:   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
 89:   PetscErrorCode    ierr;
 90:   PetscTruth        iascii;
 91:   PetscInt          i,j;
 92:   PC_FieldSplitLink ilink = jac->head;
 93:   KSP               ksp;

 96:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
 97:   if (iascii) {
 98:     PetscViewerASCIIPrintf(viewer,"  FieldSplit with Schur preconditioner, blocksize = %D\n",jac->bs);
 99:     PetscViewerASCIIPrintf(viewer,"  Split info:\n");
100:     PetscViewerASCIIPushTab(viewer);
101:     for (i=0; i<jac->nsplits; i++) {
102:       if (ilink->fields) {
103:         PetscViewerASCIIPrintf(viewer,"Split number %D Fields ",i);
104:         PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);
105:         for (j=0; j<ilink->nfields; j++) {
106:           if (j > 0) {
107:             PetscViewerASCIIPrintf(viewer,",");
108:           }
109:           PetscViewerASCIIPrintf(viewer," %D",ilink->fields[j]);
110:         }
111:         PetscViewerASCIIPrintf(viewer,"\n");
112:         PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);
113:       } else {
114:         PetscViewerASCIIPrintf(viewer,"Split number %D Defined by IS\n",i);
115:       }
116:       ilink = ilink->next;
117:     }
118:     PetscViewerASCIIPrintf(viewer,"KSP solver for A block \n");
119:     MatSchurComplementGetKSP(jac->schur,&ksp);
120:     PetscViewerASCIIPushTab(viewer);
121:     KSPView(ksp,viewer);
122:     PetscViewerASCIIPopTab(viewer);
123:     PetscViewerASCIIPrintf(viewer,"KSP solver for S = D - C inv(A) B \n");
124:     PetscViewerASCIIPushTab(viewer);
125:     KSPView(jac->kspschur,viewer);
126:     PetscViewerASCIIPopTab(viewer);
127:     PetscViewerASCIIPopTab(viewer);
128:   } else {
129:     SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported for PCFieldSplit",((PetscObject)viewer)->type_name);
130:   }
131:   return(0);
132: }

136: static PetscErrorCode PCFieldSplitSetDefaults(PC pc)
137: {
138:   PC_FieldSplit     *jac  = (PC_FieldSplit*)pc->data;
139:   PetscErrorCode    ierr;
140:   PC_FieldSplitLink ilink = jac->head;
141:   PetscInt          i = 0,*ifields,nfields;
142:   PetscTruth        flg = PETSC_FALSE,*fields,flg2;
143:   char              optionname[128];

146:   if (!ilink) {

148:     if (jac->bs <= 0) {
149:       if (pc->pmat) {
150:         MatGetBlockSize(pc->pmat,&jac->bs);
151:       } else {
152:         jac->bs = 1;
153:       }
154:     }

156:     PetscOptionsGetTruth(((PetscObject)pc)->prefix,"-pc_fieldsplit_default",&flg,PETSC_NULL);
157:     if (!flg) {
158:       /* Allow user to set fields from command line,  if bs was known at the time of PCSetFromOptions_FieldSplit()
159:          then it is set there. This is not ideal because we should only have options set in XXSetFromOptions(). */
160:       flg = PETSC_TRUE; /* switched off automatically if user sets fields manually here */
161:       PetscMalloc(jac->bs*sizeof(PetscInt),&ifields);
162:       while (PETSC_TRUE) {
163:         sprintf(optionname,"-pc_fieldsplit_%d_fields",(int)i++);
164:         nfields = jac->bs;
165:         PetscOptionsGetIntArray(((PetscObject)pc)->prefix,optionname,ifields,&nfields,&flg2);
166:         if (!flg2) break;
167:         if (!nfields) SETERRQ(PETSC_ERR_USER,"Cannot list zero fields");
168:         flg = PETSC_FALSE;
169:         PCFieldSplitSetFields(pc,nfields,ifields);
170:       }
171:       PetscFree(ifields);
172:     }
173: 
174:     if (flg) {
175:       PetscInfo(pc,"Using default splitting of fields\n");
176:       PetscMalloc(jac->bs*sizeof(PetscTruth),&fields);
177:       PetscMemzero(fields,jac->bs*sizeof(PetscTruth));
178:       while (ilink) {
179:         for (i=0; i<ilink->nfields; i++) {
180:           fields[ilink->fields[i]] = PETSC_TRUE;
181:         }
182:         ilink = ilink->next;
183:       }
184:       jac->defaultsplit = PETSC_TRUE;
185:       for (i=0; i<jac->bs; i++) {
186:         if (!fields[i]) {
187:           PCFieldSplitSetFields(pc,1,&i);
188:         } else {
189:           jac->defaultsplit = PETSC_FALSE;
190:         }
191:       }
192:       PetscFree(fields);
193:     }
194:   } else if (jac->nsplits == 1) {
195:     if (ilink->is) {
196:       IS       is2;
197:       PetscInt nmin,nmax;

199:       MatGetOwnershipRange(pc->mat,&nmin,&nmax);
200:       ISComplement(ilink->is,nmin,nmax,&is2);
201:       PCFieldSplitSetIS(pc,is2);
202:       ISDestroy(is2);
203:     } else {
204:       SETERRQ(PETSC_ERR_SUP,"Must provide at least two sets of fields to PCFieldSplit()");
205:     }
206:   }
207:   return(0);
208: }


213: static PetscErrorCode PCSetUp_FieldSplit(PC pc)
214: {
215:   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
216:   PetscErrorCode    ierr;
217:   PC_FieldSplitLink ilink;
218:   PetscInt          i,nsplit,ccsize;
219:   MatStructure      flag = pc->flag;
220:   PetscTruth        sorted,getsub;

223:   PCFieldSplitSetDefaults(pc);
224:   nsplit = jac->nsplits;
225:   ilink  = jac->head;

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

231:     jac->issetup = PETSC_TRUE;

233:     /* This is done here instead of in PCFieldSplitSetFields() because may not have matrix at that point */
234:     bs     = jac->bs;
235:     MatGetOwnershipRange(pc->pmat,&rstart,&rend);
236:     MatGetLocalSize(pc->pmat,PETSC_NULL,&ccsize);
237:     nslots = (rend - rstart)/bs;
238:     for (i=0; i<nsplit; i++) {
239:       if (jac->defaultsplit) {
240:         ISCreateStride(((PetscObject)pc)->comm,nslots,rstart+i,nsplit,&ilink->is);
241:       } else if (!ilink->is) {
242:         if (ilink->nfields > 1) {
243:           PetscInt   *ii,j,k,nfields = ilink->nfields,*fields = ilink->fields;
244:           PetscMalloc(ilink->nfields*nslots*sizeof(PetscInt),&ii);
245:           for (j=0; j<nslots; j++) {
246:             for (k=0; k<nfields; k++) {
247:               ii[nfields*j + k] = rstart + bs*j + fields[k];
248:             }
249:           }
250:           ISCreateGeneral(((PetscObject)pc)->comm,nslots*nfields,ii,&ilink->is);
251:           PetscFree(ii);
252:         } else {
253:           ISCreateStride(((PetscObject)pc)->comm,nslots,rstart+ilink->fields[0],bs,&ilink->is);
254:         }
255:       }
256:       ISGetLocalSize(ilink->is,&ilink->csize);
257:       ISSorted(ilink->is,&sorted);
258:       if (!sorted) SETERRQ(PETSC_ERR_USER,"Fields must be sorted when creating split");
259:       ISAllGather(ilink->is,&ilink->cis);
260:       ilink = ilink->next;
261:     }
262:   }
263: 
264:   ilink  = jac->head;
265:   if (!jac->pmat) {
266:     PetscMalloc(nsplit*sizeof(Mat),&jac->pmat);
267:     for (i=0; i<nsplit; i++) {
268:       MatGetSubMatrix(pc->pmat,ilink->is,ilink->cis,ilink->csize,MAT_INITIAL_MATRIX,&jac->pmat[i]);
269:       ilink = ilink->next;
270:     }
271:   } else {
272:     for (i=0; i<nsplit; i++) {
273:       MatGetSubMatrix(pc->pmat,ilink->is,ilink->cis,ilink->csize,MAT_REUSE_MATRIX,&jac->pmat[i]);
274:       ilink = ilink->next;
275:     }
276:   }

278:   /* extract the rows of the matrix associated with each field: used for efficient computation of residual inside algorithm */
279:   MatHasOperation(pc->mat,MATOP_GET_SUBMATRIX,&getsub);
280:   if (getsub && jac->type != PC_COMPOSITE_ADDITIVE  && jac->type != PC_COMPOSITE_SCHUR) {
281:     ilink  = jac->head;
282:     if (!jac->Afield) {
283:       PetscMalloc(nsplit*sizeof(Mat),&jac->Afield);
284:       for (i=0; i<nsplit; i++) {
285:         MatGetSubMatrix(pc->mat,ilink->is,PETSC_NULL,PETSC_DECIDE,MAT_INITIAL_MATRIX,&jac->Afield[i]);
286:         ilink = ilink->next;
287:       }
288:     } else {
289:       for (i=0; i<nsplit; i++) {
290:         MatGetSubMatrix(pc->mat,ilink->is,PETSC_NULL,PETSC_DECIDE,MAT_REUSE_MATRIX,&jac->Afield[i]);
291:         ilink = ilink->next;
292:       }
293:     }
294:   }

296:   if (jac->type == PC_COMPOSITE_SCHUR) {
297:     IS       ccis;
298:     PetscInt N,nlocal,nis;
299:     if (nsplit != 2) SETERRQ(PETSC_ERR_ARG_INCOMP,"To use Schur complement preconditioner you must have exactly 2 fields");

301:     /* need to handle case when one is resetting up the preconditioner */
302:     if (jac->schur) {
303:       MatGetSize(pc->mat,PETSC_NULL,&N);
304:       ilink = jac->head;
305:       ISComplement(ilink->cis,0,N,&ccis);
306:       ISGetLocalSize(ilink->is,&nis);
307:       MatGetLocalSize(pc->mat,PETSC_NULL,&nlocal);
308:       nlocal = nlocal - nis;
309:       MatGetSubMatrix(pc->mat,ilink->is,ccis,nlocal,MAT_REUSE_MATRIX,&jac->B);
310:       ISDestroy(ccis);
311:       ilink = ilink->next;
312:       ISComplement(ilink->cis,0,N,&ccis);
313:       ISGetLocalSize(ilink->is,&nis);
314:       MatGetLocalSize(pc->mat,PETSC_NULL,&nlocal);
315:       nlocal = nlocal - nis;
316:       MatGetSubMatrix(pc->mat,ilink->is,ccis,nlocal,MAT_REUSE_MATRIX,&jac->C);
317:       ISDestroy(ccis);
318:       MatSchurComplementUpdate(jac->schur,jac->pmat[0],jac->B,jac->C,jac->pmat[1],pc->flag);
319:       if (jac->schurpre) {
320:         KSPSetOperators(jac->kspschur,jac->schur,jac->pmat[1],pc->flag);
321:       } else {
322:         KSPSetOperators(jac->kspschur,jac->schur,jac->schur,pc->flag);
323:       }

325:      } else {
326:       KSP ksp;

328:       /* extract the B and C matrices */
329:       MatGetSize(pc->mat,PETSC_NULL,&N);
330:       ilink = jac->head;
331:       ISComplement(ilink->cis,0,N,&ccis);
332:       ISGetLocalSize(ilink->is,&nis);
333:       MatGetLocalSize(pc->mat,PETSC_NULL,&nlocal);
334:       nlocal = nlocal - nis;
335:       MatGetSubMatrix(pc->mat,ilink->is,ccis,nlocal,MAT_INITIAL_MATRIX,&jac->B);
336:       ISDestroy(ccis);
337:       ilink = ilink->next;
338:       ISComplement(ilink->cis,0,N,&ccis);
339:       ISGetLocalSize(ilink->is,&nis);
340:       MatGetLocalSize(pc->mat,PETSC_NULL,&nlocal);
341:       nlocal = nlocal - nis;
342:       MatGetSubMatrix(pc->mat,ilink->is,ccis,nlocal,MAT_INITIAL_MATRIX,&jac->C);
343:       ISDestroy(ccis);
344:       MatCreateSchurComplement(jac->pmat[0],jac->B,jac->C,jac->pmat[1],&jac->schur);
345:       MatSchurComplementGetKSP(jac->schur,&ksp);
346:       PetscObjectIncrementTabLevel((PetscObject)ksp,(PetscObject)pc,2);
347:       MatSetFromOptions(jac->schur);

349:       KSPCreate(((PetscObject)pc)->comm,&jac->kspschur);
350:       PetscObjectIncrementTabLevel((PetscObject)jac->kspschur,(PetscObject)pc,1);
351:       if (jac->schurpre) {
352:         KSPSetOperators(jac->kspschur,jac->schur,jac->pmat[1],DIFFERENT_NONZERO_PATTERN);
353:       } else {
354:         KSPSetOperators(jac->kspschur,jac->schur,jac->schur,DIFFERENT_NONZERO_PATTERN);
355:       }
356:       KSPSetOptionsPrefix(jac->kspschur,((PetscObject)pc)->prefix);
357:       KSPAppendOptionsPrefix(jac->kspschur,"fieldsplit_1_");
358:       /* really want setfromoptions called in PCSetFromOptions_FieldSplit(), but it is not ready yet */
359:       KSPSetFromOptions(jac->kspschur);

361:       PetscMalloc2(2,Vec,&jac->x,2,Vec,&jac->y);
362:       MatGetVecs(jac->pmat[0],&jac->x[0],&jac->y[0]);
363:       MatGetVecs(jac->pmat[1],&jac->x[1],&jac->y[1]);
364:       ilink = jac->head;
365:       ilink->x = jac->x[0]; ilink->y = jac->y[0];
366:       ilink = ilink->next;
367:       ilink->x = jac->x[1]; ilink->y = jac->y[1];
368:     }
369:   } else {
370:     /* set up the individual PCs */
371:     i    = 0;
372:     ilink = jac->head;
373:     while (ilink) {
374:       KSPSetOperators(ilink->ksp,jac->pmat[i],jac->pmat[i],flag);
375:       /* really want setfromoptions called in PCSetFromOptions_FieldSplit(), but it is not ready yet */
376:       KSPSetFromOptions(ilink->ksp);
377:       KSPSetUp(ilink->ksp);
378:       i++;
379:       ilink = ilink->next;
380:     }
381: 
382:     /* create work vectors for each split */
383:     if (!jac->x) {
384:       PetscMalloc2(nsplit,Vec,&jac->x,nsplit,Vec,&jac->y);
385:       ilink = jac->head;
386:       for (i=0; i<nsplit; i++) {
387:         Vec *vl,*vr;

389:         KSPGetVecs(ilink->ksp,1,&vr,1,&vl);
390:         ilink->x  = *vr;
391:         ilink->y  = *vl;
392:         PetscFree(vr);
393:         PetscFree(vl);
394:         jac->x[i] = ilink->x;
395:         jac->y[i] = ilink->y;
396:         ilink     = ilink->next;
397:       }
398:     }
399:   }


402:   if (!jac->head->sctx) {
403:     Vec xtmp;

405:     /* compute scatter contexts needed by multiplicative versions and non-default splits */
406: 
407:     ilink = jac->head;
408:     MatGetVecs(pc->pmat,&xtmp,PETSC_NULL);
409:     for (i=0; i<nsplit; i++) {
410:       VecScatterCreate(xtmp,ilink->is,jac->x[i],PETSC_NULL,&ilink->sctx);
411:       ilink = ilink->next;
412:     }
413:     VecDestroy(xtmp);
414:   }
415:   return(0);
416: }

418: #define FieldSplitSplitSolveAdd(ilink,xx,yy) \
419:     (VecScatterBegin(ilink->sctx,xx,ilink->x,INSERT_VALUES,SCATTER_FORWARD) || \
420:      VecScatterEnd(ilink->sctx,xx,ilink->x,INSERT_VALUES,SCATTER_FORWARD) || \
421:      KSPSolve(ilink->ksp,ilink->x,ilink->y) || \
422:      VecScatterBegin(ilink->sctx,ilink->y,yy,ADD_VALUES,SCATTER_REVERSE) || \
423:      VecScatterEnd(ilink->sctx,ilink->y,yy,ADD_VALUES,SCATTER_REVERSE))

427: static PetscErrorCode PCApply_FieldSplit_Schur(PC pc,Vec x,Vec y)
428: {
429:   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
430:   PetscErrorCode    ierr;
431:   KSP               ksp;
432:   PC_FieldSplitLink ilinkA = jac->head, ilinkD = ilinkA->next;

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

437:   VecScatterBegin(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);
438:   VecScatterEnd(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);
439:   KSPSolve(ksp,ilinkA->x,ilinkA->y);
440:   MatMult(jac->C,ilinkA->y,ilinkD->x);
441:   VecScale(ilinkD->x,-1.0);
442:   VecScatterBegin(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);
443:   VecScatterEnd(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);

445:   KSPSolve(jac->kspschur,ilinkD->x,ilinkD->y);
446:   VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);
447:   VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);

449:   MatMult(jac->B,ilinkD->y,ilinkA->y);
450:   VecAXPY(ilinkA->x,-1.0,ilinkA->y);
451:   KSPSolve(ksp,ilinkA->x,ilinkA->y);
452:   VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);
453:   VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);

455:   return(0);
456: }

460: static PetscErrorCode PCApply_FieldSplit(PC pc,Vec x,Vec y)
461: {
462:   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
463:   PetscErrorCode    ierr;
464:   PC_FieldSplitLink ilink = jac->head;
465:   PetscInt          bs,cnt;

468:   CHKMEMQ;
469:   VecGetBlockSize(x,&bs);
470:   VecSetBlockSize(x,jac->bs);
471:   VecSetBlockSize(y,jac->bs);

473:   if (jac->type == PC_COMPOSITE_ADDITIVE) {
474:     if (jac->defaultsplit) {
475:       VecStrideGatherAll(x,jac->x,INSERT_VALUES);
476:       while (ilink) {
477:         KSPSolve(ilink->ksp,ilink->x,ilink->y);
478:         ilink = ilink->next;
479:       }
480:       VecStrideScatterAll(jac->y,y,INSERT_VALUES);
481:     } else {
482:       VecSet(y,0.0);
483:       while (ilink) {
484:         FieldSplitSplitSolveAdd(ilink,x,y);
485:         ilink = ilink->next;
486:       }
487:     }
488:   } else if (jac->type == PC_COMPOSITE_MULTIPLICATIVE || jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
489:     if (!jac->w1) {
490:       VecDuplicate(x,&jac->w1);
491:       VecDuplicate(x,&jac->w2);
492:     }
493:     VecSet(y,0.0);
494:     FieldSplitSplitSolveAdd(ilink,x,y);
495:     cnt = 1;
496:     while (ilink->next) {
497:       ilink = ilink->next;
498:       if (jac->Afield) {
499:         /* compute the residual only over the part of the vector needed */
500:         MatMult(jac->Afield[cnt++],y,ilink->x);
501:         VecScale(ilink->x,-1.0);
502:         VecScatterBegin(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);
503:         VecScatterEnd(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);
504:         KSPSolve(ilink->ksp,ilink->x,ilink->y);
505:         VecScatterBegin(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);
506:         VecScatterEnd(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);
507:       } else {
508:         /* compute the residual over the entire vector */
509:         MatMult(pc->mat,y,jac->w1);
510:         VecWAXPY(jac->w2,-1.0,jac->w1,x);
511:         FieldSplitSplitSolveAdd(ilink,jac->w2,y);
512:       }
513:     }
514:     if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
515:       cnt -= 2;
516:       while (ilink->previous) {
517:         ilink = ilink->previous;
518:         if (jac->Afield) {
519:           /* compute the residual only over the part of the vector needed */
520:           MatMult(jac->Afield[cnt--],y,ilink->x);
521:           VecScale(ilink->x,-1.0);
522:           VecScatterBegin(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);
523:           VecScatterEnd(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);
524:           KSPSolve(ilink->ksp,ilink->x,ilink->y);
525:           VecScatterBegin(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);
526:           VecScatterEnd(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);
527:         } else {
528:           MatMult(pc->mat,y,jac->w1);
529:           VecWAXPY(jac->w2,-1.0,jac->w1,x);
530:           FieldSplitSplitSolveAdd(ilink,jac->w2,y);
531:         }
532:       }
533:     }
534:   } else SETERRQ1(PETSC_ERR_SUP,"Unsupported or unknown composition",(int) jac->type);
535:   CHKMEMQ;
536:   return(0);
537: }

539: #define FieldSplitSplitSolveAddTranspose(ilink,xx,yy) \
540:     (VecScatterBegin(ilink->sctx,xx,ilink->y,INSERT_VALUES,SCATTER_FORWARD) || \
541:      VecScatterEnd(ilink->sctx,xx,ilink->y,INSERT_VALUES,SCATTER_FORWARD) || \
542:      KSPSolveTranspose(ilink->ksp,ilink->y,ilink->x) || \
543:      VecScatterBegin(ilink->sctx,ilink->x,yy,ADD_VALUES,SCATTER_REVERSE) || \
544:      VecScatterEnd(ilink->sctx,ilink->x,yy,ADD_VALUES,SCATTER_REVERSE))

548: static PetscErrorCode PCApplyTranspose_FieldSplit(PC pc,Vec x,Vec y)
549: {
550:   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
551:   PetscErrorCode    ierr;
552:   PC_FieldSplitLink ilink = jac->head;
553:   PetscInt          bs;

556:   CHKMEMQ;
557:   VecGetBlockSize(x,&bs);
558:   VecSetBlockSize(x,jac->bs);
559:   VecSetBlockSize(y,jac->bs);

561:   if (jac->type == PC_COMPOSITE_ADDITIVE) {
562:     if (jac->defaultsplit) {
563:       VecStrideGatherAll(x,jac->x,INSERT_VALUES);
564:       while (ilink) {
565:         KSPSolveTranspose(ilink->ksp,ilink->x,ilink->y);
566:         ilink = ilink->next;
567:       }
568:       VecStrideScatterAll(jac->y,y,INSERT_VALUES);
569:     } else {
570:       VecSet(y,0.0);
571:       while (ilink) {
572:         FieldSplitSplitSolveAddTranspose(ilink,x,y);
573:         ilink = ilink->next;
574:       }
575:     }
576:   } else {
577:     if (!jac->w1) {
578:       VecDuplicate(x,&jac->w1);
579:       VecDuplicate(x,&jac->w2);
580:     }
581:     VecSet(y,0.0);
582:     if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
583:       FieldSplitSplitSolveAddTranspose(ilink,x,y);
584:       while (ilink->next) {
585:         ilink = ilink->next;
586:         MatMultTranspose(pc->mat,y,jac->w1);
587:         VecWAXPY(jac->w2,-1.0,jac->w1,x);
588:         FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);
589:       }
590:       while (ilink->previous) {
591:         ilink = ilink->previous;
592:         MatMultTranspose(pc->mat,y,jac->w1);
593:         VecWAXPY(jac->w2,-1.0,jac->w1,x);
594:         FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);
595:       }
596:     } else {
597:       while (ilink->next) {   /* get to last entry in linked list */
598:         ilink = ilink->next;
599:       }
600:       FieldSplitSplitSolveAddTranspose(ilink,x,y);
601:       while (ilink->previous) {
602:         ilink = ilink->previous;
603:         MatMultTranspose(pc->mat,y,jac->w1);
604:         VecWAXPY(jac->w2,-1.0,jac->w1,x);
605:         FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);
606:       }
607:     }
608:   }
609:   CHKMEMQ;
610:   return(0);
611: }

615: static PetscErrorCode PCDestroy_FieldSplit(PC pc)
616: {
617:   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
618:   PetscErrorCode    ierr;
619:   PC_FieldSplitLink ilink = jac->head,next;

622:   while (ilink) {
623:     KSPDestroy(ilink->ksp);
624:     if (ilink->x) {VecDestroy(ilink->x);}
625:     if (ilink->y) {VecDestroy(ilink->y);}
626:     if (ilink->sctx) {VecScatterDestroy(ilink->sctx);}
627:     if (ilink->is) {ISDestroy(ilink->is);}
628:     if (ilink->cis) {ISDestroy(ilink->cis);}
629:     next = ilink->next;
630:     PetscFree(ilink->fields);
631:     PetscFree(ilink);
632:     ilink = next;
633:   }
634:   PetscFree2(jac->x,jac->y);
635:   if (jac->pmat) {MatDestroyMatrices(jac->nsplits,&jac->pmat);}
636:   if (jac->Afield) {MatDestroyMatrices(jac->nsplits,&jac->Afield);}
637:   if (jac->w1) {VecDestroy(jac->w1);}
638:   if (jac->w2) {VecDestroy(jac->w2);}
639:   if (jac->schur) {MatDestroy(jac->schur);}
640:   if (jac->kspschur) {KSPDestroy(jac->kspschur);}
641:   if (jac->B) {MatDestroy(jac->B);}
642:   if (jac->C) {MatDestroy(jac->C);}
643:   PetscFree(jac);
644:   return(0);
645: }

649: static PetscErrorCode PCSetFromOptions_FieldSplit(PC pc)
650: {
651:   PetscErrorCode  ierr;
652:   PetscInt        i = 0,nfields,*fields,bs;
653:   PetscTruth      flg,set;
654:   char            optionname[128];
655:   PC_FieldSplit   *jac = (PC_FieldSplit*)pc->data;
656:   PCCompositeType ctype;

659:   PetscOptionsHead("FieldSplit options");
660:   PetscOptionsInt("-pc_fieldsplit_block_size","Blocksize that defines number of fields","PCFieldSplitSetBlockSize",jac->bs,&bs,&flg);
661:   if (flg) {
662:     PCFieldSplitSetBlockSize(pc,bs);
663:   }

665:   PetscOptionsEnum("-pc_fieldsplit_type","Type of composition","PCFieldSplitSetType",PCCompositeTypes,(PetscEnum)jac->type,(PetscEnum*)&ctype,&flg);
666:   if (flg) {
667:     PCFieldSplitSetType(pc,ctype);
668:   }

670:   /* Only setup fields once */
671:   if ((jac->bs > 0) && (jac->nsplits == 0)) {
672:     /* only allow user to set fields from command line if bs is already known.
673:        otherwise user can set them in PCFieldSplitSetDefaults() */
674:     PetscMalloc(jac->bs*sizeof(PetscInt),&fields);
675:     while (PETSC_TRUE) {
676:       sprintf(optionname,"-pc_fieldsplit_%d_fields",(int)i++);
677:       nfields = jac->bs;
678:       PetscOptionsIntArray(optionname,"Fields in this split","PCFieldSplitSetFields",fields,&nfields,&flg);
679:       if (!flg) break;
680:       if (!nfields) SETERRQ(PETSC_ERR_USER,"Cannot list zero fields");
681:       PCFieldSplitSetFields(pc,nfields,fields);
682:     }
683:     PetscFree(fields);
684:   }
685:   PetscOptionsTruth("-pc_fieldsplit_schur_precondition","Build preconditioner for Schur complement","PCFieldSplitSchurPrecondition",jac->schurpre,&flg,&set);
686:   if (set) {
687:     PCFieldSplitSchurPrecondition(pc,flg);
688:   }
689:   PetscOptionsTail();
690:   return(0);
691: }

693: /*------------------------------------------------------------------------------------*/

698: PetscErrorCode  PCFieldSplitSetFields_FieldSplit(PC pc,PetscInt n,PetscInt *fields)
699: {
700:   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
701:   PetscErrorCode    ierr;
702:   PC_FieldSplitLink ilink,next = jac->head;
703:   char              prefix[128];
704:   PetscInt          i;

707:   if (n <= 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Negative number of fields requested");
708:   for (i=0; i<n; i++) {
709:     if (fields[i] >= jac->bs) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Field %D requested but only %D exist",fields[i],jac->bs);
710:     if (fields[i] < 0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Negative field %D requested",fields[i]);
711:   }
712:   PetscNew(struct _PC_FieldSplitLink,&ilink);
713:   PetscMalloc(n*sizeof(PetscInt),&ilink->fields);
714:   PetscMemcpy(ilink->fields,fields,n*sizeof(PetscInt));
715:   ilink->nfields = n;
716:   ilink->next    = PETSC_NULL;
717:   KSPCreate(((PetscObject)pc)->comm,&ilink->ksp);
718:   PetscObjectIncrementTabLevel((PetscObject)ilink->ksp,(PetscObject)pc,1);
719:   KSPSetType(ilink->ksp,KSPPREONLY);

721:   if (((PetscObject)pc)->prefix) {
722:     sprintf(prefix,"%sfieldsplit_%d_",((PetscObject)pc)->prefix,(int)jac->nsplits);
723:   } else {
724:     sprintf(prefix,"fieldsplit_%d_",(int)jac->nsplits);
725:   }
726:   KSPSetOptionsPrefix(ilink->ksp,prefix);

728:   if (!next) {
729:     jac->head       = ilink;
730:     ilink->previous = PETSC_NULL;
731:   } else {
732:     while (next->next) {
733:       next = next->next;
734:     }
735:     next->next      = ilink;
736:     ilink->previous = next;
737:   }
738:   jac->nsplits++;
739:   return(0);
740: }

746: PetscErrorCode  PCFieldSplitGetSubKSP_FieldSplit_Schur(PC pc,PetscInt *n,KSP **subksp)
747: {
748:   PC_FieldSplit *jac = (PC_FieldSplit*)pc->data;

752:   PetscMalloc(jac->nsplits*sizeof(KSP*),subksp);
753:   MatSchurComplementGetKSP(jac->schur,*subksp);
754:   (*subksp)[1] = jac->kspschur;
755:   return(0);
756: }

762: PetscErrorCode  PCFieldSplitGetSubKSP_FieldSplit(PC pc,PetscInt *n,KSP **subksp)
763: {
764:   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
765:   PetscErrorCode    ierr;
766:   PetscInt          cnt = 0;
767:   PC_FieldSplitLink ilink = jac->head;

770:   PetscMalloc(jac->nsplits*sizeof(KSP*),subksp);
771:   while (ilink) {
772:     (*subksp)[cnt++] = ilink->ksp;
773:     ilink = ilink->next;
774:   }
775:   if (cnt != jac->nsplits) SETERRQ2(PETSC_ERR_PLIB,"Corrupt PCFIELDSPLIT object: number splits in linked list %D in object %D",cnt,jac->nsplits);
776:   *n = jac->nsplits;
777:   return(0);
778: }

784: PetscErrorCode  PCFieldSplitSetIS_FieldSplit(PC pc,IS is)
785: {
786:   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
787:   PetscErrorCode    ierr;
788:   PC_FieldSplitLink ilink, next = jac->head;
789:   char              prefix[128];

792:   PetscNew(struct _PC_FieldSplitLink,&ilink);
793:   ilink->is      = is;
794:   PetscObjectReference((PetscObject)is);
795:   ilink->next    = PETSC_NULL;
796:   KSPCreate(((PetscObject)pc)->comm,&ilink->ksp);
797:   PetscObjectIncrementTabLevel((PetscObject)ilink->ksp,(PetscObject)pc,1);
798:   KSPSetType(ilink->ksp,KSPPREONLY);

800:   if (((PetscObject)pc)->prefix) {
801:     sprintf(prefix,"%sfieldsplit_%d_",((PetscObject)pc)->prefix,(int)jac->nsplits);
802:   } else {
803:     sprintf(prefix,"fieldsplit_%d_",(int)jac->nsplits);
804:   }
805:   KSPSetOptionsPrefix(ilink->ksp,prefix);

807:   if (!next) {
808:     jac->head       = ilink;
809:     ilink->previous = PETSC_NULL;
810:   } else {
811:     while (next->next) {
812:       next = next->next;
813:     }
814:     next->next      = ilink;
815:     ilink->previous = next;
816:   }
817:   jac->nsplits++;

819:   return(0);
820: }

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

828:     Collective on PC

830:     Input Parameters:
831: +   pc  - the preconditioner context
832: .   n - the number of fields in this split
833: .   fields - the fields in this split

835:     Level: intermediate

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

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

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

846: @*/
847: PetscErrorCode  PCFieldSplitSetFields(PC pc,PetscInt n, PetscInt *fields)
848: {
849:   PetscErrorCode ierr,(*f)(PC,PetscInt,PetscInt *);

853:   PetscObjectQueryFunction((PetscObject)pc,"PCFieldSplitSetFields_C",(void (**)(void))&f);
854:   if (f) {
855:     (*f)(pc,n,fields);
856:   }
857:   return(0);
858: }

862: /*@
863:     PCFieldSplitSetIS - Sets the exact elements for field

865:     Collective on PC

867:     Input Parameters:
868: +   pc  - the preconditioner context
869: .   is - the index set that defines the vector elements in this field


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

874:     Level: intermediate

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

878: @*/
879: PetscErrorCode  PCFieldSplitSetIS(PC pc,IS is)
880: {
881:   PetscErrorCode ierr,(*f)(PC,IS);

886:   PetscObjectQueryFunction((PetscObject)pc,"PCFieldSplitSetIS_C",(void (**)(void))&f);
887:   if (f) {
888:     (*f)(pc,is);
889:   }
890:   return(0);
891: }

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

899:     Collective on PC

901:     Input Parameters:
902: +   pc  - the preconditioner context
903: -   bs - the block size

905:     Level: intermediate

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

909: @*/
910: PetscErrorCode  PCFieldSplitSetBlockSize(PC pc,PetscInt bs)
911: {
912:   PetscErrorCode ierr,(*f)(PC,PetscInt);

916:   PetscObjectQueryFunction((PetscObject)pc,"PCFieldSplitSetBlockSize_C",(void (**)(void))&f);
917:   if (f) {
918:     (*f)(pc,bs);
919:   }
920:   return(0);
921: }

925: /*@C
926:    PCFieldSplitGetSubKSP - Gets the KSP contexts for all splits
927:    
928:    Collective on KSP

930:    Input Parameter:
931: .  pc - the preconditioner context

933:    Output Parameters:
934: +  n - the number of split
935: -  pc - the array of KSP contexts

937:    Note:  
938:    After PCFieldSplitGetSubKSP() the array of KSPs IS to be freed by the user
939:    (not the KSP just the array that contains them).

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

943:    Level: advanced

945: .seealso: PCFIELDSPLIT
946: @*/
947: PetscErrorCode  PCFieldSplitGetSubKSP(PC pc,PetscInt *n,KSP *subksp[])
948: {
949:   PetscErrorCode ierr,(*f)(PC,PetscInt*,KSP **);

954:   PetscObjectQueryFunction((PetscObject)pc,"PCFieldSplitGetSubKSP_C",(void (**)(void))&f);
955:   if (f) {
956:     (*f)(pc,n,subksp);
957:   } else {
958:     SETERRQ(PETSC_ERR_ARG_WRONG,"Cannot get subksp for this type of PC");
959:   }
960:   return(0);
961: }

965: /*@
966:     PCFieldSplitSchurPrecondition - Indicates if the Schur complement is preconditioned by a preconditioner constructed by the
967:       D matrix. Otherwise no preconditioner is used.

969:     Collective on PC

971:     Input Parameters:
972: +   pc  - the preconditioner context
973: -   flg - build the preconditioner

975:     Options Database:
976: .     -pc_fieldsplit_schur_precondition <true,false> default is true

978:     Level: intermediate

980:     Notes: What should we do if the user wants to provide a different matrix (like a mass matrix) to use to build the preconditioner

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

984: @*/
985: PetscErrorCode  PCFieldSplitSchurPrecondition(PC pc,PetscTruth flg)
986: {
987:   PetscErrorCode ierr,(*f)(PC,PetscTruth);

991:   PetscObjectQueryFunction((PetscObject)pc,"PCFieldSplitSchurPrecondition_C",(void (**)(void))&f);
992:   if (f) {
993:     (*f)(pc,flg);
994:   }
995:   return(0);
996: }

1001: PetscErrorCode  PCFieldSplitSchurPrecondition_FieldSplit(PC pc,PetscTruth flg)
1002: {
1003:   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;

1006:   jac->schurpre = flg;
1007:   return(0);
1008: }

1013: /*@C
1014:    PCFieldSplitGetSchurBlocks - Gets the all matrix blocks for the Schur complement
1015:    
1016:    Collective on KSP

1018:    Input Parameter:
1019: .  pc - the preconditioner context

1021:    Output Parameters:
1022: +  A - the (0,0) block
1023: .  B - the (0,1) block
1024: .  C - the (1,0) block
1025: -  D - the (1,1) block

1027:    Level: advanced

1029: .seealso: PCFIELDSPLIT
1030: @*/
1031: PetscErrorCode  PCFieldSplitGetSchurBlocks(PC pc,Mat *A,Mat *B,Mat *C, Mat *D)
1032: {
1033:   PC_FieldSplit *jac = (PC_FieldSplit *) pc->data;

1037:   if (jac->type != PC_COMPOSITE_SCHUR) {SETERRQ(PETSC_ERR_ARG_WRONG, "FieldSplit is not using a Schur complement approach.");}
1038:   if (A) *A = jac->pmat[0];
1039:   if (B) *B = jac->B;
1040:   if (C) *C = jac->C;
1041:   if (D) *D = jac->pmat[1];
1042:   return(0);
1043: }

1048: PetscErrorCode  PCFieldSplitSetType_FieldSplit(PC pc,PCCompositeType type)
1049: {
1050:   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;

1054:   jac->type = type;
1055:   if (type == PC_COMPOSITE_SCHUR) {
1056:     pc->ops->apply = PCApply_FieldSplit_Schur;
1057:     pc->ops->view  = PCView_FieldSplit_Schur;
1058:     PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitGetSubKSP_C","PCFieldSplitGetSubKSP_FieldSplit_Schur",PCFieldSplitGetSubKSP_FieldSplit_Schur);
1059:     PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSchurPrecondition_C","PCFieldSplitSchurPrecondition_FieldSplit",PCFieldSplitSchurPrecondition_FieldSplit);

1061:   } else {
1062:     pc->ops->apply = PCApply_FieldSplit;
1063:     pc->ops->view  = PCView_FieldSplit;
1064:     PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitGetSubKSP_C","PCFieldSplitGetSubKSP_FieldSplit",PCFieldSplitGetSubKSP_FieldSplit);
1065:     PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSchurPrecondition_C","",0);
1066:   }
1067:   return(0);
1068: }

1074: PetscErrorCode  PCFieldSplitSetBlockSize_FieldSplit(PC pc,PetscInt bs)
1075: {
1076:   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;

1079:   if (bs < 1) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Blocksize must be positive, you gave %D",bs);
1080:   if (jac->bs > 0 && jac->bs != bs) SETERRQ2(PETSC_ERR_ARG_WRONGSTATE,"Cannot change fieldsplit blocksize from %D to %D after it has been set",jac->bs,bs);
1081:   jac->bs = bs;
1082:   return(0);
1083: }

1088: /*@
1089:    PCFieldSplitSetType - Sets the type of fieldsplit preconditioner.
1090:    
1091:    Collective on PC

1093:    Input Parameter:
1094: .  pc - the preconditioner context
1095: .  type - PC_COMPOSITE_ADDITIVE, PC_COMPOSITE_MULTIPLICATIVE (default), PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE, PC_COMPOSITE_SPECIAL, PC_COMPOSITE_SCHUR

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

1100:    Level: Developer

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

1104: .seealso: PCCompositeSetType()

1106: @*/
1107: PetscErrorCode  PCFieldSplitSetType(PC pc,PCCompositeType type)
1108: {
1109:   PetscErrorCode ierr,(*f)(PC,PCCompositeType);

1113:   PetscObjectQueryFunction((PetscObject)pc,"PCFieldSplitSetType_C",(void (**)(void))&f);
1114:   if (f) {
1115:     (*f)(pc,type);
1116:   }
1117:   return(0);
1118: }

1120: /* -------------------------------------------------------------------------------------*/
1121: /*MC
1122:    PCFIELDSPLIT - Preconditioner created by combining separate preconditioners for individual
1123:                   fields or groups of fields


1126:      To set options on the solvers for each block append -fieldsplit_ to all the PC
1127:         options database keys. For example, -fieldsplit_pc_type ilu -fieldsplit_pc_factor_levels 1
1128:         
1129:      To set the options on the solvers separate for each block call PCFieldSplitGetSubKSP()
1130:          and set the options directly on the resulting KSP object

1132:    Level: intermediate

1134:    Options Database Keys:
1135: +   -pc_fieldsplit_%d_fields <a,b,..> - indicates the fields to be used in the %d'th split
1136: .   -pc_fieldsplit_default - automatically add any fields to additional splits that have not
1137:                               been supplied explicitly by -pc_fieldsplit_%d_fields
1138: .   -pc_fieldsplit_block_size <bs> - size of block that defines fields (i.e. there are bs fields)
1139: .    -pc_fieldsplit_type <additive,multiplicative,schur,symmetric_multiplicative>
1140: .    -pc_fieldsplit_schur_precondition <true,false> default is true

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


1146:    Notes: use PCFieldSplitSetFields() to set fields defined by "strided" entries and PCFieldSplitSetIS()
1147:      to define a field by an arbitrary collection of entries.

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

1154:       Currently for the multiplicative version, the updated residual needed for the next field
1155:      solve is computed via a matrix vector product over the entire array. An optimization would be
1156:      to update the residual only for the part of the right hand side associated with the next field
1157:      solve. (This would involve more MatGetSubMatrix() calls or some other mechanism to compute the 
1158:      part of the matrix needed to just update part of the residual).

1160:      For the Schur complement preconditioner if J = ( A B )
1161:                                                     ( C D )
1162:      the preconditioner is 
1163:               (I   -B inv(A)) ( inv(A)   0    ) (I         0  )
1164:               (0    I       ) (   0    inv(S) ) (-C inv(A) I  )
1165:      where the action of inv(A) is applied using the KSP solver with prefix -fieldsplit_0_. The action of 
1166:      inv(S) is computed using the KSP solver with prefix -schur_. For PCFieldSplitGetKSP() when field number is
1167:      0 it returns the KSP associated with -fieldsplit_0_ while field number 1 gives -fieldsplit_1_ KSP. By default
1168:      D is used to construct a preconditioner for S, use PCFieldSplitSchurPrecondition() to turn on or off this
1169:      option.
1170:      
1171:      If only one set of indices (one IS) is provided with PCFieldSplitSetIS() then the complement of that IS
1172:      is used automatically for a second block.

1174:    Concepts: physics based preconditioners, block preconditioners

1176: .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC, Block_Preconditioners
1177:            PCFieldSplitGetSubKSP(), PCFieldSplitSetFields(), PCFieldSplitSetType(), PCFieldSplitSetIS(), PCFieldSplitSchurPrecondition()
1178: M*/

1183: PetscErrorCode  PCCreate_FieldSplit(PC pc)
1184: {
1186:   PC_FieldSplit  *jac;

1189:   PetscNewLog(pc,PC_FieldSplit,&jac);
1190:   jac->bs        = -1;
1191:   jac->nsplits   = 0;
1192:   jac->type      = PC_COMPOSITE_MULTIPLICATIVE;
1193:   jac->schurpre  = PETSC_TRUE;

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

1197:   pc->ops->apply             = PCApply_FieldSplit;
1198:   pc->ops->applytranspose    = PCApplyTranspose_FieldSplit;
1199:   pc->ops->setup             = PCSetUp_FieldSplit;
1200:   pc->ops->destroy           = PCDestroy_FieldSplit;
1201:   pc->ops->setfromoptions    = PCSetFromOptions_FieldSplit;
1202:   pc->ops->view              = PCView_FieldSplit;
1203:   pc->ops->applyrichardson   = 0;

1205:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitGetSubKSP_C","PCFieldSplitGetSubKSP_FieldSplit",
1206:                     PCFieldSplitGetSubKSP_FieldSplit);
1207:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetFields_C","PCFieldSplitSetFields_FieldSplit",
1208:                     PCFieldSplitSetFields_FieldSplit);
1209:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetIS_C","PCFieldSplitSetIS_FieldSplit",
1210:                     PCFieldSplitSetIS_FieldSplit);
1211:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetType_C","PCFieldSplitSetType_FieldSplit",
1212:                     PCFieldSplitSetType_FieldSplit);
1213:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetBlockSize_C","PCFieldSplitSetBlockSize_FieldSplit",
1214:                     PCFieldSplitSetBlockSize_FieldSplit);
1215:   return(0);
1216: }


1220: /*MC
1221:    Block_Preconditioners - PETSc provides support for a variety of "block preconditioners", this provides an
1222:           overview of these methods. 

1224:       Consider the solution to ( A B ) (x_1)  =  (b_1)
1225:                                ( C D ) (x_2)     (b_2)

1227:       Important special cases, the Stokes equation: C = B' and D = 0  (A   B) (x_1) = (b_1)
1228:                                                                        B'  0) (x_2)   (b_2) 

1230:       One of the goals of the PCFieldSplit preconditioner in PETSc is to provide a variety of preconditioners
1231:       for this block system.
1232:    
1233:       Consider an additional matrix (Ap  Bp)
1234:                                     (Cp  Dp) where some or all of the entries may be the same as
1235:       in the original matrix (for example Ap == A).

1237:       In the following, A^ denotes the approximate application of the inverse of A, possibly using Ap in the 
1238:       approximation. In PETSc this simply means one has called KSPSetOperators(ksp,A,Ap,...) or KSPSetOperators(ksp,Ap,Ap,...)

1240:       Block Jacobi:   x_1 = A^ b_1
1241:                       x_2 = D^ b_2

1243:       Lower block Gauss-Seidel:   x_1 = A^ b_1
1244:                             x_2 = D^ (b_2 - C x_1)       variant x_2 = D^ (b_2 - Cp x_1)

1246:       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)
1247:           Interestingly this form is not actually a symmetric matrix, the symmetric version is 
1248:                               x_1 = A^(b_1 - B x_2)      variant x_1 = A^(b_1 - Bp x_2)

1250:    Level: intermediate

1252: .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC, PCFIELDSPLIT
1253:            PCFieldSplitGetSubKSP(), PCFieldSplitSetFields(), PCFieldSplitSetType(), PCFieldSplitSetIS(), PCFieldSplitSchurPrecondition()
1254: M*/