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/ksp/pc/pcimpl.h

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

 14: int PCGetDefaultType_Private(PC pc,const char* type[])
 15: {
 16:   int        ierr,size;
 17:   PetscTruth flg1,flg2;

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

 55: /*@C
 56:    PCNullSpaceAttach - attaches a null space to a preconditioner object.
 57:         This null space will be removed from the resulting vector whenever
 58:         the preconditioner is applied.

 60:    Collective on PC

 62:    Input Parameters:
 63: +  pc - the preconditioner context
 64: -  nullsp - the null space object

 66:    Level: developer

 68:    Notes:
 69:       Overwrites any previous null space that may have been attached

 71:   Users manual sections:
 72: .   Section 4.15 Solving Singular Systems

 74: .keywords: PC, destroy, null space

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

 78: @*/
 79: int PCNullSpaceAttach(PC pc,MatNullSpace nullsp)
 80: {


 87:   if (pc->nullsp) {
 88:     MatNullSpaceDestroy(pc->nullsp);
 89:   }
 90:   pc->nullsp = nullsp;
 91:   PetscObjectReference((PetscObject)nullsp);
 92:   return(0);
 93: }

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

100:    Collective on PC

102:    Input Parameter:
103: .  pc - the preconditioner context

105:    Level: developer

107: .keywords: PC, destroy

109: .seealso: PCCreate(), PCSetUp()
110: @*/
111: int PCDestroy(PC pc)
112: {

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

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

122:   if (pc->ops->destroy)       { (*pc->ops->destroy)(pc);}
123:   if (pc->nullsp)             {MatNullSpaceDestroy(pc->nullsp);}
124:   if (pc->diagonalscaleright) {VecDestroy(pc->diagonalscaleright);}
125:   if (pc->diagonalscaleleft)  {VecDestroy(pc->diagonalscaleleft);}

127:   PetscLogObjectDestroy(pc);
128:   PetscHeaderDestroy(pc);
129:   return(0);
130: }

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

138:    Collective on PC

140:    Input Parameter:
141: .  pc - the preconditioner context

143:    Output Parameter:
144: .  flag - PETSC_TRUE if it applies the scaling

146:    Level: developer

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

152: .keywords: PC

154: .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleLeft(), PCDiagonalScaleRight(), PCDiagonalScaleSet()
155: @*/
156: int PCDiagonalScale(PC pc,PetscTruth *flag)
157: {
161:   *flag = pc->diagonalscale;
162:   return(0);
163: }

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

171:    Collective on PC

173:    Input Parameters:
174: +  pc - the preconditioner context
175: -  s - scaling vector

177:    Level: intermediate

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

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

185: .keywords: PC

187: .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleLeft(), PCDiagonalScaleRight(), PCDiagonalScale()
188: @*/
189: int PCDiagonalScaleSet(PC pc,Vec s)
190: {

196:   pc->diagonalscale     = PETSC_TRUE;
197:   if (pc->diagonalscaleleft) {
198:     VecDestroy(pc->diagonalscaleleft);
199:   }
200:   pc->diagonalscaleleft = s;
201:   PetscObjectReference((PetscObject)s);
202:   if (!pc->diagonalscaleright) {
203:     VecDuplicate(s,&pc->diagonalscaleright);
204:   }
205:   VecCopy(s,pc->diagonalscaleright);
206:   VecReciprocal(pc->diagonalscaleright);
207:   return(0);
208: }

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

216:    Collective on PC

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

223:    Level: intermediate

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

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

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

233: .keywords: PC

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

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

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

258:    Collective on PC

260:    Input Parameters:
261: +  pc - the preconditioner context
262: .  in - input vector
263: +  out - scaled vector (maybe the same as in)

265:    Level: intermediate

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

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

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

275: .keywords: PC

277: .seealso: PCCreate(), PCSetUp(), PCDiagonalScaleLeft(), PCDiagonalScaleSet(), PCDiagonalScale()
278: @*/
279: int PCDiagonalScaleRight(PC pc,Vec in,Vec out)
280: {

287:   if (pc->diagonalscale) {
288:     VecPointwiseMult(pc->diagonalscaleright,in,out);
289:   } else if (in != out) {
290:     VecCopy(in,out);
291:   }
292:   return(0);
293: }

297: static int PCPublish_Petsc(PetscObject obj)
298: {
299: #if defined(PETSC_HAVE_AMS)
300:   PC          v = (PC) obj;
301:   int         ierr;
302: #endif


306: #if defined(PETSC_HAVE_AMS)
307:   /* if it is already published then return */
308:   if (v->amem >=0) return(0);

310:   PetscObjectPublishBaseBegin(obj);
311:   PetscObjectPublishBaseEnd(obj);
312: #endif

314:   return(0);
315: }

319: /*@C
320:    PCCreate - Creates a preconditioner context.

322:    Collective on MPI_Comm

324:    Input Parameter:
325: .  comm - MPI communicator 

327:    Output Parameter:
328: .  pc - location to put the preconditioner context

330:    Notes:
331:    The default preconditioner on one processor is PCILU with 0 fill on more 
332:    then one it is PCBJACOBI with ILU() on each processor.

334:    Level: developer

336: .keywords: PC, create, context

338: .seealso: PCSetUp(), PCApply(), PCDestroy()
339: @*/
340: int PCCreate(MPI_Comm comm,PC *newpc)
341: {
342:   PC  pc;

347:   *newpc = 0;
348: #ifndef PETSC_USE_DYNAMIC_LIBRARIES
349:   PCInitializePackage(PETSC_NULL);
350: #endif

352:   PetscHeaderCreate(pc,_p_PC,struct _PCOps,PC_COOKIE,-1,"PC",comm,PCDestroy,PCView);
353:   PetscLogObjectCreate(pc);
354:   pc->bops->publish      = PCPublish_Petsc;
355:   pc->vec                = 0;
356:   pc->mat                = 0;
357:   pc->setupcalled        = 0;
358:   pc->nullsp             = 0;
359:   pc->data               = 0;
360:   pc->diagonalscale      = PETSC_FALSE;
361:   pc->diagonalscaleleft  = 0;
362:   pc->diagonalscaleright = 0;

364:   pc->ops->destroy             = 0;
365:   pc->ops->apply               = 0;
366:   pc->ops->applytranspose      = 0;
367:   pc->ops->applyBA             = 0;
368:   pc->ops->applyBAtranspose    = 0;
369:   pc->ops->applyrichardson     = 0;
370:   pc->ops->view                = 0;
371:   pc->ops->getfactoredmatrix   = 0;
372:   pc->ops->applysymmetricright = 0;
373:   pc->ops->applysymmetricleft  = 0;
374:   pc->ops->setuponblocks       = 0;

376:   pc->modifysubmatrices   = 0;
377:   pc->modifysubmatricesP  = 0;
378:   *newpc                  = pc;
379:   PetscPublishAll(pc);
380:   return(0);

382: }

384: /* -------------------------------------------------------------------------------*/

388: /*@
389:    PCApply - Applies the preconditioner to a vector.

391:    Collective on PC and Vec

393:    Input Parameters:
394: +  pc - the preconditioner context
395: -  x - input vector

397:    Output Parameter:
398: .  y - output vector

400:    Level: developer

402: .keywords: PC, apply

404: .seealso: PCApplyTranspose(), PCApplyBAorAB()
405: @*/
406: int PCApply(PC pc,Vec x,Vec y,PCSide side)
407: {
408:   int        ierr;

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

416:   if (pc->setupcalled < 2) {
417:     PCSetUp(pc);
418:   }

420:   /* Remove null space from input vector y */
421:   if (side == PC_RIGHT && pc->nullsp) {
422:     Vec tmp;
423:     MatNullSpaceRemove(pc->nullsp,x,&tmp);
424:     x    = tmp;
425:     SETERRQ(1,"Cannot deflate out null space if using right preconditioner!");
426:   }

428:   PetscLogEventBegin(PC_Apply,pc,x,y,0);
429:   (*pc->ops->apply)(pc,x,y);
430:   PetscLogEventEnd(PC_Apply,pc,x,y,0);

432:   /* Remove null space from preconditioned vector y */
433:   if (side == PC_LEFT && pc->nullsp) {
434:     MatNullSpaceRemove(pc->nullsp,y,PETSC_NULL);
435:   }
436:   return(0);
437: }

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

444:    Collective on PC and Vec

446:    Input Parameters:
447: +  pc - the preconditioner context
448: -  x - input vector

450:    Output Parameter:
451: .  y - output vector

453:    Notes:
454:    Currently, this routine is implemented only for PCICC and PCJACOBI preconditioners.

456:    Level: developer

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

460: .seealso: PCApply(), PCApplySymmetricRight()
461: @*/
462: int PCApplySymmetricLeft(PC pc,Vec x,Vec y)
463: {

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

472:   if (pc->setupcalled < 2) {
473:     PCSetUp(pc);
474:   }

476:   PetscLogEventBegin(PC_ApplySymmetricLeft,pc,x,y,0);
477:   (*pc->ops->applysymmetricleft)(pc,x,y);
478:   PetscLogEventEnd(PC_ApplySymmetricLeft,pc,x,y,0);
479:   return(0);
480: }

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

487:    Collective on PC and Vec

489:    Input Parameters:
490: +  pc - the preconditioner context
491: -  x - input vector

493:    Output Parameter:
494: .  y - output vector

496:    Level: developer

498:    Notes:
499:    Currently, this routine is implemented only for PCICC and PCJACOBI preconditioners.

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

503: .seealso: PCApply(), PCApplySymmetricLeft()
504: @*/
505: int PCApplySymmetricRight(PC pc,Vec x,Vec y)
506: {

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

515:   if (pc->setupcalled < 2) {
516:     PCSetUp(pc);
517:   }

519:   PetscLogEventBegin(PC_ApplySymmetricRight,pc,x,y,0);
520:   (*pc->ops->applysymmetricright)(pc,x,y);
521:   PetscLogEventEnd(PC_ApplySymmetricRight,pc,x,y,0);
522:   return(0);
523: }

527: /*@
528:    PCApplyTranspose - Applies the transpose of preconditioner to a vector.

530:    Collective on PC and Vec

532:    Input Parameters:
533: +  pc - the preconditioner context
534: -  x - input vector

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

539:    Level: developer

541: .keywords: PC, apply, transpose

543: .seealso: PCApply(), PCApplyBAorAB(), PCApplyBAorABTranspose(), PCHasApplyTranspose()
544: @*/
545: int PCApplyTranspose(PC pc,Vec x,Vec y)
546: {

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

556:   if (pc->setupcalled < 2) {
557:     PCSetUp(pc);
558:   }

560:   PetscLogEventBegin(PC_Apply,pc,x,y,0);
561:   (*pc->ops->applytranspose)(pc,x,y);
562:   PetscLogEventEnd(PC_Apply,pc,x,y,0);
563:   return(0);
564: }

568: /*@
569:    PCHasApplyTranspose - Test whether the preconditioner has a transpose apply operation

571:    Collective on PC and Vec

573:    Input Parameters:
574: .  pc - the preconditioner context

576:    Output Parameter:
577: .  flg - PETSC_TRUE if a transpose operation is defined

579:    Level: developer

581: .keywords: PC, apply, transpose

583: .seealso: PCApplyTranspose()
584: @*/
585: int PCHasApplyTranspose(PC pc,PetscTruth *flg)
586: {
590:   *flg = (PetscTruth) (pc->ops->applytranspose == 0);
591:   return(0);
592: }

596: /*@
597:    PCApplyBAorAB - Applies the preconditioner and operator to a vector. 

599:    Collective on PC and Vec

601:    Input Parameters:
602: +  pc - the preconditioner context
603: .  side - indicates the preconditioner side, one of PC_LEFT, PC_RIGHT, or PC_SYMMETRIC
604: .  x - input vector
605: -  work - work vector

607:    Output Parameter:
608: .  y - output vector

610:    Level: developer

612: .keywords: PC, apply, operator

614: .seealso: PCApply(), PCApplyTranspose(), PCApplyBAorABTranspose()
615: @*/
616: int PCApplyBAorAB(PC pc,PCSide side,Vec x,Vec y,Vec work)
617: {
618:   int        ierr;

625:   if (x == y) SETERRQ(PETSC_ERR_ARG_IDN,"x and y must be different vectors");
626:   if (side != PC_LEFT && side != PC_SYMMETRIC && side != PC_RIGHT) {
627:     SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Side must be right, left, or symmetric");
628:   }
629:   if (pc->diagonalscale && side == PC_SYMMETRIC) {
630:     SETERRQ(1,"Cannot include diagonal scaling with symmetric preconditioner application");
631:   }

633:   if (pc->setupcalled < 2) {
634:     PCSetUp(pc);
635:   }

637:   if (pc->diagonalscale) {
638:     if (pc->ops->applyBA) {
639:       Vec work2; /* this is expensive, but to fix requires a second work vector argument to PCApplyBAorAB() */
640:       VecDuplicate(x,&work2);
641:       PCDiagonalScaleRight(pc,x,work2);
642:       (*pc->ops->applyBA)(pc,side,work2,y,work);
643:       /* Remove null space from preconditioned vector y */
644:       if (pc->nullsp) {
645:         MatNullSpaceRemove(pc->nullsp,y,PETSC_NULL);
646:       }
647:       PCDiagonalScaleLeft(pc,y,y);
648:       VecDestroy(work2);
649:     } else if (side == PC_RIGHT) {
650:       PCDiagonalScaleRight(pc,x,y);
651:       PCApply(pc,y,work,side);
652:       MatMult(pc->mat,work,y);
653:       PCDiagonalScaleLeft(pc,y,y);
654:     } else if (side == PC_LEFT) {
655:       PCDiagonalScaleRight(pc,x,y);
656:       MatMult(pc->mat,y,work);
657:       PCApply(pc,work,y,side);
658:       PCDiagonalScaleLeft(pc,y,y);
659:     } else if (side == PC_SYMMETRIC) {
660:       SETERRQ(1,"Cannot provide diagonal scaling with symmetric application of preconditioner");
661:     }
662:   } else {
663:     if (pc->ops->applyBA) {
664:       (*pc->ops->applyBA)(pc,side,x,y,work);
665:       /* Remove null space from preconditioned vector y */
666:       if (pc->nullsp) {
667:         MatNullSpaceRemove(pc->nullsp,y,PETSC_NULL);
668:       }
669:     } else if (side == PC_RIGHT) {
670:       PCApply(pc,x,work,side);
671:       MatMult(pc->mat,work,y);
672:     } else if (side == PC_LEFT) {
673:       MatMult(pc->mat,x,work);
674:       PCApply(pc,work,y,side);
675:     } else if (side == PC_SYMMETRIC) {
676:       /* There's an extra copy here; maybe should provide 2 work vectors instead? */
677:       PCApplySymmetricRight(pc,x,work);
678:       MatMult(pc->mat,work,y);
679:       VecCopy(y,work);
680:       PCApplySymmetricLeft(pc,work,y);
681:     }
682:   }
683:   return(0);
684: }

688: /*@ 
689:    PCApplyBAorABTranspose - Applies the transpose of the preconditioner
690:    and operator to a vector. That is, applies tr(B) * tr(A) with left preconditioning,
691:    not tr(B*A) = tr(A)*tr(B).

693:    Collective on PC and Vec

695:    Input Parameters:
696: +  pc - the preconditioner context
697: .  side - indicates the preconditioner side, one of PC_LEFT, PC_RIGHT, or PC_SYMMETRIC
698: .  x - input vector
699: -  work - work vector

701:    Output Parameter:
702: .  y - output vector

704:    Level: developer

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

708: .seealso: PCApply(), PCApplyTranspose(), PCApplyBAorAB()
709: @*/
710: int PCApplyBAorABTranspose(PC pc,PCSide side,Vec x,Vec y,Vec work)
711: {

719:   if (x == y) SETERRQ(PETSC_ERR_ARG_IDN,"x and y must be different vectors");
720:   if (pc->ops->applyBAtranspose) {
721:     (*pc->ops->applyBAtranspose)(pc,side,x,y,work);
722:     return(0);
723:   }
724:   if (side != PC_LEFT && side != PC_RIGHT) {
725:     SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Side must be right or left");
726:   }

728:   if (pc->setupcalled < 2) {
729:     PCSetUp(pc);
730:   }

732:   if (side == PC_RIGHT) {
733:     PCApplyTranspose(pc,x,work);
734:     MatMultTranspose(pc->mat,work,y);
735:   } else if (side == PC_LEFT) {
736:     MatMultTranspose(pc->mat,x,work);
737:     PCApplyTranspose(pc,work,y);
738:   }
739:   /* add support for PC_SYMMETRIC */
740:   return(0); /* actually will never get here */
741: }

743: /* -------------------------------------------------------------------------------*/

747: /*@
748:    PCApplyRichardsonExists - Determines whether a particular preconditioner has a 
749:    built-in fast application of Richardson's method.

751:    Not Collective

753:    Input Parameter:
754: .  pc - the preconditioner

756:    Output Parameter:
757: .  exists - PETSC_TRUE or PETSC_FALSE

759:    Level: developer

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

763: .seealso: PCApplyRichardson()
764: @*/
765: int PCApplyRichardsonExists(PC pc,PetscTruth *exists)
766: {
770:   if (pc->ops->applyrichardson) *exists = PETSC_TRUE;
771:   else                    *exists = PETSC_FALSE;
772:   return(0);
773: }

777: /*@
778:    PCApplyRichardson - Applies several steps of Richardson iteration with 
779:    the particular preconditioner. This routine is usually used by the 
780:    Krylov solvers and not the application code directly.

782:    Collective on PC

784:    Input Parameters:
785: +  pc  - the preconditioner context
786: .  x   - the initial guess 
787: .  w   - one work vector
788: .  rtol - relative decrease in residual norm convergence criteria
789: .  atol - absolute residual norm convergence criteria
790: .  dtol - divergence residual norm increase criteria
791: -  its - the number of iterations to apply.

793:    Output Parameter:
794: .  y - the solution

796:    Notes: 
797:    Most preconditioners do not support this function. Use the command
798:    PCApplyRichardsonExists() to determine if one does.

800:    Except for the multigrid PC this routine ignores the convergence tolerances
801:    and always runs for the number of iterations
802:  
803:    Level: developer

805: .keywords: PC, apply, Richardson

807: .seealso: PCApplyRichardsonExists()
808: @*/
809: int PCApplyRichardson(PC pc,Vec x,Vec y,Vec w,PetscReal rtol,PetscReal atol, PetscReal dtol,int its)
810: {

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

820:   if (pc->setupcalled < 2) {
821:     PCSetUp(pc);
822:   }

824:   (*pc->ops->applyrichardson)(pc,x,y,w,rtol,atol,dtol,its);
825:   return(0);
826: }

828: /* 
829:       a setupcall of 0 indicates never setup, 
830:                      1 needs to be resetup,
831:                      2 does not need any changes.
832: */
835: /*@
836:    PCSetUp - Prepares for the use of a preconditioner.

838:    Collective on PC

840:    Input Parameter:
841: .  pc - the preconditioner context

843:    Level: developer

845: .keywords: PC, setup

847: .seealso: PCCreate(), PCApply(), PCDestroy()
848: @*/
849: int PCSetUp(PC pc)
850: {
851:   int        ierr;
852:   const char *def;


857:   if (pc->setupcalled > 1) {
858:     PetscLogInfo(pc,"PCSetUp:Setting PC with identical preconditioner\n");
859:     return(0);
860:   } else if (pc->setupcalled == 0) {
861:     PetscLogInfo(pc,"PCSetUp:Setting up new PC\n");
862:   } else if (pc->flag == SAME_NONZERO_PATTERN) {
863:     PetscLogInfo(pc,"PCSetUp:Setting up PC with same nonzero pattern\n");
864:   } else {
865:     PetscLogInfo(pc,"PCSetUp:Setting up PC with different nonzero pattern\n");
866:   }

868:   PetscLogEventBegin(PC_SetUp,pc,0,0,0);
869:   if (!pc->vec) {SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Vector must be set first");}
870:   if (!pc->mat) {SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Matrix must be set first");}

872:   if (!pc->type_name) {
873:     PCGetDefaultType_Private(pc,&def);
874:     PCSetType(pc,def);
875:   }

877:   if (pc->ops->setup) {
878:     (*pc->ops->setup)(pc);
879:   }
880:   pc->setupcalled = 2;
881:   if (pc->nullsp) {
882:     PetscTruth test;
883:     PetscOptionsHasName(pc->prefix,"-pc_test_null_space",&test);
884:     if (test) {
885:       MatNullSpaceTest(pc->nullsp,pc->mat);
886:     }
887:   }
888:   PetscLogEventEnd(PC_SetUp,pc,0,0,0);
889:   return(0);
890: }

894: /*@
895:    PCSetUpOnBlocks - Sets up the preconditioner for each block in
896:    the block Jacobi, block Gauss-Seidel, and overlapping Schwarz 
897:    methods.

899:    Collective on PC

901:    Input Parameters:
902: .  pc - the preconditioner context

904:    Level: developer

906: .keywords: PC, setup, blocks

908: .seealso: PCCreate(), PCApply(), PCDestroy(), PCSetUp()
909: @*/
910: int PCSetUpOnBlocks(PC pc)
911: {

916:   if (!pc->ops->setuponblocks) return(0);
917:   PetscLogEventBegin(PC_SetUpOnBlocks,pc,0,0,0);
918:   (*pc->ops->setuponblocks)(pc);
919:   PetscLogEventEnd(PC_SetUpOnBlocks,pc,0,0,0);
920:   return(0);
921: }

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

932:    Collective on PC

934:    Input Parameters:
935: +  pc - the preconditioner context
936: .  func - routine for modifying the submatrices
937: -  ctx - optional user-defined context (may be null)

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

942: .  row - an array of index sets that contain the global row numbers
943:          that comprise each local submatrix
944: .  col - an array of index sets that contain the global column numbers
945:          that comprise each local submatrix
946: .  submat - array of local submatrices
947: -  ctx - optional user-defined context for private data for the 
948:          user-defined func routine (may be null)

950:    Notes:
951:    PCSetModifySubMatrices() MUST be called before KSPSetUp() and
952:    KSPSolve().

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

958:    Level: advanced

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

962: .seealso: PCModifySubMatrices()
963: @*/
964: int PCSetModifySubMatrices(PC pc,int(*func)(PC,int,const IS[],const IS[],Mat[],void*),void *ctx)
965: {
968:   pc->modifysubmatrices  = func;
969:   pc->modifysubmatricesP = ctx;
970:   return(0);
971: }

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

979:    Collective on PC

981:    Input Parameters:
982: +  pc - the preconditioner context
983: .  nsub - the number of local submatrices
984: .  row - an array of index sets that contain the global row numbers
985:          that comprise each local submatrix
986: .  col - an array of index sets that contain the global column numbers
987:          that comprise each local submatrix
988: .  submat - array of local submatrices
989: -  ctx - optional user-defined context for private data for the 
990:          user-defined routine (may be null)

992:    Output Parameter:
993: .  submat - array of local submatrices (the entries of which may
994:             have been modified)

996:    Notes:
997:    The user should NOT generally call this routine, as it will
998:    automatically be called within certain preconditioners (currently
999:    block Jacobi, additive Schwarz) if set.

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

1006:    Level: developer

1008: .keywords: PC, modify, submatrices

1010: .seealso: PCSetModifySubMatrices()
1011: @*/
1012: int PCModifySubMatrices(PC pc,int nsub,const IS row[],const IS col[],Mat submat[],void *ctx)
1013: {

1017:   if (!pc->modifysubmatrices) return(0);
1018:   PetscLogEventBegin(PC_ModifySubMatrices,pc,0,0,0);
1019:   (*pc->modifysubmatrices)(pc,nsub,row,col,submat,ctx);
1020:   PetscLogEventEnd(PC_ModifySubMatrices,pc,0,0,0);
1021:   return(0);
1022: }

1026: /*@
1027:    PCSetOperators - Sets the matrix associated with the linear system and 
1028:    a (possibly) different one associated with the preconditioner.

1030:    Collective on PC and Mat

1032:    Input Parameters:
1033: +  pc - the preconditioner context
1034: .  Amat - the matrix associated with the linear system
1035: .  Pmat - the matrix to be used in constructing the preconditioner, usually
1036:           the same as Amat. 
1037: -  flag - flag indicating information about the preconditioner matrix structure
1038:    during successive linear solves.  This flag is ignored the first time a
1039:    linear system is solved, and thus is irrelevant when solving just one linear
1040:    system.

1042:    Notes: 
1043:    The flag can be used to eliminate unnecessary work in the preconditioner 
1044:    during the repeated solution of linear systems of the same size.  The 
1045:    available options are
1046: +    SAME_PRECONDITIONER -
1047:        Pmat is identical during successive linear solves.
1048:        This option is intended for folks who are using
1049:        different Amat and Pmat matrices and wish to reuse the
1050:        same preconditioner matrix.  For example, this option
1051:        saves work by not recomputing incomplete factorization
1052:        for ILU/ICC preconditioners.
1053: .     SAME_NONZERO_PATTERN -
1054:        Pmat has the same nonzero structure during
1055:        successive linear solves. 
1056: -     DIFFERENT_NONZERO_PATTERN -
1057:        Pmat does not have the same nonzero structure.

1059:    Caution:
1060:    If you specify SAME_NONZERO_PATTERN, PETSc believes your assertion
1061:    and does not check the structure of the matrix.  If you erroneously
1062:    claim that the structure is the same when it actually is not, the new
1063:    preconditioner will not function correctly.  Thus, use this optimization
1064:    feature carefully!

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

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

1075:    Level: intermediate

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

1079: .seealso: PCGetOperators(), MatZeroEntries()
1080:  @*/
1081: int PCSetOperators(PC pc,Mat Amat,Mat Pmat,MatStructure flag)
1082: {
1083:   int        ierr;
1084:   PetscTruth isbjacobi,isrowbs;


1091:   /*
1092:       BlockSolve95 cannot use default BJacobi preconditioning
1093:   */
1094:   PetscTypeCompare((PetscObject)Amat,MATMPIROWBS,&isrowbs);
1095:   if (isrowbs) {
1096:     PetscTypeCompare((PetscObject)pc,PCBJACOBI,&isbjacobi);
1097:     if (isbjacobi) {
1098:       PCSetType(pc,PCILU);
1099:       PetscLogInfo(pc,"PCSetOperators:Switching default PC to PCILU since BS95 doesn't support PCBJACOBI\n");
1100:     }
1101:   }

1103:   pc->mat  = Amat;
1104:   pc->pmat = Pmat;
1105:   if (pc->setupcalled == 2 && flag != SAME_PRECONDITIONER) {
1106:     pc->setupcalled = 1;
1107:   }
1108:   pc->flag = flag;
1109:   return(0);
1110: }

1114: /*@C
1115:    PCGetOperators - Gets the matrix associated with the linear system and
1116:    possibly a different one associated with the preconditioner.

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

1120:    Input Parameter:
1121: .  pc - the preconditioner context

1123:    Output Parameters:
1124: +  mat - the matrix associated with the linear system
1125: .  pmat - matrix associated with the preconditioner, usually the same
1126:           as mat. 
1127: -  flag - flag indicating information about the preconditioner
1128:           matrix structure.  See PCSetOperators() for details.

1130:    Level: intermediate

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

1134: .seealso: PCSetOperators()
1135: @*/
1136: int PCGetOperators(PC pc,Mat *mat,Mat *pmat,MatStructure *flag)
1137: {
1140:   if (mat)  *mat  = pc->mat;
1141:   if (pmat) *pmat = pc->pmat;
1142:   if (flag) *flag = pc->flag;
1143:   return(0);
1144: }

1148: /*@
1149:    PCSetVector - Sets a vector associated with the preconditioner.

1151:    Collective on PC and Vec

1153:    Input Parameters:
1154: +  pc - the preconditioner context
1155: -  vec - the vector

1157:    Notes:
1158:    The vector must be set so that the preconditioner knows what type
1159:    of vector to allocate if necessary.

1161:    Level: intermediate

1163: .keywords: PC, set, vector

1165: .seealso: PCGetVector()

1167: @*/
1168: int PCSetVector(PC pc,Vec vec)
1169: {
1174:   pc->vec = vec;
1175:   return(0);
1176: }

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

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

1186:    Input Parameter:
1187: .  pc - the preconditioner context

1189:    Output Parameter:
1190: .  vec - the vector

1192:    Level: intermediate

1194: .keywords: PC, get, vector

1196: .seealso: PCSetVector()

1198: @*/
1199: int PCGetVector(PC pc,Vec *vec)
1200: {
1203:   *vec = pc->vec;
1204:   return(0);
1205: }

1209: /*@C 
1210:    PCGetFactoredMatrix - Gets the factored matrix from the
1211:    preconditioner context.  This routine is valid only for the LU, 
1212:    incomplete LU, Cholesky, and incomplete Cholesky methods.

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

1216:    Input Parameters:
1217: .  pc - the preconditioner context

1219:    Output parameters:
1220: .  mat - the factored matrix

1222:    Level: advanced

1224: .keywords: PC, get, factored, matrix
1225: @*/
1226: int PCGetFactoredMatrix(PC pc,Mat *mat)
1227: {

1233:   if (pc->ops->getfactoredmatrix) {
1234:     (*pc->ops->getfactoredmatrix)(pc,mat);
1235:   }
1236:   return(0);
1237: }

1241: /*@C
1242:    PCSetOptionsPrefix - Sets the prefix used for searching for all 
1243:    PC options in the database.

1245:    Collective on PC

1247:    Input Parameters:
1248: +  pc - the preconditioner context
1249: -  prefix - the prefix string to prepend to all PC option requests

1251:    Notes:
1252:    A hyphen (-) must NOT be given at the beginning of the prefix name.
1253:    The first character of all runtime options is AUTOMATICALLY the
1254:    hyphen.

1256:    Level: advanced

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

1260: .seealso: PCAppendOptionsPrefix(), PCGetOptionsPrefix()
1261: @*/
1262: int PCSetOptionsPrefix(PC pc,const char prefix[])
1263: {

1268:   PetscObjectSetOptionsPrefix((PetscObject)pc,prefix);
1269:   return(0);
1270: }

1274: /*@C
1275:    PCAppendOptionsPrefix - Appends to the prefix used for searching for all 
1276:    PC options in the database.

1278:    Collective on PC

1280:    Input Parameters:
1281: +  pc - the preconditioner context
1282: -  prefix - the prefix string to prepend to all PC option requests

1284:    Notes:
1285:    A hyphen (-) must NOT be given at the beginning of the prefix name.
1286:    The first character of all runtime options is AUTOMATICALLY the
1287:    hyphen.

1289:    Level: advanced

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

1293: .seealso: PCSetOptionsPrefix(), PCGetOptionsPrefix()
1294: @*/
1295: int PCAppendOptionsPrefix(PC pc,const char prefix[])
1296: {

1301:   PetscObjectAppendOptionsPrefix((PetscObject)pc,prefix);
1302:   return(0);
1303: }

1307: /*@C
1308:    PCGetOptionsPrefix - Gets the prefix used for searching for all 
1309:    PC options in the database.

1311:    Not Collective

1313:    Input Parameters:
1314: .  pc - the preconditioner context

1316:    Output Parameters:
1317: .  prefix - pointer to the prefix string used, is returned

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

1322:    Level: advanced

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

1326: .seealso: PCSetOptionsPrefix(), PCAppendOptionsPrefix()
1327: @*/
1328: int PCGetOptionsPrefix(PC pc,char *prefix[])
1329: {

1335:   PetscObjectGetOptionsPrefix((PetscObject)pc,prefix);
1336:   return(0);
1337: }

1341: /*@
1342:    PCPreSolve - Optional pre-solve phase, intended for any
1343:    preconditioner-specific actions that must be performed before 
1344:    the iterative solve itself.

1346:    Collective on PC

1348:    Input Parameters:
1349: +  pc - the preconditioner context
1350: -  ksp - the Krylov subspace context

1352:    Level: developer

1354:    Sample of Usage:
1355: .vb
1356:     PCPreSolve(pc,ksp);
1357:     KSPSolve(ksp,its);
1358:     PCPostSolve(pc,ksp);
1359: .ve

1361:    Notes:
1362:    The pre-solve phase is distinct from the PCSetUp() phase.

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

1366: .keywords: PC, pre-solve

1368: .seealso: PCPostSolve()
1369: @*/
1370: int PCPreSolve(PC pc,KSP ksp)
1371: {
1373:   Vec x,rhs;
1374:   Mat A,B;

1379:   KSPGetSolution(ksp,&x);
1380:   KSPGetRhs(ksp,&rhs);
1381:   /*
1382:       Scale the system and have the matrices use the scaled form
1383:     only if the two matrices are actually the same (and hence
1384:     have the same scaling
1385:   */
1386:   PCGetOperators(pc,&A,&B,PETSC_NULL);
1387:   if (A == B) {
1388:     MatScaleSystem(pc->mat,x,rhs);
1389:     MatUseScaledForm(pc->mat,PETSC_TRUE);
1390:   }

1392:   if (pc->ops->presolve) {
1393:     (*pc->ops->presolve)(pc,ksp,x,rhs);
1394:   }
1395:   return(0);
1396: }

1400: /*@
1401:    PCPostSolve - Optional post-solve phase, intended for any
1402:    preconditioner-specific actions that must be performed after
1403:    the iterative solve itself.

1405:    Collective on PC

1407:    Input Parameters:
1408: +  pc - the preconditioner context
1409: -  ksp - the Krylov subspace context

1411:    Sample of Usage:
1412: .vb
1413:     PCPreSolve(pc,ksp);
1414:     KSPSolve(ksp,its);
1415:     PCPostSolve(pc,ksp);
1416: .ve

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

1421:    Level: developer

1423: .keywords: PC, post-solve

1425: .seealso: PCPreSolve(), KSPSolve()
1426: @*/
1427: int PCPostSolve(PC pc,KSP ksp)
1428: {
1430:   Vec x,rhs;
1431:   Mat A,B;

1436:   KSPGetSolution(ksp,&x);
1437:   KSPGetRhs(ksp,&rhs);
1438:   if (pc->ops->postsolve) {
1439:      (*pc->ops->postsolve)(pc,ksp,x,rhs);
1440:   }

1442:   /*
1443:       Scale the system and have the matrices use the scaled form
1444:     only if the two matrices are actually the same (and hence
1445:     have the same scaling
1446:   */
1447:   PCGetOperators(pc,&A,&B,PETSC_NULL);
1448:   if (A == B) {
1449:     MatUnScaleSystem(pc->mat,x,rhs);
1450:     MatUseScaledForm(pc->mat,PETSC_FALSE);
1451:   }
1452:   return(0);
1453: }

1457: /*@C
1458:    PCView - Prints the PC data structure.

1460:    Collective on PC

1462:    Input Parameters:
1463: +  PC - the PC context
1464: -  viewer - optional visualization context

1466:    Note:
1467:    The available visualization contexts include
1468: +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
1469: -     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
1470:          output where only the first processor opens
1471:          the file.  All other processors send their 
1472:          data to the first processor to print. 

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

1477:    Level: developer

1479: .keywords: PC, view

1481: .seealso: KSPView(), PetscViewerASCIIOpen()
1482: @*/
1483: int PCView(PC pc,PetscViewer viewer)
1484: {
1485:   PCType            cstr;
1486:   int               ierr;
1487:   PetscTruth        mat_exists,isascii,isstring;
1488:   PetscViewerFormat format;

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

1496:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
1497:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_STRING,&isstring);
1498:   if (isascii) {
1499:     PetscViewerGetFormat(viewer,&format);
1500:     if (pc->prefix) {
1501:       PetscViewerASCIIPrintf(viewer,"PC Object:(%s)\n",pc->prefix);
1502:     } else {
1503:       PetscViewerASCIIPrintf(viewer,"PC Object:\n");
1504:     }
1505:     PCGetType(pc,&cstr);
1506:     if (cstr) {
1507:       PetscViewerASCIIPrintf(viewer,"  type: %s\n",cstr);
1508:     } else {
1509:       PetscViewerASCIIPrintf(viewer,"  type: not yet set\n");
1510:     }
1511:     if (pc->ops->view) {
1512:       PetscViewerASCIIPushTab(viewer);
1513:       (*pc->ops->view)(pc,viewer);
1514:       PetscViewerASCIIPopTab(viewer);
1515:     }
1516:     PetscObjectExists((PetscObject)pc->mat,&mat_exists);
1517:     if (mat_exists) {
1518:       PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_INFO);
1519:       if (pc->pmat == pc->mat) {
1520:         PetscViewerASCIIPrintf(viewer,"  linear system matrix = precond matrix:\n");
1521:         PetscViewerASCIIPushTab(viewer);
1522:         MatView(pc->mat,viewer);
1523:         PetscViewerASCIIPopTab(viewer);
1524:       } else {
1525:         PetscObjectExists((PetscObject)pc->pmat,&mat_exists);
1526:         if (mat_exists) {
1527:           PetscViewerASCIIPrintf(viewer,"  linear system matrix followed by preconditioner matrix:\n");
1528:         } else {
1529:           PetscViewerASCIIPrintf(viewer,"  linear system matrix:\n");
1530:         }
1531:         PetscViewerASCIIPushTab(viewer);
1532:         MatView(pc->mat,viewer);
1533:         if (mat_exists) {MatView(pc->pmat,viewer);}
1534:         PetscViewerASCIIPopTab(viewer);
1535:       }
1536:       PetscViewerPopFormat(viewer);
1537:     }
1538:   } else if (isstring) {
1539:     PCGetType(pc,&cstr);
1540:     PetscViewerStringSPrintf(viewer," %-7.7s",cstr);
1541:     if (pc->ops->view) {(*pc->ops->view)(pc,viewer);}
1542:   } else {
1543:     SETERRQ1(1,"Viewer type %s not supported by PC",((PetscObject)viewer)->type_name);
1544:   }
1545:   return(0);
1546: }

1550: /*@C
1551:   PCRegister - See PCRegisterDynamic()

1553:   Level: advanced
1554: @*/
1555: int PCRegister(const char sname[],const char path[],const char name[],int (*function)(PC))
1556: {
1557:   int  ierr;
1558:   char fullname[256];


1562:   PetscFListConcat(path,name,fullname);
1563:   PetscFListAdd(&PCList,sname,fullname,(void (*)(void))function);
1564:   return(0);
1565: }

1569: /*@
1570:     PCComputeExplicitOperator - Computes the explicit preconditioned operator.  

1572:     Collective on PC

1574:     Input Parameter:
1575: .   pc - the preconditioner object

1577:     Output Parameter:
1578: .   mat - the explict preconditioned operator

1580:     Notes:
1581:     This computation is done by applying the operators to columns of the 
1582:     identity matrix.

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

1588:     Level: advanced
1589:    
1590: .keywords: PC, compute, explicit, operator

1592: @*/
1593: int PCComputeExplicitOperator(PC pc,Mat *mat)
1594: {
1595:   Vec      in,out;
1596:   int      ierr,i,M,m,size,*rows,start,end;
1597:   MPI_Comm comm;
1598:   PetscScalar   *array,zero = 0.0,one = 1.0;


1604:   comm = pc->comm;
1605:   MPI_Comm_size(comm,&size);

1607:   PCGetVector(pc,&in);
1608:   VecDuplicate(in,&out);
1609:   VecGetOwnershipRange(in,&start,&end);
1610:   VecGetSize(in,&M);
1611:   VecGetLocalSize(in,&m);
1612:   PetscMalloc((m+1)*sizeof(int),&rows);
1613:   for (i=0; i<m; i++) {rows[i] = start + i;}

1615:   MatCreate(comm,m,m,M,M,mat);
1616:   if (size == 1) {
1617:     MatSetType(*mat,MATSEQDENSE);
1618:     MatSeqDenseSetPreallocation(*mat,PETSC_NULL);
1619:   } else {
1620:     MatSetType(*mat,MATMPIAIJ);
1621:     MatMPIAIJSetPreallocation(*mat,0,PETSC_NULL,0,PETSC_NULL);
1622:   }

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

1626:     VecSet(&zero,in);
1627:     VecSetValues(in,1,&i,&one,INSERT_VALUES);
1628:     VecAssemblyBegin(in);
1629:     VecAssemblyEnd(in);

1631:     /* should fix, allowing user to choose side */
1632:     PCApply(pc,in,out,PC_LEFT);
1633: 
1634:     VecGetArray(out,&array);
1635:     MatSetValues(*mat,m,rows,1,&i,array,INSERT_VALUES);
1636:     VecRestoreArray(out,&array);

1638:   }
1639:   PetscFree(rows);
1640:   VecDestroy(out);
1641:   MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);
1642:   MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);
1643:   return(0);
1644: }