Actual source code: damgsnes.c

  2: #include <petscdmda.h>      /*I      "petscdmda.h"    I*/
  3: #include <petscdmmesh.h>    /*I      "petscdmmesh.h"  I*/
  4: #include <private/daimpl.h> 
  5: /* It appears that preprocessor directives are not respected by bfort */
  6: #include <petscpcmg.h>      /*I      "petscpcmg.h"    I*/
  7: #include <petscdmmg.h>    /*I      "petscdmmg.h"  I*/

  9: #if defined(PETSC_HAVE_ADIC)
 16: #endif


 26: /*
 27:       period of -1 indicates update only on zeroth iteration of SNES
 28: */
 29: #define ShouldUpdate(l,it) (((dmmg[l-1]->updatejacobianperiod == -1) && (it == 0)) || \
 30:                             ((dmmg[l-1]->updatejacobianperiod >   0) && !(it % dmmg[l-1]->updatejacobianperiod)))
 31: /*
 32:    Evaluates the Jacobian on all of the grids. It is used by DMMG to provide the 
 33:    ComputeJacobian() function that SNESSetJacobian() requires.
 34: */
 37: PetscErrorCode DMMGComputeJacobian_Multigrid(SNES snes,Vec X,Mat *J,Mat *B,MatStructure *flag,void *ptr)
 38: {
 39:   DMMG           *dmmg = (DMMG*)ptr;
 41:   PetscInt       i,nlevels = dmmg[0]->nlevels,it;
 42:   KSP            ksp,lksp;
 43:   PC             pc;
 44:   PetscBool      ismg,galerkin = PETSC_FALSE;
 45:   Vec            W;
 46:   MatStructure   flg;

 49:   if (!dmmg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Passing null as user context which should contain DMMG");
 50:   SNESGetIterationNumber(snes,&it);

 52:   /* compute Jacobian on finest grid */
 53:   if (dmmg[nlevels-1]->updatejacobian && ShouldUpdate(nlevels,it)) {
 54:     (*DMMGGetFine(dmmg)->computejacobian)(snes,X,J,B,flag,DMMGGetFine(dmmg));
 55:   } else {
 56:     PetscInfo3(0,"Skipping Jacobian, SNES iteration %D frequence %D level %D\n",it,dmmg[nlevels-1]->updatejacobianperiod,nlevels-1);
 57:     *flag = SAME_PRECONDITIONER;
 58:   }
 59:   MatMFFDSetBase(DMMGGetFine(dmmg)->J,X,PETSC_NULL);

 61:   /* create coarser grid Jacobians for preconditioner if multigrid is the preconditioner */
 62:   SNESGetKSP(snes,&ksp);
 63:   KSPGetPC(ksp,&pc);
 64:   PetscTypeCompare((PetscObject)pc,PCMG,&ismg);
 65:   if (ismg) {
 66:     PCMGGetGalerkin(pc,&galerkin);
 67:   }

 69:   if (!galerkin) {
 70:     for (i=nlevels-1; i>0; i--) {
 71:       if (!dmmg[i-1]->w) {
 72:         VecDuplicate(dmmg[i-1]->x,&dmmg[i-1]->w);
 73:       }
 74:       W    = dmmg[i-1]->w;
 75:       /* restrict X to coarser grid */
 76:       MatRestrict(dmmg[i]->R,X,W);
 77:       X    = W;
 78:       /* scale to "natural" scaling for that grid */
 79:       VecPointwiseMult(X,X,dmmg[i]->Rscale);
 80:       /* tell the base vector for matrix free multiplies */
 81:       MatMFFDSetBase(dmmg[i-1]->J,X,PETSC_NULL);
 82:       /* compute Jacobian on coarse grid */
 83:       if (dmmg[i-1]->updatejacobian && ShouldUpdate(i,it)) {
 84:         (*dmmg[i-1]->computejacobian)(snes,X,&dmmg[i-1]->J,&dmmg[i-1]->B,&flg,dmmg[i-1]);
 85:         flg = SAME_NONZERO_PATTERN;
 86:       } else {
 87:         PetscInfo3(0,"Skipping Jacobian, SNES iteration %D frequence %D level %D\n",it,dmmg[i-1]->updatejacobianperiod,i-1);
 88:         flg = SAME_PRECONDITIONER;
 89:       }
 90:       if (ismg) {
 91:         PCMGGetSmoother(pc,i-1,&lksp);
 92:         KSPSetOperators(lksp,dmmg[i-1]->J,dmmg[i-1]->B,flg);
 93:       }
 94:     }
 95:   }
 96:   return(0);
 97: }

 99: /* ---------------------------------------------------------------------------*/


104: /* 
105:    DMMGFormFunction - This is a universal global FormFunction used by the DMMG code
106:    when the user provides a local function.

108:    Input Parameters:
109: +  snes - the SNES context
110: .  X - input vector
111: -  ptr - optional user-defined context, as set by SNESSetFunction()

113:    Output Parameter:
114: .  F - function vector

116:  */
117: PetscErrorCode DMMGFormFunction(SNES snes,Vec X,Vec F,void *ptr)
118: {
119:   DMMG           dmmg = (DMMG)ptr;
121:   Vec            localX;
122:   DM             da = dmmg->dm;

125:   DMGetLocalVector(da,&localX);
126:   /*
127:      Scatter ghost points to local vector, using the 2-step process
128:         DMGlobalToLocalBegin(), DMGlobalToLocalEnd().
129:   */
130:   DMGlobalToLocalBegin(da,X,INSERT_VALUES,localX);
131:   DMGlobalToLocalEnd(da,X,INSERT_VALUES,localX);
132:   DMDAFormFunction1(da,localX,F,dmmg->user);
133:   DMRestoreLocalVector(da,&localX);
134:   return(0);
135: }

139: PetscErrorCode DMMGFormFunctionGhost(SNES snes,Vec X,Vec F,void *ptr)
140: {
141:   DMMG           dmmg = (DMMG)ptr;
143:   Vec            localX, localF;
144:   DM             da = dmmg->dm;

147:   DMGetLocalVector(da,&localX);
148:   DMGetLocalVector(da,&localF);
149:   /*
150:      Scatter ghost points to local vector, using the 2-step process
151:         DMGlobalToLocalBegin(), DMGlobalToLocalEnd().
152:   */
153:   DMGlobalToLocalBegin(da,X,INSERT_VALUES,localX);
154:   DMGlobalToLocalEnd(da,X,INSERT_VALUES,localX);
155:   VecSet(F, 0.0);
156:   VecSet(localF, 0.0);
157:   DMDAFormFunction1(da,localX,localF,dmmg->user);
158:   DMLocalToGlobalBegin(da,localF,ADD_VALUES,F);
159:   DMLocalToGlobalEnd(da,localF,ADD_VALUES,F);
160:   DMRestoreLocalVector(da,&localX);
161:   DMRestoreLocalVector(da,&localF);
162:   return(0);
163: }

167: /* 
168:    DMMGFormFunctionFD - This is a universal global FormFunction used by the DMMG code
169:    when the user provides a local function used to compute the Jacobian via FD.

171:    Input Parameters:
172: +  snes - the SNES context
173: .  X - input vector
174: -  ptr - optional user-defined context, as set by SNESSetFunction()

176:    Output Parameter:
177: .  F - function vector

179:  */
180: PetscErrorCode DMMGFormFunctionFD(SNES snes,Vec X,Vec F,void *ptr)
181: {
182:   DMMG           dmmg = (DMMG)ptr;
184:   Vec            localX;
185:   DM             da = dmmg->dm;
186:   PetscInt       N,n;
187: 
189:   /* determine whether X=localX */
190:   DMGetLocalVector(da,&localX);
191:   VecGetSize(X,&N);
192:   VecGetSize(localX,&n);

194:   if (n != N){ /* X != localX */
195:     /* Scatter ghost points to local vector, using the 2-step process
196:        DMGlobalToLocalBegin(), DMGlobalToLocalEnd().
197:     */
198:     DMGlobalToLocalBegin(da,X,INSERT_VALUES,localX);
199:     DMGlobalToLocalEnd(da,X,INSERT_VALUES,localX);
200:   } else {
201:     DMRestoreLocalVector(da,&localX);
202:     localX = X;
203:   }
204:   DMDAFormFunction(da,dmmg->lfj,localX,F,dmmg->user);
205:   if (n != N){
206:     DMRestoreLocalVector(da,&localX);
207:   }
208:   return(0);
209: }

211: #include <private/snesimpl.h>

215: /*@C 
216:    SNESDAFormFunction - This is a universal function evaluation routine that
217:    may be used with SNESSetFunction(). Must be used with SNESSetDM().

219:    Collective on SNES

221:    Input Parameters:
222: +  snes - the SNES context
223: .  X - input vector
224: .  F - function vector
225: -  ptr - pointer to a user context containing problem specific information used by application function

227:    Level: intermediate

229: .seealso: DMDASetLocalFunction(), DMDASetLocalJacobian(), DMDASetLocalAdicFunction(), DMDASetLocalAdicMFFunction(),
230:           SNESSetFunction(), SNESSetJacobian(), SNESSetDM()

232: @*/
233: PetscErrorCode  SNESDAFormFunction(SNES snes,Vec X,Vec F,void *ptr)
234: {
236:   Vec            localX;
237:   DM             da = snes->dm;
238:   PetscInt       N,n;
239: 
241:   if (!da) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Looks like you called SNESSetFuntion(snes,SNESDAFormFunction,) without also calling SNESSetDM() to set the DMDA context");

243:   /* determine whether X=localX */
244:   DMGetLocalVector(da,&localX);
245:   VecGetSize(X,&N);
246:   VecGetSize(localX,&n);
247: 
248: 
249:   if (n != N){ /* X != localX */
250:     /* Scatter ghost points to local vector, using the 2-step process
251:         DMGlobalToLocalBegin(), DMGlobalToLocalEnd().
252:     */
253:     DMGlobalToLocalBegin(da,X,INSERT_VALUES,localX);
254:     DMGlobalToLocalEnd(da,X,INSERT_VALUES,localX);
255:   } else {
256:     DMRestoreLocalVector(da,&localX);
257:     localX = X;
258:   }
259:   DMDAFormFunction1(da,localX,F,ptr);
260:   if (n != N){
261:     DMRestoreLocalVector(da,&localX);
262:   }
263:   return(0);
264: }

266: #if defined(PETSC_HAVE_SIEVE)
269: /*@C
270:   SNESMeshFormFunction - This is a universal function evaluation routine that
271:   may be used with SNESSetFunction() as long as the user context has a DMMesh
272:   as its first record and the user has called DMMeshSetLocalFunction().

274:   Collective on SNES

276:   Input Parameters:
277: + snes - the SNES context
278: . X - input vector
279: . F - function vector
280: - ptr - pointer to a structure that must have a DMMesh as its first entry.
281:         This ptr must have been passed into SNESMeshFormFunction() as the context.

283:   Level: intermediate

285: .seealso: DMMeshSetLocalFunction(), DMMeshSetLocalJacobian(), SNESSetFunction(), SNESSetJacobian()
286: @*/
287: PetscErrorCode SNESMeshFormFunction(SNES snes, Vec X, Vec F, void *ptr)
288: {
289:   DM               dm = *(DM*) ptr;
290:   PetscErrorCode (*lf)(DM, Vec, Vec, void *);
291:   Vec              localX, localF;
292:   PetscInt         N, n;
293:   PetscErrorCode   ierr;

299:   if (!dm) SETERRQ(((PetscObject)snes)->comm, PETSC_ERR_ARG_WRONGSTATE, "Looks like you called SNESSetFromFuntion(snes,SNESMeshFormFunction,) without the DMMesh context");

302:   /* determine whether X = localX */
303:   DMGetLocalVector(dm, &localX);
304:   DMGetLocalVector(dm, &localF);
305:   VecGetSize(X, &N);
306:   VecGetSize(localX, &n);

308:   if (n != N){ /* X != localX */
309:     /* Scatter ghost points to local vector, using the 2-step process
310:         DMGlobalToLocalBegin(), DMGlobalToLocalEnd().
311:     */
312:     DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);
313:     DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);
314:   } else {
315:     DMRestoreLocalVector(dm, &localX);
316:     localX = X;
317:   }
318:   DMMeshGetLocalFunction(dm, &lf);
319:   (*lf)(dm, localX, localF, ptr);
320:   if (n != N){
321:     DMRestoreLocalVector(dm, &localX);
322:   }
323:   DMLocalToGlobalBegin(dm, localF, ADD_VALUES, F);
324:   DMLocalToGlobalEnd(dm, localF, ADD_VALUES, F);
325:   DMRestoreLocalVector(dm, &localF);
326:   return(0);
327: }
328: #endif

