Actual source code: damgsnes.c

  1: #define PETSCSNES_DLL
  2: 
 3:  #include petscda.h
 4:  #include private/daimpl.h
  5: /* It appears that preprocessor directives are not respected by bfort */
  6: #ifdef PETSC_HAVE_SIEVE
 7:  #include petscmesh.h
  8: #endif
 9:  #include petscmg.h
 10:  #include petscdmmg.h

 12: #if defined(PETSC_HAVE_ADIC)
 19: #endif
 20: #if defined(PETSC_HAVE_SIEVE)
 22: #endif

 25: EXTERN PetscErrorCode  NLFCreate_DAAD(NLF*);
 26: EXTERN PetscErrorCode  NLFDAADSetDA_DAAD(NLF,DA);
 27: EXTERN PetscErrorCode  NLFDAADSetCtx_DAAD(NLF,void*);
 28: EXTERN PetscErrorCode  NLFDAADSetResidual_DAAD(NLF,Vec);
 29: EXTERN PetscErrorCode  NLFDAADSetNewtonIterations_DAAD(NLF,PetscInt);

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

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

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

 67:   /* create coarser grid Jacobians for preconditioner if multigrid is the preconditioner */
 68:   SNESGetKSP(snes,&ksp);
 69:   KSPGetPC(ksp,&pc);
 70:   PetscTypeCompare((PetscObject)pc,PCMG,&ismg);
 71:   if (ismg) {
 72:     PCMGGetGalerkin(pc,&galerkin);
 73:   }

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

105: /* ---------------------------------------------------------------------------*/


110: /* 
111:    DMMGFormFunction - This is a universal global FormFunction used by the DMMG code
112:    when the user provides a local function.

114:    Input Parameters:
115: +  snes - the SNES context
116: .  X - input vector
117: -  ptr - optional user-defined context, as set by SNESSetFunction()

119:    Output Parameter:
120: .  F - function vector

122:  */
123: PetscErrorCode DMMGFormFunction(SNES snes,Vec X,Vec F,void *ptr)
124: {
125:   DMMG           dmmg = (DMMG)ptr;
127:   Vec            localX;
128:   DA             da = (DA)dmmg->dm;

131:   DAGetLocalVector(da,&localX);
132:   /*
133:      Scatter ghost points to local vector, using the 2-step process
134:         DAGlobalToLocalBegin(), DAGlobalToLocalEnd().
135:   */
136:   DAGlobalToLocalBegin(da,X,INSERT_VALUES,localX);
137:   DAGlobalToLocalEnd(da,X,INSERT_VALUES,localX);
138:   DAFormFunction1(da,localX,F,dmmg->user);
139:   DARestoreLocalVector(da,&localX);
140:   return(0);
141: }

145: PetscErrorCode DMMGFormFunctionGhost(SNES snes,Vec X,Vec F,void *ptr)
146: {
147:   DMMG           dmmg = (DMMG)ptr;
149:   Vec            localX, localF;
150:   DA             da = (DA)dmmg->dm;

153:   DAGetLocalVector(da,&localX);
154:   DAGetLocalVector(da,&localF);
155:   /*
156:      Scatter ghost points to local vector, using the 2-step process
157:         DAGlobalToLocalBegin(), DAGlobalToLocalEnd().
158:   */
159:   DAGlobalToLocalBegin(da,X,INSERT_VALUES,localX);
160:   DAGlobalToLocalEnd(da,X,INSERT_VALUES,localX);
161:   VecSet(F, 0.0);
162:   VecSet(localF, 0.0);
163:   DAFormFunction1(da,localX,localF,dmmg->user);
164:   DALocalToGlobalBegin(da,localF,F);
165:   DALocalToGlobalEnd(da,localF,F);
166:   DARestoreLocalVector(da,&localX);
167:   DARestoreLocalVector(da,&localF);
168:   return(0);
169: }

171: #ifdef PETSC_HAVE_SIEVE
174: /* 
175:    DMMGFormFunctionMesh - This is a universal global FormFunction used by the DMMG code
176:    when the user provides a local function.

178:    Input Parameters:
179: +  snes - the SNES context
180: .  X - input vector
181: -  ptr - This is the DMMG object

183:    Output Parameter:
184: .  F - function vector

186:  */
187: PetscErrorCode DMMGFormFunctionMesh(SNES snes, Vec X, Vec F, void *ptr)
188: {
189:   DMMG           dmmg = (DMMG) ptr;
190:   Mesh           mesh = (Mesh) dmmg->dm;
191:   SectionReal    sectionF, section;

195:   MeshGetSectionReal(mesh, "default", &section);
196:   SectionRealDuplicate(section, &sectionF);
197:   SectionRealToVec(section, mesh, SCATTER_REVERSE, X);
198:   MeshFormFunction(mesh, section, sectionF, dmmg->user);
199:   SectionRealToVec(sectionF, mesh, SCATTER_FORWARD, F);
200:   SectionRealDestroy(sectionF);
201:   SectionRealDestroy(section);
202:   return(0);
203: }

207: /* 
208:    DMMGComputeJacobianMesh - This is a universal global FormJacobian used by the DMMG code
209:    when the user provides a local function.

211:    Input Parameters:
212: +  snes - the SNES context
213: .  X - input vector
214: -  ptr - This is the DMMG object

216:    Output Parameter:
217: .  F - function vector

219:  */
220: PetscErrorCode DMMGComputeJacobianMesh(SNES snes, Vec X, Mat *J, Mat *B, MatStructure *flag, void *ptr)
221: {
222:   DMMG           dmmg = (DMMG) ptr;
223:   Mesh           mesh = (Mesh) dmmg->dm;
224:   SectionReal    sectionX;

228:   MeshGetSectionReal(mesh, "default", &sectionX);
229:   SectionRealToVec(sectionX, mesh, SCATTER_REVERSE, X);
230:   MeshFormJacobian(mesh, sectionX, *B, dmmg->user);
231:   /* Assemble true Jacobian; if it is different */
232:   if (*J != *B) {
233:     MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);
234:     MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);
235:   }
236:   MatSetOption(*B, MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);
237:   *flag = SAME_NONZERO_PATTERN;
238:   SectionRealDestroy(sectionX);
239:   return(0);
240: }
241: #endif

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

