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; 273*f4f49eeaSPierre Jolivet 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)); 3533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 35440be0ff1SMatthew G. Knepley } 35540be0ff1SMatthew G. Knepley 356d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESTSFormJacobian_DiscGrad(SNES snes, Vec x, Mat A, Mat B, TS ts) 357d71ae5a4SJacob Faibussowitsch { 35840be0ff1SMatthew G. Knepley TS_DiscGrad *dg = (TS_DiscGrad *)ts->data; 35940be0ff1SMatthew G. Knepley PetscReal shift = 1 / (0.5 * ts->time_step); 36040be0ff1SMatthew G. Knepley Vec Xdot; 36140be0ff1SMatthew G. Knepley DM dm, dmsave; 36240be0ff1SMatthew G. Knepley 36340be0ff1SMatthew G. Knepley PetscFunctionBegin; 3649566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm)); 36540be0ff1SMatthew G. Knepley /* Xdot has already been computed in SNESTSFormFunction_DiscGrad (SNES guarantees this) */ 3669566063dSJacob Faibussowitsch PetscCall(TSDiscGradGetX0AndXdot(ts, dm, NULL, &Xdot)); 36740be0ff1SMatthew G. Knepley 36840be0ff1SMatthew G. Knepley dmsave = ts->dm; 36940be0ff1SMatthew G. Knepley ts->dm = dm; 3709566063dSJacob Faibussowitsch PetscCall(TSComputeIJacobian(ts, dg->stage_time, x, Xdot, shift, A, B, PETSC_FALSE)); 37140be0ff1SMatthew G. Knepley ts->dm = dmsave; 3729566063dSJacob Faibussowitsch PetscCall(TSDiscGradRestoreX0AndXdot(ts, dm, NULL, &Xdot)); 3733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 37440be0ff1SMatthew G. Knepley } 37540be0ff1SMatthew G. Knepley 376d71ae5a4SJacob 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) 377d71ae5a4SJacob Faibussowitsch { 37840be0ff1SMatthew G. Knepley TS_DiscGrad *dg = (TS_DiscGrad *)ts->data; 37940be0ff1SMatthew G. Knepley 38040be0ff1SMatthew G. Knepley PetscFunctionBegin; 38140be0ff1SMatthew G. Knepley *Sfunc = dg->Sfunc; 38240be0ff1SMatthew G. Knepley *Ffunc = dg->Ffunc; 38340be0ff1SMatthew G. Knepley *Gfunc = dg->Gfunc; 3843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 38540be0ff1SMatthew G. Knepley } 38640be0ff1SMatthew G. Knepley 387d71ae5a4SJacob 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) 388d71ae5a4SJacob Faibussowitsch { 38940be0ff1SMatthew G. Knepley TS_DiscGrad *dg = (TS_DiscGrad *)ts->data; 39040be0ff1SMatthew G. Knepley 39140be0ff1SMatthew G. Knepley PetscFunctionBegin; 39240be0ff1SMatthew G. Knepley dg->Sfunc = Sfunc; 39340be0ff1SMatthew G. Knepley dg->Ffunc = Ffunc; 39440be0ff1SMatthew G. Knepley dg->Gfunc = Gfunc; 395db4653c2SDaniel Finn dg->funcCtx = ctx; 3963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 39740be0ff1SMatthew G. Knepley } 39840be0ff1SMatthew G. Knepley 39940be0ff1SMatthew G. Knepley /*MC 40040be0ff1SMatthew G. Knepley TSDISCGRAD - ODE solver using the discrete gradients version of the implicit midpoint method 40140be0ff1SMatthew G. Knepley 402bcf0153eSBarry Smith Level: intermediate 403bcf0153eSBarry Smith 4042ceb51e8SPatrick Sanan Notes: 40514d0ab18SJacob Faibussowitsch This is the implicit midpoint rule, with an optional term that guarantees the discrete 40614d0ab18SJacob Faibussowitsch gradient property. This timestepper applies to systems of the form $u_t = S(u) \nabla F(u)$ 40714d0ab18SJacob Faibussowitsch where $S(u)$ is a linear operator, and $F$ is a functional of $u$. 40840be0ff1SMatthew G. Knepley 4091cc06b55SBarry Smith .seealso: [](ch_ts), `TSCreate()`, `TSSetType()`, `TS`, `TSDISCGRAD`, `TSDiscGradSetFormulation()` 41040be0ff1SMatthew G. Knepley M*/ 411d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode TSCreate_DiscGrad(TS ts) 412d71ae5a4SJacob Faibussowitsch { 41340be0ff1SMatthew G. Knepley TS_DiscGrad *th; 41440be0ff1SMatthew G. Knepley 41540be0ff1SMatthew G. Knepley PetscFunctionBegin; 4169566063dSJacob Faibussowitsch PetscCall(PetscCitationsRegister(DGCitation, &DGCite)); 41740be0ff1SMatthew G. Knepley ts->ops->reset = TSReset_DiscGrad; 41840be0ff1SMatthew G. Knepley ts->ops->destroy = TSDestroy_DiscGrad; 41940be0ff1SMatthew G. Knepley ts->ops->view = TSView_DiscGrad; 42040be0ff1SMatthew G. Knepley ts->ops->setfromoptions = TSSetFromOptions_DiscGrad; 42140be0ff1SMatthew G. Knepley ts->ops->setup = TSSetUp_DiscGrad; 42240be0ff1SMatthew G. Knepley ts->ops->step = TSStep_DiscGrad; 42340be0ff1SMatthew G. Knepley ts->ops->interpolate = TSInterpolate_DiscGrad; 42440be0ff1SMatthew G. Knepley ts->ops->getstages = TSGetStages_DiscGrad; 42540be0ff1SMatthew G. Knepley ts->ops->snesfunction = SNESTSFormFunction_DiscGrad; 42640be0ff1SMatthew G. Knepley ts->ops->snesjacobian = SNESTSFormJacobian_DiscGrad; 42740be0ff1SMatthew G. Knepley ts->default_adapt_type = TSADAPTNONE; 42840be0ff1SMatthew G. Knepley 42940be0ff1SMatthew G. Knepley ts->usessnes = PETSC_TRUE; 43040be0ff1SMatthew G. Knepley 4314dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&th)); 43240be0ff1SMatthew G. Knepley ts->data = (void *)th; 433db4653c2SDaniel Finn 434db4653c2SDaniel Finn th->gonzalez = PETSC_FALSE; 435db4653c2SDaniel Finn 4369566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSDiscGradGetFormulation_C", TSDiscGradGetFormulation_DiscGrad)); 4379566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSDiscGradSetFormulation_C", TSDiscGradSetFormulation_DiscGrad)); 4389566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSDiscGradIsGonzalez_C", TSDiscGradIsGonzalez_DiscGrad)); 4399566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSDiscGradUseGonzalez_C", TSDiscGradUseGonzalez_DiscGrad)); 4403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 44140be0ff1SMatthew G. Knepley } 44240be0ff1SMatthew G. Knepley 44340be0ff1SMatthew G. Knepley /*@C 44414d0ab18SJacob Faibussowitsch TSDiscGradGetFormulation - Get the construction method for S, F, and grad F from the 44514d0ab18SJacob Faibussowitsch formulation $u_t = S \nabla F$ for `TSDISCGRAD` 44640be0ff1SMatthew G. Knepley 44740be0ff1SMatthew G. Knepley Not Collective 44840be0ff1SMatthew G. Knepley 44940be0ff1SMatthew G. Knepley Input Parameter: 45040be0ff1SMatthew G. Knepley . ts - timestepping context 45140be0ff1SMatthew G. Knepley 45240be0ff1SMatthew G. Knepley Output Parameters: 45340be0ff1SMatthew G. Knepley + Sfunc - constructor for the S matrix from the formulation 45440be0ff1SMatthew G. Knepley . Ffunc - functional F from the formulation 455f1a722f8SMatthew G. Knepley . Gfunc - constructor for the gradient of F from the formulation 456f1a722f8SMatthew G. Knepley - ctx - the user context 45740be0ff1SMatthew G. Knepley 45820f4b53cSBarry Smith Calling sequence of `Sfunc`: 4598847d985SBarry Smith + ts - the integrator 4608847d985SBarry Smith . time - the current time 4618847d985SBarry Smith . u - the solution 4628847d985SBarry Smith . S - the S-matrix from the formulation 4638847d985SBarry Smith - ctx - the user context 46440be0ff1SMatthew G. Knepley 46520f4b53cSBarry Smith Calling sequence of `Ffunc`: 4668847d985SBarry Smith + ts - the integrator 4678847d985SBarry Smith . time - the current time 4688847d985SBarry Smith . u - the solution 4698847d985SBarry Smith . F - the computed function from the formulation 4708847d985SBarry Smith - ctx - the user context 47140be0ff1SMatthew G. Knepley 47220f4b53cSBarry Smith Calling sequence of `Gfunc`: 4738847d985SBarry Smith + ts - the integrator 4748847d985SBarry Smith . time - the current time 4758847d985SBarry Smith . u - the solution 4768847d985SBarry Smith . G - the gradient of the computed function from the formulation 4778847d985SBarry Smith - ctx - the user context 47840be0ff1SMatthew G. Knepley 47940be0ff1SMatthew G. Knepley Level: intermediate 48040be0ff1SMatthew G. Knepley 4811cc06b55SBarry Smith .seealso: [](ch_ts), `TS`, `TSDISCGRAD`, `TSDiscGradSetFormulation()` 48240be0ff1SMatthew G. Knepley @*/ 4838847d985SBarry Smith PetscErrorCode TSDiscGradGetFormulation(TS ts, PetscErrorCode (**Sfunc)(TS ts, PetscReal time, Vec u, Mat S, void *ctx), PetscErrorCode (**Ffunc)(TS ts, PetscReal time, Vec u, PetscScalar *F, void *ctx), PetscErrorCode (**Gfunc)(TS ts, PetscReal time, Vec u, Vec G, void *ctx), void *ctx) 484d71ae5a4SJacob Faibussowitsch { 48540be0ff1SMatthew G. Knepley PetscFunctionBegin; 48640be0ff1SMatthew G. Knepley PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4874f572ea9SToby Isaac PetscAssertPointer(Sfunc, 2); 4884f572ea9SToby Isaac PetscAssertPointer(Ffunc, 3); 4894f572ea9SToby Isaac PetscAssertPointer(Gfunc, 4); 490cac4c232SBarry 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)); 4913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 49240be0ff1SMatthew G. Knepley } 49340be0ff1SMatthew G. Knepley 49440be0ff1SMatthew G. Knepley /*@C 49514d0ab18SJacob Faibussowitsch TSDiscGradSetFormulation - Set the construction method for S, F, and grad F from the 49614d0ab18SJacob Faibussowitsch formulation $u_t = S(u) \nabla F(u)$ for `TSDISCGRAD` 49740be0ff1SMatthew G. Knepley 49840be0ff1SMatthew G. Knepley Not Collective 49940be0ff1SMatthew G. Knepley 50040be0ff1SMatthew G. Knepley Input Parameters: 50140be0ff1SMatthew G. Knepley + ts - timestepping context 50240be0ff1SMatthew G. Knepley . Sfunc - constructor for the S matrix from the formulation 50340be0ff1SMatthew G. Knepley . Ffunc - functional F from the formulation 5042fe279fdSBarry Smith . Gfunc - constructor for the gradient of F from the formulation 5052fe279fdSBarry Smith - ctx - optional context for the functions 50640be0ff1SMatthew G. Knepley 50720f4b53cSBarry Smith Calling sequence of `Sfunc`: 5088847d985SBarry Smith + ts - the integrator 5098847d985SBarry Smith . time - the current time 5108847d985SBarry Smith . u - the solution 5118847d985SBarry Smith . S - the S-matrix from the formulation 5128847d985SBarry Smith - ctx - the user context 51340be0ff1SMatthew G. Knepley 51420f4b53cSBarry Smith Calling sequence of `Ffunc`: 5158847d985SBarry Smith + ts - the integrator 5168847d985SBarry Smith . time - the current time 5178847d985SBarry Smith . u - the solution 5188847d985SBarry Smith . F - the computed function from the formulation 5198847d985SBarry Smith - ctx - the user context 52020f4b53cSBarry Smith 52120f4b53cSBarry Smith Calling sequence of `Gfunc`: 5228847d985SBarry Smith + ts - the integrator 5238847d985SBarry Smith . time - the current time 5248847d985SBarry Smith . u - the solution 5258847d985SBarry Smith . G - the gradient of the computed function from the formulation 5268847d985SBarry Smith - ctx - the user context 52740be0ff1SMatthew G. Knepley 528b43aa488SJacob Faibussowitsch Level: intermediate 52940be0ff1SMatthew G. Knepley 5301cc06b55SBarry Smith .seealso: [](ch_ts), `TSDISCGRAD`, `TSDiscGradGetFormulation()` 53140be0ff1SMatthew G. Knepley @*/ 5328847d985SBarry Smith PetscErrorCode TSDiscGradSetFormulation(TS ts, PetscErrorCode (*Sfunc)(TS ts, PetscReal time, Vec u, Mat S, void *ctx), PetscErrorCode (*Ffunc)(TS ts, PetscReal time, Vec u, PetscScalar *F, void *ctx), PetscErrorCode (*Gfunc)(TS ts, PetscReal time, Vec u, Vec G, void *ctx), void *ctx) 533d71ae5a4SJacob Faibussowitsch { 53440be0ff1SMatthew G. Knepley PetscFunctionBegin; 53540be0ff1SMatthew G. Knepley PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 53640be0ff1SMatthew G. Knepley PetscValidFunction(Sfunc, 2); 53740be0ff1SMatthew G. Knepley PetscValidFunction(Ffunc, 3); 53840be0ff1SMatthew G. Knepley PetscValidFunction(Gfunc, 4); 539cac4c232SBarry 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)); 5403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 541db4653c2SDaniel Finn } 542db4653c2SDaniel Finn 543db4653c2SDaniel Finn /*@ 54414d0ab18SJacob Faibussowitsch TSDiscGradIsGonzalez - Checks flag for whether to use additional conservative terms in 54514d0ab18SJacob Faibussowitsch discrete gradient formulation for `TSDISCGRAD` 546db4653c2SDaniel Finn 547db4653c2SDaniel Finn Not Collective 548db4653c2SDaniel Finn 549db4653c2SDaniel Finn Input Parameter: 550db4653c2SDaniel Finn . ts - timestepping context 551db4653c2SDaniel Finn 552db4653c2SDaniel Finn Output Parameter: 553bcf0153eSBarry Smith . gonzalez - `PETSC_TRUE` when using the Gonzalez term 554db4653c2SDaniel Finn 555b43aa488SJacob Faibussowitsch Level: advanced 556db4653c2SDaniel Finn 557b43aa488SJacob Faibussowitsch .seealso: [](ch_ts), `TSDISCGRAD`, `TSDiscGradUseGonzalez()` 558db4653c2SDaniel Finn @*/ 559d71ae5a4SJacob Faibussowitsch PetscErrorCode TSDiscGradIsGonzalez(TS ts, PetscBool *gonzalez) 560d71ae5a4SJacob Faibussowitsch { 561db4653c2SDaniel Finn PetscFunctionBegin; 562db4653c2SDaniel Finn PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5634f572ea9SToby Isaac PetscAssertPointer(gonzalez, 2); 564cac4c232SBarry Smith PetscUseMethod(ts, "TSDiscGradIsGonzalez_C", (TS, PetscBool *), (ts, gonzalez)); 5653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 566db4653c2SDaniel Finn } 567db4653c2SDaniel Finn 568db4653c2SDaniel Finn /*@ 56914d0ab18SJacob Faibussowitsch TSDiscGradUseGonzalez - Sets discrete gradient formulation with or without additional 57014d0ab18SJacob Faibussowitsch conservative terms. 571db4653c2SDaniel Finn 572db4653c2SDaniel Finn Not Collective 573db4653c2SDaniel Finn 574f1a722f8SMatthew G. Knepley Input Parameters: 575db4653c2SDaniel Finn + ts - timestepping context 576bcf0153eSBarry Smith - flg - `PETSC_TRUE` to use the Gonzalez term 577db4653c2SDaniel Finn 578bcf0153eSBarry Smith Options Database Key: 57967b8a455SSatish Balay . -ts_discgrad_gonzalez <flg> - use the Gonzalez term for the discrete gradient formulation 580db4653c2SDaniel Finn 581b43aa488SJacob Faibussowitsch Level: intermediate 582db4653c2SDaniel Finn 58314d0ab18SJacob Faibussowitsch Notes: 58414d0ab18SJacob Faibussowitsch Without `flg`, the discrete gradients timestepper is just backwards Euler. 58514d0ab18SJacob Faibussowitsch 5861cc06b55SBarry Smith .seealso: [](ch_ts), `TSDISCGRAD` 587db4653c2SDaniel Finn @*/ 588d71ae5a4SJacob Faibussowitsch PetscErrorCode TSDiscGradUseGonzalez(TS ts, PetscBool flg) 589d71ae5a4SJacob Faibussowitsch { 590db4653c2SDaniel Finn PetscFunctionBegin; 591db4653c2SDaniel Finn PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 592cac4c232SBarry Smith PetscTryMethod(ts, "TSDiscGradUseGonzalez_C", (TS, PetscBool), (ts, flg)); 5933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 59440be0ff1SMatthew G. Knepley } 595