Actual source code: precon.c

  1: #define PETSCKSP_DLL

  3: /*
  4:     The PC (preconditioner) interface routines, callable by users.
  5: */
 6:  #include src/ksp/pc/pcimpl.h

  8: /* Logging support */
  9: PetscCookie PC_COOKIE = 0;
 10: PetscEvent  PC_SetUp = 0, PC_SetUpOnBlocks = 0, PC_Apply = 0, PC_ApplyCoarse = 0, PC_ApplyMultiple = 0, PC_ApplySymmetricLeft = 0;
 11: PetscEvent  PC_ApplySymmetricRight = 0, PC_ModifySubMatrices = 0;

 15: PetscErrorCode PCGetDefaultType_Private(PC pc,const char* type[])
 16: {
 18:   PetscMPIInt    size;
 19:   PetscTruth     flg1,flg2,set,flg3;

 22:   MPI_Comm_size(pc->comm,&size);
 23:   if (pc->pmat) {
 24:     PetscErrorCode (*f)(Mat,PetscTruth*,MatReuse,Mat*);
 25:     PetscObjectQueryFunction((PetscObject)pc->pmat,"MatGetDiagonalBlock_C",(void (**)(void))&f);
 26:     if (size == 1) {
 27:       MatHasOperation(pc->pmat,MATOP_ICCFACTOR_SYMBOLIC,&flg1);
 28:       MatHasOperation(pc->pmat,MATOP_ILUFACTOR_SYMBOLIC,&flg2);
 29:       MatIsSymmetricKnown(pc->pmat,&set,&flg3);
 30:       if (flg1 && (!flg2 || (set && flg3))) {
 31:         *type = PCICC;
 32:       } else if (flg2) {
 33:         *type = PCILU;
 34:       } else if (f) { /* likely is a parallel matrix run on one processor */
 35:         *type = PCBJACOBI;
 36:       } else {
 37:         *type = PCNONE;
 38:       }
 39:     } else {
 40:        if (f) {
 41:         *type = PCBJACOBI;
 42:       } else {
 43:         *type = PCNONE;
 44:       }
 45:     }
 46:   } else {
 47:     if (size == 1) {
 48:       *type = PCILU;
 49:     } else {
 50:       *type = PCBJACOBI;
 51:     }
 52:   }
 53:   return(0);
 54: }

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

 61:    Collective on PC

 63:    Input Parameter:
 64: .  pc - the preconditioner context

 66:    Level: developer

 68: .keywords: PC, destroy

 70: .seealso: PCCreate(), PCSetUp()
 71: @*/
 72: PetscErrorCode PETSCKSP_DLLEXPORT PCDestroy(PC pc)
 73: {

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

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

 83:   if (pc->ops->destroy)       { (*pc->ops->destroy)(pc);}
 84:   if (pc->diagonalscaleright) {VecDestroy(pc->diagonalscaleright);}
 85:   if (pc->diagonalscaleleft)  {VecDestroy(pc->diagonalscaleleft);}

 87:   PetscHeaderDestroy(pc);
 88:   return(0);
 89: }

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

 97:    Collective on PC

 99:    Input Parameter:
100: .  pc - the preconditioner context

102:    Output Parameter:
103: .  flag - PETSC_TRUE if it applies the scaling

105:    Level: developer

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

111: .keywords: PC

113: .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleLeft(), PCDiagonalScaleRight(), PCDiagonalScaleSet()
114: @*/
115: PetscErrorCode PETSCKSP_DLLEXPORT PCDiagonalScale(PC pc,PetscTruth *flag)
116: {
120:   *flag = pc->diagonalscale;
121:   return(0);
122: }

126: /*@
127:    PCDiagonalScaleSet - Indicates the left scaling to use to apply an additional left and right
128:       scaling as needed by certain time-stepping codes.

130:    Collective on PC

132:    Input Parameters:
133: +  pc - the preconditioner context
134: -  s - scaling vector

136:    Level: intermediate

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

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

144: .keywords: PC

146: .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleLeft(), PCDiagonalScaleRight(), PCDiagonalScale()
147: @*/
148: PetscErrorCode PETSCKSP_DLLEXPORT PCDiagonalScaleSet(PC pc,Vec s)
149: {

155:   pc->diagonalscale     = PETSC_TRUE;
156:   if (pc->diagonalscaleleft) {
157:     VecDestroy(pc->diagonalscaleleft);
158:   }
159:   pc->diagonalscaleleft = s;
160:   PetscObjectReference((PetscObject)s);
161:   if (!pc->diagonalscaleright) {
162:     VecDuplicate(s,&pc->diagonalscaleright);
163:   }
164:   VecCopy(s,pc->diagonalscaleright);
165:   VecReciprocal(pc->diagonalscaleright);
166:   return(0);
167: }

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

175:    Collective on PC

