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  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:        The default behavior of this should be idential to using -pc_mg_galerkin; this offers
 83:        more potential flexibility since you can select exactly which levels are done via
 84:        Galerkin and which are done via user provided function.

 86: .seealso DMMGCreate(), PCMGSetGalerkin()

 88: @*/
 89: PetscErrorCode  DMMGSetUseGalerkinCoarse(DMMG* dmmg)
 90: {
 91:   PetscInt  i,nlevels = dmmg[0]->nlevels;

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

 96:   for (i=0; i<nlevels-1; i++) {
 97:     dmmg[i]->galerkin = PETSC_TRUE;
 98:   }
 99:   return(0);
100: }

104: /*@C
105:     DMMGDestroy - Destroys a DA based multigrid solver object. 

107:     Collective on DMMG

109:     Input Parameter:
110: .    - the context

112:     Level: advanced

114: .seealso DMMGCreate()

116: @*/
117: PetscErrorCode  DMMGDestroy(DMMG *dmmg)
118: {
120:   PetscInt       i,nlevels = dmmg[0]->nlevels;

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

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

152: /*@C
153:     DMMGSetDM - Sets the coarse grid information for the grids

155:     Collective on DMMG

157:     Input Parameter:
158: +   dmmg - the context
159: -   dm - the DA or VecPack object

161:     Level: advanced

163: .seealso DMMGCreate(), DMMGDestroy()

165: @*/
166: PetscErrorCode  DMMGSetDM(DMMG *dmmg,DM dm)
167: {
169:   PetscInt       i,nlevels = dmmg[0]->nlevels;

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

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

186: /*@C
187:     DMMGSetUp - Prepares the DMMG to solve a system

189:     Collective on DMMG

191:     Input Parameter:
192: .   dmmg - the context

194:     Level: advanced

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

198: @*/
199: PetscErrorCode  DMMGSetUp(DMMG *dmmg)
200: {
202:   PetscInt       i,nlevels = dmmg[0]->nlevels;


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

213:   /* Create interpolation/restriction between levels */
214:   for (i=1; i<nlevels; i++) {
215:     DMGetInterpolation(dmmg[i-1]->dm,dmmg[i]->dm,&dmmg[i]->R,PETSC_NULL);
216:   }

218:   return(0);
219: }

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

226:     Collective on DMMG

228:     Input Parameter:
229: .   dmmg - the context

231:     Level: advanced

233:     Options Database:
234: +   -dmmg_grid_sequence - use grid sequencing to get the initial solution for each level from the previous
235: -   -dmmg_vecmonitor - display the solution at each iteration

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

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

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

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

293: PetscErrorCode  DMMGSolveKSP(DMMG *dmmg,PetscInt level)
294: {

298:   if (dmmg[level]->rhs) {
299:     CHKMEMQ;
300:     (*dmmg[level]->rhs)(dmmg[level],dmmg[level]->b);
301:     CHKMEMQ;
302:   }
303:   if (dmmg[level]->matricesset) {
304:     KSPSetOperators(dmmg[level]->ksp,dmmg[level]->J,dmmg[level]->B,SAME_NONZERO_PATTERN);
305:     dmmg[level]->matricesset = PETSC_FALSE;
306:   }
307:   KSPSolve(dmmg[level]->ksp,dmmg[level]->b,dmmg[level]->x);
308:   return(0);
309: }

311: /*
312:     Sets each of the linear solvers to use multigrid 
313: */
316: PetscErrorCode  DMMGSetUpLevel(DMMG *dmmg,KSP ksp,PetscInt nlevels)
317: {
319:   PetscInt       i;
320:   PC             pc;
321:   PetscTruth     ismg,monitor,ismf,isshell,ismffd;
322:   KSP            lksp; /* solver internal to the multigrid preconditioner */
323:   MPI_Comm       *comms,comm;
324:   PetscViewer    ascii;

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

329:   PetscOptionsHasName(PETSC_NULL,"-dmmg_ksp_monitor",&monitor);
330:   if (monitor) {
331:     PetscObjectGetComm((PetscObject)ksp,&comm);
332:     PetscViewerASCIIOpen(comm,"stdout",&ascii);
333:     PetscViewerASCIISetTab(ascii,1+dmmg[0]->nlevels-nlevels);
334:     KSPSetMonitor(ksp,KSPDefaultMonitor,ascii,(PetscErrorCode(*)(void*))PetscViewerDestroy);
335:   }

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

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

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

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

397:     Collective on DMMG

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

405:     Level: advanced

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

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

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

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

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

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

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

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

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

471:   return(0);
472: }

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

479:     Collective on DMMG and PetscViewer

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

485:     Level: advanced

487: .seealso DMMGCreate(), DMMGDestroy

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

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

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

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

546:     Collective on DMMG

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

554:     Level: advanced

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

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

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

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

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

618:     Collective on DMMG

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

624:     Level: intermediate

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

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

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

640:     Collective on DMMG

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

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

656:     Level: intermediate


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

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

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