Actual source code: damg.c

  1: 
  2: #include <petscdm.h>            /*I "petscdm.h"   I*/
  3: #include <petscksp.h>           /*I "petscksp.h"  I*/
  4: #include <petscpcmg.h>            /*I "petscpcmg.h"   I*/
  5: #include <petscdmmg.h>          /*I "petscdmmg.h" I*/
  6: #include <private/pcimpl.h>     /*I "petscpc.h"   I*/

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

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

 18:      This is being deprecated. Use KSPSetDM() for linear problems and SNESSetDM() for nonlinear problems. 
 19:     See src/ksp/ksp/examples/tutorials/ex45.c and src/snes/examples/tutorials/ex57.c 

 21:     Collective on MPI_Comm

 23:     Input Parameter:
 24: +   comm - the processors that will share the grids and solution process
 25: .   nlevels - number of multigrid levels (if this is negative it CANNOT be reset with -dmmg_nlevels
 26: -   user - an optional user context

 28:     Output Parameters:
 29: .    - the context

 31:     Options Database:
 32: +     -dmmg_nlevels <levels> - number of levels to use
 33: .     -pc_mg_galerkin - use Galerkin approach to compute coarser matrices
 34: -     -dmmg_mat_type <type> - matrix type that DMMG should create, defaults to MATAIJ

 36:     Notes:
 37:       To provide a different user context for each level call DMMGSetUser() after calling
 38:       this routine

 40:     Level: advanced

 42: .seealso DMMGDestroy(), DMMGSetUser(), DMMGGetUser(), DMMGSetMatType(),  DMMGSetNullSpace(), DMMGSetInitialGuess(),
 43:          DMMGSetISColoringType()

 45: @*/
 46: PetscErrorCode  DMMGCreate(MPI_Comm comm,PetscInt nlevels,void *user,DMMG **dmmg)
 47: {
 49:   PetscInt       i;
 50:   DMMG           *p;
 51:   PetscBool      ftype;
 52:   char           mtype[256];

 55:   if (nlevels < 0) {
 56:     nlevels = -nlevels;
 57:   } else {
 58:     PetscOptionsGetInt(0,"-dmmg_nlevels",&nlevels,PETSC_IGNORE);
 59:   }
 60:   if (nlevels < 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot set levels less than 1");

 62:   PetscMalloc(nlevels*sizeof(DMMG),&p);
 63:   for (i=0; i<nlevels; i++) {
 64:     PetscNew(struct _n_DMMG,&p[i]);
 65:     p[i]->nlevels  = nlevels - i;
 66:     p[i]->comm     = comm;
 67:     p[i]->user     = user;
 68:     p[i]->updatejacobianperiod = 1;
 69:     p[i]->updatejacobian       = PETSC_TRUE;
 70:     p[i]->isctype  = IS_COLORING_GLOBAL;
 71:     PetscStrallocpy(MATAIJ,&p[i]->mtype);
 72:   }
 73:   *dmmg = p;

 75:   PetscOptionsGetString(PETSC_NULL,"-dmmg_mat_type",mtype,256,&ftype);
 76:   if (ftype) {
 77:     DMMGSetMatType(*dmmg,mtype);
 78:   }
 79:   return(0);
 80: }

 84: /*@C
 85:     DMMGSetMatType - Sets the type of matrices that DMMG will create for its solvers.

 87:     This is being deprecated. Use KSPSetDM() for linear problems and SNESSetDM() for nonlinear problems. 
 88:     See src/ksp/ksp/examples/tutorials/ex45.c and src/snes/examples/tutorials/ex57.c 

 90:     Logically Collective on MPI_Comm 

 92:     Input Parameters:
 93: +    dmmg - the DMMG object created with DMMGCreate()
 94: -    mtype - the matrix type, defaults to MATAIJ

 96:     Level: intermediate

 98: .seealso DMMGDestroy(), DMMGSetUser(), DMMGGetUser(), DMMGCreate(), DMMGSetNullSpace()

100: @*/
101: PetscErrorCode  DMMGSetMatType(DMMG *dmmg,const MatType mtype)
102: {
103:   PetscInt       i;

107:   for (i=0; i<dmmg[0]->nlevels; i++) {
108:     PetscFree(dmmg[i]->mtype);
109:     PetscStrallocpy(mtype,&dmmg[i]->mtype);
110:   }
111:   return(0);
112: }

116: /*@C
117:     DMMGSetOptionsPrefix - Sets the prefix used for the solvers inside a DMMG

119:     This is being deprecated. Use KSPSetDM() for linear problems and SNESSetDM() for nonlinear problems. 
120:     See src/ksp/ksp/examples/tutorials/ex45.c and src/snes/examples/tutorials/ex57.c 

122:     Logically Collective on MPI_Comm 

124:     Input Parameters:
125: +    dmmg - the DMMG object created with DMMGCreate()
126: -    prefix - the prefix string

128:     Level: intermediate

130: .seealso DMMGDestroy(), DMMGSetUser(), DMMGGetUser(), DMMGCreate(), DMMGSetNullSpace()

132: @*/
133: PetscErrorCode  DMMGSetOptionsPrefix(DMMG *dmmg,const char prefix[])
134: {
135:   PetscInt       i;
137: 
139:   for (i=0; i<dmmg[0]->nlevels; i++) {
140:     PetscStrallocpy(prefix,&dmmg[i]->prefix);
141:   }
142:   return(0);
143: }

147: /*@C
148:     DMMGDestroy - Destroys a DM based multigrid solver object. 

150:     This is being deprecated. Use KSPSetDM() for linear problems and SNESSetDM() for nonlinear problems. 
151:     See src/ksp/ksp/examples/tutorials/ex45.c and src/snes/examples/tutorials/ex57.c 

153:     Collective on DMMG

155:     Input Parameter:
156: .    - the context

158:     Level: advanced

160: .seealso DMMGCreate()

162: @*/
163: PetscErrorCode  DMMGDestroy(DMMG *dmmg)
164: {
166:   PetscInt       i,nlevels = dmmg[0]->nlevels;

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

171:   for (i=1; i<nlevels; i++) {
172:     MatDestroy(&dmmg[i]->R);
173:   }
174:   for (i=0; i<nlevels; i++) {
175:     PetscFree(dmmg[i]->prefix);
176:     PetscFree(dmmg[i]->mtype);
177:     DMDestroy(&dmmg[i]->dm);
178:     VecDestroy(&dmmg[i]->x);
179:     VecDestroy(&dmmg[i]->b);
180:     VecDestroy(&dmmg[i]->r);
181:     VecDestroy(&dmmg[i]->work1);
182:     VecDestroy(&dmmg[i]->w);
183:     VecDestroy(&dmmg[i]->work2);
184:     VecDestroy(&dmmg[i]->lwork1);
185:     MatDestroy(&dmmg[i]->B);
186:     MatDestroy(&dmmg[i]->J);
187:     VecDestroy(&dmmg[i]->Rscale);
188:     MatFDColoringDestroy(&dmmg[i]->fdcoloring);
189:     if (dmmg[i]->ksp && !dmmg[i]->snes) {KSPDestroy(&dmmg[i]->ksp);}
190:     PetscObjectDestroy((PetscObject*)&dmmg[i]->snes);
191:     VecScatterDestroy(&dmmg[i]->inject);
192:     PetscFree(dmmg[i]);
193:   }
194:   PetscFree(dmmg);
195:   return(0);
196: }

200: /*@C
201:     DMMGSetDM - Sets the coarse grid information for the grids

203:     This is being deprecated. Use KSPSetDM() for linear problems and SNESSetDM() for nonlinear problems. 
204:     See src/ksp/ksp/examples/tutorials/ex45.c and src/snes/examples/tutorials/ex57.c 

206:     Logically Collective on DMMG and DM

208:     Input Parameter:
209: +   dmmg - the context
210: -   dm - the DMDA or DMComposite object

212:     Options Database Keys:
213: .   -dmmg_refine: Use the input problem as the coarse level and refine.
214: .   -dmmg_refine false: Use the input problem as the fine level and coarsen.

216:     Level: advanced

218: .seealso DMMGCreate(), DMMGDestroy(), DMMGSetMatType()

220: @*/
221: PetscErrorCode  DMMGSetDM(DMMG *dmmg, DM dm)
222: {
223:   PetscInt       nlevels     = dmmg[0]->nlevels;
224:   PetscBool      doRefine    = PETSC_TRUE;
225:   PetscInt       i;
226:   DM             *hierarchy;

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

232:   /* Create DM data structure for all the levels */
233:   PetscOptionsGetBool(PETSC_NULL, "-dmmg_refine", &doRefine, PETSC_IGNORE);
234:   PetscObjectReference((PetscObject) dm);
235:   PetscMalloc(nlevels*sizeof(DM),&hierarchy);
236:   if (doRefine) {
237:     DMRefineHierarchy(dm,nlevels-1,hierarchy);
238:     dmmg[0]->dm = dm;
239:     for(i=1; i<nlevels; ++i) {
240:       dmmg[i]->dm = hierarchy[i-1];
241:     }
242:   } else {
243:     dmmg[nlevels-1]->dm = dm;
244:     DMCoarsenHierarchy(dm,nlevels-1,hierarchy);
245:     for(i=0; i<nlevels-1; ++i) {
246:       dmmg[nlevels-2-i]->dm = hierarchy[i];
247:     }
248:   }
249:   PetscFree(hierarchy);
250:   /* Cleanup old structures (should use some private Destroy() instead) */
251:   for(i = 0; i < nlevels; ++i) {
252:     MatDestroy(&dmmg[i]->B);
253:     MatDestroy(&dmmg[i]->J);
254:   }

256:   /* Create work vectors and matrix for each level */
257:   for (i=0; i<nlevels; i++) {
258:     DMCreateGlobalVector(dmmg[i]->dm,&dmmg[i]->x);
259:     VecDuplicate(dmmg[i]->x,&dmmg[i]->b);
260:     VecDuplicate(dmmg[i]->x,&dmmg[i]->r);
261:   }

263:   /* Create interpolation/restriction between levels */
264:   for (i=1; i<nlevels; i++) {
265:     DMGetInterpolation(dmmg[i-1]->dm,dmmg[i]->dm,&dmmg[i]->R,PETSC_NULL);
266:   }
267:   return(0);
268: }


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

276:     This is being deprecated. Use KSPSetDM() for linear problems and SNESSetDM() for nonlinear problems. 
277:     See src/ksp/ksp/examples/tutorials/ex45.c and src/snes/examples/tutorials/ex57.c 

279:     Collective on DMMG

281:     Input Parameter:
282: .   dmmg - the context

284:     Level: advanced

286:     Options Database:
287: +   -dmmg_grid_sequence - use grid sequencing to get the initial solution for each level from the previous
288: -   -dmmg_monitor_solution - display the solution at each iteration

290:      Notes: For linear (KSP) problems may be called more than once, uses the same 
291:     matrices but recomputes the right hand side for each new solve. Call DMMGSetKSP()
292:     to generate new matrices.
293:  
294: .seealso DMMGCreate(), DMMGDestroy(), DMMG, DMMGSetSNES(), DMMGSetKSP(), DMMGSetUp(), DMMGSetMatType()

296: @*/
297: PetscErrorCode  DMMGSolve(DMMG *dmmg)
298: {
300:   PetscInt       i,nlevels = dmmg[0]->nlevels;
301:   PetscBool      gridseq = PETSC_FALSE,vecmonitor = PETSC_FALSE,flg;

304:   PetscOptionsGetBool(0,"-dmmg_grid_sequence",&gridseq,PETSC_NULL);
305:   PetscOptionsGetBool(0,"-dmmg_monitor_solution",&vecmonitor,PETSC_NULL);
306:   if (gridseq) {
307:     if (dmmg[0]->initialguess) {
308:       (*dmmg[0]->initialguess)(dmmg[0],dmmg[0]->x);
309:       if (dmmg[0]->ksp && !dmmg[0]->snes) {
310:         KSPSetInitialGuessNonzero(dmmg[0]->ksp,PETSC_TRUE);
311:       }
312:     }
313:     for (i=0; i<nlevels-1; i++) {
314:       (*dmmg[i]->solve)(dmmg,i);
315:       if (vecmonitor) {
316:         VecView(dmmg[i]->x,PETSC_VIEWER_DRAW_(dmmg[i]->comm));
317:       }
318:       MatInterpolate(dmmg[i+1]->R,dmmg[i]->x,dmmg[i+1]->x);
319:       if (dmmg[i+1]->ksp && !dmmg[i+1]->snes) {
320:         KSPSetInitialGuessNonzero(dmmg[i+1]->ksp,PETSC_TRUE);
321:      }
322:     }
323:   } else {
324:     if (dmmg[nlevels-1]->initialguess) {
325:       (*dmmg[nlevels-1]->initialguess)(dmmg[nlevels-1],dmmg[nlevels-1]->x);
326:     }
327:   }

329:   /*VecView(dmmg[nlevels-1]->x,PETSC_VIEWER_DRAW_WORLD);*/

331:   (*DMMGGetFine(dmmg)->solve)(dmmg,nlevels-1);
332:   if (vecmonitor) {
333:      VecView(dmmg[nlevels-1]->x,PETSC_VIEWER_DRAW_(dmmg[nlevels-1]->comm));
334:   }

336:   flg  = PETSC_FALSE;
337:   PetscOptionsGetBool(PETSC_NULL,"-dmmg_view",&flg,PETSC_NULL);
338:   if (flg && !PetscPreLoadingOn) {
339:     PetscViewer viewer;
340:     PetscViewerASCIIGetStdout(dmmg[0]->comm,&viewer);
341:     DMMGView(dmmg,viewer);
342:   }
343:   flg  = PETSC_FALSE;
344:   PetscOptionsGetBool(PETSC_NULL,"-dmmg_view_binary",&flg,PETSC_NULL);
345:   if (flg && !PetscPreLoadingOn) {
346:     DMMGView(dmmg,PETSC_VIEWER_BINARY_(dmmg[0]->comm));
347:   }
348:   return(0);
349: }

353: PetscErrorCode  DMMGSolveKSP(DMMG *dmmg,PetscInt level)
354: {

358:   if (dmmg[level]->rhs) {
359:     CHKMEMQ;
360:     (*dmmg[level]->rhs)(dmmg[level],dmmg[level]->b);
361:     CHKMEMQ;
362:   }
363:   KSPSolve(dmmg[level]->ksp,dmmg[level]->b,dmmg[level]->x);
364:   return(0);
365: }

367: /*
368:     For each level (of grid sequencing) this sets the interpolation/restriction and 
369:     work vectors needed by the multigrid preconditioner within the KSP 
370:     (for nonlinear problems the KSP inside the SNES) of that level.

372:     Also sets the KSP monitoring on all the levels if requested by user.

374: */
377: PetscErrorCode  DMMGSetUpLevel(DMMG *dmmg,KSP ksp,PetscInt nlevels)
378: {
379:   PetscErrorCode          ierr;
380:   PetscInt                i;
381:   PC                      pc;
382:   PetscBool               ismg,ismf,isshell,ismffd;
383:   KSP                     lksp; /* solver internal to the multigrid preconditioner */
384:   MPI_Comm                *comms;

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

389:   /* use fgmres on outer iteration by default */
390:   KSPSetType(ksp,KSPFGMRES);
391:   KSPGetPC(ksp,&pc);
392:   PCSetType(pc,PCMG);
393:   PetscMalloc(nlevels*sizeof(MPI_Comm),&comms);
394:   for (i=0; i<nlevels; i++) {
395:     comms[i] = dmmg[i]->comm;
396:   }
397:   PCMGSetLevels(pc,nlevels,comms);
398:   PetscFree(comms);
399:    PCMGSetType(pc,PC_MG_FULL);

401:   PetscTypeCompare((PetscObject)pc,PCMG,&ismg);
402:   if (ismg) {
403:     /* set solvers for each level */
404:     for (i=0; i<nlevels; i++) {
405:       if (i < nlevels-1) { /* don't set for finest level, they are set in PCApply_MG()*/
406:         PCMGSetX(pc,i,dmmg[i]->x);
407:         PCMGSetRhs(pc,i,dmmg[i]->b);
408:       }
409:       if (i > 0) {
410:         PCMGSetR(pc,i,dmmg[i]->r);
411:       }
412:       /* If using a matrix free multiply and did not provide an explicit matrix to build
413:          the preconditioner then must use no preconditioner 
414:       */
415:       PetscTypeCompare((PetscObject)dmmg[i]->B,MATSHELL,&isshell);
416:       PetscTypeCompare((PetscObject)dmmg[i]->B,MATDAAD,&ismf);
417:       PetscTypeCompare((PetscObject)dmmg[i]->B,MATMFFD,&ismffd);
418:       if (isshell || ismf || ismffd) {
419:         PC  lpc;
420:         PCMGGetSmoother(pc,i,&lksp);
421:         KSPGetPC(lksp,&lpc);
422:         PCSetType(lpc,PCNONE);
423:       }
424:     }

426:     /* Set interpolation/restriction between levels */
427:     for (i=1; i<nlevels; i++) {
428:       PCMGSetInterpolation(pc,i,dmmg[i]->R);
429:       PCMGSetRestriction(pc,i,dmmg[i]->R);
430:     }
431:   }
432:   return(0);
433: }

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

440:     This is being deprecated. Use KSPSetDM() for linear problems and SNESSetDM() for nonlinear problems. 
441:     See src/ksp/ksp/examples/tutorials/ex45.c and src/snes/examples/tutorials/ex57.c 

443:     Logically Collective on DMMG

445:     Input Parameter:
446: +   dmmg - the context
447: .   func - function to compute linear system matrix on each grid level
448: -   rhs - function to compute right hand side on each level (need only work on the finest grid
449:           if you do not use grid sequencing)

451:     Level: advanced

453:     Notes: For linear problems my be called more than once, reevaluates the matrices if it is called more
454:        than once. Call DMMGSolve() directly several times to solve with the same matrix but different 
455:        right hand sides.
456:    
457: .seealso DMMGCreate(), DMMGDestroy, DMMGSetDM(), DMMGSolve(), DMMGSetMatType()

459: @*/
460: PetscErrorCode  DMMGSetKSP(DMMG *dmmg,PetscErrorCode (*rhs)(DMMG,Vec),PetscErrorCode (*func)(DMMG,Mat,Mat))
461: {
463:   PetscInt       i,nlevels = dmmg[0]->nlevels,level;
464:   PetscBool      ismg,galerkin=PETSC_FALSE;
465:   PC             pc;
466:   KSP            lksp;
467: 
469:   if (!dmmg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Passing null as DMMG");

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

475:       KSPCreate(dmmg[i]->comm,&dmmg[i]->ksp);
476:       PetscObjectIncrementTabLevel((PetscObject)dmmg[i]->ksp,PETSC_NULL,nlevels-i);
477:       KSPSetOptionsPrefix(dmmg[i]->ksp,dmmg[i]->prefix);
478:       DMMGSetUpLevel(dmmg,dmmg[i]->ksp,i+1);
479:       KSPSetFromOptions(dmmg[i]->ksp);

481:       /*  if the multigrid is being run with Galerkin then these matrices do not need to be created except on the finest level
482:           we do not take advantage of this because it may be that Galerkin has not yet been selected for the KSP object 
483:           These are also used if grid sequencing is selected for the linear problem. We should probably turn off grid sequencing
484:           for the linear problem */
485:       if (!dmmg[i]->B) {
486:         DMGetMatrix(dmmg[i]->dm,dmmg[nlevels-1]->mtype,&dmmg[i]->B);
487:       }
488:       if (!dmmg[i]->J) {
489:         dmmg[i]->J = dmmg[i]->B;
490:         PetscObjectReference((PetscObject) dmmg[i]->J);
491:       }

493:       dmmg[i]->solve = DMMGSolveKSP;
494:       dmmg[i]->rhs   = rhs;
495:     }
496:   }

498:   /* evalute matrix on each level */
499:   KSPGetPC(dmmg[nlevels-1]->ksp,&pc);
500:   PetscTypeCompare((PetscObject)pc,PCMG,&ismg);
501:   if (ismg) {
502:     PCMGGetGalerkin(pc,&galerkin);
503:   }
504:   if (func) {
505:     if (galerkin) {
506:       (*func)(dmmg[nlevels-1],dmmg[nlevels-1]->J,dmmg[nlevels-1]->B);
507:     } else {
508:       for (i=0; i<nlevels; i++) {
509:         (*func)(dmmg[i],dmmg[i]->J,dmmg[i]->B);
510:       }
511:     }
512:   }

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

518:   for (level=0; level<nlevels; level++) {
519:     KSPSetOperators(dmmg[level]->ksp,dmmg[level]->J,dmmg[level]->B,SAME_NONZERO_PATTERN);
520:     KSPGetPC(dmmg[level]->ksp,&pc);
521:     if (ismg) {
522:       for (i=0; i<=level; i++) {
523:         PCMGGetSmoother(pc,i,&lksp);
524:         KSPSetOperators(lksp,dmmg[i]->J,dmmg[i]->B,SAME_NONZERO_PATTERN);
525:       }
526:     }
527:   }

529:   return(0);
530: }

534: /*@C
535:     DMMGView - prints information on a DM based multi-level preconditioner

537:     This is being deprecated. Use KSPSetDM() for linear problems and SNESSetDM() for nonlinear problems. 
538:     See src/ksp/ksp/examples/tutorials/ex45.c and src/snes/examples/tutorials/ex57.c 

540:     Collective on DMMG and PetscViewer

542:     Input Parameter:
543: +   dmmg - the context
544: -   viewer - the viewer

546:     Level: advanced

548: .seealso DMMGCreate(), DMMGDestroy(), DMMGSetMatType()

550: @*/
551: PetscErrorCode  DMMGView(DMMG *dmmg,PetscViewer viewer)
552: {
554:   PetscInt       i,nlevels = dmmg[0]->nlevels;
555:   PetscMPIInt    flag;
556:   MPI_Comm       comm;
557:   PetscBool      iascii,isbinary;

562:   PetscObjectGetComm((PetscObject)viewer,&comm);
563:   MPI_Comm_compare(comm,dmmg[0]->comm,&flag);
564:   if (flag != MPI_CONGRUENT && flag != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"Different communicators in the DMMG and the PetscViewer");

566:   PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
567:   PetscTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);
568:   if (isbinary) {
569:     for (i=0; i<nlevels; i++) {
570:       MatView(dmmg[i]->J,viewer);
571:     }
572:     for (i=1; i<nlevels; i++) {
573:       MatView(dmmg[i]->R,viewer);
574:     }
575:   } else {
576:     if (iascii) {
577:       PetscViewerASCIIPrintf(viewer,"DMMG Object with %D levels\n",nlevels);
578:       if (dmmg[0]->isctype == IS_COLORING_GLOBAL) {
579:         PetscViewerASCIIPrintf(viewer,"Using global (nonghosted) Jacobian coloring computation\n");
580:       } else {
581:         PetscViewerASCIIPrintf(viewer,"Using ghosted Jacobian coloring computation\n");
582:       }
583:     }
584:     for (i=0; i<nlevels; i++) {
585:       PetscViewerASCIIPushTab(viewer);
586:       DMView(dmmg[i]->dm,viewer);
587:       PetscViewerASCIIPopTab(viewer);
588:     }
589:     if (iascii) {
590:       PetscViewerASCIIPrintf(viewer,"Using matrix type %s\n",dmmg[nlevels-1]->mtype);
591:     }
592:     if (DMMGGetKSP(dmmg)) {
593:       KSPView(DMMGGetKSP(dmmg),viewer);
594:     } else if (DMMGGetSNES(dmmg)) {
595:       SNESView(DMMGGetSNES(dmmg),viewer);
596:     } else if (iascii) {
597:       PetscViewerASCIIPrintf(viewer,"DMMG does not have a SNES or KSP set\n");
598:     }
599:   }
600:   return(0);
601: }

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

