Actual source code: dmdasnes.c

petsc-dev 2014-02-02
Report Typos and Errors
  1: #include <petscdmda.h>          /*I "petscdmda.h" I*/
  2: #include <petsc-private/dmimpl.h>
  3: #include <petsc-private/snesimpl.h>   /*I "petscsnes.h" I*/

  5: /* This structure holds the user-provided DMDA callbacks */
  6: typedef struct {
  7:   PetscErrorCode (*residuallocal)(DMDALocalInfo*,void*,void*,void*);
  8:   PetscErrorCode (*jacobianlocal)(DMDALocalInfo*,void*,Mat,Mat,MatStructure*,void*);
  9:   PetscErrorCode (*objectivelocal)(DMDALocalInfo*,void*,PetscReal*,void*);
 10:   void       *residuallocalctx;
 11:   void       *jacobianlocalctx;
 12:   void       *objectivelocalctx;
 13:   InsertMode residuallocalimode;

 15:   /*   For Picard iteration defined locally */
 16:   PetscErrorCode (*rhsplocal)(DMDALocalInfo*,void*,void*,void*);
 17:   PetscErrorCode (*jacobianplocal)(DMDALocalInfo*,void*,Mat,Mat,MatStructure*,void*);
 18:   void *picardlocalctx;
 19: } DMSNES_DA;

 23: static PetscErrorCode DMSNESDestroy_DMDA(DMSNES sdm)
 24: {

 28:   PetscFree(sdm->data);
 29:   return(0);
 30: }

 34: static PetscErrorCode DMSNESDuplicate_DMDA(DMSNES oldsdm,DMSNES sdm)
 35: {

 39:   PetscNewLog(sdm,(DMSNES_DA**)&sdm->data);
 40:   if (oldsdm->data) {
 41:     PetscMemcpy(sdm->data,oldsdm->data,sizeof(DMSNES_DA));
 42:   }
 43:   return(0);
 44: }


 49: static PetscErrorCode DMDASNESGetContext(DM dm,DMSNES sdm,DMSNES_DA  **dmdasnes)
 50: {

 54:   *dmdasnes = NULL;
 55:   if (!sdm->data) {
 56:     PetscNewLog(dm,(DMSNES_DA**)&sdm->data);
 57:     sdm->ops->destroy   = DMSNESDestroy_DMDA;
 58:     sdm->ops->duplicate = DMSNESDuplicate_DMDA;
 59:   }
 60:   *dmdasnes = (DMSNES_DA*)sdm->data;
 61:   return(0);
 62: }

 66: /*
 67:   This function should eventually replace:
 68:     DMDAComputeFunction() and DMDAComputeFunction1()
 69:  */
 70: static PetscErrorCode SNESComputeFunction_DMDA(SNES snes,Vec X,Vec F,void *ctx)
 71: {
 73:   DM             dm;
 74:   DMSNES_DA      *dmdasnes = (DMSNES_DA*)ctx;
 75:   DMDALocalInfo  info;
 76:   Vec            Xloc;
 77:   void           *x,*f;

 83:   if (!dmdasnes->residuallocal) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_PLIB,"Corrupt context");
 84:   SNESGetDM(snes,&dm);
 85:   DMGetLocalVector(dm,&Xloc);
 86:   DMGlobalToLocalBegin(dm,X,INSERT_VALUES,Xloc);
 87:   DMGlobalToLocalEnd(dm,X,INSERT_VALUES,Xloc);
 88:   DMDAGetLocalInfo(dm,&info);
 89:   DMDAVecGetArray(dm,Xloc,&x);
 90:   switch (dmdasnes->residuallocalimode) {
 91:   case INSERT_VALUES: {
 92:     DMDAVecGetArray(dm,F,&f);
 93:     CHKMEMQ;
 94:     (*dmdasnes->residuallocal)(&info,x,f,dmdasnes->residuallocalctx);
 95:     CHKMEMQ;
 96:     DMDAVecRestoreArray(dm,F,&f);
 97:   } break;
 98:   case ADD_VALUES: {
 99:     Vec Floc;
100:     DMGetLocalVector(dm,&Floc);
101:     VecZeroEntries(Floc);
102:     DMDAVecGetArray(dm,Floc,&f);
103:     CHKMEMQ;
104:     (*dmdasnes->residuallocal)(&info,x,f,dmdasnes->residuallocalctx);
105:     CHKMEMQ;
106:     DMDAVecRestoreArray(dm,Floc,&f);
107:     VecZeroEntries(F);
108:     DMLocalToGlobalBegin(dm,Floc,ADD_VALUES,F);
109:     DMLocalToGlobalEnd(dm,Floc,ADD_VALUES,F);
110:     DMRestoreLocalVector(dm,&Floc);
111:   } break;
112:   default: SETERRQ1(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_INCOMP,"Cannot use imode=%d",(int)dmdasnes->residuallocalimode);
113:   }
114:   DMDAVecRestoreArray(dm,Xloc,&x);
115:   DMRestoreLocalVector(dm,&Xloc);
116:   return(0);
117: }

