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:   Users manual sections:
 31: .   Section 4.15 Solving Singular Systems

 33: .keywords: PC, destroy, null space

 35: .seealso: PCCreate(), PCSetUp(), MatNullSpaceCreate(), MatNullSpace

 37: @*/
 38: int PCNullSpaceAttach(PC pc,MatNullSpace nullsp)
 39: {


 46:   if (pc->nullsp) {
 47:     MatNullSpaceDestroy(pc->nullsp);
 48:   }
 49:   pc->nullsp = nullsp;
 50:   PetscObjectReference((PetscObject)nullsp);
 51:   return(0);
 52: }

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

 57:    Collective on PC

 59:    Input Parameter:
 60: .  pc - the preconditioner context

 62:    Level: developer

 64: .keywords: PC, destroy

 66: .seealso: PCCreate(), PCSetUp()
 67: @*/
 68: int PCDestroy(PC pc)
 69: {

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

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

 79:   if (pc->ops->destroy)       { (*pc->ops->destroy)(pc);}
 80:   if (pc->nullsp)             {MatNullSpaceDestroy(pc->nullsp);}
 81:   if (pc->diagonalscaleright) {VecDestroy(pc->diagonalscaleright);}
 82:   if (pc->diagonalscaleleft)  {VecDestroy(pc->diagonalscaleleft);}

 84:   PetscLogObjectDestroy(pc);
 85:   PetscHeaderDestroy(pc);
 86:   return(0);
 87: }

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

 93:    Collective on PC

 95:    Input Parameter:
 96: .  pc - the preconditioner context

 98:    Output Parameter:
 99: .  flag - PETSC_TRUE if it applies the scaling

101:    Level: developer

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

107: .keywords: PC

109: .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleLeft(), PCDiagonalScaleRight(), PCDiagonalScaleSet()
110: @*/
111: int PCDiagonalScale(PC pc,PetscTruth *flag)
112: {
115:   *flag = pc->diagonalscale;
116:   return(0);
117: }

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

123:    Collective on PC

125:    Input Parameters:
126: +  pc - the preconditioner context
127: -  s - scaling vector

129:    Level: intermediate

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

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

137: .keywords: PC

139: .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleLeft(), PCDiagonalScaleRight(), PCDiagonalScale()
140: @*/
141: int PCDiagonalScaleSet(PC pc,Vec s)
142: {

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

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

166:    Collective on PC

168:    Input Parameters:
169: +  pc - the preconditioner context
170: .  in - input vector
171: +  out - scaled vector (maybe the same as in)

173:    Level: intermediate

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

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

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

183: .keywords: PC

185: .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleSet(), PCDiagonalScaleRight(), PCDiagonalScale()
186: @*/
187: int PCDiagonalScaleLeft(PC pc,Vec in,Vec out)
188: {

195:   if (pc->diagonalscale) {
196:     VecPointwiseMult(pc->diagonalscaleleft,in,out);
197:   } else if (in != out) {
198:     VecCopy(in,out);
199:   }
200:   return(0);
201: }

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

206:    Collective on PC

208:    Input Parameters:
209: +  pc - the preconditioner context
210: .  in - input vector
211: +  out - scaled vector (maybe the same as in)

213:    Level: intermediate

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

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

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

223: .keywords: PC

225: .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleLeft(), PCDiagonalScaleSet(), PCDiagonalScale()
226: @*/
227: int PCDiagonalScaleRight(PC pc,Vec in,Vec out)
228: {

235:   if (pc->diagonalscale) {
236:     VecPointwiseMult(pc->diagonalscaleright,in,out);
237:   } else if (in != out) {
238:     VecCopy(in,out);
239:   }
240:   return(0);
241: }

243: static int PCPublish_Petsc(PetscObject obj)
244: {
245: #if defined(PETSC_HAVE_AMS)
246:   PC          v = (PC) obj;
247:   int         ierr;
248: #endif


252: #if defined(PETSC_HAVE_AMS)
253:   /* if it is already published then return */
254:   if (v->amem >=0) return(0);

256:   PetscObjectPublishBaseBegin(obj);
257:   PetscObjectPublishBaseEnd(obj);
258: #endif

260:   return(0);
261: }

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

266:    Collective on MPI_Comm

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

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

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

278:    Level: developer

280: .keywords: PC, create, context

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

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

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

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

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

326: }

