Actual source code: mgfunc.c

petsc-master 2018-04-16
Report Typos and Errors

  2:  #include <petsc/private/pcmgimpl.h>

  4: /* ---------------------------------------------------------------------------*/
  5: /*@C
  6:    PCMGResidualDefault - Default routine to calculate the residual.

  8:    Collective on Mat and Vec

 10:    Input Parameters:
 11: +  mat - the matrix
 12: .  b   - the right-hand-side
 13: -  x   - the approximate solution

 15:    Output Parameter:
 16: .  r - location to store the residual

 18:    Level: developer

 20: .keywords: MG, default, multigrid, residual

 22: .seealso: PCMGSetResidual()
 23: @*/
 24: PetscErrorCode  PCMGResidualDefault(Mat mat,Vec b,Vec x,Vec r)
 25: {

 29:   MatResidual(mat,b,x,r);
 30:   return(0);
 31: }

 33: /*@
 34:    PCMGGetCoarseSolve - Gets the solver context to be used on the coarse grid.

 36:    Not Collective

 38:    Input Parameter:
 39: .  pc - the multigrid context

 41:    Output Parameter:
 42: .  ksp - the coarse grid solver context

 44:    Level: advanced

 46: .keywords: MG, multigrid, get, coarse grid
 47: @*/
 48: PetscErrorCode  PCMGGetCoarseSolve(PC pc,KSP *ksp)
 49: {
 50:   PC_MG        *mg        = (PC_MG*)pc->data;
 51:   PC_MG_Levels **mglevels = mg->levels;

 55:   *ksp =  mglevels[0]->smoothd;
 56:   return(0);
 57: }

 59: /*@C
 60:    PCMGSetResidual - Sets the function to be used to calculate the residual
 61:    on the lth level.

 63:    Logically Collective on PC and Mat

 65:    Input Parameters:
 66: +  pc       - the multigrid context
 67: .  l        - the level (0 is coarsest) to supply
 68: .  residual - function used to form residual, if none is provided the previously provide one is used, if no
 69:               previous one were provided then a default is used
 70: -  mat      - matrix associated with residual

 72:    Level: advanced

 74: .keywords:  MG, set, multigrid, residual, level

 76: .seealso: PCMGResidualDefault()
 77: @*/
 78: PetscErrorCode  PCMGSetResidual(PC pc,PetscInt l,PetscErrorCode (*residual)(Mat,Vec,Vec,Vec),Mat mat)
 79: {
 80:   PC_MG          *mg        = (PC_MG*)pc->data;
 81:   PC_MG_Levels   **mglevels = mg->levels;

 86:   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
 87:   if (residual) mglevels[l]->residual = residual;
 88:   if (!mglevels[l]->residual) mglevels[l]->residual = PCMGResidualDefault;
 89:   if (mat) {PetscObjectReference((PetscObject)mat);}
 90:   MatDestroy(&mglevels[l]->A);
 91:   mglevels[l]->A = mat;
 92:   return(0);
 93: }

 95: /*@
 96:    PCMGSetInterpolation - Sets the function to be used to calculate the
 97:    interpolation from l-1 to the lth level

 99:    Logically Collective on PC and Mat

101:    Input Parameters:
102: +  pc  - the multigrid context
103: .  mat - the interpolation operator
104: -  l   - the level (0 is coarsest) to supply [do not supply 0]

106:    Level: advanced

108:    Notes:
109:           Usually this is the same matrix used also to set the restriction
110:     for the same level.

112:           One can pass in the interpolation matrix or its transpose; PETSc figures
113:     out from the matrix size which one it is.

115: .keywords:  multigrid, set, interpolate, level

117: .seealso: PCMGSetRestriction()
118: @*/
119: PetscErrorCode  PCMGSetInterpolation(PC pc,PetscInt l,Mat mat)
120: {
121:   PC_MG          *mg        = (PC_MG*)pc->data;
122:   PC_MG_Levels   **mglevels = mg->levels;

127:   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
128:   if (!l) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Do not set interpolation routine for coarsest level");
129:   PetscObjectReference((PetscObject)mat);
130:   MatDestroy(&mglevels[l]->interpolate);

132:   mglevels[l]->interpolate = mat;
133:   return(0);
134: }