608:     This is being deprecated. Use KSPSetDM() for linear problems and SNESSetDM() for nonlinear problems. 
609:     See src/ksp/ksp/examples/tutorials/ex45.c and src/snes/examples/tutorials/ex57.c 

611:     Logically Collective on DMMG

613:     Input Parameter:
614: +   dmmg - the context
615: .   has_cnst - is the constant vector in the null space
616: .   n - number of null vectors (excluding the possible constant vector)
617: -   func - a function that fills an array of vectors with the null vectors (must be orthonormal), may be PETSC_NULL

619:     Level: advanced

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

623: @*/
624: PetscErrorCode  DMMGSetNullSpace(DMMG *dmmg,PetscBool  has_cnst,PetscInt n,PetscErrorCode (*func)(DMMG,Vec[]))
625: {
627:   PetscInt       i,j,nlevels = dmmg[0]->nlevels;
628:   Vec            *nulls = 0;
629:   MatNullSpace   nullsp;
630:   KSP            iksp;
631:   PC             pc,ipc;
632:   PetscBool      ismg,isred;

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

640:   for (i=0; i<nlevels; i++) {
641:     if (n) {
642:       VecDuplicateVecs(dmmg[i]->b,n,&nulls);
643:       (*func)(dmmg[i],nulls);
644:     }
645:     MatNullSpaceCreate(dmmg[i]->comm,has_cnst,n,nulls,&nullsp);
646:     KSPSetNullSpace(dmmg[i]->ksp,nullsp);
647:     for (j=i; j<nlevels; j++) {
648:       KSPGetPC(dmmg[j]->ksp,&pc);
649:       PetscTypeCompare((PetscObject)pc,PCMG,&ismg);
650:       if (ismg) {
651:         PCMGGetSmoother(pc,i,&iksp);
652:         KSPSetNullSpace(iksp, nullsp);
653:       }
654:     }
655:     MatNullSpaceDestroy(&nullsp);
656:     if (n) {
657:       VecDestroyVecs(n,&nulls);
658:     }
659:   }
660:   /* make all the coarse grid solvers have LU shift since they are singular */
661:   for (i=0; i<nlevels; i++) {
662:     KSPGetPC(dmmg[i]->ksp,&pc);
663:     PetscTypeCompare((PetscObject)pc,PCMG,&ismg);
664:     if (ismg) {
665:       PCMGGetSmoother(pc,0,&iksp);
666:       KSPGetPC(iksp,&ipc);
667:       PetscTypeCompare((PetscObject)ipc,PCREDUNDANT,&isred);
668:       if (isred) {
669:         KSP iksp;
670:         PCRedundantGetKSP(ipc,&iksp);
671:         KSPGetPC(iksp,&ipc);
672:       }
673:       PCFactorSetShiftType(ipc,MAT_SHIFT_POSITIVE_DEFINITE);
674:     }
675:   }
676:   return(0);
677: }