328: /* -------------------------------------------------------------------------------*/

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

333:    Collective on PC and Vec

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

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

342:    Level: developer

344: .keywords: PC, apply

346: .seealso: PCApplyTranspose(), PCApplyBAorAB()
347: @*/
348: int PCApply(PC pc,Vec x,Vec y)
349: {
350:   int        ierr;

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

358:   if (pc->setupcalled < 2) {
359:     PCSetUp(pc);
360:   }

362:   PetscLogEventBegin(PC_Apply,pc,x,y,0);
363:   (*pc->ops->apply)(pc,x,y);
364:   PetscLogEventEnd(PC_Apply,pc,x,y,0);

366:   /* Remove null space from preconditioned vector y */
367:   if (pc->nullsp) {
368:     MatNullSpaceRemove(pc->nullsp,y,PETSC_NULL);
369:   }
370:   return(0);
371: }

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

376:    Collective on PC and Vec

378:    Input Parameters:
379: +  pc - the preconditioner context
380: -  x - input vector

382:    Output Parameter:
383: .  y - output vector

385:    Notes:
386:    Currently, this routine is implemented only for PCICC and PCJACOBI preconditioners.

388:    Level: developer

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

392: .seealso: PCApply(), PCApplySymmetricRight()
393: @*/
394: int PCApplySymmetricLeft(PC pc,Vec x,Vec y)
395: {

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

404:   if (pc->setupcalled < 2) {
405:     PCSetUp(pc);
406:   }

408:   PetscLogEventBegin(PC_ApplySymmetricLeft,pc,x,y,0);
409:   (*pc->ops->applysymmetricleft)(pc,x,y);
410:   PetscLogEventEnd(PC_ApplySymmetricLeft,pc,x,y,0);
411:   return(0);
412: }

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

417:    Collective on PC and Vec

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

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

426:    Level: developer

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

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

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

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

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

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

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

458:    Collective on PC and Vec

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

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

467:    Level: developer

469: .keywords: PC, apply, transpose

