1316643e7SJed Brown /*
2316643e7SJed Brown Code for timestepping with implicit Theta method
3316643e7SJed Brown */
4af0996ceSBarry Smith #include <petsc/private/tsimpl.h> /*I "petscts.h" I*/
5a055c8caSBarry Smith #include <petscsnes.h>
61e25c274SJed Brown #include <petscdm.h>
73c54f92cSHong Zhang #include <petscmat.h>
8316643e7SJed Brown
9316643e7SJed Brown typedef struct {
10715f1b00SHong Zhang /* context for time stepping */
111566a47fSLisandro Dalcin PetscReal stage_time;
12cc4f23bcSHong Zhang Vec Stages[2]; /* Storage for stage solutions */
13cc4f23bcSHong Zhang Vec X0, X, Xdot; /* Storage for u^n, u^n + dt a_{11} k_1, and time derivative u^{n+1}_t */
141566a47fSLisandro Dalcin Vec affine; /* Affine vector needed for residual at beginning of step in endpoint formulation */
151566a47fSLisandro Dalcin PetscReal Theta;
161a352fa8SHong Zhang PetscReal shift; /* Shift parameter for SNES Jacobian, used by forward, TLM and adjoint */
171566a47fSLisandro Dalcin PetscInt order;
181566a47fSLisandro Dalcin PetscBool endpoint;
191566a47fSLisandro Dalcin PetscBool extrapolate;
20715f1b00SHong Zhang TSStepStatus status;
211a352fa8SHong Zhang Vec VecCostIntegral0; /* Backup for roll-backs due to events, used by cost integral */
221a352fa8SHong Zhang PetscReal ptime0; /* Backup for ts->ptime, the start time of current time step, used by TLM and cost integral */
231a352fa8SHong Zhang PetscReal time_step0; /* Backup for ts->timestep, the step size of current time step, used by TLM and cost integral*/
241566a47fSLisandro Dalcin
25715f1b00SHong Zhang /* context for sensitivity analysis */
26022c081aSHong Zhang PetscInt num_tlm; /* Total number of tangent linear equations */
27b5e0532dSHong Zhang Vec *VecsDeltaLam; /* Increment of the adjoint sensitivity w.r.t IC at stage */
28b5e0532dSHong Zhang Vec *VecsDeltaMu; /* Increment of the adjoint sensitivity w.r.t P at stage */
2913b1b0ffSHong Zhang Vec *VecsSensiTemp; /* Vector to be multiplied with Jacobian transpose */
30cc4f23bcSHong Zhang Mat MatFwdStages[2]; /* TLM Stages */
3113b1b0ffSHong Zhang Mat MatDeltaFwdSensip; /* Increment of the forward sensitivity at stage */
32b5b4017aSHong Zhang Vec VecDeltaFwdSensipCol; /* Working vector for holding one column of the sensitivity matrix */
3313b1b0ffSHong Zhang Mat MatFwdSensip0; /* backup for roll-backs due to events */
347207e0fdSHong Zhang Mat MatIntegralSensipTemp; /* Working vector for forward integral sensitivity */
357207e0fdSHong Zhang Mat MatIntegralSensip0; /* backup for roll-backs due to events */
36b5b4017aSHong Zhang Vec *VecsDeltaLam2; /* Increment of the 2nd-order adjoint sensitivity w.r.t IC at stage */
37b5b4017aSHong Zhang Vec *VecsDeltaMu2; /* Increment of the 2nd-order adjoint sensitivity w.r.t P at stage */
38b5b4017aSHong Zhang Vec *VecsSensi2Temp; /* Working vectors that holds the residual for the second-order adjoint */
39b5b4017aSHong Zhang Vec *VecsAffine; /* Working vectors to store residuals */
40715f1b00SHong Zhang /* context for error estimation */
411566a47fSLisandro Dalcin Vec vec_sol_prev;
421566a47fSLisandro Dalcin Vec vec_lte_work;
43316643e7SJed Brown } TS_Theta;
44316643e7SJed Brown
TSThetaGetX0AndXdot(TS ts,DM dm,Vec * X0,Vec * Xdot)45d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSThetaGetX0AndXdot(TS ts, DM dm, Vec *X0, Vec *Xdot)
46d71ae5a4SJacob Faibussowitsch {
477445fe48SJed Brown TS_Theta *th = (TS_Theta *)ts->data;
487445fe48SJed Brown
497445fe48SJed Brown PetscFunctionBegin;
507445fe48SJed Brown if (X0) {
51ac530a7eSPierre Jolivet if (dm && dm != ts->dm) PetscCall(DMGetNamedGlobalVector(dm, "TSTheta_X0", X0));
52ac530a7eSPierre Jolivet else *X0 = ts->vec_sol;
537445fe48SJed Brown }
547445fe48SJed Brown if (Xdot) {
55ac530a7eSPierre Jolivet if (dm && dm != ts->dm) PetscCall(DMGetNamedGlobalVector(dm, "TSTheta_Xdot", Xdot));
56ac530a7eSPierre Jolivet else *Xdot = th->Xdot;
577445fe48SJed Brown }
583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
597445fe48SJed Brown }
607445fe48SJed Brown
TSThetaRestoreX0AndXdot(TS ts,DM dm,Vec * X0,Vec * Xdot)61d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSThetaRestoreX0AndXdot(TS ts, DM dm, Vec *X0, Vec *Xdot)
62d71ae5a4SJacob Faibussowitsch {
630d0b770aSPeter Brune PetscFunctionBegin;
640d0b770aSPeter Brune if (X0) {
6548a46eb9SPierre Jolivet if (dm && dm != ts->dm) PetscCall(DMRestoreNamedGlobalVector(dm, "TSTheta_X0", X0));
660d0b770aSPeter Brune }
670d0b770aSPeter Brune if (Xdot) {
6848a46eb9SPierre Jolivet if (dm && dm != ts->dm) PetscCall(DMRestoreNamedGlobalVector(dm, "TSTheta_Xdot", Xdot));
690d0b770aSPeter Brune }
703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
710d0b770aSPeter Brune }
720d0b770aSPeter Brune
DMCoarsenHook_TSTheta(DM fine,DM coarse,PetscCtx ctx)73*2a8381b2SBarry Smith static PetscErrorCode DMCoarsenHook_TSTheta(DM fine, DM coarse, PetscCtx ctx)
74d71ae5a4SJacob Faibussowitsch {
757445fe48SJed Brown PetscFunctionBegin;
763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
777445fe48SJed Brown }
787445fe48SJed Brown
DMRestrictHook_TSTheta(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse,PetscCtx ctx)79*2a8381b2SBarry Smith static PetscErrorCode DMRestrictHook_TSTheta(DM fine, Mat restrct, Vec rscale, Mat inject, DM coarse, PetscCtx ctx)
80d71ae5a4SJacob Faibussowitsch {
817445fe48SJed Brown TS ts = (TS)ctx;
827445fe48SJed Brown Vec X0, Xdot, X0_c, Xdot_c;
837445fe48SJed Brown
847445fe48SJed Brown PetscFunctionBegin;
859566063dSJacob Faibussowitsch PetscCall(TSThetaGetX0AndXdot(ts, fine, &X0, &Xdot));
869566063dSJacob Faibussowitsch PetscCall(TSThetaGetX0AndXdot(ts, coarse, &X0_c, &Xdot_c));
879566063dSJacob Faibussowitsch PetscCall(MatRestrict(restrct, X0, X0_c));
889566063dSJacob Faibussowitsch PetscCall(MatRestrict(restrct, Xdot, Xdot_c));
899566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(X0_c, rscale, X0_c));
909566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(Xdot_c, rscale, Xdot_c));
919566063dSJacob Faibussowitsch PetscCall(TSThetaRestoreX0AndXdot(ts, fine, &X0, &Xdot));
929566063dSJacob Faibussowitsch PetscCall(TSThetaRestoreX0AndXdot(ts, coarse, &X0_c, &Xdot_c));
933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
947445fe48SJed Brown }
957445fe48SJed Brown
DMSubDomainHook_TSTheta(DM dm,DM subdm,PetscCtx ctx)96*2a8381b2SBarry Smith static PetscErrorCode DMSubDomainHook_TSTheta(DM dm, DM subdm, PetscCtx ctx)
97d71ae5a4SJacob Faibussowitsch {
98258e1594SPeter Brune PetscFunctionBegin;
993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
100258e1594SPeter Brune }
101258e1594SPeter Brune
DMSubDomainRestrictHook_TSTheta(DM dm,VecScatter gscat,VecScatter lscat,DM subdm,PetscCtx ctx)102*2a8381b2SBarry Smith static PetscErrorCode DMSubDomainRestrictHook_TSTheta(DM dm, VecScatter gscat, VecScatter lscat, DM subdm, PetscCtx ctx)
103d71ae5a4SJacob Faibussowitsch {
104258e1594SPeter Brune TS ts = (TS)ctx;
105258e1594SPeter Brune Vec X0, Xdot, X0_sub, Xdot_sub;
106258e1594SPeter Brune
107258e1594SPeter Brune PetscFunctionBegin;
1089566063dSJacob Faibussowitsch PetscCall(TSThetaGetX0AndXdot(ts, dm, &X0, &Xdot));
1099566063dSJacob Faibussowitsch PetscCall(TSThetaGetX0AndXdot(ts, subdm, &X0_sub, &Xdot_sub));
110258e1594SPeter Brune
1119566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(gscat, X0, X0_sub, INSERT_VALUES, SCATTER_FORWARD));
1129566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(gscat, X0, X0_sub, INSERT_VALUES, SCATTER_FORWARD));
113258e1594SPeter Brune
1149566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(gscat, Xdot, Xdot_sub, INSERT_VALUES, SCATTER_FORWARD));
1159566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(gscat, Xdot, Xdot_sub, INSERT_VALUES, SCATTER_FORWARD));
116258e1594SPeter Brune
1179566063dSJacob Faibussowitsch PetscCall(TSThetaRestoreX0AndXdot(ts, dm, &X0, &Xdot));
1189566063dSJacob Faibussowitsch PetscCall(TSThetaRestoreX0AndXdot(ts, subdm, &X0_sub, &Xdot_sub));
1193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
120258e1594SPeter Brune }
121258e1594SPeter Brune
TSThetaEvaluateCostIntegral(TS ts)122d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSThetaEvaluateCostIntegral(TS ts)
123d71ae5a4SJacob Faibussowitsch {
124022c081aSHong Zhang TS_Theta *th = (TS_Theta *)ts->data;
125cd4cee2dSHong Zhang TS quadts = ts->quadraturets;
126022c081aSHong Zhang
127022c081aSHong Zhang PetscFunctionBegin;
128022c081aSHong Zhang if (th->endpoint) {
129022c081aSHong Zhang /* Evolve ts->vec_costintegral to compute integrals */
130022c081aSHong Zhang if (th->Theta != 1.0) {
1319566063dSJacob Faibussowitsch PetscCall(TSComputeRHSFunction(quadts, th->ptime0, th->X0, ts->vec_costintegrand));
1329566063dSJacob Faibussowitsch PetscCall(VecAXPY(quadts->vec_sol, th->time_step0 * (1.0 - th->Theta), ts->vec_costintegrand));
133022c081aSHong Zhang }
1349566063dSJacob Faibussowitsch PetscCall(TSComputeRHSFunction(quadts, ts->ptime, ts->vec_sol, ts->vec_costintegrand));
1359566063dSJacob Faibussowitsch PetscCall(VecAXPY(quadts->vec_sol, th->time_step0 * th->Theta, ts->vec_costintegrand));
136022c081aSHong Zhang } else {
1379566063dSJacob Faibussowitsch PetscCall(TSComputeRHSFunction(quadts, th->stage_time, th->X, ts->vec_costintegrand));
1389566063dSJacob Faibussowitsch PetscCall(VecAXPY(quadts->vec_sol, th->time_step0, ts->vec_costintegrand));
139022c081aSHong Zhang }
1403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
141022c081aSHong Zhang }
142022c081aSHong Zhang
TSForwardCostIntegral_Theta(TS ts)143d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSForwardCostIntegral_Theta(TS ts)
144d71ae5a4SJacob Faibussowitsch {
145b1cb36f3SHong Zhang TS_Theta *th = (TS_Theta *)ts->data;
146cd4cee2dSHong Zhang TS quadts = ts->quadraturets;
147b1cb36f3SHong Zhang
148b1cb36f3SHong Zhang PetscFunctionBegin;
149b1cb36f3SHong Zhang /* backup cost integral */
1509566063dSJacob Faibussowitsch PetscCall(VecCopy(quadts->vec_sol, th->VecCostIntegral0));
1519566063dSJacob Faibussowitsch PetscCall(TSThetaEvaluateCostIntegral(ts));
1523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
153b1cb36f3SHong Zhang }
154b1cb36f3SHong Zhang
TSAdjointCostIntegral_Theta(TS ts)155d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSAdjointCostIntegral_Theta(TS ts)
156d71ae5a4SJacob Faibussowitsch {
1571a352fa8SHong Zhang TS_Theta *th = (TS_Theta *)ts->data;
158b1cb36f3SHong Zhang
159b1cb36f3SHong Zhang PetscFunctionBegin;
1601a352fa8SHong Zhang /* Like TSForwardCostIntegral(), the adjoint cost integral evaluation relies on ptime0 and time_step0. */
1611a352fa8SHong Zhang th->ptime0 = ts->ptime + ts->time_step;
1621a352fa8SHong Zhang th->time_step0 = -ts->time_step;
1639566063dSJacob Faibussowitsch PetscCall(TSThetaEvaluateCostIntegral(ts));
1643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
16524655328SShri }
16624655328SShri
TSTheta_SNESSolve(TS ts,Vec b,Vec x)167d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSTheta_SNESSolve(TS ts, Vec b, Vec x)
168d71ae5a4SJacob Faibussowitsch {
1691566a47fSLisandro Dalcin PetscInt nits, lits;
1701566a47fSLisandro Dalcin
1711566a47fSLisandro Dalcin PetscFunctionBegin;
1729566063dSJacob Faibussowitsch PetscCall(SNESSolve(ts->snes, b, x));
1739566063dSJacob Faibussowitsch PetscCall(SNESGetIterationNumber(ts->snes, &nits));
1749566063dSJacob Faibussowitsch PetscCall(SNESGetLinearSolveIterations(ts->snes, &lits));
1759371c9d4SSatish Balay ts->snes_its += nits;
1769371c9d4SSatish Balay ts->ksp_its += lits;
1773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1781566a47fSLisandro Dalcin }
1791566a47fSLisandro Dalcin
TSResizeRegister_Theta(TS ts,PetscBool reg)18026b5f05dSStefano Zampini static PetscErrorCode TSResizeRegister_Theta(TS ts, PetscBool reg)
18126b5f05dSStefano Zampini {
18226b5f05dSStefano Zampini TS_Theta *th = (TS_Theta *)ts->data;
18326b5f05dSStefano Zampini
18426b5f05dSStefano Zampini PetscFunctionBegin;
185ecc87898SStefano Zampini if (reg) {
186ecc87898SStefano Zampini PetscCall(TSResizeRegisterVec(ts, "ts:theta:sol_prev", th->vec_sol_prev));
187ecc87898SStefano Zampini PetscCall(TSResizeRegisterVec(ts, "ts:theta:X0", th->X0));
188ecc87898SStefano Zampini } else {
189ecc87898SStefano Zampini PetscCall(TSResizeRetrieveVec(ts, "ts:theta:sol_prev", &th->vec_sol_prev));
190ecc87898SStefano Zampini PetscCall(PetscObjectReference((PetscObject)th->vec_sol_prev));
191ecc87898SStefano Zampini PetscCall(TSResizeRetrieveVec(ts, "ts:theta:X0", &th->X0));
19226b5f05dSStefano Zampini PetscCall(PetscObjectReference((PetscObject)th->X0));
19326b5f05dSStefano Zampini }
19426b5f05dSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS);
19526b5f05dSStefano Zampini }
19626b5f05dSStefano Zampini
TSStep_Theta(TS ts)197d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSStep_Theta(TS ts)
198d71ae5a4SJacob Faibussowitsch {
199316643e7SJed Brown TS_Theta *th = (TS_Theta *)ts->data;
2001566a47fSLisandro Dalcin PetscInt rejections = 0;
2014957b756SLisandro Dalcin PetscBool stageok, accept = PETSC_TRUE;
2021566a47fSLisandro Dalcin PetscReal next_time_step = ts->time_step;
203316643e7SJed Brown
204316643e7SJed Brown PetscFunctionBegin;
2051566a47fSLisandro Dalcin if (!ts->steprollback) {
2069566063dSJacob Faibussowitsch if (th->vec_sol_prev) PetscCall(VecCopy(th->X0, th->vec_sol_prev));
2079566063dSJacob Faibussowitsch PetscCall(VecCopy(ts->vec_sol, th->X0));
2081566a47fSLisandro Dalcin }
2091566a47fSLisandro Dalcin
2101566a47fSLisandro Dalcin th->status = TS_STEP_INCOMPLETE;
21199260352SHong Zhang while (!ts->reason && th->status != TS_STEP_COMPLETE) {
2123e05ceb1SHong Zhang th->shift = 1 / (th->Theta * ts->time_step);
2131566a47fSLisandro Dalcin th->stage_time = ts->ptime + (th->endpoint ? (PetscReal)1 : th->Theta) * ts->time_step;
2149566063dSJacob Faibussowitsch PetscCall(VecCopy(th->X0, th->X));
21548a46eb9SPierre Jolivet if (th->extrapolate && !ts->steprestart) PetscCall(VecAXPY(th->X, 1 / th->shift, th->Xdot));
216eb284becSJed Brown if (th->endpoint) { /* This formulation assumes linear time-independent mass matrix */
2179566063dSJacob Faibussowitsch if (!th->affine) PetscCall(VecDuplicate(ts->vec_sol, &th->affine));
2189566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(th->Xdot));
2199566063dSJacob Faibussowitsch PetscCall(TSComputeIFunction(ts, ts->ptime, th->X0, th->Xdot, th->affine, PETSC_FALSE));
2209566063dSJacob Faibussowitsch PetscCall(VecScale(th->affine, (th->Theta - 1) / th->Theta));
221eb284becSJed Brown }
2229566063dSJacob Faibussowitsch PetscCall(TSPreStage(ts, th->stage_time));
22382d7ce88SStefano Zampini PetscCall(TSTheta_SNESSolve(ts, th->endpoint ? th->affine : NULL, th->X));
2249566063dSJacob Faibussowitsch PetscCall(TSPostStage(ts, th->stage_time, 0, &th->X));
2259566063dSJacob Faibussowitsch PetscCall(TSAdaptCheckStage(ts->adapt, ts, th->stage_time, th->X, &stageok));
226fecfb714SLisandro Dalcin if (!stageok) goto reject_step;
227051f2191SLisandro Dalcin
228b7795fd7SStefano Zampini if (th->endpoint) {
2299566063dSJacob Faibussowitsch PetscCall(VecCopy(th->X, ts->vec_sol));
2301566a47fSLisandro Dalcin } else {
231b7795fd7SStefano Zampini PetscCall(VecAXPBYPCZ(th->Xdot, -th->shift, th->shift, 0, th->X0, th->X)); /* th->Xdot is needed by TSInterpolate_Theta */
232b7795fd7SStefano Zampini if (th->Theta == 1.0) PetscCall(VecCopy(th->X, ts->vec_sol)); /* BEULER, stage already checked */
233b7795fd7SStefano Zampini else {
2349566063dSJacob Faibussowitsch PetscCall(VecAXPY(ts->vec_sol, ts->time_step, th->Xdot));
235b7795fd7SStefano Zampini PetscCall(TSAdaptCheckStage(ts->adapt, ts, ts->ptime + ts->time_step, ts->vec_sol, &stageok));
236b7795fd7SStefano Zampini if (!stageok) {
237b7795fd7SStefano Zampini PetscCall(VecCopy(th->X0, ts->vec_sol));
238b7795fd7SStefano Zampini goto reject_step;
2391566a47fSLisandro Dalcin }
240b7795fd7SStefano Zampini }
241b7795fd7SStefano Zampini }
242b7795fd7SStefano Zampini
243b7795fd7SStefano Zampini th->status = TS_STEP_PENDING;
2449566063dSJacob Faibussowitsch PetscCall(TSAdaptChoose(ts->adapt, ts, ts->time_step, NULL, &next_time_step, &accept));
2451566a47fSLisandro Dalcin th->status = accept ? TS_STEP_COMPLETE : TS_STEP_INCOMPLETE;
2461566a47fSLisandro Dalcin if (!accept) {
2479566063dSJacob Faibussowitsch PetscCall(VecCopy(th->X0, ts->vec_sol));
248be5899b3SLisandro Dalcin ts->time_step = next_time_step;
249be5899b3SLisandro Dalcin goto reject_step;
250051f2191SLisandro Dalcin }
2513b1890cdSShri Abhyankar
252715f1b00SHong Zhang if (ts->forward_solve || ts->costintegralfwd) { /* Save the info for the later use in cost integral evaluation */
2531a352fa8SHong Zhang th->ptime0 = ts->ptime;
2541a352fa8SHong Zhang th->time_step0 = ts->time_step;
25517145e75SHong Zhang }
2562b5a38e1SLisandro Dalcin ts->ptime += ts->time_step;
257cdbf8f93SLisandro Dalcin ts->time_step = next_time_step;
258051f2191SLisandro Dalcin break;
259051f2191SLisandro Dalcin
260051f2191SLisandro Dalcin reject_step:
2619371c9d4SSatish Balay ts->reject++;
2629371c9d4SSatish Balay accept = PETSC_FALSE;
2631566a47fSLisandro Dalcin if (!ts->reason && ++rejections > ts->max_reject && ts->max_reject >= 0) {
264051f2191SLisandro Dalcin ts->reason = TS_DIVERGED_STEP_REJECTED;
26563a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(ts, "Step=%" PetscInt_FMT ", step rejections %" PetscInt_FMT " greater than current TS allowed, stopping solve\n", ts->steps, rejections));
2663b1890cdSShri Abhyankar }
2673b1890cdSShri Abhyankar }
2683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
269316643e7SJed Brown }
270316643e7SJed Brown
TSAdjointStepBEuler_Private(TS ts)271d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSAdjointStepBEuler_Private(TS ts)
272d71ae5a4SJacob Faibussowitsch {
273c9681e5dSHong Zhang TS_Theta *th = (TS_Theta *)ts->data;
274cd4cee2dSHong Zhang TS quadts = ts->quadraturets;
275c9681e5dSHong Zhang Vec *VecsDeltaLam = th->VecsDeltaLam, *VecsDeltaMu = th->VecsDeltaMu, *VecsSensiTemp = th->VecsSensiTemp;
276c9681e5dSHong Zhang Vec *VecsDeltaLam2 = th->VecsDeltaLam2, *VecsDeltaMu2 = th->VecsDeltaMu2, *VecsSensi2Temp = th->VecsSensi2Temp;
277c9681e5dSHong Zhang PetscInt nadj;
2787207e0fdSHong Zhang Mat J, Jpre, quadJ = NULL, quadJp = NULL;
279c9681e5dSHong Zhang KSP ksp;
280c9681e5dSHong Zhang PetscScalar *xarr;
281077c4feaSHong Zhang TSEquationType eqtype;
282077c4feaSHong Zhang PetscBool isexplicitode = PETSC_FALSE;
2831a352fa8SHong Zhang PetscReal adjoint_time_step;
284c9681e5dSHong Zhang
285c9681e5dSHong Zhang PetscFunctionBegin;
2869566063dSJacob Faibussowitsch PetscCall(TSGetEquationType(ts, &eqtype));
287077c4feaSHong Zhang if (eqtype == TS_EQ_ODE_EXPLICIT) {
288077c4feaSHong Zhang isexplicitode = PETSC_TRUE;
289077c4feaSHong Zhang VecsDeltaLam = ts->vecs_sensi;
290077c4feaSHong Zhang VecsDeltaLam2 = ts->vecs_sensi2;
291077c4feaSHong Zhang }
292c9681e5dSHong Zhang th->status = TS_STEP_INCOMPLETE;
2939566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(ts->snes, &ksp));
2949566063dSJacob Faibussowitsch PetscCall(TSGetIJacobian(ts, &J, &Jpre, NULL, NULL));
2957207e0fdSHong Zhang if (quadts) {
2969566063dSJacob Faibussowitsch PetscCall(TSGetRHSJacobian(quadts, &quadJ, NULL, NULL, NULL));
2979566063dSJacob Faibussowitsch PetscCall(TSGetRHSJacobianP(quadts, &quadJp, NULL, NULL));
2987207e0fdSHong Zhang }
299c9681e5dSHong Zhang
3001a352fa8SHong Zhang th->stage_time = ts->ptime;
3011a352fa8SHong Zhang adjoint_time_step = -ts->time_step; /* always positive since time_step is negative */
302c9681e5dSHong Zhang
30333f72c5dSHong Zhang /* Build RHS for first-order adjoint lambda_{n+1}/h + r_u^T(n+1) */
3041baa6e33SBarry Smith if (quadts) PetscCall(TSComputeRHSJacobian(quadts, th->stage_time, ts->vec_sol, quadJ, NULL));
305cd4cee2dSHong Zhang
306c9681e5dSHong Zhang for (nadj = 0; nadj < ts->numcost; nadj++) {
3079566063dSJacob Faibussowitsch PetscCall(VecCopy(ts->vecs_sensi[nadj], VecsSensiTemp[nadj]));
3089566063dSJacob Faibussowitsch PetscCall(VecScale(VecsSensiTemp[nadj], 1. / adjoint_time_step)); /* lambda_{n+1}/h */
309cd4cee2dSHong Zhang if (quadJ) {
3109566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumn(quadJ, nadj, &xarr));
3119566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(ts->vec_drdu_col, xarr));
3129566063dSJacob Faibussowitsch PetscCall(VecAXPY(VecsSensiTemp[nadj], 1., ts->vec_drdu_col));
3139566063dSJacob Faibussowitsch PetscCall(VecResetArray(ts->vec_drdu_col));
3149566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumn(quadJ, &xarr));
315c9681e5dSHong Zhang }
316c9681e5dSHong Zhang }
317c9681e5dSHong Zhang
318c9681e5dSHong Zhang /* Build LHS for first-order adjoint */
319c87ba875SIvan Yashchuk th->shift = 1. / adjoint_time_step;
3209566063dSJacob Faibussowitsch PetscCall(TSComputeSNESJacobian(ts, ts->vec_sol, J, Jpre));
3219566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(ksp, J, Jpre));
322c9681e5dSHong Zhang
323c9681e5dSHong Zhang /* Solve stage equation LHS*lambda_s = RHS for first-order adjoint */
324c9681e5dSHong Zhang for (nadj = 0; nadj < ts->numcost; nadj++) {
325c9681e5dSHong Zhang KSPConvergedReason kspreason;
3269566063dSJacob Faibussowitsch PetscCall(KSPSolveTranspose(ksp, VecsSensiTemp[nadj], VecsDeltaLam[nadj]));
3279566063dSJacob Faibussowitsch PetscCall(KSPGetConvergedReason(ksp, &kspreason));
328c9681e5dSHong Zhang if (kspreason < 0) {
329c9681e5dSHong Zhang ts->reason = TSADJOINT_DIVERGED_LINEAR_SOLVE;
33063a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(ts, "Step=%" PetscInt_FMT ", %" PetscInt_FMT "th cost function, transposed linear solve fails, stopping 1st-order adjoint solve\n", ts->steps, nadj));
331c9681e5dSHong Zhang }
332c9681e5dSHong Zhang }
333c9681e5dSHong Zhang
334c9681e5dSHong Zhang if (ts->vecs_sensi2) { /* U_{n+1} */
335c9681e5dSHong Zhang /* Get w1 at t_{n+1} from TLM matrix */
3369566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumn(ts->mat_sensip, 0, &xarr));
3379566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(ts->vec_sensip_col, xarr));
338c9681e5dSHong Zhang /* lambda_s^T F_UU w_1 */
3399566063dSJacob Faibussowitsch PetscCall(TSComputeIHessianProductFunctionUU(ts, th->stage_time, ts->vec_sol, VecsDeltaLam, ts->vec_sensip_col, ts->vecs_fuu));
340c9681e5dSHong Zhang /* lambda_s^T F_UP w_2 */
3419566063dSJacob Faibussowitsch PetscCall(TSComputeIHessianProductFunctionUP(ts, th->stage_time, ts->vec_sol, VecsDeltaLam, ts->vec_dir, ts->vecs_fup));
342c9681e5dSHong Zhang for (nadj = 0; nadj < ts->numcost; nadj++) { /* compute the residual */
3439566063dSJacob Faibussowitsch PetscCall(VecCopy(ts->vecs_sensi2[nadj], VecsSensi2Temp[nadj]));
3449566063dSJacob Faibussowitsch PetscCall(VecScale(VecsSensi2Temp[nadj], 1. / adjoint_time_step));
3459566063dSJacob Faibussowitsch PetscCall(VecAXPY(VecsSensi2Temp[nadj], -1., ts->vecs_fuu[nadj]));
34648a46eb9SPierre Jolivet if (ts->vecs_fup) PetscCall(VecAXPY(VecsSensi2Temp[nadj], -1., ts->vecs_fup[nadj]));
347c9681e5dSHong Zhang }
348c9681e5dSHong Zhang /* Solve stage equation LHS X = RHS for second-order adjoint */
349c9681e5dSHong Zhang for (nadj = 0; nadj < ts->numcost; nadj++) {
35005c9950eSHong Zhang KSPConvergedReason kspreason;
3519566063dSJacob Faibussowitsch PetscCall(KSPSolveTranspose(ksp, VecsSensi2Temp[nadj], VecsDeltaLam2[nadj]));
3529566063dSJacob Faibussowitsch PetscCall(KSPGetConvergedReason(ksp, &kspreason));
35305c9950eSHong Zhang if (kspreason < 0) {
35405c9950eSHong Zhang ts->reason = TSADJOINT_DIVERGED_LINEAR_SOLVE;
35563a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(ts, "Step=%" PetscInt_FMT ", %" PetscInt_FMT "th cost function, transposed linear solve fails, stopping 2nd-order adjoint solve\n", ts->steps, nadj));
35605c9950eSHong Zhang }
357c9681e5dSHong Zhang }
358c9681e5dSHong Zhang }
359c9681e5dSHong Zhang
360c9681e5dSHong Zhang /* Update sensitivities, and evaluate integrals if there is any */
361077c4feaSHong Zhang if (!isexplicitode) {
3623e05ceb1SHong Zhang th->shift = 0.0;
3639566063dSJacob Faibussowitsch PetscCall(TSComputeSNESJacobian(ts, ts->vec_sol, J, Jpre));
3649566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(ksp, J, Jpre));
365c9681e5dSHong Zhang for (nadj = 0; nadj < ts->numcost; nadj++) {
36633f72c5dSHong Zhang /* Add f_U \lambda_s to the original RHS */
3679566063dSJacob Faibussowitsch PetscCall(VecScale(VecsSensiTemp[nadj], -1.));
3689566063dSJacob Faibussowitsch PetscCall(MatMultTransposeAdd(J, VecsDeltaLam[nadj], VecsSensiTemp[nadj], VecsSensiTemp[nadj]));
3699566063dSJacob Faibussowitsch PetscCall(VecScale(VecsSensiTemp[nadj], -adjoint_time_step));
3709566063dSJacob Faibussowitsch PetscCall(VecCopy(VecsSensiTemp[nadj], ts->vecs_sensi[nadj]));
371c9681e5dSHong Zhang if (ts->vecs_sensi2) {
3729566063dSJacob Faibussowitsch PetscCall(MatMultTransposeAdd(J, VecsDeltaLam2[nadj], VecsSensi2Temp[nadj], VecsSensi2Temp[nadj]));
3739566063dSJacob Faibussowitsch PetscCall(VecScale(VecsSensi2Temp[nadj], -adjoint_time_step));
3749566063dSJacob Faibussowitsch PetscCall(VecCopy(VecsSensi2Temp[nadj], ts->vecs_sensi2[nadj]));
375c9681e5dSHong Zhang }
376c9681e5dSHong Zhang }
377077c4feaSHong Zhang }
378c9681e5dSHong Zhang if (ts->vecs_sensip) {
3799566063dSJacob Faibussowitsch PetscCall(VecAXPBYPCZ(th->Xdot, -1. / adjoint_time_step, 1.0 / adjoint_time_step, 0, th->X0, ts->vec_sol));
3809566063dSJacob Faibussowitsch PetscCall(TSComputeIJacobianP(ts, th->stage_time, ts->vec_sol, th->Xdot, 1. / adjoint_time_step, ts->Jacp, PETSC_FALSE)); /* get -f_p */
3811baa6e33SBarry Smith if (quadts) PetscCall(TSComputeRHSJacobianP(quadts, th->stage_time, ts->vec_sol, quadJp));
382c9681e5dSHong Zhang if (ts->vecs_sensi2p) {
383c9681e5dSHong Zhang /* lambda_s^T F_PU w_1 */
3849566063dSJacob Faibussowitsch PetscCall(TSComputeIHessianProductFunctionPU(ts, th->stage_time, ts->vec_sol, VecsDeltaLam, ts->vec_sensip_col, ts->vecs_fpu));
38533f72c5dSHong Zhang /* lambda_s^T F_PP w_2 */
3869566063dSJacob Faibussowitsch PetscCall(TSComputeIHessianProductFunctionPP(ts, th->stage_time, ts->vec_sol, VecsDeltaLam, ts->vec_dir, ts->vecs_fpp));
387c9681e5dSHong Zhang }
388cd4cee2dSHong Zhang
389c9681e5dSHong Zhang for (nadj = 0; nadj < ts->numcost; nadj++) {
3909566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(ts->Jacp, VecsDeltaLam[nadj], VecsDeltaMu[nadj]));
3919566063dSJacob Faibussowitsch PetscCall(VecAXPY(ts->vecs_sensip[nadj], -adjoint_time_step, VecsDeltaMu[nadj]));
392cd4cee2dSHong Zhang if (quadJp) {
3939566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumn(quadJp, nadj, &xarr));
3949566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(ts->vec_drdp_col, xarr));
3959566063dSJacob Faibussowitsch PetscCall(VecAXPY(ts->vecs_sensip[nadj], adjoint_time_step, ts->vec_drdp_col));
3969566063dSJacob Faibussowitsch PetscCall(VecResetArray(ts->vec_drdp_col));
3979566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumn(quadJp, &xarr));
39833f72c5dSHong Zhang }
399c9681e5dSHong Zhang if (ts->vecs_sensi2p) {
4009566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(ts->Jacp, VecsDeltaLam2[nadj], VecsDeltaMu2[nadj]));
4019566063dSJacob Faibussowitsch PetscCall(VecAXPY(ts->vecs_sensi2p[nadj], -adjoint_time_step, VecsDeltaMu2[nadj]));
40248a46eb9SPierre Jolivet if (ts->vecs_fpu) PetscCall(VecAXPY(ts->vecs_sensi2p[nadj], -adjoint_time_step, ts->vecs_fpu[nadj]));
40348a46eb9SPierre Jolivet if (ts->vecs_fpp) PetscCall(VecAXPY(ts->vecs_sensi2p[nadj], -adjoint_time_step, ts->vecs_fpp[nadj]));
404c9681e5dSHong Zhang }
405c9681e5dSHong Zhang }
406c9681e5dSHong Zhang }
407c9681e5dSHong Zhang
408c9681e5dSHong Zhang if (ts->vecs_sensi2) {
4099566063dSJacob Faibussowitsch PetscCall(VecResetArray(ts->vec_sensip_col));
4109566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumn(ts->mat_sensip, &xarr));
411c9681e5dSHong Zhang }
412c9681e5dSHong Zhang th->status = TS_STEP_COMPLETE;
4133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
414c9681e5dSHong Zhang }
415c9681e5dSHong Zhang
TSAdjointStep_Theta(TS ts)416d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSAdjointStep_Theta(TS ts)
417d71ae5a4SJacob Faibussowitsch {
4182ca6e920SHong Zhang TS_Theta *th = (TS_Theta *)ts->data;
419cd4cee2dSHong Zhang TS quadts = ts->quadraturets;
420b5e0532dSHong Zhang Vec *VecsDeltaLam = th->VecsDeltaLam, *VecsDeltaMu = th->VecsDeltaMu, *VecsSensiTemp = th->VecsSensiTemp;
421b5b4017aSHong Zhang Vec *VecsDeltaLam2 = th->VecsDeltaLam2, *VecsDeltaMu2 = th->VecsDeltaMu2, *VecsSensi2Temp = th->VecsSensi2Temp;
4222ca6e920SHong Zhang PetscInt nadj;
4237207e0fdSHong Zhang Mat J, Jpre, quadJ = NULL, quadJp = NULL;
4242ca6e920SHong Zhang KSP ksp;
425b5b4017aSHong Zhang PetscScalar *xarr;
4261a352fa8SHong Zhang PetscReal adjoint_time_step;
427da81f932SPierre Jolivet PetscReal adjoint_ptime; /* end time of the adjoint time step (ts->ptime is the start time, usually ts->ptime is larger than adjoint_ptime) */
4282ca6e920SHong Zhang
4292ca6e920SHong Zhang PetscFunctionBegin;
430c9681e5dSHong Zhang if (th->Theta == 1.) {
4319566063dSJacob Faibussowitsch PetscCall(TSAdjointStepBEuler_Private(ts));
4323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
433c9681e5dSHong Zhang }
4342ca6e920SHong Zhang th->status = TS_STEP_INCOMPLETE;
4359566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(ts->snes, &ksp));
4369566063dSJacob Faibussowitsch PetscCall(TSGetIJacobian(ts, &J, &Jpre, NULL, NULL));
4377207e0fdSHong Zhang if (quadts) {
4389566063dSJacob Faibussowitsch PetscCall(TSGetRHSJacobian(quadts, &quadJ, NULL, NULL, NULL));
4399566063dSJacob Faibussowitsch PetscCall(TSGetRHSJacobianP(quadts, &quadJp, NULL, NULL));
4407207e0fdSHong Zhang }
441b5e0532dSHong Zhang /* If endpoint=1, th->ptime and th->X0 will be used; if endpoint=0, th->stage_time and th->X will be used. */
4421a352fa8SHong Zhang th->stage_time = th->endpoint ? ts->ptime : (ts->ptime + (1. - th->Theta) * ts->time_step);
4431a352fa8SHong Zhang adjoint_ptime = ts->ptime + ts->time_step;
4441a352fa8SHong Zhang adjoint_time_step = -ts->time_step; /* always positive since time_step is negative */
4452ca6e920SHong Zhang
44682ad9101SHong Zhang if (!th->endpoint) {
4475072d23cSHong Zhang /* recover th->X0 using vec_sol and the stage value th->X */
4489566063dSJacob Faibussowitsch PetscCall(VecAXPBYPCZ(th->X0, 1.0 / (1.0 - th->Theta), th->Theta / (th->Theta - 1.0), 0, th->X, ts->vec_sol));
44982ad9101SHong Zhang }
45082ad9101SHong Zhang
451b5b4017aSHong Zhang /* Build RHS for first-order adjoint */
45233f72c5dSHong Zhang /* Cost function has an integral term */
4537207e0fdSHong Zhang if (quadts) {
45405755b9cSHong Zhang if (th->endpoint) {
4559566063dSJacob Faibussowitsch PetscCall(TSComputeRHSJacobian(quadts, th->stage_time, ts->vec_sol, quadJ, NULL));
45605755b9cSHong Zhang } else {
4579566063dSJacob Faibussowitsch PetscCall(TSComputeRHSJacobian(quadts, th->stage_time, th->X, quadJ, NULL));
45805755b9cSHong Zhang }
4597207e0fdSHong Zhang }
46033f72c5dSHong Zhang
461abc2977eSBarry Smith for (nadj = 0; nadj < ts->numcost; nadj++) {
4629566063dSJacob Faibussowitsch PetscCall(VecCopy(ts->vecs_sensi[nadj], VecsSensiTemp[nadj]));
4639566063dSJacob Faibussowitsch PetscCall(VecScale(VecsSensiTemp[nadj], 1. / (th->Theta * adjoint_time_step)));
464cd4cee2dSHong Zhang if (quadJ) {
4659566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumn(quadJ, nadj, &xarr));
4669566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(ts->vec_drdu_col, xarr));
4679566063dSJacob Faibussowitsch PetscCall(VecAXPY(VecsSensiTemp[nadj], 1., ts->vec_drdu_col));
4689566063dSJacob Faibussowitsch PetscCall(VecResetArray(ts->vec_drdu_col));
4699566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumn(quadJ, &xarr));
47036eaed60SHong Zhang }
4712ca6e920SHong Zhang }
4723c54f92cSHong Zhang
473b5b4017aSHong Zhang /* Build LHS for first-order adjoint */
4741a352fa8SHong Zhang th->shift = 1. / (th->Theta * adjoint_time_step);
4753c54f92cSHong Zhang if (th->endpoint) {
4769566063dSJacob Faibussowitsch PetscCall(TSComputeSNESJacobian(ts, ts->vec_sol, J, Jpre));
4773c54f92cSHong Zhang } else {
4789566063dSJacob Faibussowitsch PetscCall(TSComputeSNESJacobian(ts, th->X, J, Jpre));
4793c54f92cSHong Zhang }
4809566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(ksp, J, Jpre));
4812ca6e920SHong Zhang
482b5b4017aSHong Zhang /* Solve stage equation LHS*lambda_s = RHS for first-order adjoint */
483abc2977eSBarry Smith for (nadj = 0; nadj < ts->numcost; nadj++) {
4841d14d03bSHong Zhang KSPConvergedReason kspreason;
4859566063dSJacob Faibussowitsch PetscCall(KSPSolveTranspose(ksp, VecsSensiTemp[nadj], VecsDeltaLam[nadj]));
4869566063dSJacob Faibussowitsch PetscCall(KSPGetConvergedReason(ksp, &kspreason));
4871d14d03bSHong Zhang if (kspreason < 0) {
4881d14d03bSHong Zhang ts->reason = TSADJOINT_DIVERGED_LINEAR_SOLVE;
48963a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(ts, "Step=%" PetscInt_FMT ", %" PetscInt_FMT "th cost function, transposed linear solve fails, stopping 1st-order adjoint solve\n", ts->steps, nadj));
4901d14d03bSHong Zhang }
4912ca6e920SHong Zhang }
4923c54f92cSHong Zhang
4931d14d03bSHong Zhang /* Second-order adjoint */
494b5b4017aSHong Zhang if (ts->vecs_sensi2) { /* U_{n+1} */
4953c633725SBarry Smith PetscCheck(th->endpoint, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "Operation not implemented in TS_Theta");
496b5b4017aSHong Zhang /* Get w1 at t_{n+1} from TLM matrix */
4979566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumn(ts->mat_sensip, 0, &xarr));
4989566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(ts->vec_sensip_col, xarr));
499b5b4017aSHong Zhang /* lambda_s^T F_UU w_1 */
5009566063dSJacob Faibussowitsch PetscCall(TSComputeIHessianProductFunctionUU(ts, th->stage_time, ts->vec_sol, VecsDeltaLam, ts->vec_sensip_col, ts->vecs_fuu));
5019566063dSJacob Faibussowitsch PetscCall(VecResetArray(ts->vec_sensip_col));
5029566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumn(ts->mat_sensip, &xarr));
503b5b4017aSHong Zhang /* lambda_s^T F_UP w_2 */
5049566063dSJacob Faibussowitsch PetscCall(TSComputeIHessianProductFunctionUP(ts, th->stage_time, ts->vec_sol, VecsDeltaLam, ts->vec_dir, ts->vecs_fup));
505b5b4017aSHong Zhang for (nadj = 0; nadj < ts->numcost; nadj++) { /* compute the residual */
5069566063dSJacob Faibussowitsch PetscCall(VecCopy(ts->vecs_sensi2[nadj], VecsSensi2Temp[nadj]));
5079566063dSJacob Faibussowitsch PetscCall(VecScale(VecsSensi2Temp[nadj], th->shift));
5089566063dSJacob Faibussowitsch PetscCall(VecAXPY(VecsSensi2Temp[nadj], -1., ts->vecs_fuu[nadj]));
50948a46eb9SPierre Jolivet if (ts->vecs_fup) PetscCall(VecAXPY(VecsSensi2Temp[nadj], -1., ts->vecs_fup[nadj]));
510b5b4017aSHong Zhang }
511b5b4017aSHong Zhang /* Solve stage equation LHS X = RHS for second-order adjoint */
512b5b4017aSHong Zhang for (nadj = 0; nadj < ts->numcost; nadj++) {
5131d14d03bSHong Zhang KSPConvergedReason kspreason;
5149566063dSJacob Faibussowitsch PetscCall(KSPSolveTranspose(ksp, VecsSensi2Temp[nadj], VecsDeltaLam2[nadj]));
5159566063dSJacob Faibussowitsch PetscCall(KSPGetConvergedReason(ksp, &kspreason));
5161d14d03bSHong Zhang if (kspreason < 0) {
5171d14d03bSHong Zhang ts->reason = TSADJOINT_DIVERGED_LINEAR_SOLVE;
51863a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(ts, "Step=%" PetscInt_FMT ", %" PetscInt_FMT "th cost function, transposed linear solve fails, stopping 2nd-order adjoint solve\n", ts->steps, nadj));
5191d14d03bSHong Zhang }
520b5b4017aSHong Zhang }
521b5b4017aSHong Zhang }
522b5b4017aSHong Zhang
52336eaed60SHong Zhang /* Update sensitivities, and evaluate integrals if there is any */
5241d14d03bSHong Zhang if (th->endpoint) { /* two-stage Theta methods with th->Theta!=1, th->Theta==1 leads to BEuler */
5251a352fa8SHong Zhang th->shift = 1. / ((th->Theta - 1.) * adjoint_time_step);
5261a352fa8SHong Zhang th->stage_time = adjoint_ptime;
5279566063dSJacob Faibussowitsch PetscCall(TSComputeSNESJacobian(ts, th->X0, J, Jpre));
5289566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(ksp, J, Jpre));
52933f72c5dSHong Zhang /* R_U at t_n */
5301baa6e33SBarry Smith if (quadts) PetscCall(TSComputeRHSJacobian(quadts, adjoint_ptime, th->X0, quadJ, NULL));
531abc2977eSBarry Smith for (nadj = 0; nadj < ts->numcost; nadj++) {
5329566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(J, VecsDeltaLam[nadj], ts->vecs_sensi[nadj]));
533cd4cee2dSHong Zhang if (quadJ) {
5349566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumn(quadJ, nadj, &xarr));
5359566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(ts->vec_drdu_col, xarr));
5369566063dSJacob Faibussowitsch PetscCall(VecAXPY(ts->vecs_sensi[nadj], -1., ts->vec_drdu_col));
5379566063dSJacob Faibussowitsch PetscCall(VecResetArray(ts->vec_drdu_col));
5389566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumn(quadJ, &xarr));
539b5b4017aSHong Zhang }
5409566063dSJacob Faibussowitsch PetscCall(VecScale(ts->vecs_sensi[nadj], 1. / th->shift));
541b5b4017aSHong Zhang }
5421d14d03bSHong Zhang
5431d14d03bSHong Zhang /* Second-order adjoint */
5441d14d03bSHong Zhang if (ts->vecs_sensi2) { /* U_n */
545b5b4017aSHong Zhang /* Get w1 at t_n from TLM matrix */
5469566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumn(th->MatFwdSensip0, 0, &xarr));
5479566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(ts->vec_sensip_col, xarr));
548b5b4017aSHong Zhang /* lambda_s^T F_UU w_1 */
5499566063dSJacob Faibussowitsch PetscCall(TSComputeIHessianProductFunctionUU(ts, adjoint_ptime, th->X0, VecsDeltaLam, ts->vec_sensip_col, ts->vecs_fuu));
5509566063dSJacob Faibussowitsch PetscCall(VecResetArray(ts->vec_sensip_col));
5519566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumn(th->MatFwdSensip0, &xarr));
552b5b4017aSHong Zhang /* lambda_s^T F_UU w_2 */
5539566063dSJacob Faibussowitsch PetscCall(TSComputeIHessianProductFunctionUP(ts, adjoint_ptime, th->X0, VecsDeltaLam, ts->vec_dir, ts->vecs_fup));
554b5b4017aSHong Zhang for (nadj = 0; nadj < ts->numcost; nadj++) {
55533f72c5dSHong Zhang /* M^T Lambda_s + h(1-theta) F_U^T Lambda_s + h(1-theta) lambda_s^T F_UU w_1 + lambda_s^T F_UP w_2 */
5569566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(J, VecsDeltaLam2[nadj], ts->vecs_sensi2[nadj]));
5579566063dSJacob Faibussowitsch PetscCall(VecAXPY(ts->vecs_sensi2[nadj], 1., ts->vecs_fuu[nadj]));
55848a46eb9SPierre Jolivet if (ts->vecs_fup) PetscCall(VecAXPY(ts->vecs_sensi2[nadj], 1., ts->vecs_fup[nadj]));
5599566063dSJacob Faibussowitsch PetscCall(VecScale(ts->vecs_sensi2[nadj], 1. / th->shift));
560b5b4017aSHong Zhang }
561b5e0532dSHong Zhang }
5623fd52205SHong Zhang
563c586f2e8SHong Zhang th->stage_time = ts->ptime; /* recover the old value */
564c586f2e8SHong Zhang
5653fd52205SHong Zhang if (ts->vecs_sensip) { /* sensitivities wrt parameters */
566b5b4017aSHong Zhang /* U_{n+1} */
56782ad9101SHong Zhang th->shift = 1.0 / (adjoint_time_step * th->Theta);
5689566063dSJacob Faibussowitsch PetscCall(VecAXPBYPCZ(th->Xdot, -th->shift, th->shift, 0, th->X0, ts->vec_sol));
5699566063dSJacob Faibussowitsch PetscCall(TSComputeIJacobianP(ts, th->stage_time, ts->vec_sol, th->Xdot, -1. / (th->Theta * adjoint_time_step), ts->Jacp, PETSC_FALSE));
5701baa6e33SBarry Smith if (quadts) PetscCall(TSComputeRHSJacobianP(quadts, th->stage_time, ts->vec_sol, quadJp));
571abc2977eSBarry Smith for (nadj = 0; nadj < ts->numcost; nadj++) {
5729566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(ts->Jacp, VecsDeltaLam[nadj], VecsDeltaMu[nadj]));
5739566063dSJacob Faibussowitsch PetscCall(VecAXPY(ts->vecs_sensip[nadj], -adjoint_time_step * th->Theta, VecsDeltaMu[nadj]));
5743b711c3fSHong Zhang if (quadJp) {
5759566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumn(quadJp, nadj, &xarr));
5769566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(ts->vec_drdp_col, xarr));
5779566063dSJacob Faibussowitsch PetscCall(VecAXPY(ts->vecs_sensip[nadj], adjoint_time_step * th->Theta, ts->vec_drdp_col));
5789566063dSJacob Faibussowitsch PetscCall(VecResetArray(ts->vec_drdp_col));
5799566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumn(quadJp, &xarr));
5803b711c3fSHong Zhang }
5813fd52205SHong Zhang }
58233f72c5dSHong Zhang if (ts->vecs_sensi2p) { /* second-order */
58333f72c5dSHong Zhang /* Get w1 at t_{n+1} from TLM matrix */
5849566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumn(ts->mat_sensip, 0, &xarr));
5859566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(ts->vec_sensip_col, xarr));
586b5b4017aSHong Zhang /* lambda_s^T F_PU w_1 */
5879566063dSJacob Faibussowitsch PetscCall(TSComputeIHessianProductFunctionPU(ts, th->stage_time, ts->vec_sol, VecsDeltaLam, ts->vec_sensip_col, ts->vecs_fpu));
5889566063dSJacob Faibussowitsch PetscCall(VecResetArray(ts->vec_sensip_col));
5899566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumn(ts->mat_sensip, &xarr));
59033f72c5dSHong Zhang
591b5b4017aSHong Zhang /* lambda_s^T F_PP w_2 */
5929566063dSJacob Faibussowitsch PetscCall(TSComputeIHessianProductFunctionPP(ts, th->stage_time, ts->vec_sol, VecsDeltaLam, ts->vec_dir, ts->vecs_fpp));
593b5b4017aSHong Zhang for (nadj = 0; nadj < ts->numcost; nadj++) {
59433f72c5dSHong Zhang /* Mu2 <- Mu2 + h theta F_P^T Lambda_s + h theta (lambda_s^T F_UU w_1 + lambda_s^T F_UP w_2) */
5959566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(ts->Jacp, VecsDeltaLam2[nadj], VecsDeltaMu2[nadj]));
5969566063dSJacob Faibussowitsch PetscCall(VecAXPY(ts->vecs_sensi2p[nadj], -adjoint_time_step * th->Theta, VecsDeltaMu2[nadj]));
59748a46eb9SPierre Jolivet if (ts->vecs_fpu) PetscCall(VecAXPY(ts->vecs_sensi2p[nadj], -adjoint_time_step * th->Theta, ts->vecs_fpu[nadj]));
59848a46eb9SPierre Jolivet if (ts->vecs_fpp) PetscCall(VecAXPY(ts->vecs_sensi2p[nadj], -adjoint_time_step * th->Theta, ts->vecs_fpp[nadj]));
599b5b4017aSHong Zhang }
600b5b4017aSHong Zhang }
601b5b4017aSHong Zhang
602b5b4017aSHong Zhang /* U_s */
6039566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(th->Xdot));
6049566063dSJacob Faibussowitsch PetscCall(TSComputeIJacobianP(ts, adjoint_ptime, th->X0, th->Xdot, 1. / ((th->Theta - 1.0) * adjoint_time_step), ts->Jacp, PETSC_FALSE));
6051baa6e33SBarry Smith if (quadts) PetscCall(TSComputeRHSJacobianP(quadts, adjoint_ptime, th->X0, quadJp));
606abc2977eSBarry Smith for (nadj = 0; nadj < ts->numcost; nadj++) {
6079566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(ts->Jacp, VecsDeltaLam[nadj], VecsDeltaMu[nadj]));
6089566063dSJacob Faibussowitsch PetscCall(VecAXPY(ts->vecs_sensip[nadj], -adjoint_time_step * (1.0 - th->Theta), VecsDeltaMu[nadj]));
6093b711c3fSHong Zhang if (quadJp) {
6109566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumn(quadJp, nadj, &xarr));
6119566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(ts->vec_drdp_col, xarr));
6129566063dSJacob Faibussowitsch PetscCall(VecAXPY(ts->vecs_sensip[nadj], adjoint_time_step * (1.0 - th->Theta), ts->vec_drdp_col));
6139566063dSJacob Faibussowitsch PetscCall(VecResetArray(ts->vec_drdp_col));
6149566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumn(quadJp, &xarr));
6153b711c3fSHong Zhang }
61633f72c5dSHong Zhang if (ts->vecs_sensi2p) { /* second-order */
61733f72c5dSHong Zhang /* Get w1 at t_n from TLM matrix */
6189566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumn(th->MatFwdSensip0, 0, &xarr));
6199566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(ts->vec_sensip_col, xarr));
620b5b4017aSHong Zhang /* lambda_s^T F_PU w_1 */
6219566063dSJacob Faibussowitsch PetscCall(TSComputeIHessianProductFunctionPU(ts, adjoint_ptime, th->X0, VecsDeltaLam, ts->vec_sensip_col, ts->vecs_fpu));
6229566063dSJacob Faibussowitsch PetscCall(VecResetArray(ts->vec_sensip_col));
6239566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumn(th->MatFwdSensip0, &xarr));
624b5b4017aSHong Zhang /* lambda_s^T F_PP w_2 */
6259566063dSJacob Faibussowitsch PetscCall(TSComputeIHessianProductFunctionPP(ts, adjoint_ptime, th->X0, VecsDeltaLam, ts->vec_dir, ts->vecs_fpp));
626b5b4017aSHong Zhang for (nadj = 0; nadj < ts->numcost; nadj++) {
62733f72c5dSHong Zhang /* Mu2 <- Mu2 + h(1-theta) F_P^T Lambda_s + h(1-theta) (lambda_s^T F_UU w_1 + lambda_s^T F_UP w_2) */
6289566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(ts->Jacp, VecsDeltaLam2[nadj], VecsDeltaMu2[nadj]));
6299566063dSJacob Faibussowitsch PetscCall(VecAXPY(ts->vecs_sensi2p[nadj], -adjoint_time_step * (1.0 - th->Theta), VecsDeltaMu2[nadj]));
63048a46eb9SPierre Jolivet if (ts->vecs_fpu) PetscCall(VecAXPY(ts->vecs_sensi2p[nadj], -adjoint_time_step * (1.0 - th->Theta), ts->vecs_fpu[nadj]));
63148a46eb9SPierre Jolivet if (ts->vecs_fpp) PetscCall(VecAXPY(ts->vecs_sensi2p[nadj], -adjoint_time_step * (1.0 - th->Theta), ts->vecs_fpp[nadj]));
63236eaed60SHong Zhang }
63336eaed60SHong Zhang }
6343fd52205SHong Zhang }
635b5e0532dSHong Zhang }
6363fd52205SHong Zhang } else { /* one-stage case */
6373e05ceb1SHong Zhang th->shift = 0.0;
6389566063dSJacob Faibussowitsch PetscCall(TSComputeSNESJacobian(ts, th->X, J, Jpre)); /* get -f_y */
6399566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(ksp, J, Jpre));
6401baa6e33SBarry Smith if (quadts) PetscCall(TSComputeRHSJacobian(quadts, th->stage_time, th->X, quadJ, NULL));
641abc2977eSBarry Smith for (nadj = 0; nadj < ts->numcost; nadj++) {
6429566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(J, VecsDeltaLam[nadj], VecsSensiTemp[nadj]));
6439566063dSJacob Faibussowitsch PetscCall(VecAXPY(ts->vecs_sensi[nadj], -adjoint_time_step, VecsSensiTemp[nadj]));
644cd4cee2dSHong Zhang if (quadJ) {
6459566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumn(quadJ, nadj, &xarr));
6469566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(ts->vec_drdu_col, xarr));
6479566063dSJacob Faibussowitsch PetscCall(VecAXPY(ts->vecs_sensi[nadj], adjoint_time_step, ts->vec_drdu_col));
6489566063dSJacob Faibussowitsch PetscCall(VecResetArray(ts->vec_drdu_col));
6499566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumn(quadJ, &xarr));
65036eaed60SHong Zhang }
6512ca6e920SHong Zhang }
6523fd52205SHong Zhang if (ts->vecs_sensip) {
65382ad9101SHong Zhang th->shift = 1.0 / (adjoint_time_step * th->Theta);
6549566063dSJacob Faibussowitsch PetscCall(VecAXPBYPCZ(th->Xdot, -th->shift, th->shift, 0, th->X0, th->X));
6559566063dSJacob Faibussowitsch PetscCall(TSComputeIJacobianP(ts, th->stage_time, th->X, th->Xdot, th->shift, ts->Jacp, PETSC_FALSE));
6561baa6e33SBarry Smith if (quadts) PetscCall(TSComputeRHSJacobianP(quadts, th->stage_time, th->X, quadJp));
657abc2977eSBarry Smith for (nadj = 0; nadj < ts->numcost; nadj++) {
6589566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(ts->Jacp, VecsDeltaLam[nadj], VecsDeltaMu[nadj]));
6599566063dSJacob Faibussowitsch PetscCall(VecAXPY(ts->vecs_sensip[nadj], -adjoint_time_step, VecsDeltaMu[nadj]));
660cd4cee2dSHong Zhang if (quadJp) {
6619566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumn(quadJp, nadj, &xarr));
6629566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(ts->vec_drdp_col, xarr));
6639566063dSJacob Faibussowitsch PetscCall(VecAXPY(ts->vecs_sensip[nadj], adjoint_time_step, ts->vec_drdp_col));
6649566063dSJacob Faibussowitsch PetscCall(VecResetArray(ts->vec_drdp_col));
6659566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumn(quadJp, &xarr));
66636eaed60SHong Zhang }
66736eaed60SHong Zhang }
6683fd52205SHong Zhang }
6692ca6e920SHong Zhang }
6702ca6e920SHong Zhang
6712ca6e920SHong Zhang th->status = TS_STEP_COMPLETE;
6723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
6732ca6e920SHong Zhang }
6742ca6e920SHong Zhang
TSInterpolate_Theta(TS ts,PetscReal t,Vec X)675d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSInterpolate_Theta(TS ts, PetscReal t, Vec X)
676d71ae5a4SJacob Faibussowitsch {
677cd652676SJed Brown TS_Theta *th = (TS_Theta *)ts->data;
678be5899b3SLisandro Dalcin PetscReal dt = t - ts->ptime;
679cd652676SJed Brown
680cd652676SJed Brown PetscFunctionBegin;
6819566063dSJacob Faibussowitsch PetscCall(VecCopy(ts->vec_sol, th->X));
682be5899b3SLisandro Dalcin if (th->endpoint) dt *= th->Theta;
6839566063dSJacob Faibussowitsch PetscCall(VecWAXPY(X, dt, th->Xdot, th->X));
6843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
685cd652676SJed Brown }
686cd652676SJed Brown
TSEvaluateWLTE_Theta(TS ts,NormType wnormtype,PetscInt * order,PetscReal * wlte)687d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSEvaluateWLTE_Theta(TS ts, NormType wnormtype, PetscInt *order, PetscReal *wlte)
688d71ae5a4SJacob Faibussowitsch {
6891566a47fSLisandro Dalcin TS_Theta *th = (TS_Theta *)ts->data;
6901566a47fSLisandro Dalcin Vec X = ts->vec_sol; /* X = solution */
6911566a47fSLisandro Dalcin Vec Y = th->vec_lte_work; /* Y = X + LTE */
6927453f775SEmil Constantinescu PetscReal wltea, wlter;
6931566a47fSLisandro Dalcin
6941566a47fSLisandro Dalcin PetscFunctionBegin;
6959371c9d4SSatish Balay if (!th->vec_sol_prev) {
6969371c9d4SSatish Balay *wlte = -1;
6973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
6989371c9d4SSatish Balay }
6991566a47fSLisandro Dalcin /* Cannot compute LTE in first step or in restart after event */
7009371c9d4SSatish Balay if (ts->steprestart) {
7019371c9d4SSatish Balay *wlte = -1;
7023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
7039371c9d4SSatish Balay }
7041566a47fSLisandro Dalcin /* Compute LTE using backward differences with non-constant time step */
705fecfb714SLisandro Dalcin {
706be5899b3SLisandro Dalcin PetscReal h = ts->time_step, h_prev = ts->ptime - ts->ptime_prev;
707be5899b3SLisandro Dalcin PetscReal a = 1 + h_prev / h;
7089371c9d4SSatish Balay PetscScalar scal[3];
7099371c9d4SSatish Balay Vec vecs[3];
71052f13ae7SStefano Zampini
711225f7d0bSStefano Zampini scal[0] = -1 / a;
712225f7d0bSStefano Zampini scal[1] = +1 / (a - 1);
713225f7d0bSStefano Zampini scal[2] = -1 / (a * (a - 1));
7149371c9d4SSatish Balay vecs[0] = X;
7159371c9d4SSatish Balay vecs[1] = th->X0;
7169371c9d4SSatish Balay vecs[2] = th->vec_sol_prev;
7179566063dSJacob Faibussowitsch PetscCall(VecCopy(X, Y));
7189566063dSJacob Faibussowitsch PetscCall(VecMAXPY(Y, 3, scal, vecs));
7199566063dSJacob Faibussowitsch PetscCall(TSErrorWeightedNorm(ts, X, Y, wnormtype, wlte, &wltea, &wlter));
7201566a47fSLisandro Dalcin }
7211566a47fSLisandro Dalcin if (order) *order = 2;
7223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
7231566a47fSLisandro Dalcin }
7241566a47fSLisandro Dalcin
TSRollBack_Theta(TS ts)725d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSRollBack_Theta(TS ts)
726d71ae5a4SJacob Faibussowitsch {
7271566a47fSLisandro Dalcin TS_Theta *th = (TS_Theta *)ts->data;
7287207e0fdSHong Zhang TS quadts = ts->quadraturets;
7291566a47fSLisandro Dalcin
7301566a47fSLisandro Dalcin PetscFunctionBegin;
73148a46eb9SPierre Jolivet if (quadts && ts->costintegralfwd) PetscCall(VecCopy(th->VecCostIntegral0, quadts->vec_sol));
732715f1b00SHong Zhang th->status = TS_STEP_INCOMPLETE;
7331baa6e33SBarry Smith if (ts->mat_sensip) PetscCall(MatCopy(th->MatFwdSensip0, ts->mat_sensip, SAME_NONZERO_PATTERN));
73448a46eb9SPierre Jolivet if (quadts && quadts->mat_sensip) PetscCall(MatCopy(th->MatIntegralSensip0, quadts->mat_sensip, SAME_NONZERO_PATTERN));
7353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
736715f1b00SHong Zhang }
737715f1b00SHong Zhang
TSForwardStep_Theta(TS ts)738d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSForwardStep_Theta(TS ts)
739d71ae5a4SJacob Faibussowitsch {
740715f1b00SHong Zhang TS_Theta *th = (TS_Theta *)ts->data;
741cd4cee2dSHong Zhang TS quadts = ts->quadraturets;
74213b1b0ffSHong Zhang Mat MatDeltaFwdSensip = th->MatDeltaFwdSensip;
743b5b4017aSHong Zhang Vec VecDeltaFwdSensipCol = th->VecDeltaFwdSensipCol;
7447207e0fdSHong Zhang PetscInt ntlm;
745715f1b00SHong Zhang KSP ksp;
7467207e0fdSHong Zhang Mat J, Jpre, quadJ = NULL, quadJp = NULL;
74713b1b0ffSHong Zhang PetscScalar *barr, *xarr;
7481a352fa8SHong Zhang PetscReal previous_shift;
749715f1b00SHong Zhang
750715f1b00SHong Zhang PetscFunctionBegin;
7511a352fa8SHong Zhang previous_shift = th->shift;
7529566063dSJacob Faibussowitsch PetscCall(MatCopy(ts->mat_sensip, th->MatFwdSensip0, SAME_NONZERO_PATTERN));
75313b1b0ffSHong Zhang
75448a46eb9SPierre Jolivet if (quadts && quadts->mat_sensip) PetscCall(MatCopy(quadts->mat_sensip, th->MatIntegralSensip0, SAME_NONZERO_PATTERN));
7559566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(ts->snes, &ksp));
7569566063dSJacob Faibussowitsch PetscCall(TSGetIJacobian(ts, &J, &Jpre, NULL, NULL));
7577207e0fdSHong Zhang if (quadts) {
7589566063dSJacob Faibussowitsch PetscCall(TSGetRHSJacobian(quadts, &quadJ, NULL, NULL, NULL));
7599566063dSJacob Faibussowitsch PetscCall(TSGetRHSJacobianP(quadts, &quadJp, NULL, NULL));
7607207e0fdSHong Zhang }
761715f1b00SHong Zhang
762715f1b00SHong Zhang /* Build RHS */
763715f1b00SHong Zhang if (th->endpoint) { /* 2-stage method*/
7641a352fa8SHong Zhang th->shift = 1. / ((th->Theta - 1.) * th->time_step0);
7659566063dSJacob Faibussowitsch PetscCall(TSComputeIJacobian(ts, th->ptime0, th->X0, th->Xdot, th->shift, J, Jpre, PETSC_FALSE));
766fb842aefSJose E. Roman PetscCall(MatMatMult(J, ts->mat_sensip, MAT_REUSE_MATRIX, PETSC_DETERMINE, &MatDeltaFwdSensip));
7679566063dSJacob Faibussowitsch PetscCall(MatScale(MatDeltaFwdSensip, (th->Theta - 1.) / th->Theta));
768715f1b00SHong Zhang
769022c081aSHong Zhang /* Add the f_p forcing terms */
7700e11c21fSHong Zhang if (ts->Jacp) {
7719566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(th->Xdot));
7729566063dSJacob Faibussowitsch PetscCall(TSComputeIJacobianP(ts, th->ptime0, th->X0, th->Xdot, th->shift, ts->Jacp, PETSC_FALSE));
7739566063dSJacob Faibussowitsch PetscCall(MatAXPY(MatDeltaFwdSensip, (th->Theta - 1.) / th->Theta, ts->Jacp, SUBSET_NONZERO_PATTERN));
77482ad9101SHong Zhang th->shift = previous_shift;
7759566063dSJacob Faibussowitsch PetscCall(VecAXPBYPCZ(th->Xdot, -th->shift, th->shift, 0, th->X0, ts->vec_sol));
7769566063dSJacob Faibussowitsch PetscCall(TSComputeIJacobianP(ts, th->stage_time, ts->vec_sol, th->Xdot, th->shift, ts->Jacp, PETSC_FALSE));
7779566063dSJacob Faibussowitsch PetscCall(MatAXPY(MatDeltaFwdSensip, -1., ts->Jacp, SUBSET_NONZERO_PATTERN));
7780e11c21fSHong Zhang }
779715f1b00SHong Zhang } else { /* 1-stage method */
7803e05ceb1SHong Zhang th->shift = 0.0;
7819566063dSJacob Faibussowitsch PetscCall(TSComputeIJacobian(ts, th->stage_time, th->X, th->Xdot, th->shift, J, Jpre, PETSC_FALSE));
782fb842aefSJose E. Roman PetscCall(MatMatMult(J, ts->mat_sensip, MAT_REUSE_MATRIX, PETSC_DETERMINE, &MatDeltaFwdSensip));
7839566063dSJacob Faibussowitsch PetscCall(MatScale(MatDeltaFwdSensip, -1.));
78413b1b0ffSHong Zhang
785022c081aSHong Zhang /* Add the f_p forcing terms */
7860e11c21fSHong Zhang if (ts->Jacp) {
78782ad9101SHong Zhang th->shift = previous_shift;
7889566063dSJacob Faibussowitsch PetscCall(VecAXPBYPCZ(th->Xdot, -th->shift, th->shift, 0, th->X0, th->X));
7899566063dSJacob Faibussowitsch PetscCall(TSComputeIJacobianP(ts, th->stage_time, th->X, th->Xdot, th->shift, ts->Jacp, PETSC_FALSE));
7909566063dSJacob Faibussowitsch PetscCall(MatAXPY(MatDeltaFwdSensip, -1., ts->Jacp, SUBSET_NONZERO_PATTERN));
791715f1b00SHong Zhang }
7920e11c21fSHong Zhang }
793715f1b00SHong Zhang
794715f1b00SHong Zhang /* Build LHS */
7951a352fa8SHong Zhang th->shift = previous_shift; /* recover the previous shift used in TSStep_Theta() */
796715f1b00SHong Zhang if (th->endpoint) {
7979566063dSJacob Faibussowitsch PetscCall(TSComputeIJacobian(ts, th->stage_time, ts->vec_sol, th->Xdot, th->shift, J, Jpre, PETSC_FALSE));
798715f1b00SHong Zhang } else {
7999566063dSJacob Faibussowitsch PetscCall(TSComputeIJacobian(ts, th->stage_time, th->X, th->Xdot, th->shift, J, Jpre, PETSC_FALSE));
800715f1b00SHong Zhang }
8019566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(ksp, J, Jpre));
802715f1b00SHong Zhang
803715f1b00SHong Zhang /*
804715f1b00SHong Zhang Evaluate the first stage of integral gradients with the 2-stage method:
805c9ad9de0SHong Zhang drdu|t_n*S(t_n) + drdp|t_n
806715f1b00SHong Zhang This is done before the linear solve because the sensitivity variable S(t_n) will be propagated to S(t_{n+1})
807715f1b00SHong Zhang */
808715f1b00SHong Zhang if (th->endpoint) { /* 2-stage method only */
8097207e0fdSHong Zhang if (quadts && quadts->mat_sensip) {
8109566063dSJacob Faibussowitsch PetscCall(TSComputeRHSJacobian(quadts, th->ptime0, th->X0, quadJ, NULL));
8119566063dSJacob Faibussowitsch PetscCall(TSComputeRHSJacobianP(quadts, th->ptime0, th->X0, quadJp));
812fb842aefSJose E. Roman PetscCall(MatTransposeMatMult(ts->mat_sensip, quadJ, MAT_REUSE_MATRIX, PETSC_DETERMINE, &th->MatIntegralSensipTemp));
8139566063dSJacob Faibussowitsch PetscCall(MatAXPY(th->MatIntegralSensipTemp, 1, quadJp, SAME_NONZERO_PATTERN));
8149566063dSJacob Faibussowitsch PetscCall(MatAXPY(quadts->mat_sensip, th->time_step0 * (1. - th->Theta), th->MatIntegralSensipTemp, SAME_NONZERO_PATTERN));
815715f1b00SHong Zhang }
816715f1b00SHong Zhang }
817715f1b00SHong Zhang
818715f1b00SHong Zhang /* Solve the tangent linear equation for forward sensitivities to parameters */
819022c081aSHong Zhang for (ntlm = 0; ntlm < th->num_tlm; ntlm++) {
820b5b4017aSHong Zhang KSPConvergedReason kspreason;
8219566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumn(MatDeltaFwdSensip, ntlm, &barr));
8229566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(VecDeltaFwdSensipCol, barr));
823715f1b00SHong Zhang if (th->endpoint) {
8249566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumn(ts->mat_sensip, ntlm, &xarr));
8259566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(ts->vec_sensip_col, xarr));
8269566063dSJacob Faibussowitsch PetscCall(KSPSolve(ksp, VecDeltaFwdSensipCol, ts->vec_sensip_col));
8279566063dSJacob Faibussowitsch PetscCall(VecResetArray(ts->vec_sensip_col));
8289566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumn(ts->mat_sensip, &xarr));
829715f1b00SHong Zhang } else {
8309566063dSJacob Faibussowitsch PetscCall(KSPSolve(ksp, VecDeltaFwdSensipCol, VecDeltaFwdSensipCol));
831715f1b00SHong Zhang }
8329566063dSJacob Faibussowitsch PetscCall(KSPGetConvergedReason(ksp, &kspreason));
833b5b4017aSHong Zhang if (kspreason < 0) {
834b5b4017aSHong Zhang ts->reason = TSFORWARD_DIVERGED_LINEAR_SOLVE;
83563a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(ts, "Step=%" PetscInt_FMT ", %" PetscInt_FMT "th tangent linear solve, linear solve fails, stopping tangent linear solve\n", ts->steps, ntlm));
836b5b4017aSHong Zhang }
8379566063dSJacob Faibussowitsch PetscCall(VecResetArray(VecDeltaFwdSensipCol));
8389566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumn(MatDeltaFwdSensip, &barr));
839715f1b00SHong Zhang }
840715f1b00SHong Zhang
84113b1b0ffSHong Zhang /*
84213b1b0ffSHong Zhang Evaluate the second stage of integral gradients with the 2-stage method:
843c9ad9de0SHong Zhang drdu|t_{n+1}*S(t_{n+1}) + drdp|t_{n+1}
84413b1b0ffSHong Zhang */
8457207e0fdSHong Zhang if (quadts && quadts->mat_sensip) {
84613b1b0ffSHong Zhang if (!th->endpoint) {
8479566063dSJacob Faibussowitsch PetscCall(MatAXPY(ts->mat_sensip, 1, MatDeltaFwdSensip, SAME_NONZERO_PATTERN)); /* stage sensitivity */
8489566063dSJacob Faibussowitsch PetscCall(TSComputeRHSJacobian(quadts, th->stage_time, th->X, quadJ, NULL));
8499566063dSJacob Faibussowitsch PetscCall(TSComputeRHSJacobianP(quadts, th->stage_time, th->X, quadJp));
850fb842aefSJose E. Roman PetscCall(MatTransposeMatMult(ts->mat_sensip, quadJ, MAT_REUSE_MATRIX, PETSC_DETERMINE, &th->MatIntegralSensipTemp));
8519566063dSJacob Faibussowitsch PetscCall(MatAXPY(th->MatIntegralSensipTemp, 1, quadJp, SAME_NONZERO_PATTERN));
8529566063dSJacob Faibussowitsch PetscCall(MatAXPY(quadts->mat_sensip, th->time_step0, th->MatIntegralSensipTemp, SAME_NONZERO_PATTERN));
8539566063dSJacob Faibussowitsch PetscCall(MatAXPY(ts->mat_sensip, (1. - th->Theta) / th->Theta, MatDeltaFwdSensip, SAME_NONZERO_PATTERN));
85413b1b0ffSHong Zhang } else {
8559566063dSJacob Faibussowitsch PetscCall(TSComputeRHSJacobian(quadts, th->stage_time, ts->vec_sol, quadJ, NULL));
8569566063dSJacob Faibussowitsch PetscCall(TSComputeRHSJacobianP(quadts, th->stage_time, ts->vec_sol, quadJp));
857fb842aefSJose E. Roman PetscCall(MatTransposeMatMult(ts->mat_sensip, quadJ, MAT_REUSE_MATRIX, PETSC_DETERMINE, &th->MatIntegralSensipTemp));
8589566063dSJacob Faibussowitsch PetscCall(MatAXPY(th->MatIntegralSensipTemp, 1, quadJp, SAME_NONZERO_PATTERN));
8599566063dSJacob Faibussowitsch PetscCall(MatAXPY(quadts->mat_sensip, th->time_step0 * th->Theta, th->MatIntegralSensipTemp, SAME_NONZERO_PATTERN));
86013b1b0ffSHong Zhang }
86113b1b0ffSHong Zhang } else {
86248a46eb9SPierre Jolivet if (!th->endpoint) PetscCall(MatAXPY(ts->mat_sensip, 1. / th->Theta, MatDeltaFwdSensip, SAME_NONZERO_PATTERN));
863715f1b00SHong Zhang }
8643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
8651566a47fSLisandro Dalcin }
8661566a47fSLisandro Dalcin
TSForwardGetStages_Theta(TS ts,PetscInt * ns,Mat * stagesensip[])867d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSForwardGetStages_Theta(TS ts, PetscInt *ns, Mat *stagesensip[])
868d71ae5a4SJacob Faibussowitsch {
8696affb6f8SHong Zhang TS_Theta *th = (TS_Theta *)ts->data;
8706affb6f8SHong Zhang
8716affb6f8SHong Zhang PetscFunctionBegin;
8727409eceaSHong Zhang if (ns) {
8737409eceaSHong Zhang if (!th->endpoint && th->Theta != 1.0) *ns = 1; /* midpoint form */
8747409eceaSHong Zhang else *ns = 2; /* endpoint form */
8757409eceaSHong Zhang }
8765072d23cSHong Zhang if (stagesensip) {
877cc4f23bcSHong Zhang if (!th->endpoint && th->Theta != 1.0) {
8787409eceaSHong Zhang th->MatFwdStages[0] = th->MatDeltaFwdSensip;
879cc4f23bcSHong Zhang } else {
880cc4f23bcSHong Zhang th->MatFwdStages[0] = th->MatFwdSensip0;
881cc4f23bcSHong Zhang th->MatFwdStages[1] = ts->mat_sensip; /* stiffly accurate */
882cc4f23bcSHong Zhang }
883cc4f23bcSHong Zhang *stagesensip = th->MatFwdStages;
8845072d23cSHong Zhang }
8853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
8866affb6f8SHong Zhang }
8876affb6f8SHong Zhang
TSReset_Theta(TS ts)888d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSReset_Theta(TS ts)
889d71ae5a4SJacob Faibussowitsch {
890316643e7SJed Brown TS_Theta *th = (TS_Theta *)ts->data;
891316643e7SJed Brown
892316643e7SJed Brown PetscFunctionBegin;
8939566063dSJacob Faibussowitsch PetscCall(VecDestroy(&th->X));
8949566063dSJacob Faibussowitsch PetscCall(VecDestroy(&th->Xdot));
8959566063dSJacob Faibussowitsch PetscCall(VecDestroy(&th->X0));
8969566063dSJacob Faibussowitsch PetscCall(VecDestroy(&th->affine));
8971566a47fSLisandro Dalcin
8989566063dSJacob Faibussowitsch PetscCall(VecDestroy(&th->vec_sol_prev));
8999566063dSJacob Faibussowitsch PetscCall(VecDestroy(&th->vec_lte_work));
9001566a47fSLisandro Dalcin
9019566063dSJacob Faibussowitsch PetscCall(VecDestroy(&th->VecCostIntegral0));
9023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
903277b19d0SLisandro Dalcin }
904277b19d0SLisandro Dalcin
TSAdjointReset_Theta(TS ts)905d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSAdjointReset_Theta(TS ts)
906d71ae5a4SJacob Faibussowitsch {
907ece46509SHong Zhang TS_Theta *th = (TS_Theta *)ts->data;
908ece46509SHong Zhang
909ece46509SHong Zhang PetscFunctionBegin;
9109566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(ts->numcost, &th->VecsDeltaLam));
9119566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(ts->numcost, &th->VecsDeltaMu));
9129566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(ts->numcost, &th->VecsDeltaLam2));
9139566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(ts->numcost, &th->VecsDeltaMu2));
9149566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(ts->numcost, &th->VecsSensiTemp));
9159566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(ts->numcost, &th->VecsSensi2Temp));
9163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
917ece46509SHong Zhang }
918ece46509SHong Zhang
TSDestroy_Theta(TS ts)919d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSDestroy_Theta(TS ts)
920d71ae5a4SJacob Faibussowitsch {
921277b19d0SLisandro Dalcin PetscFunctionBegin;
9229566063dSJacob Faibussowitsch PetscCall(TSReset_Theta(ts));
923b3a6b972SJed Brown if (ts->dm) {
9249566063dSJacob Faibussowitsch PetscCall(DMCoarsenHookRemove(ts->dm, DMCoarsenHook_TSTheta, DMRestrictHook_TSTheta, ts));
9259566063dSJacob Faibussowitsch PetscCall(DMSubDomainHookRemove(ts->dm, DMSubDomainHook_TSTheta, DMSubDomainRestrictHook_TSTheta, ts));
926b3a6b972SJed Brown }
9279566063dSJacob Faibussowitsch PetscCall(PetscFree(ts->data));
9289566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSThetaGetTheta_C", NULL));
9299566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSThetaSetTheta_C", NULL));
9309566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSThetaGetEndpoint_C", NULL));
9319566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSThetaSetEndpoint_C", NULL));
9323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
933316643e7SJed Brown }
934316643e7SJed Brown
935316643e7SJed Brown /*
936316643e7SJed Brown This defines the nonlinear equation that is to be solved with SNES
9372b5a38e1SLisandro Dalcin G(U) = F[t0+Theta*dt, U, (U-U0)*shift] = 0
9380fd10508SMatthew Knepley
9390fd10508SMatthew Knepley Note that U here is the stage argument. This means that U = U_{n+1} only if endpoint = true,
9400fd10508SMatthew Knepley otherwise U = theta U_{n+1} + (1 - theta) U0, which for the case of implicit midpoint is
9410fd10508SMatthew Knepley U = (U_{n+1} + U0)/2
942316643e7SJed Brown */
SNESTSFormFunction_Theta(SNES snes,Vec x,Vec y,TS ts)943d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESTSFormFunction_Theta(SNES snes, Vec x, Vec y, TS ts)
944d71ae5a4SJacob Faibussowitsch {
945316643e7SJed Brown TS_Theta *th = (TS_Theta *)ts->data;
9467445fe48SJed Brown Vec X0, Xdot;
9477445fe48SJed Brown DM dm, dmsave;
9483e05ceb1SHong Zhang PetscReal shift = th->shift;
949316643e7SJed Brown
950316643e7SJed Brown PetscFunctionBegin;
9519566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm));
9525a3a76d0SJed Brown /* When using the endpoint variant, this is actually 1/Theta * Xdot */
9539566063dSJacob Faibussowitsch PetscCall(TSThetaGetX0AndXdot(ts, dm, &X0, &Xdot));
954494ce9fcSHong Zhang if (x != X0) {
9559566063dSJacob Faibussowitsch PetscCall(VecAXPBYPCZ(Xdot, -shift, shift, 0, X0, x));
956494ce9fcSHong Zhang } else {
9579566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(Xdot));
958494ce9fcSHong Zhang }
9597445fe48SJed Brown /* DM monkey-business allows user code to call TSGetDM() inside of functions evaluated on levels of FAS */
9607445fe48SJed Brown dmsave = ts->dm;
9617445fe48SJed Brown ts->dm = dm;
9629566063dSJacob Faibussowitsch PetscCall(TSComputeIFunction(ts, th->stage_time, x, Xdot, y, PETSC_FALSE));
9637445fe48SJed Brown ts->dm = dmsave;
9649566063dSJacob Faibussowitsch PetscCall(TSThetaRestoreX0AndXdot(ts, dm, &X0, &Xdot));
9653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
966316643e7SJed Brown }
967316643e7SJed Brown
SNESTSFormJacobian_Theta(SNES snes,Vec x,Mat A,Mat B,TS ts)968d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESTSFormJacobian_Theta(SNES snes, Vec x, Mat A, Mat B, TS ts)
969d71ae5a4SJacob Faibussowitsch {
970316643e7SJed Brown TS_Theta *th = (TS_Theta *)ts->data;
9717445fe48SJed Brown Vec Xdot;
9727445fe48SJed Brown DM dm, dmsave;
9733e05ceb1SHong Zhang PetscReal shift = th->shift;
974316643e7SJed Brown
975316643e7SJed Brown PetscFunctionBegin;
9769566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm));
977be5899b3SLisandro Dalcin /* Xdot has already been computed in SNESTSFormFunction_Theta (SNES guarantees this) */
9789566063dSJacob Faibussowitsch PetscCall(TSThetaGetX0AndXdot(ts, dm, NULL, &Xdot));
9797445fe48SJed Brown
9807445fe48SJed Brown dmsave = ts->dm;
9817445fe48SJed Brown ts->dm = dm;
9829566063dSJacob Faibussowitsch PetscCall(TSComputeIJacobian(ts, th->stage_time, x, Xdot, shift, A, B, PETSC_FALSE));
9837445fe48SJed Brown ts->dm = dmsave;
9849566063dSJacob Faibussowitsch PetscCall(TSThetaRestoreX0AndXdot(ts, dm, NULL, &Xdot));
9853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
986316643e7SJed Brown }
987316643e7SJed Brown
TSForwardSetUp_Theta(TS ts)988d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSForwardSetUp_Theta(TS ts)
989d71ae5a4SJacob Faibussowitsch {
990715f1b00SHong Zhang TS_Theta *th = (TS_Theta *)ts->data;
9917207e0fdSHong Zhang TS quadts = ts->quadraturets;
992715f1b00SHong Zhang
993715f1b00SHong Zhang PetscFunctionBegin;
994022c081aSHong Zhang /* combine sensitivities to parameters and sensitivities to initial values into one array */
99513b1b0ffSHong Zhang th->num_tlm = ts->num_parameters;
9969566063dSJacob Faibussowitsch PetscCall(MatDuplicate(ts->mat_sensip, MAT_DO_NOT_COPY_VALUES, &th->MatDeltaFwdSensip));
9977207e0fdSHong Zhang if (quadts && quadts->mat_sensip) {
9989566063dSJacob Faibussowitsch PetscCall(MatDuplicate(quadts->mat_sensip, MAT_DO_NOT_COPY_VALUES, &th->MatIntegralSensipTemp));
9999566063dSJacob Faibussowitsch PetscCall(MatDuplicate(quadts->mat_sensip, MAT_DO_NOT_COPY_VALUES, &th->MatIntegralSensip0));
1000715f1b00SHong Zhang }
10016f92202bSHong Zhang /* backup sensitivity results for roll-backs */
10029566063dSJacob Faibussowitsch PetscCall(MatDuplicate(ts->mat_sensip, MAT_DO_NOT_COPY_VALUES, &th->MatFwdSensip0));
100313b1b0ffSHong Zhang
10049566063dSJacob Faibussowitsch PetscCall(VecDuplicate(ts->vec_sol, &th->VecDeltaFwdSensipCol));
10053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1006715f1b00SHong Zhang }
1007715f1b00SHong Zhang
TSForwardReset_Theta(TS ts)1008d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSForwardReset_Theta(TS ts)
1009d71ae5a4SJacob Faibussowitsch {
10107adebddeSHong Zhang TS_Theta *th = (TS_Theta *)ts->data;
10117207e0fdSHong Zhang TS quadts = ts->quadraturets;
10127adebddeSHong Zhang
10137adebddeSHong Zhang PetscFunctionBegin;
10147207e0fdSHong Zhang if (quadts && quadts->mat_sensip) {
10159566063dSJacob Faibussowitsch PetscCall(MatDestroy(&th->MatIntegralSensipTemp));
10169566063dSJacob Faibussowitsch PetscCall(MatDestroy(&th->MatIntegralSensip0));
10177adebddeSHong Zhang }
10189566063dSJacob Faibussowitsch PetscCall(VecDestroy(&th->VecDeltaFwdSensipCol));
10199566063dSJacob Faibussowitsch PetscCall(MatDestroy(&th->MatDeltaFwdSensip));
10209566063dSJacob Faibussowitsch PetscCall(MatDestroy(&th->MatFwdSensip0));
10213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
10227adebddeSHong Zhang }
10237adebddeSHong Zhang
TSSetUp_Theta(TS ts)1024d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSSetUp_Theta(TS ts)
1025d71ae5a4SJacob Faibussowitsch {
1026316643e7SJed Brown TS_Theta *th = (TS_Theta *)ts->data;
1027cd4cee2dSHong Zhang TS quadts = ts->quadraturets;
10282ffb9264SLisandro Dalcin PetscBool match;
1029316643e7SJed Brown
1030316643e7SJed Brown PetscFunctionBegin;
1031cd4cee2dSHong Zhang if (!th->VecCostIntegral0 && quadts && ts->costintegralfwd) { /* back up cost integral */
10329566063dSJacob Faibussowitsch PetscCall(VecDuplicate(quadts->vec_sol, &th->VecCostIntegral0));
1033b1cb36f3SHong Zhang }
103448a46eb9SPierre Jolivet if (!th->X) PetscCall(VecDuplicate(ts->vec_sol, &th->X));
103548a46eb9SPierre Jolivet if (!th->Xdot) PetscCall(VecDuplicate(ts->vec_sol, &th->Xdot));
103648a46eb9SPierre Jolivet if (!th->X0) PetscCall(VecDuplicate(ts->vec_sol, &th->X0));
103748a46eb9SPierre Jolivet if (th->endpoint) PetscCall(VecDuplicate(ts->vec_sol, &th->affine));
10383b1890cdSShri Abhyankar
10391566a47fSLisandro Dalcin th->order = (th->Theta == 0.5) ? 2 : 1;
104020d49056SMatthew G. Knepley th->shift = 1 / (th->Theta * ts->time_step);
10411566a47fSLisandro Dalcin
10429566063dSJacob Faibussowitsch PetscCall(TSGetDM(ts, &ts->dm));
10439566063dSJacob Faibussowitsch PetscCall(DMCoarsenHookAdd(ts->dm, DMCoarsenHook_TSTheta, DMRestrictHook_TSTheta, ts));
10449566063dSJacob Faibussowitsch PetscCall(DMSubDomainHookAdd(ts->dm, DMSubDomainHook_TSTheta, DMSubDomainRestrictHook_TSTheta, ts));
10451566a47fSLisandro Dalcin
10469566063dSJacob Faibussowitsch PetscCall(TSGetAdapt(ts, &ts->adapt));
10479566063dSJacob Faibussowitsch PetscCall(TSAdaptCandidatesClear(ts->adapt));
10489566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)ts->adapt, TSADAPTNONE, &match));
10492ffb9264SLisandro Dalcin if (!match) {
1050ecc87898SStefano Zampini if (!th->vec_sol_prev) PetscCall(VecDuplicate(ts->vec_sol, &th->vec_sol_prev));
1051ecc87898SStefano Zampini if (!th->vec_lte_work) PetscCall(VecDuplicate(ts->vec_sol, &th->vec_lte_work));
10523b1890cdSShri Abhyankar }
10539566063dSJacob Faibussowitsch PetscCall(TSGetSNES(ts, &ts->snes));
1054cc4f23bcSHong Zhang
1055cc4f23bcSHong Zhang ts->stifflyaccurate = (!th->endpoint && th->Theta != 1.0) ? PETSC_FALSE : PETSC_TRUE;
10563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1057b4dd3bf9SBarry Smith }
10580c7376e5SHong Zhang
TSAdjointSetUp_Theta(TS ts)1059d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSAdjointSetUp_Theta(TS ts)
1060d71ae5a4SJacob Faibussowitsch {
1061b4dd3bf9SBarry Smith TS_Theta *th = (TS_Theta *)ts->data;
1062b4dd3bf9SBarry Smith
1063b4dd3bf9SBarry Smith PetscFunctionBegin;
10649566063dSJacob Faibussowitsch PetscCall(VecDuplicateVecs(ts->vecs_sensi[0], ts->numcost, &th->VecsDeltaLam));
10659566063dSJacob Faibussowitsch PetscCall(VecDuplicateVecs(ts->vecs_sensi[0], ts->numcost, &th->VecsSensiTemp));
106648a46eb9SPierre Jolivet if (ts->vecs_sensip) PetscCall(VecDuplicateVecs(ts->vecs_sensip[0], ts->numcost, &th->VecsDeltaMu));
1067b5b4017aSHong Zhang if (ts->vecs_sensi2) {
10689566063dSJacob Faibussowitsch PetscCall(VecDuplicateVecs(ts->vecs_sensi[0], ts->numcost, &th->VecsDeltaLam2));
10699566063dSJacob Faibussowitsch PetscCall(VecDuplicateVecs(ts->vecs_sensi2[0], ts->numcost, &th->VecsSensi2Temp));
107067633408SHong Zhang /* hack ts to make implicit TS solver work when users provide only explicit versions of callbacks (RHSFunction,RHSJacobian,RHSHessian etc.) */
107167633408SHong Zhang if (!ts->ihessianproduct_fuu) ts->vecs_fuu = ts->vecs_guu;
107267633408SHong Zhang if (!ts->ihessianproduct_fup) ts->vecs_fup = ts->vecs_gup;
1073b5b4017aSHong Zhang }
1074c9681e5dSHong Zhang if (ts->vecs_sensi2p) {
10759566063dSJacob Faibussowitsch PetscCall(VecDuplicateVecs(ts->vecs_sensi2p[0], ts->numcost, &th->VecsDeltaMu2));
107667633408SHong Zhang /* hack ts to make implicit TS solver work when users provide only explicit versions of callbacks (RHSFunction,RHSJacobian,RHSHessian etc.) */
107767633408SHong Zhang if (!ts->ihessianproduct_fpu) ts->vecs_fpu = ts->vecs_gpu;
107867633408SHong Zhang if (!ts->ihessianproduct_fpp) ts->vecs_fpp = ts->vecs_gpp;
1079b5b4017aSHong Zhang }
10803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1081316643e7SJed Brown }
1082316643e7SJed Brown
TSSetFromOptions_Theta(TS ts,PetscOptionItems PetscOptionsObject)1083ce78bad3SBarry Smith static PetscErrorCode TSSetFromOptions_Theta(TS ts, PetscOptionItems PetscOptionsObject)
1084d71ae5a4SJacob Faibussowitsch {
1085316643e7SJed Brown TS_Theta *th = (TS_Theta *)ts->data;
1086316643e7SJed Brown
1087316643e7SJed Brown PetscFunctionBegin;
1088d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "Theta ODE solver options");
1089316643e7SJed Brown {
10909566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-ts_theta_theta", "Location of stage (0<Theta<=1)", "TSThetaSetTheta", th->Theta, &th->Theta, NULL));
10919566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-ts_theta_endpoint", "Use the endpoint instead of midpoint form of the Theta method", "TSThetaSetEndpoint", th->endpoint, &th->endpoint, NULL));
10929566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-ts_theta_initial_guess_extrapolate", "Extrapolate stage initial guess from previous solution (sometimes unstable)", "TSThetaSetExtrapolate", th->extrapolate, &th->extrapolate, NULL));
1093316643e7SJed Brown }
1094d0609cedSBarry Smith PetscOptionsHeadEnd();
10953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1096316643e7SJed Brown }
1097316643e7SJed Brown
TSView_Theta(TS ts,PetscViewer viewer)1098d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSView_Theta(TS ts, PetscViewer viewer)
1099d71ae5a4SJacob Faibussowitsch {
1100316643e7SJed Brown TS_Theta *th = (TS_Theta *)ts->data;
11019f196a02SMartin Diehl PetscBool isascii;
1102316643e7SJed Brown
1103316643e7SJed Brown PetscFunctionBegin;
11049f196a02SMartin Diehl PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
11059f196a02SMartin Diehl if (isascii) {
11069566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Theta=%g\n", (double)th->Theta));
11079566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Extrapolation=%s\n", th->extrapolate ? "yes" : "no"));
1108316643e7SJed Brown }
11093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1110316643e7SJed Brown }
1111316643e7SJed Brown
TSThetaGetTheta_Theta(TS ts,PetscReal * theta)1112d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSThetaGetTheta_Theta(TS ts, PetscReal *theta)
1113d71ae5a4SJacob Faibussowitsch {
11140de4c49aSJed Brown TS_Theta *th = (TS_Theta *)ts->data;
11150de4c49aSJed Brown
11160de4c49aSJed Brown PetscFunctionBegin;
11170de4c49aSJed Brown *theta = th->Theta;
11183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
11190de4c49aSJed Brown }
11200de4c49aSJed Brown
TSThetaSetTheta_Theta(TS ts,PetscReal theta)1121d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSThetaSetTheta_Theta(TS ts, PetscReal theta)
1122d71ae5a4SJacob Faibussowitsch {
11230de4c49aSJed Brown TS_Theta *th = (TS_Theta *)ts->data;
11240de4c49aSJed Brown
11250de4c49aSJed Brown PetscFunctionBegin;
1126cad9d221SBarry Smith PetscCheck(theta > 0 && theta <= 1, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Theta %g not in range (0,1]", (double)theta);
11270de4c49aSJed Brown th->Theta = theta;
11281566a47fSLisandro Dalcin th->order = (th->Theta == 0.5) ? 2 : 1;
11293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
11300de4c49aSJed Brown }
1131eb284becSJed Brown
TSThetaGetEndpoint_Theta(TS ts,PetscBool * endpoint)1132d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSThetaGetEndpoint_Theta(TS ts, PetscBool *endpoint)
1133d71ae5a4SJacob Faibussowitsch {
113426f2ff8fSLisandro Dalcin TS_Theta *th = (TS_Theta *)ts->data;
113526f2ff8fSLisandro Dalcin
113626f2ff8fSLisandro Dalcin PetscFunctionBegin;
113726f2ff8fSLisandro Dalcin *endpoint = th->endpoint;
11383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
113926f2ff8fSLisandro Dalcin }
114026f2ff8fSLisandro Dalcin
TSThetaSetEndpoint_Theta(TS ts,PetscBool flg)1141d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSThetaSetEndpoint_Theta(TS ts, PetscBool flg)
1142d71ae5a4SJacob Faibussowitsch {
1143eb284becSJed Brown TS_Theta *th = (TS_Theta *)ts->data;
1144eb284becSJed Brown
1145eb284becSJed Brown PetscFunctionBegin;
1146eb284becSJed Brown th->endpoint = flg;
11473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1148eb284becSJed Brown }
11490de4c49aSJed Brown
1150f9c1d6abSBarry Smith #if defined(PETSC_HAVE_COMPLEX)
TSComputeLinearStability_Theta(TS ts,PetscReal xr,PetscReal xi,PetscReal * yr,PetscReal * yi)1151d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSComputeLinearStability_Theta(TS ts, PetscReal xr, PetscReal xi, PetscReal *yr, PetscReal *yi)
1152d71ae5a4SJacob Faibussowitsch {
1153f9c1d6abSBarry Smith PetscComplex z = xr + xi * PETSC_i, f;
1154f9c1d6abSBarry Smith TS_Theta *th = (TS_Theta *)ts->data;
1155f9c1d6abSBarry Smith
1156f9c1d6abSBarry Smith PetscFunctionBegin;
1157520136c7SJose E. Roman f = (1.0 + (1.0 - th->Theta) * z) / (1.0 - th->Theta * z);
1158f9c1d6abSBarry Smith *yr = PetscRealPartComplex(f);
1159f9c1d6abSBarry Smith *yi = PetscImaginaryPartComplex(f);
11603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1161f9c1d6abSBarry Smith }
1162f9c1d6abSBarry Smith #endif
1163f9c1d6abSBarry Smith
TSGetStages_Theta(TS ts,PetscInt * ns,Vec * Y[])1164d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSGetStages_Theta(TS ts, PetscInt *ns, Vec *Y[])
1165d71ae5a4SJacob Faibussowitsch {
116642682096SHong Zhang TS_Theta *th = (TS_Theta *)ts->data;
116742682096SHong Zhang
116842682096SHong Zhang PetscFunctionBegin;
11697409eceaSHong Zhang if (ns) {
11707409eceaSHong Zhang if (!th->endpoint && th->Theta != 1.0) *ns = 1; /* midpoint form */
11717409eceaSHong Zhang else *ns = 2; /* endpoint form */
11727409eceaSHong Zhang }
11735072d23cSHong Zhang if (Y) {
1174cc4f23bcSHong Zhang if (!th->endpoint && th->Theta != 1.0) {
11757409eceaSHong Zhang th->Stages[0] = th->X;
1176cc4f23bcSHong Zhang } else {
1177cc4f23bcSHong Zhang th->Stages[0] = th->X0;
1178cc4f23bcSHong Zhang th->Stages[1] = ts->vec_sol; /* stiffly accurate */
1179cc4f23bcSHong Zhang }
1180cc4f23bcSHong Zhang *Y = th->Stages;
11815072d23cSHong Zhang }
11823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
118342682096SHong Zhang }
1184f9c1d6abSBarry Smith
1185316643e7SJed Brown /*MC
118696f5712cSJed Brown TSTHETA - DAE solver using the implicit Theta method
1187316643e7SJed Brown
1188316643e7SJed Brown Level: beginner
1189316643e7SJed Brown
1190bcf0153eSBarry Smith Options Database Keys:
1191c82ed962SBarry Smith + -ts_theta_theta <Theta> - Location of stage (0<Theta<=1)
1192c82ed962SBarry Smith . -ts_theta_endpoint <flag> - Use the endpoint (like Crank-Nicholson) instead of midpoint form of the Theta method
119303842d09SLisandro Dalcin - -ts_theta_initial_guess_extrapolate <flg> - Extrapolate stage initial guess from previous solution (sometimes unstable)
11944eb428fdSBarry Smith
1195eb284becSJed Brown Notes:
119637fdd005SBarry Smith .vb
119737fdd005SBarry Smith -ts_type theta -ts_theta_theta 1.0 corresponds to backward Euler (TSBEULER)
119837fdd005SBarry Smith -ts_type theta -ts_theta_theta 0.5 corresponds to the implicit midpoint rule
119937fdd005SBarry Smith -ts_type theta -ts_theta_theta 0.5 -ts_theta_endpoint corresponds to Crank-Nicholson (TSCN)
120037fdd005SBarry Smith .ve
12014eb428fdSBarry Smith
12027409eceaSHong Zhang The endpoint variant of the Theta method and backward Euler can be applied to DAE. The midpoint variant is not suitable for DAEs because it is not stiffly accurate.
1203eb284becSJed Brown
12047409eceaSHong Zhang The midpoint variant is cast as a 1-stage implicit Runge-Kutta method.
1205eb284becSJed Brown
1206eb284becSJed Brown .vb
1207eb284becSJed Brown Theta | Theta
1208eb284becSJed Brown -------------
1209eb284becSJed Brown | 1
1210eb284becSJed Brown .ve
1211eb284becSJed Brown
1212eb284becSJed Brown For the default Theta=0.5, this is also known as the implicit midpoint rule.
1213eb284becSJed Brown
1214eb284becSJed Brown When the endpoint variant is chosen, the method becomes a 2-stage method with first stage explicit:
1215eb284becSJed Brown
1216eb284becSJed Brown .vb
1217eb284becSJed Brown 0 | 0 0
1218eb284becSJed Brown 1 | 1-Theta Theta
1219eb284becSJed Brown -------------------
1220eb284becSJed Brown | 1-Theta Theta
1221eb284becSJed Brown .ve
1222eb284becSJed Brown
1223eb284becSJed Brown For the default Theta=0.5, this is the trapezoid rule (also known as Crank-Nicolson, see TSCN).
1224eb284becSJed Brown
1225eb284becSJed Brown To apply a diagonally implicit RK method to DAE, the stage formula
1226b44f4de4SBarry Smith .vb
1227b44f4de4SBarry Smith Y_i = X + h sum_j a_ij Y'_j
1228b44f4de4SBarry Smith .ve
12294eb428fdSBarry Smith is interpreted as a formula for Y'_i in terms of Y_i and known values (Y'_j, j<i)
1230eb284becSJed Brown
12311cc06b55SBarry Smith .seealso: [](ch_ts), `TSCreate()`, `TS`, `TSSetType()`, `TSCN`, `TSBEULER`, `TSThetaSetTheta()`, `TSThetaSetEndpoint()`
1232316643e7SJed Brown M*/
TSCreate_Theta(TS ts)1233d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode TSCreate_Theta(TS ts)
1234d71ae5a4SJacob Faibussowitsch {
1235316643e7SJed Brown TS_Theta *th;
1236316643e7SJed Brown
1237316643e7SJed Brown PetscFunctionBegin;
1238277b19d0SLisandro Dalcin ts->ops->reset = TSReset_Theta;
1239ece46509SHong Zhang ts->ops->adjointreset = TSAdjointReset_Theta;
1240316643e7SJed Brown ts->ops->destroy = TSDestroy_Theta;
1241316643e7SJed Brown ts->ops->view = TSView_Theta;
1242316643e7SJed Brown ts->ops->setup = TSSetUp_Theta;
124342f2b339SBarry Smith ts->ops->adjointsetup = TSAdjointSetUp_Theta;
1244ece46509SHong Zhang ts->ops->adjointreset = TSAdjointReset_Theta;
1245316643e7SJed Brown ts->ops->step = TSStep_Theta;
1246cd652676SJed Brown ts->ops->interpolate = TSInterpolate_Theta;
12471566a47fSLisandro Dalcin ts->ops->evaluatewlte = TSEvaluateWLTE_Theta;
124824655328SShri ts->ops->rollback = TSRollBack_Theta;
124926b5f05dSStefano Zampini ts->ops->resizeregister = TSResizeRegister_Theta;
1250316643e7SJed Brown ts->ops->setfromoptions = TSSetFromOptions_Theta;
12510f5c6efeSJed Brown ts->ops->snesfunction = SNESTSFormFunction_Theta;
12520f5c6efeSJed Brown ts->ops->snesjacobian = SNESTSFormJacobian_Theta;
1253f9c1d6abSBarry Smith #if defined(PETSC_HAVE_COMPLEX)
1254f9c1d6abSBarry Smith ts->ops->linearstability = TSComputeLinearStability_Theta;
1255f9c1d6abSBarry Smith #endif
125642682096SHong Zhang ts->ops->getstages = TSGetStages_Theta;
125742f2b339SBarry Smith ts->ops->adjointstep = TSAdjointStep_Theta;
1258b1cb36f3SHong Zhang ts->ops->adjointintegral = TSAdjointCostIntegral_Theta;
1259b1cb36f3SHong Zhang ts->ops->forwardintegral = TSForwardCostIntegral_Theta;
12602ffb9264SLisandro Dalcin ts->default_adapt_type = TSADAPTNONE;
12616affb6f8SHong Zhang
1262715f1b00SHong Zhang ts->ops->forwardsetup = TSForwardSetUp_Theta;
12637adebddeSHong Zhang ts->ops->forwardreset = TSForwardReset_Theta;
1264715f1b00SHong Zhang ts->ops->forwardstep = TSForwardStep_Theta;
12656affb6f8SHong Zhang ts->ops->forwardgetstages = TSForwardGetStages_Theta;
1266316643e7SJed Brown
1267efd4aadfSBarry Smith ts->usessnes = PETSC_TRUE;
1268efd4aadfSBarry Smith
12694dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&th));
1270316643e7SJed Brown ts->data = (void *)th;
1271316643e7SJed Brown
1272715f1b00SHong Zhang th->VecsDeltaLam = NULL;
1273715f1b00SHong Zhang th->VecsDeltaMu = NULL;
1274715f1b00SHong Zhang th->VecsSensiTemp = NULL;
1275b5b4017aSHong Zhang th->VecsSensi2Temp = NULL;
1276715f1b00SHong Zhang
12776f700aefSJed Brown th->extrapolate = PETSC_FALSE;
1278316643e7SJed Brown th->Theta = 0.5;
12791566a47fSLisandro Dalcin th->order = 2;
12809566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSThetaGetTheta_C", TSThetaGetTheta_Theta));
12819566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSThetaSetTheta_C", TSThetaSetTheta_Theta));
12829566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSThetaGetEndpoint_C", TSThetaGetEndpoint_Theta));
12839566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSThetaSetEndpoint_C", TSThetaSetEndpoint_Theta));
12843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1285316643e7SJed Brown }
12860de4c49aSJed Brown
12870de4c49aSJed Brown /*@
1288bcf0153eSBarry Smith TSThetaGetTheta - Get the abscissa of the stage in (0,1] for `TSTHETA`
12890de4c49aSJed Brown
12900de4c49aSJed Brown Not Collective
12910de4c49aSJed Brown
12920de4c49aSJed Brown Input Parameter:
12930de4c49aSJed Brown . ts - timestepping context
12940de4c49aSJed Brown
12950de4c49aSJed Brown Output Parameter:
12960de4c49aSJed Brown . theta - stage abscissa
12970de4c49aSJed Brown
1298bcf0153eSBarry Smith Level: advanced
1299bcf0153eSBarry Smith
13000de4c49aSJed Brown Note:
1301bcf0153eSBarry Smith Use of this function is normally only required to hack `TSTHETA` to use a modified integration scheme.
13020de4c49aSJed Brown
13031cc06b55SBarry Smith .seealso: [](ch_ts), `TSThetaSetTheta()`, `TSTHETA`
13040de4c49aSJed Brown @*/
TSThetaGetTheta(TS ts,PetscReal * theta)1305d71ae5a4SJacob Faibussowitsch PetscErrorCode TSThetaGetTheta(TS ts, PetscReal *theta)
1306d71ae5a4SJacob Faibussowitsch {
13070de4c49aSJed Brown PetscFunctionBegin;
1308afb20b64SJed Brown PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
13094f572ea9SToby Isaac PetscAssertPointer(theta, 2);
1310cac4c232SBarry Smith PetscUseMethod(ts, "TSThetaGetTheta_C", (TS, PetscReal *), (ts, theta));
13113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
13120de4c49aSJed Brown }
13130de4c49aSJed Brown
13140de4c49aSJed Brown /*@
1315bcf0153eSBarry Smith TSThetaSetTheta - Set the abscissa of the stage in (0,1] for `TSTHETA`
13160de4c49aSJed Brown
13170de4c49aSJed Brown Not Collective
13180de4c49aSJed Brown
1319d8d19677SJose E. Roman Input Parameters:
13200de4c49aSJed Brown + ts - timestepping context
13210de4c49aSJed Brown - theta - stage abscissa
13220de4c49aSJed Brown
1323bcf0153eSBarry Smith Options Database Key:
132467b8a455SSatish Balay . -ts_theta_theta <theta> - set theta
13250de4c49aSJed Brown
1326bcf0153eSBarry Smith Level: intermediate
13270de4c49aSJed Brown
13281cc06b55SBarry Smith .seealso: [](ch_ts), `TSThetaGetTheta()`, `TSTHETA`, `TSCN`
13290de4c49aSJed Brown @*/
TSThetaSetTheta(TS ts,PetscReal theta)1330d71ae5a4SJacob Faibussowitsch PetscErrorCode TSThetaSetTheta(TS ts, PetscReal theta)
1331d71ae5a4SJacob Faibussowitsch {
13320de4c49aSJed Brown PetscFunctionBegin;
1333afb20b64SJed Brown PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
1334cac4c232SBarry Smith PetscTryMethod(ts, "TSThetaSetTheta_C", (TS, PetscReal), (ts, theta));
13353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
13360de4c49aSJed Brown }
1337f33bbcb6SJed Brown
133826f2ff8fSLisandro Dalcin /*@
1339bcf0153eSBarry Smith TSThetaGetEndpoint - Gets whether to use the endpoint variant of the method (e.g. trapezoid/Crank-Nicolson instead of midpoint rule) for `TSTHETA`
134026f2ff8fSLisandro Dalcin
134126f2ff8fSLisandro Dalcin Not Collective
134226f2ff8fSLisandro Dalcin
134326f2ff8fSLisandro Dalcin Input Parameter:
134426f2ff8fSLisandro Dalcin . ts - timestepping context
134526f2ff8fSLisandro Dalcin
134626f2ff8fSLisandro Dalcin Output Parameter:
1347bcf0153eSBarry Smith . endpoint - `PETSC_TRUE` when using the endpoint variant
134826f2ff8fSLisandro Dalcin
1349bcf0153eSBarry Smith Level: advanced
135026f2ff8fSLisandro Dalcin
13511cc06b55SBarry Smith .seealso: [](ch_ts), `TSThetaSetEndpoint()`, `TSTHETA`, `TSCN`
135226f2ff8fSLisandro Dalcin @*/
TSThetaGetEndpoint(TS ts,PetscBool * endpoint)1353d71ae5a4SJacob Faibussowitsch PetscErrorCode TSThetaGetEndpoint(TS ts, PetscBool *endpoint)
1354d71ae5a4SJacob Faibussowitsch {
135526f2ff8fSLisandro Dalcin PetscFunctionBegin;
135626f2ff8fSLisandro Dalcin PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
13574f572ea9SToby Isaac PetscAssertPointer(endpoint, 2);
1358cac4c232SBarry Smith PetscUseMethod(ts, "TSThetaGetEndpoint_C", (TS, PetscBool *), (ts, endpoint));
13593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
136026f2ff8fSLisandro Dalcin }
136126f2ff8fSLisandro Dalcin
1362eb284becSJed Brown /*@
1363bcf0153eSBarry Smith TSThetaSetEndpoint - Sets whether to use the endpoint variant of the method (e.g. trapezoid/Crank-Nicolson instead of midpoint rule) for `TSTHETA`
1364eb284becSJed Brown
1365eb284becSJed Brown Not Collective
1366eb284becSJed Brown
1367d8d19677SJose E. Roman Input Parameters:
1368eb284becSJed Brown + ts - timestepping context
1369bcf0153eSBarry Smith - flg - `PETSC_TRUE` to use the endpoint variant
1370eb284becSJed Brown
1371bcf0153eSBarry Smith Options Database Key:
137267b8a455SSatish Balay . -ts_theta_endpoint <flg> - use the endpoint variant
1373eb284becSJed Brown
1374bcf0153eSBarry Smith Level: intermediate
1375eb284becSJed Brown
13761cc06b55SBarry Smith .seealso: [](ch_ts), `TSTHETA`, `TSCN`
1377eb284becSJed Brown @*/
TSThetaSetEndpoint(TS ts,PetscBool flg)1378d71ae5a4SJacob Faibussowitsch PetscErrorCode TSThetaSetEndpoint(TS ts, PetscBool flg)
1379d71ae5a4SJacob Faibussowitsch {
1380eb284becSJed Brown PetscFunctionBegin;
1381eb284becSJed Brown PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
1382cac4c232SBarry Smith PetscTryMethod(ts, "TSThetaSetEndpoint_C", (TS, PetscBool), (ts, flg));
13833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1384eb284becSJed Brown }
1385eb284becSJed Brown
1386f33bbcb6SJed Brown /*
1387f33bbcb6SJed Brown * TSBEULER and TSCN are straightforward specializations of TSTHETA.
1388f33bbcb6SJed Brown * The creation functions for these specializations are below.
1389f33bbcb6SJed Brown */
1390f33bbcb6SJed Brown
TSSetUp_BEuler(TS ts)1391d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSSetUp_BEuler(TS ts)
1392d71ae5a4SJacob Faibussowitsch {
13931566a47fSLisandro Dalcin TS_Theta *th = (TS_Theta *)ts->data;
13941566a47fSLisandro Dalcin
13951566a47fSLisandro Dalcin PetscFunctionBegin;
139608401ef6SPierre Jolivet PetscCheck(th->Theta == 1.0, PetscObjectComm((PetscObject)ts), PETSC_ERR_OPT_OVERWRITE, "Can not change the default value (1) of theta when using backward Euler");
139728b400f6SJacob Faibussowitsch PetscCheck(!th->endpoint, PetscObjectComm((PetscObject)ts), PETSC_ERR_OPT_OVERWRITE, "Can not change to the endpoint form of the Theta methods when using backward Euler");
13989566063dSJacob Faibussowitsch PetscCall(TSSetUp_Theta(ts));
13993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
14001566a47fSLisandro Dalcin }
14011566a47fSLisandro Dalcin
TSView_BEuler(TS ts,PetscViewer viewer)1402d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSView_BEuler(TS ts, PetscViewer viewer)
1403d71ae5a4SJacob Faibussowitsch {
1404f33bbcb6SJed Brown PetscFunctionBegin;
14053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1406f33bbcb6SJed Brown }
1407f33bbcb6SJed Brown
1408f33bbcb6SJed Brown /*MC
1409f33bbcb6SJed Brown TSBEULER - ODE solver using the implicit backward Euler method
1410f33bbcb6SJed Brown
1411f33bbcb6SJed Brown Level: beginner
1412f33bbcb6SJed Brown
1413bcf0153eSBarry Smith Note:
141437fdd005SBarry Smith `TSBEULER` is equivalent to `TSTHETA` with Theta=1.0 or `-ts_type theta -ts_theta_theta 1.0`
14154eb428fdSBarry Smith
14161cc06b55SBarry Smith .seealso: [](ch_ts), `TSCreate()`, `TS`, `TSSetType()`, `TSEULER`, `TSCN`, `TSTHETA`
1417f33bbcb6SJed Brown M*/
TSCreate_BEuler(TS ts)1418d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode TSCreate_BEuler(TS ts)
1419d71ae5a4SJacob Faibussowitsch {
1420f33bbcb6SJed Brown PetscFunctionBegin;
14219566063dSJacob Faibussowitsch PetscCall(TSCreate_Theta(ts));
14229566063dSJacob Faibussowitsch PetscCall(TSThetaSetTheta(ts, 1.0));
14239566063dSJacob Faibussowitsch PetscCall(TSThetaSetEndpoint(ts, PETSC_FALSE));
14240c7376e5SHong Zhang ts->ops->setup = TSSetUp_BEuler;
1425f33bbcb6SJed Brown ts->ops->view = TSView_BEuler;
14263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1427f33bbcb6SJed Brown }
1428f33bbcb6SJed Brown
TSSetUp_CN(TS ts)1429d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSSetUp_CN(TS ts)
1430d71ae5a4SJacob Faibussowitsch {
14311566a47fSLisandro Dalcin TS_Theta *th = (TS_Theta *)ts->data;
14321566a47fSLisandro Dalcin
14331566a47fSLisandro Dalcin PetscFunctionBegin;
143408401ef6SPierre Jolivet PetscCheck(th->Theta == 0.5, PetscObjectComm((PetscObject)ts), PETSC_ERR_OPT_OVERWRITE, "Can not change the default value (0.5) of theta when using Crank-Nicolson");
14353c633725SBarry Smith PetscCheck(th->endpoint, PetscObjectComm((PetscObject)ts), PETSC_ERR_OPT_OVERWRITE, "Can not change to the midpoint form of the Theta methods when using Crank-Nicolson");
14369566063dSJacob Faibussowitsch PetscCall(TSSetUp_Theta(ts));
14373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
14381566a47fSLisandro Dalcin }
14391566a47fSLisandro Dalcin
TSView_CN(TS ts,PetscViewer viewer)1440d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSView_CN(TS ts, PetscViewer viewer)
1441d71ae5a4SJacob Faibussowitsch {
1442f33bbcb6SJed Brown PetscFunctionBegin;
14433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1444f33bbcb6SJed Brown }
1445f33bbcb6SJed Brown
1446f33bbcb6SJed Brown /*MC
1447f33bbcb6SJed Brown TSCN - ODE solver using the implicit Crank-Nicolson method.
1448f33bbcb6SJed Brown
1449f33bbcb6SJed Brown Level: beginner
1450f33bbcb6SJed Brown
1451f33bbcb6SJed Brown Notes:
1452bcf0153eSBarry Smith `TSCN` is equivalent to `TSTHETA` with Theta=0.5 and the "endpoint" option set. I.e.
1453bcf0153eSBarry Smith .vb
1454bcf0153eSBarry Smith -ts_type theta
1455bcf0153eSBarry Smith -ts_theta_theta 0.5
1456bcf0153eSBarry Smith -ts_theta_endpoint
1457bcf0153eSBarry Smith .ve
14587cf5af47SJed Brown
14591cc06b55SBarry Smith .seealso: [](ch_ts), `TSCreate()`, `TS`, `TSSetType()`, `TSBEULER`, `TSTHETA`, `TSType`,
1460f33bbcb6SJed Brown M*/
TSCreate_CN(TS ts)1461d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode TSCreate_CN(TS ts)
1462d71ae5a4SJacob Faibussowitsch {
1463f33bbcb6SJed Brown PetscFunctionBegin;
14649566063dSJacob Faibussowitsch PetscCall(TSCreate_Theta(ts));
14659566063dSJacob Faibussowitsch PetscCall(TSThetaSetTheta(ts, 0.5));
14669566063dSJacob Faibussowitsch PetscCall(TSThetaSetEndpoint(ts, PETSC_TRUE));
14670c7376e5SHong Zhang ts->ops->setup = TSSetUp_CN;
1468f33bbcb6SJed Brown ts->ops->view = TSView_CN;
14693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1470f33bbcb6SJed Brown }
1471