177:    Input Parameters:
178: +  pc - the preconditioner context
179: .  in - input vector
180: +  out - scaled vector (maybe the same as in)

182:    Level: intermediate

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

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

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

192: .keywords: PC

194: .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleSet(), PCDiagonalScaleRight(), PCDiagonalScale()
195: @*/
196: PetscErrorCode PETSCKSP_DLLEXPORT PCDiagonalScaleLeft(PC pc,Vec in,Vec out)
197: {

204:   if (pc->diagonalscale) {
205:     VecPointwiseMult(out,pc->diagonalscaleleft,in);
206:   } else if (in != out) {
207:     VecCopy(in,out);
208:   }
209:   return(0);
210: }

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

217:    Collective on PC

219:    Input Parameters:
220: +  pc - the preconditioner context
221: .  in - input vector
222: +  out - scaled vector (maybe the same as in)

224:    Level: intermediate

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

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

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

234: .keywords: PC

236: .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleLeft(), PCDiagonalScaleSet(), PCDiagonalScale()
237: @*/
238: PetscErrorCode PETSCKSP_DLLEXPORT PCDiagonalScaleRight(PC pc,Vec in,Vec out)
239: {

246:   if (pc->diagonalscale) {
247:     VecPointwiseMult(out,pc->diagonalscaleright,in);
248:   } else if (in != out) {
249:     VecCopy(in,out);
250:   }
251:   return(0);
252: }

256: static PetscErrorCode PCPublish_Petsc(PetscObject obj)
257: {
259:   return(0);
260: }

264: /*@C
265:    PCCreate - Creates a preconditioner context.

267:    Collective on MPI_Comm

269:    Input Parameter:
270: .  comm - MPI communicator 

272:    Output Parameter:
273: .  pc - location to put the preconditioner context

275:    Notes:
276:    The default preconditioner on one processor is PCILU with 0 fill on more 
277:    then one it is PCBJACOBI with ILU() on each processor.

279:    Level: developer

281: .keywords: PC, create, context

283: .seealso: PCSetUp(), PCApply(), PCDestroy()
284: @*/
285: PetscErrorCode PETSCKSP_DLLEXPORT PCCreate(MPI_Comm comm,PC *newpc)
286: {
287:   PC             pc;

292:   *newpc = 0;
293: #ifndef PETSC_USE_DYNAMIC_LIBRARIES
294:   PCInitializePackage(PETSC_NULL);
295: #endif

297:   PetscHeaderCreate(pc,_p_PC,struct _PCOps,PC_COOKIE,-1,"PC",comm,PCDestroy,PCView);
298:   pc->bops->publish      = PCPublish_Petsc;
299:   pc->mat                = 0;
300:   pc->pmat               = 0;
301:   pc->setupcalled        = 0;
302:   pc->data               = 0;
303:   pc->diagonalscale      = PETSC_FALSE;
304:   pc->diagonalscaleleft  = 0;
305:   pc->diagonalscaleright = 0;

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

319:   pc->modifysubmatrices   = 0;
320:   pc->modifysubmatricesP  = 0;
321:   *newpc                  = pc;
322:   PetscPublishAll(pc);
323:   return(0);

325: }

327: /* -------------------------------------------------------------------------------*/

331: /*@
332:    PCApply - Applies the preconditioner to a vector.

334:    Collective on PC and Vec

336:    Input Parameters:
337: +  pc - the preconditioner context
338: -  x - input vector

340:    Output Parameter:
341: .  y - output vector

343:    Level: developer

345: .keywords: PC, apply

347: .seealso: PCApplyTranspose(), PCApplyBAorAB()
348: @*/
349: PetscErrorCode PETSCKSP_DLLEXPORT PCApply(PC pc,Vec x,Vec y)
350: {

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

359:   if (pc->setupcalled < 2) {
360:     PCSetUp(pc);
361:   }
362:   PetscLogEventBegin(PC_Apply,pc,x,y,0);
363:   (*pc->ops->apply)(pc,x,y);
364:   PetscLogEventEnd(PC_Apply,pc,x,y,0);
365:   return(0);
366: }

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

373:    Collective on PC and Vec

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

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

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

385:    Level: developer

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

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

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

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

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

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

416:    Collective on PC and Vec

418:    Input Parameters:
419: +  pc - the preconditioner context
420: -  x - input vector

422:    Output Parameter:
423: .  y - output vector

425:    Level: developer

427:    Notes:
428:    Currently, this routine is implemented only for PCICC and PCJACOBI preconditioners.

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

432: .seealso: PCApply(), PCApplySymmetricLeft()
433: @*/
434: PetscErrorCode PETSCKSP_DLLEXPORT PCApplySymmetricRight(PC pc,Vec x,Vec y)
435: {

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

444:   if (pc->setupcalled < 2) {
445:     PCSetUp(pc);
446:   }

448:   PetscLogEventBegin(PC_ApplySymmetricRight,pc,x,y,0);
449:   (*pc->ops->applysymmetricright)(pc,x,y);
450:   PetscLogEventEnd(PC_ApplySymmetricRight,pc,x,y,0);
451:   return(0);
452: }

