Actual source code: dmsnes.c

  1: #include <petsc/private/snesimpl.h>
  2: #include <petsc/private/dmimpl.h>

  4: static PetscErrorCode DMSNESDestroy(DMSNES *kdm)
  5: {

  9:   if (!*kdm) return(0);
 11:   if (--((PetscObject)(*kdm))->refct > 0) {*kdm = NULL; return(0);}
 12:   if ((*kdm)->ops->destroy) {((*kdm)->ops->destroy)(*kdm);}
 13:   PetscHeaderDestroy(kdm);
 14:   return(0);
 15: }

 17: PetscErrorCode DMSNESLoad(DMSNES kdm,PetscViewer viewer)
 18: {

 22:   PetscViewerBinaryRead(viewer,&kdm->ops->computefunction,1,NULL,PETSC_FUNCTION);
 23:   PetscViewerBinaryRead(viewer,&kdm->ops->computejacobian,1,NULL,PETSC_FUNCTION);
 24:   return(0);
 25: }

 27: PetscErrorCode DMSNESView(DMSNES kdm,PetscViewer viewer)
 28: {
 30:   PetscBool      isascii,isbinary;

 33:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
 34:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);
 35:   if (isascii) {
 36: #if defined(PETSC_SERIALIZE_FUNCTIONS) && defined(PETSC_SERIALIZE_FUNCTIONS_VIEW)
 37:     const char *fname;

 39:     PetscFPTFind(kdm->ops->computefunction,&fname);
 40:     if (fname) {
 41:       PetscViewerASCIIPrintf(viewer,"Function used by SNES: %s\n",fname);
 42:     }
 43:     PetscFPTFind(kdm->ops->computejacobian,&fname);
 44:     if (fname) {
 45:       PetscViewerASCIIPrintf(viewer,"Jacobian function used by SNES: %s\n",fname);
 46:     }
 47: #endif
 48:   } else if (isbinary) {
 49:     struct {
 50:       PetscErrorCode (*func)(SNES,Vec,Vec,void*);
 51:     } funcstruct;
 52:     struct {
 53:       PetscErrorCode (*jac)(SNES,Vec,Mat,Mat,void*);
 54:     } jacstruct;
 55:     funcstruct.func = kdm->ops->computefunction;
 56:     jacstruct.jac   = kdm->ops->computejacobian;
 57:     PetscViewerBinaryWrite(viewer,&funcstruct,1,PETSC_FUNCTION);
 58:     PetscViewerBinaryWrite(viewer,&jacstruct,1,PETSC_FUNCTION);
 59:   }
 60:   return(0);
 61: }

 63: static PetscErrorCode DMSNESCreate(MPI_Comm comm,DMSNES *kdm)
 64: {

 68:   SNESInitializePackage();
 69:   PetscHeaderCreate(*kdm, DMSNES_CLASSID,  "DMSNES", "DMSNES", "DMSNES", comm, DMSNESDestroy, DMSNESView);
 70:   return(0);
 71: }

 73: /* Attaches the DMSNES to the coarse level.
 74:  * Under what conditions should we copy versus duplicate?
 75:  */
 76: static PetscErrorCode DMCoarsenHook_DMSNES(DM dm,DM dmc,void *ctx)
 77: {

 81:   DMCopyDMSNES(dm,dmc);
 82:   return(0);
 83: }

 85: /* This could restrict auxiliary information to the coarse level.
 86:  */
 87: static PetscErrorCode DMRestrictHook_DMSNES(DM dm,Mat Restrict,Vec rscale,Mat Inject,DM dmc,void *ctx)
 88: {

 91:   return(0);
 92: }

 94: /* Attaches the DMSNES to the subdomain. */
 95: static PetscErrorCode DMSubDomainHook_DMSNES(DM dm,DM subdm,void *ctx)
 96: {

100:   DMCopyDMSNES(dm,subdm);
101:   return(0);
102: }

104: /* This could restrict auxiliary information to the coarse level.
105:  */
106: static PetscErrorCode DMSubDomainRestrictHook_DMSNES(DM dm,VecScatter gscat,VecScatter lscat,DM subdm,void *ctx)
107: {

110:   return(0);
111: }

113: static PetscErrorCode DMRefineHook_DMSNES(DM dm,DM dmf,void *ctx)
114: {

118:   DMCopyDMSNES(dm,dmf);
119:   return(0);
120: }

122: /* This could restrict auxiliary information to the coarse level.
123:  */
124: static PetscErrorCode DMInterpolateHook_DMSNES(DM dm,Mat Interp,DM dmf,void *ctx)
125: {

128:   return(0);
129: }

