Actual source code: damg.c

  1: #define PETSCSNES_DLL
  2: 
 3:  #include petscda.h
 4:  #include petscksp.h
 5:  #include petscmg.h
 6:  #include petscdmmg.h
 7:  #include private/pcimpl.h

  9: /*
 10:    Code for almost fully managing multigrid/multi-level linear solvers for DA grids
 11: */

 15: /*@C
 16:     DMMGCreate - Creates a DA based multigrid solver object. This allows one to 
 17:       easily implement MG methods on regular grids.

 19:     Collective on MPI_Comm

 21:     Input Parameter:
 22: +   comm - the processors that will share the grids and solution process
 23: .   nlevels - number of multigrid levels 
 24: -   user - an optional user context

 26:     Output Parameters:
 27: .    - the context

 29:     Notes:
 30:       To provide a different user context for each level call DMMGSetUser() after calling
 31:       this routine

 33:     Level: advanced

 35: .seealso DMMGDestroy(), DMMGSetUser(), DMMGGetUser()

 37: @*/
 38: PetscErrorCode PETSCSNES_DLLEXPORT DMMGCreate(MPI_Comm comm,PetscInt nlevels,void *user,DMMG **dmmg)
 39: {
 41:   PetscInt       i;
 42:   DMMG           *p;
 43:   PetscTruth     galerkin;

 46:   PetscOptionsGetInt(0,"-dmmg_nlevels",&nlevels,PETSC_IGNORE);
 47:   PetscOptionsHasName(0,"-dmmg_galerkin",&galerkin);

 49:   PetscMalloc(nlevels*sizeof(DMMG),&p);
 50:   for (i=0; i<nlevels; i++) {
 51:     PetscNew(struct _n_DMMG,&p[i]);
 52:     p[i]->nlevels  = nlevels - i;
 53:     p[i]->comm     = comm;
 54:     p[i]->user     = user;
 55:     p[i]->galerkin = galerkin;
 56:   }
 57:   p[nlevels-1]->galerkin = PETSC_FALSE;
 58:   *dmmg = p;
 59:   return(0);
 60: }

 64: /*@C
 65:     DMMGSetUseGalerkinCoarse - Courses the DMMG to use R*A_f*R^T to form
 66:        the coarser matrices from finest 

 68:     Collective on DMMG

 70:     Input Parameter:
 71: .    - the context

 73:     Options Database Keys:
 74: .    -dmmg_galerkin

 76:     Level: advanced

 78:     Notes: After you have called this you can manually set dmmg[0]->galerkin = PETSC_FALSE
 79:        to have the coarsest grid not compute via Galerkin but still have the intermediate
 80:        grids computed via Galerkin.

 82: .seealso DMMGCreate()

 84: @*/
 85: PetscErrorCode PETSCSNES_DLLEXPORT DMMGSetUseGalerkinCoarse(DMMG* dmmg)
 86: {
 87:   PetscInt  i,nlevels = dmmg[0]->nlevels;

 90:   if (!dmmg) SETERRQ(PETSC_ERR_ARG_NULL,"Passing null as DMMG");

 92:   for (i=0; i<nlevels-1; i++) {
 93:     dmmg[i]->galerkin = PETSC_TRUE;
 94:   }
 95:   return(0);
 96: }