136: /*@
137:    PCMGGetInterpolation - Gets the function to be used to calculate the
138:    interpolation from l-1 to the lth level

140:    Logically Collective on PC

142:    Input Parameters:
143: +  pc - the multigrid context
144: -  l - the level (0 is coarsest) to supply [Do not supply 0]

146:    Output Parameter:
147: .  mat - the interpolation matrix, can be NULL

149:    Level: advanced

151: .keywords: MG, get, multigrid, interpolation, level

153: .seealso: PCMGGetRestriction(), PCMGSetInterpolation(), PCMGGetRScale()
154: @*/
155: PetscErrorCode  PCMGGetInterpolation(PC pc,PetscInt l,Mat *mat)
156: {
157:   PC_MG          *mg        = (PC_MG*)pc->data;
158:   PC_MG_Levels   **mglevels = mg->levels;

164:   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
165:   if (l <= 0 || mg->nlevels <= l) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Level %D must be in range {1,...,%D}",l,mg->nlevels-1);
166:   if (!mglevels[l]->interpolate) {
167:     if (!mglevels[l]->restrct) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must call PCMGSetInterpolation() or PCMGSetRestriction()");
168:     PCMGSetInterpolation(pc,l,mglevels[l]->restrct);
169:   }
170:   if (mat) *mat = mglevels[l]->interpolate;
171:   return(0);
172: }

174: /*@
175:    PCMGSetRestriction - Sets the function to be used to restrict dual vectors
176:    from level l to l-1.

178:    Logically Collective on PC and Mat

180:    Input Parameters:
181: +  pc - the multigrid context
182: .  l - the level (0 is coarsest) to supply [Do not supply 0]
183: -  mat - the restriction matrix

185:    Level: advanced

187:    Notes:
188:           Usually this is the same matrix used also to set the interpolation
189:     for the same level.

191:           One can pass in the interpolation matrix or its transpose; PETSc figures
192:     out from the matrix size which one it is.

194:          If you do not set this, the transpose of the Mat set with PCMGSetInterpolation()
195:     is used.

197: .keywords: MG, set, multigrid, restriction, level

199: .seealso: PCMGSetInterpolation(), PCMGetSetInjection()
200: @*/
201: PetscErrorCode  PCMGSetRestriction(PC pc,PetscInt l,Mat mat)
202: {
204:   PC_MG          *mg        = (PC_MG*)pc->data;
205:   PC_MG_Levels   **mglevels = mg->levels;

210:   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
211:   if (!l) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Do not set restriction routine for coarsest level");
212:   PetscObjectReference((PetscObject)mat);
213:   MatDestroy(&mglevels[l]->restrct);

215:   mglevels[l]->restrct = mat;
216:   return(0);
217: }

219: /*@
220:    PCMGGetRestriction - Gets the function to be used to restrict dual vectors
221:    from level l to l-1.

223:    Logically Collective on PC and Mat

225:    Input Parameters:
226: +  pc - the multigrid context
227: -  l - the level (0 is coarsest) to supply [Do not supply 0]

229:    Output Parameter:
230: .  mat - the restriction matrix

232:    Level: advanced

234: .keywords: MG, get, multigrid, restriction, level

236: .seealso: PCMGGetInterpolation(), PCMGSetRestriction(), PCMGGetRScale(), PCMGGetInjection()
237: @*/
238: PetscErrorCode  PCMGGetRestriction(PC pc,PetscInt l,Mat *mat)
239: {
240:   PC_MG          *mg        = (PC_MG*)pc->data;
241:   PC_MG_Levels   **mglevels = mg->levels;

247:   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
248:   if (l <= 0 || mg->nlevels <= l) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Level %D must be in range {1,...,%D}",l,mg->nlevels-1);
249:   if (!mglevels[l]->restrct) {
250:     if (!mglevels[l]->interpolate) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must call PCMGSetRestriction() or PCMGSetInterpolation()");
251:     PCMGSetRestriction(pc,l,mglevels[l]->interpolate);
252:   }
253:   if (mat) *mat = mglevels[l]->restrct;
254:   return(0);
255: }