131: /*@C
132:    DMSNESCopy - copies the information in a DMSNES to another DMSNES

134:    Not Collective

136:    Input Argument:
137: +  kdm - Original DMSNES
138: -  nkdm - DMSNES to receive the data, should have been created with DMSNESCreate()

140:    Level: developer

142: .seealso: DMSNESCreate(), DMSNESDestroy()
143: @*/
144: PetscErrorCode DMSNESCopy(DMSNES kdm,DMSNES nkdm)
145: {

151:   nkdm->ops->computefunction  = kdm->ops->computefunction;
152:   nkdm->ops->computejacobian  = kdm->ops->computejacobian;
153:   nkdm->ops->computegs        = kdm->ops->computegs;
154:   nkdm->ops->computeobjective = kdm->ops->computeobjective;
155:   nkdm->ops->computepjacobian = kdm->ops->computepjacobian;
156:   nkdm->ops->computepfunction = kdm->ops->computepfunction;
157:   nkdm->ops->destroy          = kdm->ops->destroy;
158:   nkdm->ops->duplicate        = kdm->ops->duplicate;

160:   nkdm->functionctx  = kdm->functionctx;
161:   nkdm->gsctx        = kdm->gsctx;
162:   nkdm->pctx         = kdm->pctx;
163:   nkdm->jacobianctx  = kdm->jacobianctx;
164:   nkdm->objectivectx = kdm->objectivectx;
165:   nkdm->originaldm   = kdm->originaldm;

167:   /*
168:   nkdm->fortran_func_pointers[0] = kdm->fortran_func_pointers[0];
169:   nkdm->fortran_func_pointers[1] = kdm->fortran_func_pointers[1];
170:   nkdm->fortran_func_pointers[2] = kdm->fortran_func_pointers[2];
171:   */

173:   /* implementation specific copy hooks */
174:   if (kdm->ops->duplicate) {(*kdm->ops->duplicate)(kdm,nkdm);}
175:   return(0);
176: }

178: /*@C
179:    DMGetDMSNES - get read-only private DMSNES context from a DM

181:    Not Collective

183:    Input Argument:
184: .  dm - DM to be used with SNES

186:    Output Argument:
187: .  snesdm - private DMSNES context

189:    Level: developer

191:    Notes:
192:    Use DMGetDMSNESWrite() if write access is needed. The DMSNESSetXXX API should be used wherever possible.

194: .seealso: DMGetDMSNESWrite()
195: @*/
196: PetscErrorCode DMGetDMSNES(DM dm,DMSNES *snesdm)
197: {

202:   *snesdm = (DMSNES) dm->dmsnes;
203:   if (!*snesdm) {
204:     PetscInfo(dm,"Creating new DMSNES\n");
205:     DMSNESCreate(PetscObjectComm((PetscObject)dm),snesdm);

207:     dm->dmsnes            = (PetscObject) *snesdm;
208:     (*snesdm)->originaldm = dm;
209:     DMCoarsenHookAdd(dm,DMCoarsenHook_DMSNES,DMRestrictHook_DMSNES,NULL);
210:     DMRefineHookAdd(dm,DMRefineHook_DMSNES,DMInterpolateHook_DMSNES,NULL);
211:     DMSubDomainHookAdd(dm,DMSubDomainHook_DMSNES,DMSubDomainRestrictHook_DMSNES,NULL);
212:   }
213:   return(0);
214: }

216: /*@C
217:    DMGetDMSNESWrite - get write access to private DMSNES context from a DM

219:    Not Collective

221:    Input Argument:
222: .  dm - DM to be used with SNES

224:    Output Argument:
225: .  snesdm - private DMSNES context

227:    Level: developer

229: .seealso: DMGetDMSNES()
230: @*/
231: PetscErrorCode DMGetDMSNESWrite(DM dm,DMSNES *snesdm)
232: {
234:   DMSNES         sdm;

238:   DMGetDMSNES(dm,&sdm);
239:   if (!sdm->originaldm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"DMSNES has a NULL originaldm");
240:   if (sdm->originaldm != dm) {  /* Copy on write */
241:     DMSNES oldsdm = sdm;
242:     PetscInfo(dm,"Copying DMSNES due to write\n");
243:     DMSNESCreate(PetscObjectComm((PetscObject)dm),&sdm);
244:     DMSNESCopy(oldsdm,sdm);
245:     DMSNESDestroy((DMSNES*)&dm->dmsnes);
246:     dm->dmsnes = (PetscObject)sdm;
247:     sdm->originaldm = dm;
248:   }
249:   *snesdm = sdm;
250:   return(0);
251: }

