Actual source code: fieldsplit.c

  1: #define PETSCKSP_DLL

  3: /*

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

  8: const char *PCFieldSplitSchurPreTypes[] = {"self","diag","user","PCFieldSplitSchurPreType","PC_FIELDSPLIT_SCHUR_PRE_",0};

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

 21: typedef struct {
 22:   PCCompositeType   type;
 23:   PetscTruth        defaultsplit; /* Flag for a system with a set of 'k' scalar fields with the same layout (and bs = k) */
 24:   PetscTruth        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:   PetscTruth        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 = D - C A^{-1} B */
 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:   KSP               kspschur;     /* The solver for S */
 39:   PC_FieldSplitLink head;
 40: } PC_FieldSplit;

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

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


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

 73:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
 74:   if (iascii) {
 75:     PetscViewerASCIIPrintf(viewer,"  FieldSplit with %s composition: total splits = %D, blocksize = %D\n",PCCompositeTypes[jac->type],jac->nsplits,jac->bs);
 76:     PetscViewerASCIIPrintf(viewer,"  Solver info for each split is in the following KSP objects:\n");
 77:     PetscViewerASCIIPushTab(viewer);
 78:     for (i=0; i<jac->nsplits; i++) {
 79:       if (ilink->fields) {
 80:         PetscViewerASCIIPrintf(viewer,"Split number %D Fields ",i);
 81:         PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);
 82:         for (j=0; j<ilink->nfields; j++) {
 83:           if (j > 0) {
 84:             PetscViewerASCIIPrintf(viewer,",");
 85:           }
 86:           PetscViewerASCIIPrintf(viewer," %D",ilink->fields[j]);
 87:         }
 88:         PetscViewerASCIIPrintf(viewer,"\n");
 89:         PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);
 90:       } else {
 91:         PetscViewerASCIIPrintf(viewer,"Split number %D Defined by IS\n",i);
 92:       }
 93:       KSPView(ilink->ksp,viewer);
 94:       ilink = ilink->next;
 95:     }
 96:     PetscViewerASCIIPopTab(viewer);
 97:   } else {
 98:     SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported for PCFieldSplit",((PetscObject)viewer)->type_name);
 99:   }
100:   return(0);
101: }

105: static PetscErrorCode PCView_FieldSplit_Schur(PC pc,PetscViewer viewer)
106: {
107:   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
108:   PetscErrorCode    ierr;
109:   PetscTruth        iascii;
110:   PetscInt          i,j;
111:   PC_FieldSplitLink ilink = jac->head;
112:   KSP               ksp;

115:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
116:   if (iascii) {
117:     PetscViewerASCIIPrintf(viewer,"  FieldSplit with Schur preconditioner, blocksize = %D\n",jac->bs);
118:     PetscViewerASCIIPrintf(viewer,"  Split info:\n");
119:     PetscViewerASCIIPushTab(viewer);
120:     for (i=0; i<jac->nsplits; i++) {
121:       if (ilink->fields) {
122:         PetscViewerASCIIPrintf(viewer,"Split number %D Fields ",i);
123:         PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);
124:         for (j=0; j<ilink->nfields; j++) {
125:           if (j > 0) {
126:             PetscViewerASCIIPrintf(viewer,",");
127:           }
128:           PetscViewerASCIIPrintf(viewer," %D",ilink->fields[j]);
129:         }
130:         PetscViewerASCIIPrintf(viewer,"\n");
131:         PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);
132:       } else {
133:         PetscViewerASCIIPrintf(viewer,"Split number %D Defined by IS\n",i);
134:       }
135:       ilink = ilink->next;
136:     }
137:     PetscViewerASCIIPrintf(viewer,"KSP solver for A block \n");
138:     PetscViewerASCIIPushTab(viewer);
139:     if (jac->schur) {
140:       MatSchurComplementGetKSP(jac->schur,&ksp);
141:       KSPView(ksp,viewer);
142:     } else {
143:       PetscViewerASCIIPrintf(viewer,"  not yet available\n");
144:     }
145:     PetscViewerASCIIPopTab(viewer);
146:     PetscViewerASCIIPrintf(viewer,"KSP solver for S = D - C inv(A) B \n");
147:     PetscViewerASCIIPushTab(viewer);
148:     if (jac->kspschur) {
149:       KSPView(jac->kspschur,viewer);
150:     } else {
151:       PetscViewerASCIIPrintf(viewer,"  not yet available\n");
152:     }
153:     PetscViewerASCIIPopTab(viewer);
154:     PetscViewerASCIIPopTab(viewer);
155:   } else {
156:     SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported for PCFieldSplit",((PetscObject)viewer)->type_name);
157:   }
158:   return(0);
159: }