100: /*@C
101:     DMMGDestroy - Destroys a DA based multigrid solver object. 

103:     Collective on DMMG

105:     Input Parameter:
106: .    - the context

108:     Level: advanced

110: .seealso DMMGCreate()

112: @*/
113: PetscErrorCode PETSCSNES_DLLEXPORT DMMGDestroy(DMMG *dmmg)
114: {
116:   PetscInt       i,nlevels = dmmg[0]->nlevels;

119:   if (!dmmg) SETERRQ(PETSC_ERR_ARG_NULL,"Passing null as DMMG");

121:   for (i=1; i<nlevels; i++) {
122:     if (dmmg[i]->R) {MatDestroy(dmmg[i]->R);}
123:   }
124:   for (i=0; i<nlevels; i++) {
125:     if (dmmg[i]->dm)      {DMDestroy(dmmg[i]->dm);}
126:     if (dmmg[i]->x)       {VecDestroy(dmmg[i]->x);}
127:     if (dmmg[i]->b)       {VecDestroy(dmmg[i]->b);}
128:     if (dmmg[i]->r)       {VecDestroy(dmmg[i]->r);}
129:     if (dmmg[i]->work1)   {VecDestroy(dmmg[i]->work1);}
130:     if (dmmg[i]->w)       {VecDestroy(dmmg[i]->w);}
131:     if (dmmg[i]->work2)   {VecDestroy(dmmg[i]->work2);}
132:     if (dmmg[i]->lwork1)  {VecDestroy(dmmg[i]->lwork1);}
133:     if (dmmg[i]->B && dmmg[i]->B != dmmg[i]->J) {MatDestroy(dmmg[i]->B);}
134:     if (dmmg[i]->J)         {MatDestroy(dmmg[i]->J);}
135:     if (dmmg[i]->Rscale)    {VecDestroy(dmmg[i]->Rscale);}
136:     if (dmmg[i]->fdcoloring){MatFDColoringDestroy(dmmg[i]->fdcoloring);}
137:     if (dmmg[i]->ksp && !dmmg[i]->snes) {KSPDestroy(dmmg[i]->ksp);}
138:     if (dmmg[i]->snes)      {PetscObjectDestroy((PetscObject)dmmg[i]->snes);}
139:     if (dmmg[i]->inject)    {VecScatterDestroy(dmmg[i]->inject);}
140:     PetscFree(dmmg[i]);
141:   }
142:   PetscFree(dmmg);
143:   return(0);
144: }

148: /*@C
149:     DMMGSetDM - Sets the coarse grid information for the grids

151:     Collective on DMMG

153:     Input Parameter:
154: +   dmmg - the context
155: -   dm - the DA or VecPack object

157:     Level: advanced

159: .seealso DMMGCreate(), DMMGDestroy()

161: @*/
162: PetscErrorCode PETSCSNES_DLLEXPORT DMMGSetDM(DMMG *dmmg,DM dm)
163: {
165:   PetscInt       i,nlevels = dmmg[0]->nlevels;

168:   if (!dmmg) SETERRQ(PETSC_ERR_ARG_NULL,"Passing null as DMMG");

170:   /* Create DA data structure for all the levels */
171:   dmmg[0]->dm = dm;
172:   PetscObjectReference((PetscObject)dm);
173:   for (i=1; i<nlevels; i++) {
174:     DMRefine(dmmg[i-1]->dm,dmmg[i]->comm,&dmmg[i]->dm);
175:   }
176:   DMMGSetUp(dmmg);
177:   return(0);
178: }

182: /*@C
183:     DMMGSetUp - Prepares the DMMG to solve a system

185:     Collective on DMMG

187:     Input Parameter:
188: .   dmmg - the context

190:     Level: advanced

192: .seealso DMMGCreate(), DMMGDestroy(), DMMG, DMMGSetSNES(), DMMGSetKSP(), DMMGSolve()

194: @*/
195: PetscErrorCode PETSCSNES_DLLEXPORT DMMGSetUp(DMMG *dmmg)
196: {
198:   PetscInt       i,nlevels = dmmg[0]->nlevels;


202:   /* Create work vectors and matrix for each level */
203:   for (i=0; i<nlevels; i++) {
204:     DMCreateGlobalVector(dmmg[i]->dm,&dmmg[i]->x);
205:     VecDuplicate(dmmg[i]->x,&dmmg[i]->b);
206:     VecDuplicate(dmmg[i]->x,&dmmg[i]->r);
207:   }

209:   /* Create interpolation/restriction between levels */
210:   for (i=1; i<nlevels; i++) {
211:     DMGetInterpolation(dmmg[i-1]->dm,dmmg[i]->dm,&dmmg[i]->R,PETSC_NULL);
212:   }

214:   return(0);
215: }