249:    Input Parameters:
250: +  snes - the SNES context
251: .  X - input vector
252: -  ptr - optional user-defined context, as set by SNESSetFunction()

254:    Output Parameter:
255: .  F - function vector

257:  */
258: PetscErrorCode DMMGFormFunctionFD(SNES snes,Vec X,Vec F,void *ptr)
259: {
260:   DMMG           dmmg = (DMMG)ptr;
262:   Vec            localX;
263:   DA             da = (DA)dmmg->dm;
264:   PetscInt       N,n;
265: 
267:   /* determine whether X=localX */
268:   DAGetLocalVector(da,&localX);
269:   VecGetSize(X,&N);
270:   VecGetSize(localX,&n);

272:   if (n != N){ /* X != localX */
273:     /* Scatter ghost points to local vector, using the 2-step process
274:        DAGlobalToLocalBegin(), DAGlobalToLocalEnd().
275:     */
276:     DAGlobalToLocalBegin(da,X,INSERT_VALUES,localX);
277:     DAGlobalToLocalEnd(da,X,INSERT_VALUES,localX);
278:   } else {
279:     DARestoreLocalVector(da,&localX);
280:     localX = X;
281:   }
282:   DAFormFunction(da,dmmg->lfj,localX,F,dmmg->user);
283:   if (n != N){
284:     DARestoreLocalVector(da,&localX);
285:   }
286:   return(0);
287: }

291: /*@C 
292:    SNESDAFormFunction - This is a universal function evaluation routine that
293:    may be used with SNESSetFunction() as long as the user context has a DA
294:    as its first record and the user has called DASetLocalFunction().

296:    Collective on SNES

298:    Input Parameters:
299: +  snes - the SNES context
300: .  X - input vector
301: .  F - function vector
302: -  ptr - pointer to a structure that must have a DA as its first entry. For example this 
303:          could be a DMMG, this ptr must have been passed into SNESDAFormFunction() as the context

305:    Level: intermediate

307: .seealso: DASetLocalFunction(), DASetLocalJacobian(), DASetLocalAdicFunction(), DASetLocalAdicMFFunction(),
308:           SNESSetFunction(), SNESSetJacobian()

310: @*/
311: PetscErrorCode  SNESDAFormFunction(SNES snes,Vec X,Vec F,void *ptr)
312: {
314:   Vec            localX;
315:   DA             da = *(DA*)ptr;
316:   PetscInt       N,n;
317: 
319:   if (!da) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Looks like you called SNESSetFromFuntion(snes,SNESDAFormFunction,) without the DA context");

321:   /* determine whether X=localX */
322:   DAGetLocalVector(da,&localX);
323:   VecGetSize(X,&N);
324:   VecGetSize(localX,&n);
325: 
326: 
327:   if (n != N){ /* X != localX */
328:     /* Scatter ghost points to local vector, using the 2-step process
329:         DAGlobalToLocalBegin(), DAGlobalToLocalEnd().
330:     */
331:     DAGlobalToLocalBegin(da,X,INSERT_VALUES,localX);
332:     DAGlobalToLocalEnd(da,X,INSERT_VALUES,localX);
333:   } else {
334:     DARestoreLocalVector(da,&localX);
335:     localX = X;
336:   }
337:   DAFormFunction1(da,localX,F,ptr);
338:   if (n != N){
339:     if (PetscExceptionValue(ierr)) {
340:       PetscErrorCode pDARestoreLocalVector(da,&localX);CHKERRQ(pierr);
341:     }
342: 
343:     DARestoreLocalVector(da,&localX);
344:   }
345:   return(0);
346: }

348: /* ------------------------------------------------------------------------------*/
349:  #include private/matimpl.h
352: PetscErrorCode DMMGComputeJacobianWithFD(SNES snes,Vec x1,Mat *J,Mat *B,MatStructure *flag,void *ctx)
353: {
355:   DMMG           dmmg = (DMMG)ctx;
356:   MatFDColoring  color = (MatFDColoring)dmmg->fdcoloring;
357: 
359:   if (color->ctype == IS_COLORING_GHOSTED){
360:     DA            da=(DA)dmmg->dm;
361:     Vec           x1_loc;
362:     DAGetLocalVector(da,&x1_loc);
363:     DAGlobalToLocalBegin(da,x1,INSERT_VALUES,x1_loc);
364:     DAGlobalToLocalEnd(da,x1,INSERT_VALUES,x1_loc);
365:     SNESDefaultComputeJacobianColor(snes,x1_loc,J,B,flag,dmmg->fdcoloring);
366:     DARestoreLocalVector(da,&x1_loc);
367:   } else {
368:     SNESDefaultComputeJacobianColor(snes,x1,J,B,flag,dmmg->fdcoloring);
369:   }
370:   return(0);
371: }

375: PetscErrorCode DMMGComputeJacobianWithMF(SNES snes,Vec x1,Mat *J,Mat *B,MatStructure *flag,void *ctx)
376: {
378: 
380:   MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);
381:   MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);
382:   return(0);
383: }