163: static PetscErrorCode PCFieldSplitSetDefaults(PC pc)
164: {
165:   PC_FieldSplit     *jac  = (PC_FieldSplit*)pc->data;
166:   PetscErrorCode    ierr;
167:   PC_FieldSplitLink ilink = jac->head;
168:   PetscInt          i = 0,*ifields,nfields;
169:   PetscTruth        flg = PETSC_FALSE,*fields,flg2;
170:   char              optionname[128];

173:   if (!ilink) {

175:     if (jac->bs <= 0) {
176:       if (pc->pmat) {
177:         MatGetBlockSize(pc->pmat,&jac->bs);
178:       } else {
179:         jac->bs = 1;
180:       }
181:     }

183:     PetscOptionsGetTruth(((PetscObject)pc)->prefix,"-pc_fieldsplit_default",&flg,PETSC_NULL);
184:     if (!flg) {
185:       /* Allow user to set fields from command line,  if bs was known at the time of PCSetFromOptions_FieldSplit()
186:          then it is set there. This is not ideal because we should only have options set in XXSetFromOptions(). */
187:       flg = PETSC_TRUE; /* switched off automatically if user sets fields manually here */
188:       PetscMalloc(jac->bs*sizeof(PetscInt),&ifields);
189:       while (PETSC_TRUE) {
190:         sprintf(optionname,"-pc_fieldsplit_%d_fields",(int)i++);
191:         nfields = jac->bs;
192:         PetscOptionsGetIntArray(((PetscObject)pc)->prefix,optionname,ifields,&nfields,&flg2);
193:         if (!flg2) break;
194:         if (!nfields) SETERRQ(PETSC_ERR_USER,"Cannot list zero fields");
195:         flg = PETSC_FALSE;
196:         PCFieldSplitSetFields(pc,nfields,ifields);
197:       }
198:       PetscFree(ifields);
199:     }
200: 
201:     if (flg) {
202:       PetscInfo(pc,"Using default splitting of fields\n");
203:       PetscMalloc(jac->bs*sizeof(PetscTruth),&fields);
204:       PetscMemzero(fields,jac->bs*sizeof(PetscTruth));
205:       while (ilink) {
206:         for (i=0; i<ilink->nfields; i++) {
207:           fields[ilink->fields[i]] = PETSC_TRUE;
208:         }
209:         ilink = ilink->next;
210:       }
211:       jac->defaultsplit = PETSC_TRUE;
212:       for (i=0; i<jac->bs; i++) {
213:         if (!fields[i]) {
214:           PCFieldSplitSetFields(pc,1,&i);
215:         } else {
216:           jac->defaultsplit = PETSC_FALSE;
217:         }
218:       }
219:       PetscFree(fields);
220:     }
221:   } else if (jac->nsplits == 1) {
222:     if (ilink->is) {
223:       IS       is2;
224:       PetscInt nmin,nmax;

226:       MatGetOwnershipRange(pc->mat,&nmin,&nmax);
227:       ISComplement(ilink->is,nmin,nmax,&is2);
228:       PCFieldSplitSetIS(pc,is2);
229:       ISDestroy(is2);
230:     } else {
231:       SETERRQ(PETSC_ERR_SUP,"Must provide at least two sets of fields to PCFieldSplit()");
232:     }
233:   }
234:   if (jac->nsplits < 2) {
235:     SETERRQ(PETSC_ERR_PLIB,"Unhandled case, must have at least two fields");
236:   }
237:   return(0);
238: }


243: static PetscErrorCode PCSetUp_FieldSplit(PC pc)
244: {
245:   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
246:   PetscErrorCode    ierr;
247:   PC_FieldSplitLink ilink;
248:   PetscInt          i,nsplit,ccsize;
249:   MatStructure      flag = pc->flag;
250:   PetscTruth        sorted;

253:   PCFieldSplitSetDefaults(pc);
254:   nsplit = jac->nsplits;
255:   ilink  = jac->head;

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

261:     jac->issetup = PETSC_TRUE;

263:     /* This is done here instead of in PCFieldSplitSetFields() because may not have matrix at that point */
264:     bs     = jac->bs;
265:     MatGetOwnershipRange(pc->pmat,&rstart,&rend);
266:     MatGetLocalSize(pc->pmat,PETSC_NULL,&ccsize);
267:     nslots = (rend - rstart)/bs;
268:     for (i=0; i<nsplit; i++) {
269:       if (jac->defaultsplit) {
270:         ISCreateStride(((PetscObject)pc)->comm,nslots,rstart+i,nsplit,&ilink->is);
271:       } else if (!ilink->is) {
272:         if (ilink->nfields > 1) {
273:           PetscInt   *ii,j,k,nfields = ilink->nfields,*fields = ilink->fields;
274:           PetscMalloc(ilink->nfields*nslots*sizeof(PetscInt),&ii);
275:           for (j=0; j<nslots; j++) {
276:             for (k=0; k<nfields; k++) {
277:               ii[nfields*j + k] = rstart + bs*j + fields[k];
278:             }
279:           }
280:           ISCreateGeneral(((PetscObject)pc)->comm,nslots*nfields,ii,&ilink->is);
281:           PetscFree(ii);
282:         } else {
283:           ISCreateStride(((PetscObject)pc)->comm,nslots,rstart+ilink->fields[0],bs,&ilink->is);
284:         }
285:       }
286:       ISSorted(ilink->is,&sorted);
287:       if (!sorted) SETERRQ(PETSC_ERR_USER,"Fields must be sorted when creating split");
288:       ilink = ilink->next;
289:     }
290:   }
291: 
292:   ilink  = jac->head;
293:   if (!jac->pmat) {
294:     PetscMalloc(nsplit*sizeof(Mat),&jac->pmat);
295:     for (i=0; i<nsplit; i++) {
296:       MatGetSubMatrix(pc->pmat,ilink->is,ilink->is,MAT_INITIAL_MATRIX,&jac->pmat[i]);
297:       ilink = ilink->next;
298:     }
299:   } else {
300:     for (i=0; i<nsplit; i++) {
301:       MatGetSubMatrix(pc->pmat,ilink->is,ilink->is,MAT_REUSE_MATRIX,&jac->pmat[i]);
302:       ilink = ilink->next;
303:     }
304:   }
305:   if (jac->realdiagonal) {
306:     ilink = jac->head;
307:     if (!jac->mat) {
308:       PetscMalloc(nsplit*sizeof(Mat),&jac->mat);
309:       for (i=0; i<nsplit; i++) {
310:         MatGetSubMatrix(pc->mat,ilink->is,ilink->is,MAT_INITIAL_MATRIX,&jac->mat[i]);
311:         ilink = ilink->next;
312:       }
313:     } else {
314:       for (i=0; i<nsplit; i++) {
315:         MatGetSubMatrix(pc->mat,ilink->is,ilink->is,MAT_REUSE_MATRIX,&jac->mat[i]);
316:         ilink = ilink->next;
317:       }
318:     }
319:   } else {
320:     jac->mat = jac->pmat;
321:   }