121: /*
122:   This function should eventually replace:
123:     DMDAComputeFunction() and DMDAComputeFunction1()
124:  */
125: static PetscErrorCode SNESComputeObjective_DMDA(SNES snes,Vec X,PetscReal *ob,void *ctx)
126: {
128:   DM             dm;
129:   DMSNES_DA      *dmdasnes = (DMSNES_DA*)ctx;
130:   DMDALocalInfo  info;
131:   Vec            Xloc;
132:   void           *x;

138:   if (!dmdasnes->objectivelocal) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_PLIB,"Corrupt context");
139:   SNESGetDM(snes,&dm);
140:   DMGetLocalVector(dm,&Xloc);
141:   DMGlobalToLocalBegin(dm,X,INSERT_VALUES,Xloc);
142:   DMGlobalToLocalEnd(dm,X,INSERT_VALUES,Xloc);
143:   DMDAGetLocalInfo(dm,&info);
144:   DMDAVecGetArray(dm,Xloc,&x);
145:   CHKMEMQ;
146:   (*dmdasnes->objectivelocal)(&info,x,ob,dmdasnes->objectivelocalctx);
147:   CHKMEMQ;
148:   DMDAVecRestoreArray(dm,Xloc,&x);
149:   DMRestoreLocalVector(dm,&Xloc);
150:   return(0);
151: }


156: static PetscErrorCode SNESComputeJacobian_DMDA(SNES snes,Vec X,Mat *A,Mat *B,MatStructure *mstr,void *ctx)
157: {
159:   DM             dm;
160:   DMSNES_DA      *dmdasnes = (DMSNES_DA*)ctx;
161:   DMDALocalInfo  info;
162:   Vec            Xloc;
163:   void           *x;

166:   if (!dmdasnes->residuallocal) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_PLIB,"Corrupt context");
167:   SNESGetDM(snes,&dm);