257: /*@
258:    PCMGSetRScale - Sets the pointwise scaling for the restriction operator from level l to l-1.

260:    Logically Collective on PC and Vec

262:    Input Parameters:
263: +  pc - the multigrid context
264: -  l - the level (0 is coarsest) to supply [Do not supply 0]
265: .  rscale - the scaling

267:    Level: advanced

269:    Notes:
270:        When evaluating a function on a coarse level one does not want to do F(R * x) one does F(rscale * R * x) where rscale is 1 over the row sums of R.  It is preferable to use PCMGSetInjection() to control moving primal vectors.

272: .keywords: MG, set, multigrid, restriction, level

274: .seealso: PCMGSetInterpolation(), PCMGSetRestriction(), PCMGGetRScale(), PCMGSetInjection()
275: @*/
276: PetscErrorCode  PCMGSetRScale(PC pc,PetscInt l,Vec rscale)
277: {
279:   PC_MG          *mg        = (PC_MG*)pc->data;
280:   PC_MG_Levels   **mglevels = mg->levels;

284:   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
285:   if (l <= 0 || mg->nlevels <= l) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Level %D must be in range {1,...,%D}",l,mg->nlevels-1);
286:   PetscObjectReference((PetscObject)rscale);
287:   VecDestroy(&mglevels[l]->rscale);

289:   mglevels[l]->rscale = rscale;
290:   return(0);
291: }

293: /*@
294:    PCMGGetRScale - Gets the pointwise scaling for the restriction operator from level l to l-1.

296:    Collective on PC

298:    Input Parameters:
299: +  pc - the multigrid context
300: .  rscale - the scaling
301: -  l - the level (0 is coarsest) to supply [Do not supply 0]

303:    Level: advanced

305:    Notes:
306:        When evaluating a function on a coarse level one does not want to do F(R * x) one does F(rscale * R * x) where rscale is 1 over the row sums of R.  It is preferable to use PCMGGetInjection() to control moving primal vectors.

308: .keywords: MG, set, multigrid, restriction, level

310: .seealso: PCMGSetInterpolation(), PCMGGetRestriction(), PCMGGetInjection()
311: @*/
312: PetscErrorCode PCMGGetRScale(PC pc,PetscInt l,Vec *rscale)
313: {
315:   PC_MG          *mg        = (PC_MG*)pc->data;
316:   PC_MG_Levels   **mglevels = mg->levels;

320:   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
321:   if (l <= 0 || mg->nlevels <= l) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Level %D must be in range {1,...,%D}",l,mg->nlevels-1);
322:   if (!mglevels[l]->rscale) {
323:     Mat      R;
324:     Vec      X,Y,coarse,fine;
325:     PetscInt M,N;
326:     PCMGGetRestriction(pc,l,&R);
327:     MatCreateVecs(R,&X,&Y);
328:     MatGetSize(R,&M,&N);
329:     if (M < N) {
330:       fine = X;
331:       coarse = Y;
332:     } else if (N < M) {
333:       fine = Y; coarse = X;
334:     } else SETERRQ(PetscObjectComm((PetscObject)R),PETSC_ERR_SUP,"Restriction matrix is square, cannot determine which Vec is coarser");
335:     VecSet(fine,1.);
336:     MatRestrict(R,fine,coarse);
337:     VecDestroy(&fine);
338:     VecReciprocal(coarse);
339:     mglevels[l]->rscale = coarse;
340:   }
341:   *rscale = mglevels[l]->rscale;
342:   return(0);
343: }