387: /*
388:     DMMGComputeJacobian - Evaluates the Jacobian when the user has provided
389:     a local function evaluation routine.
390: */
391: PetscErrorCode DMMGComputeJacobian(SNES snes,Vec X,Mat *J,Mat *B,MatStructure *flag,void *ptr)
392: {
393:   DMMG           dmmg = (DMMG) ptr;
395:   Vec            localX;
396:   DA             da = (DA) dmmg->dm;

399:   DAGetLocalVector(da,&localX);
400:   DAGlobalToLocalBegin(da,X,INSERT_VALUES,localX);
401:   DAGlobalToLocalEnd(da,X,INSERT_VALUES,localX);
402:   DAComputeJacobian1(da,localX,*B,dmmg->user);
403:   DARestoreLocalVector(da,&localX);
404:   /* Assemble true Jacobian; if it is different */
405:   if (*J != *B) {
406:     MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);
407:     MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);
408:   }
409:   MatSetOption(*B,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);
410:   *flag = SAME_NONZERO_PATTERN;
411:   return(0);
412: }

416: /*
417:     SNESDAComputeJacobianWithAdifor - This is a universal Jacobian evaluation routine
418:     that may be used with SNESSetJacobian() from Fortran as long as the user context has 
419:     a DA as its first record and DASetLocalAdiforFunction() has been called.  

421:    Collective on SNES

423:    Input Parameters:
424: +  snes - the SNES context
425: .  X - input vector
426: .  J - Jacobian
427: .  B - Jacobian used in preconditioner (usally same as J)
428: .  flag - indicates if the matrix changed its structure
429: -  ptr - optional user-defined context, as set by SNESSetFunction()

431:    Level: intermediate

433: .seealso: DASetLocalFunction(), DASetLocalAdicFunction(), SNESSetFunction(), SNESSetJacobian()

435: */
436: PetscErrorCode  SNESDAComputeJacobianWithAdifor(SNES snes,Vec X,Mat *J,Mat *B,MatStructure *flag,void *ptr)
437: {
438:   DA             da = *(DA*) ptr;
440:   Vec            localX;

443:   DAGetLocalVector(da,&localX);
444:   DAGlobalToLocalBegin(da,X,INSERT_VALUES,localX);
445:   DAGlobalToLocalEnd(da,X,INSERT_VALUES,localX);
446:   DAComputeJacobian1WithAdifor(da,localX,*B,ptr);
447:   DARestoreLocalVector(da,&localX);
448:   /* Assemble true Jacobian; if it is different */
449:   if (*J != *B) {
450:     MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);
451:     MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);
452:   }
453:   MatSetOption(*B,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);
454:   *flag = SAME_NONZERO_PATTERN;
455:   return(0);
456: }

460: /*
461:    SNESDAComputeJacobian - This is a universal Jacobian evaluation routine for a
462:    locally provided Jacobian.

464:    Collective on SNES

466:    Input Parameters:
467: +  snes - the SNES context
468: .  X - input vector
469: .  J - Jacobian
470: .  B - Jacobian used in preconditioner (usally same as J)
471: .  flag - indicates if the matrix changed its structure
472: -  ptr - optional user-defined context, as set by SNESSetFunction()

474:    Level: intermediate

476: .seealso: DASetLocalFunction(), DASetLocalJacobian(), SNESSetFunction(), SNESSetJacobian()

478: */
479: PetscErrorCode  SNESDAComputeJacobian(SNES snes,Vec X,Mat *J,Mat *B,MatStructure *flag,void *ptr)
480: {
481:   DA             da = *(DA*) ptr;
483:   Vec            localX;

486:   DAGetLocalVector(da,&localX);
487:   DAGlobalToLocalBegin(da,X,INSERT_VALUES,localX);
488:   DAGlobalToLocalEnd(da,X,INSERT_VALUES,localX);
489:   DAComputeJacobian1(da,localX,*B,ptr);
490:   DARestoreLocalVector(da,&localX);
491:   /* Assemble true Jacobian; if it is different */
492:   if (*J != *B) {
493:     MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);
494:     MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);
495:   }
496:   MatSetOption(*B,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);
497:   *flag = SAME_NONZERO_PATTERN;
498:   return(0);
499: }

503: PetscErrorCode DMMGSolveSNES(DMMG *dmmg,PetscInt level)
504: {
506:   PetscInt       nlevels = dmmg[0]->nlevels;

509:   dmmg[0]->nlevels = level+1;
510:   SNESSolve(dmmg[level]->snes,PETSC_NULL,dmmg[level]->x);
511:   dmmg[0]->nlevels = nlevels;
512:   return(0);
513: }

515: /* ===========================================================================================================*/

