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