169:   if (dmdasnes->jacobianlocal) {
170:     DMGetLocalVector(dm,&Xloc);
171:     DMGlobalToLocalBegin(dm,X,INSERT_VALUES,Xloc);
172:     DMGlobalToLocalEnd(dm,X,INSERT_VALUES,Xloc);
173:     DMDAGetLocalInfo(dm,&info);
174:     DMDAVecGetArray(dm,Xloc,&x);
175:     CHKMEMQ;
176:     (*dmdasnes->jacobianlocal)(&info,x,*A,*B,mstr,dmdasnes->jacobianlocalctx);
177:     CHKMEMQ;
178:     DMDAVecRestoreArray(dm,Xloc,&x);
179:     DMRestoreLocalVector(dm,&Xloc);
180:   } else {
181:     MatFDColoring fdcoloring;
182:     PetscObjectQuery((PetscObject)dm,"DMDASNES_FDCOLORING",(PetscObject*)&fdcoloring);
183:     if (!fdcoloring) {
184:       ISColoring coloring;

186:       DMCreateColoring(dm,dm->coloringtype,&coloring);
187:       MatFDColoringCreate(*B,coloring,&fdcoloring);
188:       switch (dm->coloringtype) {
189:       case IS_COLORING_GLOBAL:
190:         MatFDColoringSetFunction(fdcoloring,(PetscErrorCode (*)(void))SNESComputeFunction_DMDA,dmdasnes);
191:         break;
192:       default: SETERRQ1(PetscObjectComm((PetscObject)snes),PETSC_ERR_SUP,"No support for coloring type '%s'",ISColoringTypes[dm->coloringtype]);
193:       }
194:       PetscObjectSetOptionsPrefix((PetscObject)fdcoloring,((PetscObject)dm)->prefix);
195:       MatFDColoringSetFromOptions(fdcoloring);
196:       MatFDColoringSetUp(*B,coloring,fdcoloring);
197:       ISColoringDestroy(&coloring);
198:       PetscObjectCompose((PetscObject)dm,"DMDASNES_FDCOLORING",(PetscObject)fdcoloring);
199:       PetscObjectDereference((PetscObject)fdcoloring);

201:       /* The following breaks an ugly reference counting loop that deserves a paragraph. MatFDColoringApply() will call
202:        * VecDuplicate() with the state Vec and store inside the MatFDColoring. This Vec will duplicate the Vec, but the
203:        * MatFDColoring is composed with the DM. We dereference the DM here so that the reference count will eventually
204:        * drop to 0. Note the code in DMDestroy() that exits early for a negative reference count. That code path will be
205:        * taken when the PetscObjectList for the Vec inside MatFDColoring is destroyed.
206:        */
207:       PetscObjectDereference((PetscObject)dm);
208:     }
209:     *mstr = SAME_NONZERO_PATTERN;
210:     MatFDColoringApply(*B,fdcoloring,X,mstr,snes);
211:   }
212:   /* This will be redundant if the user called both, but it's too common to forget. */
213:   if (*A != *B) {
214:     MatAssemblyBegin(*A,MAT_FINAL_ASSEMBLY);
215:     MatAssemblyEnd(*A,MAT_FINAL_ASSEMBLY);
216:   }
217:   return(0);
218: }

222: /*@C
223:    DMDASNESSetFunctionLocal - set a local residual evaluation function

225:    Logically Collective

227:    Input Arguments:
228: +  dm - DM to associate callback with
229: .  imode - INSERT_VALUES if local function computes owned part, ADD_VALUES if it contributes to ghosted part
230: .  func - local residual evaluation
231: -  ctx - optional context for local residual evaluation

233:    Calling sequence for func:
234: +  info - DMDALocalInfo defining the subdomain to evaluate the residual on
235: .  x - dimensional pointer to state at which to evaluate residual
236: .  f - dimensional pointer to residual, write the residual here
237: -  ctx - optional context passed above

239:    Level: beginner

241: .seealso: DMSNESSetFunction(), DMDASNESSetJacobian(), DMDACreate1d(), DMDACreate2d(), DMDACreate3d()
242: @*/
243: PetscErrorCode DMDASNESSetFunctionLocal(DM dm,InsertMode imode,PetscErrorCode (*func)(DMDALocalInfo*,void*,void*,void*),void *ctx)
244: {
246:   DMSNES         sdm;
247:   DMSNES_DA      *dmdasnes;

251:   DMGetDMSNESWrite(dm,&sdm);
252:   DMDASNESGetContext(dm,sdm,&dmdasnes);

254:   dmdasnes->residuallocalimode = imode;
255:   dmdasnes->residuallocal      = func;
256:   dmdasnes->residuallocalctx   = ctx;

258:   DMSNESSetFunction(dm,SNESComputeFunction_DMDA,dmdasnes);
259:   if (!sdm->ops->computejacobian) {  /* Call us for the Jacobian too, can be overridden by the user. */
260:     DMSNESSetJacobian(dm,SNESComputeJacobian_DMDA,dmdasnes);
261:   }
262:   return(0);
263: }