519: /*@C
520:     DMMGSetSNES - Sets the nonlinear function that defines the nonlinear set of equations
521:     to be solved using the grid hierarchy.

523:     Collective on DMMG

525:     Input Parameter:
526: +   dmmg - the context
527: .   function - the function that defines the nonlinear system
528: -   jacobian - optional function to compute Jacobian

530:     Options Database Keys:
531: +    -snes_monitor
532: .    -dmmg_coloring_from_mat - use graph coloring on the actual matrix nonzero structure instead of getting the coloring from the DM
533: .    -dmmg_jacobian_fd
534: .    -dmmg_jacobian_ad
535: .    -dmmg_jacobian_mf_fd_operator
536: .    -dmmg_jacobian_mf_fd
537: .    -dmmg_jacobian_mf_ad_operator
538: .    -dmmg_jacobian_mf_ad
539: .    -dmmg_iscoloring_type
540: -
541:                                  The period at which the Jacobian is recomputed can be set differently for different levels
542:                                  of the Jacobian (for example lag all Jacobians except on the finest level).
543:                                  There is no user interface currently for setting a different period on the different levels, one must set the
544:                                  fields dmmg[i]->updatejacobian and dmmg[i]->updatejacobianperiod directly in the DMMG data structure.
545:                                  

547:     Level: advanced

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

551: @*/
552: PetscErrorCode  DMMGSetSNES(DMMG *dmmg,PetscErrorCode (*function)(SNES,Vec,Vec,void*),PetscErrorCode (*jacobian)(SNES,Vec,Mat*,Mat*,MatStructure*,void*))
553: {
554:   PetscErrorCode          ierr;
555:   PetscInt                i,nlevels = dmmg[0]->nlevels;
556:   PetscTruth              mffdoperator,mffd,fdjacobian;
557:   PetscTruth              useFAS = PETSC_FALSE, fasBlock=PETSC_FALSE, fasGMRES=PETSC_FALSE;
558:   PetscTruth              monitor, monitorAll;
559:   PetscInt                fasPresmooth = 1, fasPostsmooth = 1, fasCoarsesmooth = 1, fasMaxIter = 2;
560:   PetscReal               fasRtol = 1.0e-8, fasAbstol = 1.0e-50;
561: #if defined(PETSC_HAVE_ADIC)
562:   PetscTruth              mfadoperator,mfad,adjacobian;
563: #endif
564:   PetscCookie             cookie;

567:   if (!dmmg)     SETERRQ(PETSC_ERR_ARG_NULL,"Passing null as DMMG");
568:   if (!jacobian) jacobian = DMMGComputeJacobianWithFD;
569:   PetscObjectGetCookie((PetscObject) dmmg[0]->dm, &cookie);

571:   PetscOptionsBegin(dmmg[0]->comm,dmmg[0]->prefix,"DMMG Options","SNES");
572:     PetscOptionsName("-dmmg_monitor","Monitor DMMG iterations","DMMG",&monitor);
573:     PetscOptionsName("-dmmg_monitor_all","Monitor DMMG iterations","DMMG",&monitorAll);
574:     /*
575:     PetscOptionsTruth("-dmmg_fas","Use the Full Approximation Scheme","DMMGSetSNES",useFAS,&useFAS,PETSC_NULL);
576:     PetscOptionsName("-dmmg_fas_block","Use point-block smoothing","DMMG",&fasBlock);
577:     PetscOptionsName("-dmmg_fas_ngmres","Use Nonlinear GMRES","DMMG",&fasGMRES);
578:     PetscOptionsInt("-dmmg_fas_presmooth","Number of downward smoother iterates","DMMG",fasPresmooth,&fasPresmooth,PETSC_NULL);
579:     PetscOptionsInt("-dmmg_fas_postsmooth","Number of upward smoother iterates","DMMG",fasPostsmooth,&fasPostsmooth,PETSC_NULL);
580:     PetscOptionsInt("-dmmg_fas_coarsesmooth","Number of coarse smoother iterates","DMMG",fasCoarsesmooth,&fasCoarsesmooth,PETSC_NULL);
581:     PetscOptionsReal("-dmmg_fas_rtol","Relative tolerance for FAS","DMMG",fasRtol,&fasRtol,PETSC_NULL);
582:     PetscOptionsReal("-dmmg_fas_atol","Absolute tolerance for FAS","DMMG",fasAbstol,&fasAbstol,PETSC_NULL);
583:     PetscOptionsInt("-dmmg_fas_max_its","Maximum number of iterates per smoother","DMMG",fasMaxIter,&fasMaxIter,PETSC_NULL);
584:     */

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

588:     PetscOptionsName("-dmmg_jacobian_fd","Compute sparse Jacobian explicitly with finite differencing","DMMGSetSNES",&fdjacobian);
589:     if (fdjacobian) jacobian = DMMGComputeJacobianWithFD;
590: #if defined(PETSC_HAVE_ADIC)
591:     PetscOptionsName("-dmmg_jacobian_ad","Compute sparse Jacobian explicitly with ADIC (automatic differentiation)","DMMGSetSNES",&adjacobian);
592:     if (adjacobian) jacobian = DMMGComputeJacobianWithAdic;
593: #endif

595:     PetscOptionsTruthGroupBegin("-dmmg_jacobian_mf_fd_operator","Apply Jacobian via matrix free finite differencing","DMMGSetSNES",&mffdoperator);
596:     PetscOptionsTruthGroupEnd("-dmmg_jacobian_mf_fd","Apply Jacobian via matrix free finite differencing even in computing preconditioner","DMMGSetSNES",&mffd);
597:     if (mffd) mffdoperator = PETSC_TRUE;
598: #if defined(PETSC_HAVE_ADIC)
599:     PetscOptionsTruthGroupBegin("-dmmg_jacobian_mf_ad_operator","Apply Jacobian via matrix free ADIC (automatic differentiation)","DMMGSetSNES",&mfadoperator);
600:     PetscOptionsTruthGroupEnd("-dmmg_jacobian_mf_ad","Apply Jacobian via matrix free ADIC (automatic differentiation) even in computing preconditioner","DMMGSetSNES",&mfad);
601:     if (mfad) mfadoperator = PETSC_TRUE;
602: #endif
603:     PetscOptionsEnum("-dmmg_iscoloring_type","Type of ISColoring","None",ISColoringTypes,(PetscEnum)dmmg[0]->isctype,(PetscEnum*)&dmmg[0]->isctype,PETSC_NULL);
604: 
605:   PetscOptionsEnd();

607:   /* create solvers for each level */
608:   for (i=0; i<nlevels; i++) {
609:     SNESCreate(dmmg[i]->comm,&dmmg[i]->snes);
610:     PetscObjectIncrementTabLevel((PetscObject)dmmg[i]->snes,PETSC_NULL,nlevels - i - 1);
611:     SNESSetFunction(dmmg[i]->snes,dmmg[i]->b,function,dmmg[i]);
612:     SNESSetOptionsPrefix(dmmg[i]->snes,dmmg[i]->prefix);
613:     SNESGetKSP(dmmg[i]->snes,&dmmg[i]->ksp);

615:     if (mffdoperator) {
616:       MatCreateSNESMF(dmmg[i]->snes,&dmmg[i]->J);
617:       VecDuplicate(dmmg[i]->x,&dmmg[i]->work1);
618:       VecDuplicate(dmmg[i]->x,&dmmg[i]->work2);
619:       MatMFFDSetFunction(dmmg[i]->J,(PetscErrorCode (*)(void*, Vec,Vec))SNESComputeFunction,dmmg[i]->snes);
620:       if (mffd) {
621:         dmmg[i]->B = dmmg[i]->J;
622:         jacobian   = DMMGComputeJacobianWithMF;
623:         PetscObjectReference((PetscObject) dmmg[i]->B);
624:       }
625: #if defined(PETSC_HAVE_ADIC)
626:     } else if (mfadoperator) {
627:       MatRegisterDAAD();
628:       MatCreateDAAD((DA)dmmg[i]->dm,&dmmg[i]->J);
629:       MatDAADSetCtx(dmmg[i]->J,dmmg[i]->user);
630:       if (mfad) {
631:         dmmg[i]->B = dmmg[i]->J;
632:         jacobian   = DMMGComputeJacobianWithMF;
633:         PetscObjectReference((PetscObject) dmmg[i]->B);
634:       }
635: #endif
636:     }
637: 
638:     if (!useFAS) {
639:       if (!dmmg[i]->B) {
640:         DMGetMatrix(dmmg[i]->dm,dmmg[i]->mtype,&dmmg[i]->B);
641:       }
642:       if (!dmmg[i]->J) {
643:         dmmg[i]->J = dmmg[i]->B;
644:         PetscObjectReference((PetscObject) dmmg[i]->B);
645:       }
646:     }

648:     DMMGSetUpLevel(dmmg,dmmg[i]->ksp,i+1);
649: 
650:     /*
651:        if the number of levels is > 1 then we want the coarse solve in the grid sequencing to use LU
652:        when possible 
653:     */
654:     if (nlevels > 1 && i == 0) {
655:       PC          pc;
656:       PetscMPIInt size;
657:       MPI_Comm    comm;
658:       PetscTruth  flg1,flg2,flg3;
659:       KSP         cksp;

661:       KSPGetPC(dmmg[i]->ksp,&pc);
662:       PCMGGetCoarseSolve(pc,&cksp);
663:       KSPGetPC(cksp,&pc);
664:       PetscTypeCompare((PetscObject)pc,PCILU,&flg1);
665:       PetscTypeCompare((PetscObject)pc,PCSOR,&flg2);
666:       PetscTypeCompare((PetscObject)pc,PETSC_NULL,&flg3);
667:       if (flg1 || flg2 || flg3) {
668:         KSPSetType(dmmg[i]->ksp,KSPPREONLY);
669:         PetscObjectGetComm((PetscObject) pc,&comm);
670:         MPI_Comm_size(comm,&size);
671:         if (size > 1) {
672:           PCSetType(pc,PCREDUNDANT);
673:         } else {
674:           PCSetType(pc,PCLU);
675:         }
676:       }
677:     }

679:     dmmg[i]->computejacobian = jacobian;
680:     if (useFAS) {
681:       if (cookie == DM_COOKIE) {
682: #if defined(PETSC_HAVE_ADIC)
683:         if (fasBlock) {
684:           dmmg[i]->solve     = DMMGSolveFASb;
685:         } else if(fasGMRES) {
686:           dmmg[i]->solve     = DMMGSolveFAS_NGMRES;
687:         } else {
688:           dmmg[i]->solve     = DMMGSolveFAS4;
689:         }
690: #else
691:         SETERRQ(PETSC_ERR_SUP, "Must use ADIC for structured FAS.");
692: #endif
693:       } else {
694: #if defined(PETSC_HAVE_SIEVE)
695:         dmmg[i]->solve       = DMMGSolveFAS_Mesh;
696: #endif
697:       }
698:     } else {
699:       dmmg[i]->solve         = DMMGSolveSNES;
700:     }
701:   }

703:   if (jacobian == DMMGComputeJacobianWithFD) {
704:     ISColoring iscoloring;

706:     for (i=0; i<nlevels; i++) {
707:       if (dmmg[0]->getcoloringfrommat) {
708:         MatGetColoring(dmmg[i]->B,(MatColoringType)MATCOLORING_SL,&iscoloring);
709:       } else {
710:         DMGetColoring(dmmg[i]->dm,dmmg[0]->isctype,dmmg[i]->mtype,&iscoloring);
711:       }
712:       MatFDColoringCreate(dmmg[i]->B,iscoloring,&dmmg[i]->fdcoloring);
713:       ISColoringDestroy(iscoloring);
714:       if (function == DMMGFormFunction) function = DMMGFormFunctionFD;
715:       MatFDColoringSetFunction(dmmg[i]->fdcoloring,(PetscErrorCode(*)(void))function,dmmg[i]);
716:       MatFDColoringSetFromOptions(dmmg[i]->fdcoloring);
717:     }
718: #if defined(PETSC_HAVE_ADIC)
719:   } else if (jacobian == DMMGComputeJacobianWithAdic) {
720:     for (i=0; i<nlevels; i++) {
721:       ISColoring iscoloring;
722:       DMGetColoring(dmmg[i]->dm,IS_COLORING_GHOSTED,dmmg[i]->mtype,&iscoloring);
723:       MatSetColoring(dmmg[i]->B,iscoloring);
724:       ISColoringDestroy(iscoloring);
725:     }
726: #endif
727:   }
728:   if (!useFAS) {
729:     for (i=0; i<nlevels; i++) {
730:       SNESSetJacobian(dmmg[i]->snes,dmmg[i]->J,dmmg[i]->B,DMMGComputeJacobian_Multigrid,dmmg);
731:     }
732:   }

734:   /* Create interpolation scaling */
735:   for (i=1; i<nlevels; i++) {
736:     DMGetInterpolationScale(dmmg[i-1]->dm,dmmg[i]->dm,dmmg[i]->R,&dmmg[i]->Rscale);
737:   }

739:   if (useFAS) {
740:     PetscTruth flg;

742:     for(i = 0; i < nlevels; i++) {
743:       VecDuplicate(dmmg[i]->b,&dmmg[i]->w);
744:       if (cookie == DM_COOKIE) {
745: #if defined(PETSC_HAVE_ADIC)
746:         NLFCreate_DAAD(&dmmg[i]->nlf);
747:         NLFDAADSetDA_DAAD(dmmg[i]->nlf,(DA)dmmg[i]->dm);
748:         NLFDAADSetCtx_DAAD(dmmg[i]->nlf,dmmg[i]->user);
749:         NLFDAADSetResidual_DAAD(dmmg[i]->nlf,dmmg[i]->r);
750:         NLFDAADSetNewtonIterations_DAAD(dmmg[i]->nlf,fasMaxIter);
751: #endif
752:       } else {
753:       }

755:       dmmg[i]->monitor      = monitor;
756:       dmmg[i]->monitorall   = monitorAll;
757:       dmmg[i]->presmooth    = fasPresmooth;
758:       dmmg[i]->postsmooth   = fasPostsmooth;
759:       dmmg[i]->coarsesmooth = fasCoarsesmooth;
760:       dmmg[i]->rtol         = fasRtol;
761:       dmmg[i]->abstol       = fasAbstol;
762:     }

764:     flg  = PETSC_FALSE;
765:     PetscOptionsGetTruth(0, "-dmmg_fas_view", &flg,PETSC_NULL);
766:     if (flg) {
767:       for(i = 0; i < nlevels; i++) {
768:         if (i == 0) {
769:           PetscPrintf(dmmg[i]->comm,"FAS Solver Parameters\n");
770:           PetscPrintf(dmmg[i]->comm,"  rtol %G atol %G\n",dmmg[i]->rtol,dmmg[i]->abstol);
771:           PetscPrintf(dmmg[i]->comm,"             coarsesmooths %D\n",dmmg[i]->coarsesmooth);
772:           PetscPrintf(dmmg[i]->comm,"             Newton iterations %D\n",fasMaxIter);
773:         } else {
774:           PetscPrintf(dmmg[i]->comm,"  level %D   presmooths    %D\n",i,dmmg[i]->presmooth);
775:           PetscPrintf(dmmg[i]->comm,"             postsmooths   %D\n",dmmg[i]->postsmooth);
776:           PetscPrintf(dmmg[i]->comm,"             Newton iterations %D\n",fasMaxIter);
777:         }
778:         if (fasBlock) {
779:           PetscPrintf(dmmg[i]->comm,"  using point-block smoothing\n");
780:         } else if(fasGMRES) {
781:           PetscPrintf(dmmg[i]->comm,"  using non-linear gmres\n");
782:         }
783:       }
784:     }
785:   }
786:   return(0);
787: }