253: /*@C
254:    DMCopyDMSNES - copies a DM context to a new DM

256:    Logically Collective

258:    Input Arguments:
259: +  dmsrc - DM to obtain context from
260: -  dmdest - DM to add context to

262:    Level: developer

264:    Note:
265:    The context is copied by reference. This function does not ensure that a context exists.

267: .seealso: DMGetDMSNES(), SNESSetDM()
268: @*/
269: PetscErrorCode DMCopyDMSNES(DM dmsrc,DM dmdest)
270: {

276:   if (!dmdest->dmsnes) {DMSNESCreate(PetscObjectComm((PetscObject) dmdest), (DMSNES *) &dmdest->dmsnes);}
277:   DMSNESCopy((DMSNES) dmsrc->dmsnes, (DMSNES) dmdest->dmsnes);
278:   DMCoarsenHookAdd(dmdest,DMCoarsenHook_DMSNES,NULL,NULL);
279:   DMRefineHookAdd(dmdest,DMRefineHook_DMSNES,NULL,NULL);
280:   DMSubDomainHookAdd(dmdest,DMSubDomainHook_DMSNES,DMSubDomainRestrictHook_DMSNES,NULL);
281:   return(0);
282: }

284: /*@C
285:    DMSNESSetFunction - set SNES residual evaluation function

287:    Not Collective

289:    Input Arguments:
290: +  dm - DM to be used with SNES
291: .  f - residual evaluation function; see SNESFunction for details
292: -  ctx - context for residual evaluation

294:    Level: advanced

296:    Note:
297:    SNESSetFunction() is normally used, but it calls this function internally because the user context is actually
298:    associated with the DM.  This makes the interface consistent regardless of whether the user interacts with a DM or
299:    not. If DM took a more central role at some later date, this could become the primary method of setting the residual.

301: .seealso: DMSNESSetContext(), SNESSetFunction(), DMSNESSetJacobian(), SNESFunction
302: @*/
303: PetscErrorCode DMSNESSetFunction(DM dm,PetscErrorCode (*f)(SNES,Vec,Vec,void*),void *ctx)
304: {
306:   DMSNES         sdm;

310:   if (f || ctx) {
311:     DMGetDMSNESWrite(dm,&sdm);
312:   }
313:   if (f) sdm->ops->computefunction = f;
314:   if (ctx) sdm->functionctx = ctx;
315:   return(0);
316: }

318: /*@C
319:    DMSNESSetMFFunction - set SNES residual evaluation function used in applying the matrix-free Jacobian with -snes_mf_operator

321:    Logically Collective on dm

323:    Input Arguments:
324: +  dm - DM to be used with SNES
325: -  f - residual evaluation function; see SNESFunction for details

327:    Level: advanced

329: .seealso: DMSNESSetContext(), SNESSetFunction(), DMSNESSetJacobian(), SNESFunction, DMSNESSetFunction()
330: @*/
331: PetscErrorCode DMSNESSetMFFunction(DM dm,PetscErrorCode (*f)(SNES,Vec,Vec,void*),void *ctx)
332: {
334:   DMSNES         sdm;

338:   if (f || ctx) {
339:     DMGetDMSNESWrite(dm,&sdm);
340:   }
341:   if (f) sdm->ops->computemffunction = f;
342:   if (ctx) sdm->mffunctionctx = ctx;
343:   return(0);
344: }

346: /*@C
347:    DMSNESGetFunction - get SNES residual evaluation function

349:    Not Collective

351:    Input Argument:
352: .  dm - DM to be used with SNES

354:    Output Arguments:
355: +  f - residual evaluation function; see SNESFunction for details
356: -  ctx - context for residual evaluation

358:    Level: advanced

360:    Note:
361:    SNESGetFunction() is normally used, but it calls this function internally because the user context is actually
362:    associated with the DM.

364: .seealso: DMSNESSetContext(), DMSNESSetFunction(), SNESSetFunction(), SNESFunction
365: @*/
366: PetscErrorCode DMSNESGetFunction(DM dm,PetscErrorCode (**f)(SNES,Vec,Vec,void*),void **ctx)
367: {
369:   DMSNES         sdm;

373:   DMGetDMSNES(dm,&sdm);
374:   if (f) *f = sdm->ops->computefunction;
375:   if (ctx) *ctx = sdm->functionctx;
376:   return(0);
377: }