267: /*@C
268:    DMDASNESSetJacobianLocal - set a local Jacobian evaluation function

270:    Logically Collective

272:    Input Arguments:
273: +  dm - DM to associate callback with
274: .  func - local residual evaluation
275: -  ctx - optional context for local residual evaluation

277:    Calling sequence for func:
278: +  info - DMDALocalInfo defining the subdomain to evaluate the residual on
279: .  x - dimensional pointer to state at which to evaluate residual
280: .  f - dimensional pointer to residual, write the residual here
281: -  ctx - optional context passed above

283:    Level: beginner

285: .seealso: DMSNESSetJacobian(), DMDASNESSetJacobian(), DMDACreate1d(), DMDACreate2d(), DMDACreate3d()
286: @*/
287: PetscErrorCode DMDASNESSetJacobianLocal(DM dm,PetscErrorCode (*func)(DMDALocalInfo*,void*,Mat,Mat,MatStructure*,void*),void *ctx)
288: {
290:   DMSNES         sdm;
291:   DMSNES_DA      *dmdasnes;

295:   DMGetDMSNESWrite(dm,&sdm);
296:   DMDASNESGetContext(dm,sdm,&dmdasnes);

298:   dmdasnes->jacobianlocal    = func;
299:   dmdasnes->jacobianlocalctx = ctx;

301:   DMSNESSetJacobian(dm,SNESComputeJacobian_DMDA,dmdasnes);
302:   return(0);
303: }


308: /*@C
309:    DMDASNESSetObjectiveLocal - set a local residual evaluation function

311:    Logically Collective

313:    Input Arguments:
314: +  dm - DM to associate callback with
315: .  func - local objective evaluation
316: -  ctx - optional context for local residual evaluation

318:    Calling sequence for func:
319: +  info - DMDALocalInfo defining the subdomain to evaluate the residual on
320: .  x - dimensional pointer to state at which to evaluate residual
321: .  ob - eventual objective value
322: -  ctx - optional context passed above

324:    Level: beginner

326: .seealso: DMSNESSetFunction(), DMDASNESSetJacobian(), DMDACreate1d(), DMDACreate2d(), DMDACreate3d()
327: @*/
328: PetscErrorCode DMDASNESSetObjectiveLocal(DM dm,DMDASNESObjective func,void *ctx)
329: {
331:   DMSNES         sdm;
332:   DMSNES_DA      *dmdasnes;

336:   DMGetDMSNESWrite(dm,&sdm);
337:   DMDASNESGetContext(dm,sdm,&dmdasnes);

339:   dmdasnes->objectivelocal    = func;
340:   dmdasnes->objectivelocalctx = ctx;

342:   DMSNESSetObjective(dm,SNESComputeObjective_DMDA,dmdasnes);
343:   return(0);
344: }

348: static PetscErrorCode SNESComputePicard_DMDA(SNES snes,Vec X,Vec F,void *ctx)
349: {
351:   DM             dm;
352:   DMSNES_DA      *dmdasnes = (DMSNES_DA*)ctx;
353:   DMDALocalInfo  info;
354:   Vec            Xloc;
355:   void           *x,*f;

361:   if (!dmdasnes->rhsplocal) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_PLIB,"Corrupt context");
362:   SNESGetDM(snes,&dm);
363:   DMGetLocalVector(dm,&Xloc);
364:   DMGlobalToLocalBegin(dm,X,INSERT_VALUES,Xloc);
365:   DMGlobalToLocalEnd(dm,X,INSERT_VALUES,Xloc);
366:   DMDAGetLocalInfo(dm,&info);
367:   DMDAVecGetArray(dm,Xloc,&x);
368:   switch (dmdasnes->residuallocalimode) {
369:   case INSERT_VALUES: {
370:     DMDAVecGetArray(dm,F,&f);
371:     CHKMEMQ;
372:     (*dmdasnes->rhsplocal)(&info,x,f,dmdasnes->picardlocalctx);
373:     CHKMEMQ;
374:     DMDAVecRestoreArray(dm,F,&f);
375:   } break;
376:   case ADD_VALUES: {
377:     Vec Floc;
378:     DMGetLocalVector(dm,&Floc);
379:     VecZeroEntries(Floc);
380:     DMDAVecGetArray(dm,Floc,&f);
381:     CHKMEMQ;
382:     (*dmdasnes->rhsplocal)(&info,x,f,dmdasnes->picardlocalctx);
383:     CHKMEMQ;
384:     DMDAVecRestoreArray(dm,Floc,&f);
385:     VecZeroEntries(F);
386:     DMLocalToGlobalBegin(dm,Floc,ADD_VALUES,F);
387:     DMLocalToGlobalEnd(dm,Floc,ADD_VALUES,F);
388:     DMRestoreLocalVector(dm,&Floc);
389:   } break;
390:   default: SETERRQ1(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_INCOMP,"Cannot use imode=%d",(int)dmdasnes->residuallocalimode);
391:   }
392:   DMDAVecRestoreArray(dm,Xloc,&x);
393:   DMRestoreLocalVector(dm,&Xloc);
394:   return(0);
395: }