791: /*@C
792:     DMMGSetFromOptions - Sets various options associated with the DMMG object

794:     Collective on DMMG

796:     Input Parameter:
797: .   dmmg - the context


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

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

804:     Level: advanced

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

808: @*/
809: PetscErrorCode  DMMGSetFromOptions(DMMG *dmmg)
810: {
811:   PetscErrorCode          ierr;
812:   PetscInt                i,nlevels = dmmg[0]->nlevels;

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

817:   for (i=0; i<nlevels; i++) {
818:     SNESSetFromOptions(dmmg[i]->snes);
819:   }
820:   return(0);
821: }

825: /*@C
826:     DMMGSetSNESLocalFD - Sets the local user function that is used to approximately compute the Jacobian
827:         via finite differences.

829:     Collective on DMMG

831:     Input Parameter:
832: +   dmmg - the context
833: -   function - the function that defines the nonlinear system

835:     Level: intermediate

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

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

845:   for (i=0; i<nlevels; i++) {
846:     dmmg[i]->lfj = (PetscErrorCode (*)(void))function;
847:   }
848:   return(0);
849: }


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

857:   Collective on DMMG

859:   Input Parameter:
860: . dmmg - the context

862:   Output Parameters:
863: + function - the function that defines the nonlinear system
864: - jacobian - function defines the local part of the Jacobian

866:   Level: intermediate

868: .seealso DMMGCreate(), DMMGDestroy, DMMGSetKSP(), DMMGSetSNES(), DMMGSetSNESLocal()
869: @*/
870: PetscErrorCode DMMGGetSNESLocal(DMMG *dmmg,DALocalFunction1 *function, DALocalFunction1 *jacobian)
871: {
872:   PetscCookie    cookie;

876:   PetscObjectGetCookie((PetscObject) dmmg[0]->dm, &cookie);
877:   if (cookie == DM_COOKIE) {
878:     DAGetLocalFunction((DA) dmmg[0]->dm, function);
879:     DAGetLocalJacobian((DA) dmmg[0]->dm, jacobian);
880:   } else {
881: #ifdef PETSC_HAVE_SIEVE
882:     MeshGetLocalFunction((Mesh) dmmg[0]->dm, (PetscErrorCode (**)(Mesh,SectionReal,SectionReal,void*)) function);
883:     MeshGetLocalJacobian((Mesh) dmmg[0]->dm, (PetscErrorCode (**)(Mesh,SectionReal,Mat,void*)) jacobian);
884: #else
885:     SETERRQ(PETSC_ERR_SUP, "Unstructured grids only supported when Sieve is enabled.\nReconfigure with --with-sieve.");
886: #endif
887:   }
888:   return(0);
889: }

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

