Actual source code: precon.c

  1: /*$Id: precon.c,v 1.216 2001/08/21 21:03:13 bsmith Exp $*/
  2: /*
  3:     The PC (preconditioner) interface routines, callable by users.
  4: */
 5:  #include src/sles/pc/pcimpl.h

  7: /* Logging support */
  8: int PC_COOKIE;
  9: int PC_SetUp, PC_SetUpOnBlocks, PC_Apply, PC_ApplyCoarse, PC_ApplyMultiple, PC_ApplySymmetricLeft;
 10: int PC_ApplySymmetricRight, PC_ModifySubMatrices;

 12: EXTERN int SLESInitializePackage(char *);

 14: /*@C
 15:    PCNullSpaceAttach - attaches a null space to a preconditioner object.
 16:         This null space will be removed from the resulting vector whenever
 17:         the preconditioner is applied.

 19:    Collective on PC

 21:    Input Parameters:
 22: +  pc - the preconditioner context
 23: -  nullsp - the null space object

 25:    Level: developer

 27:    Notes:
 28:       Overwrites any previous null space that may have been attached

 30: .keywords: PC, destroy, null space

 32: .seealso: PCCreate(), PCSetUp()
 33: @*/
 34: int PCNullSpaceAttach(PC pc,MatNullSpace nullsp)
 35: {


 42:   if (pc->nullsp) {
 43:     MatNullSpaceDestroy(pc->nullsp);
 44:   }
 45:   pc->nullsp = nullsp;
 46:   PetscObjectReference((PetscObject)nullsp);
 47:   return(0);
 48: }

 50: /*@C
 51:    PCDestroy - Destroys PC context that was created with PCCreate().

 53:    Collective on PC

 55:    Input Parameter:
 56: .  pc - the preconditioner context

 58:    Level: developer

 60: .keywords: PC, destroy

 62: .seealso: PCCreate(), PCSetUp()
 63: @*/
 64: int PCDestroy(PC pc)
 65: {

 70:   if (--pc->refct > 0) return(0);

 72:   /* if memory was published with AMS then destroy it */
 73:   PetscObjectDepublish(pc);

 75:   if (pc->ops->destroy)       { (*pc->ops->destroy)(pc);}
 76:   if (pc->nullsp)             {MatNullSpaceDestroy(pc->nullsp);}
 77:   if (pc->diagonalscaleright) {VecDestroy(pc->diagonalscaleright);}
 78:   if (pc->diagonalscaleleft)  {VecDestroy(pc->diagonalscaleleft);}

 80:   PetscLogObjectDestroy(pc);
 81:   PetscHeaderDestroy(pc);
 82:   return(0);
 83: }

 85: /*@C
 86:    PCDiagonalScale - Indicates if the preconditioner applies an additional left and right
 87:       scaling as needed by certain time-stepping codes.

 89:    Collective on PC

 91:    Input Parameter:
 92: .  pc - the preconditioner context

 94:    Output Parameter:
 95: .  flag - PETSC_TRUE if it applies the scaling

 97:    Level: developer

 99:    Notes: If this returns PETSC_TRUE then the system solved via the Krylov method is
100: $           D M A D^{-1} y = D M b  for left preconditioning or
101: $           D A M D^{-1} z = D b for right preconditioning

103: .keywords: PC

105: .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleLeft(), PCDiagonalScaleRight(), PCDiagonalScaleSet()
106: @*/
107: int PCDiagonalScale(PC pc,PetscTruth *flag)
108: {
111:   *flag = pc->diagonalscale;
112:   return(0);
113: }

115: /*@C
116:    PCDiagonalScaleSet - Indicates the left scaling to use to apply an additional left and right
117:       scaling as needed by certain time-stepping codes.

119:    Collective on PC

121:    Input Parameters:
122: +  pc - the preconditioner context
123: -  s - scaling vector

125:    Level: intermediate

127:    Notes: The system solved via the Krylov method is
128: $           D M A D^{-1} y = D M b  for left preconditioning or
129: $           D A M D^{-1} z = D b for right preconditioning

131:    PCDiagonalScaleLeft() scales a vector by D. PCDiagonalScaleRight() scales a vector by D^{-1}.

133: .keywords: PC

135: .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleLeft(), PCDiagonalScaleRight(), PCDiagonalScale()
136: @*/
137: int PCDiagonalScaleSet(PC pc,Vec s)
138: {

144:   pc->diagonalscale     = PETSC_TRUE;
145:   if (pc->diagonalscaleleft) {
146:     VecDestroy(pc->diagonalscaleleft);
147:   }
148:   pc->diagonalscaleleft = s;
149:   ierr                  = PetscObjectReference((PetscObject)s);
150:   if (!pc->diagonalscaleright) {
151:     VecDuplicate(s,&pc->diagonalscaleright);
152:   }
153:   VecCopy(s,pc->diagonalscaleright);
154:   VecReciprocal(pc->diagonalscaleright);
155:   return(0);
156: }

158: /*@C
159:    PCDiagonalScaleLeft - Indicates the left scaling to use to apply an additional left and right
160:       scaling as needed by certain time-stepping codes.

162:    Collective on PC

164:    Input Parameters:
165: +  pc - the preconditioner context
166: .  in - input vector
167: +  out - scaled vector (maybe the same as in)

169:    Level: intermediate

171:    Notes: The system solved via the Krylov method is
172: $           D M A D^{-1} y = D M b  for left preconditioning or
173: $           D A M D^{-1} z = D b for right preconditioning

175:    PCDiagonalScaleLeft() scales a vector by D. PCDiagonalScaleRight() scales a vector by D^{-1}.

177:    If diagonal scaling is turned off and in is not out then in is copied to out

179: .keywords: PC

181: .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleSet(), PCDiagonalScaleRight(), PCDiagonalScale()
182: @*/
183: int PCDiagonalScaleLeft(PC pc,Vec in,Vec out)
184: {

191:   if (pc->diagonalscale) {
192:     VecPointwiseMult(pc->diagonalscaleleft,in,out);
193:   } else if (in != out) {
194:     VecCopy(in,out);
195:   }
196:   return(0);
197: }