330: #if defined(PETSC_HAVE_SIEVE)
333: /*
334:   SNESMeshFormJacobian - This is a universal Jacobian evaluation routine that
335:   may be used with SNESSetJacobian() as long as the user context has a DMMesh
336:   as its first record and the user has called DMMeshSetLocalJacobian().

338:   Collective on SNES

340:   Input Parameters:
341: + snes - the SNES context
342: . X - input vector
343: . J - Jacobian
344: . B - Jacobian used in preconditioner (usally same as J)
345: . flag - indicates if the matrix changed its structure
346: - ptr - pointer to a structure that must have a DMMesh as its first entry.
347:         This ptr must have been passed into SNESMeshFormFunction() as the context.

349:   Level: intermediate

351: .seealso: DMMeshSetLocalFunction(), DMMeshSetLocalJacobian(), SNESSetFunction(), SNESSetJacobian()
352: */
353: PetscErrorCode SNESMeshFormJacobian(SNES snes, Vec X, Mat *J, Mat *B, MatStructure *flag, void *ptr)
354: {
355:   DM               dm = *(DM*) ptr;
356:   PetscErrorCode (*lj)(DM, Vec, Mat, void *);
357:   Vec              localX;
358:   PetscErrorCode   ierr;

361:   DMGetLocalVector(dm, &localX);
362:   DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);
363:   DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);
364:   DMMeshGetLocalJacobian(dm, &lj);
365:   (*lj)(dm, localX, *B, ptr);
366:   DMRestoreLocalVector(dm, &localX);
367:   /* Assemble true Jacobian; if it is different */
368:   if (*J != *B) {
369:     MatAssemblyBegin(*J, MAT_FINAL_ASSEMBLY);
370:     MatAssemblyEnd(*J, MAT_FINAL_ASSEMBLY);
371:   }
372:   MatSetOption(*B, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE);
373:   *flag = SAME_NONZERO_PATTERN;
374:   return(0);
375: }
376: #endif

