Actual source code: mgfunc.c

petsc-3.10.5 2019-03-28
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

 48: .seealso: PCMGGetSmootherUp(), PCMGGetSmootherDown(), PCMGGetSmoother()
 49: @*/
 50: PetscErrorCode  PCMGGetCoarseSolve(PC pc,KSP *ksp)
 51: {
 52:   PC_MG        *mg        = (PC_MG*)pc->data;
 53:   PC_MG_Levels **mglevels = mg->levels;

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

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

 65:    Logically Collective on PC and Mat

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

 74:    Level: advanced

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

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

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

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

101:    Logically Collective on PC and Mat

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

108:    Level: advanced

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

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

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

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

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

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

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

142:    Logically Collective on PC

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

148:    Output Parameter:
149: .  mat - the interpolation matrix, can be NULL

151:    Level: advanced

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

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

166:   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
167:   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);
168:   if (!mglevels[l]->interpolate) {
169:     if (!mglevels[l]->restrct) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must call PCMGSetInterpolation() or PCMGSetRestriction()");
170:     PCMGSetInterpolation(pc,l,mglevels[l]->restrct);
171:   }
172:   if (mat) *mat = mglevels[l]->interpolate;
173:   return(0);
174: }

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

180:    Logically Collective on PC and Mat

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

187:    Level: advanced

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

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

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

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

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

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

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

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

225:    Logically Collective on PC and Mat

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

231:    Output Parameter:
232: .  mat - the restriction matrix

234:    Level: advanced

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

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

249:   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
250:   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);
251:   if (!mglevels[l]->restrct) {
252:     if (!mglevels[l]->interpolate) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must call PCMGSetRestriction() or PCMGSetInterpolation()");
253:     PCMGSetRestriction(pc,l,mglevels[l]->interpolate);
254:   }
255:   if (mat) *mat = mglevels[l]->restrct;
256:   return(0);
257: }

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

262:    Logically Collective on PC and Vec

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

269:    Level: advanced

271:    Notes:
272:        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.

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

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

286:   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
287:   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);
288:   PetscObjectReference((PetscObject)rscale);
289:   VecDestroy(&mglevels[l]->rscale);

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

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

298:    Collective on PC

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

305:    Level: advanced

307:    Notes:
308:        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.

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

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

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

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

351:    Logically Collective on PC and Mat

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

358:    Level: advanced

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

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

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

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

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

386:    Logically Collective on PC and Mat

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

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

395:    Level: advanced

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

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

409:   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
410:   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);
411:   if (mat) *mat = mglevels[l]->inject;
412:   return(0);
413: }

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

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

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

427:    Ouput Parameters:
428: .  ksp - the smoother

430:    Notes:
431:    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.
432:    You can also modify smoother options by calling the various KSPSetXXX() options on this ksp. In addition you can call KSPGetPC(ksp,&pc)
433:    and modify PC options for the smoother; for example PCSetType(pc,PCSOR); to use SOR smoothing.

435:    Level: advanced

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

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

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

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

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

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

462:    Ouput Parameters:
463: .  ksp - the smoother

465:    Level: advanced

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

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

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

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

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

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

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

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

533:    Ouput Parameters:
534: .  ksp - the smoother

536:    Level: advanced

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

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

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

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

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

565:    Logically Collective on PC

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

572:    Level: advanced

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

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

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

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

596:    Logically Collective on PC and Vec

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

603:    Level: advanced

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

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

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

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

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

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

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

636:    Logically Collective on PC and Vec

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

643:    Level: advanced

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

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

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

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

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

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

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

676:    Logically Collective on PC and Vec

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

683:    Level: advanced

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

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

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

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

706:   mglevels[l]->r = c;
707:   return(0);
708: }