219: /*@C
220:     DMMGSolve - Actually solves the (non)linear system defined with the DMMG

222:     Collective on DMMG

224:     Input Parameter:
225: .   dmmg - the context

227:     Level: advanced

229:     Options Database:
230: +   -dmmg_grid_sequence - use grid sequencing to get the initial solution for each level from the previous
231: -   -dmmg_vecmonitor - display the solution at each iteration

233:      Notes: For linear (KSP) problems may be called more than once, uses the same 
234:     matrices but recomputes the right hand side for each new solve. Call DMMGSetKSP()
235:     to generate new matrices.
236:  
237: .seealso DMMGCreate(), DMMGDestroy(), DMMG, DMMGSetSNES(), DMMGSetKSP(), DMMGSetUp()

239: @*/
240: PetscErrorCode PETSCSNES_DLLEXPORT DMMGSolve(DMMG *dmmg)
241: {
243:   PetscInt       i,nlevels = dmmg[0]->nlevels;
244:   PetscTruth     gridseq,vecmonitor,flg;

247:   PetscOptionsHasName(0,"-dmmg_grid_sequence",&gridseq);
248:   PetscOptionsHasName(0,"-dmmg_vecmonitor",&vecmonitor);
249:   if (gridseq) {
250:     if (dmmg[0]->initialguess) {
251:       (*dmmg[0]->initialguess)(dmmg[0],dmmg[0]->x);
252:       if (dmmg[0]->ksp && !dmmg[0]->snes) {
253:         KSPSetInitialGuessNonzero(dmmg[0]->ksp,PETSC_TRUE);
254:       }
255:     }
256:     for (i=0; i<nlevels-1; i++) {
257:       (*dmmg[i]->solve)(dmmg,i);
258:       if (vecmonitor) {
259:         VecView(dmmg[i]->x,PETSC_VIEWER_DRAW_(dmmg[i]->comm));
260:       }
261:       MatInterpolate(dmmg[i+1]->R,dmmg[i]->x,dmmg[i+1]->x);
262:       if (dmmg[i+1]->ksp && !dmmg[i+1]->ksp) {
263:         KSPSetInitialGuessNonzero(dmmg[i+1]->ksp,PETSC_TRUE);
264:       }
265:     }
266:   } else {
267:     if (dmmg[nlevels-1]->initialguess) {
268:       (*dmmg[nlevels-1]->initialguess)(dmmg[nlevels-1],dmmg[nlevels-1]->x);
269:     }
270:   }
271:   (*DMMGGetFine(dmmg)->solve)(dmmg,nlevels-1);
272:   if (vecmonitor) {
273:      VecView(dmmg[nlevels-1]->x,PETSC_VIEWER_DRAW_(dmmg[nlevels-1]->comm));
274:   }

276:   PetscOptionsHasName(PETSC_NULL,"-dmmg_view",&flg);
277:   if (flg && !PetscPreLoadingOn) {
278:     DMMGView(dmmg,PETSC_VIEWER_STDOUT_(dmmg[0]->comm));
279:   }
280:   PetscOptionsHasName(PETSC_NULL,"-dmmg_view_binary",&flg);
281:   if (flg && !PetscPreLoadingOn) {
282:     DMMGView(dmmg,PETSC_VIEWER_BINARY_(dmmg[0]->comm));
283:   }
284:   return(0);
285: }

289: PetscErrorCode PETSCSNES_DLLEXPORT DMMGSolveKSP(DMMG *dmmg,PetscInt level)
290: {

294:   if (dmmg[level]->rhs) {
295:     (*dmmg[level]->rhs)(dmmg[level],dmmg[level]->b);
296:   }
297:   if (dmmg[level]->matricesset) {
298:     KSPSetOperators(dmmg[level]->ksp,dmmg[level]->J,dmmg[level]->B,SAME_NONZERO_PATTERN);
299:     dmmg[level]->matricesset = PETSC_FALSE;
300:   }
301:   KSPSolve(dmmg[level]->ksp,dmmg[level]->b,dmmg[level]->x);
302:   return(0);
303: }