378: /* ------------------------------------------------------------------------------*/
379: #include <private/matimpl.h>        /*I "petscmat.h" I*/
382: PetscErrorCode DMMGComputeJacobianWithFD(SNES snes,Vec x1,Mat *J,Mat *B,MatStructure *flag,void *ctx)
383: {
385:   DMMG           dmmg = (DMMG)ctx;
386:   MatFDColoring  color = (MatFDColoring)dmmg->fdcoloring;
387: 
389:   if (color->ctype == IS_COLORING_GHOSTED){
390:     DM            da=dmmg->dm;
391:     Vec           x1_loc;
392:     DMGetLocalVector(da,&x1_loc);
393:     DMGlobalToLocalBegin(da,x1,INSERT_VALUES,x1_loc);
394:     DMGlobalToLocalEnd(da,x1,INSERT_VALUES,x1_loc);
395:     SNESDefaultComputeJacobianColor(snes,x1_loc,J,B,flag,dmmg->fdcoloring);
396:     DMRestoreLocalVector(da,&x1_loc);
397:   } else {
398:     SNESDefaultComputeJacobianColor(snes,x1,J,B,flag,dmmg->fdcoloring);
399:   }
400:   return(0);
401: }

405: PetscErrorCode DMMGComputeJacobianWithMF(SNES snes,Vec x1,Mat *J,Mat *B,MatStructure *flag,void *ctx)
406: {
408: 
410:   MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);
411:   MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);
412:   return(0);
413: }

417: /*
418:     DMMGComputeJacobian - Evaluates the Jacobian when the user has provided
419:     a local function evaluation routine.
420: */
421: PetscErrorCode DMMGComputeJacobian(SNES snes,Vec X,Mat *J,Mat *B,MatStructure *flag,void *ptr)
422: {
423:   DMMG           dmmg = (DMMG) ptr;
425:   Vec            localX;
426:   DM             da =  dmmg->dm;

429:   DMGetLocalVector(da,&localX);
430:   DMGlobalToLocalBegin(da,X,INSERT_VALUES,localX);
431:   DMGlobalToLocalEnd(da,X,INSERT_VALUES,localX);
432:   DMDAComputeJacobian1(da,localX,*B,dmmg->user);
433:   DMRestoreLocalVector(da,&localX);
434:   /* Assemble true Jacobian; if it is different */
435:   if (*J != *B) {
436:     MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);
437:     MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);
438:   }
439:   MatSetOption(*B,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);
440:   *flag = SAME_NONZERO_PATTERN;
441:   return(0);
442: }

446: /*
447:     SNESDAComputeJacobianWithAdifor - This is a universal Jacobian evaluation routine
448:     that may be used with SNESSetJacobian() from Fortran as long as the user context has 
449:     a DMDA as its first record and DMDASetLocalAdiforFunction() has been called.  

451:    Collective on SNES

453:    Input Parameters:
454: +  snes - the SNES context
455: .  X - input vector
456: .  J - Jacobian
457: .  B - Jacobian used in preconditioner (usally same as J)
458: .  flag - indicates if the matrix changed its structure
459: -  ptr - optional user-defined context, as set by SNESSetFunction()

461:    Level: intermediate

463: .seealso: DMDASetLocalFunction(), DMDASetLocalAdicFunction(), SNESSetFunction(), SNESSetJacobian()

465: */
466: PetscErrorCode  SNESDAComputeJacobianWithAdifor(SNES snes,Vec X,Mat *J,Mat *B,MatStructure *flag,void *ptr)
467: {
468:   DM             da = *(DM*) ptr;
470:   Vec            localX;

473:   DMGetLocalVector(da,&localX);
474:   DMGlobalToLocalBegin(da,X,INSERT_VALUES,localX);
475:   DMGlobalToLocalEnd(da,X,INSERT_VALUES,localX);
476:   DMDAComputeJacobian1WithAdifor(da,localX,*B,ptr);
477:   DMRestoreLocalVector(da,&localX);
478:   /* Assemble true Jacobian; if it is different */
479:   if (*J != *B) {
480:     MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);
481:     MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);
482:   }
483:   MatSetOption(*B,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);
484:   *flag = SAME_NONZERO_PATTERN;
485:   return(0);
486: }