399: static PetscErrorCode SNESComputePicardJacobian_DMDA(SNES snes,Vec X,Mat *A,Mat *B,MatStructure *mstr,void *ctx)
400: {
402:   DM             dm;
403:   DMSNES_DA      *dmdasnes = (DMSNES_DA*)ctx;
404:   DMDALocalInfo  info;
405:   Vec            Xloc;
406:   void           *x;

409:   if (!dmdasnes->jacobianplocal) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_PLIB,"Corrupt context");
410:   SNESGetDM(snes,&dm);

412:   DMGetLocalVector(dm,&Xloc);
413:   DMGlobalToLocalBegin(dm,X,INSERT_VALUES,Xloc);
414:   DMGlobalToLocalEnd(dm,X,INSERT_VALUES,Xloc);
415:   DMDAGetLocalInfo(dm,&info);
416:   DMDAVecGetArray(dm,Xloc,&x);
417:   CHKMEMQ;
418:   (*dmdasnes->jacobianplocal)(&info,x,*A,*B,mstr,dmdasnes->picardlocalctx);
419:   CHKMEMQ;
420:   DMDAVecRestoreArray(dm,Xloc,&x);
421:   DMRestoreLocalVector(dm,&Xloc);
422:   *mstr = SAME_NONZERO_PATTERN;
423:   if (*A != *B) {
424:     MatAssemblyBegin(*A,MAT_FINAL_ASSEMBLY);
425:     MatAssemblyEnd(*A,MAT_FINAL_ASSEMBLY);
426:   }
427:   return(0);
428: }

432: /*@C
433:    DMDASNESSetPicardLocal - set a local right hand side and matrix evaluation function for Picard iteration

435:    Logically Collective

437:    Input Arguments:
438: +  dm - DM to associate callback with
439: .  imode - INSERT_VALUES if local function computes owned part, ADD_VALUES if it contributes to ghosted part
440: .  func - local residual evaluation
441: -  ctx - optional context for local residual evaluation

443:    Calling sequence for func:
444: +  info - DMDALocalInfo defining the subdomain to evaluate the residual on
445: .  x - dimensional pointer to state at which to evaluate residual
446: .  f - dimensional pointer to residual, write the residual here
447: -  ctx - optional context passed above

449:    Notes:  The user must use
450:     extern PetscErrorCode  SNESPicardComputeFunction(SNES,Vec,Vec,void*);
451:     extern PetscErrorCode  SNESPicardComputeJacobian(SNES,Vec,Mat*,Mat*,MatStructure*,void*);
452:     SNESSetFunction(snes,NULL,SNESPicardComputeFunction,&user);
453:     in their code before calling this routine.


456:    Level: beginner

458: .seealso: DMSNESSetFunction(), DMDASNESSetJacobian(), DMDACreate1d(), DMDACreate2d(), DMDACreate3d()
459: @*/
460: PetscErrorCode DMDASNESSetPicardLocal(DM dm,InsertMode imode,PetscErrorCode (*func)(DMDALocalInfo*,void*,void*,void*),
461:                                       PetscErrorCode (*jac)(DMDALocalInfo*,void*,Mat,Mat,MatStructure*,void*),void *ctx)
462: {
464:   DMSNES         sdm;
465:   DMSNES_DA      *dmdasnes;

469:   DMGetDMSNESWrite(dm,&sdm);
470:   DMDASNESGetContext(dm,sdm,&dmdasnes);

472:   dmdasnes->residuallocalimode = imode;
473:   dmdasnes->rhsplocal          = func;
474:   dmdasnes->jacobianplocal     = jac;
475:   dmdasnes->picardlocalctx     = ctx;

477:   DMSNESSetPicard(dm,SNESComputePicard_DMDA,SNESComputePicardJacobian_DMDA,dmdasnes);
478:   return(0);
479: }