140be0ff1SMatthew G. Knepley /* 240be0ff1SMatthew G. Knepley Code for timestepping with discrete gradient integrators 340be0ff1SMatthew G. Knepley */ 440be0ff1SMatthew G. Knepley #include <petsc/private/tsimpl.h> /*I "petscts.h" I*/ 540be0ff1SMatthew G. Knepley #include <petscdm.h> 640be0ff1SMatthew G. Knepley 740be0ff1SMatthew G. Knepley PetscBool DGCite = PETSC_FALSE; 840be0ff1SMatthew G. Knepley const char DGCitation[] = "@article{Gonzalez1996,\n" 940be0ff1SMatthew G. Knepley " title = {Time integration and discrete Hamiltonian systems},\n" 1040be0ff1SMatthew G. Knepley " author = {Oscar Gonzalez},\n" 1140be0ff1SMatthew G. Knepley " journal = {Journal of Nonlinear Science},\n" 1240be0ff1SMatthew G. Knepley " volume = {6},\n" 1340be0ff1SMatthew G. Knepley " pages = {449--467},\n" 1440be0ff1SMatthew G. Knepley " doi = {10.1007/978-1-4612-1246-1_10},\n" 1540be0ff1SMatthew G. Knepley " year = {1996}\n}\n"; 1640be0ff1SMatthew G. Knepley 1740be0ff1SMatthew G. Knepley typedef struct { 1840be0ff1SMatthew G. Knepley PetscReal stage_time; 1940be0ff1SMatthew G. Knepley Vec X0, X, Xdot; 20db4653c2SDaniel Finn void *funcCtx; 21db4653c2SDaniel Finn PetscBool gonzalez; 2240be0ff1SMatthew G. Knepley PetscErrorCode (*Sfunc)(TS, PetscReal, Vec, Mat, void *); 2340be0ff1SMatthew G. Knepley PetscErrorCode (*Ffunc)(TS, PetscReal, Vec, PetscScalar *, void *); 2440be0ff1SMatthew G. Knepley PetscErrorCode (*Gfunc)(TS, PetscReal, Vec, Vec, void *); 2540be0ff1SMatthew G. Knepley } TS_DiscGrad; 2640be0ff1SMatthew G. Knepley 27d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSDiscGradGetX0AndXdot(TS ts, DM dm, Vec *X0, Vec *Xdot) 28d71ae5a4SJacob Faibussowitsch { 2940be0ff1SMatthew G. Knepley TS_DiscGrad *dg = (TS_DiscGrad *)ts->data; 3040be0ff1SMatthew G. Knepley 3140be0ff1SMatthew G. Knepley PetscFunctionBegin; 3240be0ff1SMatthew G. Knepley if (X0) { 339566063dSJacob Faibussowitsch if (dm && dm != ts->dm) PetscCall(DMGetNamedGlobalVector(dm, "TSDiscGrad_X0", X0)); 34ad540459SPierre Jolivet else *X0 = ts->vec_sol; 3540be0ff1SMatthew G. Knepley } 3640be0ff1SMatthew G. Knepley if (Xdot) { 379566063dSJacob Faibussowitsch if (dm && dm != ts->dm) PetscCall(DMGetNamedGlobalVector(dm, "TSDiscGrad_Xdot", Xdot)); 38ad540459SPierre Jolivet else *Xdot = dg->Xdot; 3940be0ff1SMatthew G. Knepley } 4040be0ff1SMatthew G. Knepley PetscFunctionReturn(0); 4140be0ff1SMatthew G. Knepley } 4240be0ff1SMatthew G. Knepley 43d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSDiscGradRestoreX0AndXdot(TS ts, DM dm, Vec *X0, Vec *Xdot) 44d71ae5a4SJacob Faibussowitsch { 4540be0ff1SMatthew G. Knepley PetscFunctionBegin; 4640be0ff1SMatthew G. Knepley if (X0) { 479566063dSJacob Faibussowitsch if (dm && dm != ts->dm) PetscCall(DMRestoreNamedGlobalVector(dm, "TSDiscGrad_X0", X0)); 4840be0ff1SMatthew G. Knepley } 4940be0ff1SMatthew G. Knepley if (Xdot) { 509566063dSJacob Faibussowitsch if (dm && dm != ts->dm) PetscCall(DMRestoreNamedGlobalVector(dm, "TSDiscGrad_Xdot", Xdot)); 5140be0ff1SMatthew G. Knepley } 5240be0ff1SMatthew G. Knepley PetscFunctionReturn(0); 5340be0ff1SMatthew G. Knepley } 5440be0ff1SMatthew G. Knepley 55d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCoarsenHook_TSDiscGrad(DM fine, DM coarse, void *ctx) 56d71ae5a4SJacob Faibussowitsch { 5740be0ff1SMatthew G. Knepley PetscFunctionBegin; 5840be0ff1SMatthew G. Knepley PetscFunctionReturn(0); 5940be0ff1SMatthew G. Knepley } 6040be0ff1SMatthew G. Knepley 61d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMRestrictHook_TSDiscGrad(DM fine, Mat restrct, Vec rscale, Mat inject, DM coarse, void *ctx) 62d71ae5a4SJacob Faibussowitsch { 6340be0ff1SMatthew G. Knepley TS ts = (TS)ctx; 6440be0ff1SMatthew G. Knepley Vec X0, Xdot, X0_c, Xdot_c; 6540be0ff1SMatthew G. Knepley 6640be0ff1SMatthew G. Knepley PetscFunctionBegin; 679566063dSJacob Faibussowitsch PetscCall(TSDiscGradGetX0AndXdot(ts, fine, &X0, &Xdot)); 689566063dSJacob Faibussowitsch PetscCall(TSDiscGradGetX0AndXdot(ts, coarse, &X0_c, &Xdot_c)); 699566063dSJacob Faibussowitsch PetscCall(MatRestrict(restrct, X0, X0_c)); 709566063dSJacob Faibussowitsch PetscCall(MatRestrict(restrct, Xdot, Xdot_c)); 719566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(X0_c, rscale, X0_c)); 729566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(Xdot_c, rscale, Xdot_c)); 739566063dSJacob Faibussowitsch PetscCall(TSDiscGradRestoreX0AndXdot(ts, fine, &X0, &Xdot)); 749566063dSJacob Faibussowitsch PetscCall(TSDiscGradRestoreX0AndXdot(ts, coarse, &X0_c, &Xdot_c)); 7540be0ff1SMatthew G. Knepley PetscFunctionReturn(0); 7640be0ff1SMatthew G. Knepley } 7740be0ff1SMatthew G. Knepley 78d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSubDomainHook_TSDiscGrad(DM dm, DM subdm, void *ctx) 79d71ae5a4SJacob Faibussowitsch { 8040be0ff1SMatthew G. Knepley PetscFunctionBegin; 8140be0ff1SMatthew G. Knepley PetscFunctionReturn(0); 8240be0ff1SMatthew G. Knepley } 8340be0ff1SMatthew G. Knepley 84d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSubDomainRestrictHook_TSDiscGrad(DM dm, VecScatter gscat, VecScatter lscat, DM subdm, void *ctx) 85d71ae5a4SJacob Faibussowitsch { 8640be0ff1SMatthew G. Knepley TS ts = (TS)ctx; 8740be0ff1SMatthew G. Knepley Vec X0, Xdot, X0_sub, Xdot_sub; 8840be0ff1SMatthew G. Knepley 8940be0ff1SMatthew G. Knepley PetscFunctionBegin; 909566063dSJacob Faibussowitsch PetscCall(TSDiscGradGetX0AndXdot(ts, dm, &X0, &Xdot)); 919566063dSJacob Faibussowitsch PetscCall(TSDiscGradGetX0AndXdot(ts, subdm, &X0_sub, &Xdot_sub)); 9240be0ff1SMatthew G. Knepley 939566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(gscat, X0, X0_sub, INSERT_VALUES, SCATTER_FORWARD)); 949566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(gscat, X0, X0_sub, INSERT_VALUES, SCATTER_FORWARD)); 9540be0ff1SMatthew G. Knepley 969566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(gscat, Xdot, Xdot_sub, INSERT_VALUES, SCATTER_FORWARD)); 979566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(gscat, Xdot, Xdot_sub, INSERT_VALUES, SCATTER_FORWARD)); 9840be0ff1SMatthew G. Knepley 999566063dSJacob Faibussowitsch PetscCall(TSDiscGradRestoreX0AndXdot(ts, dm, &X0, &Xdot)); 1009566063dSJacob Faibussowitsch PetscCall(TSDiscGradRestoreX0AndXdot(ts, subdm, &X0_sub, &Xdot_sub)); 10140be0ff1SMatthew G. Knepley PetscFunctionReturn(0); 10240be0ff1SMatthew G. Knepley } 10340be0ff1SMatthew G. Knepley 104d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSSetUp_DiscGrad(TS ts) 105d71ae5a4SJacob Faibussowitsch { 10640be0ff1SMatthew G. Knepley TS_DiscGrad *dg = (TS_DiscGrad *)ts->data; 10740be0ff1SMatthew G. Knepley DM dm; 10840be0ff1SMatthew G. Knepley 10940be0ff1SMatthew G. Knepley PetscFunctionBegin; 1109566063dSJacob Faibussowitsch if (!dg->X) PetscCall(VecDuplicate(ts->vec_sol, &dg->X)); 1119566063dSJacob Faibussowitsch if (!dg->X0) PetscCall(VecDuplicate(ts->vec_sol, &dg->X0)); 1129566063dSJacob Faibussowitsch if (!dg->Xdot) PetscCall(VecDuplicate(ts->vec_sol, &dg->Xdot)); 11340be0ff1SMatthew G. Knepley 1149566063dSJacob Faibussowitsch PetscCall(TSGetDM(ts, &dm)); 1159566063dSJacob Faibussowitsch PetscCall(DMCoarsenHookAdd(dm, DMCoarsenHook_TSDiscGrad, DMRestrictHook_TSDiscGrad, ts)); 1169566063dSJacob Faibussowitsch PetscCall(DMSubDomainHookAdd(dm, DMSubDomainHook_TSDiscGrad, DMSubDomainRestrictHook_TSDiscGrad, ts)); 11740be0ff1SMatthew G. Knepley PetscFunctionReturn(0); 11840be0ff1SMatthew G. Knepley } 11940be0ff1SMatthew G. Knepley 120d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSSetFromOptions_DiscGrad(TS ts, PetscOptionItems *PetscOptionsObject) 121d71ae5a4SJacob Faibussowitsch { 122db4653c2SDaniel Finn TS_DiscGrad *dg = (TS_DiscGrad *)ts->data; 12340be0ff1SMatthew G. Knepley 12440be0ff1SMatthew G. Knepley PetscFunctionBegin; 125d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "Discrete Gradients ODE solver options"); 126d71ae5a4SJacob Faibussowitsch { 127d71ae5a4SJacob Faibussowitsch PetscCall(PetscOptionsBool("-ts_discgrad_gonzalez", "Use Gonzalez term in discrete gradients formulation", "TSDiscGradUseGonzalez", dg->gonzalez, &dg->gonzalez, NULL)); 128d71ae5a4SJacob Faibussowitsch } 129d0609cedSBarry Smith PetscOptionsHeadEnd(); 13040be0ff1SMatthew G. Knepley PetscFunctionReturn(0); 13140be0ff1SMatthew G. Knepley } 13240be0ff1SMatthew G. Knepley 133d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSView_DiscGrad(TS ts, PetscViewer viewer) 134d71ae5a4SJacob Faibussowitsch { 13540be0ff1SMatthew G. Knepley PetscBool iascii; 13640be0ff1SMatthew G. Knepley 13740be0ff1SMatthew G. Knepley PetscFunctionBegin; 1389566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 13948a46eb9SPierre Jolivet if (iascii) PetscCall(PetscViewerASCIIPrintf(viewer, " Discrete Gradients\n")); 14040be0ff1SMatthew G. Knepley PetscFunctionReturn(0); 14140be0ff1SMatthew G. Knepley } 14240be0ff1SMatthew G. Knepley 143d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSDiscGradIsGonzalez_DiscGrad(TS ts, PetscBool *gonzalez) 144d71ae5a4SJacob Faibussowitsch { 145db4653c2SDaniel Finn TS_DiscGrad *dg = (TS_DiscGrad *)ts->data; 146db4653c2SDaniel Finn 147db4653c2SDaniel Finn PetscFunctionBegin; 148db4653c2SDaniel Finn *gonzalez = dg->gonzalez; 149db4653c2SDaniel Finn PetscFunctionReturn(0); 150db4653c2SDaniel Finn } 151db4653c2SDaniel Finn 152d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSDiscGradUseGonzalez_DiscGrad(TS ts, PetscBool flg) 153d71ae5a4SJacob Faibussowitsch { 154db4653c2SDaniel Finn TS_DiscGrad *dg = (TS_DiscGrad *)ts->data; 155db4653c2SDaniel Finn 156db4653c2SDaniel Finn PetscFunctionBegin; 157db4653c2SDaniel Finn dg->gonzalez = flg; 158db4653c2SDaniel Finn PetscFunctionReturn(0); 159db4653c2SDaniel Finn } 160db4653c2SDaniel Finn 161d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSReset_DiscGrad(TS ts) 162d71ae5a4SJacob Faibussowitsch { 16340be0ff1SMatthew G. Knepley TS_DiscGrad *dg = (TS_DiscGrad *)ts->data; 16440be0ff1SMatthew G. Knepley 16540be0ff1SMatthew G. Knepley PetscFunctionBegin; 1669566063dSJacob Faibussowitsch PetscCall(VecDestroy(&dg->X)); 1679566063dSJacob Faibussowitsch PetscCall(VecDestroy(&dg->X0)); 1689566063dSJacob Faibussowitsch PetscCall(VecDestroy(&dg->Xdot)); 16940be0ff1SMatthew G. Knepley PetscFunctionReturn(0); 17040be0ff1SMatthew G. Knepley } 17140be0ff1SMatthew G. Knepley 172d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSDestroy_DiscGrad(TS ts) 173d71ae5a4SJacob Faibussowitsch { 17440be0ff1SMatthew G. Knepley DM dm; 17540be0ff1SMatthew G. Knepley 17640be0ff1SMatthew G. Knepley PetscFunctionBegin; 1779566063dSJacob Faibussowitsch PetscCall(TSReset_DiscGrad(ts)); 1789566063dSJacob Faibussowitsch PetscCall(TSGetDM(ts, &dm)); 17940be0ff1SMatthew G. Knepley if (dm) { 1809566063dSJacob Faibussowitsch PetscCall(DMCoarsenHookRemove(dm, DMCoarsenHook_TSDiscGrad, DMRestrictHook_TSDiscGrad, ts)); 1819566063dSJacob Faibussowitsch PetscCall(DMSubDomainHookRemove(dm, DMSubDomainHook_TSDiscGrad, DMSubDomainRestrictHook_TSDiscGrad, ts)); 18240be0ff1SMatthew G. Knepley } 1839566063dSJacob Faibussowitsch PetscCall(PetscFree(ts->data)); 1849566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSDiscGradGetFormulation_C", NULL)); 1859566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSDiscGradSetFormulation_C", NULL)); 1862e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSDiscGradIsGonzalez_C", NULL)); 1872e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSDiscGradUseGonzalez_C", NULL)); 18840be0ff1SMatthew G. Knepley PetscFunctionReturn(0); 18940be0ff1SMatthew G. Knepley } 19040be0ff1SMatthew G. Knepley 191d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSInterpolate_DiscGrad(TS ts, PetscReal t, Vec X) 192d71ae5a4SJacob Faibussowitsch { 19340be0ff1SMatthew G. Knepley TS_DiscGrad *dg = (TS_DiscGrad *)ts->data; 19440be0ff1SMatthew G. Knepley PetscReal dt = t - ts->ptime; 19540be0ff1SMatthew G. Knepley 19640be0ff1SMatthew G. Knepley PetscFunctionBegin; 1979566063dSJacob Faibussowitsch PetscCall(VecCopy(ts->vec_sol, dg->X)); 1989566063dSJacob Faibussowitsch PetscCall(VecWAXPY(X, dt, dg->Xdot, dg->X)); 19940be0ff1SMatthew G. Knepley PetscFunctionReturn(0); 20040be0ff1SMatthew G. Knepley } 20140be0ff1SMatthew G. Knepley 202d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSDiscGrad_SNESSolve(TS ts, Vec b, Vec x) 203d71ae5a4SJacob Faibussowitsch { 20440be0ff1SMatthew G. Knepley SNES snes; 20540be0ff1SMatthew G. Knepley PetscInt nits, lits; 20640be0ff1SMatthew G. Knepley 20740be0ff1SMatthew G. Knepley PetscFunctionBegin; 2089566063dSJacob Faibussowitsch PetscCall(TSGetSNES(ts, &snes)); 2099566063dSJacob Faibussowitsch PetscCall(SNESSolve(snes, b, x)); 2109566063dSJacob Faibussowitsch PetscCall(SNESGetIterationNumber(snes, &nits)); 2119566063dSJacob Faibussowitsch PetscCall(SNESGetLinearSolveIterations(snes, &lits)); 21240be0ff1SMatthew G. Knepley ts->snes_its += nits; 21340be0ff1SMatthew G. Knepley ts->ksp_its += lits; 21440be0ff1SMatthew G. Knepley PetscFunctionReturn(0); 21540be0ff1SMatthew G. Knepley } 21640be0ff1SMatthew G. Knepley 217d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSStep_DiscGrad(TS ts) 218d71ae5a4SJacob Faibussowitsch { 21940be0ff1SMatthew G. Knepley TS_DiscGrad *dg = (TS_DiscGrad *)ts->data; 22040be0ff1SMatthew G. Knepley TSAdapt adapt; 22140be0ff1SMatthew G. Knepley TSStepStatus status = TS_STEP_INCOMPLETE; 22240be0ff1SMatthew G. Knepley PetscInt rejections = 0; 22340be0ff1SMatthew G. Knepley PetscBool stageok, accept = PETSC_TRUE; 22440be0ff1SMatthew G. Knepley PetscReal next_time_step = ts->time_step; 22540be0ff1SMatthew G. Knepley 22640be0ff1SMatthew G. Knepley PetscFunctionBegin; 2279566063dSJacob Faibussowitsch PetscCall(TSGetAdapt(ts, &adapt)); 2289566063dSJacob Faibussowitsch if (!ts->steprollback) PetscCall(VecCopy(ts->vec_sol, dg->X0)); 22940be0ff1SMatthew G. Knepley 23040be0ff1SMatthew G. Knepley while (!ts->reason && status != TS_STEP_COMPLETE) { 23140be0ff1SMatthew G. Knepley PetscReal shift = 1 / (0.5 * ts->time_step); 23240be0ff1SMatthew G. Knepley 23340be0ff1SMatthew G. Knepley dg->stage_time = ts->ptime + 0.5 * ts->time_step; 23440be0ff1SMatthew G. Knepley 2359566063dSJacob Faibussowitsch PetscCall(VecCopy(dg->X0, dg->X)); 2369566063dSJacob Faibussowitsch PetscCall(TSPreStage(ts, dg->stage_time)); 2379566063dSJacob Faibussowitsch PetscCall(TSDiscGrad_SNESSolve(ts, NULL, dg->X)); 2389566063dSJacob Faibussowitsch PetscCall(TSPostStage(ts, dg->stage_time, 0, &dg->X)); 2399566063dSJacob Faibussowitsch PetscCall(TSAdaptCheckStage(adapt, ts, dg->stage_time, dg->X, &stageok)); 24040be0ff1SMatthew G. Knepley if (!stageok) goto reject_step; 24140be0ff1SMatthew G. Knepley 24240be0ff1SMatthew G. Knepley status = TS_STEP_PENDING; 2439566063dSJacob Faibussowitsch PetscCall(VecAXPBYPCZ(dg->Xdot, -shift, shift, 0, dg->X0, dg->X)); 2449566063dSJacob Faibussowitsch PetscCall(VecAXPY(ts->vec_sol, ts->time_step, dg->Xdot)); 2459566063dSJacob Faibussowitsch PetscCall(TSAdaptChoose(adapt, ts, ts->time_step, NULL, &next_time_step, &accept)); 24640be0ff1SMatthew G. Knepley status = accept ? TS_STEP_COMPLETE : TS_STEP_INCOMPLETE; 24740be0ff1SMatthew G. Knepley if (!accept) { 2489566063dSJacob Faibussowitsch PetscCall(VecCopy(dg->X0, ts->vec_sol)); 24940be0ff1SMatthew G. Knepley ts->time_step = next_time_step; 25040be0ff1SMatthew G. Knepley goto reject_step; 25140be0ff1SMatthew G. Knepley } 25240be0ff1SMatthew G. Knepley ts->ptime += ts->time_step; 25340be0ff1SMatthew G. Knepley ts->time_step = next_time_step; 25440be0ff1SMatthew G. Knepley break; 25540be0ff1SMatthew G. Knepley 25640be0ff1SMatthew G. Knepley reject_step: 2579371c9d4SSatish Balay ts->reject++; 2589371c9d4SSatish Balay accept = PETSC_FALSE; 25940be0ff1SMatthew G. Knepley if (!ts->reason && ts->max_reject >= 0 && ++rejections > ts->max_reject) { 26040be0ff1SMatthew G. Knepley ts->reason = TS_DIVERGED_STEP_REJECTED; 26163a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(ts, "Step=%" PetscInt_FMT ", step rejections %" PetscInt_FMT " greater than current TS allowed, stopping solve\n", ts->steps, rejections)); 26240be0ff1SMatthew G. Knepley } 26340be0ff1SMatthew G. Knepley } 26440be0ff1SMatthew G. Knepley PetscFunctionReturn(0); 26540be0ff1SMatthew G. Knepley } 26640be0ff1SMatthew G. Knepley 267d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSGetStages_DiscGrad(TS ts, PetscInt *ns, Vec **Y) 268d71ae5a4SJacob Faibussowitsch { 26940be0ff1SMatthew G. Knepley TS_DiscGrad *dg = (TS_DiscGrad *)ts->data; 27040be0ff1SMatthew G. Knepley 27140be0ff1SMatthew G. Knepley PetscFunctionBegin; 27240be0ff1SMatthew G. Knepley if (ns) *ns = 1; 27340be0ff1SMatthew G. Knepley if (Y) *Y = &(dg->X); 27440be0ff1SMatthew G. Knepley PetscFunctionReturn(0); 27540be0ff1SMatthew G. Knepley } 27640be0ff1SMatthew G. Knepley 27740be0ff1SMatthew G. Knepley /* 27840be0ff1SMatthew G. Knepley This defines the nonlinear equation that is to be solved with SNES 27940be0ff1SMatthew G. Knepley G(U) = F[t0 + 0.5*dt, U, (U-U0)/dt] = 0 28040be0ff1SMatthew G. Knepley */ 281db4653c2SDaniel Finn 282db4653c2SDaniel Finn /* x = (x+x')/2 */ 283db4653c2SDaniel Finn /* NEED TO CALCULATE x_{n+1} from x and x_{n}*/ 284d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESTSFormFunction_DiscGrad(SNES snes, Vec x, Vec y, TS ts) 285d71ae5a4SJacob Faibussowitsch { 28640be0ff1SMatthew G. Knepley TS_DiscGrad *dg = (TS_DiscGrad *)ts->data; 287db4653c2SDaniel Finn PetscReal norm, shift = 1 / (0.5 * ts->time_step); 288db4653c2SDaniel Finn PetscInt n; 289db4653c2SDaniel Finn Vec X0, Xdot, Xp, Xdiff; 290db4653c2SDaniel Finn Mat S; 291db4653c2SDaniel Finn PetscScalar F = 0, F0 = 0, Gp; 292db4653c2SDaniel Finn Vec G, SgF; 29340be0ff1SMatthew G. Knepley DM dm, dmsave; 29440be0ff1SMatthew G. Knepley 29540be0ff1SMatthew G. Knepley PetscFunctionBegin; 2969566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 29740be0ff1SMatthew G. Knepley 2989566063dSJacob Faibussowitsch PetscCall(VecDuplicate(y, &Xp)); 2999566063dSJacob Faibussowitsch PetscCall(VecDuplicate(y, &Xdiff)); 3009566063dSJacob Faibussowitsch PetscCall(VecDuplicate(y, &SgF)); 3019566063dSJacob Faibussowitsch PetscCall(VecDuplicate(y, &G)); 302db4653c2SDaniel Finn 3039566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(y, &n)); 3049566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_WORLD, &S)); 3059566063dSJacob Faibussowitsch PetscCall(MatSetSizes(S, PETSC_DECIDE, PETSC_DECIDE, n, n)); 3069566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(S)); 3079566063dSJacob Faibussowitsch PetscCall(MatSetUp(S)); 3089566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(S, MAT_FINAL_ASSEMBLY)); 3099566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(S, MAT_FINAL_ASSEMBLY)); 310db4653c2SDaniel Finn 3119566063dSJacob Faibussowitsch PetscCall(TSDiscGradGetX0AndXdot(ts, dm, &X0, &Xdot)); 3129566063dSJacob Faibussowitsch PetscCall(VecAXPBYPCZ(Xdot, -shift, shift, 0, X0, x)); /* Xdot = shift (x - X0) */ 313db4653c2SDaniel Finn 3149566063dSJacob Faibussowitsch PetscCall(VecAXPBYPCZ(Xp, -1, 2, 0, X0, x)); /* Xp = 2*x - X0 + (0)*Xmid */ 3159566063dSJacob Faibussowitsch PetscCall(VecAXPBYPCZ(Xdiff, -1, 1, 0, X0, Xp)); /* Xdiff = xp - X0 + (0)*Xdiff */ 316db4653c2SDaniel Finn 317db4653c2SDaniel Finn if (dg->gonzalez) { 3189566063dSJacob Faibussowitsch PetscCall((*dg->Sfunc)(ts, dg->stage_time, x, S, dg->funcCtx)); 3199566063dSJacob Faibussowitsch PetscCall((*dg->Ffunc)(ts, dg->stage_time, Xp, &F, dg->funcCtx)); 3209566063dSJacob Faibussowitsch PetscCall((*dg->Ffunc)(ts, dg->stage_time, X0, &F0, dg->funcCtx)); 3219566063dSJacob Faibussowitsch PetscCall((*dg->Gfunc)(ts, dg->stage_time, x, G, dg->funcCtx)); 322db4653c2SDaniel Finn 323db4653c2SDaniel Finn /* Adding Extra Gonzalez Term */ 3249566063dSJacob Faibussowitsch PetscCall(VecDot(Xdiff, G, &Gp)); 3259566063dSJacob Faibussowitsch PetscCall(VecNorm(Xdiff, NORM_2, &norm)); 326db4653c2SDaniel Finn if (norm < PETSC_SQRT_MACHINE_EPSILON) { 327db4653c2SDaniel Finn Gp = 0; 328db4653c2SDaniel Finn } else { 329db4653c2SDaniel Finn /* Gp = (1/|xn+1 - xn|^2) * (F(xn+1) - F(xn) - Gp) */ 330db4653c2SDaniel Finn Gp = (F - F0 - Gp) / PetscSqr(norm); 331db4653c2SDaniel Finn } 3329566063dSJacob Faibussowitsch PetscCall(VecAXPY(G, Gp, Xdiff)); 3339566063dSJacob Faibussowitsch PetscCall(MatMult(S, G, SgF)); /* S*gradF */ 334db4653c2SDaniel Finn 335db4653c2SDaniel Finn } else { 3369566063dSJacob Faibussowitsch PetscCall((*dg->Sfunc)(ts, dg->stage_time, x, S, dg->funcCtx)); 3379566063dSJacob Faibussowitsch PetscCall((*dg->Gfunc)(ts, dg->stage_time, x, G, dg->funcCtx)); 338db4653c2SDaniel Finn 3399566063dSJacob Faibussowitsch PetscCall(MatMult(S, G, SgF)); /* Xdot = S*gradF */ 340db4653c2SDaniel Finn } 34140be0ff1SMatthew G. Knepley /* DM monkey-business allows user code to call TSGetDM() inside of functions evaluated on levels of FAS */ 34240be0ff1SMatthew G. Knepley dmsave = ts->dm; 34340be0ff1SMatthew G. Knepley ts->dm = dm; 3449566063dSJacob Faibussowitsch PetscCall(VecAXPBYPCZ(y, 1, -1, 0, Xdot, SgF)); 34540be0ff1SMatthew G. Knepley ts->dm = dmsave; 3469566063dSJacob Faibussowitsch PetscCall(TSDiscGradRestoreX0AndXdot(ts, dm, &X0, &Xdot)); 347db4653c2SDaniel Finn 3489566063dSJacob Faibussowitsch PetscCall(VecDestroy(&Xp)); 3499566063dSJacob Faibussowitsch PetscCall(VecDestroy(&Xdiff)); 3509566063dSJacob Faibussowitsch PetscCall(VecDestroy(&SgF)); 3519566063dSJacob Faibussowitsch PetscCall(VecDestroy(&G)); 3529566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S)); 353db4653c2SDaniel Finn 35440be0ff1SMatthew G. Knepley PetscFunctionReturn(0); 35540be0ff1SMatthew G. Knepley } 35640be0ff1SMatthew G. Knepley 357d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESTSFormJacobian_DiscGrad(SNES snes, Vec x, Mat A, Mat B, TS ts) 358d71ae5a4SJacob Faibussowitsch { 35940be0ff1SMatthew G. Knepley TS_DiscGrad *dg = (TS_DiscGrad *)ts->data; 36040be0ff1SMatthew G. Knepley PetscReal shift = 1 / (0.5 * ts->time_step); 36140be0ff1SMatthew G. Knepley Vec Xdot; 36240be0ff1SMatthew G. Knepley DM dm, dmsave; 36340be0ff1SMatthew G. Knepley 36440be0ff1SMatthew G. Knepley PetscFunctionBegin; 3659566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 36640be0ff1SMatthew G. Knepley /* Xdot has already been computed in SNESTSFormFunction_DiscGrad (SNES guarantees this) */ 3679566063dSJacob Faibussowitsch PetscCall(TSDiscGradGetX0AndXdot(ts, dm, NULL, &Xdot)); 36840be0ff1SMatthew G. Knepley 36940be0ff1SMatthew G. Knepley dmsave = ts->dm; 37040be0ff1SMatthew G. Knepley ts->dm = dm; 3719566063dSJacob Faibussowitsch PetscCall(TSComputeIJacobian(ts, dg->stage_time, x, Xdot, shift, A, B, PETSC_FALSE)); 37240be0ff1SMatthew G. Knepley ts->dm = dmsave; 3739566063dSJacob Faibussowitsch PetscCall(TSDiscGradRestoreX0AndXdot(ts, dm, NULL, &Xdot)); 37440be0ff1SMatthew G. Knepley PetscFunctionReturn(0); 37540be0ff1SMatthew G. Knepley } 37640be0ff1SMatthew G. Knepley 377d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSDiscGradGetFormulation_DiscGrad(TS ts, PetscErrorCode (**Sfunc)(TS, PetscReal, Vec, Mat, void *), PetscErrorCode (**Ffunc)(TS, PetscReal, Vec, PetscScalar *, void *), PetscErrorCode (**Gfunc)(TS, PetscReal, Vec, Vec, void *), void *ctx) 378d71ae5a4SJacob Faibussowitsch { 37940be0ff1SMatthew G. Knepley TS_DiscGrad *dg = (TS_DiscGrad *)ts->data; 38040be0ff1SMatthew G. Knepley 38140be0ff1SMatthew G. Knepley PetscFunctionBegin; 38240be0ff1SMatthew G. Knepley *Sfunc = dg->Sfunc; 38340be0ff1SMatthew G. Knepley *Ffunc = dg->Ffunc; 38440be0ff1SMatthew G. Knepley *Gfunc = dg->Gfunc; 38540be0ff1SMatthew G. Knepley PetscFunctionReturn(0); 38640be0ff1SMatthew G. Knepley } 38740be0ff1SMatthew G. Knepley 388d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSDiscGradSetFormulation_DiscGrad(TS ts, PetscErrorCode (*Sfunc)(TS, PetscReal, Vec, Mat, void *), PetscErrorCode (*Ffunc)(TS, PetscReal, Vec, PetscScalar *, void *), PetscErrorCode (*Gfunc)(TS, PetscReal, Vec, Vec, void *), void *ctx) 389d71ae5a4SJacob Faibussowitsch { 39040be0ff1SMatthew G. Knepley TS_DiscGrad *dg = (TS_DiscGrad *)ts->data; 39140be0ff1SMatthew G. Knepley 39240be0ff1SMatthew G. Knepley PetscFunctionBegin; 39340be0ff1SMatthew G. Knepley dg->Sfunc = Sfunc; 39440be0ff1SMatthew G. Knepley dg->Ffunc = Ffunc; 39540be0ff1SMatthew G. Knepley dg->Gfunc = Gfunc; 396db4653c2SDaniel Finn dg->funcCtx = ctx; 39740be0ff1SMatthew G. Knepley PetscFunctionReturn(0); 39840be0ff1SMatthew G. Knepley } 39940be0ff1SMatthew G. Knepley 40040be0ff1SMatthew G. Knepley /*MC 40140be0ff1SMatthew G. Knepley TSDISCGRAD - ODE solver using the discrete gradients version of the implicit midpoint method 40240be0ff1SMatthew G. Knepley 403*bcf0153eSBarry Smith Level: intermediate 404*bcf0153eSBarry Smith 4052ceb51e8SPatrick Sanan Notes: 4062ceb51e8SPatrick Sanan This is the implicit midpoint rule, with an optional term that guarantees the discrete gradient property. This 40740be0ff1SMatthew G. Knepley timestepper applies to systems of the form 40840be0ff1SMatthew G. Knepley $ u_t = S(u) grad F(u) 40940be0ff1SMatthew G. Knepley where S(u) is a linear operator, and F is a functional of u. 41040be0ff1SMatthew G. Knepley 411*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TSCreate()`, `TSSetType()`, `TS`, `TSDISCGRAD`, `TSDiscGradSetFormulation()` 41240be0ff1SMatthew G. Knepley M*/ 413d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode TSCreate_DiscGrad(TS ts) 414d71ae5a4SJacob Faibussowitsch { 41540be0ff1SMatthew G. Knepley TS_DiscGrad *th; 41640be0ff1SMatthew G. Knepley 41740be0ff1SMatthew G. Knepley PetscFunctionBegin; 4189566063dSJacob Faibussowitsch PetscCall(PetscCitationsRegister(DGCitation, &DGCite)); 41940be0ff1SMatthew G. Knepley ts->ops->reset = TSReset_DiscGrad; 42040be0ff1SMatthew G. Knepley ts->ops->destroy = TSDestroy_DiscGrad; 42140be0ff1SMatthew G. Knepley ts->ops->view = TSView_DiscGrad; 42240be0ff1SMatthew G. Knepley ts->ops->setfromoptions = TSSetFromOptions_DiscGrad; 42340be0ff1SMatthew G. Knepley ts->ops->setup = TSSetUp_DiscGrad; 42440be0ff1SMatthew G. Knepley ts->ops->step = TSStep_DiscGrad; 42540be0ff1SMatthew G. Knepley ts->ops->interpolate = TSInterpolate_DiscGrad; 42640be0ff1SMatthew G. Knepley ts->ops->getstages = TSGetStages_DiscGrad; 42740be0ff1SMatthew G. Knepley ts->ops->snesfunction = SNESTSFormFunction_DiscGrad; 42840be0ff1SMatthew G. Knepley ts->ops->snesjacobian = SNESTSFormJacobian_DiscGrad; 42940be0ff1SMatthew G. Knepley ts->default_adapt_type = TSADAPTNONE; 43040be0ff1SMatthew G. Knepley 43140be0ff1SMatthew G. Knepley ts->usessnes = PETSC_TRUE; 43240be0ff1SMatthew G. Knepley 4334dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&th)); 43440be0ff1SMatthew G. Knepley ts->data = (void *)th; 435db4653c2SDaniel Finn 436db4653c2SDaniel Finn th->gonzalez = PETSC_FALSE; 437db4653c2SDaniel Finn 4389566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSDiscGradGetFormulation_C", TSDiscGradGetFormulation_DiscGrad)); 4399566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSDiscGradSetFormulation_C", TSDiscGradSetFormulation_DiscGrad)); 4409566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSDiscGradIsGonzalez_C", TSDiscGradIsGonzalez_DiscGrad)); 4419566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSDiscGradUseGonzalez_C", TSDiscGradUseGonzalez_DiscGrad)); 44240be0ff1SMatthew G. Knepley PetscFunctionReturn(0); 44340be0ff1SMatthew G. Knepley } 44440be0ff1SMatthew G. Knepley 44540be0ff1SMatthew G. Knepley /*@C 446*bcf0153eSBarry Smith TSDiscGradGetFormulation - Get the construction method for S, F, and grad F from the formulation u_t = S grad F for `TSDISCGRAD` 44740be0ff1SMatthew G. Knepley 44840be0ff1SMatthew G. Knepley Not Collective 44940be0ff1SMatthew G. Knepley 45040be0ff1SMatthew G. Knepley Input Parameter: 45140be0ff1SMatthew G. Knepley . ts - timestepping context 45240be0ff1SMatthew G. Knepley 45340be0ff1SMatthew G. Knepley Output Parameters: 45440be0ff1SMatthew G. Knepley + Sfunc - constructor for the S matrix from the formulation 45540be0ff1SMatthew G. Knepley . Ffunc - functional F from the formulation 456f1a722f8SMatthew G. Knepley . Gfunc - constructor for the gradient of F from the formulation 457f1a722f8SMatthew G. Knepley - ctx - the user context 45840be0ff1SMatthew G. Knepley 45940be0ff1SMatthew G. Knepley Calling sequence of Sfunc: 46040be0ff1SMatthew G. Knepley $ PetscErrorCode func(TS ts, PetscReal time, Vec u, Mat S, void *) 46140be0ff1SMatthew G. Knepley 46240be0ff1SMatthew G. Knepley Calling sequence of Ffunc: 46340be0ff1SMatthew G. Knepley $ PetscErrorCode func(TS ts, PetscReal time, Vec u, PetscScalar *F, void *) 46440be0ff1SMatthew G. Knepley 46540be0ff1SMatthew G. Knepley Calling sequence of Gfunc: 46640be0ff1SMatthew G. Knepley $ PetscErrorCode func(TS ts, PetscReal time, Vec u, Vec G, void *) 46740be0ff1SMatthew G. Knepley 46840be0ff1SMatthew G. Knepley Level: intermediate 46940be0ff1SMatthew G. Knepley 470*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TS`, `TSDISCGRAD`, `TSDiscGradSetFormulation()` 47140be0ff1SMatthew G. Knepley @*/ 472d71ae5a4SJacob Faibussowitsch PetscErrorCode TSDiscGradGetFormulation(TS ts, PetscErrorCode (**Sfunc)(TS, PetscReal, Vec, Mat, void *), PetscErrorCode (**Ffunc)(TS, PetscReal, Vec, PetscScalar *, void *), PetscErrorCode (**Gfunc)(TS, PetscReal, Vec, Vec, void *), void *ctx) 473d71ae5a4SJacob Faibussowitsch { 47440be0ff1SMatthew G. Knepley PetscFunctionBegin; 47540be0ff1SMatthew G. Knepley PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 47640be0ff1SMatthew G. Knepley PetscValidPointer(Sfunc, 2); 47740be0ff1SMatthew G. Knepley PetscValidPointer(Ffunc, 3); 47840be0ff1SMatthew G. Knepley PetscValidPointer(Gfunc, 4); 479cac4c232SBarry Smith PetscUseMethod(ts, "TSDiscGradGetFormulation_C", (TS, PetscErrorCode(**Sfunc)(TS, PetscReal, Vec, Mat, void *), PetscErrorCode(**Ffunc)(TS, PetscReal, Vec, PetscScalar *, void *), PetscErrorCode(**Gfunc)(TS, PetscReal, Vec, Vec, void *), void *), (ts, Sfunc, Ffunc, Gfunc, ctx)); 48040be0ff1SMatthew G. Knepley PetscFunctionReturn(0); 48140be0ff1SMatthew G. Knepley } 48240be0ff1SMatthew G. Knepley 48340be0ff1SMatthew G. Knepley /*@C 484*bcf0153eSBarry Smith TSDiscGradSetFormulation - Set the construction method for S, F, and grad F from the formulation u_t = S(u) grad F(u) for `TSDISCGRAD` 48540be0ff1SMatthew G. Knepley 48640be0ff1SMatthew G. Knepley Not Collective 48740be0ff1SMatthew G. Knepley 48840be0ff1SMatthew G. Knepley Input Parameters: 48940be0ff1SMatthew G. Knepley + ts - timestepping context 49040be0ff1SMatthew G. Knepley . Sfunc - constructor for the S matrix from the formulation 49140be0ff1SMatthew G. Knepley . Ffunc - functional F from the formulation 49240be0ff1SMatthew G. Knepley - Gfunc - constructor for the gradient of F from the formulation 49340be0ff1SMatthew G. Knepley Calling sequence of Sfunc: 49440be0ff1SMatthew G. Knepley $ PetscErrorCode func(TS ts, PetscReal time, Vec u, Mat S, void *) 49540be0ff1SMatthew G. Knepley 49640be0ff1SMatthew G. Knepley Calling sequence of Ffunc: 49740be0ff1SMatthew G. Knepley $ PetscErrorCode func(TS ts, PetscReal time, Vec u, PetscScalar *F, void *) 49840be0ff1SMatthew G. Knepley 49940be0ff1SMatthew G. Knepley Calling sequence of Gfunc: 50040be0ff1SMatthew G. Knepley $ PetscErrorCode func(TS ts, PetscReal time, Vec u, Vec G, void *) 50140be0ff1SMatthew G. Knepley 50240be0ff1SMatthew G. Knepley Level: Intermediate 50340be0ff1SMatthew G. Knepley 504*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TSDISCGRAD`, `TSDiscGradGetFormulation()` 50540be0ff1SMatthew G. Knepley @*/ 506d71ae5a4SJacob Faibussowitsch PetscErrorCode TSDiscGradSetFormulation(TS ts, PetscErrorCode (*Sfunc)(TS, PetscReal, Vec, Mat, void *), PetscErrorCode (*Ffunc)(TS, PetscReal, Vec, PetscScalar *, void *), PetscErrorCode (*Gfunc)(TS, PetscReal, Vec, Vec, void *), void *ctx) 507d71ae5a4SJacob Faibussowitsch { 50840be0ff1SMatthew G. Knepley PetscFunctionBegin; 50940be0ff1SMatthew G. Knepley PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 51040be0ff1SMatthew G. Knepley PetscValidFunction(Sfunc, 2); 51140be0ff1SMatthew G. Knepley PetscValidFunction(Ffunc, 3); 51240be0ff1SMatthew G. Knepley PetscValidFunction(Gfunc, 4); 513cac4c232SBarry Smith PetscTryMethod(ts, "TSDiscGradSetFormulation_C", (TS, PetscErrorCode(*Sfunc)(TS, PetscReal, Vec, Mat, void *), PetscErrorCode(*Ffunc)(TS, PetscReal, Vec, PetscScalar *, void *), PetscErrorCode(*Gfunc)(TS, PetscReal, Vec, Vec, void *), void *), (ts, Sfunc, Ffunc, Gfunc, ctx)); 514db4653c2SDaniel Finn PetscFunctionReturn(0); 515db4653c2SDaniel Finn } 516db4653c2SDaniel Finn 517db4653c2SDaniel Finn /*@ 518*bcf0153eSBarry Smith TSDiscGradIsGonzalez - Checks flag for whether to use additional conservative terms in discrete gradient formulation for `TSDISCGRAD` 519db4653c2SDaniel Finn 520db4653c2SDaniel Finn Not Collective 521db4653c2SDaniel Finn 522db4653c2SDaniel Finn Input Parameter: 523db4653c2SDaniel Finn . ts - timestepping context 524db4653c2SDaniel Finn 525db4653c2SDaniel Finn Output Parameter: 526*bcf0153eSBarry Smith . gonzalez - `PETSC_TRUE` when using the Gonzalez term 527db4653c2SDaniel Finn 528db4653c2SDaniel Finn Level: Advanced 529db4653c2SDaniel Finn 530*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TSDISCGRAD`, `TSDiscGradUseGonzalez()`, `TSDISCGRAD` 531db4653c2SDaniel Finn @*/ 532d71ae5a4SJacob Faibussowitsch PetscErrorCode TSDiscGradIsGonzalez(TS ts, PetscBool *gonzalez) 533d71ae5a4SJacob Faibussowitsch { 534db4653c2SDaniel Finn PetscFunctionBegin; 535db4653c2SDaniel Finn PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 536dadcf809SJacob Faibussowitsch PetscValidBoolPointer(gonzalez, 2); 537cac4c232SBarry Smith PetscUseMethod(ts, "TSDiscGradIsGonzalez_C", (TS, PetscBool *), (ts, gonzalez)); 538db4653c2SDaniel Finn PetscFunctionReturn(0); 539db4653c2SDaniel Finn } 540db4653c2SDaniel Finn 541db4653c2SDaniel Finn /*@ 542db4653c2SDaniel Finn TSDiscGradUseGonzalez - Sets discrete gradient formulation with or without additional conservative terms. Without flag, the discrete gradients timestepper is just backwards euler 543db4653c2SDaniel Finn 544db4653c2SDaniel Finn Not Collective 545db4653c2SDaniel Finn 546f1a722f8SMatthew G. Knepley Input Parameters: 547db4653c2SDaniel Finn + ts - timestepping context 548*bcf0153eSBarry Smith - flg - `PETSC_TRUE` to use the Gonzalez term 549db4653c2SDaniel Finn 550*bcf0153eSBarry Smith Options Database Key: 55167b8a455SSatish Balay . -ts_discgrad_gonzalez <flg> - use the Gonzalez term for the discrete gradient formulation 552db4653c2SDaniel Finn 553db4653c2SDaniel Finn Level: Intermediate 554db4653c2SDaniel Finn 555*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TSDISCGRAD` 556db4653c2SDaniel Finn @*/ 557d71ae5a4SJacob Faibussowitsch PetscErrorCode TSDiscGradUseGonzalez(TS ts, PetscBool flg) 558d71ae5a4SJacob Faibussowitsch { 559db4653c2SDaniel Finn PetscFunctionBegin; 560db4653c2SDaniel Finn PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 561cac4c232SBarry Smith PetscTryMethod(ts, "TSDiscGradUseGonzalez_C", (TS, PetscBool), (ts, flg)); 56240be0ff1SMatthew G. Knepley PetscFunctionReturn(0); 56340be0ff1SMatthew G. Knepley } 564