199: /*@C
200:    PCDiagonalScaleRight - Scales a vector by the right scaling as needed by certain time-stepping codes.

202:    Collective on PC

204:    Input Parameters:
205: +  pc - the preconditioner context
206: .  in - input vector
207: +  out - scaled vector (maybe the same as in)

209:    Level: intermediate

211:    Notes: The system solved via the Krylov method is
212: $           D M A D^{-1} y = D M b  for left preconditioning or
213: $           D A M D^{-1} z = D b for right preconditioning

215:    PCDiagonalScaleLeft() scales a vector by D. PCDiagonalScaleRight() scales a vector by D^{-1}.

217:    If diagonal scaling is turned off and in is not out then in is copied to out

219: .keywords: PC

221: .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleLeft(), PCDiagonalScaleSet(), PCDiagonalScale()
222: @*/
223: int PCDiagonalScaleRight(PC pc,Vec in,Vec out)
224: {

231:   if (pc->diagonalscale) {
232:     VecPointwiseMult(pc->diagonalscaleright,in,out);
233:   } else if (in != out) {
234:     VecCopy(in,out);
235:   }
236:   return(0);
237: }

239: static int PCPublish_Petsc(PetscObject obj)
240: {
241: #if defined(PETSC_HAVE_AMS)
242:   PC          v = (PC) obj;
243:   int         ierr;
244: #endif


248: #if defined(PETSC_HAVE_AMS)
249:   /* if it is already published then return */
250:   if (v->amem >=0) return(0);

252:   PetscObjectPublishBaseBegin(obj);
253:   PetscObjectPublishBaseEnd(obj);
254: #endif

256:   return(0);
257: }

259: /*@C
260:    PCCreate - Creates a preconditioner context.

262:    Collective on MPI_Comm

264:    Input Parameter:
265: .  comm - MPI communicator 

267:    Output Parameter:
268: .  pc - location to put the preconditioner context

270:    Notes:
271:    The default preconditioner on one processor is PCILU with 0 fill on more 
272:    then one it is PCBJACOBI with ILU() on each processor.

274:    Level: developer

276: .keywords: PC, create, context

278: .seealso: PCSetUp(), PCApply(), PCDestroy()
279: @*/
280: int PCCreate(MPI_Comm comm,PC *newpc)
281: {
282:   PC  pc;

287:   *newpc = 0;
288: #ifndef PETSC_USE_DYNAMIC_LIBRARIES
289:   SLESInitializePackage(PETSC_NULL);
290: #endif

292:   PetscHeaderCreate(pc,_p_PC,struct _PCOps,PC_COOKIE,-1,"PC",comm,PCDestroy,PCView);
293:   PetscLogObjectCreate(pc);
294:   pc->bops->publish      = PCPublish_Petsc;
295:   pc->vec                = 0;
296:   pc->mat                = 0;
297:   pc->setupcalled        = 0;
298:   pc->nullsp             = 0;
299:   pc->data               = 0;
300:   pc->diagonalscale      = PETSC_FALSE;
301:   pc->diagonalscaleleft  = 0;
302:   pc->diagonalscaleright = 0;

304:   pc->ops->destroy             = 0;
305:   pc->ops->apply               = 0;
306:   pc->ops->applytranspose      = 0;
307:   pc->ops->applyBA             = 0;
308:   pc->ops->applyBAtranspose    = 0;
309:   pc->ops->applyrichardson     = 0;
310:   pc->ops->view                = 0;
311:   pc->ops->getfactoredmatrix   = 0;
312:   pc->ops->applysymmetricright = 0;
313:   pc->ops->applysymmetricleft  = 0;
314:   pc->ops->setuponblocks       = 0;

316:   pc->modifysubmatrices   = 0;
317:   pc->modifysubmatricesP  = 0;
318:   *newpc                  = pc;
319:   PetscPublishAll(pc);
320:   return(0);

322: }

324: /* -------------------------------------------------------------------------------*/

326: /*@
327:    PCApply - Applies the preconditioner to a vector.

329:    Collective on PC and Vec

331:    Input Parameters:
332: +  pc - the preconditioner context
333: -  x - input vector

335:    Output Parameter:
336: .  y - output vector

338:    Level: developer

340: .keywords: PC, apply

342: .seealso: PCApplyTranspose(), PCApplyBAorAB()
343: @*/
344: int PCApply(PC pc,Vec x,Vec y)
345: {
346:   int        ierr;

352:   if (x == y) SETERRQ(PETSC_ERR_ARG_IDN,"x and y must be different vectors");

354:   if (pc->setupcalled < 2) {
355:     PCSetUp(pc);
356:   }

358:   PetscLogEventBegin(PC_Apply,pc,x,y,0);
359:   (*pc->ops->apply)(pc,x,y);
360:   PetscLogEventEnd(PC_Apply,pc,x,y,0);

362:   /* Remove null space from preconditioned vector y */
363:   if (pc->nullsp) {
364:     MatNullSpaceRemove(pc->nullsp,y,PETSC_NULL);
365:   }
366:   return(0);
367: }

369: /*@
370:    PCApplySymmetricLeft - Applies the left part of a symmetric preconditioner to a vector.

372:    Collective on PC and Vec

374:    Input Parameters:
375: +  pc - the preconditioner context
376: -  x - input vector

378:    Output Parameter:
379: .  y - output vector

381:    Notes:
382:    Currently, this routine is implemented only for PCICC and PCJACOBI preconditioners.

384:    Level: developer

386: .keywords: PC, apply, symmetric, left

388: .seealso: PCApply(), PCApplySymmetricRight()
389: @*/
390: int PCApplySymmetricLeft(PC pc,Vec x,Vec y)
391: {

398:   if (!pc->ops->applysymmetricleft) SETERRQ(1,"PC does not have left symmetric apply");

400:   if (pc->setupcalled < 2) {
401:     PCSetUp(pc);
402:   }

404:   PetscLogEventBegin(PC_ApplySymmetricLeft,pc,x,y,0);
405:   (*pc->ops->applysymmetricleft)(pc,x,y);
406:   PetscLogEventEnd(PC_ApplySymmetricLeft,pc,x,y,0);
407:   return(0);
408: }