456: /*@
457:    PCApplyTranspose - Applies the transpose of preconditioner to a vector.

459:    Collective on PC and Vec

461:    Input Parameters:
462: +  pc - the preconditioner context
463: -  x - input vector

465:    Output Parameter:
466: .  y - output vector

468:    Level: developer

470: .keywords: PC, apply, transpose

472: .seealso: PCApply(), PCApplyBAorAB(), PCApplyBAorABTranspose(), PCHasApplyTranspose()
473: @*/
474: PetscErrorCode PETSCKSP_DLLEXPORT PCApplyTranspose(PC pc,Vec x,Vec y)
475: {

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

485:   if (pc->setupcalled < 2) {
486:     PCSetUp(pc);
487:   }

489:   PetscLogEventBegin(PC_Apply,pc,x,y,0);
490:   (*pc->ops->applytranspose)(pc,x,y);
491:   PetscLogEventEnd(PC_Apply,pc,x,y,0);
492:   return(0);
493: }

497: /*@
498:    PCHasApplyTranspose - Test whether the preconditioner has a transpose apply operation

500:    Collective on PC and Vec

502:    Input Parameters:
503: .  pc - the preconditioner context

505:    Output Parameter:
506: .  flg - PETSC_TRUE if a transpose operation is defined

508:    Level: developer

510: .keywords: PC, apply, transpose

512: .seealso: PCApplyTranspose()
513: @*/
514: PetscErrorCode PETSCKSP_DLLEXPORT PCHasApplyTranspose(PC pc,PetscTruth *flg)
515: {
519:   *flg = (PetscTruth) (pc->ops->applytranspose == 0);
520:   return(0);
521: }

525: /*@
526:    PCApplyBAorAB - Applies the preconditioner and operator to a vector. 

528:    Collective on PC and Vec

530:    Input Parameters:
531: +  pc - the preconditioner context
532: .  side - indicates the preconditioner side, one of PC_LEFT, PC_RIGHT, or PC_SYMMETRIC
533: .  x - input vector
534: -  work - work vector

536:    Output Parameter:
537: .  y - output vector

539:    Level: developer

541: .keywords: PC, apply, operator

543: .seealso: PCApply(), PCApplyTranspose(), PCApplyBAorABTranspose()
544: @*/
545: PetscErrorCode PETSCKSP_DLLEXPORT PCApplyBAorAB(PC pc,PCSide side,Vec x,Vec y,Vec work)
546: {

554:   if (x == y) SETERRQ(PETSC_ERR_ARG_IDN,"x and y must be different vectors");
555:   if (side != PC_LEFT && side != PC_SYMMETRIC && side != PC_RIGHT) {
556:     SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Side must be right, left, or symmetric");
557:   }
558:   if (pc->diagonalscale && side == PC_SYMMETRIC) {
559:     SETERRQ(PETSC_ERR_SUP,"Cannot include diagonal scaling with symmetric preconditioner application");
560:   }

562:   if (pc->setupcalled < 2) {
563:     PCSetUp(pc);
564:   }

566:   if (pc->diagonalscale) {
567:     if (pc->ops->applyBA) {
568:       Vec work2; /* this is expensive, but to fix requires a second work vector argument to PCApplyBAorAB() */
569:       VecDuplicate(x,&work2);
570:       PCDiagonalScaleRight(pc,x,work2);
571:       (*pc->ops->applyBA)(pc,side,work2,y,work);
572:       PCDiagonalScaleLeft(pc,y,y);
573:       VecDestroy(work2);
574:     } else if (side == PC_RIGHT) {
575:       PCDiagonalScaleRight(pc,x,y);
576:       PCApply(pc,y,work);
577:       MatMult(pc->mat,work,y);
578:       PCDiagonalScaleLeft(pc,y,y);
579:     } else if (side == PC_LEFT) {
580:       PCDiagonalScaleRight(pc,x,y);
581:       MatMult(pc->mat,y,work);
582:       PCApply(pc,work,y);
583:       PCDiagonalScaleLeft(pc,y,y);
584:     } else if (side == PC_SYMMETRIC) {
585:       SETERRQ(PETSC_ERR_SUP,"Cannot provide diagonal scaling with symmetric application of preconditioner");
586:     }
587:   } else {
588:     if (pc->ops->applyBA) {
589:       (*pc->ops->applyBA)(pc,side,x,y,work);
590:     } else if (side == PC_RIGHT) {
591:       PCApply(pc,x,work);
592:       MatMult(pc->mat,work,y);
593:     } else if (side == PC_LEFT) {
594:       MatMult(pc->mat,x,work);
595:       PCApply(pc,work,y);
596:     } else if (side == PC_SYMMETRIC) {
597:       /* There's an extra copy here; maybe should provide 2 work vectors instead? */
598:       PCApplySymmetricRight(pc,x,work);
599:       MatMult(pc->mat,work,y);
600:       VecCopy(y,work);
601:       PCApplySymmetricLeft(pc,work,y);
602:     }
603:   }
604:   return(0);
605: }