323:   if (jac->type != PC_COMPOSITE_ADDITIVE  && jac->type != PC_COMPOSITE_SCHUR) {
324:     /* extract the rows of the matrix associated with each field: used for efficient computation of residual inside algorithm */
325:     ilink  = jac->head;
326:     if (!jac->Afield) {
327:       PetscMalloc(nsplit*sizeof(Mat),&jac->Afield);
328:       for (i=0; i<nsplit; i++) {
329:         MatGetSubMatrix(pc->mat,ilink->is,PETSC_NULL,MAT_INITIAL_MATRIX,&jac->Afield[i]);
330:         ilink = ilink->next;
331:       }
332:     } else {
333:       for (i=0; i<nsplit; i++) {
334:         MatGetSubMatrix(pc->mat,ilink->is,PETSC_NULL,MAT_REUSE_MATRIX,&jac->Afield[i]);
335:         ilink = ilink->next;
336:       }
337:     }
338:   }

340:   if (jac->type == PC_COMPOSITE_SCHUR) {
341:     IS       ccis;
342:     PetscInt rstart,rend;
343:     if (nsplit != 2) SETERRQ(PETSC_ERR_ARG_INCOMP,"To use Schur complement preconditioner you must have exactly 2 fields");

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

348:     /* need to handle case when one is resetting up the preconditioner */
349:     if (jac->schur) {
350:       ilink = jac->head;
351:       ISComplement(ilink->is,rstart,rend,&ccis);
352:       MatGetSubMatrix(pc->mat,ilink->is,ccis,MAT_REUSE_MATRIX,&jac->B);
353:       ISDestroy(ccis);
354:       ilink = ilink->next;
355:       ISComplement(ilink->is,rstart,rend,&ccis);
356:       MatGetSubMatrix(pc->mat,ilink->is,ccis,MAT_REUSE_MATRIX,&jac->C);
357:       ISDestroy(ccis);
358:       MatSchurComplementUpdate(jac->schur,jac->mat[0],jac->pmat[0],jac->B,jac->C,jac->pmat[1],pc->flag);
359:       KSPSetOperators(jac->kspschur,jac->schur,FieldSplitSchurPre(jac),pc->flag);

361:      } else {
362:       KSP ksp;

364:       /* extract the B and C matrices */
365:       ilink = jac->head;
366:       ISComplement(ilink->is,rstart,rend,&ccis);
367:       MatGetSubMatrix(pc->mat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->B);
368:       ISDestroy(ccis);
369:       ilink = ilink->next;
370:       ISComplement(ilink->is,rstart,rend,&ccis);
371:       MatGetSubMatrix(pc->mat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->C);
372:       ISDestroy(ccis);
373:       /* Better would be to use 'mat[0]' (diagonal block of the real matrix) preconditioned by pmat[0] */
374:       MatCreateSchurComplement(jac->mat[0],jac->pmat[0],jac->B,jac->C,jac->mat[1],&jac->schur);
375:       MatSchurComplementGetKSP(jac->schur,&ksp);
376:       PetscObjectIncrementTabLevel((PetscObject)ksp,(PetscObject)pc,2);
377:       MatSetFromOptions(jac->schur);

379:       KSPCreate(((PetscObject)pc)->comm,&jac->kspschur);
380:       PetscObjectIncrementTabLevel((PetscObject)jac->kspschur,(PetscObject)pc,1);
381:       KSPSetOperators(jac->kspschur,jac->schur,FieldSplitSchurPre(jac),DIFFERENT_NONZERO_PATTERN);
382:       if (jac->schurpre == PC_FIELDSPLIT_SCHUR_PRE_SELF) {
383:         PC pc;
384:         KSPGetPC(jac->kspschur,&pc);
385:         PCSetType(pc,PCNONE);
386:         /* Note: This is bad if there exist preconditioners for MATSCHURCOMPLEMENT */
387:       }
388:       KSPSetOptionsPrefix(jac->kspschur,((PetscObject)pc)->prefix);
389:       KSPAppendOptionsPrefix(jac->kspschur,"fieldsplit_1_");
390:       /* really want setfromoptions called in PCSetFromOptions_FieldSplit(), but it is not ready yet */
391:       KSPSetFromOptions(jac->kspschur);

393:       PetscMalloc2(2,Vec,&jac->x,2,Vec,&jac->y);
394:       MatGetVecs(jac->pmat[0],&jac->x[0],&jac->y[0]);
395:       MatGetVecs(jac->pmat[1],&jac->x[1],&jac->y[1]);
396:       ilink = jac->head;
397:       ilink->x = jac->x[0]; ilink->y = jac->y[0];
398:       ilink = ilink->next;
399:       ilink->x = jac->x[1]; ilink->y = jac->y[1];
400:     }
401:   } else {
402:     /* set up the individual PCs */
403:     i    = 0;
404:     ilink = jac->head;
405:     while (ilink) {
406:       KSPSetOperators(ilink->ksp,jac->mat[i],jac->pmat[i],flag);
407:       /* really want setfromoptions called in PCSetFromOptions_FieldSplit(), but it is not ready yet */
408:       KSPSetFromOptions(ilink->ksp);
409:       KSPSetUp(ilink->ksp);
410:       i++;
411:       ilink = ilink->next;
412:     }
413: 
414:     /* create work vectors for each split */
415:     if (!jac->x) {
416:       PetscMalloc2(nsplit,Vec,&jac->x,nsplit,Vec,&jac->y);
417:       ilink = jac->head;
418:       for (i=0; i<nsplit; i++) {
419:         Vec *vl,*vr;

421:         KSPGetVecs(ilink->ksp,1,&vr,1,&vl);
422:         ilink->x  = *vr;
423:         ilink->y  = *vl;
424:         PetscFree(vr);
425:         PetscFree(vl);
426:         jac->x[i] = ilink->x;
427:         jac->y[i] = ilink->y;
428:         ilink     = ilink->next;
429:       }
430:     }
431:   }