410: /*@
411:    PCApplySymmetricRight - Applies the right part of a symmetric preconditioner to a vector.

413:    Collective on PC and Vec

415:    Input Parameters:
416: +  pc - the preconditioner context
417: -  x - input vector

419:    Output Parameter:
420: .  y - output vector

422:    Level: developer

424:    Notes:
425:    Currently, this routine is implemented only for PCICC and PCJACOBI preconditioners.

427: .keywords: PC, apply, symmetric, right

429: .seealso: PCApply(), PCApplySymmetricLeft()
430: @*/
431: int PCApplySymmetricRight(PC pc,Vec x,Vec y)
432: {

439:   if (!pc->ops->applysymmetricright) SETERRQ(1,"PC does not have left symmetric apply");

441:   if (pc->setupcalled < 2) {
442:     PCSetUp(pc);
443:   }

445:   PetscLogEventBegin(PC_ApplySymmetricRight,pc,x,y,0);
446:   (*pc->ops->applysymmetricright)(pc,x,y);
447:   PetscLogEventEnd(PC_ApplySymmetricRight,pc,x,y,0);
448:   return(0);
449: }

451: /*@
452:    PCApplyTranspose - Applies the transpose of preconditioner to a vector.

454:    Collective on PC and Vec

456:    Input Parameters:
457: +  pc - the preconditioner context
458: -  x - input vector

460:    Output Parameter:
461: .  y - output vector

463:    Level: developer

465: .keywords: PC, apply, transpose

467: .seealso: PCApplyTranspose(), PCApplyBAorAB(), PCApplyBAorABTranspose()
468: @*/
469: int PCApplyTranspose(PC pc,Vec x,Vec y)
470: {

477:   if (x == y) SETERRQ(PETSC_ERR_ARG_IDN,"x and y must be different vectors");
478:   if (!pc->ops->applytranspose) SETERRQ(PETSC_ERR_SUP," ");

480:   if (pc->setupcalled < 2) {
481:     PCSetUp(pc);
482:   }

484:   PetscLogEventBegin(PC_Apply,pc,x,y,0);
485:   (*pc->ops->applytranspose)(pc,x,y);
486:   PetscLogEventEnd(PC_Apply,pc,x,y,0);
487:   return(0);
488: }

490: /*@
491:    PCApplyBAorAB - Applies the preconditioner and operator to a vector. 

493:    Collective on PC and Vec

495:    Input Parameters:
496: +  pc - the preconditioner context
497: .  side - indicates the preconditioner side, one of PC_LEFT, PC_RIGHT, or PC_SYMMETRIC
498: .  x - input vector
499: -  work - work vector

501:    Output Parameter:
502: .  y - output vector

504:    Level: developer

506: .keywords: PC, apply, operator

508: .seealso: PCApply(), PCApplyTranspose(), PCApplyBAorABTranspose()
509: @*/
510: int PCApplyBAorAB(PC pc,PCSide side,Vec x,Vec y,Vec work)
511: {
512:   int        ierr;

519:   if (x == y) SETERRQ(PETSC_ERR_ARG_IDN,"x and y must be different vectors");
520:   if (side != PC_LEFT && side != PC_SYMMETRIC && side != PC_RIGHT) {
521:     SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Side must be right, left, or symmetric");
522:   }
523:   if (pc->diagonalscale && side == PC_SYMMETRIC) {
524:     SETERRQ(1,"Cannot include diagonal scaling with symmetric preconditioner application");
525:   }

527:   if (pc->setupcalled < 2) {
528:     PCSetUp(pc);
529:   }

531:   if (pc->diagonalscale) {
532:     if (pc->ops->applyBA) {
533:       Vec work2; /* this is expensive, but to fix requires a second work vector argument to PCApplyBAorAB() */
534:       VecDuplicate(x,&work2);
535:       PCDiagonalScaleRight(pc,x,work2);
536:       (*pc->ops->applyBA)(pc,side,work2,y,work);
537:       /* Remove null space from preconditioned vector y */
538:       if (pc->nullsp) {
539:         MatNullSpaceRemove(pc->nullsp,y,PETSC_NULL);
540:       }
541:       PCDiagonalScaleLeft(pc,y,y);
542:       VecDestroy(work2);
543:     } else if (side == PC_RIGHT) {
544:       PCDiagonalScaleRight(pc,x,y);
545:       PCApply(pc,y,work);
546:       MatMult(pc->mat,work,y);
547:       PCDiagonalScaleLeft(pc,y,y);
548:     } else if (side == PC_LEFT) {
549:       PCDiagonalScaleRight(pc,x,y);
550:       MatMult(pc->mat,y,work);
551:       PCApply(pc,work,y);
552:       PCDiagonalScaleLeft(pc,y,y);
553:     } else if (side == PC_SYMMETRIC) {
554:       SETERRQ(1,"Cannot provide diagonal scaling with symmetric application of preconditioner");
555:     }
556:   } else {
557:     if (pc->ops->applyBA) {
558:       (*pc->ops->applyBA)(pc,side,x,y,work);
559:       /* Remove null space from preconditioned vector y */
560:       if (pc->nullsp) {
561:         MatNullSpaceRemove(pc->nullsp,y,PETSC_NULL);
562:       }
563:     } else if (side == PC_RIGHT) {
564:       PCApply(pc,x,work);
565:       MatMult(pc->mat,work,y);
566:     } else if (side == PC_LEFT) {
567:       MatMult(pc->mat,x,work);
568:       PCApply(pc,work,y);
569:     } else if (side == PC_SYMMETRIC) {
570:       /* There's an extra copy here; maybe should provide 2 work vectors instead? */
571:       PCApplySymmetricRight(pc,x,work);
572:       MatMult(pc->mat,work,y);
573:       VecCopy(y,work);
574:       PCApplySymmetricLeft(pc,work,y);
575:     }
576:   }
577:   return(0);
578: }