490: /*
491:    SNESDAComputeJacobian - This is a universal Jacobian evaluation routine for a
492:    locally provided Jacobian. Must be used with SNESSetDM().

494:    Collective on SNES

496:    Input Parameters:
497: +  snes - the SNES context
498: .  X - input vector
499: .  J - Jacobian
500: .  B - Jacobian used in preconditioner (usally same as J)
501: .  flag - indicates if the matrix changed its structure
502: -  ptr - optional user-defined context, as set by SNESSetFunction()

504:    Level: intermediate

506: .seealso: DMDASetLocalFunction(), DMDASetLocalJacobian(), SNESSetFunction(), SNESSetJacobian(), SNESSetDM()

508: */
509: PetscErrorCode  SNESDAComputeJacobian(SNES snes,Vec X,Mat *J,Mat *B,MatStructure *flag,void *ptr)
510: {
511:   DM             da = snes->dm;
513:   Vec            localX;

516:   DMGetLocalVector(da,&localX);
517:   DMGlobalToLocalBegin(da,X,INSERT_VALUES,localX);
518:   DMGlobalToLocalEnd(da,X,INSERT_VALUES,localX);
519:   DMDAComputeJacobian1(da,localX,*B,ptr);
520:   DMRestoreLocalVector(da,&localX);
521:   /* Assemble true Jacobian; if it is different */
522:   if (*J != *B) {
523:     MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);
524:     MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);
525:   }
526:   MatSetOption(*B,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);
527:   *flag = SAME_NONZERO_PATTERN;
528:   return(0);
529: }

533: PetscErrorCode DMMGSolveSNES(DMMG *dmmg,PetscInt level)
534: {
536:   PetscInt       nlevels = dmmg[0]->nlevels;

539:   dmmg[0]->nlevels = level+1;
540:   SNESSolve(dmmg[level]->snes,PETSC_NULL,dmmg[level]->x);
541:   dmmg[0]->nlevels = nlevels;
542:   return(0);
543: }

545: /* ===========================================================================================================*/