379: /*@C
380:    DMSNESSetObjective - set SNES objective evaluation function

382:    Not Collective

384:    Input Arguments:
385: +  dm - DM to be used with SNES
386: .  obj - objective evaluation function; see SNESObjectiveFunction for details
387: -  ctx - context for residual evaluation

389:    Level: advanced

391: .seealso: DMSNESSetContext(), SNESGetObjective(), DMSNESSetFunction()
392: @*/
393: PetscErrorCode DMSNESSetObjective(DM dm,PetscErrorCode (*obj)(SNES,Vec,PetscReal*,void*),void *ctx)
394: {
396:   DMSNES         sdm;

400:   if (obj || ctx) {
401:     DMGetDMSNESWrite(dm,&sdm);
402:   }
403:   if (obj) sdm->ops->computeobjective = obj;
404:   if (ctx) sdm->objectivectx = ctx;
405:   return(0);
406: }

408: /*@C
409:    DMSNESGetObjective - get SNES objective evaluation function

411:    Not Collective

413:    Input Argument:
414: .  dm - DM to be used with SNES

416:    Output Arguments:
417: +  obj- residual evaluation function; see SNESObjectiveFunction for details
418: -  ctx - context for residual evaluation

420:    Level: advanced

422:    Note:
423:    SNESGetFunction() is normally used, but it calls this function internally because the user context is actually
424:    associated with the DM.

426: .seealso: DMSNESSetContext(), DMSNESSetObjective(), SNESSetFunction()
427: @*/
428: PetscErrorCode DMSNESGetObjective(DM dm,PetscErrorCode (**obj)(SNES,Vec,PetscReal*,void*),void **ctx)
429: {
431:   DMSNES         sdm;

435:   DMGetDMSNES(dm,&sdm);
436:   if (obj) *obj = sdm->ops->computeobjective;
437:   if (ctx) *ctx = sdm->objectivectx;
438:   return(0);
439: }

441: /*@C
442:    DMSNESSetNGS - set SNES Gauss-Seidel relaxation function

444:    Not Collective

446:    Input Argument:
447: +  dm - DM to be used with SNES
448: .  f  - relaxation function, see SNESGSFunction
449: -  ctx - context for residual evaluation

451:    Level: advanced

453:    Note:
454:    SNESSetNGS() is normally used, but it calls this function internally because the user context is actually
455:    associated with the DM.  This makes the interface consistent regardless of whether the user interacts with a DM or
456:    not. If DM took a more central role at some later date, this could become the primary method of setting the residual.

458: .seealso: DMSNESSetContext(), SNESSetFunction(), DMSNESSetJacobian(), DMSNESSetFunction(), SNESGSFunction
459: @*/
460: PetscErrorCode DMSNESSetNGS(DM dm,PetscErrorCode (*f)(SNES,Vec,Vec,void*),void *ctx)
461: {
463:   DMSNES         sdm;

467:   if (f || ctx) {
468:     DMGetDMSNESWrite(dm,&sdm);
469:   }
470:   if (f) sdm->ops->computegs = f;
471:   if (ctx) sdm->gsctx = ctx;
472:   return(0);
473: }

475: /*@C
476:    DMSNESGetNGS - get SNES Gauss-Seidel relaxation function

478:    Not Collective

480:    Input Argument:
481: .  dm - DM to be used with SNES

483:    Output Arguments:
484: +  f - relaxation function which performs Gauss-Seidel sweeps, see SNESGSFunction
485: -  ctx - context for residual evaluation

487:    Level: advanced

489:    Note:
490:    SNESGetNGS() is normally used, but it calls this function internally because the user context is actually
491:    associated with the DM.  This makes the interface consistent regardless of whether the user interacts with a DM or
492:    not. If DM took a more central role at some later date, this could become the primary method of setting the residual.

494: .seealso: DMSNESSetContext(), SNESGetNGS(), DMSNESGetJacobian(), DMSNESGetFunction(), SNESNGSFunction
495: @*/
496: PetscErrorCode DMSNESGetNGS(DM dm,PetscErrorCode (**f)(SNES,Vec,Vec,void*),void **ctx)
497: {
499:   DMSNES         sdm;

503:   DMGetDMSNES(dm,&sdm);
504:   if (f) *f = sdm->ops->computegs;
505:   if (ctx) *ctx = sdm->gsctx;
506:   return(0);
507: }

