xref: /petsc/src/ksp/pc/impls/mg/mgfunc.c (revision cf1aed2ce99d23e50336629af3ca8cf096900abb)
1 
2 #include <../src/ksp/pc/impls/mg/mgimpl.h>       /*I "petscksp.h" I*/
3 
4 /* ---------------------------------------------------------------------------*/
5 #undef __FUNCT__
6 #define __FUNCT__ "PCMGResidualDefault"
7 /*@C
8    PCMGResidualDefault - Default routine to calculate the residual.
9 
10    Collective on Mat and Vec
11 
12    Input Parameters:
13 +  mat - the matrix
14 .  b   - the right-hand-side
15 -  x   - the approximate solution
16 
17    Output Parameter:
18 .  r - location to store the residual
19 
20    Level: developer
21 
22 .keywords: MG, default, multigrid, residual
23 
24 .seealso: PCMGSetResidual()
25 @*/
26 PetscErrorCode  PCMGResidualDefault(Mat mat,Vec b,Vec x,Vec r)
27 {
28   PetscErrorCode ierr;
29 
30   PetscFunctionBegin;
31   ierr = MatResidual(mat,b,x,r);CHKERRQ(ierr);
32   PetscFunctionReturn(0);
33 }
34 
35 #undef __FUNCT__
36 #define __FUNCT__ "PCMGGetCoarseSolve"
37 /*@
38    PCMGGetCoarseSolve - Gets the solver context to be used on the coarse grid.
39 
40    Not Collective
41 
42    Input Parameter:
43 .  pc - the multigrid context
44 
45    Output Parameter:
46 .  ksp - the coarse grid solver context
47 
48    Level: advanced
49 
50 .keywords: MG, multigrid, get, coarse grid
51 @*/
52 PetscErrorCode  PCMGGetCoarseSolve(PC pc,KSP *ksp)
53 {
54   PC_MG        *mg        = (PC_MG*)pc->data;
55   PC_MG_Levels **mglevels = mg->levels;
56 
57   PetscFunctionBegin;
58   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
59   *ksp =  mglevels[0]->smoothd;
60   PetscFunctionReturn(0);
61 }
62 
63 #undef __FUNCT__
64 #define __FUNCT__ "PCMGSetResidual"
65 /*@C
66    PCMGSetResidual - Sets the function to be used to calculate the residual
67    on the lth level.
68 
69    Logically Collective on PC and Mat
70 
71    Input Parameters:
72 +  pc       - the multigrid context
73 .  l        - the level (0 is coarsest) to supply
74 .  residual - function used to form residual, if none is provided the previously provide one is used, if no
75               previous one were provided then a default is used
76 -  mat      - matrix associated with residual
77 
78    Level: advanced
79 
80 .keywords:  MG, set, multigrid, residual, level
81 
82 .seealso: PCMGResidualDefault()
83 @*/
84 PetscErrorCode  PCMGSetResidual(PC pc,PetscInt l,PetscErrorCode (*residual)(Mat,Vec,Vec,Vec),Mat mat)
85 {
86   PC_MG          *mg        = (PC_MG*)pc->data;
87   PC_MG_Levels   **mglevels = mg->levels;
88   PetscErrorCode ierr;
89 
90   PetscFunctionBegin;
91   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
92   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
93   if (residual) mglevels[l]->residual = residual;
94   if (!mglevels[l]->residual) mglevels[l]->residual = PCMGResidualDefault;
95   if (mat) {ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr);}
96   ierr = MatDestroy(&mglevels[l]->A);CHKERRQ(ierr);
97   mglevels[l]->A = mat;
98   PetscFunctionReturn(0);
99 }
100 
101 #undef __FUNCT__
102 #define __FUNCT__ "PCMGSetInterpolation"
103 /*@
104    PCMGSetInterpolation - Sets the function to be used to calculate the
105    interpolation from l-1 to the lth level
106 
107    Logically Collective on PC and Mat
108 
109    Input Parameters:
110 +  pc  - the multigrid context
111 .  mat - the interpolation operator
112 -  l   - the level (0 is coarsest) to supply [do not supply 0]
113 
114    Level: advanced
115 
116    Notes:
117           Usually this is the same matrix used also to set the restriction
118     for the same level.
119 
120           One can pass in the interpolation matrix or its transpose; PETSc figures
121     out from the matrix size which one it is.
122 
123 .keywords:  multigrid, set, interpolate, level
124 
125 .seealso: PCMGSetRestriction()
126 @*/
127 PetscErrorCode  PCMGSetInterpolation(PC pc,PetscInt l,Mat mat)
128 {
129   PC_MG          *mg        = (PC_MG*)pc->data;
130   PC_MG_Levels   **mglevels = mg->levels;
131   PetscErrorCode ierr;
132 
133   PetscFunctionBegin;
134   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
135   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
136   if (!l) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Do not set interpolation routine for coarsest level");
137   ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr);
138   ierr = MatDestroy(&mglevels[l]->interpolate);CHKERRQ(ierr);
139 
140   mglevels[l]->interpolate = mat;
141   PetscFunctionReturn(0);
142 }
143 
144 #undef __FUNCT__
145 #define __FUNCT__ "PCMGGetInterpolation"
146 /*@
147    PCMGGetInterpolation - Gets the function to be used to calculate the
148    interpolation from l-1 to the lth level
149 
150    Logically Collective on PC
151 
152    Input Parameters:
153 +  pc - the multigrid context
154 -  l - the level (0 is coarsest) to supply [Do not supply 0]
155 
156    Output Parameter:
157 .  mat - the interpolation matrix
158 
159    Level: advanced
160 
161 .keywords: MG, get, multigrid, interpolation, level
162 
163 .seealso: PCMGGetRestriction(), PCMGSetInterpolation(), PCMGGetRScale()
164 @*/
165 PetscErrorCode  PCMGGetInterpolation(PC pc,PetscInt l,Mat *mat)
166 {
167   PC_MG          *mg        = (PC_MG*)pc->data;
168   PC_MG_Levels   **mglevels = mg->levels;
169   PetscErrorCode ierr;
170 
171   PetscFunctionBegin;
172   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
173   PetscValidPointer(mat,3);
174   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
175   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);
176   if (!mglevels[l]->interpolate) {
177     if (!mglevels[l]->restrct) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must call PCMGSetInterpolation() or PCMGSetInterpolation()");
178     ierr = PCMGSetInterpolation(pc,l,mglevels[l]->restrct);CHKERRQ(ierr);
179   }
180   *mat = mglevels[l]->interpolate;
181   PetscFunctionReturn(0);
182 }
183 
184 #undef __FUNCT__
185 #define __FUNCT__ "PCMGSetRestriction"
186 /*@
187    PCMGSetRestriction - Sets the function to be used to restrict vector
188    from level l to l-1.
189 
190    Logically Collective on PC and Mat
191 
192    Input Parameters:
193 +  pc - the multigrid context
194 .  l - the level (0 is coarsest) to supply [Do not supply 0]
195 -  mat - the restriction matrix
196 
197    Level: advanced
198 
199    Notes:
200           Usually this is the same matrix used also to set the interpolation
201     for the same level.
202 
203           One can pass in the interpolation matrix or its transpose; PETSc figures
204     out from the matrix size which one it is.
205 
206          If you do not set this, the transpose of the Mat set with PCMGSetInterpolation()
207     is used.
208 
209 .keywords: MG, set, multigrid, restriction, level
210 
211 .seealso: PCMGSetInterpolation()
212 @*/
213 PetscErrorCode  PCMGSetRestriction(PC pc,PetscInt l,Mat mat)
214 {
215   PetscErrorCode ierr;
216   PC_MG          *mg        = (PC_MG*)pc->data;
217   PC_MG_Levels   **mglevels = mg->levels;
218 
219   PetscFunctionBegin;
220   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
221   PetscValidHeaderSpecific(mat,MAT_CLASSID,3);
222   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
223   if (!l) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Do not set restriction routine for coarsest level");
224   ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr);
225   ierr = MatDestroy(&mglevels[l]->restrct);CHKERRQ(ierr);
226 
227   mglevels[l]->restrct = mat;
228   PetscFunctionReturn(0);
229 }
230 
231 #undef __FUNCT__
232 #define __FUNCT__ "PCMGGetRestriction"
233 /*@
234    PCMGGetRestriction - Gets the function to be used to restrict vector
235    from level l to l-1.
236 
237    Logically Collective on PC and Mat
238 
239    Input Parameters:
240 +  pc - the multigrid context
241 -  l - the level (0 is coarsest) to supply [Do not supply 0]
242 
243    Output Parameter:
244 .  mat - the restriction matrix
245 
246    Level: advanced
247 
248 .keywords: MG, get, multigrid, restriction, level
249 
250 .seealso: PCMGGetInterpolation(), PCMGSetRestriction(), PCMGGetRScale()
251 @*/
252 PetscErrorCode  PCMGGetRestriction(PC pc,PetscInt l,Mat *mat)
253 {
254   PC_MG          *mg        = (PC_MG*)pc->data;
255   PC_MG_Levels   **mglevels = mg->levels;
256   PetscErrorCode ierr;
257 
258   PetscFunctionBegin;
259   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
260   PetscValidPointer(mat,3);
261   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
262   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);
263   if (!mglevels[l]->restrct) {
264     if (!mglevels[l]->interpolate) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must call PCMGSetRestriction() or PCMGSetInterpolation()");
265     ierr = PCMGSetRestriction(pc,l,mglevels[l]->interpolate);CHKERRQ(ierr);
266   }
267   *mat = mglevels[l]->restrct;
268   PetscFunctionReturn(0);
269 }
270 
271 #undef __FUNCT__
272 #define __FUNCT__ "PCMGSetRScale"
273 /*@
274    PCMGSetRScale - Sets the pointwise scaling for the restriction operator from level l to l-1.
275 
276    Logically Collective on PC and Vec
277 
278    Input Parameters:
279 +  pc - the multigrid context
280 -  l - the level (0 is coarsest) to supply [Do not supply 0]
281 .  rscale - the scaling
282 
283    Level: advanced
284 
285    Notes:
286        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.
287 
288 .keywords: MG, set, multigrid, restriction, level
289 
290 .seealso: PCMGSetInterpolation(), PCMGSetRestriction(), PCMGGetRScale()
291 @*/
292 PetscErrorCode  PCMGSetRScale(PC pc,PetscInt l,Vec rscale)
293 {
294   PetscErrorCode ierr;
295   PC_MG          *mg        = (PC_MG*)pc->data;
296   PC_MG_Levels   **mglevels = mg->levels;
297 
298   PetscFunctionBegin;
299   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
300   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
301   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);
302   ierr = PetscObjectReference((PetscObject)rscale);CHKERRQ(ierr);
303   ierr = VecDestroy(&mglevels[l]->rscale);CHKERRQ(ierr);
304 
305   mglevels[l]->rscale = rscale;
306   PetscFunctionReturn(0);
307 }
308 
309 #undef __FUNCT__
310 #define __FUNCT__ "PCMGGetRScale"
311 /*@
312    PCMGGetRScale - Gets the pointwise scaling for the restriction operator from level l to l-1.
313 
314    Collective on PC
315 
316    Input Parameters:
317 +  pc - the multigrid context
318 .  rscale - the scaling
319 -  l - the level (0 is coarsest) to supply [Do not supply 0]
320 
321    Level: advanced
322 
323    Notes:
324        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.
325 
326 .keywords: MG, set, multigrid, restriction, level
327 
328 .seealso: PCMGSetInterpolation(), PCMGGetRestriction()
329 @*/
330 PetscErrorCode PCMGGetRScale(PC pc,PetscInt l,Vec *rscale)
331 {
332   PetscErrorCode ierr;
333   PC_MG          *mg        = (PC_MG*)pc->data;
334   PC_MG_Levels   **mglevels = mg->levels;
335 
336   PetscFunctionBegin;
337   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
338   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
339   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);
340   if (!mglevels[l]->rscale) {
341     Mat      R;
342     Vec      X,Y,coarse,fine;
343     PetscInt M,N;
344     ierr = PCMGGetRestriction(pc,l,&R);CHKERRQ(ierr);
345     ierr = MatGetVecs(R,&X,&Y);CHKERRQ(ierr);
346     ierr = MatGetSize(R,&M,&N);CHKERRQ(ierr);
347     if (M < N) {
348       fine = X;
349       coarse = Y;
350     } else if (N < M) {
351       fine = Y; coarse = X;
352     } else SETERRQ(PetscObjectComm((PetscObject)R),PETSC_ERR_SUP,"Restriction matrix is square, cannot determine which Vec is coarser");
353     ierr = VecSet(fine,1.);CHKERRQ(ierr);
354     ierr = MatRestrict(R,fine,coarse);CHKERRQ(ierr);
355     ierr = VecDestroy(&fine);CHKERRQ(ierr);
356     ierr = VecReciprocal(coarse);CHKERRQ(ierr);
357     mglevels[l]->rscale = coarse;
358   }
359   *rscale = mglevels[l]->rscale;
360   PetscFunctionReturn(0);
361 }
362 
363 #undef __FUNCT__
364 #define __FUNCT__ "PCMGGetSmoother"
365 /*@
366    PCMGGetSmoother - Gets the KSP context to be used as smoother for
367    both pre- and post-smoothing.  Call both PCMGGetSmootherUp() and
368    PCMGGetSmootherDown() to use different functions for pre- and
369    post-smoothing.
370 
371    Not Collective, KSP returned is parallel if PC is
372 
373    Input Parameters:
374 +  pc - the multigrid context
375 -  l - the level (0 is coarsest) to supply
376 
377    Ouput Parameters:
378 .  ksp - the smoother
379 
380    Level: advanced
381 
382 .keywords: MG, get, multigrid, level, smoother, pre-smoother, post-smoother
383 
384 .seealso: PCMGGetSmootherUp(), PCMGGetSmootherDown()
385 @*/
386 PetscErrorCode  PCMGGetSmoother(PC pc,PetscInt l,KSP *ksp)
387 {
388   PC_MG        *mg        = (PC_MG*)pc->data;
389   PC_MG_Levels **mglevels = mg->levels;
390 
391   PetscFunctionBegin;
392   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
393   *ksp = mglevels[l]->smoothd;
394   PetscFunctionReturn(0);
395 }
396 
397 #undef __FUNCT__
398 #define __FUNCT__ "PCMGGetSmootherUp"
399 /*@
400    PCMGGetSmootherUp - Gets the KSP context to be used as smoother after
401    coarse grid correction (post-smoother).
402 
403    Not Collective, KSP returned is parallel if PC is
404 
405    Input Parameters:
406 +  pc - the multigrid context
407 -  l  - the level (0 is coarsest) to supply
408 
409    Ouput Parameters:
410 .  ksp - the smoother
411 
412    Level: advanced
413 
414    Notes: calling this will result in a different pre and post smoother so you may need to
415          set options on the pre smoother also
416 
417 .keywords: MG, multigrid, get, smoother, up, post-smoother, level
418 
419 .seealso: PCMGGetSmootherUp(), PCMGGetSmootherDown()
420 @*/
421 PetscErrorCode  PCMGGetSmootherUp(PC pc,PetscInt l,KSP *ksp)
422 {
423   PC_MG          *mg        = (PC_MG*)pc->data;
424   PC_MG_Levels   **mglevels = mg->levels;
425   PetscErrorCode ierr;
426   const char     *prefix;
427   MPI_Comm       comm;
428 
429   PetscFunctionBegin;
430   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
431   /*
432      This is called only if user wants a different pre-smoother from post.
433      Thus we check if a different one has already been allocated,
434      if not we allocate it.
435   */
436   if (!l) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"There is no such thing as a up smoother on the coarse grid");
437   if (mglevels[l]->smoothu == mglevels[l]->smoothd) {
438     KSPType     ksptype;
439     PCType      pctype;
440     PC          ipc;
441     PetscReal   rtol,abstol,dtol;
442     PetscInt    maxits;
443     KSPNormType normtype;
444     ierr = PetscObjectGetComm((PetscObject)mglevels[l]->smoothd,&comm);CHKERRQ(ierr);
445     ierr = KSPGetOptionsPrefix(mglevels[l]->smoothd,&prefix);CHKERRQ(ierr);
446     ierr = KSPGetTolerances(mglevels[l]->smoothd,&rtol,&abstol,&dtol,&maxits);CHKERRQ(ierr);
447     ierr = KSPGetType(mglevels[l]->smoothd,&ksptype);CHKERRQ(ierr);
448     ierr = KSPGetNormType(mglevels[l]->smoothd,&normtype);CHKERRQ(ierr);
449     ierr = KSPGetPC(mglevels[l]->smoothd,&ipc);CHKERRQ(ierr);
450     ierr = PCGetType(ipc,&pctype);CHKERRQ(ierr);
451 
452     ierr = KSPCreate(comm,&mglevels[l]->smoothu);CHKERRQ(ierr);
453     ierr = PetscObjectIncrementTabLevel((PetscObject)mglevels[l]->smoothu,(PetscObject)pc,mglevels[0]->levels-l);CHKERRQ(ierr);
454     ierr = KSPSetOptionsPrefix(mglevels[l]->smoothu,prefix);CHKERRQ(ierr);
455     ierr = KSPSetTolerances(mglevels[l]->smoothu,rtol,abstol,dtol,maxits);CHKERRQ(ierr);
456     ierr = KSPSetType(mglevels[l]->smoothu,ksptype);CHKERRQ(ierr);
457     ierr = KSPSetNormType(mglevels[l]->smoothu,normtype);CHKERRQ(ierr);
458     ierr = KSPSetConvergenceTest(mglevels[l]->smoothu,KSPConvergedSkip,NULL,NULL);CHKERRQ(ierr);
459     ierr = KSPGetPC(mglevels[l]->smoothu,&ipc);CHKERRQ(ierr);
460     ierr = PCSetType(ipc,pctype);CHKERRQ(ierr);
461     ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)mglevels[l]->smoothu);CHKERRQ(ierr);
462   }
463   if (ksp) *ksp = mglevels[l]->smoothu;
464   PetscFunctionReturn(0);
465 }
466 
467 #undef __FUNCT__
468 #define __FUNCT__ "PCMGGetSmootherDown"
469 /*@
470    PCMGGetSmootherDown - Gets the KSP context to be used as smoother before
471    coarse grid correction (pre-smoother).
472 
473    Not Collective, KSP returned is parallel if PC is
474 
475    Input Parameters:
476 +  pc - the multigrid context
477 -  l  - the level (0 is coarsest) to supply
478 
479    Ouput Parameters:
480 .  ksp - the smoother
481 
482    Level: advanced
483 
484    Notes: calling this will result in a different pre and post smoother so you may need to
485          set options on the post smoother also
486 
487 .keywords: MG, multigrid, get, smoother, down, pre-smoother, level
488 
489 .seealso: PCMGGetSmootherUp(), PCMGGetSmoother()
490 @*/
491 PetscErrorCode  PCMGGetSmootherDown(PC pc,PetscInt l,KSP *ksp)
492 {
493   PetscErrorCode ierr;
494   PC_MG          *mg        = (PC_MG*)pc->data;
495   PC_MG_Levels   **mglevels = mg->levels;
496 
497   PetscFunctionBegin;
498   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
499   /* make sure smoother up and down are different */
500   if (l) {
501     ierr = PCMGGetSmootherUp(pc,l,NULL);CHKERRQ(ierr);
502   }
503   *ksp = mglevels[l]->smoothd;
504   PetscFunctionReturn(0);
505 }
506 
507 #undef __FUNCT__
508 #define __FUNCT__ "PCMGSetCyclesOnLevel"
509 /*@
510    PCMGSetCyclesOnLevel - Sets the number of cycles to run on this level.
511 
512    Logically Collective on PC
513 
514    Input Parameters:
515 +  pc - the multigrid context
516 .  l  - the level (0 is coarsest) this is to be used for
517 -  n  - the number of cycles
518 
519    Level: advanced
520 
521 .keywords: MG, multigrid, set, cycles, V-cycle, W-cycle, level
522 
523 .seealso: PCMGSetCycles()
524 @*/
525 PetscErrorCode  PCMGSetCyclesOnLevel(PC pc,PetscInt l,PetscInt c)
526 {
527   PC_MG        *mg        = (PC_MG*)pc->data;
528   PC_MG_Levels **mglevels = mg->levels;
529 
530   PetscFunctionBegin;
531   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
532   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
533   PetscValidLogicalCollectiveInt(pc,l,2);
534   PetscValidLogicalCollectiveInt(pc,c,3);
535   mglevels[l]->cycles = c;
536   PetscFunctionReturn(0);
537 }
538 
539 #undef __FUNCT__
540 #define __FUNCT__ "PCMGSetRhs"
541 /*@
542    PCMGSetRhs - Sets the vector space to be used to store the right-hand side
543    on a particular level.
544 
545    Logically Collective on PC and Vec
546 
547    Input Parameters:
548 +  pc - the multigrid context
549 .  l  - the level (0 is coarsest) this is to be used for
550 -  c  - the space
551 
552    Level: advanced
553 
554    Notes: If this is not provided PETSc will automatically generate one.
555 
556           You do not need to keep a reference to this vector if you do
557           not need it PCDestroy() will properly free it.
558 
559 .keywords: MG, multigrid, set, right-hand-side, rhs, level
560 
561 .seealso: PCMGSetX(), PCMGSetR()
562 @*/
563 PetscErrorCode  PCMGSetRhs(PC pc,PetscInt l,Vec c)
564 {
565   PetscErrorCode ierr;
566   PC_MG          *mg        = (PC_MG*)pc->data;
567   PC_MG_Levels   **mglevels = mg->levels;
568 
569   PetscFunctionBegin;
570   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
571   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
572   if (l == mglevels[0]->levels-1) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_INCOMP,"Do not set rhs for finest level");
573   ierr = PetscObjectReference((PetscObject)c);CHKERRQ(ierr);
574   ierr = VecDestroy(&mglevels[l]->b);CHKERRQ(ierr);
575 
576   mglevels[l]->b = c;
577   PetscFunctionReturn(0);
578 }
579 
580 #undef __FUNCT__
581 #define __FUNCT__ "PCMGSetX"
582 /*@
583    PCMGSetX - Sets the vector space to be used to store the solution on a
584    particular level.
585 
586    Logically Collective on PC and Vec
587 
588    Input Parameters:
589 +  pc - the multigrid context
590 .  l - the level (0 is coarsest) this is to be used for (do not supply the finest level)
591 -  c - the space
592 
593    Level: advanced
594 
595    Notes: If this is not provided PETSc will automatically generate one.
596 
597           You do not need to keep a reference to this vector if you do
598           not need it PCDestroy() will properly free it.
599 
600 .keywords: MG, multigrid, set, solution, level
601 
602 .seealso: PCMGSetRhs(), PCMGSetR()
603 @*/
604 PetscErrorCode  PCMGSetX(PC pc,PetscInt l,Vec c)
605 {
606   PetscErrorCode ierr;
607   PC_MG          *mg        = (PC_MG*)pc->data;
608   PC_MG_Levels   **mglevels = mg->levels;
609 
610   PetscFunctionBegin;
611   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
612   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
613   if (l == mglevels[0]->levels-1) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_INCOMP,"Do not set x for finest level");
614   ierr = PetscObjectReference((PetscObject)c);CHKERRQ(ierr);
615   ierr = VecDestroy(&mglevels[l]->x);CHKERRQ(ierr);
616 
617   mglevels[l]->x = c;
618   PetscFunctionReturn(0);
619 }
620 
621 #undef __FUNCT__
622 #define __FUNCT__ "PCMGSetR"
623 /*@
624    PCMGSetR - Sets the vector space to be used to store the residual on a
625    particular level.
626 
627    Logically Collective on PC and Vec
628 
629    Input Parameters:
630 +  pc - the multigrid context
631 .  l - the level (0 is coarsest) this is to be used for
632 -  c - the space
633 
634    Level: advanced
635 
636    Notes: If this is not provided PETSc will automatically generate one.
637 
638           You do not need to keep a reference to this vector if you do
639           not need it PCDestroy() will properly free it.
640 
641 .keywords: MG, multigrid, set, residual, level
642 @*/
643 PetscErrorCode  PCMGSetR(PC pc,PetscInt l,Vec c)
644 {
645   PetscErrorCode ierr;
646   PC_MG          *mg        = (PC_MG*)pc->data;
647   PC_MG_Levels   **mglevels = mg->levels;
648 
649   PetscFunctionBegin;
650   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
651   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
652   if (!l) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Need not set residual vector for coarse grid");
653   ierr = PetscObjectReference((PetscObject)c);CHKERRQ(ierr);
654   ierr = VecDestroy(&mglevels[l]->r);CHKERRQ(ierr);
655 
656   mglevels[l]->r = c;
657   PetscFunctionReturn(0);
658 }
659