580: /*@ 
581:    PCApplyBAorABTranspose - Applies the transpose of the preconditioner
582:    and operator to a vector. That is, applies tr(B) * tr(A) with left preconditioning,
583:    not tr(B*A) = tr(A)*tr(B).

585:    Collective on PC and Vec

587:    Input Parameters:
588: +  pc - the preconditioner context
589: .  side - indicates the preconditioner side, one of PC_LEFT, PC_RIGHT, or PC_SYMMETRIC
590: .  x - input vector
591: -  work - work vector

593:    Output Parameter:
594: .  y - output vector

596:    Level: developer

598: .keywords: PC, apply, operator, transpose

600: .seealso: PCApply(), PCApplyTranspose(), PCApplyBAorAB()
601: @*/
602: int PCApplyBAorABTranspose(PC pc,PCSide side,Vec x,Vec y,Vec work)
603: {

611:   if (x == y) SETERRQ(PETSC_ERR_ARG_IDN,"x and y must be different vectors");
612:   if (pc->ops->applyBAtranspose) {
613:     (*pc->ops->applyBAtranspose)(pc,side,x,y,work);
614:     return(0);
615:   }
616:   if (side != PC_LEFT && side != PC_RIGHT) {
617:     SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Side must be right or left");
618:   }

620:   if (pc->setupcalled < 2) {
621:     PCSetUp(pc);
622:   }

624:   if (side == PC_RIGHT) {
625:     PCApplyTranspose(pc,x,work);
626:     MatMultTranspose(pc->mat,work,y);
627:   } else if (side == PC_LEFT) {
628:     MatMultTranspose(pc->mat,x,work);
629:     PCApplyTranspose(pc,work,y);
630:   }
631:   /* add support for PC_SYMMETRIC */
632:   return(0); /* actually will never get here */
633: }

635: /* -------------------------------------------------------------------------------*/

637: /*@
638:    PCApplyRichardsonExists - Determines whether a particular preconditioner has a 
639:    built-in fast application of Richardson's method.

641:    Not Collective

643:    Input Parameter:
644: .  pc - the preconditioner

646:    Output Parameter:
647: .  exists - PETSC_TRUE or PETSC_FALSE

649:    Level: developer

651: .keywords: PC, apply, Richardson, exists

653: .seealso: PCApplyRichardson()
654: @*/
655: int PCApplyRichardsonExists(PC pc,PetscTruth *exists)
656: {
660:   if (pc->ops->applyrichardson) *exists = PETSC_TRUE;
661:   else                    *exists = PETSC_FALSE;
662:   return(0);
663: }

665: /*@
666:    PCApplyRichardson - Applies several steps of Richardson iteration with 
667:    the particular preconditioner. This routine is usually used by the 
668:    Krylov solvers and not the application code directly.

670:    Collective on PC

672:    Input Parameters:
673: +  pc  - the preconditioner context
674: .  x   - the initial guess 
675: .  w   - one work vector
676: .  rtol - relative decrease in residual norm convergence criteria
677: .  atol - absolute residual norm convergence criteria
678: .  dtol - divergence residual norm increase criteria
679: -  its - the number of iterations to apply.

681:    Output Parameter:
682: .  y - the solution

684:    Notes: 
685:    Most preconditioners do not support this function. Use the command
686:    PCApplyRichardsonExists() to determine if one does.

688:    Except for the multigrid PC this routine ignores the convergence tolerances
689:    and always runs for the number of iterations
690:  
691:    Level: developer

693: .keywords: PC, apply, Richardson

695: .seealso: PCApplyRichardsonExists()
696: @*/
697: int PCApplyRichardson(PC pc,Vec x,Vec y,Vec w,PetscReal rtol,PetscReal atol, PetscReal dtol,int its)
698: {

706:   if (!pc->ops->applyrichardson) SETERRQ(PETSC_ERR_SUP," ");

708:   if (pc->setupcalled < 2) {
709:     PCSetUp(pc);
710:   }

712:   (*pc->ops->applyrichardson)(pc,x,y,w,rtol,atol,dtol,its);
713:   return(0);
714: }

