Actual source code: mgfunc.c
2: #include <../src/ksp/pc/impls/mg/mgimpl.h> /*I "petscksp.h" I*/
3: /*I "petscpcmg.h" I*/
7: /*@C
8: PCMGDefaultResidual - Default routine to calculate the residual.
10: Collective on Mat and Vec
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
20: Level: advanced
22: .keywords: MG, default, multigrid, residual
24: .seealso: PCMGSetResidual()
25: @*/
26: PetscErrorCode PCMGDefaultResidual(Mat mat,Vec b,Vec x,Vec r)
27: {
31: MatMult(mat,x,r);
32: VecAYPX(r,-1.0,b);
33: return(0);
34: }
36: /* ---------------------------------------------------------------------------*/
40: /*@
41: PCMGGetCoarseSolve - Gets the solver context to be used on the coarse grid.
43: Not Collective
45: Input Parameter:
46: . pc - the multigrid context
48: Output Parameter:
49: . ksp - the coarse grid solver context
51: Level: advanced
53: .keywords: MG, multigrid, get, coarse grid
54: @*/
55: PetscErrorCode PCMGGetCoarseSolve(PC pc,KSP *ksp)
56: {
57: PC_MG *mg = (PC_MG*)pc->data;
58: PC_MG_Levels **mglevels = mg->levels;
62: *ksp = mglevels[0]->smoothd;
63: return(0);
64: }
68: /*@C
69: PCMGSetResidual - Sets the function to be used to calculate the residual
70: on the lth level.
72: Logically Collective on PC and Mat
74: Input Parameters:
75: + pc - the multigrid context
76: . l - the level (0 is coarsest) to supply
77: . residual - function used to form residual, if none is provided the previously provide one is used, if no
78: previous one were provided then PCMGDefaultResidual() is used
79: - mat - matrix associated with residual
81: Level: advanced
83: .keywords: MG, set, multigrid, residual, level
85: .seealso: PCMGDefaultResidual()
86: @*/
87: PetscErrorCode PCMGSetResidual(PC pc,PetscInt l,PetscErrorCode (*residual)(Mat,Vec,Vec,Vec),Mat mat)
88: {
89: PC_MG *mg = (PC_MG*)pc->data;
90: PC_MG_Levels **mglevels = mg->levels;
95: if (!mglevels) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
96: if (residual) {
97: mglevels[l]->residual = residual;
98: } if (!mglevels[l]->residual) {
99: mglevels[l]->residual = PCMGDefaultResidual;
100: }
101: if (mat) {PetscObjectReference((PetscObject)mat);}
102: MatDestroy(&mglevels[l]->A);
103: mglevels[l]->A = mat;
104: return(0);
105: }
109: /*@
110: PCMGSetInterpolation - Sets the function to be used to calculate the
111: interpolation from l-1 to the lth level
113: Logically Collective on PC and Mat
115: Input Parameters:
116: + pc - the multigrid context
117: . mat - the interpolation operator
118: - l - the level (0 is coarsest) to supply [do not supply 0]
120: Level: advanced
122: Notes:
123: Usually this is the same matrix used also to set the restriction
124: for the same level.
126: One can pass in the interpolation matrix or its transpose; PETSc figures
127: out from the matrix size which one it is.
129: .keywords: multigrid, set, interpolate, level
131: .seealso: PCMGSetRestriction()
132: @*/
133: PetscErrorCode PCMGSetInterpolation(PC pc,PetscInt l,Mat mat)
134: {
135: PC_MG *mg = (PC_MG*)pc->data;
136: PC_MG_Levels **mglevels = mg->levels;
141: if (!mglevels) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
142: if (!l) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Do not set interpolation routine for coarsest level");
143: PetscObjectReference((PetscObject)mat);
144: MatDestroy(&mglevels[l]->interpolate);
145: mglevels[l]->interpolate = mat;
146: return(0);
147: }
151: /*@
152: PCMGSetRestriction - Sets the function to be used to restrict vector
153: from level l to l-1.
155: Logically Collective on PC and Mat
157: Input Parameters:
158: + pc - the multigrid context
159: . mat - the restriction matrix
160: - l - the level (0 is coarsest) to supply [Do not supply 0]
162: Level: advanced
164: Notes:
165: Usually this is the same matrix used also to set the interpolation
166: for the same level.
168: One can pass in the interpolation matrix or its transpose; PETSc figures
169: out from the matrix size which one it is.
171: If you do not set this, the transpose of the Mat set with PCMGSetInterpolation()
172: is used.
174: .keywords: MG, set, multigrid, restriction, level
176: .seealso: PCMGSetInterpolation()
177: @*/
178: PetscErrorCode PCMGSetRestriction(PC pc,PetscInt l,Mat mat)
179: {
181: PC_MG *mg = (PC_MG*)pc->data;
182: PC_MG_Levels **mglevels = mg->levels;
186: if (!mglevels) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
187: if (!l) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Do not set restriction routine for coarsest level");
188: PetscObjectReference((PetscObject)mat);
189: MatDestroy(&mglevels[l]->restrct);
190: mglevels[l]->restrct = mat;
191: return(0);
192: }
196: /*@
197: PCMGSetRScale - Sets the pointwise scaling for the restriction operator from level l to l-1.
199: Logically Collective on PC and Mat
201: Input Parameters:
202: + pc - the multigrid context
203: . rscale - the scaling
204: - l - the level (0 is coarsest) to supply [Do not supply 0]
206: Level: advanced
208: Notes:
209: 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.
211: .keywords: MG, set, multigrid, restriction, level
213: .seealso: PCMGSetInterpolation(), PCMGSetRestriction()
214: @*/
215: PetscErrorCode PCMGSetRScale(PC pc,PetscInt l,Vec rscale)
216: {
218: PC_MG *mg = (PC_MG*)pc->data;
219: PC_MG_Levels **mglevels = mg->levels;
223: if (!mglevels) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
224: if (!l) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Do not set restriction routine for coarsest level");
225: PetscObjectReference((PetscObject)rscale);
226: VecDestroy(&mglevels[l]->rscale);
227: mglevels[l]->rscale = rscale;
228: return(0);
229: }
233: /*@
234: PCMGGetSmoother - Gets the KSP context to be used as smoother for
235: both pre- and post-smoothing. Call both PCMGGetSmootherUp() and
236: PCMGGetSmootherDown() to use different functions for pre- and
237: post-smoothing.
239: Not Collective, KSP returned is parallel if PC is
241: Input Parameters:
242: + pc - the multigrid context
243: - l - the level (0 is coarsest) to supply
245: Ouput Parameters:
246: . ksp - the smoother
248: Level: advanced
250: .keywords: MG, get, multigrid, level, smoother, pre-smoother, post-smoother
252: .seealso: PCMGGetSmootherUp(), PCMGGetSmootherDown()
253: @*/
254: PetscErrorCode PCMGGetSmoother(PC pc,PetscInt l,KSP *ksp)
255: {
256: PC_MG *mg = (PC_MG*)pc->data;
257: PC_MG_Levels **mglevels = mg->levels;
261: *ksp = mglevels[l]->smoothd;
262: return(0);
263: }
267: /*@
268: PCMGGetSmootherUp - Gets the KSP context to be used as smoother after
269: coarse grid correction (post-smoother).
271: Not Collective, KSP returned is parallel if PC is
273: Input Parameters:
274: + pc - the multigrid context
275: - l - the level (0 is coarsest) to supply
277: Ouput Parameters:
278: . ksp - the smoother
280: Level: advanced
282: Notes: calling this will result in a different pre and post smoother so you may need to
283: set options on the pre smoother also
285: .keywords: MG, multigrid, get, smoother, up, post-smoother, level
287: .seealso: PCMGGetSmootherUp(), PCMGGetSmootherDown()
288: @*/
289: PetscErrorCode PCMGGetSmootherUp(PC pc,PetscInt l,KSP *ksp)
290: {
291: PC_MG *mg = (PC_MG*)pc->data;
292: PC_MG_Levels **mglevels = mg->levels;
294: const char *prefix;
295: MPI_Comm comm;
299: /*
300: This is called only if user wants a different pre-smoother from post.
301: Thus we check if a different one has already been allocated,
302: if not we allocate it.
303: */
304: if (!l) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ARG_OUTOFRANGE,"There is no such thing as a up smoother on the coarse grid");
305: if (mglevels[l]->smoothu == mglevels[l]->smoothd) {
306: PetscObjectGetComm((PetscObject)mglevels[l]->smoothd,&comm);
307: KSPGetOptionsPrefix(mglevels[l]->smoothd,&prefix);
308: KSPCreate(comm,&mglevels[l]->smoothu);
309: PetscObjectIncrementTabLevel((PetscObject)mglevels[l]->smoothu,(PetscObject)pc,mglevels[0]->levels-l);
310: KSPSetTolerances(mglevels[l]->smoothu,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);
311: KSPSetOptionsPrefix(mglevels[l]->smoothu,prefix);
312: PetscLogObjectParent(pc,mglevels[l]->smoothu);
313: }
314: if (ksp) *ksp = mglevels[l]->smoothu;
315: return(0);
316: }
320: /*@
321: PCMGGetSmootherDown - Gets the KSP context to be used as smoother before
322: coarse grid correction (pre-smoother).
324: Not Collective, KSP returned is parallel if PC is
326: Input Parameters:
327: + pc - the multigrid context
328: - l - the level (0 is coarsest) to supply
330: Ouput Parameters:
331: . ksp - the smoother
333: Level: advanced
335: Notes: calling this will result in a different pre and post smoother so you may need to
336: set options on the post smoother also
338: .keywords: MG, multigrid, get, smoother, down, pre-smoother, level
340: .seealso: PCMGGetSmootherUp(), PCMGGetSmoother()
341: @*/
342: PetscErrorCode PCMGGetSmootherDown(PC pc,PetscInt l,KSP *ksp)
343: {
345: PC_MG *mg = (PC_MG*)pc->data;
346: PC_MG_Levels **mglevels = mg->levels;
350: /* make sure smoother up and down are different */
351: if (l) {
352: PCMGGetSmootherUp(pc,l,PETSC_NULL);
353: }
354: *ksp = mglevels[l]->smoothd;
355: return(0);
356: }
360: /*@
361: PCMGSetCyclesOnLevel - Sets the number of cycles to run on this level.
363: Logically Collective on PC
365: Input Parameters:
366: + pc - the multigrid context
367: . l - the level (0 is coarsest) this is to be used for
368: - n - the number of cycles
370: Level: advanced
372: .keywords: MG, multigrid, set, cycles, V-cycle, W-cycle, level
374: .seealso: PCMGSetCycles()
375: @*/
376: PetscErrorCode PCMGSetCyclesOnLevel(PC pc,PetscInt l,PetscInt c)
377: {
378: PC_MG *mg = (PC_MG*)pc->data;
379: PC_MG_Levels **mglevels = mg->levels;
383: if (!mglevels) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
386: mglevels[l]->cycles = c;
387: return(0);
388: }
392: /*@
393: PCMGSetRhs - Sets the vector space to be used to store the right-hand side
394: on a particular level.
396: Logically Collective on PC and Vec
398: Input Parameters:
399: + pc - the multigrid context
400: . l - the level (0 is coarsest) this is to be used for
401: - c - the space
403: Level: advanced
405: Notes: If this is not provided PETSc will automatically generate one.
407: You do not need to keep a reference to this vector if you do
408: not need it PCDestroy() will properly free it.
410: .keywords: MG, multigrid, set, right-hand-side, rhs, level
412: .seealso: PCMGSetX(), PCMGSetR()
413: @*/
414: PetscErrorCode PCMGSetRhs(PC pc,PetscInt l,Vec c)
415: {
417: PC_MG *mg = (PC_MG*)pc->data;
418: PC_MG_Levels **mglevels = mg->levels;
422: if (!mglevels) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
423: if (l == mglevels[0]->levels-1) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ARG_INCOMP,"Do not set rhs for finest level");
424: PetscObjectReference((PetscObject)c);
425: VecDestroy(&mglevels[l]->b);
426: mglevels[l]->b = c;
427: return(0);
428: }
432: /*@
433: PCMGSetX - Sets the vector space to be used to store the solution on a
434: particular level.
436: Logically Collective on PC and Vec
438: Input Parameters:
439: + pc - the multigrid context
440: . l - the level (0 is coarsest) this is to be used for
441: - c - the space
443: Level: advanced
445: Notes: If this is not provided PETSc will automatically generate one.
447: You do not need to keep a reference to this vector if you do
448: not need it PCDestroy() will properly free it.
450: .keywords: MG, multigrid, set, solution, level
452: .seealso: PCMGSetRhs(), PCMGSetR()
453: @*/
454: PetscErrorCode PCMGSetX(PC pc,PetscInt l,Vec c)
455: {
457: PC_MG *mg = (PC_MG*)pc->data;
458: PC_MG_Levels **mglevels = mg->levels;
462: if (!mglevels) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
463: if (l == mglevels[0]->levels-1) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ARG_INCOMP,"Do not set x for finest level");
464: PetscObjectReference((PetscObject)c);
465: VecDestroy(&mglevels[l]->x);
466: mglevels[l]->x = c;
467: return(0);
468: }
472: /*@
473: PCMGSetR - Sets the vector space to be used to store the residual on a
474: particular level.
476: Logically Collective on PC and Vec
478: Input Parameters:
479: + pc - the multigrid context
480: . l - the level (0 is coarsest) this is to be used for
481: - c - the space
483: Level: advanced
485: Notes: If this is not provided PETSc will automatically generate one.
487: You do not need to keep a reference to this vector if you do
488: not need it PCDestroy() will properly free it.
490: .keywords: MG, multigrid, set, residual, level
491: @*/
492: PetscErrorCode PCMGSetR(PC pc,PetscInt l,Vec c)
493: {
495: PC_MG *mg = (PC_MG*)pc->data;
496: PC_MG_Levels **mglevels = mg->levels;
500: if (!mglevels) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
501: if (!l) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Need not set residual vector for coarse grid");
502: PetscObjectReference((PetscObject)c);
503: VecDestroy(&mglevels[l]->r);
504: mglevels[l]->r = c;
505: return(0);
506: }