305: /*
306:     Sets each of the linear solvers to use multigrid 
307: */
310: PetscErrorCode PETSCSNES_DLLEXPORT DMMGSetUpLevel(DMMG *dmmg,KSP ksp,PetscInt nlevels)
311: {
313:   PetscInt       i;
314:   PC             pc;
315:   PetscTruth     ismg,monitor,ismf,isshell,ismffd;
316:   KSP            lksp; /* solver internal to the multigrid preconditioner */
317:   MPI_Comm       *comms,comm;
318:   PetscViewer    ascii;

321:   if (!dmmg) SETERRQ(PETSC_ERR_ARG_NULL,"Passing null as DMMG");

323:   PetscOptionsHasName(PETSC_NULL,"-dmmg_ksp_monitor",&monitor);
324:   if (monitor) {
325:     PetscObjectGetComm((PetscObject)ksp,&comm);
326:     PetscViewerASCIIOpen(comm,"stdout",&ascii);
327:     PetscViewerASCIISetTab(ascii,1+dmmg[0]->nlevels-nlevels);
328:     KSPSetMonitor(ksp,KSPDefaultMonitor,ascii,(PetscErrorCode(*)(void*))PetscViewerDestroy);
329:   }

331:   /* use fgmres on outer iteration by default */
332:   KSPSetType(ksp,KSPFGMRES);
333:   KSPGetPC(ksp,&pc);
334:   PCSetType(pc,PCMG);
335:   PetscMalloc(nlevels*sizeof(MPI_Comm),&comms);
336:   for (i=0; i<nlevels; i++) {
337:     comms[i] = dmmg[i]->comm;
338:   }
339:   PCMGSetLevels(pc,nlevels,comms);
340:   PetscFree(comms);
341:    PCMGSetType(pc,PC_MG_FULL);

343:   PetscTypeCompare((PetscObject)pc,PCMG,&ismg);
344:   if (ismg) {
345:     if (dmmg[0]->galerkin) {
346:       PCMGSetGalerkin(pc);
347:     }

349:     /* set solvers for each level */
350:     for (i=0; i<nlevels; i++) {
351:       PCMGGetSmoother(pc,i,&lksp);
352:       if (i == nlevels-1 || !dmmg[0]->galerkin) {
353:         KSPSetOperators(lksp,dmmg[i]->J,dmmg[i]->B,DIFFERENT_NONZERO_PATTERN);
354:       }
355:       if (i < nlevels-1) { /* don't set for finest level, they are set in PCApply_MG()*/
356:         PCMGSetX(pc,i,dmmg[i]->x);
357:         PCMGSetRhs(pc,i,dmmg[i]->b);
358:       }
359:       if (i > 0) {
360:         PCMGSetR(pc,i,dmmg[i]->r);
361:         PCMGSetResidual(pc,i,PCMGDefaultResidual,dmmg[i]->J);
362:       }
363:       if (monitor) {
364:         PetscObjectGetComm((PetscObject)lksp,&comm);
365:         PetscViewerASCIIOpen(comm,"stdout",&ascii);
366:         PetscViewerASCIISetTab(ascii,1+dmmg[0]->nlevels-i);
367:         KSPSetMonitor(lksp,KSPDefaultMonitor,ascii,(PetscErrorCode(*)(void*))PetscViewerDestroy);
368:       }
369:       /* If using a matrix free multiply and did not provide an explicit matrix to build
370:          the preconditioner then must use no preconditioner 
371:       */
372:       PetscTypeCompare((PetscObject)dmmg[i]->B,MATSHELL,&isshell);
373:       PetscTypeCompare((PetscObject)dmmg[i]->B,MATDAAD,&ismf);
374:       PetscTypeCompare((PetscObject)dmmg[i]->B,MATMFFD,&ismffd);
375:       if (isshell || ismf || ismffd) {
376:         PC  lpc;
377:         KSPGetPC(lksp,&lpc);
378:         PCSetType(lpc,PCNONE);
379:       }
380:     }

382:     /* Set interpolation/restriction between levels */
383:     for (i=1; i<nlevels; i++) {
384:       PCMGSetInterpolate(pc,i,dmmg[i]->R);
385:       PCMGSetRestriction(pc,i,dmmg[i]->R);
386:     }
387:   }
388:   return(0);
389: }