434:   if (!jac->head->sctx) {
435:     Vec xtmp;

437:     /* compute scatter contexts needed by multiplicative versions and non-default splits */
438: 
439:     ilink = jac->head;
440:     MatGetVecs(pc->pmat,&xtmp,PETSC_NULL);
441:     for (i=0; i<nsplit; i++) {
442:       VecScatterCreate(xtmp,ilink->is,jac->x[i],PETSC_NULL,&ilink->sctx);
443:       ilink = ilink->next;
444:     }
445:     VecDestroy(xtmp);
446:   }
447:   return(0);
448: }

450: #define FieldSplitSplitSolveAdd(ilink,xx,yy) \
451:     (VecScatterBegin(ilink->sctx,xx,ilink->x,INSERT_VALUES,SCATTER_FORWARD) || \
452:      VecScatterEnd(ilink->sctx,xx,ilink->x,INSERT_VALUES,SCATTER_FORWARD) || \
453:      KSPSolve(ilink->ksp,ilink->x,ilink->y) || \
454:      VecScatterBegin(ilink->sctx,ilink->y,yy,ADD_VALUES,SCATTER_REVERSE) || \
455:      VecScatterEnd(ilink->sctx,ilink->y,yy,ADD_VALUES,SCATTER_REVERSE))

459: static PetscErrorCode PCApply_FieldSplit_Schur(PC pc,Vec x,Vec y)
460: {
461:   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
462:   PetscErrorCode    ierr;
463:   KSP               ksp;
464:   PC_FieldSplitLink ilinkA = jac->head, ilinkD = ilinkA->next;

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

469:   VecScatterBegin(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);
470:   VecScatterEnd(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);
471:   KSPSolve(ksp,ilinkA->x,ilinkA->y);
472:   MatMult(jac->C,ilinkA->y,ilinkD->x);
473:   VecScale(ilinkD->x,-1.0);
474:   VecScatterBegin(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);
475:   VecScatterEnd(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);

477:   KSPSolve(jac->kspschur,ilinkD->x,ilinkD->y);
478:   VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);
479:   VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);

481:   MatMult(jac->B,ilinkD->y,ilinkA->y);
482:   VecAXPY(ilinkA->x,-1.0,ilinkA->y);
483:   KSPSolve(ksp,ilinkA->x,ilinkA->y);
484:   VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);
485:   VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);

487:   return(0);
488: }

492: static PetscErrorCode PCApply_FieldSplit(PC pc,Vec x,Vec y)
493: {
494:   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
495:   PetscErrorCode    ierr;
496:   PC_FieldSplitLink ilink = jac->head;
497:   PetscInt          cnt;

500:   CHKMEMQ;
501:   VecSetBlockSize(x,jac->bs);
502:   VecSetBlockSize(y,jac->bs);

504:   if (jac->type == PC_COMPOSITE_ADDITIVE) {
505:     if (jac->defaultsplit) {
506:       VecStrideGatherAll(x,jac->x,INSERT_VALUES);
507:       while (ilink) {
508:         KSPSolve(ilink->ksp,ilink->x,ilink->y);
509:         ilink = ilink->next;
510:       }
511:       VecStrideScatterAll(jac->y,y,INSERT_VALUES);
512:     } else {
513:       VecSet(y,0.0);
514:       while (ilink) {
515:         FieldSplitSplitSolveAdd(ilink,x,y);
516:         ilink = ilink->next;
517:       }
518:     }
519:   } else if (jac->type == PC_COMPOSITE_MULTIPLICATIVE || jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
520:     if (!jac->w1) {
521:       VecDuplicate(x,&jac->w1);
522:       VecDuplicate(x,&jac->w2);
523:     }
524:     VecSet(y,0.0);
525:     FieldSplitSplitSolveAdd(ilink,x,y);
526:     cnt = 1;
527:     while (ilink->next) {
528:       ilink = ilink->next;
529:       /* compute the residual only over the part of the vector needed */
530:       MatMult(jac->Afield[cnt++],y,ilink->x);
531:       VecScale(ilink->x,-1.0);
532:       VecScatterBegin(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);
533:       VecScatterEnd(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);
534:       KSPSolve(ilink->ksp,ilink->x,ilink->y);
535:       VecScatterBegin(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);
536:       VecScatterEnd(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);
537:     }
538:     if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
539:       cnt -= 2;
540:       while (ilink->previous) {
541:         ilink = ilink->previous;
542:         /* compute the residual only over the part of the vector needed */
543:         MatMult(jac->Afield[cnt--],y,ilink->x);
544:         VecScale(ilink->x,-1.0);
545:         VecScatterBegin(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);
546:         VecScatterEnd(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);
547:         KSPSolve(ilink->ksp,ilink->x,ilink->y);
548:         VecScatterBegin(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);
549:         VecScatterEnd(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);
550:       }
551:     }
552:   } else SETERRQ1(PETSC_ERR_SUP,"Unsupported or unknown composition",(int) jac->type);
553:   CHKMEMQ;
554:   return(0);
555: }

557: #define FieldSplitSplitSolveAddTranspose(ilink,xx,yy) \
558:     (VecScatterBegin(ilink->sctx,xx,ilink->y,INSERT_VALUES,SCATTER_FORWARD) || \
559:      VecScatterEnd(ilink->sctx,xx,ilink->y,INSERT_VALUES,SCATTER_FORWARD) || \
560:      KSPSolveTranspose(ilink->ksp,ilink->y,ilink->x) || \
561:      VecScatterBegin(ilink->sctx,ilink->x,yy,ADD_VALUES,SCATTER_REVERSE) || \
562:      VecScatterEnd(ilink->sctx,ilink->x,yy,ADD_VALUES,SCATTER_REVERSE))

