int TSFunction_Sundials(realtype t,N_Vector y,N_Vector ydot,void *ctx) { TS ts = (TS) ctx; DM dm; DMTS tsdm; TSIFunction ifunction; MPI_Comm comm; TS_Sundials *cvode = (TS_Sundials*)ts->data; Vec yy = cvode->w1,yyd = cvode->w2,yydot = cvode->ydot; PetscScalar *y_data,*ydot_data; PetscErrorCode ierr; PetscFunctionBegin; ierr = PetscObjectGetComm((PetscObject)ts,&comm);CHKERRQ(ierr); /* Make the PETSc work vectors yy and yyd point to the arrays in the SUNDIALS vectors y and ydot respectively*/ y_data = (PetscScalar*) N_VGetArrayPointer(y); ydot_data = (PetscScalar*) N_VGetArrayPointer(ydot); ierr = VecPlaceArray(yy,y_data);CHKERRABORT(comm,ierr); ierr = VecPlaceArray(yyd,ydot_data);CHKERRABORT(comm,ierr); /* Now compute the right hand side function, via IFunction unless only the more efficient RHSFunction is set */ ierr = TSGetDM(ts,&dm);CHKERRQ(ierr); ierr = DMGetDMTS(dm,&tsdm);CHKERRQ(ierr); ierr = DMTSGetIFunction(dm,&ifunction,NULL);CHKERRQ(ierr); if (!ifunction) { ierr = TSComputeRHSFunction(ts,t,yy,yyd);CHKERRQ(ierr); } else { /* If rhsfunction is also set, this computes both parts and shifts them to the right */ ierr = VecZeroEntries(yydot);CHKERRQ(ierr); ierr = TSComputeIFunction(ts,t,yy,yydot,yyd,PETSC_FALSE);CHKERRABORT(comm,ierr); ierr = VecScale(yyd,-1.);CHKERRQ(ierr); } ierr = VecResetArray(yy);CHKERRABORT(comm,ierr); ierr = VecResetArray(yyd);CHKERRABORT(comm,ierr); PetscFunctionReturn(0); }
/*@C DMPlexTSGetGradientDM - Return gradient data layout Input Parameters: + dm - The DM - fv - The PetscFV Output Parameter: . dmGrad - The layout for gradient values Level: developer .seealso: DMPlexTSGetGeometryFVM(), DMPlexTSSetRHSFunctionLocal() @*/ PetscErrorCode DMPlexTSGetGradientDM(DM dm, PetscFV fv, DM *dmGrad) { DMTS dmts; PetscObject obj; PetscBool computeGradients; PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(dm,DM_CLASSID,1); PetscValidHeaderSpecific(fv,PETSCFV_CLASSID,2); PetscValidPointer(dmGrad,3); ierr = PetscFVGetComputeGradients(fv, &computeGradients);CHKERRQ(ierr); if (!computeGradients) {*dmGrad = NULL; PetscFunctionReturn(0);} ierr = DMGetDMTS(dm, &dmts);CHKERRQ(ierr); ierr = PetscObjectQuery((PetscObject) dmts, "DMPlexTS_dmgrad_fvm", &obj);CHKERRQ(ierr); if (!obj) { DM dmGrad; Vec faceGeometry, cellGeometry; ierr = DMPlexTSGetGeometryFVM(dm, &faceGeometry, &cellGeometry, NULL);CHKERRQ(ierr); ierr = DMPlexComputeGradientFVM(dm, fv, faceGeometry, cellGeometry, &dmGrad);CHKERRQ(ierr); ierr = PetscObjectCompose((PetscObject) dmts, "DMPlexTS_dmgrad_fvm", (PetscObject) dmGrad);CHKERRQ(ierr); ierr = DMDestroy(&dmGrad);CHKERRQ(ierr); } ierr = PetscObjectQuery((PetscObject) dmts, "DMPlexTS_dmgrad_fvm", (PetscObject *) dmGrad);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*@C DMTSGetRHSJacobian - get TS Jacobian evaluation function Not Collective Input Argument: . dm - DM to be used with TS Output Arguments: + func - Jacobian evaluation function, see TSSetRHSJacobian() for calling sequence - ctx - context for residual evaluation Level: advanced Note: TSGetJacobian() is normally used, but it calls this function internally because the user context is actually associated with the DM. This makes the interface consistent regardless of whether the user interacts with a DM or not. If DM took a more central role at some later date, this could become the primary method of setting the Jacobian. .seealso: DMTSSetContext(), TSSetFunction(), DMTSSetJacobian() @*/ PetscErrorCode DMTSGetRHSJacobian(DM dm,TSRHSJacobian *func,void **ctx) { PetscErrorCode ierr; DMTS tsdm; PetscFunctionBegin; PetscValidHeaderSpecific(dm,DM_CLASSID,1); ierr = DMGetDMTS(dm,&tsdm);CHKERRQ(ierr); if (func) *func = tsdm->ops->rhsjacobian; if (ctx) *ctx = tsdm->rhsjacobianctx; PetscFunctionReturn(0); }
/*@C DMTSGetI2Jacobian - get TS implicit Jacobian evaluation function for 2nd order systems Not Collective Input Argument: . dm - DM to be used with TS Output Arguments: + jac - Jacobian evaluation function, see TSSetI2Jacobian() for calling sequence - ctx - context for Jacobian evaluation Level: advanced Note: TSGetI2Jacobian() is normally used, but it calls this function internally because the user context is actually associated with the DM. .seealso: DMTSSetI2Jacobian(),TSGetI2Jacobian() @*/ PetscErrorCode DMTSGetI2Jacobian(DM dm,TSI2Jacobian *jac,void **ctx) { DMTS tsdm; PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(dm,DM_CLASSID,1); ierr = DMGetDMTS(dm,&tsdm);CHKERRQ(ierr); if (jac) *jac = tsdm->ops->i2jacobian; if (ctx) *ctx = tsdm->i2jacobianctx; PetscFunctionReturn(0); }
/*@C DMTSGetI2Function - get TS implicit residual evaluation function for 2nd order systems Not Collective Input Argument: . dm - DM to be used with TS Output Arguments: + fun - function evaluation function, see TSSetI2Function() for calling sequence - ctx - context for residual evaluation Level: advanced Note: TSGetI2Function() is normally used, but it calls this function internally because the user context is actually associated with the DM. .seealso: DMTSSetI2Function(),TSGetI2Function() @*/ PetscErrorCode DMTSGetI2Function(DM dm,TSI2Function *fun,void **ctx) { DMTS tsdm; PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(dm,DM_CLASSID,1); ierr = DMGetDMTS(dm,&tsdm);CHKERRQ(ierr); if (fun) *fun = tsdm->ops->i2function; if (ctx) *ctx = tsdm->i2functionctx; PetscFunctionReturn(0); }
/*@ DMPlexTSGetGeometry - Return precomputed geometric data Input Parameter: . dm - The DM Output Parameters: + facegeom - The values precomputed from face geometry . cellgeom - The values precomputed from cell geometry - minRadius - The minimum radius over the mesh of an inscribed sphere in a cell Level: developer .seealso: DMPlexTSSetRHSFunctionLocal() @*/ PetscErrorCode DMPlexTSGetGeometry(DM dm, Vec *facegeom, Vec *cellgeom, PetscReal *minRadius) { DMTS dmts; DMTS_Plex *dmplexts; PetscErrorCode ierr; PetscFunctionBegin; ierr = DMGetDMTS(dm, &dmts);CHKERRQ(ierr); ierr = DMPlexTSGetContext(dm, dmts, &dmplexts);CHKERRQ(ierr); if (facegeom) *facegeom = dmplexts->facegeom; if (cellgeom) *cellgeom = dmplexts->cellgeom; if (minRadius) *minRadius = dmplexts->minradius; PetscFunctionReturn(0); }
/*@C DMGetDMTSWrite - get write access to private DMTS context from a DM Not Collective Input Argument: . dm - DM to be used with TS Output Argument: . tsdm - private DMTS context Level: developer .seealso: DMGetDMTS() @*/ PetscErrorCode DMGetDMTSWrite(DM dm,DMTS *tsdm) { PetscErrorCode ierr; DMTS sdm; PetscFunctionBegin; PetscValidHeaderSpecific(dm,DM_CLASSID,1); ierr = DMGetDMTS(dm,&sdm);CHKERRQ(ierr); if (!sdm->originaldm) sdm->originaldm = dm; if (sdm->originaldm != dm) { /* Copy on write */ DMTS oldsdm = sdm; ierr = PetscInfo(dm,"Copying DMTS due to write\n");CHKERRQ(ierr); ierr = DMTSCreate(PetscObjectComm((PetscObject)dm),&sdm);CHKERRQ(ierr); ierr = DMTSCopy(oldsdm,sdm);CHKERRQ(ierr); ierr = DMTSDestroy((DMTS*)&dm->dmts);CHKERRQ(ierr); dm->dmts = (PetscObject) sdm; } *tsdm = sdm; PetscFunctionReturn(0); }
/*@ DMPlexTSGetGeometryFVM - Return precomputed geometric data Input Parameter: . dm - The DM Output Parameters: + facegeom - The values precomputed from face geometry . cellgeom - The values precomputed from cell geometry - minRadius - The minimum radius over the mesh of an inscribed sphere in a cell Level: developer .seealso: DMPlexTSSetRHSFunctionLocal() @*/ PetscErrorCode DMPlexTSGetGeometryFVM(DM dm, Vec *facegeom, Vec *cellgeom, PetscReal *minRadius) { DMTS dmts; PetscObject obj; PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(dm,DM_CLASSID,1); ierr = DMGetDMTS(dm, &dmts);CHKERRQ(ierr); ierr = PetscObjectQuery((PetscObject) dmts, "DMPlexTS_facegeom_fvm", &obj);CHKERRQ(ierr); if (!obj) { Vec cellgeom, facegeom; ierr = DMPlexComputeGeometryFVM(dm, &cellgeom, &facegeom);CHKERRQ(ierr); ierr = PetscObjectCompose((PetscObject) dmts, "DMPlexTS_facegeom_fvm", (PetscObject) facegeom);CHKERRQ(ierr); ierr = PetscObjectCompose((PetscObject) dmts, "DMPlexTS_cellgeom_fvm", (PetscObject) cellgeom);CHKERRQ(ierr); ierr = VecDestroy(&facegeom);CHKERRQ(ierr); ierr = VecDestroy(&cellgeom);CHKERRQ(ierr); } if (facegeom) {PetscValidPointer(facegeom, 2); ierr = PetscObjectQuery((PetscObject) dmts, "DMPlexTS_facegeom_fvm", (PetscObject *) facegeom);CHKERRQ(ierr);} if (cellgeom) {PetscValidPointer(cellgeom, 3); ierr = PetscObjectQuery((PetscObject) dmts, "DMPlexTS_cellgeom_fvm", (PetscObject *) cellgeom);CHKERRQ(ierr);} if (minRadius) {ierr = DMPlexGetMinRadius(dm, minRadius);CHKERRQ(ierr);} PetscFunctionReturn(0); }