xref: /petsc/src/ts/impls/implicit/discgrad/tsdiscgrad.c (revision db4653c29aec83ac4814f22af49087b221e90623)
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;
20*db4653c2SDaniel Finn   void        *funcCtx;
21*db4653c2SDaniel 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 
2740be0ff1SMatthew G. Knepley static PetscErrorCode TSDiscGradGetX0AndXdot(TS ts, DM dm, Vec *X0, Vec *Xdot)
2840be0ff1SMatthew G. Knepley {
2940be0ff1SMatthew G. Knepley   TS_DiscGrad   *dg = (TS_DiscGrad *) ts->data;
3040be0ff1SMatthew G. Knepley   PetscErrorCode ierr;
3140be0ff1SMatthew G. Knepley 
3240be0ff1SMatthew G. Knepley   PetscFunctionBegin;
3340be0ff1SMatthew G. Knepley   if (X0) {
3440be0ff1SMatthew G. Knepley     if (dm && dm != ts->dm) {ierr = DMGetNamedGlobalVector(dm, "TSDiscGrad_X0", X0);CHKERRQ(ierr);}
3540be0ff1SMatthew G. Knepley     else                    {*X0  = ts->vec_sol;}
3640be0ff1SMatthew G. Knepley   }
3740be0ff1SMatthew G. Knepley   if (Xdot) {
3840be0ff1SMatthew G. Knepley     if (dm && dm != ts->dm) {ierr = DMGetNamedGlobalVector(dm, "TSDiscGrad_Xdot", Xdot);CHKERRQ(ierr);}
3940be0ff1SMatthew G. Knepley     else                    {*Xdot = dg->Xdot;}
4040be0ff1SMatthew G. Knepley   }
4140be0ff1SMatthew G. Knepley   PetscFunctionReturn(0);
4240be0ff1SMatthew G. Knepley }
4340be0ff1SMatthew G. Knepley 
4440be0ff1SMatthew G. Knepley static PetscErrorCode TSDiscGradRestoreX0AndXdot(TS ts, DM dm, Vec *X0, Vec *Xdot)
4540be0ff1SMatthew G. Knepley {
4640be0ff1SMatthew G. Knepley   PetscErrorCode ierr;
4740be0ff1SMatthew G. Knepley 
4840be0ff1SMatthew G. Knepley   PetscFunctionBegin;
4940be0ff1SMatthew G. Knepley   if (X0) {
5040be0ff1SMatthew G. Knepley     if (dm && dm != ts->dm) {ierr = DMRestoreNamedGlobalVector(dm, "TSDiscGrad_X0", X0);CHKERRQ(ierr);}
5140be0ff1SMatthew G. Knepley   }
5240be0ff1SMatthew G. Knepley   if (Xdot) {
5340be0ff1SMatthew G. Knepley     if (dm && dm != ts->dm) {ierr = DMRestoreNamedGlobalVector(dm, "TSDiscGrad_Xdot", Xdot);CHKERRQ(ierr);}
5440be0ff1SMatthew G. Knepley   }
5540be0ff1SMatthew G. Knepley   PetscFunctionReturn(0);
5640be0ff1SMatthew G. Knepley }
5740be0ff1SMatthew G. Knepley 
5840be0ff1SMatthew G. Knepley static PetscErrorCode DMCoarsenHook_TSDiscGrad(DM fine, DM coarse, void *ctx)
5940be0ff1SMatthew G. Knepley {
6040be0ff1SMatthew G. Knepley   PetscFunctionBegin;
6140be0ff1SMatthew G. Knepley   PetscFunctionReturn(0);
6240be0ff1SMatthew G. Knepley }
6340be0ff1SMatthew G. Knepley 
6440be0ff1SMatthew G. Knepley static PetscErrorCode DMRestrictHook_TSDiscGrad(DM fine, Mat restrct, Vec rscale, Mat inject, DM coarse, void *ctx)
6540be0ff1SMatthew G. Knepley {
6640be0ff1SMatthew G. Knepley   TS             ts = (TS) ctx;
6740be0ff1SMatthew G. Knepley   Vec            X0, Xdot, X0_c, Xdot_c;
6840be0ff1SMatthew G. Knepley   PetscErrorCode ierr;
6940be0ff1SMatthew G. Knepley 
7040be0ff1SMatthew G. Knepley   PetscFunctionBegin;
7140be0ff1SMatthew G. Knepley   ierr = TSDiscGradGetX0AndXdot(ts, fine, &X0, &Xdot);CHKERRQ(ierr);
7240be0ff1SMatthew G. Knepley   ierr = TSDiscGradGetX0AndXdot(ts, coarse, &X0_c, &Xdot_c);CHKERRQ(ierr);
7340be0ff1SMatthew G. Knepley   ierr = MatRestrict(restrct, X0, X0_c);CHKERRQ(ierr);
7440be0ff1SMatthew G. Knepley   ierr = MatRestrict(restrct, Xdot, Xdot_c);CHKERRQ(ierr);
7540be0ff1SMatthew G. Knepley   ierr = VecPointwiseMult(X0_c, rscale, X0_c);CHKERRQ(ierr);
7640be0ff1SMatthew G. Knepley   ierr = VecPointwiseMult(Xdot_c, rscale, Xdot_c);CHKERRQ(ierr);
7740be0ff1SMatthew G. Knepley   ierr = TSDiscGradRestoreX0AndXdot(ts, fine, &X0, &Xdot);CHKERRQ(ierr);
7840be0ff1SMatthew G. Knepley   ierr = TSDiscGradRestoreX0AndXdot(ts, coarse, &X0_c, &Xdot_c);CHKERRQ(ierr);
7940be0ff1SMatthew G. Knepley   PetscFunctionReturn(0);
8040be0ff1SMatthew G. Knepley }
8140be0ff1SMatthew G. Knepley 
8240be0ff1SMatthew G. Knepley static PetscErrorCode DMSubDomainHook_TSDiscGrad(DM dm, DM subdm, void *ctx)
8340be0ff1SMatthew G. Knepley {
8440be0ff1SMatthew G. Knepley   PetscFunctionBegin;
8540be0ff1SMatthew G. Knepley   PetscFunctionReturn(0);
8640be0ff1SMatthew G. Knepley }
8740be0ff1SMatthew G. Knepley 
8840be0ff1SMatthew G. Knepley static PetscErrorCode DMSubDomainRestrictHook_TSDiscGrad(DM dm, VecScatter gscat, VecScatter lscat, DM subdm, void *ctx)
8940be0ff1SMatthew G. Knepley {
9040be0ff1SMatthew G. Knepley   TS             ts = (TS) ctx;
9140be0ff1SMatthew G. Knepley   Vec            X0, Xdot, X0_sub, Xdot_sub;
9240be0ff1SMatthew G. Knepley   PetscErrorCode ierr;
9340be0ff1SMatthew G. Knepley 
9440be0ff1SMatthew G. Knepley   PetscFunctionBegin;
9540be0ff1SMatthew G. Knepley   ierr = TSDiscGradGetX0AndXdot(ts, dm, &X0, &Xdot);CHKERRQ(ierr);
9640be0ff1SMatthew G. Knepley   ierr = TSDiscGradGetX0AndXdot(ts, subdm, &X0_sub, &Xdot_sub);CHKERRQ(ierr);
9740be0ff1SMatthew G. Knepley 
9840be0ff1SMatthew G. Knepley   ierr = VecScatterBegin(gscat, X0, X0_sub, INSERT_VALUES, SCATTER_FORWARD);CHKERRQ(ierr);
9940be0ff1SMatthew G. Knepley   ierr = VecScatterEnd(gscat, X0, X0_sub, INSERT_VALUES, SCATTER_FORWARD);CHKERRQ(ierr);
10040be0ff1SMatthew G. Knepley 
10140be0ff1SMatthew G. Knepley   ierr = VecScatterBegin(gscat, Xdot, Xdot_sub, INSERT_VALUES, SCATTER_FORWARD);CHKERRQ(ierr);
10240be0ff1SMatthew G. Knepley   ierr = VecScatterEnd(gscat, Xdot, Xdot_sub, INSERT_VALUES, SCATTER_FORWARD);CHKERRQ(ierr);
10340be0ff1SMatthew G. Knepley 
10440be0ff1SMatthew G. Knepley   ierr = TSDiscGradRestoreX0AndXdot(ts, dm, &X0, &Xdot);CHKERRQ(ierr);
10540be0ff1SMatthew G. Knepley   ierr = TSDiscGradRestoreX0AndXdot(ts, subdm, &X0_sub, &Xdot_sub);CHKERRQ(ierr);
10640be0ff1SMatthew G. Knepley   PetscFunctionReturn(0);
10740be0ff1SMatthew G. Knepley }
10840be0ff1SMatthew G. Knepley 
10940be0ff1SMatthew G. Knepley static PetscErrorCode TSSetUp_DiscGrad(TS ts)
11040be0ff1SMatthew G. Knepley {
11140be0ff1SMatthew G. Knepley   TS_DiscGrad   *dg = (TS_DiscGrad *) ts->data;
11240be0ff1SMatthew G. Knepley   DM             dm;
11340be0ff1SMatthew G. Knepley   PetscErrorCode ierr;
11440be0ff1SMatthew G. Knepley 
11540be0ff1SMatthew G. Knepley   PetscFunctionBegin;
11640be0ff1SMatthew G. Knepley   if (!dg->X)    {ierr = VecDuplicate(ts->vec_sol, &dg->X);CHKERRQ(ierr);}
11740be0ff1SMatthew G. Knepley   if (!dg->X0)   {ierr = VecDuplicate(ts->vec_sol, &dg->X0);CHKERRQ(ierr);}
11840be0ff1SMatthew G. Knepley   if (!dg->Xdot) {ierr = VecDuplicate(ts->vec_sol, &dg->Xdot);CHKERRQ(ierr);}
11940be0ff1SMatthew G. Knepley 
12040be0ff1SMatthew G. Knepley   ierr = TSGetDM(ts, &dm);CHKERRQ(ierr);
12140be0ff1SMatthew G. Knepley   ierr = DMCoarsenHookAdd(dm, DMCoarsenHook_TSDiscGrad, DMRestrictHook_TSDiscGrad, ts);CHKERRQ(ierr);
12240be0ff1SMatthew G. Knepley   ierr = DMSubDomainHookAdd(dm, DMSubDomainHook_TSDiscGrad, DMSubDomainRestrictHook_TSDiscGrad, ts);CHKERRQ(ierr);
12340be0ff1SMatthew G. Knepley   PetscFunctionReturn(0);
12440be0ff1SMatthew G. Knepley }
12540be0ff1SMatthew G. Knepley 
12640be0ff1SMatthew G. Knepley static PetscErrorCode TSSetFromOptions_DiscGrad(PetscOptionItems *PetscOptionsObject, TS ts)
12740be0ff1SMatthew G. Knepley {
128*db4653c2SDaniel Finn   TS_DiscGrad   *dg = (TS_DiscGrad *) ts->data;
12940be0ff1SMatthew G. Knepley   PetscErrorCode ierr;
13040be0ff1SMatthew G. Knepley 
13140be0ff1SMatthew G. Knepley   PetscFunctionBegin;
13240be0ff1SMatthew G. Knepley   ierr = PetscOptionsHead(PetscOptionsObject, "Discrete Gradients ODE solver options");CHKERRQ(ierr);
13340be0ff1SMatthew G. Knepley   {
134*db4653c2SDaniel Finn     ierr = PetscOptionsBool("-ts_discgrad_gonzalez","Use Gonzalez term in discrete gradients formulation","TSDiscGradUseGonzalez",dg->gonzalez,&dg->gonzalez,NULL);CHKERRQ(ierr);
13540be0ff1SMatthew G. Knepley   }
13640be0ff1SMatthew G. Knepley   ierr = PetscOptionsTail();CHKERRQ(ierr);
13740be0ff1SMatthew G. Knepley   PetscFunctionReturn(0);
13840be0ff1SMatthew G. Knepley }
13940be0ff1SMatthew G. Knepley 
14040be0ff1SMatthew G. Knepley static PetscErrorCode TSView_DiscGrad(TS ts,PetscViewer viewer)
14140be0ff1SMatthew G. Knepley {
14240be0ff1SMatthew G. Knepley   PetscBool      iascii;
14340be0ff1SMatthew G. Knepley   PetscErrorCode ierr;
14440be0ff1SMatthew G. Knepley 
14540be0ff1SMatthew G. Knepley   PetscFunctionBegin;
14640be0ff1SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
14740be0ff1SMatthew G. Knepley   if (iascii) {
14840be0ff1SMatthew G. Knepley     ierr = PetscViewerASCIIPrintf(viewer,"  Discrete Gradients\n");CHKERRQ(ierr);
14940be0ff1SMatthew G. Knepley   }
15040be0ff1SMatthew G. Knepley   PetscFunctionReturn(0);
15140be0ff1SMatthew G. Knepley }
15240be0ff1SMatthew G. Knepley 
153*db4653c2SDaniel Finn static PetscErrorCode TSDiscGradIsGonzalez_DiscGrad(TS ts,PetscBool *gonzalez)
154*db4653c2SDaniel Finn {
155*db4653c2SDaniel Finn   TS_DiscGrad *dg = (TS_DiscGrad*)ts->data;
156*db4653c2SDaniel Finn 
157*db4653c2SDaniel Finn   PetscFunctionBegin;
158*db4653c2SDaniel Finn   *gonzalez = dg->gonzalez;
159*db4653c2SDaniel Finn   PetscFunctionReturn(0);
160*db4653c2SDaniel Finn }
161*db4653c2SDaniel Finn 
162*db4653c2SDaniel Finn static PetscErrorCode TSDiscGradUseGonzalez_DiscGrad(TS ts,PetscBool flg)
163*db4653c2SDaniel Finn {
164*db4653c2SDaniel Finn   TS_DiscGrad *dg = (TS_DiscGrad*)ts->data;
165*db4653c2SDaniel Finn 
166*db4653c2SDaniel Finn   PetscFunctionBegin;
167*db4653c2SDaniel Finn   dg->gonzalez = flg;
168*db4653c2SDaniel Finn   PetscFunctionReturn(0);
169*db4653c2SDaniel Finn }
170*db4653c2SDaniel Finn 
17140be0ff1SMatthew G. Knepley static PetscErrorCode TSReset_DiscGrad(TS ts)
17240be0ff1SMatthew G. Knepley {
17340be0ff1SMatthew G. Knepley   TS_DiscGrad   *dg = (TS_DiscGrad *) ts->data;
17440be0ff1SMatthew G. Knepley   PetscErrorCode ierr;
17540be0ff1SMatthew G. Knepley 
17640be0ff1SMatthew G. Knepley   PetscFunctionBegin;
17740be0ff1SMatthew G. Knepley   ierr = VecDestroy(&dg->X);CHKERRQ(ierr);
17840be0ff1SMatthew G. Knepley   ierr = VecDestroy(&dg->X0);CHKERRQ(ierr);
17940be0ff1SMatthew G. Knepley   ierr = VecDestroy(&dg->Xdot);CHKERRQ(ierr);
18040be0ff1SMatthew G. Knepley   PetscFunctionReturn(0);
18140be0ff1SMatthew G. Knepley }
18240be0ff1SMatthew G. Knepley 
18340be0ff1SMatthew G. Knepley static PetscErrorCode TSDestroy_DiscGrad(TS ts)
18440be0ff1SMatthew G. Knepley {
18540be0ff1SMatthew G. Knepley   DM             dm;
18640be0ff1SMatthew G. Knepley   PetscErrorCode ierr;
18740be0ff1SMatthew G. Knepley 
18840be0ff1SMatthew G. Knepley   PetscFunctionBegin;
18940be0ff1SMatthew G. Knepley   ierr = TSReset_DiscGrad(ts);CHKERRQ(ierr);
19040be0ff1SMatthew G. Knepley   ierr = TSGetDM(ts, &dm);CHKERRQ(ierr);
19140be0ff1SMatthew G. Knepley   if (dm) {
19240be0ff1SMatthew G. Knepley     ierr = DMCoarsenHookRemove(dm, DMCoarsenHook_TSDiscGrad, DMRestrictHook_TSDiscGrad, ts);CHKERRQ(ierr);
19340be0ff1SMatthew G. Knepley     ierr = DMSubDomainHookRemove(dm, DMSubDomainHook_TSDiscGrad, DMSubDomainRestrictHook_TSDiscGrad, ts);CHKERRQ(ierr);
19440be0ff1SMatthew G. Knepley   }
19540be0ff1SMatthew G. Knepley   ierr = PetscFree(ts->data);CHKERRQ(ierr);
19640be0ff1SMatthew G. Knepley   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSDiscGradGetFormulation_C",NULL);CHKERRQ(ierr);
19740be0ff1SMatthew G. Knepley   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSDiscGradSetFormulation_C",NULL);CHKERRQ(ierr);
19840be0ff1SMatthew G. Knepley   PetscFunctionReturn(0);
19940be0ff1SMatthew G. Knepley }
20040be0ff1SMatthew G. Knepley 
20140be0ff1SMatthew G. Knepley static PetscErrorCode TSInterpolate_DiscGrad(TS ts, PetscReal t, Vec X)
20240be0ff1SMatthew G. Knepley {
20340be0ff1SMatthew G. Knepley   TS_DiscGrad   *dg = (TS_DiscGrad*)ts->data;
20440be0ff1SMatthew G. Knepley   PetscReal      dt = t - ts->ptime;
20540be0ff1SMatthew G. Knepley   PetscErrorCode ierr;
20640be0ff1SMatthew G. Knepley 
20740be0ff1SMatthew G. Knepley   PetscFunctionBegin;
20840be0ff1SMatthew G. Knepley   ierr = VecCopy(ts->vec_sol, dg->X);CHKERRQ(ierr);
20940be0ff1SMatthew G. Knepley   ierr = VecWAXPY(X, dt, dg->Xdot, dg->X);CHKERRQ(ierr);
21040be0ff1SMatthew G. Knepley   PetscFunctionReturn(0);
21140be0ff1SMatthew G. Knepley }
21240be0ff1SMatthew G. Knepley 
21340be0ff1SMatthew G. Knepley static PetscErrorCode TSDiscGrad_SNESSolve(TS ts, Vec b, Vec x)
21440be0ff1SMatthew G. Knepley {
21540be0ff1SMatthew G. Knepley   SNES           snes;
21640be0ff1SMatthew G. Knepley   PetscInt       nits, lits;
21740be0ff1SMatthew G. Knepley   PetscErrorCode ierr;
21840be0ff1SMatthew G. Knepley 
21940be0ff1SMatthew G. Knepley   PetscFunctionBegin;
22040be0ff1SMatthew G. Knepley   ierr = TSGetSNES(ts, &snes);CHKERRQ(ierr);
22140be0ff1SMatthew G. Knepley   ierr = SNESSolve(snes, b, x);CHKERRQ(ierr);
22240be0ff1SMatthew G. Knepley   ierr = SNESGetIterationNumber(snes, &nits);CHKERRQ(ierr);
22340be0ff1SMatthew G. Knepley   ierr = SNESGetLinearSolveIterations(snes, &lits);CHKERRQ(ierr);
22440be0ff1SMatthew G. Knepley   ts->snes_its += nits;
22540be0ff1SMatthew G. Knepley   ts->ksp_its  += lits;
22640be0ff1SMatthew G. Knepley   PetscFunctionReturn(0);
22740be0ff1SMatthew G. Knepley }
22840be0ff1SMatthew G. Knepley 
22940be0ff1SMatthew G. Knepley static PetscErrorCode TSStep_DiscGrad(TS ts)
23040be0ff1SMatthew G. Knepley {
23140be0ff1SMatthew G. Knepley   TS_DiscGrad   *dg = (TS_DiscGrad *) ts->data;
23240be0ff1SMatthew G. Knepley   TSAdapt        adapt;
23340be0ff1SMatthew G. Knepley   TSStepStatus   status          = TS_STEP_INCOMPLETE;
23440be0ff1SMatthew G. Knepley   PetscInt       rejections      = 0;
23540be0ff1SMatthew G. Knepley   PetscBool      stageok, accept = PETSC_TRUE;
23640be0ff1SMatthew G. Knepley   PetscReal      next_time_step  = ts->time_step;
23740be0ff1SMatthew G. Knepley   PetscErrorCode ierr;
23840be0ff1SMatthew G. Knepley 
23940be0ff1SMatthew G. Knepley   PetscFunctionBegin;
24040be0ff1SMatthew G. Knepley   ierr = TSGetAdapt(ts, &adapt);CHKERRQ(ierr);
24140be0ff1SMatthew G. Knepley   if (!ts->steprollback) {ierr = VecCopy(ts->vec_sol, dg->X0);CHKERRQ(ierr);}
24240be0ff1SMatthew G. Knepley 
24340be0ff1SMatthew G. Knepley   while (!ts->reason && status != TS_STEP_COMPLETE) {
24440be0ff1SMatthew G. Knepley     PetscReal shift = 1/(0.5*ts->time_step);
24540be0ff1SMatthew G. Knepley 
24640be0ff1SMatthew G. Knepley     dg->stage_time = ts->ptime + 0.5*ts->time_step;
24740be0ff1SMatthew G. Knepley 
24840be0ff1SMatthew G. Knepley     ierr = VecCopy(dg->X0, dg->X);CHKERRQ(ierr);
24940be0ff1SMatthew G. Knepley     ierr = TSPreStage(ts, dg->stage_time);CHKERRQ(ierr);
25040be0ff1SMatthew G. Knepley     ierr = TSDiscGrad_SNESSolve(ts, NULL, dg->X);CHKERRQ(ierr);
25140be0ff1SMatthew G. Knepley     ierr = TSPostStage(ts, dg->stage_time, 0, &dg->X);CHKERRQ(ierr);
25240be0ff1SMatthew G. Knepley     ierr = TSAdaptCheckStage(adapt, ts, dg->stage_time, dg->X, &stageok);CHKERRQ(ierr);
25340be0ff1SMatthew G. Knepley     if (!stageok) goto reject_step;
25440be0ff1SMatthew G. Knepley 
25540be0ff1SMatthew G. Knepley     status = TS_STEP_PENDING;
25640be0ff1SMatthew G. Knepley     ierr = VecAXPBYPCZ(dg->Xdot, -shift, shift, 0, dg->X0, dg->X);CHKERRQ(ierr);
25740be0ff1SMatthew G. Knepley     ierr = VecAXPY(ts->vec_sol, ts->time_step, dg->Xdot);CHKERRQ(ierr);
25840be0ff1SMatthew G. Knepley     ierr = TSAdaptChoose(adapt, ts, ts->time_step, NULL, &next_time_step, &accept);CHKERRQ(ierr);
25940be0ff1SMatthew G. Knepley     status = accept ? TS_STEP_COMPLETE : TS_STEP_INCOMPLETE;
26040be0ff1SMatthew G. Knepley     if (!accept) {
26140be0ff1SMatthew G. Knepley       ierr = VecCopy(dg->X0, ts->vec_sol);CHKERRQ(ierr);
26240be0ff1SMatthew G. Knepley       ts->time_step = next_time_step;
26340be0ff1SMatthew G. Knepley       goto reject_step;
26440be0ff1SMatthew G. Knepley     }
26540be0ff1SMatthew G. Knepley     ts->ptime    += ts->time_step;
26640be0ff1SMatthew G. Knepley     ts->time_step = next_time_step;
26740be0ff1SMatthew G. Knepley     break;
26840be0ff1SMatthew G. Knepley 
26940be0ff1SMatthew G. Knepley   reject_step:
27040be0ff1SMatthew G. Knepley     ts->reject++; accept = PETSC_FALSE;
27140be0ff1SMatthew G. Knepley     if (!ts->reason && ts->max_reject >= 0 && ++rejections > ts->max_reject) {
27240be0ff1SMatthew G. Knepley       ts->reason = TS_DIVERGED_STEP_REJECTED;
27340be0ff1SMatthew G. Knepley       ierr = PetscInfo2(ts, "Step=%D, step rejections %D greater than current TS allowed, stopping solve\n", ts->steps, rejections);CHKERRQ(ierr);
27440be0ff1SMatthew G. Knepley     }
27540be0ff1SMatthew G. Knepley   }
27640be0ff1SMatthew G. Knepley   PetscFunctionReturn(0);
27740be0ff1SMatthew G. Knepley }
27840be0ff1SMatthew G. Knepley 
27940be0ff1SMatthew G. Knepley static PetscErrorCode TSGetStages_DiscGrad(TS ts, PetscInt *ns, Vec **Y)
28040be0ff1SMatthew G. Knepley {
28140be0ff1SMatthew G. Knepley   TS_DiscGrad *dg = (TS_DiscGrad *) ts->data;
28240be0ff1SMatthew G. Knepley 
28340be0ff1SMatthew G. Knepley   PetscFunctionBegin;
28440be0ff1SMatthew G. Knepley   if (ns) *ns = 1;
28540be0ff1SMatthew G. Knepley   if (Y)  *Y  = &(dg->X);
28640be0ff1SMatthew G. Knepley   PetscFunctionReturn(0);
28740be0ff1SMatthew G. Knepley }
28840be0ff1SMatthew G. Knepley 
28940be0ff1SMatthew G. Knepley /*
29040be0ff1SMatthew G. Knepley   This defines the nonlinear equation that is to be solved with SNES
29140be0ff1SMatthew G. Knepley     G(U) = F[t0 + 0.5*dt, U, (U-U0)/dt] = 0
29240be0ff1SMatthew G. Knepley */
293*db4653c2SDaniel Finn 
294*db4653c2SDaniel Finn /* x = (x+x')/2 */
295*db4653c2SDaniel Finn /* NEED TO CALCULATE x_{n+1} from x and x_{n}*/
29640be0ff1SMatthew G. Knepley static PetscErrorCode SNESTSFormFunction_DiscGrad(SNES snes, Vec x, Vec y, TS ts)
29740be0ff1SMatthew G. Knepley {
298*db4653c2SDaniel Finn 
29940be0ff1SMatthew G. Knepley   TS_DiscGrad   *dg    = (TS_DiscGrad *) ts->data;
300*db4653c2SDaniel Finn   PetscReal      norm, shift = 1/(0.5*ts->time_step);
301*db4653c2SDaniel Finn   PetscInt       n;
302*db4653c2SDaniel Finn   Vec            X0, Xdot, Xp, Xdiff;
303*db4653c2SDaniel Finn   Mat            S;
304*db4653c2SDaniel Finn   PetscScalar    F=0, F0=0, Gp;
305*db4653c2SDaniel Finn   Vec            G, SgF;
30640be0ff1SMatthew G. Knepley   DM             dm, dmsave;
30740be0ff1SMatthew G. Knepley   PetscErrorCode ierr;
30840be0ff1SMatthew G. Knepley 
30940be0ff1SMatthew G. Knepley   PetscFunctionBegin;
31040be0ff1SMatthew G. Knepley   ierr = SNESGetDM(snes, &dm);CHKERRQ(ierr);
31140be0ff1SMatthew G. Knepley 
312*db4653c2SDaniel Finn   ierr = VecDuplicate(y, &Xp);CHKERRQ(ierr);
313*db4653c2SDaniel Finn   ierr = VecDuplicate(y, &Xdiff);CHKERRQ(ierr);
314*db4653c2SDaniel Finn   ierr = VecDuplicate(y, &SgF);CHKERRQ(ierr);
315*db4653c2SDaniel Finn   ierr = VecDuplicate(y, &G);CHKERRQ(ierr);
316*db4653c2SDaniel Finn 
317*db4653c2SDaniel Finn   ierr = VecGetLocalSize(y, &n);CHKERRQ(ierr);
318*db4653c2SDaniel Finn   ierr = MatCreate(PETSC_COMM_WORLD, &S);CHKERRQ(ierr);
319*db4653c2SDaniel Finn   ierr = MatSetSizes(S, PETSC_DECIDE, PETSC_DECIDE, n, n);CHKERRQ(ierr);
320*db4653c2SDaniel Finn   ierr = MatSetFromOptions(S);CHKERRQ(ierr);
321*db4653c2SDaniel Finn   ierr = MatSetUp(S);CHKERRQ(ierr);
322*db4653c2SDaniel Finn   ierr = MatAssemblyBegin(S,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
323*db4653c2SDaniel Finn   ierr = MatAssemblyEnd(S,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
324*db4653c2SDaniel Finn 
325*db4653c2SDaniel Finn   ierr = TSDiscGradGetX0AndXdot(ts, dm, &X0, &Xdot);CHKERRQ(ierr);
326*db4653c2SDaniel Finn   ierr = VecAXPBYPCZ(Xdot, -shift, shift, 0, X0, x);CHKERRQ(ierr); /* Xdot = shift (x - X0) */
327*db4653c2SDaniel Finn 
328*db4653c2SDaniel Finn   ierr = VecAXPBYPCZ(Xp, -1, 2, 0, X0, x);CHKERRQ(ierr); /* Xp = 2*x - X0 + (0)*Xmid */
329*db4653c2SDaniel Finn   ierr = VecAXPBYPCZ(Xdiff, -1, 1, 0, X0, Xp);CHKERRQ(ierr); /* Xdiff = xp - X0 + (0)*Xdiff */
330*db4653c2SDaniel Finn 
331*db4653c2SDaniel Finn   if (dg->gonzalez) {
332*db4653c2SDaniel Finn     ierr = (*dg->Sfunc)(ts, dg->stage_time, x ,   S,  dg->funcCtx);CHKERRQ(ierr);
333*db4653c2SDaniel Finn     ierr = (*dg->Ffunc)(ts, dg->stage_time, Xp,  &F,  dg->funcCtx);CHKERRQ(ierr);
334*db4653c2SDaniel Finn     ierr = (*dg->Ffunc)(ts, dg->stage_time, X0,  &F0, dg->funcCtx);CHKERRQ(ierr);
335*db4653c2SDaniel Finn     ierr = (*dg->Gfunc)(ts, dg->stage_time, x ,   G,  dg->funcCtx);CHKERRQ(ierr);
336*db4653c2SDaniel Finn 
337*db4653c2SDaniel Finn     /* Adding Extra Gonzalez Term */
338*db4653c2SDaniel Finn     ierr = VecDot(Xdiff, G, &Gp);CHKERRQ(ierr);
339*db4653c2SDaniel Finn     ierr = VecNorm(Xdiff, NORM_2, &norm);CHKERRQ(ierr);
340*db4653c2SDaniel Finn     if (norm < PETSC_SQRT_MACHINE_EPSILON) {
341*db4653c2SDaniel Finn       Gp = 0;
342*db4653c2SDaniel Finn     } else {
343*db4653c2SDaniel Finn       /* Gp = (1/|xn+1 - xn|^2) * (F(xn+1) - F(xn) - Gp) */
344*db4653c2SDaniel Finn       Gp = (F - F0 - Gp)/PetscSqr(norm);
345*db4653c2SDaniel Finn     }
346*db4653c2SDaniel Finn     ierr = VecAXPY(G, Gp, Xdiff);CHKERRQ(ierr);
347*db4653c2SDaniel Finn     ierr = MatMult(S, G , SgF);CHKERRQ(ierr); /* S*gradF */
348*db4653c2SDaniel Finn 
349*db4653c2SDaniel Finn   } else {
350*db4653c2SDaniel Finn     ierr = (*dg->Sfunc)(ts, dg->stage_time, x, S,  dg->funcCtx);CHKERRQ(ierr);
351*db4653c2SDaniel Finn     ierr = (*dg->Gfunc)(ts, dg->stage_time, x, G,  dg->funcCtx);CHKERRQ(ierr);
352*db4653c2SDaniel Finn 
353*db4653c2SDaniel Finn     ierr = MatMult(S, G , SgF);CHKERRQ(ierr); /* Xdot = S*gradF */
354*db4653c2SDaniel Finn   }
35540be0ff1SMatthew G. Knepley   /* DM monkey-business allows user code to call TSGetDM() inside of functions evaluated on levels of FAS */
35640be0ff1SMatthew G. Knepley   dmsave = ts->dm;
35740be0ff1SMatthew G. Knepley   ts->dm = dm;
358*db4653c2SDaniel Finn   ierr = VecAXPBYPCZ(y, 1, -1, 0, Xdot, SgF);CHKERRQ(ierr);
35940be0ff1SMatthew G. Knepley   ts->dm = dmsave;
36040be0ff1SMatthew G. Knepley   ierr   = TSDiscGradRestoreX0AndXdot(ts, dm, &X0, &Xdot);CHKERRQ(ierr);
361*db4653c2SDaniel Finn 
362*db4653c2SDaniel Finn   ierr = VecDestroy(&Xp);CHKERRQ(ierr);
363*db4653c2SDaniel Finn   ierr = VecDestroy(&Xdiff);CHKERRQ(ierr);
364*db4653c2SDaniel Finn   ierr = VecDestroy(&SgF);CHKERRQ(ierr);
365*db4653c2SDaniel Finn   ierr = VecDestroy(&G);CHKERRQ(ierr);
366*db4653c2SDaniel Finn   ierr = MatDestroy(&S);CHKERRQ(ierr);
367*db4653c2SDaniel Finn 
36840be0ff1SMatthew G. Knepley   PetscFunctionReturn(0);
36940be0ff1SMatthew G. Knepley }
37040be0ff1SMatthew G. Knepley 
37140be0ff1SMatthew G. Knepley static PetscErrorCode SNESTSFormJacobian_DiscGrad(SNES snes, Vec x, Mat A, Mat B, TS ts)
37240be0ff1SMatthew G. Knepley {
37340be0ff1SMatthew G. Knepley   TS_DiscGrad   *dg    = (TS_DiscGrad *) ts->data;
37440be0ff1SMatthew G. Knepley   PetscReal      shift = 1/(0.5*ts->time_step);
37540be0ff1SMatthew G. Knepley   Vec            Xdot;
37640be0ff1SMatthew G. Knepley   DM             dm,dmsave;
37740be0ff1SMatthew G. Knepley   PetscErrorCode ierr;
37840be0ff1SMatthew G. Knepley 
37940be0ff1SMatthew G. Knepley   PetscFunctionBegin;
38040be0ff1SMatthew G. Knepley   ierr = SNESGetDM(snes, &dm);CHKERRQ(ierr);
38140be0ff1SMatthew G. Knepley   /* Xdot has already been computed in SNESTSFormFunction_DiscGrad (SNES guarantees this) */
38240be0ff1SMatthew G. Knepley   ierr = TSDiscGradGetX0AndXdot(ts, dm, NULL, &Xdot);CHKERRQ(ierr);
38340be0ff1SMatthew G. Knepley 
38440be0ff1SMatthew G. Knepley   dmsave = ts->dm;
38540be0ff1SMatthew G. Knepley   ts->dm = dm;
38640be0ff1SMatthew G. Knepley   ierr   = TSComputeIJacobian(ts, dg->stage_time, x, Xdot, shift, A, B, PETSC_FALSE);CHKERRQ(ierr);
38740be0ff1SMatthew G. Knepley   ts->dm = dmsave;
38840be0ff1SMatthew G. Knepley   ierr   = TSDiscGradRestoreX0AndXdot(ts, dm, NULL, &Xdot);CHKERRQ(ierr);
38940be0ff1SMatthew G. Knepley   PetscFunctionReturn(0);
39040be0ff1SMatthew G. Knepley }
39140be0ff1SMatthew G. Knepley 
392*db4653c2SDaniel Finn 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)
39340be0ff1SMatthew G. Knepley {
39440be0ff1SMatthew G. Knepley   TS_DiscGrad *dg = (TS_DiscGrad *) ts->data;
39540be0ff1SMatthew G. Knepley 
39640be0ff1SMatthew G. Knepley   PetscFunctionBegin;
39740be0ff1SMatthew G. Knepley   *Sfunc = dg->Sfunc;
39840be0ff1SMatthew G. Knepley   *Ffunc = dg->Ffunc;
39940be0ff1SMatthew G. Knepley   *Gfunc = dg->Gfunc;
40040be0ff1SMatthew G. Knepley   PetscFunctionReturn(0);
40140be0ff1SMatthew G. Knepley }
40240be0ff1SMatthew G. Knepley 
403*db4653c2SDaniel Finn 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)
40440be0ff1SMatthew G. Knepley {
40540be0ff1SMatthew G. Knepley   TS_DiscGrad *dg = (TS_DiscGrad *) ts->data;
40640be0ff1SMatthew G. Knepley 
40740be0ff1SMatthew G. Knepley   PetscFunctionBegin;
40840be0ff1SMatthew G. Knepley   dg->Sfunc = Sfunc;
40940be0ff1SMatthew G. Knepley   dg->Ffunc = Ffunc;
41040be0ff1SMatthew G. Knepley   dg->Gfunc = Gfunc;
411*db4653c2SDaniel Finn   dg->funcCtx = ctx;
41240be0ff1SMatthew G. Knepley   PetscFunctionReturn(0);
41340be0ff1SMatthew G. Knepley }
41440be0ff1SMatthew G. Knepley 
41540be0ff1SMatthew G. Knepley /*MC
41640be0ff1SMatthew G. Knepley   TSDISCGRAD - ODE solver using the discrete gradients version of the implicit midpoint method
41740be0ff1SMatthew G. Knepley 
4182ceb51e8SPatrick Sanan   Notes:
4192ceb51e8SPatrick Sanan   This is the implicit midpoint rule, with an optional term that guarantees the discrete gradient property. This
42040be0ff1SMatthew G. Knepley   timestepper applies to systems of the form
42140be0ff1SMatthew G. Knepley $ u_t = S(u) grad F(u)
42240be0ff1SMatthew G. Knepley   where S(u) is a linear operator, and F is a functional of u.
42340be0ff1SMatthew G. Knepley 
424*db4653c2SDaniel Finn .seealso: TSCreate(), TSSetType(), TS, TSDISCGRAD, TSDiscGradSetFormulation()
42540be0ff1SMatthew G. Knepley M*/
42640be0ff1SMatthew G. Knepley PETSC_EXTERN PetscErrorCode TSCreate_DiscGrad(TS ts)
42740be0ff1SMatthew G. Knepley {
42840be0ff1SMatthew G. Knepley   TS_DiscGrad       *th;
42940be0ff1SMatthew G. Knepley   PetscErrorCode     ierr;
43040be0ff1SMatthew G. Knepley 
43140be0ff1SMatthew G. Knepley   PetscFunctionBegin;
43240be0ff1SMatthew G. Knepley   ierr = PetscCitationsRegister(DGCitation, &DGCite);CHKERRQ(ierr);
43340be0ff1SMatthew G. Knepley   ts->ops->reset           = TSReset_DiscGrad;
43440be0ff1SMatthew G. Knepley   ts->ops->destroy         = TSDestroy_DiscGrad;
43540be0ff1SMatthew G. Knepley   ts->ops->view            = TSView_DiscGrad;
43640be0ff1SMatthew G. Knepley   ts->ops->setfromoptions  = TSSetFromOptions_DiscGrad;
43740be0ff1SMatthew G. Knepley   ts->ops->setup           = TSSetUp_DiscGrad;
43840be0ff1SMatthew G. Knepley   ts->ops->step            = TSStep_DiscGrad;
43940be0ff1SMatthew G. Knepley   ts->ops->interpolate     = TSInterpolate_DiscGrad;
44040be0ff1SMatthew G. Knepley   ts->ops->getstages       = TSGetStages_DiscGrad;
44140be0ff1SMatthew G. Knepley   ts->ops->snesfunction    = SNESTSFormFunction_DiscGrad;
44240be0ff1SMatthew G. Knepley   ts->ops->snesjacobian    = SNESTSFormJacobian_DiscGrad;
44340be0ff1SMatthew G. Knepley   ts->default_adapt_type   = TSADAPTNONE;
44440be0ff1SMatthew G. Knepley 
44540be0ff1SMatthew G. Knepley   ts->usessnes = PETSC_TRUE;
44640be0ff1SMatthew G. Knepley 
44740be0ff1SMatthew G. Knepley   ierr = PetscNewLog(ts,&th);CHKERRQ(ierr);
44840be0ff1SMatthew G. Knepley   ts->data = (void*)th;
449*db4653c2SDaniel Finn 
450*db4653c2SDaniel Finn   th->gonzalez = PETSC_FALSE;
451*db4653c2SDaniel Finn 
45240be0ff1SMatthew G. Knepley   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSDiscGradGetFormulation_C",TSDiscGradGetFormulation_DiscGrad);CHKERRQ(ierr);
45340be0ff1SMatthew G. Knepley   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSDiscGradSetFormulation_C",TSDiscGradSetFormulation_DiscGrad);CHKERRQ(ierr);
454*db4653c2SDaniel Finn   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSDiscGradIsGonzalez_C",TSDiscGradIsGonzalez_DiscGrad);CHKERRQ(ierr);
455*db4653c2SDaniel Finn   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSDiscGradUseGonzalez_C",TSDiscGradUseGonzalez_DiscGrad);CHKERRQ(ierr);
45640be0ff1SMatthew G. Knepley   PetscFunctionReturn(0);
45740be0ff1SMatthew G. Knepley }
45840be0ff1SMatthew G. Knepley 
45940be0ff1SMatthew G. Knepley /*@C
46040be0ff1SMatthew G. Knepley   TSDiscGradGetFormulation - Get the construction method for S, F, and grad F from the formulation u_t = S grad F
46140be0ff1SMatthew G. Knepley 
46240be0ff1SMatthew G. Knepley   Not Collective
46340be0ff1SMatthew G. Knepley 
46440be0ff1SMatthew G. Knepley   Input Parameter:
46540be0ff1SMatthew G. Knepley . ts - timestepping context
46640be0ff1SMatthew G. Knepley 
46740be0ff1SMatthew G. Knepley   Output Parameters:
46840be0ff1SMatthew G. Knepley + Sfunc - constructor for the S matrix from the formulation
46940be0ff1SMatthew G. Knepley . Ffunc - functional F from the formulation
47040be0ff1SMatthew G. Knepley - Gfunc - constructor for the gradient of F from the formulation
47140be0ff1SMatthew G. Knepley 
47240be0ff1SMatthew G. Knepley   Calling sequence of Sfunc:
47340be0ff1SMatthew G. Knepley $ PetscErrorCode func(TS ts, PetscReal time, Vec u, Mat S, void *)
47440be0ff1SMatthew G. Knepley 
47540be0ff1SMatthew G. Knepley   Calling sequence of Ffunc:
47640be0ff1SMatthew G. Knepley $ PetscErrorCode func(TS ts, PetscReal time, Vec u, PetscScalar *F, void *)
47740be0ff1SMatthew G. Knepley 
47840be0ff1SMatthew G. Knepley   Calling sequence of Gfunc:
47940be0ff1SMatthew G. Knepley $ PetscErrorCode func(TS ts, PetscReal time, Vec u, Vec G, void *)
48040be0ff1SMatthew G. Knepley 
48140be0ff1SMatthew G. Knepley   Level: intermediate
48240be0ff1SMatthew G. Knepley 
48340be0ff1SMatthew G. Knepley .seealso: TSDiscGradSetFormulation()
48440be0ff1SMatthew G. Knepley @*/
485*db4653c2SDaniel Finn 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)
48640be0ff1SMatthew G. Knepley {
48740be0ff1SMatthew G. Knepley   PetscErrorCode ierr;
48840be0ff1SMatthew G. Knepley 
48940be0ff1SMatthew G. Knepley   PetscFunctionBegin;
49040be0ff1SMatthew G. Knepley   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
49140be0ff1SMatthew G. Knepley   PetscValidPointer(Sfunc, 2);
49240be0ff1SMatthew G. Knepley   PetscValidPointer(Ffunc, 3);
49340be0ff1SMatthew G. Knepley   PetscValidPointer(Gfunc, 4);
494*db4653c2SDaniel Finn   ierr = 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));CHKERRQ(ierr);
49540be0ff1SMatthew G. Knepley   PetscFunctionReturn(0);
49640be0ff1SMatthew G. Knepley }
49740be0ff1SMatthew G. Knepley 
49840be0ff1SMatthew G. Knepley /*@C
49940be0ff1SMatthew G. Knepley   TSDiscGradSetFormulation - Set the construction method for S, F, and grad F from the formulation u_t = S(u) grad F(u)
50040be0ff1SMatthew G. Knepley 
50140be0ff1SMatthew G. Knepley   Not Collective
50240be0ff1SMatthew G. Knepley 
50340be0ff1SMatthew G. Knepley   Input Parameters:
50440be0ff1SMatthew G. Knepley + ts    - timestepping context
50540be0ff1SMatthew G. Knepley . Sfunc - constructor for the S matrix from the formulation
50640be0ff1SMatthew G. Knepley . Ffunc - functional F from the formulation
50740be0ff1SMatthew G. Knepley - Gfunc - constructor for the gradient of F from the formulation
50840be0ff1SMatthew G. Knepley   Calling sequence of Sfunc:
50940be0ff1SMatthew G. Knepley $ PetscErrorCode func(TS ts, PetscReal time, Vec u, Mat S, void *)
51040be0ff1SMatthew G. Knepley 
51140be0ff1SMatthew G. Knepley   Calling sequence of Ffunc:
51240be0ff1SMatthew G. Knepley $ PetscErrorCode func(TS ts, PetscReal time, Vec u, PetscScalar *F, void *)
51340be0ff1SMatthew G. Knepley 
51440be0ff1SMatthew G. Knepley   Calling sequence of Gfunc:
51540be0ff1SMatthew G. Knepley $ PetscErrorCode func(TS ts, PetscReal time, Vec u, Vec G, void *)
51640be0ff1SMatthew G. Knepley 
51740be0ff1SMatthew G. Knepley   Level: Intermediate
51840be0ff1SMatthew G. Knepley 
51940be0ff1SMatthew G. Knepley .seealso: TSDiscGradGetFormulation()
52040be0ff1SMatthew G. Knepley @*/
52140be0ff1SMatthew G. Knepley 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)
52240be0ff1SMatthew G. Knepley {
52340be0ff1SMatthew G. Knepley   PetscErrorCode ierr;
52440be0ff1SMatthew G. Knepley 
52540be0ff1SMatthew G. Knepley   PetscFunctionBegin;
52640be0ff1SMatthew G. Knepley   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
52740be0ff1SMatthew G. Knepley   PetscValidFunction(Sfunc, 2);
52840be0ff1SMatthew G. Knepley   PetscValidFunction(Ffunc, 3);
52940be0ff1SMatthew G. Knepley   PetscValidFunction(Gfunc, 4);
530*db4653c2SDaniel Finn   ierr = 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));CHKERRQ(ierr);
531*db4653c2SDaniel Finn   PetscFunctionReturn(0);
532*db4653c2SDaniel Finn }
533*db4653c2SDaniel Finn 
534*db4653c2SDaniel Finn /*@
535*db4653c2SDaniel Finn   TSDiscGradIsGonzalez - Checks flag for whether to use additional conservative terms in discrete gradient formulation.
536*db4653c2SDaniel Finn 
537*db4653c2SDaniel Finn   Not Collective
538*db4653c2SDaniel Finn 
539*db4653c2SDaniel Finn   Input Parameter:
540*db4653c2SDaniel Finn .  ts - timestepping context
541*db4653c2SDaniel Finn 
542*db4653c2SDaniel Finn   Output Parameter:
543*db4653c2SDaniel Finn .  gonzalez - PETSC_TRUE when using the Gonzalez term
544*db4653c2SDaniel Finn 
545*db4653c2SDaniel Finn   Level: Advanced
546*db4653c2SDaniel Finn 
547*db4653c2SDaniel Finn .seealso: TSDiscGradUseGonzalez(), TSDISCGRAD
548*db4653c2SDaniel Finn @*/
549*db4653c2SDaniel Finn PetscErrorCode TSDiscGradIsGonzalez(TS ts,PetscBool *gonzalez)
550*db4653c2SDaniel Finn {
551*db4653c2SDaniel Finn   PetscErrorCode ierr;
552*db4653c2SDaniel Finn 
553*db4653c2SDaniel Finn   PetscFunctionBegin;
554*db4653c2SDaniel Finn   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
555*db4653c2SDaniel Finn   PetscValidPointer(gonzalez,2);
556*db4653c2SDaniel Finn   ierr = PetscUseMethod(ts,"TSDiscGradIsGonzalez_C",(TS,PetscBool*),(ts,gonzalez));CHKERRQ(ierr);
557*db4653c2SDaniel Finn   PetscFunctionReturn(0);
558*db4653c2SDaniel Finn }
559*db4653c2SDaniel Finn 
560*db4653c2SDaniel Finn /*@
561*db4653c2SDaniel Finn   TSDiscGradUseGonzalez - Sets discrete gradient formulation with or without additional conservative terms.  Without flag, the discrete gradients timestepper is just backwards euler
562*db4653c2SDaniel Finn 
563*db4653c2SDaniel Finn   Not Collective
564*db4653c2SDaniel Finn 
565*db4653c2SDaniel Finn   Input Parameter:
566*db4653c2SDaniel Finn +  ts - timestepping context
567*db4653c2SDaniel Finn -  flg - PETSC_TRUE to use the Gonzalez term
568*db4653c2SDaniel Finn 
569*db4653c2SDaniel Finn   Options Database:
570*db4653c2SDaniel Finn .  -ts_discgrad_gonzalez <flg>
571*db4653c2SDaniel Finn 
572*db4653c2SDaniel Finn   Level: Intermediate
573*db4653c2SDaniel Finn 
574*db4653c2SDaniel Finn .seealso: TSDISCGRAD
575*db4653c2SDaniel Finn @*/
576*db4653c2SDaniel Finn PetscErrorCode TSDiscGradUseGonzalez(TS ts,PetscBool flg)
577*db4653c2SDaniel Finn {
578*db4653c2SDaniel Finn   PetscErrorCode ierr;
579*db4653c2SDaniel Finn 
580*db4653c2SDaniel Finn   PetscFunctionBegin;
581*db4653c2SDaniel Finn   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
582*db4653c2SDaniel Finn   ierr = PetscTryMethod(ts,"TSDiscGradUseGonzalez_C",(TS,PetscBool),(ts,flg));CHKERRQ(ierr);
58340be0ff1SMatthew G. Knepley   PetscFunctionReturn(0);
58440be0ff1SMatthew G. Knepley }
585