895:     Collective on DMMG

897:    Synopsis:
898:    PetscErrorCode DMMGSetSNESLocal(DMMG *dmmg,DALocalFunction1 function, DALocalFunction1 jacobian,
899:                         DALocalFunction1 ad_function, DALocalFunction1 admf_function);

901:     Input Parameter:
902: +   dmmg - the context
903: .   function - the function that defines the nonlinear system
904: .   jacobian - function defines the local part of the Jacobian
905: .   ad_function - the name of the function with an ad_ prefix. This is ignored currently
906: -   admf_function - the name of the function with an ad_ prefix. This is ignored currently

908:     Options Database Keys:
909: +    -dmmg_jacobian_fd
910: .    -dmmg_jacobian_ad
911: .    -dmmg_jacobian_mf_fd_operator
912: .    -dmmg_jacobian_mf_fd
913: .    -dmmg_jacobian_mf_ad_operator
914: -    -dmmg_jacobian_mf_ad


917:     Level: intermediate

919:     Notes: 
920:     If the Jacobian is not provided, this routine
921:     uses finite differencing to approximate the Jacobian.

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

925: M*/

929: PetscErrorCode DMMGSetSNESLocal_Private(DMMG *dmmg,DALocalFunction1 function,DALocalFunction1 jacobian,DALocalFunction1 ad_function,DALocalFunction1 admf_function)
930: {
932:   PetscInt       i,nlevels = dmmg[0]->nlevels;
933:   PetscCookie    cookie;
934:   PetscErrorCode (*computejacobian)(SNES,Vec,Mat*,Mat*,MatStructure*,void*) = 0;


938:   if (jacobian)         computejacobian = DMMGComputeJacobian;
939: #if defined(PETSC_HAVE_ADIC)
940:   else if (ad_function) computejacobian = DMMGComputeJacobianWithAdic;
941: #endif
942:   CHKMEMQ;
943:   PetscObjectGetCookie((PetscObject) dmmg[0]->dm,&cookie);
944:   if (cookie == DM_COOKIE) {
945:     PetscTruth flag;
946:     /* it makes no sense to use an option to decide on ghost, it depends on whether the 
947:        formfunctionlocal computes ghost values in F or not. */
948:     PetscOptionsHasName(PETSC_NULL, "-dmmg_form_function_ghost", &flag);
949:     if (flag) {
950:       DMMGSetSNES(dmmg,DMMGFormFunctionGhost,computejacobian);
951:     } else {
952:       DMMGSetSNES(dmmg,DMMGFormFunction,computejacobian);
953:     }
954:     for (i=0; i<nlevels; i++) {
955:       dmmg[i]->isctype  = IS_COLORING_GHOSTED;   /* switch to faster version since have local function evaluation */
956:       DASetLocalFunction((DA)dmmg[i]->dm,function);
957:       dmmg[i]->lfj = (PetscErrorCode (*)(void))function;
958:       DASetLocalJacobian((DA)dmmg[i]->dm,jacobian);
959:       DASetLocalAdicFunction((DA)dmmg[i]->dm,ad_function);
960:       DASetLocalAdicMFFunction((DA)dmmg[i]->dm,admf_function);
961:     }
962:     CHKMEMQ;
963:   } else {
964: #ifdef PETSC_HAVE_SIEVE
965:     DMMGSetSNES(dmmg, DMMGFormFunctionMesh, DMMGComputeJacobianMesh);
966:     for (i=0; i<nlevels; i++) {
967:       MeshSetLocalFunction((Mesh) dmmg[i]->dm, (PetscErrorCode (*)(Mesh,SectionReal,SectionReal,void*)) function);
968:       dmmg[i]->lfj = (PetscErrorCode (*)(void)) function;
969:       MeshSetLocalJacobian((Mesh) dmmg[i]->dm, (PetscErrorCode (*)(Mesh,SectionReal,Mat,void*)) jacobian);
970:       // Setup a work section
971:       SectionReal defaultSec, constantSec;
972:       PetscTruth  hasConstant;

974:       MeshGetSectionReal((Mesh) dmmg[i]->dm, "default", &defaultSec);
975:       MeshHasSectionReal((Mesh) dmmg[i]->dm, "constant", &hasConstant);
976:       if (!hasConstant) {
977:         SectionRealDuplicate(defaultSec, &constantSec);
978:         PetscObjectSetName((PetscObject) constantSec, "constant");
979:         MeshSetSectionReal((Mesh) dmmg[i]->dm, constantSec);
980:         SectionRealDestroy(constantSec);
981:       }
982:     }
983:     CHKMEMQ;
984: #else
985:     SETERRQ(PETSC_ERR_SUP, "Unstructured grids only supported when Sieve is enabled.\nReconfigure with --with-sieve.");
986: #endif
987:   }
988:   CHKMEMQ;
989:   return(0);
990: }

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

