Actual source code: mgfunc.c
petsc-3.9.4 2018-09-11
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: }