549: /*@C
550:     DMMGSetSNES - Sets the nonlinear function that defines the nonlinear set of equations
551:     to be solved using the grid hierarchy.

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

556:     Collective on DMMG

558:     Input Parameter:
559: +   dmmg - the context
560: .   function - the function that defines the nonlinear system
561: -   jacobian - optional function to compute Jacobian

563:     Options Database Keys:
564: +    -snes_monitor
565: .    -dmmg_coloring_from_mat - use graph coloring on the actual matrix nonzero structure instead of getting the coloring from the DM
566: .    -dmmg_jacobian_fd
567: .    -dmmg_jacobian_ad
568: .    -dmmg_jacobian_mf_fd_operator
569: .    -dmmg_jacobian_mf_fd
570: .    -dmmg_jacobian_mf_ad_operator
571: .    -dmmg_jacobian_mf_ad
572: .    -dmmg_iscoloring_type
573: -
574:                                  The period at which the Jacobian is recomputed can be set differently for different levels
575:                                  of the Jacobian (for example lag all Jacobians except on the finest level).
576:                                  There is no user interface currently for setting a different period on the different levels, one must set the
577:                                  fields dmmg[i]->updatejacobian and dmmg[i]->updatejacobianperiod directly in the DMMG data structure.
578:                                  

580:     Level: advanced

582: .seealso DMMGCreate(), DMMGDestroy, DMMGSetKSP(), DMMGSetSNESLocal(), DMMGSetFromOptions()

584: @*/
585: PetscErrorCode  DMMGSetSNES(DMMG *dmmg,PetscErrorCode (*function)(SNES,Vec,Vec,void*),PetscErrorCode (*jacobian)(SNES,Vec,Mat*,Mat*,MatStructure*,void*))
586: {
587:   PetscErrorCode          ierr;
588:   PetscInt                i,nlevels = dmmg[0]->nlevels;
589:   PetscBool               mffdoperator,mffd,fdjacobian;
590:   PetscBool               useFAS = PETSC_FALSE, fasBlock=PETSC_FALSE, fasGMRES=PETSC_FALSE;
591:   PetscBool               monitor, monitorAll;
592:   PetscInt                fasPresmooth = 1, fasPostsmooth = 1, fasCoarsesmooth = 1, fasMaxIter = 2;
593:   PetscReal               fasRtol = 1.0e-8, fasAbstol = 1.0e-50;
594: #if defined(PETSC_HAVE_ADIC)
595:   PetscBool               mfadoperator,mfad,adjacobian;
596: #endif
597:   PetscClassId            classid;

600:   if (!dmmg)     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Passing null as DMMG");
601:   if (!jacobian) jacobian = DMMGComputeJacobianWithFD;
602:   PetscObjectGetClassId((PetscObject) dmmg[0]->dm, &classid);

604:   PetscOptionsBegin(dmmg[0]->comm,dmmg[0]->prefix,"DMMG Options","SNES");
605:     PetscOptionsName("-dmmg_monitor","Monitor DMMG iterations","DMMG",&monitor);
606:     PetscOptionsName("-dmmg_monitor_all","Monitor all DMMG iterations","DMMG",&monitorAll);
607:     /*
608:     PetscOptionsBool("-dmmg_fas","Use the Full Approximation Scheme","DMMGSetSNES",useFAS,&useFAS,PETSC_NULL);
609:     PetscOptionsName("-dmmg_fas_block","Use point-block smoothing","DMMG",&fasBlock);
610:     PetscOptionsName("-dmmg_fas_ngmres","Use Nonlinear GMRES","DMMG",&fasGMRES);
611:     PetscOptionsInt("-dmmg_fas_presmooth","Number of downward smoother iterates","DMMG",fasPresmooth,&fasPresmooth,PETSC_NULL);
612:     PetscOptionsInt("-dmmg_fas_postsmooth","Number of upward smoother iterates","DMMG",fasPostsmooth,&fasPostsmooth,PETSC_NULL);
613:     PetscOptionsInt("-dmmg_fas_coarsesmooth","Number of coarse smoother iterates","DMMG",fasCoarsesmooth,&fasCoarsesmooth,PETSC_NULL);
614:     PetscOptionsReal("-dmmg_fas_rtol","Relative tolerance for FAS","DMMG",fasRtol,&fasRtol,PETSC_NULL);
615:     PetscOptionsReal("-dmmg_fas_atol","Absolute tolerance for FAS","DMMG",fasAbstol,&fasAbstol,PETSC_NULL);
616:     PetscOptionsInt("-dmmg_fas_max_its","Maximum number of iterates per smoother","DMMG",fasMaxIter,&fasMaxIter,PETSC_NULL);
617:     */

619:     PetscOptionsBool("-dmmg_coloring_from_mat","Compute the coloring directly from the matrix nonzero structure","DMMGSetSNES",dmmg[0]->getcoloringfrommat,&dmmg[0]->getcoloringfrommat,PETSC_NULL);

621:     PetscOptionsName("-dmmg_jacobian_fd","Compute sparse Jacobian explicitly with finite differencing","DMMGSetSNES",&fdjacobian);
622:     if (fdjacobian) jacobian = DMMGComputeJacobianWithFD;
623: #if defined(PETSC_HAVE_ADIC)
624:     PetscOptionsName("-dmmg_jacobian_ad","Compute sparse Jacobian explicitly with ADIC (automatic differentiation)","DMMGSetSNES",&adjacobian);
625:     if (adjacobian) jacobian = DMMGComputeJacobianWithAdic;
626: #endif

628:     PetscOptionsBoolGroupBegin("-dmmg_jacobian_mf_fd_operator","Apply Jacobian via matrix free finite differencing","DMMGSetSNES",&mffdoperator);
629:     PetscOptionsBoolGroupEnd("-dmmg_jacobian_mf_fd","Apply Jacobian via matrix free finite differencing even in computing preconditioner","DMMGSetSNES",&mffd);
630:     if (mffd) mffdoperator = PETSC_TRUE;
631: #if defined(PETSC_HAVE_ADIC)
632:     PetscOptionsBoolGroupBegin("-dmmg_jacobian_mf_ad_operator","Apply Jacobian via matrix free ADIC (automatic differentiation)","DMMGSetSNES",&mfadoperator);
633:     PetscOptionsBoolGroupEnd("-dmmg_jacobian_mf_ad","Apply Jacobian via matrix free ADIC (automatic differentiation) even in computing preconditioner","DMMGSetSNES",&mfad);
634:     if (mfad) mfadoperator = PETSC_TRUE;
635: #endif
636:     PetscOptionsEnum("-dmmg_iscoloring_type","Type of ISColoring","None",ISColoringTypes,(PetscEnum)dmmg[0]->isctype,(PetscEnum*)&dmmg[0]->isctype,PETSC_NULL);
637: 
638:   PetscOptionsEnd();

640:   /* create solvers for each level */
641:   for (i=0; i<nlevels; i++) {
642:     SNESCreate(dmmg[i]->comm,&dmmg[i]->snes);
643:     PetscObjectIncrementTabLevel((PetscObject)dmmg[i]->snes,PETSC_NULL,nlevels - i - 1);
644:     SNESSetFunction(dmmg[i]->snes,dmmg[i]->b,function,dmmg[i]);
645:     SNESSetOptionsPrefix(dmmg[i]->snes,dmmg[i]->prefix);
646:     SNESGetKSP(dmmg[i]->snes,&dmmg[i]->ksp);

648:     if (mffdoperator) {
649:       MatCreateSNESMF(dmmg[i]->snes,&dmmg[i]->J);
650:       VecDuplicate(dmmg[i]->x,&dmmg[i]->work1);
651:       VecDuplicate(dmmg[i]->x,&dmmg[i]->work2);
652:       MatMFFDSetFunction(dmmg[i]->J,(PetscErrorCode (*)(void*, Vec,Vec))SNESComputeFunction,dmmg[i]->snes);
653:       if (mffd) {
654:         dmmg[i]->B = dmmg[i]->J;
655:         jacobian   = DMMGComputeJacobianWithMF;
656:         PetscObjectReference((PetscObject) dmmg[i]->B);
657:       }
658: #if defined(PETSC_HAVE_ADIC)
659:     } else if (mfadoperator) {
660:       MatRegisterDAAD();
661:       MatCreateDAAD(dmmg[i]->dm,&dmmg[i]->J);
662:       MatDAADSetCtx(dmmg[i]->J,dmmg[i]->user);
663:       if (mfad) {
664:         dmmg[i]->B = dmmg[i]->J;
665:         jacobian   = DMMGComputeJacobianWithMF;
666:         PetscObjectReference((PetscObject) dmmg[i]->B);
667:       }
668: #endif
669:     }
670: 
671:     if (!useFAS) {
672:       if (!dmmg[i]->B) {
673:         DMGetMatrix(dmmg[i]->dm,dmmg[i]->mtype,&dmmg[i]->B);
674:       }
675:       if (!dmmg[i]->J) {
676:         dmmg[i]->J = dmmg[i]->B;
677:         PetscObjectReference((PetscObject) dmmg[i]->B);
678:       }
679:     }

681:     DMMGSetUpLevel(dmmg,dmmg[i]->ksp,i+1);
682: 
683:     /*
684:        if the number of levels is > 1 then we want the coarse solve in the grid sequencing to use LU
685:        when possible 
686:     */
687:     if (nlevels > 1 && i == 0) {
688:       PC          pc;
689:       PetscMPIInt size;
690:       MPI_Comm    comm;
691:       PetscBool   flg1,flg2,flg3;
692:       KSP         cksp;

694:       KSPGetPC(dmmg[i]->ksp,&pc);
695:       PCMGGetCoarseSolve(pc,&cksp);
696:       KSPGetPC(cksp,&pc);
697:       PetscTypeCompare((PetscObject)pc,PCILU,&flg1);
698:       PetscTypeCompare((PetscObject)pc,PCSOR,&flg2);
699:       PetscTypeCompare((PetscObject)pc,PETSC_NULL,&flg3);
700:       if (flg1 || flg2 || flg3) {
701:         KSPSetType(dmmg[i]->ksp,KSPPREONLY);
702:         PetscObjectGetComm((PetscObject) pc,&comm);
703:         MPI_Comm_size(comm,&size);
704:         if (size > 1) {
705:           PCSetType(pc,PCREDUNDANT);
706:         } else {
707:           PCSetType(pc,PCLU);
708:         }
709:       }
710:     }

712:     dmmg[i]->computejacobian = jacobian;
713:     if (useFAS) {
714: #if defined(PETSC_HAVE_ADIC)
715:       if (fasBlock) {
716:         dmmg[i]->solve     = DMMGSolveFASb;
717:       } else if(fasGMRES) {
718:         dmmg[i]->solve     = DMMGSolveFAS_NGMRES;
719:       } else {
720:         dmmg[i]->solve     = DMMGSolveFAS4;
721:       }
722: #else
723:       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP, "Must use ADIC for structured FAS.");
724: #endif
725:     } else {
726:       dmmg[i]->solve         = DMMGSolveSNES;
727:     }
728:   }