471: .seealso: PCApplyTranspose(), PCApplyBAorAB(), PCApplyBAorABTranspose()
472: @*/
473: int PCApplyTranspose(PC pc,Vec x,Vec y)
474: {

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

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

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

494: /*@
495:    PCApplyBAorAB - Applies the preconditioner and operator to a vector. 

497:    Collective on PC and Vec

499:    Input Parameters:
500: +  pc - the preconditioner context
501: .  side - indicates the preconditioner side, one of PC_LEFT, PC_RIGHT, or PC_SYMMETRIC
502: .  x - input vector
503: -  work - work vector

505:    Output Parameter:
506: .  y - output vector

508:    Level: developer

510: .keywords: PC, apply, operator

512: .seealso: PCApply(), PCApplyTranspose(), PCApplyBAorABTranspose()
513: @*/
514: int PCApplyBAorAB(PC pc,PCSide side,Vec x,Vec y,Vec work)
515: {
516:   int        ierr;

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

531:   if (pc->setupcalled < 2) {
532:     PCSetUp(pc);
533:   }

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

584: /*@ 
585:    PCApplyBAorABTranspose - Applies the transpose of the preconditioner
586:    and operator to a vector. That is, applies tr(B) * tr(A) with left preconditioning,
587:    not tr(B*A) = tr(A)*tr(B).

589:    Collective on PC and Vec

591:    Input Parameters:
592: +  pc - the preconditioner context
593: .  side - indicates the preconditioner side, one of PC_LEFT, PC_RIGHT, or PC_SYMMETRIC
594: .  x - input vector
595: -  work - work vector

597:    Output Parameter:
598: .  y - output vector

600:    Level: developer

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

604: .seealso: PCApply(), PCApplyTranspose(), PCApplyBAorAB()
605: @*/
606: int PCApplyBAorABTranspose(PC pc,PCSide side,Vec x,Vec y,Vec work)
607: {

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

624:   if (pc->setupcalled < 2) {
625:     PCSetUp(pc);
626:   }

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

639: /* -------------------------------------------------------------------------------*/

641: /*@
642:    PCApplyRichardsonExists - Determines whether a particular preconditioner has a 
643:    built-in fast application of Richardson's method.

645:    Not Collective

647:    Input Parameter:
648: .  pc - the preconditioner

650:    Output Parameter:
651: .  exists - PETSC_TRUE or PETSC_FALSE

653:    Level: developer

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

657: .seealso: PCApplyRichardson()
658: @*/
659: int PCApplyRichardsonExists(PC pc,PetscTruth *exists)
660: {
664:   if (pc->ops->applyrichardson) *exists = PETSC_TRUE;
665:   else                    *exists = PETSC_FALSE;
666:   return(0);
667: }

669: /*@
670:    PCApplyRichardson - Applies several steps of Richardson iteration with 
671:    the particular preconditioner. This routine is usually used by the 
672:    Krylov solvers and not the application code directly.

674:    Collective on PC

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

685:    Output Parameter:
686: .  y - the solution

688:    Notes: 
689:    Most preconditioners do not support this function. Use the command
690:    PCApplyRichardsonExists() to determine if one does.

692:    Except for the multigrid PC this routine ignores the convergence tolerances
693:    and always runs for the number of iterations
694:  
695:    Level: developer

697: .keywords: PC, apply, Richardson

699: .seealso: PCApplyRichardsonExists()
700: @*/
701: int PCApplyRichardson(PC pc,Vec x,Vec y,Vec w,PetscReal rtol,PetscReal atol, PetscReal dtol,int its)
702: {

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

712:   if (pc->setupcalled < 2) {
713:     PCSetUp(pc);
714:   }

716:   (*pc->ops->applyrichardson)(pc,x,y,w,rtol,atol,dtol,its);
717:   return(0);
718: }

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

728:    Collective on PC

730:    Input Parameter:
731: .  pc - the preconditioner context

733:    Level: developer

735: .keywords: PC, setup

737: .seealso: PCCreate(), PCApply(), PCDestroy()
738: @*/
739: int PCSetUp(PC pc)
740: {


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

757:   PetscLogEventBegin(PC_SetUp,pc,0,0,0);
758:   if (!pc->vec) {SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Vector must be set first");}
759:   if (!pc->mat) {SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Matrix must be set first");}
760:   if (!pc->type_name) {
761:     int size;

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

785: /*@
786:    PCSetUpOnBlocks - Sets up the preconditioner for each block in
787:    the block Jacobi, block Gauss-Seidel, and overlapping Schwarz 
788:    methods.

790:    Collective on PC

792:    Input Parameters:
793: .  pc - the preconditioner context

795:    Level: developer

797: .keywords: PC, setup, blocks

799: .seealso: PCCreate(), PCApply(), PCDestroy(), PCSetUp()
800: @*/
801: int PCSetUpOnBlocks(PC pc)
802: {

807:   if (!pc->ops->setuponblocks) return(0);
808:   PetscLogEventBegin(PC_SetUpOnBlocks,pc,0,0,0);
809:   (*pc->ops->setuponblocks)(pc);
810:   PetscLogEventEnd(PC_SetUpOnBlocks,pc,0,0,0);
811:   return(0);
812: }

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

821:    Collective on PC

823:    Input Parameters:
824: +  pc - the preconditioner context
825: .  func - routine for modifying the submatrices
826: -  ctx - optional user-defined context (may be null)

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

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

839:    Notes:
840:    PCSetModifySubMatrices() MUST be called before SLESSetUp() and
841:    SLESSolve().

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

847:    Level: advanced

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

851: .seealso: PCModifySubMatrices()
852: @*/
853: int PCSetModifySubMatrices(PC pc,int(*func)(PC,int,IS*,IS*,Mat*,void*),void *ctx)
854: {
857:   pc->modifysubmatrices  = func;
858:   pc->modifysubmatricesP = ctx;
859:   return(0);
860: }

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

866:    Collective on PC

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

879:    Output Parameter:
880: .  submat - array of local submatrices (the entries of which may
881:             have been modified)

883:    Notes:
884:    The user should NOT generally call this routine, as it will
885:    automatically be called within certain preconditioners (currently
886:    block Jacobi, additive Schwarz) if set.

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

893:    Level: developer

895: .keywords: PC, modify, submatrices

897: .seealso: PCSetModifySubMatrices()
898: @*/
899: int PCModifySubMatrices(PC pc,int nsub,IS *row,IS *col,Mat *submat,void *ctx)
900: {

904:   if (!pc->modifysubmatrices) return(0);
905:   PetscLogEventBegin(PC_ModifySubMatrices,pc,0,0,0);
906:   (*pc->modifysubmatrices)(pc,nsub,row,col,submat,ctx);
907:   PetscLogEventEnd(PC_ModifySubMatrices,pc,0,0,0);
908:   return(0);
909: }

911: /*@
912:    PCSetOperators - Sets the matrix associated with the linear system and 
913:    a (possibly) different one associated with the preconditioner.

915:    Collective on PC and Mat

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

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

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

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

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

960:    Level: developer

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

964: .seealso: PCGetOperators(), MatZeroEntries()
965:  @*/
966: int PCSetOperators(PC pc,Mat Amat,Mat Pmat,MatStructure flag)
967: {
968:   int        ierr;
969:   PetscTruth isbjacobi,isrowbs;


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

988:   pc->mat  = Amat;
989:   pc->pmat = Pmat;
990:   if (pc->setupcalled == 2 && flag != SAME_PRECONDITIONER) {
991:     pc->setupcalled = 1;
992:   }
993:   pc->flag = flag;
994:   return(0);
995: }

997: /*@C
998:    PCGetOperators - Gets the matrix associated with the linear system and
999:    possibly a different one associated with the preconditioner.

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

1003:    Input Parameter:
1004: .  pc - the preconditioner context

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

1013:    Level: developer

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

1017: .seealso: PCSetOperators()
1018: @*/
1019: int PCGetOperators(PC pc,Mat *mat,Mat *pmat,MatStructure *flag)
1020: {
1023:   if (mat)  *mat  = pc->mat;
1024:   if (pmat) *pmat = pc->pmat;
1025:   if (flag) *flag = pc->flag;
1026:   return(0);
1027: }

1029: /*@
1030:    PCSetVector - Sets a vector associated with the preconditioner.

1032:    Collective on PC and Vec

1034:    Input Parameters:
1035: +  pc - the preconditioner context
1036: -  vec - the vector

1038:    Notes:
1039:    The vector must be set so that the preconditioner knows what type
1040:    of vector to allocate if necessary.

1042:    Level: developer

1044: .keywords: PC, set, vector

1046: .seealso: PCGetVector()

1048: @*/
1049: int PCSetVector(PC pc,Vec vec)
1050: {
1055:   pc->vec = vec;
1056:   return(0);
1057: }

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

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

1065:    Input Parameter:
1066: .  pc - the preconditioner context

1068:    Output Parameter:
1069: .  vec - the vector

1071:    Level: developer

1073: .keywords: PC, get, vector

1075: .seealso: PCSetVector()

1077: @*/
1078: int PCGetVector(PC pc,Vec *vec)
1079: {
1082:   *vec = pc->vec;
1083:   return(0);
1084: }

1086: /*@C 
1087:    PCGetFactoredMatrix - Gets the factored matrix from the
1088:    preconditioner context.  This routine is valid only for the LU, 
1089:    incomplete LU, Cholesky, and incomplete Cholesky methods.

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

1093:    Input Parameters:
1094: .  pc - the preconditioner context

1096:    Output parameters:
1097: .  mat - the factored matrix

1099:    Level: advanced

1101: .keywords: PC, get, factored, matrix
1102: @*/
1103: int PCGetFactoredMatrix(PC pc,Mat *mat)
1104: {

1109:   if (pc->ops->getfactoredmatrix) {
1110:     (*pc->ops->getfactoredmatrix)(pc,mat);
1111:   }
1112:   return(0);
1113: }

1115: /*@C
1116:    PCSetOptionsPrefix - Sets the prefix used for searching for all 
1117:    PC options in the database.

1119:    Collective on PC

1121:    Input Parameters:
1122: +  pc - the preconditioner context
1123: -  prefix - the prefix string to prepend to all PC option requests

1125:    Notes:
1126:    A hyphen (-) must NOT be given at the beginning of the prefix name.
1127:    The first character of all runtime options is AUTOMATICALLY the
1128:    hyphen.

1130:    Level: advanced

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

1134: .seealso: PCAppendOptionsPrefix(), PCGetOptionsPrefix()
1135: @*/
1136: int PCSetOptionsPrefix(PC pc,char *prefix)
1137: {

1142:   PetscObjectSetOptionsPrefix((PetscObject)pc,prefix);
1143:   return(0);
1144: }

1146: /*@C
1147:    PCAppendOptionsPrefix - Appends to the prefix used for searching for all 
1148:    PC options in the database.

1150:    Collective on PC

1152:    Input Parameters:
1153: +  pc - the preconditioner context
1154: -  prefix - the prefix string to prepend to all PC option requests

1156:    Notes:
1157:    A hyphen (-) must NOT be given at the beginning of the prefix name.
1158:    The first character of all runtime options is AUTOMATICALLY the
1159:    hyphen.

1161:    Level: advanced

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

1165: .seealso: PCSetOptionsPrefix(), PCGetOptionsPrefix()
1166: @*/
1167: int PCAppendOptionsPrefix(PC pc,char *prefix)
1168: {

1173:   PetscObjectAppendOptionsPrefix((PetscObject)pc,prefix);
1174:   return(0);
1175: }

1177: /*@C
1178:    PCGetOptionsPrefix - Gets the prefix used for searching for all 
1179:    PC options in the database.

1181:    Not Collective

1183:    Input Parameters:
1184: .  pc - the preconditioner context

1186:    Output Parameters:
1187: .  prefix - pointer to the prefix string used, is returned

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

1192:    Level: advanced

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

1196: .seealso: PCSetOptionsPrefix(), PCAppendOptionsPrefix()
1197: @*/
1198: int PCGetOptionsPrefix(PC pc,char **prefix)
1199: {

1204:   PetscObjectGetOptionsPrefix((PetscObject)pc,prefix);
1205:   return(0);
1206: }

1208: /*@
1209:    PCPreSolve - Optional pre-solve phase, intended for any
1210:    preconditioner-specific actions that must be performed before 
1211:    the iterative solve itself.

1213:    Collective on PC

1215:    Input Parameters:
1216: +  pc - the preconditioner context
1217: -  ksp - the Krylov subspace context

1219:    Level: developer

1221:    Sample of Usage:
1222: .vb
1223:     PCPreSolve(pc,ksp);
1224:     KSPSolve(ksp,its);
1225:     PCPostSolve(pc,ksp);
1226: .ve

1228:    Notes:
1229:    The pre-solve phase is distinct from the PCSetUp() phase.

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

1233: .keywords: PC, pre-solve

1235: .seealso: PCPostSolve()
1236: @*/
1237: int PCPreSolve(PC pc,KSP ksp)
1238: {
1240:   Vec x,rhs;
1241:   Mat A,B;


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

1259:   if (pc->ops->presolve) {
1260:     (*pc->ops->presolve)(pc,ksp,x,rhs);
1261:   }
1262:   return(0);
1263: }

1265: /*@
1266:    PCPostSolve - Optional post-solve phase, intended for any
1267:    preconditioner-specific actions that must be performed after
1268:    the iterative solve itself.

1270:    Collective on PC

1272:    Input Parameters:
1273: +  pc - the preconditioner context
1274: -  ksp - the Krylov subspace context

1276:    Sample of Usage:
1277: .vb
1278:     PCPreSolve(pc,ksp);
1279:     KSPSolve(ksp,its);
1280:     PCPostSolve(pc,ksp);
1281: .ve

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

1286:    Level: developer

1288: .keywords: PC, post-solve

1290: .seealso: PCPreSolve(), SLESSolve()
1291: @*/
1292: int PCPostSolve(PC pc,KSP ksp)
1293: {
1295:   Vec x,rhs;
1296:   Mat A,B;

1300:   KSPGetSolution(ksp,&x);
1301:   KSPGetRhs(ksp,&rhs);
1302:   if (pc->ops->postsolve) {
1303:      (*pc->ops->postsolve)(pc,ksp,x,rhs);
1304:   }

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

1319: /*@C
1320:    PCView - Prints the PC data structure.

1322:    Collective on PC

1324:    Input Parameters:
1325: +  PC - the PC context
1326: -  viewer - optional visualization context

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

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

1339:    Level: developer

1341: .keywords: PC, view

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

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

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

1410: /*MC
1411:    PCRegisterDynamic - Adds a method to the preconditioner package.

1413:    Synopsis:
1414:    int PCRegisterDynamic(char *name_solver,char *path,char *name_create,int (*routine_create)(PC))

1416:    Not collective

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

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

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

1430:    Sample usage:
1431: .vb
1432:    PCRegisterDynamic("my_solver","/home/username/my_lib/lib/libO/solaris/mylib",
1433:               "MySolverCreate",MySolverCreate);
1434: .ve

1436:    Then, your solver can be chosen with the procedural interface via
1437: $     PCSetType(pc,"my_solver")
1438:    or at runtime via the option
1439: $     -pc_type my_solver

1441:    Level: advanced

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

1446: .keywords: PC, register

1448: .seealso: PCRegisterAll(), PCRegisterDestroy(), PCRegister()
1449: M*/

1451: int PCRegister(char *sname,char *path,char *name,int (*function)(PC))
1452: {
1453:   int  ierr;
1454:   char fullname[256];


1458:   PetscFListConcat(path,name,fullname);
1459:   PetscFListAdd(&PCList,sname,fullname,(void (*)(void))function);
1460:   return(0);
1461: }

1463: /*@
1464:     PCComputeExplicitOperator - Computes the explicit preconditioned operator.  

1466:     Collective on PC

1468:     Input Parameter:
1469: .   pc - the preconditioner object

1471:     Output Parameter:
1472: .   mat - the explict preconditioned operator

1474:     Notes:
1475:     This computation is done by applying the operators to columns of the 
1476:     identity matrix.

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

1482:     Level: advanced
1483:    
1484: .keywords: PC, compute, explicit, operator

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


1498:   comm = pc->comm;
1499:   MPI_Comm_size(comm,&size);

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

1509:   if (size == 1) {
1510:     MatCreateSeqDense(comm,M,M,PETSC_NULL,mat);
1511:   } else {
1512:     MatCreateMPIAIJ(comm,m,m,M,M,0,0,0,0,mat);
1513:   }

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

1517:     VecSet(&zero,in);
1518:     VecSetValues(in,1,&i,&one,INSERT_VALUES);
1519:     VecAssemblyBegin(in);
1520:     VecAssemblyEnd(in);

1522:     PCApply(pc,in,out);
1523: 
1524:     VecGetArray(out,&array);
1525:     MatSetValues(*mat,m,rows,1,&i,array,INSERT_VALUES);
1526:     VecRestoreArray(out,&array);

1528:   }
1529:   PetscFree(rows);
1530:   VecDestroy(out);
1531:   MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);
1532:   MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);
1533:   return(0);
1534: }