566: static PetscErrorCode PCApplyTranspose_FieldSplit(PC pc,Vec x,Vec y)
567: {
568:   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
569:   PetscErrorCode    ierr;
570:   PC_FieldSplitLink ilink = jac->head;

573:   CHKMEMQ;
574:   VecSetBlockSize(x,jac->bs);
575:   VecSetBlockSize(y,jac->bs);

577:   if (jac->type == PC_COMPOSITE_ADDITIVE) {
578:     if (jac->defaultsplit) {
579:       VecStrideGatherAll(x,jac->x,INSERT_VALUES);
580:       while (ilink) {
581:         KSPSolveTranspose(ilink->ksp,ilink->x,ilink->y);
582:         ilink = ilink->next;
583:       }
584:       VecStrideScatterAll(jac->y,y,INSERT_VALUES);
585:     } else {
586:       VecSet(y,0.0);
587:       while (ilink) {
588:         FieldSplitSplitSolveAddTranspose(ilink,x,y);
589:         ilink = ilink->next;
590:       }
591:     }
592:   } else {
593:     if (!jac->w1) {
594:       VecDuplicate(x,&jac->w1);
595:       VecDuplicate(x,&jac->w2);
596:     }
597:     VecSet(y,0.0);
598:     if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
599:       FieldSplitSplitSolveAddTranspose(ilink,x,y);
600:       while (ilink->next) {
601:         ilink = ilink->next;
602:         MatMultTranspose(pc->mat,y,jac->w1);
603:         VecWAXPY(jac->w2,-1.0,jac->w1,x);
604:         FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);
605:       }
606:       while (ilink->previous) {
607:         ilink = ilink->previous;
608:         MatMultTranspose(pc->mat,y,jac->w1);
609:         VecWAXPY(jac->w2,-1.0,jac->w1,x);
610:         FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);
611:       }
612:     } else {
613:       while (ilink->next) {   /* get to last entry in linked list */
614:         ilink = ilink->next;
615:       }
616:       FieldSplitSplitSolveAddTranspose(ilink,x,y);
617:       while (ilink->previous) {
618:         ilink = ilink->previous;
619:         MatMultTranspose(pc->mat,y,jac->w1);
620:         VecWAXPY(jac->w2,-1.0,jac->w1,x);
621:         FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);
622:       }
623:     }
624:   }
625:   CHKMEMQ;
626:   return(0);
627: }

631: static PetscErrorCode PCDestroy_FieldSplit(PC pc)
632: {
633:   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
634:   PetscErrorCode    ierr;
635:   PC_FieldSplitLink ilink = jac->head,next;

638:   while (ilink) {
639:     KSPDestroy(ilink->ksp);
640:     if (ilink->x) {VecDestroy(ilink->x);}
641:     if (ilink->y) {VecDestroy(ilink->y);}
642:     if (ilink->sctx) {VecScatterDestroy(ilink->sctx);}
643:     if (ilink->is) {ISDestroy(ilink->is);}
644:     next = ilink->next;
645:     PetscFree(ilink->fields);
646:     PetscFree(ilink);
647:     ilink = next;
648:   }
649:   PetscFree2(jac->x,jac->y);
650:   if (jac->mat && jac->mat != jac->pmat) {MatDestroyMatrices(jac->nsplits,&jac->mat);}
651:   if (jac->pmat) {MatDestroyMatrices(jac->nsplits,&jac->pmat);}
652:   if (jac->Afield) {MatDestroyMatrices(jac->nsplits,&jac->Afield);}
653:   if (jac->w1) {VecDestroy(jac->w1);}
654:   if (jac->w2) {VecDestroy(jac->w2);}
655:   if (jac->schur) {MatDestroy(jac->schur);}
656:   if (jac->schur_user) {MatDestroy(jac->schur_user);}
657:   if (jac->kspschur) {KSPDestroy(jac->kspschur);}
658:   if (jac->B) {MatDestroy(jac->B);}
659:   if (jac->C) {MatDestroy(jac->C);}
660:   PetscFree(jac);
661:   return(0);
662: }

666: static PetscErrorCode PCSetFromOptions_FieldSplit(PC pc)
667: {
668:   PetscErrorCode  ierr;
669:   PetscInt        i = 0,nfields,*fields,bs;
670:   PetscTruth      flg;
671:   char            optionname[128];
672:   PC_FieldSplit   *jac = (PC_FieldSplit*)pc->data;
673:   PCCompositeType ctype;

676:   PetscOptionsHead("FieldSplit options");
677:   PetscOptionsTruth("-pc_fieldsplit_real_diagonal","Use diagonal blocks of the operator","PCFieldSplitSetRealDiagonal",jac->realdiagonal,&jac->realdiagonal,PETSC_NULL);
678:   PetscOptionsInt("-pc_fieldsplit_block_size","Blocksize that defines number of fields","PCFieldSplitSetBlockSize",jac->bs,&bs,&flg);
679:   if (flg) {
680:     PCFieldSplitSetBlockSize(pc,bs);
681:   }

683:   PetscOptionsEnum("-pc_fieldsplit_type","Type of composition","PCFieldSplitSetType",PCCompositeTypes,(PetscEnum)jac->type,(PetscEnum*)&ctype,&flg);
684:   if (flg) {
685:     PCFieldSplitSetType(pc,ctype);
686:   }

688:   /* Only setup fields once */
689:   if ((jac->bs > 0) && (jac->nsplits == 0)) {
690:     /* only allow user to set fields from command line if bs is already known.
691:        otherwise user can set them in PCFieldSplitSetDefaults() */
692:     PetscMalloc(jac->bs*sizeof(PetscInt),&fields);
693:     while (PETSC_TRUE) {
694:       sprintf(optionname,"-pc_fieldsplit_%d_fields",(int)i++);
695:       nfields = jac->bs;
696:       PetscOptionsIntArray(optionname,"Fields in this split","PCFieldSplitSetFields",fields,&nfields,&flg);
697:       if (!flg) break;
698:       if (!nfields) SETERRQ(PETSC_ERR_USER,"Cannot list zero fields");
699:       PCFieldSplitSetFields(pc,nfields,fields);
700:     }
701:     PetscFree(fields);
702:   }
703:   PetscOptionsEnum("-pc_fieldsplit_schur_precondition","How to build preconditioner for Schur complement","PCFieldSplitSchurPrecondition",PCFieldSplitSchurPreTypes,(PetscEnum)jac->schurpre,(PetscEnum*)&jac->schurpre,PETSC_NULL);
704:   PetscOptionsTail();
705:   return(0);
706: }

