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 } 403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 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 } 523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5340be0ff1SMatthew G. Knepley } 5440be0ff1SMatthew G. Knepley 55d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCoarsenHook_TSDiscGrad(DM fine, DM coarse, void *ctx) 56d71ae5a4SJacob Faibussowitsch { 5740be0ff1SMatthew G. Knepley PetscFunctionBegin; 583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 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)); 753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7640be0ff1SMatthew G. Knepley } 7740be0ff1SMatthew G. Knepley 78d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSubDomainHook_TSDiscGrad(DM dm, DM subdm, void *ctx) 79d71ae5a4SJacob Faibussowitsch { 8040be0ff1SMatthew G. Knepley PetscFunctionBegin; 813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 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)); 1013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 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)); 1173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 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(); 1303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 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")); 1403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 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; 1493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 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; 1583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 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)); 1693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 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)); 1883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 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)); 1993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 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; 2143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 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 } 2643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 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); 2743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 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 3543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 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)); 3743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 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; 3853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 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; 3973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 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 403bcf0153eSBarry Smith Level: intermediate 404bcf0153eSBarry 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 411bcf0153eSBarry 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)); 4423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 44340be0ff1SMatthew G. Knepley } 44440be0ff1SMatthew G. Knepley 44540be0ff1SMatthew G. Knepley /*@C 446bcf0153eSBarry 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 459*20f4b53cSBarry Smith Calling sequence of `Sfunc`: 460*20f4b53cSBarry Smith $ PetscErrorCode Sfunc(TS ts, PetscReal time, Vec u, Mat S, void *ctx) 46140be0ff1SMatthew G. Knepley 462*20f4b53cSBarry Smith Calling sequence of `Ffunc`: 463*20f4b53cSBarry Smith $ PetscErrorCode Ffunc(TS ts, PetscReal time, Vec u, PetscScalar *F, void *ctx) 46440be0ff1SMatthew G. Knepley 465*20f4b53cSBarry Smith Calling sequence of `Gfunc`: 466*20f4b53cSBarry Smith $ PetscErrorCode Gfunc(TS ts, PetscReal time, Vec u, Vec G, void *ctx) 46740be0ff1SMatthew G. Knepley 46840be0ff1SMatthew G. Knepley Level: intermediate 46940be0ff1SMatthew G. Knepley 470bcf0153eSBarry 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)); 4803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 48140be0ff1SMatthew G. Knepley } 48240be0ff1SMatthew G. Knepley 48340be0ff1SMatthew G. Knepley /*@C 484bcf0153eSBarry 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 494*20f4b53cSBarry Smith Calling sequence of `Sfunc`: 495*20f4b53cSBarry Smith $ PetscErrorCode Sfunc(TS ts, PetscReal time, Vec u, Mat S, void *ctx) 49640be0ff1SMatthew G. Knepley 497*20f4b53cSBarry Smith Calling sequence of `Ffunc`: 498*20f4b53cSBarry Smith $ PetscErrorCode Ffunc(TS ts, PetscReal time, Vec u, PetscScalar *F, void *ctx) 499*20f4b53cSBarry Smith 500*20f4b53cSBarry Smith Calling sequence of `Gfunc`: 501*20f4b53cSBarry Smith $ PetscErrorCode Gfunc(TS ts, PetscReal time, Vec u, Vec G, void *ctx) 50240be0ff1SMatthew G. Knepley 50340be0ff1SMatthew G. Knepley Level: Intermediate 50440be0ff1SMatthew G. Knepley 505bcf0153eSBarry Smith .seealso: [](chapter_ts), `TSDISCGRAD`, `TSDiscGradGetFormulation()` 50640be0ff1SMatthew G. Knepley @*/ 507d71ae5a4SJacob 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) 508d71ae5a4SJacob Faibussowitsch { 50940be0ff1SMatthew G. Knepley PetscFunctionBegin; 51040be0ff1SMatthew G. Knepley PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 51140be0ff1SMatthew G. Knepley PetscValidFunction(Sfunc, 2); 51240be0ff1SMatthew G. Knepley PetscValidFunction(Ffunc, 3); 51340be0ff1SMatthew G. Knepley PetscValidFunction(Gfunc, 4); 514cac4c232SBarry 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)); 5153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 516db4653c2SDaniel Finn } 517db4653c2SDaniel Finn 518db4653c2SDaniel Finn /*@ 519bcf0153eSBarry Smith TSDiscGradIsGonzalez - Checks flag for whether to use additional conservative terms in discrete gradient formulation for `TSDISCGRAD` 520db4653c2SDaniel Finn 521db4653c2SDaniel Finn Not Collective 522db4653c2SDaniel Finn 523db4653c2SDaniel Finn Input Parameter: 524db4653c2SDaniel Finn . ts - timestepping context 525db4653c2SDaniel Finn 526db4653c2SDaniel Finn Output Parameter: 527bcf0153eSBarry Smith . gonzalez - `PETSC_TRUE` when using the Gonzalez term 528db4653c2SDaniel Finn 529db4653c2SDaniel Finn Level: Advanced 530db4653c2SDaniel Finn 531bcf0153eSBarry Smith .seealso: [](chapter_ts), `TSDISCGRAD`, `TSDiscGradUseGonzalez()`, `TSDISCGRAD` 532db4653c2SDaniel Finn @*/ 533d71ae5a4SJacob Faibussowitsch PetscErrorCode TSDiscGradIsGonzalez(TS ts, PetscBool *gonzalez) 534d71ae5a4SJacob Faibussowitsch { 535db4653c2SDaniel Finn PetscFunctionBegin; 536db4653c2SDaniel Finn PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 537dadcf809SJacob Faibussowitsch PetscValidBoolPointer(gonzalez, 2); 538cac4c232SBarry Smith PetscUseMethod(ts, "TSDiscGradIsGonzalez_C", (TS, PetscBool *), (ts, gonzalez)); 5393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 540db4653c2SDaniel Finn } 541db4653c2SDaniel Finn 542db4653c2SDaniel Finn /*@ 543*20f4b53cSBarry Smith TSDiscGradUseGonzalez - Sets discrete gradient formulation with or without additional conservative terms. 544*20f4b53cSBarry Smith Without the flag, the discrete gradients timestepper is just backwards Euler 545db4653c2SDaniel Finn 546db4653c2SDaniel Finn Not Collective 547db4653c2SDaniel Finn 548f1a722f8SMatthew G. Knepley Input Parameters: 549db4653c2SDaniel Finn + ts - timestepping context 550bcf0153eSBarry Smith - flg - `PETSC_TRUE` to use the Gonzalez term 551db4653c2SDaniel Finn 552bcf0153eSBarry Smith Options Database Key: 55367b8a455SSatish Balay . -ts_discgrad_gonzalez <flg> - use the Gonzalez term for the discrete gradient formulation 554db4653c2SDaniel Finn 555db4653c2SDaniel Finn Level: Intermediate 556db4653c2SDaniel Finn 557bcf0153eSBarry Smith .seealso: [](chapter_ts), `TSDISCGRAD` 558db4653c2SDaniel Finn @*/ 559d71ae5a4SJacob Faibussowitsch PetscErrorCode TSDiscGradUseGonzalez(TS ts, PetscBool flg) 560d71ae5a4SJacob Faibussowitsch { 561db4653c2SDaniel Finn PetscFunctionBegin; 562db4653c2SDaniel Finn PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 563cac4c232SBarry Smith PetscTryMethod(ts, "TSDiscGradUseGonzalez_C", (TS, PetscBool), (ts, flg)); 5643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 56540be0ff1SMatthew G. Knepley } 566