730:   if (jacobian == DMMGComputeJacobianWithFD) {
731:     ISColoring iscoloring;

733:     for (i=0; i<nlevels; i++) {
734:       if (dmmg[0]->getcoloringfrommat) {
735:         MatGetColoring(dmmg[i]->B,(MatColoringType)MATCOLORINGSL,&iscoloring);
736:       } else {
737:         DMGetColoring(dmmg[i]->dm,dmmg[0]->isctype,dmmg[i]->mtype,&iscoloring);
738:       }
739:       MatFDColoringCreate(dmmg[i]->B,iscoloring,&dmmg[i]->fdcoloring);
740:       ISColoringDestroy(&iscoloring);
741:       if (function == DMMGFormFunction) function = DMMGFormFunctionFD;
742:       MatFDColoringSetFunction(dmmg[i]->fdcoloring,(PetscErrorCode(*)(void))function,dmmg[i]);
743:       MatFDColoringSetFromOptions(dmmg[i]->fdcoloring);
744:     }
745: #if defined(PETSC_HAVE_ADIC)
746:   } else if (jacobian == DMMGComputeJacobianWithAdic) {
747:     for (i=0; i<nlevels; i++) {
748:       ISColoring iscoloring;
749:       DMGetColoring(dmmg[i]->dm,IS_COLORING_GHOSTED,dmmg[i]->mtype,&iscoloring);
750:       MatSetColoring(dmmg[i]->B,iscoloring);
751:       ISColoringDestroy(&iscoloring);
752:     }
753: #endif
754:   }
755:   if (!useFAS) {
756:     for (i=0; i<nlevels; i++) {
757:       SNESSetJacobian(dmmg[i]->snes,dmmg[i]->J,dmmg[i]->B,DMMGComputeJacobian_Multigrid,dmmg);
758:     }
759:   }

761:   /* Create interpolation scaling */
762:   for (i=1; i<nlevels; i++) {
763:     DMGetInterpolationScale(dmmg[i-1]->dm,dmmg[i]->dm,dmmg[i]->R,&dmmg[i]->Rscale);
764:   }

766:   if (useFAS) {
767:     PetscBool  flg;

769:     for(i = 0; i < nlevels; i++) {
770:       VecDuplicate(dmmg[i]->b,&dmmg[i]->w);
771:       if (classid == DM_CLASSID) {
772: #if defined(PETSC_HAVE_ADIC)
773:         NLFCreate_DAAD(&dmmg[i]->nlf);
774:         NLFDAADSetDA_DAAD(dmmg[i]->nlf,dmmg[i]->dm);
775:         NLFDAADSetCtx_DAAD(dmmg[i]->nlf,dmmg[i]->user);
776:         NLFDAADSetResidual_DAAD(dmmg[i]->nlf,dmmg[i]->r);
777:         NLFDAADSetNewtonIterations_DAAD(dmmg[i]->nlf,fasMaxIter);
778: #endif
779:       } else {
780:       }

782:       dmmg[i]->monitor      = monitor;
783:       dmmg[i]->monitorall   = monitorAll;
784:       dmmg[i]->presmooth    = fasPresmooth;
785:       dmmg[i]->postsmooth   = fasPostsmooth;
786:       dmmg[i]->coarsesmooth = fasCoarsesmooth;
787:       dmmg[i]->rtol         = fasRtol;
788:       dmmg[i]->abstol       = fasAbstol;
789:     }

791:     flg  = PETSC_FALSE;
792:     PetscOptionsGetBool(0, "-dmmg_fas_view", &flg,PETSC_NULL);
793:     if (flg) {
794:       for(i = 0; i < nlevels; i++) {
795:         if (i == 0) {
796:           PetscPrintf(dmmg[i]->comm,"FAS Solver Parameters\n");
797:           PetscPrintf(dmmg[i]->comm,"  rtol %G atol %G\n",dmmg[i]->rtol,dmmg[i]->abstol);
798:           PetscPrintf(dmmg[i]->comm,"             coarsesmooths %D\n",dmmg[i]->coarsesmooth);
799:           PetscPrintf(dmmg[i]->comm,"             Newton iterations %D\n",fasMaxIter);
800:         } else {
801:           PetscPrintf(dmmg[i]->comm,"  level %D   presmooths    %D\n",i,dmmg[i]->presmooth);
802:           PetscPrintf(dmmg[i]->comm,"             postsmooths   %D\n",dmmg[i]->postsmooth);
803:           PetscPrintf(dmmg[i]->comm,"             Newton iterations %D\n",fasMaxIter);
804:         }
805:         if (fasBlock) {
806:           PetscPrintf(dmmg[i]->comm,"  using point-block smoothing\n");
807:         } else if(fasGMRES) {
808:           PetscPrintf(dmmg[i]->comm,"  using non-linear gmres\n");
809:         }
810:       }
811:     }
812:   }
813:   return(0);
814: }

818: /*@C
819:     DMMGSetFromOptions - Sets various options associated with the DMMG object

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

824:     Collective on DMMG

826:     Input Parameter:
827: .   dmmg - the context


830:     Notes: this is currently only supported for use with DMMGSetSNES() NOT DMMGSetKSP()

832:            Most options are checked in DMMGSetSNES(); this does call SNESSetFromOptions()

834:     Level: advanced

836: .seealso DMMGCreate(), DMMGDestroy, DMMGSetKSP(), DMMGSetSNESLocal(), DMMGSetSNES()

838: @*/
839: PetscErrorCode  DMMGSetFromOptions(DMMG *dmmg)
840: {
841:   PetscErrorCode          ierr;
842:   PetscInt                i,nlevels = dmmg[0]->nlevels;

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

847:   for (i=0; i<nlevels; i++) {
848:     SNESSetFromOptions(dmmg[i]->snes);
849:   }
850:   return(0);
851: }