393: /*@C
394:     DMMGSetKSP - Sets the linear solver object that will use the grid hierarchy

396:     Collective on DMMG

398:     Input Parameter:
399: +   dmmg - the context
400: .   func - function to compute linear system matrix on each grid level
401: -   rhs - function to compute right hand side on each level (need only work on the finest grid
402:           if you do not use grid sequencing)

404:     Level: advanced

406:     Notes: For linear problems my be called more than once, reevaluates the matrices if it is called more
407:        than once. Call DMMGSolve() directly several times to solve with the same matrix but different 
408:        right hand sides.
409:    
410: .seealso DMMGCreate(), DMMGDestroy, DMMGSetDM(), DMMGSolve()

412: @*/
413: PetscErrorCode PETSCSNES_DLLEXPORT DMMGSetKSP(DMMG *dmmg,PetscErrorCode (*rhs)(DMMG,Vec),PetscErrorCode (*func)(DMMG,Mat,Mat))
414: {
416:   PetscInt       i,nlevels = dmmg[0]->nlevels;
417:   PetscTruth     galerkin;

420:   if (!dmmg) SETERRQ(PETSC_ERR_ARG_NULL,"Passing null as DMMG");
421:   galerkin = dmmg[nlevels - 2 > 0 ? nlevels - 2 : 0]->galerkin;

423:   if (galerkin) {
424:     DMGetMatrix(dmmg[nlevels-1]->dm,MATAIJ,&dmmg[nlevels-1]->B);
425:     if (!dmmg[nlevels-1]->J) {
426:       dmmg[nlevels-1]->J = dmmg[nlevels-1]->B;
427:     }
428:     (*func)(dmmg[nlevels-1],dmmg[nlevels-1]->J,dmmg[nlevels-1]->B);
429:     for (i=nlevels-2; i>-1; i--) {
430:       if (dmmg[i]->galerkin) {
431:         MatPtAP(dmmg[i+1]->B,dmmg[i+1]->R,MAT_INITIAL_MATRIX,1.0,&dmmg[i]->B);
432:         if (!dmmg[i]->J) {
433:           dmmg[i]->J = dmmg[i]->B;
434:         }
435:       }
436:     }
437:   }

439:   if (!dmmg[0]->ksp) {
440:     /* create solvers for each level if they don't already exist*/
441:     for (i=0; i<nlevels; i++) {

443:       if (!dmmg[i]->B && !dmmg[i]->galerkin) {
444:         DMGetMatrix(dmmg[i]->dm,MATAIJ,&dmmg[i]->B);
445:       }
446:       if (!dmmg[i]->J) {
447:         dmmg[i]->J = dmmg[i]->B;
448:       }

450:       KSPCreate(dmmg[i]->comm,&dmmg[i]->ksp);
451:       DMMGSetUpLevel(dmmg,dmmg[i]->ksp,i+1);
452:       KSPSetFromOptions(dmmg[i]->ksp);
453:       dmmg[i]->solve = DMMGSolveKSP;
454:       dmmg[i]->rhs   = rhs;
455:     }
456:   }

458:   /* evalute matrix on each level */
459:   for (i=0; i<nlevels; i++) {
460:     if (!dmmg[i]->galerkin) {
461:       (*func)(dmmg[i],dmmg[i]->J,dmmg[i]->B);
462:     }
463:     dmmg[i]->matricesset = PETSC_TRUE;
464:   }

466:   for (i=0; i<nlevels-1; i++) {
467:     KSPSetOptionsPrefix(dmmg[i]->ksp,"dmmg_");
468:   }

470:   return(0);
471: }

