Actual source code: mgfunc.c
1: #define PETSCKSP_DLL
3: #include ../src/ksp/pc/impls/mg/mgimpl.h
4: /*I "petscmg.h" I*/
8: /*@C
9: PCMGDefaultResidual - Default routine to calculate the residual.
11: Collective on Mat and Vec
13: Input Parameters:
14: + mat - the matrix
15: . b - the right-hand-side
16: - x - the approximate solution
17:
18: Output Parameter:
19: . r - location to store the residual
21: Level: advanced
23: .keywords: MG, default, multigrid, residual
25: .seealso: PCMGSetResidual()
26: @*/
27: PetscErrorCode PCMGDefaultResidual(Mat mat,Vec b,Vec x,Vec r)
28: {
32: MatMult(mat,x,r);
33: VecAYPX(r,-1.0,b);
34: return(0);
35: }
37: /* ---------------------------------------------------------------------------*/
41: /*@
42: PCMGGetCoarseSolve - Gets the solver context to be used on the coarse grid.
44: Not Collective
46: Input Parameter:
47: . pc - the multigrid context
49: Output Parameter:
50: . ksp - the coarse grid solver context
52: Level: advanced
54: .keywords: MG, multigrid, get, coarse grid
55: @*/
56: PetscErrorCode PCMGGetCoarseSolve(PC pc,KSP *ksp)
57: {
58: PC_MG *mg = (PC_MG*)pc->data;
59: 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: 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 (usually PCMGDefaultResidual)
78: - mat - matrix associated with residual
80: Level: advanced
82: .keywords: MG, set, multigrid, residual, level
84: .seealso: PCMGDefaultResidual()
85: @*/
86: PetscErrorCode PCMGSetResidual(PC pc,PetscInt l,PetscErrorCode (*residual)(Mat,Vec,Vec,Vec),Mat mat)
87: {
88: PC_MG *mg = (PC_MG*)pc->data;
89: PC_MG_Levels **mglevels = mg->levels;
92: if (!mglevels) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
94: mglevels[l]->residual = residual;
95: mglevels[l]->A = mat;
96: return(0);
97: }
101: /*@
102: PCMGSetInterpolation - Sets the function to be used to calculate the
103: interpolation from l-1 to the lth level
105: Collective on PC and Mat
107: Input Parameters:
108: + pc - the multigrid context
109: . mat - the interpolation operator
110: - l - the level (0 is coarsest) to supply [do not supply 0]
112: Level: advanced
114: Notes:
115: Usually this is the same matrix used also to set the restriction
116: for the same level.
118: One can pass in the interpolation matrix or its transpose; PETSc figures
119: out from the matrix size which one it is.
121: .keywords: multigrid, set, interpolate, level
123: .seealso: PCMGSetRestriction()
124: @*/
125: PetscErrorCode PCMGSetInterpolation(PC pc,PetscInt l,Mat mat)
126: {
127: PC_MG *mg = (PC_MG*)pc->data;
128: PC_MG_Levels **mglevels = mg->levels;
132: if (!mglevels) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
133: if (!l) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Do not set interpolation routine for coarsest level");
134: PetscObjectReference((PetscObject)mat);
135: if (mglevels[l]->interpolate) {MatDestroy(mglevels[l]->interpolate);}
136: mglevels[l]->interpolate = mat;
137: return(0);
138: }
142: /*@
143: PCMGSetRestriction - Sets the function to be used to restrict vector
144: from level l to l-1.
146: Collective on PC and Mat
148: Input Parameters:
149: + pc - the multigrid context
150: . mat - the restriction matrix
151: - l - the level (0 is coarsest) to supply [Do not supply 0]
153: Level: advanced
155: Notes:
156: Usually this is the same matrix used also to set the interpolation
157: for the same level.
159: One can pass in the interpolation matrix or its transpose; PETSc figures
160: out from the matrix size which one it is.
162: If you do not set this, the transpose of the Mat set with PCMGSetInterpolation()
163: is used.
165: .keywords: MG, set, multigrid, restriction, level
167: .seealso: PCMGSetInterpolation()
168: @*/
169: PetscErrorCode PCMGSetRestriction(PC pc,PetscInt l,Mat mat)
170: {
172: PC_MG *mg = (PC_MG*)pc->data;
173: PC_MG_Levels **mglevels = mg->levels;
176: if (!mglevels) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
177: if (!l) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Do not set restriction routine for coarsest level");
178: PetscObjectReference((PetscObject)mat);
179: if (mglevels[l]->restrct) {MatDestroy(mglevels[l]->restrct);}
180: mglevels[l]->restrct = mat;
181: return(0);
182: }
186: /*@
187: PCMGGetSmoother - Gets the KSP context to be used as smoother for
188: both pre- and post-smoothing. Call both PCMGGetSmootherUp() and
189: PCMGGetSmootherDown() to use different functions for pre- and
190: post-smoothing.
192: Not Collective, KSP returned is parallel if PC is
194: Input Parameters:
195: + pc - the multigrid context
196: - l - the level (0 is coarsest) to supply
198: Ouput Parameters:
199: . ksp - the smoother
201: Level: advanced
203: .keywords: MG, get, multigrid, level, smoother, pre-smoother, post-smoother
205: .seealso: PCMGGetSmootherUp(), PCMGGetSmootherDown()
206: @*/
207: PetscErrorCode PCMGGetSmoother(PC pc,PetscInt l,KSP *ksp)
208: {
209: PC_MG *mg = (PC_MG*)pc->data;
210: PC_MG_Levels **mglevels = mg->levels;
213: *ksp = mglevels[l]->smoothd;
214: return(0);
215: }
219: /*@
220: PCMGGetSmootherUp - Gets the KSP context to be used as smoother after
221: coarse grid correction (post-smoother).
223: Not Collective, KSP returned is parallel if PC is
225: Input Parameters:
226: + pc - the multigrid context
227: - l - the level (0 is coarsest) to supply
229: Ouput Parameters:
230: . ksp - the smoother
232: Level: advanced
234: .keywords: MG, multigrid, get, smoother, up, post-smoother, level
236: .seealso: PCMGGetSmootherUp(), PCMGGetSmootherDown()
237: @*/
238: PetscErrorCode PCMGGetSmootherUp(PC pc,PetscInt l,KSP *ksp)
239: {
240: PC_MG *mg = (PC_MG*)pc->data;
241: PC_MG_Levels **mglevels = mg->levels;
243: const char *prefix;
244: MPI_Comm comm;
247: /*
248: This is called only if user wants a different pre-smoother from post.
249: Thus we check if a different one has already been allocated,
250: if not we allocate it.
251: */
252: if (!l) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"There is no such thing as a up smoother on the coarse grid");
253: if (mglevels[l]->smoothu == mglevels[l]->smoothd) {
254: PetscObjectGetComm((PetscObject)mglevels[l]->smoothd,&comm);
255: KSPGetOptionsPrefix(mglevels[l]->smoothd,&prefix);
256: KSPCreate(comm,&mglevels[l]->smoothu);
257: PetscObjectIncrementTabLevel((PetscObject)mglevels[l]->smoothu,(PetscObject)pc,mglevels[0]->levels-l);
258: KSPSetTolerances(mglevels[l]->smoothu,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);
259: KSPSetOptionsPrefix(mglevels[l]->smoothu,prefix);
260: PetscLogObjectParent(pc,mglevels[l]->smoothu);
261: }
262: if (ksp) *ksp = mglevels[l]->smoothu;
263: return(0);
264: }
268: /*@
269: PCMGGetSmootherDown - Gets the KSP context to be used as smoother before
270: coarse grid correction (pre-smoother).
272: Not Collective, KSP returned is parallel if PC is
274: Input Parameters:
275: + pc - the multigrid context
276: - l - the level (0 is coarsest) to supply
278: Ouput Parameters:
279: . ksp - the smoother
281: Level: advanced
283: .keywords: MG, multigrid, get, smoother, down, pre-smoother, level
285: .seealso: PCMGGetSmootherUp(), PCMGGetSmoother()
286: @*/
287: PetscErrorCode PCMGGetSmootherDown(PC pc,PetscInt l,KSP *ksp)
288: {
290: PC_MG *mg = (PC_MG*)pc->data;
291: PC_MG_Levels **mglevels = mg->levels;
294: /* make sure smoother up and down are different */
295: if (l != 0) {
296: PCMGGetSmootherUp(pc,l,PETSC_NULL);
297: }
298: *ksp = mglevels[l]->smoothd;
299: return(0);
300: }
304: /*@
305: PCMGSetCyclesOnLevel - Sets the number of cycles to run on this level.
307: Collective on PC
309: Input Parameters:
310: + pc - the multigrid context
311: . l - the level (0 is coarsest) this is to be used for
312: - n - the number of cycles
314: Level: advanced
316: .keywords: MG, multigrid, set, cycles, V-cycle, W-cycle, level
318: .seealso: PCMGSetCycles()
319: @*/
320: PetscErrorCode PCMGSetCyclesOnLevel(PC pc,PetscInt l,PetscInt c)
321: {
322: PC_MG *mg = (PC_MG*)pc->data;
323: PC_MG_Levels **mglevels = mg->levels;
326: if (!mglevels) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
327: mglevels[l]->cycles = c;
328: return(0);
329: }
333: /*@
334: PCMGSetRhs - Sets the vector space to be used to store the right-hand side
335: on a particular level.
337: Collective on PC and Vec
339: Input Parameters:
340: + pc - the multigrid context
341: . l - the level (0 is coarsest) this is to be used for
342: - c - the space
344: Level: advanced
346: Notes: If this is not provided PETSc will automatically generate one.
348: You do not need to keep a reference to this vector if you do
349: not need it PCDestroy() will properly free it.
351: .keywords: MG, multigrid, set, right-hand-side, rhs, level
353: .seealso: PCMGSetX(), PCMGSetR()
354: @*/
355: PetscErrorCode PCMGSetRhs(PC pc,PetscInt l,Vec c)
356: {
358: PC_MG *mg = (PC_MG*)pc->data;
359: PC_MG_Levels **mglevels = mg->levels;
362: if (!mglevels) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
363: if (l == mglevels[0]->levels-1) SETERRQ(PETSC_ERR_ARG_INCOMP,"Do not set rhs for finest level");
364: PetscObjectReference((PetscObject)c);
365: if (mglevels[l]->b) {VecDestroy(mglevels[l]->b);}
366: mglevels[l]->b = c;
367: return(0);
368: }
372: /*@
373: PCMGSetX - Sets the vector space to be used to store the solution on a
374: particular level.
376: Collective on PC and Vec
378: Input Parameters:
379: + pc - the multigrid context
380: . l - the level (0 is coarsest) this is to be used for
381: - c - the space
383: Level: advanced
385: Notes: If this is not provided PETSc will automatically generate one.
387: You do not need to keep a reference to this vector if you do
388: not need it PCDestroy() will properly free it.
390: .keywords: MG, multigrid, set, solution, level
392: .seealso: PCMGSetRhs(), PCMGSetR()
393: @*/
394: PetscErrorCode PCMGSetX(PC pc,PetscInt l,Vec c)
395: {
397: PC_MG *mg = (PC_MG*)pc->data;
398: PC_MG_Levels **mglevels = mg->levels;
401: if (!mglevels) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
402: if (l == mglevels[0]->levels-1) SETERRQ(PETSC_ERR_ARG_INCOMP,"Do not set rhs for finest level");
403: PetscObjectReference((PetscObject)c);
404: if (mglevels[l]->x) {VecDestroy(mglevels[l]->x);}
405: mglevels[l]->x = c;
406: return(0);
407: }
411: /*@
412: PCMGSetR - Sets the vector space to be used to store the residual on a
413: particular level.
415: Collective on PC and Vec
417: Input Parameters:
418: + pc - the multigrid context
419: . l - the level (0 is coarsest) this is to be used for
420: - c - the space
422: Level: advanced
424: Notes: If this is not provided PETSc will automatically generate one.
426: You do not need to keep a reference to this vector if you do
427: not need it PCDestroy() will properly free it.
429: .keywords: MG, multigrid, set, residual, level
430: @*/
431: PetscErrorCode PCMGSetR(PC pc,PetscInt l,Vec c)
432: {
434: PC_MG *mg = (PC_MG*)pc->data;
435: PC_MG_Levels **mglevels = mg->levels;
438: if (!mglevels) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
439: if (!l) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Need not set residual vector for coarse grid");
440: PetscObjectReference((PetscObject)c);
441: if (mglevels[l]->r) {VecDestroy(mglevels[l]->r);}
442: mglevels[l]->r = c;
443: return(0);
444: }