681: /*@C
682:     DMMGInitialGuessCurrent - Use with DMMGSetInitialGuess() to use the current value in the 
683:        solution vector (obtainable with DMMGGetx()) as the initial guess. Otherwise for linear
684:        problems zero is used for the initial guess (unless grid sequencing is used). For nonlinear 
685:        problems this is not needed; it always uses the previous solution as the initial guess.

687:     This is being deprecated. Use KSPSetDM() for linear problems and SNESSetDM() for nonlinear problems. 
688:     See src/ksp/ksp/examples/tutorials/ex45.c and src/snes/examples/tutorials/ex57.c 

690:     Logically Collective on DMMG

692:     Input Parameter:
693: +   dmmg - the context
694: -   vec - dummy argument

696:     Level: intermediate

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

700: @*/
701: PetscErrorCode  DMMGInitialGuessCurrent(DMMG dmmg,Vec vec)
702: {
704:   return(0);
705: }

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

712:     This is being deprecated. Use KSPSetDM() for linear problems and SNESSetDM() for nonlinear problems. 
713:     See src/ksp/ksp/examples/tutorials/ex45.c and src/snes/examples/tutorials/ex57.c 

715:     Logically Collective on DMMG

717:     Input Parameter:
718: +   dmmg - the context
719: -   guess - the function