475: /*@C
476:     DMMGView - prints information on a DA based multi-level preconditioner

478:     Collective on DMMG and PetscViewer

480:     Input Parameter:
481: +   dmmg - the context
482: -   viewer - the viewer

484:     Level: advanced

486: .seealso DMMGCreate(), DMMGDestroy

488: @*/
489: PetscErrorCode PETSCSNES_DLLEXPORT DMMGView(DMMG *dmmg,PetscViewer viewer)
490: {
492:   PetscInt       i,nlevels = dmmg[0]->nlevels;
493:   PetscMPIInt    flag;
494:   MPI_Comm       comm;
495:   PetscTruth     iascii,isbinary;

500:   PetscObjectGetComm((PetscObject)viewer,&comm);
501:   MPI_Comm_compare(comm,dmmg[0]->comm,&flag);
502:   if (flag != MPI_CONGRUENT && flag != MPI_IDENT) {
503:     SETERRQ(PETSC_ERR_ARG_NOTSAMECOMM,"Different communicators in the DMMG and the PetscViewer");
504:   }

506:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
507:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_BINARY,&isbinary);
508:   if (isbinary) {
509:     for (i=0; i<nlevels; i++) {
510:       MatView(dmmg[i]->J,viewer);
511:     }
512:     for (i=1; i<nlevels; i++) {
513:       MatView(dmmg[i]->R,viewer);
514:     }
515:   } else {
516:     if (iascii) {
517:       PetscViewerASCIIPrintf(viewer,"DMMG Object with %D levels\n",nlevels);
518:     }
519:     for (i=0; i<nlevels; i++) {
520:       PetscViewerASCIIPushTab(viewer);
521:       DMView(dmmg[i]->dm,viewer);
522:       PetscViewerASCIIPopTab(viewer);
523:     }
524:     if (iascii) {
525:       PetscViewerASCIIPrintf(viewer,"%s Object on finest level\n",dmmg[nlevels-1]->ksp ? "KSP" : "SNES");
526:       if (dmmg[nlevels-2 > 0 ? nlevels-2 : 0]->galerkin) {
527:         PetscViewerASCIIPrintf(viewer,"Using Galerkin R^T*A*R process to compute coarser matrices");
528:       }
529:     }
530:     if (dmmg[nlevels-1]->ksp) {
531:       KSPView(dmmg[nlevels-1]->ksp,viewer);
532:     } else {
533:       /* use of PetscObjectView() means we do not have to link with libpetscsnes if SNES is not being used */
534:       PetscObjectView((PetscObject)dmmg[nlevels-1]->snes,viewer);
535:     }
536:   }
537:   return(0);
538: }