1002:   /* copy u into interior part of U */
1003:   DAGetScatter((DA)dmmg->dm,0,&gtol,0);
1004:   VecScatterBegin(gtol,u,U,INSERT_VALUES,SCATTER_FORWARD_LOCAL);
1005:   VecScatterEnd(gtol,u,U,INSERT_VALUES,SCATTER_FORWARD_LOCAL);
1006:   DAFormFunctioni1((DA)dmmg->dm,i,U,r,dmmg->user);
1007:   return(0);
1008: }

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

1020:   /* copy u into interior part of U */
1021:   DAGetScatter((DA)dmmg->dm,0,&gtol,0);
1022:   VecScatterBegin(gtol,u,U,INSERT_VALUES,SCATTER_FORWARD_LOCAL);
1023:   VecScatterEnd(gtol,u,U,INSERT_VALUES,SCATTER_FORWARD_LOCAL);
1024:   DAFormFunctionib1((DA)dmmg->dm,i,U,r,dmmg->user);
1025:   return(0);
1026: }

1030: PetscErrorCode DMMGFunctioniBase(void* ctx,Vec u)
1031: {
1032:   DMMG           dmmg = (DMMG)ctx;
1033:   Vec            U = dmmg->lwork1;

1037:   DAGlobalToLocalBegin((DA)dmmg->dm,u,INSERT_VALUES,U);
1038:   DAGlobalToLocalEnd((DA)dmmg->dm,u,INSERT_VALUES,U);
1039:   return(0);
1040: }

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