708: /*------------------------------------------------------------------------------------*/

713: PetscErrorCode  PCFieldSplitSetFields_FieldSplit(PC pc,PetscInt n,PetscInt *fields)
714: {
715:   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
716:   PetscErrorCode    ierr;
717:   PC_FieldSplitLink ilink,next = jac->head;
718:   char              prefix[128];
719:   PetscInt          i;

722:   if (n <= 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Negative number of fields requested");
723:   for (i=0; i<n; i++) {
724:     if (fields[i] >= jac->bs) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Field %D requested but only %D exist",fields[i],jac->bs);
725:     if (fields[i] < 0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Negative field %D requested",fields[i]);
726:   }
727:   PetscNew(struct _PC_FieldSplitLink,&ilink);
728:   PetscMalloc(n*sizeof(PetscInt),&ilink->fields);
729:   PetscMemcpy(ilink->fields,fields,n*sizeof(PetscInt));
730:   ilink->nfields = n;
731:   ilink->next    = PETSC_NULL;
732:   KSPCreate(((PetscObject)pc)->comm,&ilink->ksp);
733:   PetscObjectIncrementTabLevel((PetscObject)ilink->ksp,(PetscObject)pc,1);
734:   KSPSetType(ilink->ksp,KSPPREONLY);

736:   if (((PetscObject)pc)->prefix) {
737:     sprintf(prefix,"%sfieldsplit_%d_",((PetscObject)pc)->prefix,(int)jac->nsplits);
738:   } else {
739:     sprintf(prefix,"fieldsplit_%d_",(int)jac->nsplits);
740:   }
741:   KSPSetOptionsPrefix(ilink->ksp,prefix);

743:   if (!next) {
744:     jac->head       = ilink;
745:     ilink->previous = PETSC_NULL;
746:   } else {
747:     while (next->next) {
748:       next = next->next;
749:     }
750:     next->next      = ilink;
751:     ilink->previous = next;
752:   }
753:   jac->nsplits++;
754:   return(0);
755: }

761: PetscErrorCode  PCFieldSplitGetSubKSP_FieldSplit_Schur(PC pc,PetscInt *n,KSP **subksp)
762: {
763:   PC_FieldSplit *jac = (PC_FieldSplit*)pc->data;

767:   PetscMalloc(jac->nsplits*sizeof(KSP),subksp);
768:   MatSchurComplementGetKSP(jac->schur,*subksp);
769:   (*subksp)[1] = jac->kspschur;
770:   *n = jac->nsplits;
771:   return(0);
772: }

778: PetscErrorCode  PCFieldSplitGetSubKSP_FieldSplit(PC pc,PetscInt *n,KSP **subksp)
779: {
780:   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
781:   PetscErrorCode    ierr;
782:   PetscInt          cnt = 0;
783:   PC_FieldSplitLink ilink = jac->head;

786:   PetscMalloc(jac->nsplits*sizeof(KSP*),subksp);
787:   while (ilink) {
788:     (*subksp)[cnt++] = ilink->ksp;
789:     ilink = ilink->next;
790:   }
791:   if (cnt != jac->nsplits) SETERRQ2(PETSC_ERR_PLIB,"Corrupt PCFIELDSPLIT object: number splits in linked list %D in object %D",cnt,jac->nsplits);
792:   *n = jac->nsplits;
793:   return(0);
794: }

800: PetscErrorCode  PCFieldSplitSetIS_FieldSplit(PC pc,IS is)
801: {
802:   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
803:   PetscErrorCode    ierr;
804:   PC_FieldSplitLink ilink, next = jac->head;
805:   char              prefix[128];

808:   PetscNew(struct _PC_FieldSplitLink,&ilink);
809:   ilink->is      = is;
810:   PetscObjectReference((PetscObject)is);
811:   ilink->next    = PETSC_NULL;
812:   KSPCreate(((PetscObject)pc)->comm,&ilink->ksp);
813:   PetscObjectIncrementTabLevel((PetscObject)ilink->ksp,(PetscObject)pc,1);
814:   KSPSetType(ilink->ksp,KSPPREONLY);

816:   if (((PetscObject)pc)->prefix) {
817:     sprintf(prefix,"%sfieldsplit_%d_",((PetscObject)pc)->prefix,(int)jac->nsplits);
818:   } else {
819:     sprintf(prefix,"fieldsplit_%d_",(int)jac->nsplits);
820:   }
821:   KSPSetOptionsPrefix(ilink->ksp,prefix);

823:   if (!next) {
824:     jac->head       = ilink;
825:     ilink->previous = PETSC_NULL;
826:   } else {
827:     while (next->next) {
828:       next = next->next;
829:     }
830:     next->next      = ilink;
831:     ilink->previous = next;
832:   }
833:   jac->nsplits++;

835:   return(0);
836: }

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

844:     Collective on PC

846:     Input Parameters:
847: +   pc  - the preconditioner context
848: .   n - the number of fields in this split
849: .   fields - the fields in this split

851:     Level: intermediate

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

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

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

862: @*/
863: PetscErrorCode  PCFieldSplitSetFields(PC pc,PetscInt n, PetscInt *fields)
864: {
865:   PetscErrorCode ierr,(*f)(PC,PetscInt,PetscInt *);

869:   PetscObjectQueryFunction((PetscObject)pc,"PCFieldSplitSetFields_C",(void (**)(void))&f);
870:   if (f) {
871:     (*f)(pc,n,fields);
872:   }
873:   return(0);
874: }

878: /*@
879:     PCFieldSplitSetIS - Sets the exact elements for field

881:     Collective on PC

883:     Input Parameters:
884: +   pc  - the preconditioner context
885: .   is - the index set that defines the vector elements in this field


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

890:     Level: intermediate

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

894: @*/
895: PetscErrorCode  PCFieldSplitSetIS(PC pc,IS is)
896: {
897:   PetscErrorCode ierr,(*f)(PC,IS);

902:   PetscObjectQueryFunction((PetscObject)pc,"PCFieldSplitSetIS_C",(void (**)(void))&f);
903:   if (f) {
904:     (*f)(pc,is);
905:   }
906:   return(0);
907: }

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

915:     Collective on PC

917:     Input Parameters:
918: +   pc  - the preconditioner context
919: -   bs - the block size

921:     Level: intermediate

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

925: @*/
926: PetscErrorCode  PCFieldSplitSetBlockSize(PC pc,PetscInt bs)
927: {
928:   PetscErrorCode ierr,(*f)(PC,PetscInt);

932:   PetscObjectQueryFunction((PetscObject)pc,"PCFieldSplitSetBlockSize_C",(void (**)(void))&f);
933:   if (f) {
934:     (*f)(pc,bs);
935:   }
936:   return(0);
937: }

941: /*@C
942:    PCFieldSplitGetSubKSP - Gets the KSP contexts for all splits
943:    
944:    Collective on KSP

946:    Input Parameter:
947: .  pc - the preconditioner context

949:    Output Parameters:
950: +  n - the number of split
951: -  pc - the array of KSP contexts

953:    Note:  
954:    After PCFieldSplitGetSubKSP() the array of KSPs IS to be freed by the user
955:    (not the KSP just the array that contains them).

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

959:    Level: advanced

961: .seealso: PCFIELDSPLIT
962: @*/
963: PetscErrorCode  PCFieldSplitGetSubKSP(PC pc,PetscInt *n,KSP *subksp[])
964: {
965:   PetscErrorCode ierr,(*f)(PC,PetscInt*,KSP **);

970:   PetscObjectQueryFunction((PetscObject)pc,"PCFieldSplitGetSubKSP_C",(void (**)(void))&f);
971:   if (f) {
972:     (*f)(pc,n,subksp);
973:   } else {
974:     SETERRQ(PETSC_ERR_ARG_WRONG,"Cannot get subksp for this type of PC");
975:   }
976:   return(0);
977: }

981: /*@
982:     PCFieldSplitSchurPrecondition -  Indicates if the Schur complement is preconditioned by a preconditioner constructed by the
983:       D matrix. Otherwise no preconditioner is used.

985:     Collective on PC

987:     Input Parameters:
988: +   pc  - the preconditioner context
989: .   ptype - which matrix to use for preconditioning the Schur complement
990: -   userpre - matrix to use for preconditioning, or PETSC_NULL

992:     Notes:
993:     The default is to use the block on the diagonal of the preconditioning matrix.  This is D, in the (1,1) position.
994:     There are currently no preconditioners that work directly with the Schur complement so setting
995:     PC_FIELDSPLIT_SCHUR_PRE_SELF is observationally equivalent to -fieldsplit_1_pc_type none.

997:     Options Database:
998: .     -pc_fieldsplit_schur_precondition <self,user,diag> default is diag

1000:     Level: intermediate

1002: .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetFields(), PCFieldSplitSchurPreType

1004: @*/
1005: PetscErrorCode  PCFieldSplitSchurPrecondition(PC pc,PCFieldSplitSchurPreType ptype,Mat pre)
1006: {
1007:   PetscErrorCode ierr,(*f)(PC,PCFieldSplitSchurPreType,Mat);

1011:   PetscObjectQueryFunction((PetscObject)pc,"PCFieldSplitSchurPrecondition_C",(void (**)(void))&f);
1012:   if (f) {
1013:     (*f)(pc,ptype,pre);
1014:   }
1015:   return(0);
1016: }

1021: PetscErrorCode  PCFieldSplitSchurPrecondition_FieldSplit(PC pc,PCFieldSplitSchurPreType ptype,Mat pre)
1022: {
1023:   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
1024:   PetscErrorCode  ierr;

1027:   jac->schurpre = ptype;
1028:   if (pre) {
1029:     if (jac->schur_user) {MatDestroy(jac->schur_user);}
1030:     jac->schur_user = pre;
1031:     PetscObjectReference((PetscObject)jac->schur_user);
1032:   }
1033:   return(0);
1034: }

1039: /*@C
1040:    PCFieldSplitGetSchurBlocks - Gets the all matrix blocks for the Schur complement
1041:    
1042:    Collective on KSP

1044:    Input Parameter:
1045: .  pc - the preconditioner context

1047:    Output Parameters:
1048: +  A - the (0,0) block
1049: .  B - the (0,1) block
1050: .  C - the (1,0) block
1051: -  D - the (1,1) block

1053:    Level: advanced

1055: .seealso: PCFIELDSPLIT
1056: @*/
1057: PetscErrorCode  PCFieldSplitGetSchurBlocks(PC pc,Mat *A,Mat *B,Mat *C, Mat *D)
1058: {
1059:   PC_FieldSplit *jac = (PC_FieldSplit *) pc->data;

1063:   if (jac->type != PC_COMPOSITE_SCHUR) {SETERRQ(PETSC_ERR_ARG_WRONG, "FieldSplit is not using a Schur complement approach.");}
1064:   if (A) *A = jac->pmat[0];
1065:   if (B) *B = jac->B;
1066:   if (C) *C = jac->C;
1067:   if (D) *D = jac->pmat[1];
1068:   return(0);
1069: }

1074: PetscErrorCode  PCFieldSplitSetType_FieldSplit(PC pc,PCCompositeType type)
1075: {
1076:   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;

1080:   jac->type = type;
1081:   if (type == PC_COMPOSITE_SCHUR) {
1082:     pc->ops->apply = PCApply_FieldSplit_Schur;
1083:     pc->ops->view  = PCView_FieldSplit_Schur;
1084:     PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitGetSubKSP_C","PCFieldSplitGetSubKSP_FieldSplit_Schur",PCFieldSplitGetSubKSP_FieldSplit_Schur);
1085:     PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSchurPrecondition_C","PCFieldSplitSchurPrecondition_FieldSplit",PCFieldSplitSchurPrecondition_FieldSplit);

1087:   } else {
1088:     pc->ops->apply = PCApply_FieldSplit;
1089:     pc->ops->view  = PCView_FieldSplit;
1090:     PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitGetSubKSP_C","PCFieldSplitGetSubKSP_FieldSplit",PCFieldSplitGetSubKSP_FieldSplit);
1091:     PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSchurPrecondition_C","",0);
1092:   }
1093:   return(0);
1094: }

1100: PetscErrorCode  PCFieldSplitSetBlockSize_FieldSplit(PC pc,PetscInt bs)
1101: {
1102:   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;

1105:   if (bs < 1) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Blocksize must be positive, you gave %D",bs);
1106:   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);
1107:   jac->bs = bs;
1108:   return(0);
1109: }

1114: /*@
1115:    PCFieldSplitSetType - Sets the type of fieldsplit preconditioner.
1116:    
1117:    Collective on PC

1119:    Input Parameter:
1120: .  pc - the preconditioner context
1121: .  type - PC_COMPOSITE_ADDITIVE, PC_COMPOSITE_MULTIPLICATIVE (default), PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE, PC_COMPOSITE_SPECIAL, PC_COMPOSITE_SCHUR

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

1126:    Level: Developer

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

1130: .seealso: PCCompositeSetType()

1132: @*/
1133: PetscErrorCode  PCFieldSplitSetType(PC pc,PCCompositeType type)
1134: {
1135:   PetscErrorCode ierr,(*f)(PC,PCCompositeType);

1139:   PetscObjectQueryFunction((PetscObject)pc,"PCFieldSplitSetType_C",(void (**)(void))&f);
1140:   if (f) {
1141:     (*f)(pc,type);
1142:   }
1143:   return(0);
1144: }

1146: /* -------------------------------------------------------------------------------------*/
1147: /*MC
1148:    PCFIELDSPLIT - Preconditioner created by combining separate preconditioners for individual
1149:                   fields or groups of fields


1152:      To set options on the solvers for each block append -fieldsplit_ to all the PC
1153:         options database keys. For example, -fieldsplit_pc_type ilu -fieldsplit_pc_factor_levels 1
1154:         
1155:      To set the options on the solvers separate for each block call PCFieldSplitGetSubKSP()
1156:          and set the options directly on the resulting KSP object

1158:    Level: intermediate

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

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


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

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

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

1186:      For the Schur complement preconditioner if J = ( A B )
1187:                                                     ( C D )
1188:      the preconditioner is 
1189:               (I   -B inv(A)) ( inv(A)   0    ) (I         0  )
1190:               (0    I       ) (   0    inv(S) ) (-C inv(A) I  )
1191:      where the action of inv(A) is applied using the KSP solver with prefix -fieldsplit_0_. The action of 
1192:      inv(S) is computed using the KSP solver with prefix -schur_. For PCFieldSplitGetKSP() when field number is
1193:      0 it returns the KSP associated with -fieldsplit_0_ while field number 1 gives -fieldsplit_1_ KSP. By default
1194:      D is used to construct a preconditioner for S, use PCFieldSplitSchurPrecondition() to turn on or off this
1195:      option.
1196:      
1197:      If only one set of indices (one IS) is provided with PCFieldSplitSetIS() then the complement of that IS
1198:      is used automatically for a second block.

1200:    Concepts: physics based preconditioners, block preconditioners

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

1209: PetscErrorCode  PCCreate_FieldSplit(PC pc)
1210: {
1212:   PC_FieldSplit  *jac;

1215:   PetscNewLog(pc,PC_FieldSplit,&jac);
1216:   jac->bs        = -1;
1217:   jac->nsplits   = 0;
1218:   jac->type      = PC_COMPOSITE_MULTIPLICATIVE;
1219:   jac->schurpre  = PC_FIELDSPLIT_SCHUR_PRE_USER; /* Try user preconditioner first, fall back on diagonal */

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

1223:   pc->ops->apply             = PCApply_FieldSplit;
1224:   pc->ops->applytranspose    = PCApplyTranspose_FieldSplit;
1225:   pc->ops->setup             = PCSetUp_FieldSplit;
1226:   pc->ops->destroy           = PCDestroy_FieldSplit;
1227:   pc->ops->setfromoptions    = PCSetFromOptions_FieldSplit;
1228:   pc->ops->view              = PCView_FieldSplit;
1229:   pc->ops->applyrichardson   = 0;

1231:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitGetSubKSP_C","PCFieldSplitGetSubKSP_FieldSplit",
1232:                     PCFieldSplitGetSubKSP_FieldSplit);
1233:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetFields_C","PCFieldSplitSetFields_FieldSplit",
1234:                     PCFieldSplitSetFields_FieldSplit);
1235:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetIS_C","PCFieldSplitSetIS_FieldSplit",
1236:                     PCFieldSplitSetIS_FieldSplit);
1237:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetType_C","PCFieldSplitSetType_FieldSplit",
1238:                     PCFieldSplitSetType_FieldSplit);
1239:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetBlockSize_C","PCFieldSplitSetBlockSize_FieldSplit",
1240:                     PCFieldSplitSetBlockSize_FieldSplit);
1241:   return(0);
1242: }


1246: /*MC
1247:    Block_Preconditioners - PETSc provides support for a variety of "block preconditioners", this provides an
1248:           overview of these methods. 

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

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

1256:       One of the goals of the PCFieldSplit preconditioner in PETSc is to provide a variety of preconditioners
1257:       for this block system.
1258:    
1259:       Consider an additional matrix (Ap  Bp)
1260:                                     (Cp  Dp) where some or all of the entries may be the same as
1261:       in the original matrix (for example Ap == A).

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

1266:       Block Jacobi:   x_1 = A^ b_1
1267:                       x_2 = D^ b_2

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

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

1276:    Level: intermediate

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