509: /*@C
510:    DMSNESSetJacobian - set SNES Jacobian evaluation function

512:    Not Collective

514:    Input Argument:
515: +  dm - DM to be used with SNES
516: .  J - Jacobian evaluation function
517: -  ctx - context for residual evaluation

519:    Level: advanced

521:    Note:
522:    SNESSetJacobian() is normally used, but it calls this function internally because the user context is actually
523:    associated with the DM.  This makes the interface consistent regardless of whether the user interacts with a DM or
524:    not. If DM took a more central role at some later date, this could become the primary method of setting the Jacobian.

526: .seealso: DMSNESSetContext(), SNESSetFunction(), DMSNESGetJacobian(), SNESSetJacobian(), SNESJacobianFunction
527: @*/
528: PetscErrorCode DMSNESSetJacobian(DM dm,PetscErrorCode (*J)(SNES,Vec,Mat,Mat,void*),void *ctx)
529: {
531:   DMSNES         sdm;

535:   if (J || ctx) {
536:     DMGetDMSNESWrite(dm,&sdm);
537:   }
538:   if (J) sdm->ops->computejacobian = J;
539:   if (ctx) sdm->jacobianctx = ctx;
540:   return(0);
541: }

543: /*@C
544:    DMSNESGetJacobian - get SNES Jacobian evaluation function

546:    Not Collective

548:    Input Argument:
549: .  dm - DM to be used with SNES

551:    Output Arguments:
552: +  J - Jacobian evaluation function; see SNESJacobianFunction for all calling sequence
553: -  ctx - context for residual evaluation

555:    Level: advanced

557:    Note:
558:    SNESGetJacobian() is normally used, but it calls this function internally because the user context is actually
559:    associated with the DM.  This makes the interface consistent regardless of whether the user interacts with a DM or
560:    not. If DM took a more central role at some later date, this could become the primary method of setting the Jacobian.

562: .seealso: DMSNESSetContext(), SNESSetFunction(), DMSNESSetJacobian(), SNESJacobianFunction
563: @*/
564: PetscErrorCode DMSNESGetJacobian(DM dm,PetscErrorCode (**J)(SNES,Vec,Mat,Mat,void*),void **ctx)
565: {
567:   DMSNES         sdm;

571:   DMGetDMSNES(dm,&sdm);
572:   if (J) *J = sdm->ops->computejacobian;
573:   if (ctx) *ctx = sdm->jacobianctx;
574:   return(0);
575: }

577: /*@C
578:    DMSNESSetPicard - set SNES Picard iteration matrix and RHS evaluation functions.

580:    Not Collective

582:    Input Argument:
583: +  dm - DM to be used with SNES
584: .  b - RHS evaluation function
585: .  J - Picard matrix evaluation function
586: -  ctx - context for residual evaluation

588:    Level: advanced

590: .seealso: SNESSetPicard(), DMSNESSetFunction(), DMSNESSetJacobian()
591: @*/
592: PetscErrorCode DMSNESSetPicard(DM dm,PetscErrorCode (*b)(SNES,Vec,Vec,void*),PetscErrorCode (*J)(SNES,Vec,Mat,Mat,void*),void *ctx)
593: {
595:   DMSNES         sdm;

599:   DMGetDMSNES(dm,&sdm);
600:   if (b) sdm->ops->computepfunction = b;
601:   if (J) sdm->ops->computepjacobian = J;
602:   if (ctx) sdm->pctx = ctx;
603:   return(0);
604: }

606: /*@C
607:    DMSNESGetPicard - get SNES Picard iteration evaluation functions

609:    Not Collective

611:    Input Argument:
612: .  dm - DM to be used with SNES

614:    Output Arguments:
615: +  b - RHS evaluation function; see SNESFunction for details
616: .  J  - RHS evaluation function; see SNESJacobianFunction for detailsa
617: -  ctx - context for residual evaluation

619:    Level: advanced

621: .seealso: DMSNESSetContext(), SNESSetFunction(), DMSNESSetJacobian()
622: @*/
623: PetscErrorCode DMSNESGetPicard(DM dm,PetscErrorCode (**b)(SNES,Vec,Vec,void*),PetscErrorCode (**J)(SNES,Vec,Mat,Mat,void*),void **ctx)
624: {
626:   DMSNES         sdm;

630:   DMGetDMSNES(dm,&sdm);
631:   if (b) *b = sdm->ops->computepfunction;
632:   if (J) *J = sdm->ops->computepjacobian;
633:   if (ctx) *ctx = sdm->pctx;
634:   return(0);
635: }