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: }