855: /*@C
856:     DMMGSetSNESLocalFD - Sets the local user function that is used to approximately compute the Jacobian
857:         via finite differences.

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

862:     Logically Collective on DMMG

864:     Input Parameter:
865: +   dmmg - the context
866: -   function - the function that defines the nonlinear system

868:     Level: intermediate

870: .seealso DMMGCreate(), DMMGDestroy, DMMGSetKSP(), DMMGSetSNES(), DMMGSetSNESLocal()

872: @*/
873: PetscErrorCode DMMGSetSNESLocalFD(DMMG *dmmg,DMDALocalFunction1 function)
874: {
875:   PetscInt       i,nlevels = dmmg[0]->nlevels;

878:   for (i=0; i<nlevels; i++) {
879:     dmmg[i]->lfj = (PetscErrorCode (*)(void))function;
880:   }
881:   return(0);
882: }


887: /*@C
888:   DMMGGetSNESLocal - Returns the local functions for residual and Jacobian evaluation.

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

893:   Not Collective

895:   Input Parameter:
896: . dmmg - the context

898:   Output Parameters:
899: + function - the function that defines the nonlinear system
900: - jacobian - function defines the local part of the Jacobian

902:   Level: intermediate

904: .seealso DMMGCreate(), DMMGDestroy, DMMGSetKSP(), DMMGSetSNES(), DMMGSetSNESLocal()
905: @*/
906: PetscErrorCode DMMGGetSNESLocal(DMMG *dmmg,DMDALocalFunction1 *function, DMDALocalFunction1 *jacobian)
907: {

911:   DMDAGetLocalFunction(dmmg[0]->dm, function);
912:   DMDAGetLocalJacobian(dmmg[0]->dm, jacobian);
913:   return(0);
914: }

916: /*MC
917:     DMMGSetSNESLocal - Sets the local user function that defines the nonlinear set of equations
918:     that will use the grid hierarchy and (optionally) its derivative.

920:    Synopsis:
921:    PetscErrorCode DMMGSetSNESLocal(DMMG *dmmg,DMDALocalFunction1 function, DMDALocalFunction1 jacobian,
922:                         DMDALocalFunction1 ad_function, DMDALocalFunction1 admf_function);

924:     Logically Collective on DMMG

926:     Input Parameter:
927: +   dmmg - the context
928: .   function - the function that defines the nonlinear system
929: .   jacobian - function defines the local part of the Jacobian
930: .   ad_function - the name of the function with an ad_ prefix. This is ignored currently
931: -   admf_function - the name of the function with an ad_ prefix. This is ignored currently

933:     Options Database Keys:
934: +    -dmmg_jacobian_fd
935: .    -dmmg_jacobian_ad
936: .    -dmmg_jacobian_mf_fd_operator
937: .    -dmmg_jacobian_mf_fd
938: .    -dmmg_jacobian_mf_ad_operator
939: -    -dmmg_jacobian_mf_ad


942:     Level: intermediate

944:     Notes: 
945:     If the Jacobian is not provided, this routine
946:     uses finite differencing to approximate the Jacobian.

948: .seealso DMMGCreate(), DMMGDestroy, DMMGSetKSP(), DMMGSetSNES()

950: M*/

954: PetscErrorCode DMMGSetSNESLocal_Private(DMMG *dmmg,DMDALocalFunction1 function,DMDALocalFunction1 jacobian,DMDALocalFunction1 ad_function,DMDALocalFunction1 admf_function)
955: {
957:   PetscInt       i,nlevels = dmmg[0]->nlevels;
958:   const char    *typeName;
959:   PetscBool      ismesh;
960:   PetscErrorCode (*computejacobian)(SNES,Vec,Mat*,Mat*,MatStructure*,void*) = 0;


964:   if (jacobian)         computejacobian = DMMGComputeJacobian;
965: #if defined(PETSC_HAVE_ADIC)
966:   else if (ad_function) computejacobian = DMMGComputeJacobianWithAdic;
967: #endif
968:   CHKMEMQ;
969:   PetscObjectGetType((PetscObject) dmmg[0]->dm, &typeName);
970:   PetscStrcmp(typeName, DMMESH, &ismesh);
971:   if (ismesh)  SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP, "Unstructured grids no longer supported since DMMG will be phased out");
972:   else {
973:     PetscBool  flag;
974:     /* it makes no sense to use an option to decide on ghost, it depends on whether the 
975:        formfunctionlocal computes ghost values in F or not. */
976:     PetscOptionsHasName(PETSC_NULL, "-dmmg_form_function_ghost", &flag);
977:     if (flag) {
978:       DMMGSetSNES(dmmg,DMMGFormFunctionGhost,computejacobian);
979:     } else {
980:       DMMGSetSNES(dmmg,DMMGFormFunction,computejacobian);
981:     }
982:     for (i=0; i<nlevels; i++) {
983:       dmmg[i]->isctype  = IS_COLORING_GHOSTED;   /* switch to faster version since have local function evaluation */
984:       DMDASetLocalFunction(dmmg[i]->dm,function);
985:       dmmg[i]->lfj = (PetscErrorCode (*)(void))function;
986:       DMDASetLocalJacobian(dmmg[i]->dm,jacobian);
987:       DMDASetLocalAdicFunction(dmmg[i]->dm,ad_function);
988:       DMDASetLocalAdicMFFunction(dmmg[i]->dm,admf_function);
989:     }
990:   }
991:   CHKMEMQ;
992:   return(0);
993: }

997: PetscErrorCode DMMGFunctioni(void* ctx,PetscInt i,Vec u,PetscScalar* r)
998: {
999:   DMMG           dmmg = (DMMG)ctx;
1000:   Vec            U = dmmg->lwork1;
1002:   VecScatter     gtol;

1005:   /* copy u into interior part of U */
1006:   DMDAGetScatter(dmmg->dm,0,&gtol,0);
1007:   VecScatterBegin(gtol,u,U,INSERT_VALUES,SCATTER_FORWARD_LOCAL);
1008:   VecScatterEnd(gtol,u,U,INSERT_VALUES,SCATTER_FORWARD_LOCAL);
1009:   DMDAFormFunctioni1(dmmg->dm,i,U,r,dmmg->user);
1010:   return(0);
1011: }