542: /*@C
543:     DMMGSetNullSpace - Indicates the null space in the linear operator (this is needed by the linear solver)

545:     Collective on DMMG

547:     Input Parameter:
548: +   dmmg - the context
549: .   has_cnst - is the constant vector in the null space
550: .   n - number of null vectors (excluding the possible constant vector)
551: -   func - a function that fills an array of vectors with the null vectors (must be orthonormal), may be PETSC_NULL

553:     Level: advanced

555: .seealso DMMGCreate(), DMMGDestroy, DMMGSetDM(), DMMGSolve(), MatNullSpaceCreate(), KSPSetNullSpace()

557: @*/
558: PetscErrorCode PETSCSNES_DLLEXPORT DMMGSetNullSpace(DMMG *dmmg,PetscTruth has_cnst,PetscInt n,PetscErrorCode (*func)(DMMG,Vec[]))
559: {
561:   PetscInt       i,j,nlevels = dmmg[0]->nlevels;
562:   Vec            *nulls = 0;
563:   MatNullSpace   nullsp;
564:   KSP            iksp;
565:   PC             pc,ipc;
566:   PetscTruth     ismg,isred;

569:   if (!dmmg) SETERRQ(PETSC_ERR_ARG_NULL,"Passing null as DMMG");
570:   if (!dmmg[0]->ksp) SETERRQ(PETSC_ERR_ORDER,"Must call AFTER DMMGSetKSP() or DMMGSetSNES()");
571:   if ((n && !func) || (!n && func)) SETERRQ(PETSC_ERR_ARG_INCOMP,"Both n and func() must be set together");
572:   if (n < 0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Cannot have negative number of vectors in null space n = %D",n)

574:   for (i=0; i<nlevels; i++) {
575:     if (n) {
576:       VecDuplicateVecs(dmmg[i]->b,n,&nulls);
577:       (*func)(dmmg[i],nulls);
578:     }
579:     MatNullSpaceCreate(dmmg[i]->comm,has_cnst,n,nulls,&nullsp);
580:     KSPSetNullSpace(dmmg[i]->ksp,nullsp);
581:     for (j=i; j<nlevels; j++) {
582:       KSPGetPC(dmmg[j]->ksp,&pc);
583:       PetscTypeCompare((PetscObject)pc,PCMG,&ismg);
584:       if (ismg) {
585:         PCMGGetSmoother(pc,i,&iksp);
586:         KSPSetNullSpace(iksp, nullsp);
587:       }
588:     }
589:     MatNullSpaceDestroy(nullsp);
590:     if (n) {
591:       PetscFree(nulls);
592:     }
593:   }
594:   /* make all the coarse grid solvers have LU shift since they are singular */
595:   for (i=0; i<nlevels; i++) {
596:     KSPGetPC(dmmg[i]->ksp,&pc);
597:     PetscTypeCompare((PetscObject)pc,PCMG,&ismg);
598:     if (ismg) {
599:       PCMGGetSmoother(pc,0,&iksp);
600:       KSPGetPC(iksp,&ipc);
601:       PetscTypeCompare((PetscObject)ipc,PCREDUNDANT,&isred);
602:       if (isred) {
603:         PCRedundantGetPC(ipc,&ipc);
604:       }
605:       PCFactorSetShiftPd(ipc,PETSC_TRUE);
606:     }
607:   }
608:   return(0);
609: }

613: /*@C
614:     DMMGInitialGuessCurrent - Use with DMMGSetInitialGuess() to use the current value in the 
615:        solution vector (obtainable with DMMGGetx() as the initial guess)

617:     Collective on DMMG

619:     Input Parameter:
620: +   dmmg - the context
621: -   vec - dummy argument

623:     Level: intermediate

625: .seealso DMMGCreate(), DMMGDestroy, DMMGSetKSP(), DMMGSetSNES(), DMMGSetInitialGuess()

627: @*/
628: PetscErrorCode PETSCSNES_DLLEXPORT DMMGInitialGuessCurrent(DMMG dmmg,Vec vec)
629: {
631:   return(0);
632: }

636: /*@C
637:     DMMGSetInitialGuess - Sets the function that computes an initial guess.

639:     Collective on DMMG

641:     Input Parameter:
642: +   dmmg - the context
643: -   guess - the function

645:     Notes: For nonlinear problems, if this is not set, then the current value in the 
646:              solution vector (obtained with DMMGGetX()) is used. Thus is if you doing 'time
647:              stepping' it will use your current solution as the guess for the next timestep.
648:            If grid sequencing is used (via -dmmg_grid_sequence) then the "guess" function
649:              is used only on the coarsest grid.
650:            For linear problems, if this is not set, then 0 is used as an initial guess.
651:              If you would like the linear solver to also (like the nonlinear solver) use
652:              the current solution vector as the initial guess then use DMMGInitialGuessCurrent()
653:              as the function you pass in

655:     Level: intermediate


658: .seealso DMMGCreate(), DMMGDestroy, DMMGSetKSP(), DMMGSetSNES(), DMMGInitialGuessCurrent()

660: @*/
661: PetscErrorCode PETSCSNES_DLLEXPORT DMMGSetInitialGuess(DMMG *dmmg,PetscErrorCode (*guess)(DMMG,Vec))
662: {
663:   PetscInt i,nlevels = dmmg[0]->nlevels;

666:   for (i=0; i<nlevels; i++) {
667:     dmmg[i]->initialguess = guess;
668:   }
669:   return(0);
670: }