716: /* 
717:       a setupcall of 0 indicates never setup, 
718:                      1 needs to be resetup,
719:                      2 does not need any changes.
720: */
721: /*@
722:    PCSetUp - Prepares for the use of a preconditioner.

724:    Collective on PC

726:    Input Parameter:
727: .  pc - the preconditioner context

729:    Level: developer

731: .keywords: PC, setup

733: .seealso: PCCreate(), PCApply(), PCDestroy()
734: @*/
735: int PCSetUp(PC pc)
736: {


742:   if (pc->setupcalled > 1) {
743:     PetscLogInfo(pc,"PCSetUp:Setting PC with identical preconditionern");
744:     return(0);
745:   } else if (pc->setupcalled == 0) {
746:     PetscLogInfo(pc,"PCSetUp:Setting up new PCn");
747:   } else if (pc->flag == SAME_NONZERO_PATTERN) {
748:     PetscLogInfo(pc,"PCSetUp:Setting up PC with same nonzero patternn");
749:   } else {
750:     PetscLogInfo(pc,"PCSetUp:Setting up PC with different nonzero patternn");
751:   }

753:   PetscLogEventBegin(PC_SetUp,pc,0,0,0);
754:   if (!pc->vec) {SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Vector must be set first");}
755:   if (!pc->mat) {SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Matrix must be set first");}
756:   if (!pc->type_name) {
757:     int size;

759:     MPI_Comm_size(pc->comm,&size);
760:     if (size == 1) {
761:       PCSetType(pc,PCILU);
762:     } else {
763:       PCSetType(pc,PCBJACOBI);
764:     }
765:   }
766:   if (pc->ops->setup) {
767:     (*pc->ops->setup)(pc);
768:   }
769:   pc->setupcalled = 2;
770:   if (pc->nullsp) {
771:     PetscTruth test;
772:     PetscOptionsHasName(pc->prefix,"-pc_test_null_space",&test);
773:     if (test) {
774:       MatNullSpaceTest(pc->nullsp,pc->mat);
775:     }
776:   }
777:   PetscLogEventEnd(PC_SetUp,pc,0,0,0);
778:   return(0);
779: }

781: /*@
782:    PCSetUpOnBlocks - Sets up the preconditioner for each block in
783:    the block Jacobi, block Gauss-Seidel, and overlapping Schwarz 
784:    methods.

786:    Collective on PC

788:    Input Parameters:
789: .  pc - the preconditioner context

791:    Level: developer

793: .keywords: PC, setup, blocks

795: .seealso: PCCreate(), PCApply(), PCDestroy(), PCSetUp()
796: @*/
797: int PCSetUpOnBlocks(PC pc)
798: {

803:   if (!pc->ops->setuponblocks) return(0);
804:   PetscLogEventBegin(PC_SetUpOnBlocks,pc,0,0,0);
805:   (*pc->ops->setuponblocks)(pc);
806:   PetscLogEventEnd(PC_SetUpOnBlocks,pc,0,0,0);
807:   return(0);
808: }

810: /*@
811:    PCSetModifySubMatrices - Sets a user-defined routine for modifying the
812:    submatrices that arise within certain subdomain-based preconditioners.
813:    The basic submatrices are extracted from the preconditioner matrix as
814:    usual; the user can then alter these (for example, to set different boundary
815:    conditions for each submatrix) before they are used for the local solves.

817:    Collective on PC

819:    Input Parameters:
820: +  pc - the preconditioner context
821: .  func - routine for modifying the submatrices
822: -  ctx - optional user-defined context (may be null)

824:    Calling sequence of func:
825: $     func (PC pc,int nsub,IS *row,IS *col,Mat *submat,void *ctx);

827: .  row - an array of index sets that contain the global row numbers
828:          that comprise each local submatrix
829: .  col - an array of index sets that contain the global column numbers
830:          that comprise each local submatrix
831: .  submat - array of local submatrices
832: -  ctx - optional user-defined context for private data for the 
833:          user-defined func routine (may be null)

835:    Notes:
836:    PCSetModifySubMatrices() MUST be called before SLESSetUp() and
837:    SLESSolve().

839:    A routine set by PCSetModifySubMatrices() is currently called within
840:    the block Jacobi (PCBJACOBI) and additive Schwarz (PCASM)
841:    preconditioners.  All other preconditioners ignore this routine.

843:    Level: advanced

845: .keywords: PC, set, modify, submatrices

847: .seealso: PCModifySubMatrices()
848: @*/
849: int PCSetModifySubMatrices(PC pc,int(*func)(PC,int,IS*,IS*,Mat*,void*),void *ctx)
850: {
853:   pc->modifysubmatrices  = func;
854:   pc->modifysubmatricesP = ctx;
855:   return(0);
856: }

858: /*@
859:    PCModifySubMatrices - Calls an optional user-defined routine within 
860:    certain preconditioners if one has been set with PCSetModifySubMarices().

862:    Collective on PC

864:    Input Parameters:
865: +  pc - the preconditioner context
866: .  nsub - the number of local submatrices
867: .  row - an array of index sets that contain the global row numbers
868:          that comprise each local submatrix
869: .  col - an array of index sets that contain the global column numbers
870:          that comprise each local submatrix
871: .  submat - array of local submatrices
872: -  ctx - optional user-defined context for private data for the 
873:          user-defined routine (may be null)

875:    Output Parameter:
876: .  submat - array of local submatrices (the entries of which may
877:             have been modified)

879:    Notes:
880:    The user should NOT generally call this routine, as it will
881:    automatically be called within certain preconditioners (currently
882:    block Jacobi, additive Schwarz) if set.

884:    The basic submatrices are extracted from the preconditioner matrix
885:    as usual; the user can then alter these (for example, to set different
886:    boundary conditions for each submatrix) before they are used for the
887:    local solves.

889:    Level: developer

891: .keywords: PC, modify, submatrices

893: .seealso: PCSetModifySubMatrices()
894: @*/
895: int PCModifySubMatrices(PC pc,int nsub,IS *row,IS *col,Mat *submat,void *ctx)
896: {

900:   if (!pc->modifysubmatrices) return(0);
901:   PetscLogEventBegin(PC_ModifySubMatrices,pc,0,0,0);
902:   (*pc->modifysubmatrices)(pc,nsub,row,col,submat,ctx);
903:   PetscLogEventEnd(PC_ModifySubMatrices,pc,0,0,0);
904:   return(0);
905: }

907: /*@
908:    PCSetOperators - Sets the matrix associated with the linear system and 
909:    a (possibly) different one associated with the preconditioner.

911:    Collective on PC and Mat

913:    Input Parameters:
914: +  pc - the preconditioner context
915: .  Amat - the matrix associated with the linear system
916: .  Pmat - the matrix to be used in constructing the preconditioner, usually
917:           the same as Amat. 
918: -  flag - flag indicating information about the preconditioner matrix structure
919:    during successive linear solves.  This flag is ignored the first time a
920:    linear system is solved, and thus is irrelevant when solving just one linear
921:    system.

923:    Notes: 
924:    The flag can be used to eliminate unnecessary work in the preconditioner 
925:    during the repeated solution of linear systems of the same size.  The 
926:    available options are
927: +    SAME_PRECONDITIONER -
928:        Pmat is identical during successive linear solves.
929:        This option is intended for folks who are using
930:        different Amat and Pmat matrices and wish to reuse the
931:        same preconditioner matrix.  For example, this option
932:        saves work by not recomputing incomplete factorization
933:        for ILU/ICC preconditioners.
934: .     SAME_NONZERO_PATTERN -
935:        Pmat has the same nonzero structure during
936:        successive linear solves. 
937: -     DIFFERENT_NONZERO_PATTERN -
938:        Pmat does not have the same nonzero structure.

940:    Caution:
941:    If you specify SAME_NONZERO_PATTERN, PETSc believes your assertion
942:    and does not check the structure of the matrix.  If you erroneously
943:    claim that the structure is the same when it actually is not, the new
944:    preconditioner will not function correctly.  Thus, use this optimization
945:    feature carefully!

947:    If in doubt about whether your preconditioner matrix has changed
948:    structure or not, use the flag DIFFERENT_NONZERO_PATTERN.

950:    More Notes about Repeated Solution of Linear Systems:
951:    PETSc does NOT reset the matrix entries of either Amat or Pmat
952:    to zero after a linear solve; the user is completely responsible for
953:    matrix assembly.  See the routine MatZeroEntries() if desiring to
954:    zero all elements of a matrix.

956:    Level: developer

958: .keywords: PC, set, operators, matrix, linear system

960: .seealso: PCGetOperators(), MatZeroEntries()
961:  @*/
962: int PCSetOperators(PC pc,Mat Amat,Mat Pmat,MatStructure flag)
963: {
964:   int        ierr;
965:   PetscTruth isbjacobi,isrowbs;


972:   /*
973:       BlockSolve95 cannot use default BJacobi preconditioning
974:   */
975:   PetscTypeCompare((PetscObject)Amat,MATMPIROWBS,&isrowbs);
976:   if (isrowbs) {
977:     PetscTypeCompare((PetscObject)pc,PCBJACOBI,&isbjacobi);
978:     if (isbjacobi) {
979:       PCSetType(pc,PCILU);
980:       PetscLogInfo(pc,"PCSetOperators:Switching default PC to PCILU since BS95 doesn't support PCBJACOBIn");
981:     }
982:   }

984:   pc->mat  = Amat;
985:   pc->pmat = Pmat;
986:   if (pc->setupcalled == 2 && flag != SAME_PRECONDITIONER) {
987:     pc->setupcalled = 1;
988:   }
989:   pc->flag = flag;
990:   return(0);
991: }

993: /*@C
994:    PCGetOperators - Gets the matrix associated with the linear system and
995:    possibly a different one associated with the preconditioner.

997:    Not collective, though parallel Mats are returned if the PC is parallel

999:    Input Parameter:
1000: .  pc - the preconditioner context

1002:    Output Parameters:
1003: +  mat - the matrix associated with the linear system
1004: .  pmat - matrix associated with the preconditioner, usually the same
1005:           as mat. 
1006: -  flag - flag indicating information about the preconditioner
1007:           matrix structure.  See PCSetOperators() for details.

1009:    Level: developer

1011: .keywords: PC, get, operators, matrix, linear system

1013: .seealso: PCSetOperators()
1014: @*/
1015: int PCGetOperators(PC pc,Mat *mat,Mat *pmat,MatStructure *flag)
1016: {
1019:   if (mat)  *mat  = pc->mat;
1020:   if (pmat) *pmat = pc->pmat;
1021:   if (flag) *flag = pc->flag;
1022:   return(0);
1023: }

1025: /*@
1026:    PCSetVector - Sets a vector associated with the preconditioner.

1028:    Collective on PC and Vec

1030:    Input Parameters:
1031: +  pc - the preconditioner context
1032: -  vec - the vector

1034:    Notes:
1035:    The vector must be set so that the preconditioner knows what type
1036:    of vector to allocate if necessary.

1038:    Level: developer

1040: .keywords: PC, set, vector

1042: .seealso: PCGetVector()

1044: @*/
1045: int PCSetVector(PC pc,Vec vec)
1046: {
1051:   pc->vec = vec;
1052:   return(0);
1053: }

1055: /*@
1056:    PCGetVector - Gets a vector associated with the preconditioner; if the 
1057:    vector was not get set it will return a 0 pointer.

1059:    Not collective, but vector is shared by all processors that share the PC

1061:    Input Parameter:
1062: .  pc - the preconditioner context

1064:    Output Parameter:
1065: .  vec - the vector

1067:    Level: developer

1069: .keywords: PC, get, vector

1071: .seealso: PCSetVector()

1073: @*/
1074: int PCGetVector(PC pc,Vec *vec)
1075: {
1078:   *vec = pc->vec;
1079:   return(0);
1080: }

1082: /*@C 
1083:    PCGetFactoredMatrix - Gets the factored matrix from the
1084:    preconditioner context.  This routine is valid only for the LU, 
1085:    incomplete LU, Cholesky, and incomplete Cholesky methods.

1087:    Not Collective on PC though Mat is parallel if PC is parallel

1089:    Input Parameters:
1090: .  pc - the preconditioner context

1092:    Output parameters:
1093: .  mat - the factored matrix

1095:    Level: advanced

1097: .keywords: PC, get, factored, matrix
1098: @*/
1099: int PCGetFactoredMatrix(PC pc,Mat *mat)
1100: {

1105:   if (pc->ops->getfactoredmatrix) {
1106:     (*pc->ops->getfactoredmatrix)(pc,mat);
1107:   }
1108:   return(0);
1109: }

1111: /*@C
1112:    PCSetOptionsPrefix - Sets the prefix used for searching for all 
1113:    PC options in the database.

1115:    Collective on PC

1117:    Input Parameters:
1118: +  pc - the preconditioner context
1119: -  prefix - the prefix string to prepend to all PC option requests

1121:    Notes:
1122:    A hyphen (-) must NOT be given at the beginning of the prefix name.
1123:    The first character of all runtime options is AUTOMATICALLY the
1124:    hyphen.

1126:    Level: advanced

1128: .keywords: PC, set, options, prefix, database

1130: .seealso: PCAppendOptionsPrefix(), PCGetOptionsPrefix()
1131: @*/
1132: int PCSetOptionsPrefix(PC pc,char *prefix)
1133: {

1138:   PetscObjectSetOptionsPrefix((PetscObject)pc,prefix);
1139:   return(0);
1140: }

1142: /*@C
1143:    PCAppendOptionsPrefix - Appends to the prefix used for searching for all 
1144:    PC options in the database.

1146:    Collective on PC

1148:    Input Parameters:
1149: +  pc - the preconditioner context
1150: -  prefix - the prefix string to prepend to all PC option requests

1152:    Notes:
1153:    A hyphen (-) must NOT be given at the beginning of the prefix name.
1154:    The first character of all runtime options is AUTOMATICALLY the
1155:    hyphen.

1157:    Level: advanced

1159: .keywords: PC, append, options, prefix, database

1161: .seealso: PCSetOptionsPrefix(), PCGetOptionsPrefix()
1162: @*/
1163: int PCAppendOptionsPrefix(PC pc,char *prefix)
1164: {

1169:   PetscObjectAppendOptionsPrefix((PetscObject)pc,prefix);
1170:   return(0);
1171: }

1173: /*@C
1174:    PCGetOptionsPrefix - Gets the prefix used for searching for all 
1175:    PC options in the database.

1177:    Not Collective

1179:    Input Parameters:
1180: .  pc - the preconditioner context

1182:    Output Parameters:
1183: .  prefix - pointer to the prefix string used, is returned

1185:    Notes: On the fortran side, the user should pass in a string 'prifix' of
1186:    sufficient length to hold the prefix.

1188:    Level: advanced

1190: .keywords: PC, get, options, prefix, database

1192: .seealso: PCSetOptionsPrefix(), PCAppendOptionsPrefix()
1193: @*/
1194: int PCGetOptionsPrefix(PC pc,char **prefix)
1195: {

1200:   PetscObjectGetOptionsPrefix((PetscObject)pc,prefix);
1201:   return(0);
1202: }

1204: /*@
1205:    PCPreSolve - Optional pre-solve phase, intended for any
1206:    preconditioner-specific actions that must be performed before 
1207:    the iterative solve itself.

1209:    Collective on PC

1211:    Input Parameters:
1212: +  pc - the preconditioner context
1213: -  ksp - the Krylov subspace context

1215:    Level: developer

1217:    Sample of Usage:
1218: .vb
1219:     PCPreSolve(pc,ksp);
1220:     KSPSolve(ksp,its);
1221:     PCPostSolve(pc,ksp);
1222: .ve

1224:    Notes:
1225:    The pre-solve phase is distinct from the PCSetUp() phase.

1227:    SLESSolve() calls this directly, so is rarely called by the user.

1229: .keywords: PC, pre-solve

1231: .seealso: PCPostSolve()
1232: @*/
1233: int PCPreSolve(PC pc,KSP ksp)
1234: {
1236:   Vec x,rhs;
1237:   Mat A,B;


1242:   KSPGetSolution(ksp,&x);
1243:   KSPGetRhs(ksp,&rhs);
1244:   /*
1245:       Scale the system and have the matrices use the scaled form
1246:     only if the two matrices are actually the same (and hence
1247:     have the same scaling
1248:   */
1249:   PCGetOperators(pc,&A,&B,PETSC_NULL);
1250:   if (A == B) {
1251:     MatScaleSystem(pc->mat,x,rhs);
1252:     MatUseScaledForm(pc->mat,PETSC_TRUE);
1253:   }

1255:   if (pc->ops->presolve) {
1256:     (*pc->ops->presolve)(pc,ksp,x,rhs);
1257:   }
1258:   return(0);
1259: }

1261: /*@
1262:    PCPostSolve - Optional post-solve phase, intended for any
1263:    preconditioner-specific actions that must be performed after
1264:    the iterative solve itself.

1266:    Collective on PC

1268:    Input Parameters:
1269: +  pc - the preconditioner context
1270: -  ksp - the Krylov subspace context

1272:    Sample of Usage:
1273: .vb
1274:     PCPreSolve(pc,ksp);
1275:     KSPSolve(ksp,its);
1276:     PCPostSolve(pc,ksp);
1277: .ve

1279:    Note:
1280:    SLESSolve() calls this routine directly, so it is rarely called by the user.

1282:    Level: developer

1284: .keywords: PC, post-solve

1286: .seealso: PCPreSolve(), SLESSolve()
1287: @*/
1288: int PCPostSolve(PC pc,KSP ksp)
1289: {
1291:   Vec x,rhs;
1292:   Mat A,B;

1296:   KSPGetSolution(ksp,&x);
1297:   KSPGetRhs(ksp,&rhs);
1298:   if (pc->ops->postsolve) {
1299:      (*pc->ops->postsolve)(pc,ksp,x,rhs);
1300:   }

1302:   /*
1303:       Scale the system and have the matrices use the scaled form
1304:     only if the two matrices are actually the same (and hence
1305:     have the same scaling
1306:   */
1307:   PCGetOperators(pc,&A,&B,PETSC_NULL);
1308:   if (A == B) {
1309:     MatUnScaleSystem(pc->mat,x,rhs);
1310:     MatUseScaledForm(pc->mat,PETSC_FALSE);
1311:   }
1312:   return(0);
1313: }

1315: /*@C
1316:    PCView - Prints the PC data structure.

1318:    Collective on PC

1320:    Input Parameters:
1321: +  PC - the PC context
1322: -  viewer - optional visualization context

1324:    Note:
1325:    The available visualization contexts include
1326: +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
1327: -     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
1328:          output where only the first processor opens
1329:          the file.  All other processors send their 
1330:          data to the first processor to print. 

1332:    The user can open an alternative visualization contexts with
1333:    PetscViewerASCIIOpen() (output to a specified file).

1335:    Level: developer

1337: .keywords: PC, view

1339: .seealso: KSPView(), PetscViewerASCIIOpen()
1340: @*/
1341: int PCView(PC pc,PetscViewer viewer)
1342: {
1343:   PCType            cstr;
1344:   int               ierr;
1345:   PetscTruth        mat_exists,isascii,isstring;
1346:   PetscViewerFormat format;

1350:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(pc->comm);

1354:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
1355:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_STRING,&isstring);
1356:   if (isascii) {
1357:     PetscViewerGetFormat(viewer,&format);
1358:     if (pc->prefix) {
1359:       PetscViewerASCIIPrintf(viewer,"PC Object:(%s)n",pc->prefix);
1360:     } else {
1361:       PetscViewerASCIIPrintf(viewer,"PC Object:n");
1362:     }
1363:     PCGetType(pc,&cstr);
1364:     if (cstr) {
1365:       PetscViewerASCIIPrintf(viewer,"  type: %sn",cstr);
1366:     } else {
1367:       PetscViewerASCIIPrintf(viewer,"  type: not yet setn");
1368:     }
1369:     if (pc->ops->view) {
1370:       PetscViewerASCIIPushTab(viewer);
1371:       (*pc->ops->view)(pc,viewer);
1372:       PetscViewerASCIIPopTab(viewer);
1373:     }
1374:     PetscObjectExists((PetscObject)pc->mat,&mat_exists);
1375:     if (mat_exists) {
1376:       PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_INFO);
1377:       if (pc->pmat == pc->mat) {
1378:         PetscViewerASCIIPrintf(viewer,"  linear system matrix = precond matrix:n");
1379:         PetscViewerASCIIPushTab(viewer);
1380:         MatView(pc->mat,viewer);
1381:         PetscViewerASCIIPopTab(viewer);
1382:       } else {
1383:         PetscObjectExists((PetscObject)pc->pmat,&mat_exists);
1384:         if (mat_exists) {
1385:           PetscViewerASCIIPrintf(viewer,"  linear system matrix followed by preconditioner matrix:n");
1386:         } else {
1387:           PetscViewerASCIIPrintf(viewer,"  linear system matrix:n");
1388:         }
1389:         PetscViewerASCIIPushTab(viewer);
1390:         MatView(pc->mat,viewer);
1391:         if (mat_exists) {MatView(pc->pmat,viewer);}
1392:         PetscViewerASCIIPopTab(viewer);
1393:       }
1394:       PetscViewerPopFormat(viewer);
1395:     }
1396:   } else if (isstring) {
1397:     PCGetType(pc,&cstr);
1398:     PetscViewerStringSPrintf(viewer," %-7.7s",cstr);
1399:     if (pc->ops->view) {(*pc->ops->view)(pc,viewer);}
1400:   } else {
1401:     SETERRQ1(1,"Viewer type %s not supported by PC",((PetscObject)viewer)->type_name);
1402:   }
1403:   return(0);
1404: }

