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 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) { 51*ac530a7eSPierre Jolivet if (dm && dm != ts->dm) PetscCall(DMGetNamedGlobalVector(dm, "TSTheta_X0", X0)); 52*ac530a7eSPierre Jolivet else *X0 = ts->vec_sol; 537445fe48SJed Brown } 547445fe48SJed Brown if (Xdot) { 55*ac530a7eSPierre Jolivet if (dm && dm != ts->dm) PetscCall(DMGetNamedGlobalVector(dm, "TSTheta_Xdot", Xdot)); 56*ac530a7eSPierre Jolivet else *Xdot = th->Xdot; 577445fe48SJed Brown } 583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 597445fe48SJed Brown } 607445fe48SJed Brown 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 73d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCoarsenHook_TSTheta(DM fine, DM coarse, void *ctx) 74d71ae5a4SJacob Faibussowitsch { 757445fe48SJed Brown PetscFunctionBegin; 763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 777445fe48SJed Brown } 787445fe48SJed Brown 79d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMRestrictHook_TSTheta(DM fine, Mat restrct, Vec rscale, Mat inject, DM coarse, void *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 96d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSubDomainHook_TSTheta(DM dm, DM subdm, void *ctx) 97d71ae5a4SJacob Faibussowitsch { 98258e1594SPeter Brune PetscFunctionBegin; 993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 100258e1594SPeter Brune } 101258e1594SPeter Brune 102d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSubDomainRestrictHook_TSTheta(DM dm, VecScatter gscat, VecScatter lscat, DM subdm, void *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 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 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 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 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 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 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 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 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 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 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]; 710225f7d0bSStefano Zampini scal[0] = -1 / a; 711225f7d0bSStefano Zampini scal[1] = +1 / (a - 1); 712225f7d0bSStefano Zampini scal[2] = -1 / (a * (a - 1)); 7139371c9d4SSatish Balay vecs[0] = X; 7149371c9d4SSatish Balay vecs[1] = th->X0; 7159371c9d4SSatish Balay vecs[2] = th->vec_sol_prev; 7169566063dSJacob Faibussowitsch PetscCall(VecCopy(X, Y)); 7179566063dSJacob Faibussowitsch PetscCall(VecMAXPY(Y, 3, scal, vecs)); 7189566063dSJacob Faibussowitsch PetscCall(TSErrorWeightedNorm(ts, X, Y, wnormtype, wlte, &wltea, &wlter)); 7191566a47fSLisandro Dalcin } 7201566a47fSLisandro Dalcin if (order) *order = 2; 7213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7221566a47fSLisandro Dalcin } 7231566a47fSLisandro Dalcin 724d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSRollBack_Theta(TS ts) 725d71ae5a4SJacob Faibussowitsch { 7261566a47fSLisandro Dalcin TS_Theta *th = (TS_Theta *)ts->data; 7277207e0fdSHong Zhang TS quadts = ts->quadraturets; 7281566a47fSLisandro Dalcin 7291566a47fSLisandro Dalcin PetscFunctionBegin; 73048a46eb9SPierre Jolivet if (quadts && ts->costintegralfwd) PetscCall(VecCopy(th->VecCostIntegral0, quadts->vec_sol)); 731715f1b00SHong Zhang th->status = TS_STEP_INCOMPLETE; 7321baa6e33SBarry Smith if (ts->mat_sensip) PetscCall(MatCopy(th->MatFwdSensip0, ts->mat_sensip, SAME_NONZERO_PATTERN)); 73348a46eb9SPierre Jolivet if (quadts && quadts->mat_sensip) PetscCall(MatCopy(th->MatIntegralSensip0, quadts->mat_sensip, SAME_NONZERO_PATTERN)); 7343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 735715f1b00SHong Zhang } 736715f1b00SHong Zhang 737d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSForwardStep_Theta(TS ts) 738d71ae5a4SJacob Faibussowitsch { 739715f1b00SHong Zhang TS_Theta *th = (TS_Theta *)ts->data; 740cd4cee2dSHong Zhang TS quadts = ts->quadraturets; 74113b1b0ffSHong Zhang Mat MatDeltaFwdSensip = th->MatDeltaFwdSensip; 742b5b4017aSHong Zhang Vec VecDeltaFwdSensipCol = th->VecDeltaFwdSensipCol; 7437207e0fdSHong Zhang PetscInt ntlm; 744715f1b00SHong Zhang KSP ksp; 7457207e0fdSHong Zhang Mat J, Jpre, quadJ = NULL, quadJp = NULL; 74613b1b0ffSHong Zhang PetscScalar *barr, *xarr; 7471a352fa8SHong Zhang PetscReal previous_shift; 748715f1b00SHong Zhang 749715f1b00SHong Zhang PetscFunctionBegin; 7501a352fa8SHong Zhang previous_shift = th->shift; 7519566063dSJacob Faibussowitsch PetscCall(MatCopy(ts->mat_sensip, th->MatFwdSensip0, SAME_NONZERO_PATTERN)); 75213b1b0ffSHong Zhang 75348a46eb9SPierre Jolivet if (quadts && quadts->mat_sensip) PetscCall(MatCopy(quadts->mat_sensip, th->MatIntegralSensip0, SAME_NONZERO_PATTERN)); 7549566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(ts->snes, &ksp)); 7559566063dSJacob Faibussowitsch PetscCall(TSGetIJacobian(ts, &J, &Jpre, NULL, NULL)); 7567207e0fdSHong Zhang if (quadts) { 7579566063dSJacob Faibussowitsch PetscCall(TSGetRHSJacobian(quadts, &quadJ, NULL, NULL, NULL)); 7589566063dSJacob Faibussowitsch PetscCall(TSGetRHSJacobianP(quadts, &quadJp, NULL, NULL)); 7597207e0fdSHong Zhang } 760715f1b00SHong Zhang 761715f1b00SHong Zhang /* Build RHS */ 762715f1b00SHong Zhang if (th->endpoint) { /* 2-stage method*/ 7631a352fa8SHong Zhang th->shift = 1. / ((th->Theta - 1.) * th->time_step0); 7649566063dSJacob Faibussowitsch PetscCall(TSComputeIJacobian(ts, th->ptime0, th->X0, th->Xdot, th->shift, J, Jpre, PETSC_FALSE)); 765fb842aefSJose E. Roman PetscCall(MatMatMult(J, ts->mat_sensip, MAT_REUSE_MATRIX, PETSC_DETERMINE, &MatDeltaFwdSensip)); 7669566063dSJacob Faibussowitsch PetscCall(MatScale(MatDeltaFwdSensip, (th->Theta - 1.) / th->Theta)); 767715f1b00SHong Zhang 768022c081aSHong Zhang /* Add the f_p forcing terms */ 7690e11c21fSHong Zhang if (ts->Jacp) { 7709566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(th->Xdot)); 7719566063dSJacob Faibussowitsch PetscCall(TSComputeIJacobianP(ts, th->ptime0, th->X0, th->Xdot, th->shift, ts->Jacp, PETSC_FALSE)); 7729566063dSJacob Faibussowitsch PetscCall(MatAXPY(MatDeltaFwdSensip, (th->Theta - 1.) / th->Theta, ts->Jacp, SUBSET_NONZERO_PATTERN)); 77382ad9101SHong Zhang th->shift = previous_shift; 7749566063dSJacob Faibussowitsch PetscCall(VecAXPBYPCZ(th->Xdot, -th->shift, th->shift, 0, th->X0, ts->vec_sol)); 7759566063dSJacob Faibussowitsch PetscCall(TSComputeIJacobianP(ts, th->stage_time, ts->vec_sol, th->Xdot, th->shift, ts->Jacp, PETSC_FALSE)); 7769566063dSJacob Faibussowitsch PetscCall(MatAXPY(MatDeltaFwdSensip, -1., ts->Jacp, SUBSET_NONZERO_PATTERN)); 7770e11c21fSHong Zhang } 778715f1b00SHong Zhang } else { /* 1-stage method */ 7793e05ceb1SHong Zhang th->shift = 0.0; 7809566063dSJacob Faibussowitsch PetscCall(TSComputeIJacobian(ts, th->stage_time, th->X, th->Xdot, th->shift, J, Jpre, PETSC_FALSE)); 781fb842aefSJose E. Roman PetscCall(MatMatMult(J, ts->mat_sensip, MAT_REUSE_MATRIX, PETSC_DETERMINE, &MatDeltaFwdSensip)); 7829566063dSJacob Faibussowitsch PetscCall(MatScale(MatDeltaFwdSensip, -1.)); 78313b1b0ffSHong Zhang 784022c081aSHong Zhang /* Add the f_p forcing terms */ 7850e11c21fSHong Zhang if (ts->Jacp) { 78682ad9101SHong Zhang th->shift = previous_shift; 7879566063dSJacob Faibussowitsch PetscCall(VecAXPBYPCZ(th->Xdot, -th->shift, th->shift, 0, th->X0, th->X)); 7889566063dSJacob Faibussowitsch PetscCall(TSComputeIJacobianP(ts, th->stage_time, th->X, th->Xdot, th->shift, ts->Jacp, PETSC_FALSE)); 7899566063dSJacob Faibussowitsch PetscCall(MatAXPY(MatDeltaFwdSensip, -1., ts->Jacp, SUBSET_NONZERO_PATTERN)); 790715f1b00SHong Zhang } 7910e11c21fSHong Zhang } 792715f1b00SHong Zhang 793715f1b00SHong Zhang /* Build LHS */ 7941a352fa8SHong Zhang th->shift = previous_shift; /* recover the previous shift used in TSStep_Theta() */ 795715f1b00SHong Zhang if (th->endpoint) { 7969566063dSJacob Faibussowitsch PetscCall(TSComputeIJacobian(ts, th->stage_time, ts->vec_sol, th->Xdot, th->shift, J, Jpre, PETSC_FALSE)); 797715f1b00SHong Zhang } else { 7989566063dSJacob Faibussowitsch PetscCall(TSComputeIJacobian(ts, th->stage_time, th->X, th->Xdot, th->shift, J, Jpre, PETSC_FALSE)); 799715f1b00SHong Zhang } 8009566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(ksp, J, Jpre)); 801715f1b00SHong Zhang 802715f1b00SHong Zhang /* 803715f1b00SHong Zhang Evaluate the first stage of integral gradients with the 2-stage method: 804c9ad9de0SHong Zhang drdu|t_n*S(t_n) + drdp|t_n 805715f1b00SHong Zhang This is done before the linear solve because the sensitivity variable S(t_n) will be propagated to S(t_{n+1}) 806715f1b00SHong Zhang */ 807715f1b00SHong Zhang if (th->endpoint) { /* 2-stage method only */ 8087207e0fdSHong Zhang if (quadts && quadts->mat_sensip) { 8099566063dSJacob Faibussowitsch PetscCall(TSComputeRHSJacobian(quadts, th->ptime0, th->X0, quadJ, NULL)); 8109566063dSJacob Faibussowitsch PetscCall(TSComputeRHSJacobianP(quadts, th->ptime0, th->X0, quadJp)); 811fb842aefSJose E. Roman PetscCall(MatTransposeMatMult(ts->mat_sensip, quadJ, MAT_REUSE_MATRIX, PETSC_DETERMINE, &th->MatIntegralSensipTemp)); 8129566063dSJacob Faibussowitsch PetscCall(MatAXPY(th->MatIntegralSensipTemp, 1, quadJp, SAME_NONZERO_PATTERN)); 8139566063dSJacob Faibussowitsch PetscCall(MatAXPY(quadts->mat_sensip, th->time_step0 * (1. - th->Theta), th->MatIntegralSensipTemp, SAME_NONZERO_PATTERN)); 814715f1b00SHong Zhang } 815715f1b00SHong Zhang } 816715f1b00SHong Zhang 817715f1b00SHong Zhang /* Solve the tangent linear equation for forward sensitivities to parameters */ 818022c081aSHong Zhang for (ntlm = 0; ntlm < th->num_tlm; ntlm++) { 819b5b4017aSHong Zhang KSPConvergedReason kspreason; 8209566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumn(MatDeltaFwdSensip, ntlm, &barr)); 8219566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(VecDeltaFwdSensipCol, barr)); 822715f1b00SHong Zhang if (th->endpoint) { 8239566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumn(ts->mat_sensip, ntlm, &xarr)); 8249566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(ts->vec_sensip_col, xarr)); 8259566063dSJacob Faibussowitsch PetscCall(KSPSolve(ksp, VecDeltaFwdSensipCol, ts->vec_sensip_col)); 8269566063dSJacob Faibussowitsch PetscCall(VecResetArray(ts->vec_sensip_col)); 8279566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumn(ts->mat_sensip, &xarr)); 828715f1b00SHong Zhang } else { 8299566063dSJacob Faibussowitsch PetscCall(KSPSolve(ksp, VecDeltaFwdSensipCol, VecDeltaFwdSensipCol)); 830715f1b00SHong Zhang } 8319566063dSJacob Faibussowitsch PetscCall(KSPGetConvergedReason(ksp, &kspreason)); 832b5b4017aSHong Zhang if (kspreason < 0) { 833b5b4017aSHong Zhang ts->reason = TSFORWARD_DIVERGED_LINEAR_SOLVE; 83463a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(ts, "Step=%" PetscInt_FMT ", %" PetscInt_FMT "th tangent linear solve, linear solve fails, stopping tangent linear solve\n", ts->steps, ntlm)); 835b5b4017aSHong Zhang } 8369566063dSJacob Faibussowitsch PetscCall(VecResetArray(VecDeltaFwdSensipCol)); 8379566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumn(MatDeltaFwdSensip, &barr)); 838715f1b00SHong Zhang } 839715f1b00SHong Zhang 84013b1b0ffSHong Zhang /* 84113b1b0ffSHong Zhang Evaluate the second stage of integral gradients with the 2-stage method: 842c9ad9de0SHong Zhang drdu|t_{n+1}*S(t_{n+1}) + drdp|t_{n+1} 84313b1b0ffSHong Zhang */ 8447207e0fdSHong Zhang if (quadts && quadts->mat_sensip) { 84513b1b0ffSHong Zhang if (!th->endpoint) { 8469566063dSJacob Faibussowitsch PetscCall(MatAXPY(ts->mat_sensip, 1, MatDeltaFwdSensip, SAME_NONZERO_PATTERN)); /* stage sensitivity */ 8479566063dSJacob Faibussowitsch PetscCall(TSComputeRHSJacobian(quadts, th->stage_time, th->X, quadJ, NULL)); 8489566063dSJacob Faibussowitsch PetscCall(TSComputeRHSJacobianP(quadts, th->stage_time, th->X, quadJp)); 849fb842aefSJose E. Roman PetscCall(MatTransposeMatMult(ts->mat_sensip, quadJ, MAT_REUSE_MATRIX, PETSC_DETERMINE, &th->MatIntegralSensipTemp)); 8509566063dSJacob Faibussowitsch PetscCall(MatAXPY(th->MatIntegralSensipTemp, 1, quadJp, SAME_NONZERO_PATTERN)); 8519566063dSJacob Faibussowitsch PetscCall(MatAXPY(quadts->mat_sensip, th->time_step0, th->MatIntegralSensipTemp, SAME_NONZERO_PATTERN)); 8529566063dSJacob Faibussowitsch PetscCall(MatAXPY(ts->mat_sensip, (1. - th->Theta) / th->Theta, MatDeltaFwdSensip, SAME_NONZERO_PATTERN)); 85313b1b0ffSHong Zhang } else { 8549566063dSJacob Faibussowitsch PetscCall(TSComputeRHSJacobian(quadts, th->stage_time, ts->vec_sol, quadJ, NULL)); 8559566063dSJacob Faibussowitsch PetscCall(TSComputeRHSJacobianP(quadts, th->stage_time, ts->vec_sol, quadJp)); 856fb842aefSJose E. Roman PetscCall(MatTransposeMatMult(ts->mat_sensip, quadJ, MAT_REUSE_MATRIX, PETSC_DETERMINE, &th->MatIntegralSensipTemp)); 8579566063dSJacob Faibussowitsch PetscCall(MatAXPY(th->MatIntegralSensipTemp, 1, quadJp, SAME_NONZERO_PATTERN)); 8589566063dSJacob Faibussowitsch PetscCall(MatAXPY(quadts->mat_sensip, th->time_step0 * th->Theta, th->MatIntegralSensipTemp, SAME_NONZERO_PATTERN)); 85913b1b0ffSHong Zhang } 86013b1b0ffSHong Zhang } else { 86148a46eb9SPierre Jolivet if (!th->endpoint) PetscCall(MatAXPY(ts->mat_sensip, 1. / th->Theta, MatDeltaFwdSensip, SAME_NONZERO_PATTERN)); 862715f1b00SHong Zhang } 8633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8641566a47fSLisandro Dalcin } 8651566a47fSLisandro Dalcin 866d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSForwardGetStages_Theta(TS ts, PetscInt *ns, Mat *stagesensip[]) 867d71ae5a4SJacob Faibussowitsch { 8686affb6f8SHong Zhang TS_Theta *th = (TS_Theta *)ts->data; 8696affb6f8SHong Zhang 8706affb6f8SHong Zhang PetscFunctionBegin; 8717409eceaSHong Zhang if (ns) { 8727409eceaSHong Zhang if (!th->endpoint && th->Theta != 1.0) *ns = 1; /* midpoint form */ 8737409eceaSHong Zhang else *ns = 2; /* endpoint form */ 8747409eceaSHong Zhang } 8755072d23cSHong Zhang if (stagesensip) { 876cc4f23bcSHong Zhang if (!th->endpoint && th->Theta != 1.0) { 8777409eceaSHong Zhang th->MatFwdStages[0] = th->MatDeltaFwdSensip; 878cc4f23bcSHong Zhang } else { 879cc4f23bcSHong Zhang th->MatFwdStages[0] = th->MatFwdSensip0; 880cc4f23bcSHong Zhang th->MatFwdStages[1] = ts->mat_sensip; /* stiffly accurate */ 881cc4f23bcSHong Zhang } 882cc4f23bcSHong Zhang *stagesensip = th->MatFwdStages; 8835072d23cSHong Zhang } 8843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8856affb6f8SHong Zhang } 8866affb6f8SHong Zhang 887316643e7SJed Brown /*------------------------------------------------------------*/ 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 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 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 */ 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 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 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 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 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 1059b4dd3bf9SBarry Smith /*------------------------------------------------------------*/ 1060b4dd3bf9SBarry Smith 1061d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSAdjointSetUp_Theta(TS ts) 1062d71ae5a4SJacob Faibussowitsch { 1063b4dd3bf9SBarry Smith TS_Theta *th = (TS_Theta *)ts->data; 1064b4dd3bf9SBarry Smith 1065b4dd3bf9SBarry Smith PetscFunctionBegin; 10669566063dSJacob Faibussowitsch PetscCall(VecDuplicateVecs(ts->vecs_sensi[0], ts->numcost, &th->VecsDeltaLam)); 10679566063dSJacob Faibussowitsch PetscCall(VecDuplicateVecs(ts->vecs_sensi[0], ts->numcost, &th->VecsSensiTemp)); 106848a46eb9SPierre Jolivet if (ts->vecs_sensip) PetscCall(VecDuplicateVecs(ts->vecs_sensip[0], ts->numcost, &th->VecsDeltaMu)); 1069b5b4017aSHong Zhang if (ts->vecs_sensi2) { 10709566063dSJacob Faibussowitsch PetscCall(VecDuplicateVecs(ts->vecs_sensi[0], ts->numcost, &th->VecsDeltaLam2)); 10719566063dSJacob Faibussowitsch PetscCall(VecDuplicateVecs(ts->vecs_sensi2[0], ts->numcost, &th->VecsSensi2Temp)); 107267633408SHong Zhang /* hack ts to make implicit TS solver work when users provide only explicit versions of callbacks (RHSFunction,RHSJacobian,RHSHessian etc.) */ 107367633408SHong Zhang if (!ts->ihessianproduct_fuu) ts->vecs_fuu = ts->vecs_guu; 107467633408SHong Zhang if (!ts->ihessianproduct_fup) ts->vecs_fup = ts->vecs_gup; 1075b5b4017aSHong Zhang } 1076c9681e5dSHong Zhang if (ts->vecs_sensi2p) { 10779566063dSJacob Faibussowitsch PetscCall(VecDuplicateVecs(ts->vecs_sensi2p[0], ts->numcost, &th->VecsDeltaMu2)); 107867633408SHong Zhang /* hack ts to make implicit TS solver work when users provide only explicit versions of callbacks (RHSFunction,RHSJacobian,RHSHessian etc.) */ 107967633408SHong Zhang if (!ts->ihessianproduct_fpu) ts->vecs_fpu = ts->vecs_gpu; 108067633408SHong Zhang if (!ts->ihessianproduct_fpp) ts->vecs_fpp = ts->vecs_gpp; 1081b5b4017aSHong Zhang } 10823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1083316643e7SJed Brown } 1084316643e7SJed Brown 1085ce78bad3SBarry Smith static PetscErrorCode TSSetFromOptions_Theta(TS ts, PetscOptionItems PetscOptionsObject) 1086d71ae5a4SJacob Faibussowitsch { 1087316643e7SJed Brown TS_Theta *th = (TS_Theta *)ts->data; 1088316643e7SJed Brown 1089316643e7SJed Brown PetscFunctionBegin; 1090d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "Theta ODE solver options"); 1091316643e7SJed Brown { 10929566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-ts_theta_theta", "Location of stage (0<Theta<=1)", "TSThetaSetTheta", th->Theta, &th->Theta, NULL)); 10939566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-ts_theta_endpoint", "Use the endpoint instead of midpoint form of the Theta method", "TSThetaSetEndpoint", th->endpoint, &th->endpoint, NULL)); 10949566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-ts_theta_initial_guess_extrapolate", "Extrapolate stage initial guess from previous solution (sometimes unstable)", "TSThetaSetExtrapolate", th->extrapolate, &th->extrapolate, NULL)); 1095316643e7SJed Brown } 1096d0609cedSBarry Smith PetscOptionsHeadEnd(); 10973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1098316643e7SJed Brown } 1099316643e7SJed Brown 1100d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSView_Theta(TS ts, PetscViewer viewer) 1101d71ae5a4SJacob Faibussowitsch { 1102316643e7SJed Brown TS_Theta *th = (TS_Theta *)ts->data; 11039f196a02SMartin Diehl PetscBool isascii; 1104316643e7SJed Brown 1105316643e7SJed Brown PetscFunctionBegin; 11069f196a02SMartin Diehl PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 11079f196a02SMartin Diehl if (isascii) { 11089566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Theta=%g\n", (double)th->Theta)); 11099566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Extrapolation=%s\n", th->extrapolate ? "yes" : "no")); 1110316643e7SJed Brown } 11113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1112316643e7SJed Brown } 1113316643e7SJed Brown 1114d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSThetaGetTheta_Theta(TS ts, PetscReal *theta) 1115d71ae5a4SJacob Faibussowitsch { 11160de4c49aSJed Brown TS_Theta *th = (TS_Theta *)ts->data; 11170de4c49aSJed Brown 11180de4c49aSJed Brown PetscFunctionBegin; 11190de4c49aSJed Brown *theta = th->Theta; 11203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11210de4c49aSJed Brown } 11220de4c49aSJed Brown 1123d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSThetaSetTheta_Theta(TS ts, PetscReal theta) 1124d71ae5a4SJacob Faibussowitsch { 11250de4c49aSJed Brown TS_Theta *th = (TS_Theta *)ts->data; 11260de4c49aSJed Brown 11270de4c49aSJed Brown PetscFunctionBegin; 1128cad9d221SBarry Smith PetscCheck(theta > 0 && theta <= 1, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Theta %g not in range (0,1]", (double)theta); 11290de4c49aSJed Brown th->Theta = theta; 11301566a47fSLisandro Dalcin th->order = (th->Theta == 0.5) ? 2 : 1; 11313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11320de4c49aSJed Brown } 1133eb284becSJed Brown 1134d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSThetaGetEndpoint_Theta(TS ts, PetscBool *endpoint) 1135d71ae5a4SJacob Faibussowitsch { 113626f2ff8fSLisandro Dalcin TS_Theta *th = (TS_Theta *)ts->data; 113726f2ff8fSLisandro Dalcin 113826f2ff8fSLisandro Dalcin PetscFunctionBegin; 113926f2ff8fSLisandro Dalcin *endpoint = th->endpoint; 11403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 114126f2ff8fSLisandro Dalcin } 114226f2ff8fSLisandro Dalcin 1143d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSThetaSetEndpoint_Theta(TS ts, PetscBool flg) 1144d71ae5a4SJacob Faibussowitsch { 1145eb284becSJed Brown TS_Theta *th = (TS_Theta *)ts->data; 1146eb284becSJed Brown 1147eb284becSJed Brown PetscFunctionBegin; 1148eb284becSJed Brown th->endpoint = flg; 11493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1150eb284becSJed Brown } 11510de4c49aSJed Brown 1152f9c1d6abSBarry Smith #if defined(PETSC_HAVE_COMPLEX) 1153d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSComputeLinearStability_Theta(TS ts, PetscReal xr, PetscReal xi, PetscReal *yr, PetscReal *yi) 1154d71ae5a4SJacob Faibussowitsch { 1155f9c1d6abSBarry Smith PetscComplex z = xr + xi * PETSC_i, f; 1156f9c1d6abSBarry Smith TS_Theta *th = (TS_Theta *)ts->data; 1157f9c1d6abSBarry Smith 1158f9c1d6abSBarry Smith PetscFunctionBegin; 1159520136c7SJose E. Roman f = (1.0 + (1.0 - th->Theta) * z) / (1.0 - th->Theta * z); 1160f9c1d6abSBarry Smith *yr = PetscRealPartComplex(f); 1161f9c1d6abSBarry Smith *yi = PetscImaginaryPartComplex(f); 11623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1163f9c1d6abSBarry Smith } 1164f9c1d6abSBarry Smith #endif 1165f9c1d6abSBarry Smith 1166d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSGetStages_Theta(TS ts, PetscInt *ns, Vec *Y[]) 1167d71ae5a4SJacob Faibussowitsch { 116842682096SHong Zhang TS_Theta *th = (TS_Theta *)ts->data; 116942682096SHong Zhang 117042682096SHong Zhang PetscFunctionBegin; 11717409eceaSHong Zhang if (ns) { 11727409eceaSHong Zhang if (!th->endpoint && th->Theta != 1.0) *ns = 1; /* midpoint form */ 11737409eceaSHong Zhang else *ns = 2; /* endpoint form */ 11747409eceaSHong Zhang } 11755072d23cSHong Zhang if (Y) { 1176cc4f23bcSHong Zhang if (!th->endpoint && th->Theta != 1.0) { 11777409eceaSHong Zhang th->Stages[0] = th->X; 1178cc4f23bcSHong Zhang } else { 1179cc4f23bcSHong Zhang th->Stages[0] = th->X0; 1180cc4f23bcSHong Zhang th->Stages[1] = ts->vec_sol; /* stiffly accurate */ 1181cc4f23bcSHong Zhang } 1182cc4f23bcSHong Zhang *Y = th->Stages; 11835072d23cSHong Zhang } 11843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 118542682096SHong Zhang } 1186f9c1d6abSBarry Smith 1187316643e7SJed Brown /* ------------------------------------------------------------ */ 1188316643e7SJed Brown /*MC 118996f5712cSJed Brown TSTHETA - DAE solver using the implicit Theta method 1190316643e7SJed Brown 1191316643e7SJed Brown Level: beginner 1192316643e7SJed Brown 1193bcf0153eSBarry Smith Options Database Keys: 1194c82ed962SBarry Smith + -ts_theta_theta <Theta> - Location of stage (0<Theta<=1) 1195c82ed962SBarry Smith . -ts_theta_endpoint <flag> - Use the endpoint (like Crank-Nicholson) instead of midpoint form of the Theta method 119603842d09SLisandro Dalcin - -ts_theta_initial_guess_extrapolate <flg> - Extrapolate stage initial guess from previous solution (sometimes unstable) 11974eb428fdSBarry Smith 1198eb284becSJed Brown Notes: 119937fdd005SBarry Smith .vb 120037fdd005SBarry Smith -ts_type theta -ts_theta_theta 1.0 corresponds to backward Euler (TSBEULER) 120137fdd005SBarry Smith -ts_type theta -ts_theta_theta 0.5 corresponds to the implicit midpoint rule 120237fdd005SBarry Smith -ts_type theta -ts_theta_theta 0.5 -ts_theta_endpoint corresponds to Crank-Nicholson (TSCN) 120337fdd005SBarry Smith .ve 12044eb428fdSBarry Smith 12057409eceaSHong 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. 1206eb284becSJed Brown 12077409eceaSHong Zhang The midpoint variant is cast as a 1-stage implicit Runge-Kutta method. 1208eb284becSJed Brown 1209eb284becSJed Brown .vb 1210eb284becSJed Brown Theta | Theta 1211eb284becSJed Brown ------------- 1212eb284becSJed Brown | 1 1213eb284becSJed Brown .ve 1214eb284becSJed Brown 1215eb284becSJed Brown For the default Theta=0.5, this is also known as the implicit midpoint rule. 1216eb284becSJed Brown 1217eb284becSJed Brown When the endpoint variant is chosen, the method becomes a 2-stage method with first stage explicit: 1218eb284becSJed Brown 1219eb284becSJed Brown .vb 1220eb284becSJed Brown 0 | 0 0 1221eb284becSJed Brown 1 | 1-Theta Theta 1222eb284becSJed Brown ------------------- 1223eb284becSJed Brown | 1-Theta Theta 1224eb284becSJed Brown .ve 1225eb284becSJed Brown 1226eb284becSJed Brown For the default Theta=0.5, this is the trapezoid rule (also known as Crank-Nicolson, see TSCN). 1227eb284becSJed Brown 1228eb284becSJed Brown To apply a diagonally implicit RK method to DAE, the stage formula 1229b44f4de4SBarry Smith .vb 1230b44f4de4SBarry Smith Y_i = X + h sum_j a_ij Y'_j 1231b44f4de4SBarry Smith .ve 12324eb428fdSBarry Smith is interpreted as a formula for Y'_i in terms of Y_i and known values (Y'_j, j<i) 1233eb284becSJed Brown 12341cc06b55SBarry Smith .seealso: [](ch_ts), `TSCreate()`, `TS`, `TSSetType()`, `TSCN`, `TSBEULER`, `TSThetaSetTheta()`, `TSThetaSetEndpoint()` 1235316643e7SJed Brown M*/ 1236d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode TSCreate_Theta(TS ts) 1237d71ae5a4SJacob Faibussowitsch { 1238316643e7SJed Brown TS_Theta *th; 1239316643e7SJed Brown 1240316643e7SJed Brown PetscFunctionBegin; 1241277b19d0SLisandro Dalcin ts->ops->reset = TSReset_Theta; 1242ece46509SHong Zhang ts->ops->adjointreset = TSAdjointReset_Theta; 1243316643e7SJed Brown ts->ops->destroy = TSDestroy_Theta; 1244316643e7SJed Brown ts->ops->view = TSView_Theta; 1245316643e7SJed Brown ts->ops->setup = TSSetUp_Theta; 124642f2b339SBarry Smith ts->ops->adjointsetup = TSAdjointSetUp_Theta; 1247ece46509SHong Zhang ts->ops->adjointreset = TSAdjointReset_Theta; 1248316643e7SJed Brown ts->ops->step = TSStep_Theta; 1249cd652676SJed Brown ts->ops->interpolate = TSInterpolate_Theta; 12501566a47fSLisandro Dalcin ts->ops->evaluatewlte = TSEvaluateWLTE_Theta; 125124655328SShri ts->ops->rollback = TSRollBack_Theta; 125226b5f05dSStefano Zampini ts->ops->resizeregister = TSResizeRegister_Theta; 1253316643e7SJed Brown ts->ops->setfromoptions = TSSetFromOptions_Theta; 12540f5c6efeSJed Brown ts->ops->snesfunction = SNESTSFormFunction_Theta; 12550f5c6efeSJed Brown ts->ops->snesjacobian = SNESTSFormJacobian_Theta; 1256f9c1d6abSBarry Smith #if defined(PETSC_HAVE_COMPLEX) 1257f9c1d6abSBarry Smith ts->ops->linearstability = TSComputeLinearStability_Theta; 1258f9c1d6abSBarry Smith #endif 125942682096SHong Zhang ts->ops->getstages = TSGetStages_Theta; 126042f2b339SBarry Smith ts->ops->adjointstep = TSAdjointStep_Theta; 1261b1cb36f3SHong Zhang ts->ops->adjointintegral = TSAdjointCostIntegral_Theta; 1262b1cb36f3SHong Zhang ts->ops->forwardintegral = TSForwardCostIntegral_Theta; 12632ffb9264SLisandro Dalcin ts->default_adapt_type = TSADAPTNONE; 12646affb6f8SHong Zhang 1265715f1b00SHong Zhang ts->ops->forwardsetup = TSForwardSetUp_Theta; 12667adebddeSHong Zhang ts->ops->forwardreset = TSForwardReset_Theta; 1267715f1b00SHong Zhang ts->ops->forwardstep = TSForwardStep_Theta; 12686affb6f8SHong Zhang ts->ops->forwardgetstages = TSForwardGetStages_Theta; 1269316643e7SJed Brown 1270efd4aadfSBarry Smith ts->usessnes = PETSC_TRUE; 1271efd4aadfSBarry Smith 12724dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&th)); 1273316643e7SJed Brown ts->data = (void *)th; 1274316643e7SJed Brown 1275715f1b00SHong Zhang th->VecsDeltaLam = NULL; 1276715f1b00SHong Zhang th->VecsDeltaMu = NULL; 1277715f1b00SHong Zhang th->VecsSensiTemp = NULL; 1278b5b4017aSHong Zhang th->VecsSensi2Temp = NULL; 1279715f1b00SHong Zhang 12806f700aefSJed Brown th->extrapolate = PETSC_FALSE; 1281316643e7SJed Brown th->Theta = 0.5; 12821566a47fSLisandro Dalcin th->order = 2; 12839566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSThetaGetTheta_C", TSThetaGetTheta_Theta)); 12849566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSThetaSetTheta_C", TSThetaSetTheta_Theta)); 12859566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSThetaGetEndpoint_C", TSThetaGetEndpoint_Theta)); 12869566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSThetaSetEndpoint_C", TSThetaSetEndpoint_Theta)); 12873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1288316643e7SJed Brown } 12890de4c49aSJed Brown 12900de4c49aSJed Brown /*@ 1291bcf0153eSBarry Smith TSThetaGetTheta - Get the abscissa of the stage in (0,1] for `TSTHETA` 12920de4c49aSJed Brown 12930de4c49aSJed Brown Not Collective 12940de4c49aSJed Brown 12950de4c49aSJed Brown Input Parameter: 12960de4c49aSJed Brown . ts - timestepping context 12970de4c49aSJed Brown 12980de4c49aSJed Brown Output Parameter: 12990de4c49aSJed Brown . theta - stage abscissa 13000de4c49aSJed Brown 1301bcf0153eSBarry Smith Level: advanced 1302bcf0153eSBarry Smith 13030de4c49aSJed Brown Note: 1304bcf0153eSBarry Smith Use of this function is normally only required to hack `TSTHETA` to use a modified integration scheme. 13050de4c49aSJed Brown 13061cc06b55SBarry Smith .seealso: [](ch_ts), `TSThetaSetTheta()`, `TSTHETA` 13070de4c49aSJed Brown @*/ 1308d71ae5a4SJacob Faibussowitsch PetscErrorCode TSThetaGetTheta(TS ts, PetscReal *theta) 1309d71ae5a4SJacob Faibussowitsch { 13100de4c49aSJed Brown PetscFunctionBegin; 1311afb20b64SJed Brown PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 13124f572ea9SToby Isaac PetscAssertPointer(theta, 2); 1313cac4c232SBarry Smith PetscUseMethod(ts, "TSThetaGetTheta_C", (TS, PetscReal *), (ts, theta)); 13143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13150de4c49aSJed Brown } 13160de4c49aSJed Brown 13170de4c49aSJed Brown /*@ 1318bcf0153eSBarry Smith TSThetaSetTheta - Set the abscissa of the stage in (0,1] for `TSTHETA` 13190de4c49aSJed Brown 13200de4c49aSJed Brown Not Collective 13210de4c49aSJed Brown 1322d8d19677SJose E. Roman Input Parameters: 13230de4c49aSJed Brown + ts - timestepping context 13240de4c49aSJed Brown - theta - stage abscissa 13250de4c49aSJed Brown 1326bcf0153eSBarry Smith Options Database Key: 132767b8a455SSatish Balay . -ts_theta_theta <theta> - set theta 13280de4c49aSJed Brown 1329bcf0153eSBarry Smith Level: intermediate 13300de4c49aSJed Brown 13311cc06b55SBarry Smith .seealso: [](ch_ts), `TSThetaGetTheta()`, `TSTHETA`, `TSCN` 13320de4c49aSJed Brown @*/ 1333d71ae5a4SJacob Faibussowitsch PetscErrorCode TSThetaSetTheta(TS ts, PetscReal theta) 1334d71ae5a4SJacob Faibussowitsch { 13350de4c49aSJed Brown PetscFunctionBegin; 1336afb20b64SJed Brown PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1337cac4c232SBarry Smith PetscTryMethod(ts, "TSThetaSetTheta_C", (TS, PetscReal), (ts, theta)); 13383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13390de4c49aSJed Brown } 1340f33bbcb6SJed Brown 134126f2ff8fSLisandro Dalcin /*@ 1342bcf0153eSBarry Smith TSThetaGetEndpoint - Gets whether to use the endpoint variant of the method (e.g. trapezoid/Crank-Nicolson instead of midpoint rule) for `TSTHETA` 134326f2ff8fSLisandro Dalcin 134426f2ff8fSLisandro Dalcin Not Collective 134526f2ff8fSLisandro Dalcin 134626f2ff8fSLisandro Dalcin Input Parameter: 134726f2ff8fSLisandro Dalcin . ts - timestepping context 134826f2ff8fSLisandro Dalcin 134926f2ff8fSLisandro Dalcin Output Parameter: 1350bcf0153eSBarry Smith . endpoint - `PETSC_TRUE` when using the endpoint variant 135126f2ff8fSLisandro Dalcin 1352bcf0153eSBarry Smith Level: advanced 135326f2ff8fSLisandro Dalcin 13541cc06b55SBarry Smith .seealso: [](ch_ts), `TSThetaSetEndpoint()`, `TSTHETA`, `TSCN` 135526f2ff8fSLisandro Dalcin @*/ 1356d71ae5a4SJacob Faibussowitsch PetscErrorCode TSThetaGetEndpoint(TS ts, PetscBool *endpoint) 1357d71ae5a4SJacob Faibussowitsch { 135826f2ff8fSLisandro Dalcin PetscFunctionBegin; 135926f2ff8fSLisandro Dalcin PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 13604f572ea9SToby Isaac PetscAssertPointer(endpoint, 2); 1361cac4c232SBarry Smith PetscUseMethod(ts, "TSThetaGetEndpoint_C", (TS, PetscBool *), (ts, endpoint)); 13623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 136326f2ff8fSLisandro Dalcin } 136426f2ff8fSLisandro Dalcin 1365eb284becSJed Brown /*@ 1366bcf0153eSBarry Smith TSThetaSetEndpoint - Sets whether to use the endpoint variant of the method (e.g. trapezoid/Crank-Nicolson instead of midpoint rule) for `TSTHETA` 1367eb284becSJed Brown 1368eb284becSJed Brown Not Collective 1369eb284becSJed Brown 1370d8d19677SJose E. Roman Input Parameters: 1371eb284becSJed Brown + ts - timestepping context 1372bcf0153eSBarry Smith - flg - `PETSC_TRUE` to use the endpoint variant 1373eb284becSJed Brown 1374bcf0153eSBarry Smith Options Database Key: 137567b8a455SSatish Balay . -ts_theta_endpoint <flg> - use the endpoint variant 1376eb284becSJed Brown 1377bcf0153eSBarry Smith Level: intermediate 1378eb284becSJed Brown 13791cc06b55SBarry Smith .seealso: [](ch_ts), `TSTHETA`, `TSCN` 1380eb284becSJed Brown @*/ 1381d71ae5a4SJacob Faibussowitsch PetscErrorCode TSThetaSetEndpoint(TS ts, PetscBool flg) 1382d71ae5a4SJacob Faibussowitsch { 1383eb284becSJed Brown PetscFunctionBegin; 1384eb284becSJed Brown PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1385cac4c232SBarry Smith PetscTryMethod(ts, "TSThetaSetEndpoint_C", (TS, PetscBool), (ts, flg)); 13863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1387eb284becSJed Brown } 1388eb284becSJed Brown 1389f33bbcb6SJed Brown /* 1390f33bbcb6SJed Brown * TSBEULER and TSCN are straightforward specializations of TSTHETA. 1391f33bbcb6SJed Brown * The creation functions for these specializations are below. 1392f33bbcb6SJed Brown */ 1393f33bbcb6SJed Brown 1394d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSSetUp_BEuler(TS ts) 1395d71ae5a4SJacob Faibussowitsch { 13961566a47fSLisandro Dalcin TS_Theta *th = (TS_Theta *)ts->data; 13971566a47fSLisandro Dalcin 13981566a47fSLisandro Dalcin PetscFunctionBegin; 139908401ef6SPierre 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"); 140028b400f6SJacob 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"); 14019566063dSJacob Faibussowitsch PetscCall(TSSetUp_Theta(ts)); 14023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14031566a47fSLisandro Dalcin } 14041566a47fSLisandro Dalcin 1405d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSView_BEuler(TS ts, PetscViewer viewer) 1406d71ae5a4SJacob Faibussowitsch { 1407f33bbcb6SJed Brown PetscFunctionBegin; 14083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1409f33bbcb6SJed Brown } 1410f33bbcb6SJed Brown 1411f33bbcb6SJed Brown /*MC 1412f33bbcb6SJed Brown TSBEULER - ODE solver using the implicit backward Euler method 1413f33bbcb6SJed Brown 1414f33bbcb6SJed Brown Level: beginner 1415f33bbcb6SJed Brown 1416bcf0153eSBarry Smith Note: 141737fdd005SBarry Smith `TSBEULER` is equivalent to `TSTHETA` with Theta=1.0 or `-ts_type theta -ts_theta_theta 1.0` 14184eb428fdSBarry Smith 14191cc06b55SBarry Smith .seealso: [](ch_ts), `TSCreate()`, `TS`, `TSSetType()`, `TSEULER`, `TSCN`, `TSTHETA` 1420f33bbcb6SJed Brown M*/ 1421d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode TSCreate_BEuler(TS ts) 1422d71ae5a4SJacob Faibussowitsch { 1423f33bbcb6SJed Brown PetscFunctionBegin; 14249566063dSJacob Faibussowitsch PetscCall(TSCreate_Theta(ts)); 14259566063dSJacob Faibussowitsch PetscCall(TSThetaSetTheta(ts, 1.0)); 14269566063dSJacob Faibussowitsch PetscCall(TSThetaSetEndpoint(ts, PETSC_FALSE)); 14270c7376e5SHong Zhang ts->ops->setup = TSSetUp_BEuler; 1428f33bbcb6SJed Brown ts->ops->view = TSView_BEuler; 14293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1430f33bbcb6SJed Brown } 1431f33bbcb6SJed Brown 1432d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSSetUp_CN(TS ts) 1433d71ae5a4SJacob Faibussowitsch { 14341566a47fSLisandro Dalcin TS_Theta *th = (TS_Theta *)ts->data; 14351566a47fSLisandro Dalcin 14361566a47fSLisandro Dalcin PetscFunctionBegin; 143708401ef6SPierre 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"); 14383c633725SBarry 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"); 14399566063dSJacob Faibussowitsch PetscCall(TSSetUp_Theta(ts)); 14403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14411566a47fSLisandro Dalcin } 14421566a47fSLisandro Dalcin 1443d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSView_CN(TS ts, PetscViewer viewer) 1444d71ae5a4SJacob Faibussowitsch { 1445f33bbcb6SJed Brown PetscFunctionBegin; 14463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1447f33bbcb6SJed Brown } 1448f33bbcb6SJed Brown 1449f33bbcb6SJed Brown /*MC 1450f33bbcb6SJed Brown TSCN - ODE solver using the implicit Crank-Nicolson method. 1451f33bbcb6SJed Brown 1452f33bbcb6SJed Brown Level: beginner 1453f33bbcb6SJed Brown 1454f33bbcb6SJed Brown Notes: 1455bcf0153eSBarry Smith `TSCN` is equivalent to `TSTHETA` with Theta=0.5 and the "endpoint" option set. I.e. 1456bcf0153eSBarry Smith .vb 1457bcf0153eSBarry Smith -ts_type theta 1458bcf0153eSBarry Smith -ts_theta_theta 0.5 1459bcf0153eSBarry Smith -ts_theta_endpoint 1460bcf0153eSBarry Smith .ve 14617cf5af47SJed Brown 14621cc06b55SBarry Smith .seealso: [](ch_ts), `TSCreate()`, `TS`, `TSSetType()`, `TSBEULER`, `TSTHETA`, `TSType`, 1463f33bbcb6SJed Brown M*/ 1464d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode TSCreate_CN(TS ts) 1465d71ae5a4SJacob Faibussowitsch { 1466f33bbcb6SJed Brown PetscFunctionBegin; 14679566063dSJacob Faibussowitsch PetscCall(TSCreate_Theta(ts)); 14689566063dSJacob Faibussowitsch PetscCall(TSThetaSetTheta(ts, 0.5)); 14699566063dSJacob Faibussowitsch PetscCall(TSThetaSetEndpoint(ts, PETSC_TRUE)); 14700c7376e5SHong Zhang ts->ops->setup = TSSetUp_CN; 1471f33bbcb6SJed Brown ts->ops->view = TSView_CN; 14723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1473f33bbcb6SJed Brown } 1474