1015: PetscErrorCode DMMGFunctionib(PetscInt i,Vec u,PetscScalar* r,void* ctx)
1016: {
1017:   DMMG           dmmg = (DMMG)ctx;
1018:   Vec            U = dmmg->lwork1;
1020:   VecScatter     gtol;

1023:   /* copy u into interior part of U */
1024:   DMDAGetScatter(dmmg->dm,0,&gtol,0);
1025:   VecScatterBegin(gtol,u,U,INSERT_VALUES,SCATTER_FORWARD_LOCAL);
1026:   VecScatterEnd(gtol,u,U,INSERT_VALUES,SCATTER_FORWARD_LOCAL);
1027:   DMDAFormFunctionib1(dmmg->dm,i,U,r,dmmg->user);
1028:   return(0);
1029: }

1033: PetscErrorCode DMMGFunctioniBase(void* ctx,Vec u)
1034: {
1035:   DMMG           dmmg = (DMMG)ctx;
1036:   Vec            U = dmmg->lwork1;

1040:   DMGlobalToLocalBegin(dmmg->dm,u,INSERT_VALUES,U);
1041:   DMGlobalToLocalEnd(dmmg->dm,u,INSERT_VALUES,U);
1042:   return(0);
1043: }

1047: PetscErrorCode DMMGSetSNESLocali_Private(DMMG *dmmg,PetscErrorCode (*functioni)(DMDALocalInfo*,MatStencil*,void*,PetscScalar*,void*),PetscErrorCode (*adi)(DMDALocalInfo*,MatStencil*,void*,void*,void*),PetscErrorCode (*adimf)(DMDALocalInfo*,MatStencil*,void*,void*,void*))
1048: {
1050:   PetscInt       i,nlevels = dmmg[0]->nlevels;

1053:   for (i=0; i<nlevels; i++) {
1054:     DMDASetLocalFunctioni(dmmg[i]->dm,functioni);
1055:     DMDASetLocalAdicFunctioni(dmmg[i]->dm,adi);
1056:     DMDASetLocalAdicMFFunctioni(dmmg[i]->dm,adimf);
1057:     MatMFFDSetFunctioni(dmmg[i]->J,DMMGFunctioni);
1058:     MatMFFDSetFunctioniBase(dmmg[i]->J,DMMGFunctioniBase);
1059:     if (!dmmg[i]->lwork1) {
1060:       DMCreateLocalVector(dmmg[i]->dm,&dmmg[i]->lwork1);
1061:     }
1062:   }
1063:   return(0);
1064: }

1068: PetscErrorCode DMMGSetSNESLocalib_Private(DMMG *dmmg,PetscErrorCode (*functioni)(DMDALocalInfo*,MatStencil*,void*,PetscScalar*,void*),PetscErrorCode (*adi)(DMDALocalInfo*,MatStencil*,void*,void*,void*),PetscErrorCode (*adimf)(DMDALocalInfo*,MatStencil*,void*,void*,void*))
1069: {
1071:   PetscInt       i,nlevels = dmmg[0]->nlevels;

1074:   for (i=0; i<nlevels; i++) {
1075:     DMDASetLocalFunctionib(dmmg[i]->dm,functioni);
1076:     DMDASetLocalAdicFunctionib(dmmg[i]->dm,adi);
1077:     DMDASetLocalAdicMFFunctionib(dmmg[i]->dm,adimf);
1078:     if (!dmmg[i]->lwork1) {
1079:       DMCreateLocalVector(dmmg[i]->dm,&dmmg[i]->lwork1);
1080:     }
1081:   }
1082:   return(0);
1083: }

1085: static PetscErrorCode (*localfunc)(void) = 0;

1089: /*
1090:     Uses the DM object to call the user provided function with the correct calling
1091:   sequence.
1092: */
1093: PetscErrorCode  DMMGInitialGuess_Local(DMMG dmmg,Vec x)
1094: {

1098:   (*dmmg->dm->ops->forminitialguess)(dmmg->dm,localfunc,x,0);
1099:   return(0);
1100: }

1104: /*@C
1105:     DMMGSetInitialGuessLocal - sets code to compute the initial guess for each level

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

1110:  Logically Collective on DMMG

1112:     Input Parameter:
1113: +   dmmg - the context
1114: -   localguess - the function that computes the initial guess

1116:     Level: intermediate

1118: .seealso DMMGCreate(), DMMGDestroy, DMMGSetKSP(), DMMGSetSNES(), DMMGSetInitialGuess(), DMMGSetSNESLocal()

1120: @*/
1121: PetscErrorCode DMMGSetInitialGuessLocal(DMMG *dmmg,PetscErrorCode (*localguess)(void))
1122: {

1126:   localfunc = localguess;  /* stash into ugly static for now */

1128:   DMMGSetInitialGuess(dmmg,DMMGInitialGuess_Local);
1129:   return(0);
1130: }

1134: /*@C
1135:     DMMGSetISColoringType - type of coloring used to compute Jacobian via finite differencing

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

1140:     Logically Collective on DMMG

1142:     Input Parameter:
1143: +   dmmg - the context
1144: -   isctype - IS_COLORING_GHOSTED (default) or IS_COLORING_GLOBAL

1146:     Options Database:
1147: .   -dmmg_iscoloring_type <ghosted or global>

1149:     Notes: ghosted coloring requires using DMMGSetSNESLocal()

1151:     Level: intermediate

1153: .seealso DMMGCreate(), DMMGDestroy, DMMGSetKSP(), DMMGSetSNES(), DMMGSetInitialGuess(), DMMGSetSNESLocal()

1155: @*/
1156: PetscErrorCode DMMGSetISColoringType(DMMG *dmmg,ISColoringType isctype)
1157: {
1159:   dmmg[0]->isctype = isctype;
1160:   return(0);
1161: }


1166: /*@C
1167:     DMMGSetUp - Called after DMMGSetSNES() and (optionally) DMMGSetFromOptions()

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

1172:     Collective on DMMG

1174:     Input Parameter:
1175: .   dmmg - the context

1177:     Notes: Currently this must be called by the user (if they want to).

1179:     Level: advanced

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

1183: @*/
1184: PetscErrorCode  DMMGSetUp(DMMG *dmmg)
1185: {
1187:   KSP            ksp;
1188:   SNES           snes;
1189:   PC             pc;

1192:   snes = DMMGGetSNES(dmmg);
1193:   if (snes) {
1194:     SNESGetKSP(snes,&ksp);
1195:   } else {
1196:     ksp = DMMGGetKSP(dmmg);
1197:   }
1198:   KSPGetPC(ksp,&pc);
1199:   PCSetDM(pc,DMMGGetDM(dmmg));
1200:   return(0);
1201: }