1406: /*MC
1407:    PCRegisterDynamic - Adds a method to the preconditioner package.

1409:    Synopsis:
1410:    int PCRegisterDynamic(char *name_solver,char *path,char *name_create,int (*routine_create)(PC))

1412:    Not collective

1414:    Input Parameters:
1415: +  name_solver - name of a new user-defined solver
1416: .  path - path (either absolute or relative) the library containing this solver
1417: .  name_create - name of routine to create method context
1418: -  routine_create - routine to create method context

1420:    Notes:
1421:    PCRegisterDynamic() may be called multiple times to add several user-defined preconditioners.

1423:    If dynamic libraries are used, then the fourth input argument (routine_create)
1424:    is ignored.

1426:    Sample usage:
1427: .vb
1428:    PCRegisterDynamic("my_solver","/home/username/my_lib/lib/libO/solaris/mylib",
1429:               "MySolverCreate",MySolverCreate);
1430: .ve

1432:    Then, your solver can be chosen with the procedural interface via
1433: $     PCSetType(pc,"my_solver")
1434:    or at runtime via the option
1435: $     -pc_type my_solver

1437:    Level: advanced

1439:    ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR}, ${BOPT}, or ${any environmental variable}
1440:  occuring in pathname will be replaced with appropriate values.

1442: .keywords: PC, register

1444: .seealso: PCRegisterAll(), PCRegisterDestroy(), PCRegister()
1445: M*/