345: /*@
346:    PCMGSetInjection - Sets the function to be used to inject primal vectors
347:    from level l to l-1.

349:    Logically Collective on PC and Mat

351:    Input Parameters:
352: +  pc - the multigrid context
353: .  l - the level (0 is coarsest) to supply [Do not supply 0]
354: -  mat - the injection matrix

356:    Level: advanced

358: .keywords: MG, set, multigrid, restriction, injection, level

360: .seealso: PCMGSetRestriction()
361: @*/
362: PetscErrorCode  PCMGSetInjection(PC pc,PetscInt l,Mat mat)
363: {
365:   PC_MG          *mg        = (PC_MG*)pc->data;
366:   PC_MG_Levels   **mglevels = mg->levels;

371:   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
372:   if (!l) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Do not set restriction routine for coarsest level");
373:   PetscObjectReference((PetscObject)mat);
374:   MatDestroy(&mglevels[l]->inject);

376:   mglevels[l]->inject = mat;
377:   return(0);
378: }

380: /*@
381:    PCMGGetInjection - Gets the function to be used to inject primal vectors
382:    from level l to l-1.

384:    Logically Collective on PC and Mat

386:    Input Parameters:
387: +  pc - the multigrid context
388: -  l - the level (0 is coarsest) to supply [Do not supply 0]

390:    Output Parameter:
391: .  mat - the restriction matrix (may be NULL if no injection is available).

393:    Level: advanced

395: .keywords: MG, get, multigrid, restriction, injection, level

397: .seealso: PCMGSetInjection(), PCMGetGetRestriction()
398: @*/
399: PetscErrorCode  PCMGGetInjection(PC pc,PetscInt l,Mat *mat)
400: {
401:   PC_MG          *mg        = (PC_MG*)pc->data;
402:   PC_MG_Levels   **mglevels = mg->levels;

407:   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
408:   if (l <= 0 || mg->nlevels <= l) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Level %D must be in range {1,...,%D}",l,mg->nlevels-1);
409:   if (mat) *mat = mglevels[l]->inject;
410:   return(0);
411: }

413: /*@
414:    PCMGGetSmoother - Gets the KSP context to be used as smoother for
415:    both pre- and post-smoothing.  Call both PCMGGetSmootherUp() and
416:    PCMGGetSmootherDown() to use different functions for pre- and
417:    post-smoothing.

419:    Not Collective, KSP returned is parallel if PC is

421:    Input Parameters:
422: +  pc - the multigrid context
423: -  l - the level (0 is coarsest) to supply

425:    Ouput Parameters:
426: .  ksp - the smoother

428:    Notes:
429:    Once you have called this routine, you can call KSPSetOperators(ksp,...) on the resulting ksp to provide the operators for the smoother for this level.
430:    You can also modify smoother options by calling the various KSPSetXXX() options on this ksp. In addition you can call KSPGetPC(ksp,&pc)
431:    and modify PC options for the smoother; for example PCSetType(pc,PCSOR); to use SOR smoothing.

433:    Level: advanced

435: .keywords: MG, get, multigrid, level, smoother, pre-smoother, post-smoother

437: .seealso: PCMGGetSmootherUp(), PCMGGetSmootherDown()
438: @*/
439: PetscErrorCode  PCMGGetSmoother(PC pc,PetscInt l,KSP *ksp)
440: {
441:   PC_MG        *mg        = (PC_MG*)pc->data;
442:   PC_MG_Levels **mglevels = mg->levels;

446:   *ksp = mglevels[l]->smoothd;
447:   return(0);
448: }

