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;

 61:   *ksp =  mg[0]->smoothd;
 62:   return(0);
 63: }

 67: /*@C
 68:    PCMGSetResidual - Sets the function to be used to calculate the residual 
 69:    on the lth level. 

 71:    Collective on PC and Mat

 73:    Input Parameters:
 74: +  pc       - the multigrid context
 75: .  l        - the level (0 is coarsest) to supply
 76: .  residual - function used to form residual (usually PCMGDefaultResidual)
 77: -  mat      - matrix associated with residual

 79:    Level: advanced

 81: .keywords:  MG, set, multigrid, residual, level

 83: .seealso: PCMGDefaultResidual()
 84: @*/
 85: PetscErrorCode  PCMGSetResidual(PC pc,PetscInt l,PetscErrorCode (*residual)(Mat,Vec,Vec,Vec),Mat mat)
 86: {
 87:   PC_MG **mg = (PC_MG**)pc->data;

 90:   if (!mg) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");

 92:   mg[l]->residual = residual;
 93:   mg[l]->A        = mat;
 94:   return(0);
 95: }

 99: /*@
100:    PCMGSetInterpolate - Sets the function to be used to calculate the 
101:    interpolation on the lth level. 

103:    Collective on PC and Mat

105:    Input Parameters:
106: +  pc  - the multigrid context
107: .  mat - the interpolation operator
108: -  l   - the level (0 is coarsest) to supply

110:    Level: advanced

112:    Notes:
113:           Usually this is the same matrix used also to set the restriction
114:     for the same level.

116:           One can pass in the interpolation matrix or its transpose; PETSc figures
117:     out from the matrix size which one it is.

119:          If you do not set this, the transpose of the Mat set with PCMGSetRestriction()
120:     is used.

122: .keywords:  multigrid, set, interpolate, level

124: .seealso: PCMGSetRestriction()
125: @*/
126: PetscErrorCode  PCMGSetInterpolate(PC pc,PetscInt l,Mat mat)
127: {
128:   PC_MG          **mg = (PC_MG**)pc->data;

132:   if (!mg) 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:   if (mg[l]->interpolate) {MatDestroy(mg[l]->interpolate);}
135:   mg[l]->interpolate = mat;
136:   PetscObjectReference((PetscObject)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

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 PCMGSetInterpolate()
163:     is used.

165: .keywords: MG, set, multigrid, restriction, level

167: .seealso: PCMGSetInterpolate()
168: @*/
169: PetscErrorCode  PCMGSetRestriction(PC pc,PetscInt l,Mat mat)
170: {
172:   PC_MG          **mg = (PC_MG**)pc->data;

175:   if (!mg) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
176:   if (!l) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Do not set restriction routine for coarsest level");
177:   if (mg[l]->restrct) {MatDestroy(mg[l]->restrct);}
178:   mg[l]->restrct  = mat;
179:   PetscObjectReference((PetscObject)mat);
180:   return(0);
181: }

185: /*@
186:    PCMGGetSmoother - Gets the KSP context to be used as smoother for 
187:    both pre- and post-smoothing.  Call both PCMGGetSmootherUp() and 
188:    PCMGGetSmootherDown() to use different functions for pre- and 
189:    post-smoothing.

191:    Not Collective, KSP returned is parallel if PC is 

193:    Input Parameters:
194: +  pc - the multigrid context 
195: -  l - the level (0 is coarsest) to supply

197:    Ouput Parameters:
198: .  ksp - the smoother

200:    Level: advanced

202: .keywords: MG, get, multigrid, level, smoother, pre-smoother, post-smoother

204: .seealso: PCMGGetSmootherUp(), PCMGGetSmootherDown()
205: @*/
206: PetscErrorCode  PCMGGetSmoother(PC pc,PetscInt l,KSP *ksp)
207: {
208:   PC_MG **mg = (PC_MG**)pc->data;

211:   *ksp = mg[l]->smoothd;
212:   return(0);
213: }

217: /*@
218:    PCMGGetSmootherUp - Gets the KSP context to be used as smoother after 
219:    coarse grid correction (post-smoother). 

221:    Not Collective, KSP returned is parallel if PC is

223:    Input Parameters:
224: +  pc - the multigrid context 
225: -  l  - the level (0 is coarsest) to supply

227:    Ouput Parameters:
228: .  ksp - the smoother

230:    Level: advanced

232: .keywords: MG, multigrid, get, smoother, up, post-smoother, level

234: .seealso: PCMGGetSmootherUp(), PCMGGetSmootherDown()
235: @*/
236: PetscErrorCode  PCMGGetSmootherUp(PC pc,PetscInt l,KSP *ksp)
237: {
238:   PC_MG          **mg = (PC_MG**)pc->data;
240:   const char     *prefix;
241:   MPI_Comm       comm;

244:   /*
245:      This is called only if user wants a different pre-smoother from post.
246:      Thus we check if a different one has already been allocated, 
247:      if not we allocate it.
248:   */
249:   if (!l) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"There is no such thing as a up smoother on the coarse grid");
250:   if (mg[l]->smoothu == mg[l]->smoothd) {
251:     PetscObjectGetComm((PetscObject)mg[l]->smoothd,&comm);
252:     KSPGetOptionsPrefix(mg[l]->smoothd,&prefix);
253:     KSPCreate(comm,&mg[l]->smoothu);
254:     KSPSetTolerances(mg[l]->smoothu,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);
255:     KSPSetOptionsPrefix(mg[l]->smoothu,prefix);
256:     PetscLogObjectParent(pc,mg[l]->smoothu);
257:   }
258:   if (ksp) *ksp = mg[l]->smoothu;
259:   return(0);
260: }

264: /*@
265:    PCMGGetSmootherDown - Gets the KSP context to be used as smoother before 
266:    coarse grid correction (pre-smoother). 

268:    Not Collective, KSP returned is parallel if PC is

270:    Input Parameters:
271: +  pc - the multigrid context 
272: -  l  - the level (0 is coarsest) to supply

274:    Ouput Parameters:
275: .  ksp - the smoother

277:    Level: advanced

279: .keywords: MG, multigrid, get, smoother, down, pre-smoother, level

281: .seealso: PCMGGetSmootherUp(), PCMGGetSmoother()
282: @*/
283: PetscErrorCode  PCMGGetSmootherDown(PC pc,PetscInt l,KSP *ksp)
284: {
286:   PC_MG          **mg = (PC_MG**)pc->data;

289:   /* make sure smoother up and down are different */
290:   if (l != 0) {
291:     PCMGGetSmootherUp(pc,l,PETSC_NULL);
292:   }
293:   *ksp = mg[l]->smoothd;
294:   return(0);
295: }

299: /*@
300:    PCMGSetCyclesOnLevel - Sets the number of cycles to run on this level. 

302:    Collective on PC

304:    Input Parameters:
305: +  pc - the multigrid context 
306: .  l  - the level (0 is coarsest) this is to be used for
307: -  n  - the number of cycles

309:    Level: advanced

311: .keywords: MG, multigrid, set, cycles, V-cycle, W-cycle, level

313: .seealso: PCMGSetCycles()
314: @*/
315: PetscErrorCode  PCMGSetCyclesOnLevel(PC pc,PetscInt l,PetscInt c)
316: {
317:   PC_MG **mg = (PC_MG**)pc->data;

320:   if (!mg) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
321:   mg[l]->cycles  = c;
322:   return(0);
323: }

327: /*@
328:    PCMGSetRhs - Sets the vector space to be used to store the right-hand side
329:    on a particular level. 

331:    Collective on PC and Vec

333:    Input Parameters:
334: +  pc - the multigrid context 
335: .  l  - the level (0 is coarsest) this is to be used for
336: -  c  - the space

338:    Level: advanced

340:    Notes: If this is not provided PETSc will automatically generate one.

342:           You do not need to keep a reference to this vector if you do 
343:           not need it PCDestroy() will properly free it.

345: .keywords: MG, multigrid, set, right-hand-side, rhs, level

347: .seealso: PCMGSetX(), PCMGSetR()
348: @*/
349: PetscErrorCode  PCMGSetRhs(PC pc,PetscInt l,Vec c)
350: {
352:   PC_MG          **mg = (PC_MG**)pc->data;

355:   if (!mg) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
356:   if (l == mg[0]->levels-1) SETERRQ(PETSC_ERR_ARG_INCOMP,"Do not set rhs for finest level");
357:   if (mg[l]->b) {VecDestroy(mg[l]->b);}
358:   mg[l]->b  = c;
359:   PetscObjectReference((PetscObject)c);
360:   return(0);
361: }

365: /*@
366:    PCMGSetX - Sets the vector space to be used to store the solution on a 
367:    particular level.

369:    Collective on PC and Vec

371:    Input Parameters:
372: +  pc - the multigrid context 
373: .  l - the level (0 is coarsest) this is to be used for
374: -  c - the space

376:    Level: advanced

378:    Notes: If this is not provided PETSc will automatically generate one.

380:           You do not need to keep a reference to this vector if you do 
381:           not need it PCDestroy() will properly free it.

383: .keywords: MG, multigrid, set, solution, level

385: .seealso: PCMGSetRhs(), PCMGSetR()
386: @*/
387: PetscErrorCode  PCMGSetX(PC pc,PetscInt l,Vec c)
388: {
390:   PC_MG          **mg = (PC_MG**)pc->data;

393:   if (!mg) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
394:   if (l == mg[0]->levels-1) SETERRQ(PETSC_ERR_ARG_INCOMP,"Do not set rhs for finest level");
395:   if (mg[l]->x) {VecDestroy(mg[l]->x);}
396:   mg[l]->x  = c;
397:   PetscObjectReference((PetscObject)c);
398:   return(0);
399: }

403: /*@
404:    PCMGSetR - Sets the vector space to be used to store the residual on a
405:    particular level. 

407:    Collective on PC and Vec

409:    Input Parameters:
410: +  pc - the multigrid context 
411: .  l - the level (0 is coarsest) this is to be used for
412: -  c - the space

414:    Level: advanced

416:    Notes: If this is not provided PETSc will automatically generate one.

418:           You do not need to keep a reference to this vector if you do 
419:           not need it PCDestroy() will properly free it.

421: .keywords: MG, multigrid, set, residual, level
422: @*/
423: PetscErrorCode  PCMGSetR(PC pc,PetscInt l,Vec c)
424: {
426:   PC_MG          **mg = (PC_MG**)pc->data;

429:   if (!mg) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
430:   if (!l) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Need not set residual vector for coarse grid");
431:   if (mg[l]->r) {VecDestroy(mg[l]->r);}
432:   mg[l]->r  = c;
433:   PetscObjectReference((PetscObject)c);
434:   return(0);
435: }