609: /*@ 
610:    PCApplyBAorABTranspose - Applies the transpose of the preconditioner
611:    and operator to a vector. That is, applies tr(B) * tr(A) with left preconditioning,
612:    not tr(B*A) = tr(A)*tr(B).

614:    Collective on PC and Vec

616:    Input Parameters:
617: +  pc - the preconditioner context
618: .  side - indicates the preconditioner side, one of PC_LEFT, PC_RIGHT, or PC_SYMMETRIC
619: .  x - input vector
620: -  work - work vector

622:    Output Parameter:
623: .  y - output vector

625:    Level: developer

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

629: .seealso: PCApply(), PCApplyTranspose(), PCApplyBAorAB()
630: @*/
631: PetscErrorCode PETSCKSP_DLLEXPORT PCApplyBAorABTranspose(PC pc,PCSide side,Vec x,Vec y,Vec work)
632: {

640:   if (x == y) SETERRQ(PETSC_ERR_ARG_IDN,"x and y must be different vectors");
641:   if (pc->ops->applyBAtranspose) {
642:     (*pc->ops->applyBAtranspose)(pc,side,x,y,work);
643:     return(0);
644:   }
645:   if (side != PC_LEFT && side != PC_RIGHT) {
646:     SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Side must be right or left");
647:   }

649:   if (pc->setupcalled < 2) {
650:     PCSetUp(pc);
651:   }

653:   if (side == PC_RIGHT) {
654:     PCApplyTranspose(pc,x,work);
655:     MatMultTranspose(pc->mat,work,y);
656:   } else if (side == PC_LEFT) {
657:     MatMultTranspose(pc->mat,x,work);
658:     PCApplyTranspose(pc,work,y);
659:   }
660:   /* add support for PC_SYMMETRIC */
661:   return(0); /* actually will never get here */
662: }

664: /* -------------------------------------------------------------------------------*/

668: /*@
669:    PCApplyRichardsonExists - Determines whether a particular preconditioner has a 
670:    built-in fast application of Richardson's method.

672:    Not Collective

674:    Input Parameter:
675: .  pc - the preconditioner

677:    Output Parameter:
678: .  exists - PETSC_TRUE or PETSC_FALSE

680:    Level: developer

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

684: .seealso: PCApplyRichardson()
685: @*/
686: PetscErrorCode PETSCKSP_DLLEXPORT PCApplyRichardsonExists(PC pc,PetscTruth *exists)
687: {
691:   if (pc->ops->applyrichardson) *exists = PETSC_TRUE;
692:   else                    *exists = PETSC_FALSE;
693:   return(0);
694: }

698: /*@
699:    PCApplyRichardson - Applies several steps of Richardson iteration with 
700:    the particular preconditioner. This routine is usually used by the 
701:    Krylov solvers and not the application code directly.

703:    Collective on PC

705:    Input Parameters:
706: +  pc  - the preconditioner context
707: .  x   - the initial guess 
708: .  w   - one work vector
709: .  rtol - relative decrease in residual norm convergence criteria
710: .  abstol - absolute residual norm convergence criteria
711: .  dtol - divergence residual norm increase criteria
712: -  its - the number of iterations to apply.

714:    Output Parameter:
715: .  y - the solution

717:    Notes: 
718:    Most preconditioners do not support this function. Use the command
719:    PCApplyRichardsonExists() to determine if one does.

721:    Except for the multigrid PC this routine ignores the convergence tolerances
722:    and always runs for the number of iterations
723:  
724:    Level: developer

726: .keywords: PC, apply, Richardson

728: .seealso: PCApplyRichardsonExists()
729: @*/
730: PetscErrorCode PETSCKSP_DLLEXPORT PCApplyRichardson(PC pc,Vec x,Vec y,Vec w,PetscReal rtol,PetscReal abstol, PetscReal dtol,PetscInt its)
731: {

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

741:   if (pc->setupcalled < 2) {
742:     PCSetUp(pc);
743:   }

745:   (*pc->ops->applyrichardson)(pc,x,y,w,rtol,abstol,dtol,its);
746:   return(0);
747: }