450: /*@
451:    PCMGGetSmootherUp - Gets the KSP context to be used as smoother after
452:    coarse grid correction (post-smoother).

454:    Not Collective, KSP returned is parallel if PC is

456:    Input Parameters:
457: +  pc - the multigrid context
458: -  l  - the level (0 is coarsest) to supply

460:    Ouput Parameters:
461: .  ksp - the smoother

463:    Level: advanced

465:    Notes: calling this will result in a different pre and post smoother so you may need to
466:          set options on the pre smoother also

468: .keywords: MG, multigrid, get, smoother, up, post-smoother, level

470: .seealso: PCMGGetSmootherUp(), PCMGGetSmootherDown()
471: @*/
472: PetscErrorCode  PCMGGetSmootherUp(PC pc,PetscInt l,KSP *ksp)
473: {
474:   PC_MG          *mg        = (PC_MG*)pc->data;
475:   PC_MG_Levels   **mglevels = mg->levels;
477:   const char     *prefix;
478:   MPI_Comm       comm;

482:   /*
483:      This is called only if user wants a different pre-smoother from post.
484:      Thus we check if a different one has already been allocated,
485:      if not we allocate it.
486:   */
487:   if (!l) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"There is no such thing as a up smoother on the coarse grid");
488:   if (mglevels[l]->smoothu == mglevels[l]->smoothd) {
489:     KSPType     ksptype;
490:     PCType      pctype;
491:     PC          ipc;
492:     PetscReal   rtol,abstol,dtol;
493:     PetscInt    maxits;
494:     KSPNormType normtype;
495:     PetscObjectGetComm((PetscObject)mglevels[l]->smoothd,&comm);
496:     KSPGetOptionsPrefix(mglevels[l]->smoothd,&prefix);
497:     KSPGetTolerances(mglevels[l]->smoothd,&rtol,&abstol,&dtol,&maxits);
498:     KSPGetType(mglevels[l]->smoothd,&ksptype);
499:     KSPGetNormType(mglevels[l]->smoothd,&normtype);
500:     KSPGetPC(mglevels[l]->smoothd,&ipc);
501:     PCGetType(ipc,&pctype);

503:     KSPCreate(comm,&mglevels[l]->smoothu);
504:     KSPSetErrorIfNotConverged(mglevels[l]->smoothu,pc->erroriffailure);
505:     PetscObjectIncrementTabLevel((PetscObject)mglevels[l]->smoothu,(PetscObject)pc,mglevels[0]->levels-l);
506:     KSPSetOptionsPrefix(mglevels[l]->smoothu,prefix);
507:     KSPSetTolerances(mglevels[l]->smoothu,rtol,abstol,dtol,maxits);
508:     KSPSetType(mglevels[l]->smoothu,ksptype);
509:     KSPSetNormType(mglevels[l]->smoothu,normtype);
510:     KSPSetConvergenceTest(mglevels[l]->smoothu,KSPConvergedSkip,NULL,NULL);
511:     KSPGetPC(mglevels[l]->smoothu,&ipc);
512:     PCSetType(ipc,pctype);
513:     PetscLogObjectParent((PetscObject)pc,(PetscObject)mglevels[l]->smoothu);
514:     PetscObjectComposedDataSetInt((PetscObject) mglevels[l]->smoothu, PetscMGLevelId, mglevels[l]->level);
515:   }
516:   if (ksp) *ksp = mglevels[l]->smoothu;
517:   return(0);
518: }

520: /*@
521:    PCMGGetSmootherDown - Gets the KSP context to be used as smoother before
522:    coarse grid correction (pre-smoother).

524:    Not Collective, KSP returned is parallel if PC is

526:    Input Parameters:
527: +  pc - the multigrid context
528: -  l  - the level (0 is coarsest) to supply

530:    Ouput Parameters:
531: .  ksp - the smoother

533:    Level: advanced

535:    Notes: calling this will result in a different pre and post smoother so you may need to
536:          set options on the post smoother also

538: .keywords: MG, multigrid, get, smoother, down, pre-smoother, level

540: .seealso: PCMGGetSmootherUp(), PCMGGetSmoother()
541: @*/
542: PetscErrorCode  PCMGGetSmootherDown(PC pc,PetscInt l,KSP *ksp)
543: {
545:   PC_MG          *mg        = (PC_MG*)pc->data;
546:   PC_MG_Levels   **mglevels = mg->levels;

550:   /* make sure smoother up and down are different */
551:   if (l) {
552:     PCMGGetSmootherUp(pc,l,NULL);
553:   }
554:   *ksp = mglevels[l]->smoothd;
555:   return(0);
556: }

