Actual source code: dmdats.c

      1: #include <petscdmda.h>
      2: #include <petsc/private/dmimpl.h>
      3: #include <petsc/private/tsimpl.h>
      4: #include <petscdraw.h>

      6: /* This structure holds the user-provided DMDA callbacks */
      7: typedef struct {
      8:   PetscErrorCode (*ifunctionlocal)(DMDALocalInfo*,PetscReal,void*,void*,void*,void*);
      9:   PetscErrorCode (*rhsfunctionlocal)(DMDALocalInfo*,PetscReal,void*,void*,void*);
     10:   PetscErrorCode (*ijacobianlocal)(DMDALocalInfo*,PetscReal,void*,void*,PetscReal,Mat,Mat,void*);
     11:   PetscErrorCode (*rhsjacobianlocal)(DMDALocalInfo*,PetscReal,void*,Mat,Mat,void*);
     12:   void       *ifunctionlocalctx;
     13:   void       *ijacobianlocalctx;
     14:   void       *rhsfunctionlocalctx;
     15:   void       *rhsjacobianlocalctx;
     16:   InsertMode ifunctionlocalimode;
     17:   InsertMode rhsfunctionlocalimode;
     18: } DMTS_DA;

     20: static PetscErrorCode DMTSDestroy_DMDA(DMTS sdm)
     21: {
     22:   PetscFree(sdm->data);
     23:   return 0;
     24: }

     26: static PetscErrorCode DMTSDuplicate_DMDA(DMTS oldsdm,DMTS sdm)
     27: {
     28:   PetscNewLog(sdm,(DMTS_DA**)&sdm->data);
     29:   if (oldsdm->data) PetscMemcpy(sdm->data,oldsdm->data,sizeof(DMTS_DA));
     30:   return 0;
     31: }

     33: static PetscErrorCode DMDATSGetContext(DM dm,DMTS sdm,DMTS_DA **dmdats)
     34: {
     35:   *dmdats = NULL;
     36:   if (!sdm->data) {
     37:     PetscNewLog(dm,(DMTS_DA**)&sdm->data);
     38:     sdm->ops->destroy   = DMTSDestroy_DMDA;
     39:     sdm->ops->duplicate = DMTSDuplicate_DMDA;
     40:   }
     41:   *dmdats = (DMTS_DA*)sdm->data;
     42:   return 0;
     43: }

     45: static PetscErrorCode TSComputeIFunction_DMDA(TS ts,PetscReal ptime,Vec X,Vec Xdot,Vec F,void *ctx)
     46: {
     47:   DM             dm;
     48:   DMTS_DA        *dmdats = (DMTS_DA*)ctx;
     49:   DMDALocalInfo  info;
     50:   Vec            Xloc,Xdotloc;
     51:   void           *x,*f,*xdot;

     57:   TSGetDM(ts,&dm);
     58:   DMGetLocalVector(dm,&Xdotloc);
     59:   DMGlobalToLocalBegin(dm,Xdot,INSERT_VALUES,Xdotloc);
     60:   DMGlobalToLocalEnd(dm,Xdot,INSERT_VALUES,Xdotloc);
     61:   DMGetLocalVector(dm,&Xloc);
     62:   DMGlobalToLocalBegin(dm,X,INSERT_VALUES,Xloc);
     63:   DMGlobalToLocalEnd(dm,X,INSERT_VALUES,Xloc);
     64:   DMDAGetLocalInfo(dm,&info);
     65:   DMDAVecGetArray(dm,Xloc,&x);
     66:   DMDAVecGetArray(dm,Xdotloc,&xdot);
     67:   switch (dmdats->ifunctionlocalimode) {
     68:   case INSERT_VALUES: {
     69:     DMDAVecGetArray(dm,F,&f);
     70:     CHKMEMQ;
     71:     (*dmdats->ifunctionlocal)(&info,ptime,x,xdot,f,dmdats->ifunctionlocalctx);
     72:     CHKMEMQ;
     73:     DMDAVecRestoreArray(dm,F,&f);
     74:   } break;
     75:   case ADD_VALUES: {
     76:     Vec Floc;
     77:     DMGetLocalVector(dm,&Floc);
     78:     VecZeroEntries(Floc);
     79:     DMDAVecGetArray(dm,Floc,&f);
     80:     CHKMEMQ;
     81:     (*dmdats->ifunctionlocal)(&info,ptime,x,xdot,f,dmdats->ifunctionlocalctx);
     82:     CHKMEMQ;
     83:     DMDAVecRestoreArray(dm,Floc,&f);
     84:     VecZeroEntries(F);
     85:     DMLocalToGlobalBegin(dm,Floc,ADD_VALUES,F);
     86:     DMLocalToGlobalEnd(dm,Floc,ADD_VALUES,F);
     87:     DMRestoreLocalVector(dm,&Floc);
     88:   } break;
     89:   default: SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_INCOMP,"Cannot use imode=%d",(int)dmdats->ifunctionlocalimode);
     90:   }
     91:   DMDAVecRestoreArray(dm,Xloc,&x);
     92:   DMRestoreLocalVector(dm,&Xloc);
     93:   DMDAVecRestoreArray(dm,Xdotloc,&xdot);
     94:   DMRestoreLocalVector(dm,&Xdotloc);
     95:   return 0;
     96: }

     98: static PetscErrorCode TSComputeIJacobian_DMDA(TS ts,PetscReal ptime,Vec X,Vec Xdot,PetscReal shift,Mat A,Mat B,void *ctx)
     99: {
    100:   DM             dm;
    101:   DMTS_DA        *dmdats = (DMTS_DA*)ctx;
    102:   DMDALocalInfo  info;
    103:   Vec            Xloc;
    104:   void           *x,*xdot;

    107:   TSGetDM(ts,&dm);

    109:   if (dmdats->ijacobianlocal) {
    110:     DMGetLocalVector(dm,&Xloc);
    111:     DMGlobalToLocalBegin(dm,X,INSERT_VALUES,Xloc);
    112:     DMGlobalToLocalEnd(dm,X,INSERT_VALUES,Xloc);
    113:     DMDAGetLocalInfo(dm,&info);
    114:     DMDAVecGetArray(dm,Xloc,&x);
    115:     DMDAVecGetArray(dm,Xdot,&xdot);
    116:     CHKMEMQ;
    117:     (*dmdats->ijacobianlocal)(&info,ptime,x,xdot,shift,A,B,dmdats->ijacobianlocalctx);
    118:     CHKMEMQ;
    119:     DMDAVecRestoreArray(dm,Xloc,&x);
    120:     DMDAVecRestoreArray(dm,Xdot,&xdot);
    121:     DMRestoreLocalVector(dm,&Xloc);
    122:   } else SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_PLIB,"TSComputeIJacobian_DMDA() called without calling DMDATSSetIJacobian()");
    123:   /* This will be redundant if the user called both, but it's too common to forget. */
    124:   if (A != B) {
    125:     MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);
    126:     MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);
    127:   }
    128:   return 0;
    129: }

    131: static PetscErrorCode TSComputeRHSFunction_DMDA(TS ts,PetscReal ptime,Vec X,Vec F,void *ctx)
    132: {
    133:   DM             dm;
    134:   DMTS_DA        *dmdats = (DMTS_DA*)ctx;
    135:   DMDALocalInfo  info;
    136:   Vec            Xloc;
    137:   void           *x,*f;

    143:   TSGetDM(ts,&dm);
    144:   DMGetLocalVector(dm,&Xloc);
    145:   DMGlobalToLocalBegin(dm,X,INSERT_VALUES,Xloc);
    146:   DMGlobalToLocalEnd(dm,X,INSERT_VALUES,Xloc);
    147:   DMDAGetLocalInfo(dm,&info);
    148:   DMDAVecGetArray(dm,Xloc,&x);
    149:   switch (dmdats->rhsfunctionlocalimode) {
    150:   case INSERT_VALUES: {
    151:     DMDAVecGetArray(dm,F,&f);
    152:     CHKMEMQ;
    153:     (*dmdats->rhsfunctionlocal)(&info,ptime,x,f,dmdats->rhsfunctionlocalctx);
    154:     CHKMEMQ;
    155:     DMDAVecRestoreArray(dm,F,&f);
    156:   } break;
    157:   case ADD_VALUES: {
    158:     Vec Floc;
    159:     DMGetLocalVector(dm,&Floc);
    160:     VecZeroEntries(Floc);
    161:     DMDAVecGetArray(dm,Floc,&f);
    162:     CHKMEMQ;
    163:     (*dmdats->rhsfunctionlocal)(&info,ptime,x,f,dmdats->rhsfunctionlocalctx);
    164:     CHKMEMQ;
    165:     DMDAVecRestoreArray(dm,Floc,&f);
    166:     VecZeroEntries(F);
    167:     DMLocalToGlobalBegin(dm,Floc,ADD_VALUES,F);
    168:     DMLocalToGlobalEnd(dm,Floc,ADD_VALUES,F);
    169:     DMRestoreLocalVector(dm,&Floc);
    170:   } break;
    171:   default: SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_INCOMP,"Cannot use imode=%d",(int)dmdats->rhsfunctionlocalimode);
    172:   }
    173:   DMDAVecRestoreArray(dm,Xloc,&x);
    174:   DMRestoreLocalVector(dm,&Xloc);
    175:   return 0;
    176: }

    178: static PetscErrorCode TSComputeRHSJacobian_DMDA(TS ts,PetscReal ptime,Vec X,Mat A,Mat B,void *ctx)
    179: {
    180:   DM             dm;
    181:   DMTS_DA        *dmdats = (DMTS_DA*)ctx;
    182:   DMDALocalInfo  info;
    183:   Vec            Xloc;
    184:   void           *x;

    187:   TSGetDM(ts,&dm);

    189:   if (dmdats->rhsjacobianlocal) {
    190:     DMGetLocalVector(dm,&Xloc);
    191:     DMGlobalToLocalBegin(dm,X,INSERT_VALUES,Xloc);
    192:     DMGlobalToLocalEnd(dm,X,INSERT_VALUES,Xloc);
    193:     DMDAGetLocalInfo(dm,&info);
    194:     DMDAVecGetArray(dm,Xloc,&x);
    195:     CHKMEMQ;
    196:     (*dmdats->rhsjacobianlocal)(&info,ptime,x,A,B,dmdats->rhsjacobianlocalctx);
    197:     CHKMEMQ;
    198:     DMDAVecRestoreArray(dm,Xloc,&x);
    199:     DMRestoreLocalVector(dm,&Xloc);
    200:   } else SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_PLIB,"TSComputeRHSJacobian_DMDA() called without calling DMDATSSetRHSJacobian()");
    201:   /* This will be redundant if the user called both, but it's too common to forget. */
    202:   if (A != B) {
    203:     MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);
    204:     MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);
    205:   }
    206:   return 0;
    207: }

    209: /*@C
    210:    DMDATSSetRHSFunctionLocal - set a local residual evaluation function

    212:    Logically Collective

    214:    Input Parameters:
    215: +  dm - DM to associate callback with
    216: .  imode - insert mode for the residual
    217: .  func - local residual evaluation
    218: -  ctx - optional context for local residual evaluation

    220:    Calling sequence for func:

    222: $ func(DMDALocalInfo info,PetscReal t,void *x,void *f,void *ctx)

    224: +  info - DMDALocalInfo defining the subdomain to evaluate the residual on
    225: .  t - time at which to evaluate residual
    226: .  x - array of local state information
    227: .  f - output array of local residual information
    228: -  ctx - optional user context

    230:    Level: beginner

    232: .seealso: DMTSSetRHSFunction(), DMDATSSetRHSJacobianLocal(), DMDASNESSetFunctionLocal()
    233: @*/
    234: PetscErrorCode DMDATSSetRHSFunctionLocal(DM dm,InsertMode imode,DMDATSRHSFunctionLocal func,void *ctx)
    235: {
    236:   DMTS           sdm;
    237:   DMTS_DA        *dmdats;

    240:   DMGetDMTSWrite(dm,&sdm);
    241:   DMDATSGetContext(dm,sdm,&dmdats);
    242:   dmdats->rhsfunctionlocalimode = imode;
    243:   dmdats->rhsfunctionlocal      = func;
    244:   dmdats->rhsfunctionlocalctx   = ctx;
    245:   DMTSSetRHSFunction(dm,TSComputeRHSFunction_DMDA,dmdats);
    246:   return 0;
    247: }

    249: /*@C
    250:    DMDATSSetRHSJacobianLocal - set a local residual evaluation function

    252:    Logically Collective

    254:    Input Parameters:
    255: +  dm    - DM to associate callback with
    256: .  func  - local RHS Jacobian evaluation routine
    257: -  ctx   - optional context for local jacobian evaluation

    259:    Calling sequence for func:

    261: $ func(DMDALocalInfo* info,PetscReal t,void* x,Mat J,Mat B,void *ctx);

    263: +  info - DMDALocalInfo defining the subdomain to evaluate the residual on
    264: .  t    - time at which to evaluate residual
    265: .  x    - array of local state information
    266: .  J    - Jacobian matrix
    267: .  B    - preconditioner matrix; often same as J
    268: -  ctx  - optional context passed above

    270:    Level: beginner

    272: .seealso: DMTSSetRHSJacobian(), DMDATSSetRHSFunctionLocal(), DMDASNESSetJacobianLocal()
    273: @*/
    274: PetscErrorCode DMDATSSetRHSJacobianLocal(DM dm,DMDATSRHSJacobianLocal func,void *ctx)
    275: {
    276:   DMTS           sdm;
    277:   DMTS_DA        *dmdats;

    280:   DMGetDMTSWrite(dm,&sdm);
    281:   DMDATSGetContext(dm,sdm,&dmdats);
    282:   dmdats->rhsjacobianlocal    = func;
    283:   dmdats->rhsjacobianlocalctx = ctx;
    284:   DMTSSetRHSJacobian(dm,TSComputeRHSJacobian_DMDA,dmdats);
    285:   return 0;
    286: }

    288: /*@C
    289:    DMDATSSetIFunctionLocal - set a local residual evaluation function

    291:    Logically Collective

    293:    Input Parameters:
    294: +  dm   - DM to associate callback with
    295: .  func - local residual evaluation
    296: -  ctx  - optional context for local residual evaluation

    298:    Calling sequence for func:
    299: +  info - DMDALocalInfo defining the subdomain to evaluate the residual on
    300: .  t    - time at which to evaluate residual
    301: .  x    - array of local state information
    302: .  xdot - array of local time derivative information
    303: .  f    - output array of local function evaluation information
    304: -  ctx - optional context passed above

    306:    Level: beginner

    308: .seealso: DMTSSetIFunction(), DMDATSSetIJacobianLocal(), DMDASNESSetFunctionLocal()
    309: @*/
    310: PetscErrorCode DMDATSSetIFunctionLocal(DM dm,InsertMode imode,DMDATSIFunctionLocal func,void *ctx)
    311: {
    312:   DMTS           sdm;
    313:   DMTS_DA        *dmdats;

    316:   DMGetDMTSWrite(dm,&sdm);
    317:   DMDATSGetContext(dm,sdm,&dmdats);
    318:   dmdats->ifunctionlocalimode = imode;
    319:   dmdats->ifunctionlocal      = func;
    320:   dmdats->ifunctionlocalctx   = ctx;
    321:   DMTSSetIFunction(dm,TSComputeIFunction_DMDA,dmdats);
    322:   return 0;
    323: }

    325: /*@C
    326:    DMDATSSetIJacobianLocal - set a local residual evaluation function

    328:    Logically Collective

    330:    Input Parameters:
    331: +  dm   - DM to associate callback with
    332: .  func - local residual evaluation
    333: -  ctx   - optional context for local residual evaluation

    335:    Calling sequence for func:

    337: $ func(DMDALocalInfo* info,PetscReal t,void* x,void *xdot,PetscScalar shift,Mat J,Mat B,void *ctx);

    339: +  info - DMDALocalInfo defining the subdomain to evaluate the residual on
    340: .  t    - time at which to evaluate the jacobian
    341: .  x    - array of local state information
    342: .  xdot - time derivative at this state
    343: .  shift - see TSSetIJacobian() for the meaning of this parameter
    344: .  J    - Jacobian matrix
    345: .  B    - preconditioner matrix; often same as J
    346: -  ctx  - optional context passed above

    348:    Level: beginner

    350: .seealso: DMTSSetJacobian(), DMDATSSetIFunctionLocal(), DMDASNESSetJacobianLocal()
    351: @*/
    352: PetscErrorCode DMDATSSetIJacobianLocal(DM dm,DMDATSIJacobianLocal func,void *ctx)
    353: {
    354:   DMTS           sdm;
    355:   DMTS_DA        *dmdats;

    358:   DMGetDMTSWrite(dm,&sdm);
    359:   DMDATSGetContext(dm,sdm,&dmdats);
    360:   dmdats->ijacobianlocal    = func;
    361:   dmdats->ijacobianlocalctx = ctx;
    362:   DMTSSetIJacobian(dm,TSComputeIJacobian_DMDA,dmdats);
    363:   return 0;
    364: }

    366: PetscErrorCode TSMonitorDMDARayDestroy(void **mctx)
    367: {
    368:   TSMonitorDMDARayCtx *rayctx = (TSMonitorDMDARayCtx *) *mctx;

    370:   if (rayctx->lgctx) TSMonitorLGCtxDestroy(&rayctx->lgctx);
    371:   VecDestroy(&rayctx->ray);
    372:   VecScatterDestroy(&rayctx->scatter);
    373:   PetscViewerDestroy(&rayctx->viewer);
    374:   PetscFree(rayctx);
    375:   return 0;
    376: }

    378: PetscErrorCode TSMonitorDMDARay(TS ts,PetscInt steps,PetscReal time,Vec u,void *mctx)
    379: {
    380:   TSMonitorDMDARayCtx *rayctx = (TSMonitorDMDARayCtx*)mctx;
    381:   Vec                 solution;

    383:   TSGetSolution(ts,&solution);
    384:   VecScatterBegin(rayctx->scatter,solution,rayctx->ray,INSERT_VALUES,SCATTER_FORWARD);
    385:   VecScatterEnd(rayctx->scatter,solution,rayctx->ray,INSERT_VALUES,SCATTER_FORWARD);
    386:   if (rayctx->viewer) {
    387:     VecView(rayctx->ray,rayctx->viewer);
    388:   }
    389:   return 0;
    390: }

    392: PetscErrorCode  TSMonitorLGDMDARay(TS ts, PetscInt step, PetscReal ptime, Vec u, void *ctx)
    393: {
    394:   TSMonitorDMDARayCtx *rayctx = (TSMonitorDMDARayCtx *) ctx;
    395:   TSMonitorLGCtx       lgctx  = (TSMonitorLGCtx) rayctx->lgctx;
    396:   Vec                  v      = rayctx->ray;
    397:   const PetscScalar   *a;
    398:   PetscInt             dim;

    400:   VecScatterBegin(rayctx->scatter, u, v, INSERT_VALUES, SCATTER_FORWARD);
    401:   VecScatterEnd(rayctx->scatter, u, v, INSERT_VALUES, SCATTER_FORWARD);
    402:   if (!step) {
    403:     PetscDrawAxis axis;

    405:     PetscDrawLGGetAxis(lgctx->lg, &axis);
    406:     PetscDrawAxisSetLabels(axis, "Solution Ray as function of time", "Time", "Solution");
    407:     VecGetLocalSize(rayctx->ray, &dim);
    408:     PetscDrawLGSetDimension(lgctx->lg, dim);
    409:     PetscDrawLGReset(lgctx->lg);
    410:   }
    411:   VecGetArrayRead(v, &a);
    412: #if defined(PETSC_USE_COMPLEX)
    413:   {
    414:     PetscReal *areal;
    415:     PetscInt   i,n;
    416:     VecGetLocalSize(v, &n);
    417:     PetscMalloc1(n, &areal);
    418:     for (i = 0; i < n; ++i) areal[i] = PetscRealPart(a[i]);
    419:     PetscDrawLGAddCommonPoint(lgctx->lg, ptime, areal);
    420:     PetscFree(areal);
    421:   }
    422: #else
    423:   PetscDrawLGAddCommonPoint(lgctx->lg, ptime, a);
    424: #endif
    425:   VecRestoreArrayRead(v, &a);
    426:   if (((lgctx->howoften > 0) && (!(step % lgctx->howoften))) || ((lgctx->howoften == -1) && ts->reason)) {
    427:     PetscDrawLGDraw(lgctx->lg);
    428:     PetscDrawLGSave(lgctx->lg);
    429:   }
    430:   return 0;
    431: }