749: /* 
750:       a setupcall of 0 indicates never setup, 
751:                      1 needs to be resetup,
752:                      2 does not need any changes.
753: */
756: /*@
757:    PCSetUp - Prepares for the use of a preconditioner.

759:    Collective on PC

761:    Input Parameter:
762: .  pc - the preconditioner context

764:    Level: developer

766: .keywords: PC, setup

768: .seealso: PCCreate(), PCApply(), PCDestroy()
769: @*/
770: PetscErrorCode PETSCKSP_DLLEXPORT PCSetUp(PC pc)
771: {
773:   const char     *def;


778:   if (pc->setupcalled > 1) {
779:     PetscLogInfo((pc,"PCSetUp:Setting PC with identical preconditioner\n"));
780:     return(0);
781:   } else if (!pc->setupcalled) {
782:     PetscLogInfo((pc,"PCSetUp:Setting up new PC\n"));
783:   } else if (pc->flag == SAME_NONZERO_PATTERN) {
784:     PetscLogInfo((pc,"PCSetUp:Setting up PC with same nonzero pattern\n"));
785:   } else {
786:     PetscLogInfo((pc,"PCSetUp:Setting up PC with different nonzero pattern\n"));
787:   }

789:   PetscLogEventBegin(PC_SetUp,pc,0,0,0);
790:   if (!pc->mat) {SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Matrix must be set first");}

792:   if (!pc->type_name) {
793:     PCGetDefaultType_Private(pc,&def);
794:     PCSetType(pc,def);
795:   }

797:   if (pc->ops->setup) {
798:     (*pc->ops->setup)(pc);
799:   }
800:   pc->setupcalled = 2;
801:   PetscLogEventEnd(PC_SetUp,pc,0,0,0);
802:   return(0);
803: }

807: /*@
808:    PCSetUpOnBlocks - Sets up the preconditioner for each block in
809:    the block Jacobi, block Gauss-Seidel, and overlapping Schwarz 
810:    methods.

812:    Collective on PC

814:    Input Parameters:
815: .  pc - the preconditioner context

817:    Level: developer

819: .keywords: PC, setup, blocks

821: .seealso: PCCreate(), PCApply(), PCDestroy(), PCSetUp()
822: @*/
823: PetscErrorCode PETSCKSP_DLLEXPORT PCSetUpOnBlocks(PC pc)
824: {

829:   if (!pc->ops->setuponblocks) return(0);
830:   PetscLogEventBegin(PC_SetUpOnBlocks,pc,0,0,0);
831:   (*pc->ops->setuponblocks)(pc);
832:   PetscLogEventEnd(PC_SetUpOnBlocks,pc,0,0,0);
833:   return(0);
834: }

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

845:    Collective on PC

847:    Input Parameters:
848: +  pc - the preconditioner context
849: .  func - routine for modifying the submatrices
850: -  ctx - optional user-defined context (may be null)

852:    Calling sequence of func:
853: $     func (PC pc,PetscInt nsub,IS *row,IS *col,Mat *submat,void *ctx);

855: .  row - an array of index sets that contain the global row numbers
856:          that comprise each local submatrix
857: .  col - an array of index sets that contain the global column numbers
858:          that comprise each local submatrix
859: .  submat - array of local submatrices
860: -  ctx - optional user-defined context for private data for the 
861:          user-defined func routine (may be null)

863:    Notes:
864:    PCSetModifySubMatrices() MUST be called before KSPSetUp() and
865:    KSPSolve().

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

871:    Level: advanced

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

875: .seealso: PCModifySubMatrices()
876: @*/
877: PetscErrorCode PETSCKSP_DLLEXPORT PCSetModifySubMatrices(PC pc,PetscErrorCode (*func)(PC,PetscInt,const IS[],const IS[],Mat[],void*),void *ctx)
878: {
881:   pc->modifysubmatrices  = func;
882:   pc->modifysubmatricesP = ctx;
883:   return(0);
884: }

888: /*@C
889:    PCModifySubMatrices - Calls an optional user-defined routine within 
890:    certain preconditioners if one has been set with PCSetModifySubMarices().

892:    Collective on PC

894:    Input Parameters:
895: +  pc - the preconditioner context
896: .  nsub - the number of local submatrices
897: .  row - an array of index sets that contain the global row numbers
898:          that comprise each local submatrix
899: .  col - an array of index sets that contain the global column numbers
900:          that comprise each local submatrix
901: .  submat - array of local submatrices
902: -  ctx - optional user-defined context for private data for the 
903:          user-defined routine (may be null)

905:    Output Parameter:
906: .  submat - array of local submatrices (the entries of which may
907:             have been modified)

909:    Notes:
910:    The user should NOT generally call this routine, as it will
911:    automatically be called within certain preconditioners (currently
912:    block Jacobi, additive Schwarz) if set.

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

919:    Level: developer

921: .keywords: PC, modify, submatrices

923: .seealso: PCSetModifySubMatrices()
924: @*/
925: PetscErrorCode PETSCKSP_DLLEXPORT PCModifySubMatrices(PC pc,PetscInt nsub,const IS row[],const IS col[],Mat submat[],void *ctx)
926: {

930:   if (!pc->modifysubmatrices) return(0);
931:   PetscLogEventBegin(PC_ModifySubMatrices,pc,0,0,0);
932:   (*pc->modifysubmatrices)(pc,nsub,row,col,submat,ctx);
933:   PetscLogEventEnd(PC_ModifySubMatrices,pc,0,0,0);
934:   return(0);
935: }

939: /*@
940:    PCSetOperators - Sets the matrix associated with the linear system and 
941:    a (possibly) different one associated with the preconditioner.

943:    Collective on PC and Mat

945:    Input Parameters:
946: +  pc - the preconditioner context
947: .  Amat - the matrix associated with the linear system
948: .  Pmat - the matrix to be used in constructing the preconditioner, usually
949:           the same as Amat. 
950: -  flag - flag indicating information about the preconditioner matrix structure
951:    during successive linear solves.  This flag is ignored the first time a
952:    linear system is solved, and thus is irrelevant when solving just one linear
953:    system.

955:    Notes: 
956:    The flag can be used to eliminate unnecessary work in the preconditioner 
957:    during the repeated solution of linear systems of the same size.  The 
958:    available options are
959: +    SAME_PRECONDITIONER -
960:        Pmat is identical during successive linear solves.
961:        This option is intended for folks who are using
962:        different Amat and Pmat matrices and wish to reuse the
963:        same preconditioner matrix.  For example, this option
964:        saves work by not recomputing incomplete factorization
965:        for ILU/ICC preconditioners.
966: .     SAME_NONZERO_PATTERN -
967:        Pmat has the same nonzero structure during
968:        successive linear solves. 
969: -     DIFFERENT_NONZERO_PATTERN -
970:        Pmat does not have the same nonzero structure.

972:    Caution:
973:    If you specify SAME_NONZERO_PATTERN, PETSc believes your assertion
974:    and does not check the structure of the matrix.  If you erroneously
975:    claim that the structure is the same when it actually is not, the new
976:    preconditioner will not function correctly.  Thus, use this optimization
977:    feature carefully!

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

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

988:    Level: intermediate

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

992: .seealso: PCGetOperators(), MatZeroEntries()
993:  @*/
994: PetscErrorCode PETSCKSP_DLLEXPORT PCSetOperators(PC pc,Mat Amat,Mat Pmat,MatStructure flag)
995: {
997:   PetscTruth     isbjacobi,isrowbs;


1004:   /*
1005:       BlockSolve95 cannot use default BJacobi preconditioning
1006:   */
1007:   if (Amat) {
1008:     PetscTypeCompare((PetscObject)Amat,MATMPIROWBS,&isrowbs);
1009:     if (isrowbs) {
1010:       PetscTypeCompare((PetscObject)pc,PCBJACOBI,&isbjacobi);
1011:       if (isbjacobi) {
1012:         PCSetType(pc,PCILU);
1013:         PetscLogInfo((pc,"PCSetOperators:Switching default PC to PCILU since BS95 doesn't support PCBJACOBI\n"));
1014:       }
1015:     }
1016:   }

1018:   pc->mat  = Amat;
1019:   pc->pmat = Pmat;
1020:   if (pc->setupcalled == 2 && flag != SAME_PRECONDITIONER) {
1021:     pc->setupcalled = 1;
1022:   }
1023:   pc->flag = flag;
1024:   return(0);
1025: }

1029: /*@C
1030:    PCGetOperators - Gets the matrix associated with the linear system and
1031:    possibly a different one associated with the preconditioner.

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

1035:    Input Parameter:
1036: .  pc - the preconditioner context

1038:    Output Parameters:
1039: +  mat - the matrix associated with the linear system
1040: .  pmat - matrix associated with the preconditioner, usually the same
1041:           as mat. 
1042: -  flag - flag indicating information about the preconditioner
1043:           matrix structure.  See PCSetOperators() for details.

1045:    Level: intermediate

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

1049: .seealso: PCSetOperators()
1050: @*/
1051: PetscErrorCode PETSCKSP_DLLEXPORT PCGetOperators(PC pc,Mat *mat,Mat *pmat,MatStructure *flag)
1052: {
1055:   if (mat)  *mat  = pc->mat;
1056:   if (pmat) *pmat = pc->pmat;
1057:   if (flag) *flag = pc->flag;
1058:   return(0);
1059: }

1063: /*@C 
1064:    PCGetFactoredMatrix - Gets the factored matrix from the
1065:    preconditioner context.  This routine is valid only for the LU, 
1066:    incomplete LU, Cholesky, and incomplete Cholesky methods.

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

1070:    Input Parameters:
1071: .  pc - the preconditioner context

1073:    Output parameters:
1074: .  mat - the factored matrix

1076:    Level: advanced

1078:    Notes: Does not increase the reference count for the matrix so DO NOT destroy it

1080: .keywords: PC, get, factored, matrix
1081: @*/
1082: PetscErrorCode PETSCKSP_DLLEXPORT PCGetFactoredMatrix(PC pc,Mat *mat)
1083: {

1089:   if (pc->ops->getfactoredmatrix) {
1090:     (*pc->ops->getfactoredmatrix)(pc,mat);
1091:   }
1092:   return(0);
1093: }

1097: /*@C
1098:    PCSetOptionsPrefix - Sets the prefix used for searching for all 
1099:    PC options in the database.

1101:    Collective on PC

1103:    Input Parameters:
1104: +  pc - the preconditioner context
1105: -  prefix - the prefix string to prepend to all PC option requests

1107:    Notes:
1108:    A hyphen (-) must NOT be given at the beginning of the prefix name.
1109:    The first character of all runtime options is AUTOMATICALLY the
1110:    hyphen.

1112:    Level: advanced

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

1116: .seealso: PCAppendOptionsPrefix(), PCGetOptionsPrefix()
1117: @*/
1118: PetscErrorCode PETSCKSP_DLLEXPORT PCSetOptionsPrefix(PC pc,const char prefix[])
1119: {

1124:   PetscObjectSetOptionsPrefix((PetscObject)pc,prefix);
1125:   return(0);
1126: }

1130: /*@C
1131:    PCAppendOptionsPrefix - Appends to the prefix used for searching for all 
1132:    PC options in the database.

1134:    Collective on PC

1136:    Input Parameters:
1137: +  pc - the preconditioner context
1138: -  prefix - the prefix string to prepend to all PC option requests

1140:    Notes:
1141:    A hyphen (-) must NOT be given at the beginning of the prefix name.
1142:    The first character of all runtime options is AUTOMATICALLY the
1143:    hyphen.

1145:    Level: advanced

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

1149: .seealso: PCSetOptionsPrefix(), PCGetOptionsPrefix()
1150: @*/
1151: PetscErrorCode PETSCKSP_DLLEXPORT PCAppendOptionsPrefix(PC pc,const char prefix[])
1152: {

1157:   PetscObjectAppendOptionsPrefix((PetscObject)pc,prefix);
1158:   return(0);
1159: }

1163: /*@C
1164:    PCGetOptionsPrefix - Gets the prefix used for searching for all 
1165:    PC options in the database.

1167:    Not Collective

1169:    Input Parameters:
1170: .  pc - the preconditioner context

1172:    Output Parameters:
1173: .  prefix - pointer to the prefix string used, is returned

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

1178:    Level: advanced

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

1182: .seealso: PCSetOptionsPrefix(), PCAppendOptionsPrefix()
1183: @*/
1184: PetscErrorCode PETSCKSP_DLLEXPORT PCGetOptionsPrefix(PC pc,const char *prefix[])
1185: {

1191:   PetscObjectGetOptionsPrefix((PetscObject)pc,prefix);
1192:   return(0);
1193: }

1197: /*@
1198:    PCPreSolve - Optional pre-solve phase, intended for any
1199:    preconditioner-specific actions that must be performed before 
1200:    the iterative solve itself.

1202:    Collective on PC

1204:    Input Parameters:
1205: +  pc - the preconditioner context
1206: -  ksp - the Krylov subspace context

1208:    Level: developer

1210:    Sample of Usage:
1211: .vb
1212:     PCPreSolve(pc,ksp);
1213:     KSPSolve(ksp,b,x);
1214:     PCPostSolve(pc,ksp);
1215: .ve

1217:    Notes:
1218:    The pre-solve phase is distinct from the PCSetUp() phase.

1220:    KSPSolve() calls this directly, so is rarely called by the user.

1222: .keywords: PC, pre-solve

1224: .seealso: PCPostSolve()
1225: @*/
1226: PetscErrorCode PETSCKSP_DLLEXPORT PCPreSolve(PC pc,KSP ksp)
1227: {
1229:   Vec            x,rhs;
1230:   Mat            A,B;

1235:   KSPGetSolution(ksp,&x);
1236:   KSPGetRhs(ksp,&rhs);
1237:   /*
1238:       Scale the system and have the matrices use the scaled form
1239:     only if the two matrices are actually the same (and hence
1240:     have the same scaling
1241:   */
1242:   PCGetOperators(pc,&A,&B,PETSC_NULL);
1243:   if (A == B) {
1244:     MatScaleSystem(pc->mat,x,rhs);
1245:     MatUseScaledForm(pc->mat,PETSC_TRUE);
1246:   }

1248:   if (pc->ops->presolve) {
1249:     (*pc->ops->presolve)(pc,ksp,x,rhs);
1250:   }
1251:   return(0);
1252: }

1256: /*@
1257:    PCPostSolve - Optional post-solve phase, intended for any
1258:    preconditioner-specific actions that must be performed after
1259:    the iterative solve itself.

1261:    Collective on PC

1263:    Input Parameters:
1264: +  pc - the preconditioner context
1265: -  ksp - the Krylov subspace context

1267:    Sample of Usage:
1268: .vb
1269:     PCPreSolve(pc,ksp);
1270:     KSPSolve(ksp,b,x);
1271:     PCPostSolve(pc,ksp);
1272: .ve

1274:    Note:
1275:    KSPSolve() calls this routine directly, so it is rarely called by the user.

1277:    Level: developer

1279: .keywords: PC, post-solve

1281: .seealso: PCPreSolve(), KSPSolve()
1282: @*/
1283: PetscErrorCode PETSCKSP_DLLEXPORT PCPostSolve(PC pc,KSP ksp)
1284: {
1286:   Vec            x,rhs;
1287:   Mat            A,B;

1292:   KSPGetSolution(ksp,&x);
1293:   KSPGetRhs(ksp,&rhs);
1294:   if (pc->ops->postsolve) {
1295:      (*pc->ops->postsolve)(pc,ksp,x,rhs);
1296:   }

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

1313: /*@C
1314:    PCView - Prints the PC data structure.

1316:    Collective on PC

1318:    Input Parameters:
1319: +  PC - the PC context
1320: -  viewer - optional visualization context

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

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

1333:    Level: developer

1335: .keywords: PC, view

1337: .seealso: KSPView(), PetscViewerASCIIOpen()
1338: @*/
1339: PetscErrorCode PETSCKSP_DLLEXPORT PCView(PC pc,PetscViewer viewer)
1340: {
1341:   PCType            cstr;
1342:   PetscErrorCode    ierr;
1343:   PetscTruth        mat_exists,iascii,isstring;
1344:   PetscViewerFormat format;

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

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

1406: /*@C
1407:   PCRegister - See PCRegisterDynamic()

1409:   Level: advanced
1410: @*/
1411: PetscErrorCode PETSCKSP_DLLEXPORT PCRegister(const char sname[],const char path[],const char name[],PetscErrorCode (*function)(PC))
1412: {
1414:   char           fullname[PETSC_MAX_PATH_LEN];


1418:   PetscFListConcat(path,name,fullname);
1419:   PetscFListAdd(&PCList,sname,fullname,(void (*)(void))function);
1420:   return(0);
1421: }

1425: /*@
1426:     PCComputeExplicitOperator - Computes the explicit preconditioned operator.  

1428:     Collective on PC

1430:     Input Parameter:
1431: .   pc - the preconditioner object

1433:     Output Parameter:
1434: .   mat - the explict preconditioned operator

1436:     Notes:
1437:     This computation is done by applying the operators to columns of the 
1438:     identity matrix.

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

1444:     Level: advanced
1445:    
1446: .keywords: PC, compute, explicit, operator

1448: @*/
1449: PetscErrorCode PETSCKSP_DLLEXPORT PCComputeExplicitOperator(PC pc,Mat *mat)
1450: {
1451:   Vec            in,out;
1453:   PetscInt       i,M,m,*rows,start,end;
1454:   PetscMPIInt    size;
1455:   MPI_Comm       comm;
1456:   PetscScalar    *array,zero = 0.0,one = 1.0;


1462:   comm = pc->comm;
1463:   MPI_Comm_size(comm,&size);

1465:   if (!pc->pmat) SETERRQ(PETSC_ERR_ORDER,"You must call KSPSetOperators() or PCSetOperators() before this call");
1466:   MatGetVecs(pc->pmat,&in,0);
1467:   VecDuplicate(in,&out);
1468:   VecGetOwnershipRange(in,&start,&end);
1469:   VecGetSize(in,&M);
1470:   VecGetLocalSize(in,&m);
1471:   PetscMalloc((m+1)*sizeof(PetscInt),&rows);
1472:   for (i=0; i<m; i++) {rows[i] = start + i;}

1474:   MatCreate(comm,mat);
1475:   MatSetSizes(*mat,m,m,M,M);
1476:   if (size == 1) {
1477:     MatSetType(*mat,MATSEQDENSE);
1478:     MatSeqDenseSetPreallocation(*mat,PETSC_NULL);
1479:   } else {
1480:     MatSetType(*mat,MATMPIAIJ);
1481:     MatMPIAIJSetPreallocation(*mat,0,PETSC_NULL,0,PETSC_NULL);
1482:   }

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

1486:     VecSet(in,zero);
1487:     VecSetValues(in,1,&i,&one,INSERT_VALUES);
1488:     VecAssemblyBegin(in);
1489:     VecAssemblyEnd(in);

1491:     /* should fix, allowing user to choose side */
1492:     PCApply(pc,in,out);
1493: 
1494:     VecGetArray(out,&array);
1495:     MatSetValues(*mat,m,rows,1,&i,array,INSERT_VALUES);
1496:     VecRestoreArray(out,&array);

1498:   }
1499:   PetscFree(rows);
1500:   VecDestroy(out);
1501:   MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);
1502:   MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);
1503:   return(0);
1504: }