1447: int PCRegister(char *sname,char *path,char *name,int (*function)(PC))
1448: {
1449:   int  ierr;
1450:   char fullname[256];


1454:   PetscFListConcat(path,name,fullname);
1455:   PetscFListAdd(&PCList,sname,fullname,(void (*)(void))function);
1456:   return(0);
1457: }

1459: /*@
1460:     PCComputeExplicitOperator - Computes the explicit preconditioned operator.  

1462:     Collective on PC

1464:     Input Parameter:
1465: .   pc - the preconditioner object

1467:     Output Parameter:
1468: .   mat - the explict preconditioned operator

1470:     Notes:
1471:     This computation is done by applying the operators to columns of the 
1472:     identity matrix.

1474:     Currently, this routine uses a dense matrix format when 1 processor
1475:     is used and a sparse format otherwise.  This routine is costly in general,
1476:     and is recommended for use only with relatively small systems.

1478:     Level: advanced
1479:    
1480: .keywords: PC, compute, explicit, operator

1482: @*/
1483: int PCComputeExplicitOperator(PC pc,Mat *mat)
1484: {
1485:   Vec      in,out;
1486:   int      ierr,i,M,m,size,*rows,start,end;
1487:   MPI_Comm comm;
1488:   PetscScalar   *array,zero = 0.0,one = 1.0;


1494:   comm = pc->comm;
1495:   MPI_Comm_size(comm,&size);

1497:   PCGetVector(pc,&in);
1498:   VecDuplicate(in,&out);
1499:   VecGetOwnershipRange(in,&start,&end);
1500:   VecGetSize(in,&M);
1501:   VecGetLocalSize(in,&m);
1502:   PetscMalloc((m+1)*sizeof(int),&rows);
1503:   for (i=0; i<m; i++) {rows[i] = start + i;}

1505:   if (size == 1) {
1506:     MatCreateSeqDense(comm,M,M,PETSC_NULL,mat);
1507:   } else {
1508:     MatCreateMPIAIJ(comm,m,m,M,M,0,0,0,0,mat);
1509:   }

1511:   for (i=0; i<M; i++) {

1513:     VecSet(&zero,in);
1514:     VecSetValues(in,1,&i,&one,INSERT_VALUES);
1515:     VecAssemblyBegin(in);
1516:     VecAssemblyEnd(in);

1518:     PCApply(pc,in,out);
1519: 
1520:     VecGetArray(out,&array);
1521:     MatSetValues(*mat,m,rows,1,&i,array,INSERT_VALUES);
1522:     VecRestoreArray(out,&array);

1524:   }
1525:   PetscFree(rows);
1526:   VecDestroy(out);
1527:   MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);
1528:   MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);
1529:   return(0);
1530: }