Actual source code: mgfunc.c

petsc-master 2018-06-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

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

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]

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

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

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

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

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]

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

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).

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.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

563:    Logically Collective on PC

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

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

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

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

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

594:    Logically Collective on PC and Vec

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

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

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

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

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

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

626:   mglevels[l]->b = c;
627:   return(0);
628: }

630: /*@
631:    PCMGSetX - Sets the vector space to be used to store the solution on a
632:    particular level.

634:    Logically Collective on PC and Vec

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

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

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

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

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

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

666:   mglevels[l]->x = c;
667:   return(0);
668: }

670: /*@
671:    PCMGSetR - Sets the vector space to be used to store the residual on a
672:    particular level.

674:    Logically Collective on PC and Vec

676:    Input Parameters:
677: +  pc - the multigrid context
678: .  l - the level (0 is coarsest) this is to be used for
679: -  c - the space

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

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

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

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

704:   mglevels[l]->r = c;
705:   return(0);
706: }
```