558: /*@
559:    PCMGSetCycleTypeOnLevel - Sets the type of cycle (aka cycle index) to run on the specified level.

561:    Logically Collective on PC

563:    Input Parameters:
564: +  pc - the multigrid context
565: .  l  - the level (0 is coarsest)
566: -  c  - either PC_MG_CYCLE_V or PC_MG_CYCLE_W

568:    Level: advanced

570: .keywords: MG, multigrid, set, cycles, V-cycle, W-cycle, level

572: .seealso: PCMGSetCycleType()
573: @*/
574: PetscErrorCode  PCMGSetCycleTypeOnLevel(PC pc,PetscInt l,PCMGCycleType c)
575: {
576:   PC_MG        *mg        = (PC_MG*)pc->data;
577:   PC_MG_Levels **mglevels = mg->levels;

581:   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
584:   mglevels[l]->cycles = c;
585:   return(0);
586: }

588: /*@
589:    PCMGSetRhs - Sets the vector space to be used to store the right-hand side
590:    on a particular level.

592:    Logically Collective on PC and Vec

594:    Input Parameters:
595: +  pc - the multigrid context
596: .  l  - the level (0 is coarsest) this is to be used for
597: -  c  - the space

599:    Level: advanced

601:    Notes: If this is not provided PETSc will automatically generate one.

603:           You do not need to keep a reference to this vector if you do
604:           not need it PCDestroy() will properly free it.

606: .keywords: MG, multigrid, set, right-hand-side, rhs, level

608: .seealso: PCMGSetX(), PCMGSetR()
609: @*/
610: PetscErrorCode  PCMGSetRhs(PC pc,PetscInt l,Vec c)
611: {
613:   PC_MG          *mg        = (PC_MG*)pc->data;
614:   PC_MG_Levels   **mglevels = mg->levels;

618:   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
619:   if (l == mglevels[0]->levels-1) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_INCOMP,"Do not set rhs for finest level");
620:   PetscObjectReference((PetscObject)c);
621:   VecDestroy(&mglevels[l]->b);

623:   mglevels[l]->b = c;
624:   return(0);
625: }

627: /*@
628:    PCMGSetX - Sets the vector space to be used to store the solution on a
629:    particular level.

631:    Logically Collective on PC and Vec

633:    Input Parameters:
634: +  pc - the multigrid context
635: .  l - the level (0 is coarsest) this is to be used for (do not supply the finest level)
636: -  c - the space

638:    Level: advanced

640:    Notes: If this is not provided PETSc will automatically generate one.

642:           You do not need to keep a reference to this vector if you do
643:           not need it PCDestroy() will properly free it.

645: .keywords: MG, multigrid, set, solution, level

647: .seealso: PCMGSetRhs(), PCMGSetR()
648: @*/
649: PetscErrorCode  PCMGSetX(PC pc,PetscInt l,Vec c)
650: {
652:   PC_MG          *mg        = (PC_MG*)pc->data;
653:   PC_MG_Levels   **mglevels = mg->levels;

657:   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
658:   if (l == mglevels[0]->levels-1) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_INCOMP,"Do not set x for finest level");
659:   PetscObjectReference((PetscObject)c);
660:   VecDestroy(&mglevels[l]->x);

662:   mglevels[l]->x = c;
663:   return(0);
664: }

666: /*@
667:    PCMGSetR - Sets the vector space to be used to store the residual on a
668:    particular level.

670:    Logically Collective on PC and Vec

672:    Input Parameters:
673: +  pc - the multigrid context
674: .  l - the level (0 is coarsest) this is to be used for
675: -  c - the space

677:    Level: advanced

679:    Notes: If this is not provided PETSc will automatically generate one.

681:           You do not need to keep a reference to this vector if you do
682:           not need it PCDestroy() will properly free it.

684: .keywords: MG, multigrid, set, residual, level
685: @*/
686: PetscErrorCode  PCMGSetR(PC pc,PetscInt l,Vec c)
687: {
689:   PC_MG          *mg        = (PC_MG*)pc->data;
690:   PC_MG_Levels   **mglevels = mg->levels;

694:   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
695:   if (!l) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Need not set residual vector for coarse grid");
696:   PetscObjectReference((PetscObject)c);
697:   VecDestroy(&mglevels[l]->r);

699:   mglevels[l]->r = c;
700:   return(0);
701: }