721:     Notes: For nonlinear problems, if this is not set, then the current value in the 
722:              solution vector (obtained with DMMGGetX()) is used. Thus is if you doing 'time
723:              stepping' it will use your current solution as the guess for the next timestep.
724:            If grid sequencing is used (via -dmmg_grid_sequence) then the "guess" function
725:              is used only on the coarsest grid.
726:            For linear problems, if this is not set, then 0 is used as an initial guess.
727:              If you would like the linear solver to also (like the nonlinear solver) use
728:              the current solution vector as the initial guess then use DMMGInitialGuessCurrent()
729:              as the function you pass in

731:     Level: intermediate


734: .seealso DMMGCreate(), DMMGDestroy, DMMGSetKSP(), DMMGSetSNES(), DMMGInitialGuessCurrent(), DMMGSetGalekin(), DMMGSetMatType(), DMMGSetNullSpace()

736: @*/
737: PetscErrorCode  DMMGSetInitialGuess(DMMG *dmmg,PetscErrorCode (*guess)(DMMG,Vec))
738: {
739:   PetscInt       i,nlevels = dmmg[0]->nlevels;

743:   for (i=0; i<nlevels; i++) {
744:     if (dmmg[i]->ksp && !dmmg[i]->snes) {
745:       KSPSetInitialGuessNonzero(dmmg[i]->ksp,PETSC_TRUE);
746:     }
747:     dmmg[i]->initialguess = guess;
748:   }
749:   return(0);
750: }