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