1050:   for (i=0; i<nlevels; i++) {
1051:     DASetLocalFunctioni((DA)dmmg[i]->dm,functioni);
1052:     DASetLocalAdicFunctioni((DA)dmmg[i]->dm,adi);
1053:     DASetLocalAdicMFFunctioni((DA)dmmg[i]->dm,adimf);
1054:     MatMFFDSetFunctioni(dmmg[i]->J,DMMGFunctioni);
1055:     MatMFFDSetFunctioniBase(dmmg[i]->J,DMMGFunctioniBase);
1056:     if (!dmmg[i]->lwork1) {
1057:       DACreateLocalVector((DA)dmmg[i]->dm,&dmmg[i]->lwork1);
1058:     }
1059:   }
1060:   return(0);
1061: }

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

1071:   for (i=0; i<nlevels; i++) {
1072:     DASetLocalFunctionib((DA)dmmg[i]->dm,functioni);
1073:     DASetLocalAdicFunctionib((DA)dmmg[i]->dm,adi);
1074:     DASetLocalAdicMFFunctionib((DA)dmmg[i]->dm,adimf);
1075:     if (!dmmg[i]->lwork1) {
1076:       DACreateLocalVector((DA)dmmg[i]->dm,&dmmg[i]->lwork1);
1077:     }
1078:   }
1079:   return(0);
1080: }

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

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

1095:   (*dmmg->dm->ops->forminitialguess)(dmmg->dm,localfunc,x,0);
1096:   return(0);
1097: }

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

1104:     Collective on DMMG

1106:     Input Parameter:
1107: +   dmmg - the context
1108: -   localguess - the function that computes the initial guess

1110:     Level: intermediate

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

1114: @*/
1115: PetscErrorCode DMMGSetInitialGuessLocal(DMMG *dmmg,PetscErrorCode (*localguess)(void))
1116: {

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

1122:   DMMGSetInitialGuess(dmmg,DMMGInitialGuess_Local);
1123:   return(0);
1124: }

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

1131:     Collective on DMMG

1133:     Input Parameter:
1134: +   dmmg - the context
1135: -   isctype - IS_COLORING_GHOSTED (default) or IS_COLORING_GLOBAL

1137:     Options Database:
1138: .   -dmmg_iscoloring_type <ghosted or global>

1140:     Notes: ghosted coloring requires using DMMGSetSNESLocal()

1142:     Level: intermediate

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

1146: @*/
1147: PetscErrorCode DMMGSetISColoringType(DMMG *dmmg,ISColoringType isctype)
1148: {
1150:   dmmg[0]->isctype = isctype;
1151:   return(0);
1152: }


1157: /*@C
1158:     DMMGSetUp - Called after DMMGSetSNES() and (optionally) DMMGSetFromOptions()

1160:     Collective on DMMG

1162:     Input Parameter:
1163: .   dmmg - the context

1165:     Notes: Currently this must be called by the user (if they want to). It checks to see if fieldsplit preconditioner
1166:            is being used and manages it.

1168:     Level: advanced

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

1172: @*/
1173: PetscErrorCode  DMMGSetUp(DMMG *dmmg)
1174: {
1176:   PetscInt       i,nDM;
1177:   PetscTruth     fieldsplit,dmcomposite;
1178:   KSP            ksp;
1179:   SNES           snes;
1180:   PC             pc;
1181:   IS             *fields;

1184:   snes = DMMGGetSNES(dmmg);
1185:   if (snes) {
1186:     SNESGetKSP(snes,&ksp);
1187:   } else {
1188:     ksp = DMMGGetKSP(dmmg);
1189:   }
1190:   KSPGetPC(ksp,&pc);
1191:   PetscTypeCompare((PetscObject)pc,PCFIELDSPLIT,&fieldsplit);
1192:   PetscTypeCompare((PetscObject)DMMGGetDM(dmmg),"DMComposite",&dmcomposite);
1193:   if (fieldsplit && dmcomposite) {
1194:     PetscInfo(ksp,"Setting up physics based fieldsplit preconditioner\n");
1195:     DMCompositeGetNumberDM((DMComposite)DMMGGetDM(dmmg),&nDM);
1196:     DMCompositeGetGlobalISs((DMComposite)DMMGGetDM(dmmg),&fields);
1197:     for (i=0; i<nDM; i++) {
1198:       PCFieldSplitSetIS(pc,fields[i]);
1199:       ISDestroy(fields[i]);
1200:     }
1201:     PetscFree(fields);
1202:   }
1203:   PCSetDA(pc,(DA)DMMGGetDM(dmmg));

1205:   return(0);
1206: }