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 457445fe48SJed Brown static PetscErrorCode TSThetaGetX0AndXdot(TS ts,DM dm,Vec *X0,Vec *Xdot) 467445fe48SJed Brown { 477445fe48SJed Brown TS_Theta *th = (TS_Theta*)ts->data; 487445fe48SJed Brown 497445fe48SJed Brown PetscFunctionBegin; 507445fe48SJed Brown if (X0) { 517445fe48SJed Brown if (dm && dm != ts->dm) { 525f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetNamedGlobalVector(dm,"TSTheta_X0",X0)); 537445fe48SJed Brown } else *X0 = ts->vec_sol; 547445fe48SJed Brown } 557445fe48SJed Brown if (Xdot) { 567445fe48SJed Brown if (dm && dm != ts->dm) { 575f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetNamedGlobalVector(dm,"TSTheta_Xdot",Xdot)); 587445fe48SJed Brown } else *Xdot = th->Xdot; 597445fe48SJed Brown } 607445fe48SJed Brown PetscFunctionReturn(0); 617445fe48SJed Brown } 627445fe48SJed Brown 630d0b770aSPeter Brune static PetscErrorCode TSThetaRestoreX0AndXdot(TS ts,DM dm,Vec *X0,Vec *Xdot) 640d0b770aSPeter Brune { 650d0b770aSPeter Brune PetscFunctionBegin; 660d0b770aSPeter Brune if (X0) { 670d0b770aSPeter Brune if (dm && dm != ts->dm) { 685f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreNamedGlobalVector(dm,"TSTheta_X0",X0)); 690d0b770aSPeter Brune } 700d0b770aSPeter Brune } 710d0b770aSPeter Brune if (Xdot) { 720d0b770aSPeter Brune if (dm && dm != ts->dm) { 735f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreNamedGlobalVector(dm,"TSTheta_Xdot",Xdot)); 740d0b770aSPeter Brune } 750d0b770aSPeter Brune } 760d0b770aSPeter Brune PetscFunctionReturn(0); 770d0b770aSPeter Brune } 780d0b770aSPeter Brune 797445fe48SJed Brown static PetscErrorCode DMCoarsenHook_TSTheta(DM fine,DM coarse,void *ctx) 807445fe48SJed Brown { 817445fe48SJed Brown PetscFunctionBegin; 827445fe48SJed Brown PetscFunctionReturn(0); 837445fe48SJed Brown } 847445fe48SJed Brown 857445fe48SJed Brown static PetscErrorCode DMRestrictHook_TSTheta(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse,void *ctx) 867445fe48SJed Brown { 877445fe48SJed Brown TS ts = (TS)ctx; 887445fe48SJed Brown Vec X0,Xdot,X0_c,Xdot_c; 897445fe48SJed Brown 907445fe48SJed Brown PetscFunctionBegin; 915f80ce2aSJacob Faibussowitsch CHKERRQ(TSThetaGetX0AndXdot(ts,fine,&X0,&Xdot)); 925f80ce2aSJacob Faibussowitsch CHKERRQ(TSThetaGetX0AndXdot(ts,coarse,&X0_c,&Xdot_c)); 935f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestrict(restrct,X0,X0_c)); 945f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestrict(restrct,Xdot,Xdot_c)); 955f80ce2aSJacob Faibussowitsch CHKERRQ(VecPointwiseMult(X0_c,rscale,X0_c)); 965f80ce2aSJacob Faibussowitsch CHKERRQ(VecPointwiseMult(Xdot_c,rscale,Xdot_c)); 975f80ce2aSJacob Faibussowitsch CHKERRQ(TSThetaRestoreX0AndXdot(ts,fine,&X0,&Xdot)); 985f80ce2aSJacob Faibussowitsch CHKERRQ(TSThetaRestoreX0AndXdot(ts,coarse,&X0_c,&Xdot_c)); 997445fe48SJed Brown PetscFunctionReturn(0); 1007445fe48SJed Brown } 1017445fe48SJed Brown 102258e1594SPeter Brune static PetscErrorCode DMSubDomainHook_TSTheta(DM dm,DM subdm,void *ctx) 103258e1594SPeter Brune { 104258e1594SPeter Brune PetscFunctionBegin; 105258e1594SPeter Brune PetscFunctionReturn(0); 106258e1594SPeter Brune } 107258e1594SPeter Brune 108258e1594SPeter Brune static PetscErrorCode DMSubDomainRestrictHook_TSTheta(DM dm,VecScatter gscat,VecScatter lscat,DM subdm,void *ctx) 109258e1594SPeter Brune { 110258e1594SPeter Brune TS ts = (TS)ctx; 111258e1594SPeter Brune Vec X0,Xdot,X0_sub,Xdot_sub; 112258e1594SPeter Brune 113258e1594SPeter Brune PetscFunctionBegin; 1145f80ce2aSJacob Faibussowitsch CHKERRQ(TSThetaGetX0AndXdot(ts,dm,&X0,&Xdot)); 1155f80ce2aSJacob Faibussowitsch CHKERRQ(TSThetaGetX0AndXdot(ts,subdm,&X0_sub,&Xdot_sub)); 116258e1594SPeter Brune 1175f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(gscat,X0,X0_sub,INSERT_VALUES,SCATTER_FORWARD)); 1185f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(gscat,X0,X0_sub,INSERT_VALUES,SCATTER_FORWARD)); 119258e1594SPeter Brune 1205f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(gscat,Xdot,Xdot_sub,INSERT_VALUES,SCATTER_FORWARD)); 1215f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(gscat,Xdot,Xdot_sub,INSERT_VALUES,SCATTER_FORWARD)); 122258e1594SPeter Brune 1235f80ce2aSJacob Faibussowitsch CHKERRQ(TSThetaRestoreX0AndXdot(ts,dm,&X0,&Xdot)); 1245f80ce2aSJacob Faibussowitsch CHKERRQ(TSThetaRestoreX0AndXdot(ts,subdm,&X0_sub,&Xdot_sub)); 125258e1594SPeter Brune PetscFunctionReturn(0); 126258e1594SPeter Brune } 127258e1594SPeter Brune 128022c081aSHong Zhang static PetscErrorCode TSThetaEvaluateCostIntegral(TS ts) 129022c081aSHong Zhang { 130022c081aSHong Zhang TS_Theta *th = (TS_Theta*)ts->data; 131cd4cee2dSHong Zhang TS quadts = ts->quadraturets; 132022c081aSHong Zhang 133022c081aSHong Zhang PetscFunctionBegin; 134022c081aSHong Zhang if (th->endpoint) { 135022c081aSHong Zhang /* Evolve ts->vec_costintegral to compute integrals */ 136022c081aSHong Zhang if (th->Theta!=1.0) { 1375f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeRHSFunction(quadts,th->ptime0,th->X0,ts->vec_costintegrand)); 1385f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(quadts->vec_sol,th->time_step0*(1.0-th->Theta),ts->vec_costintegrand)); 139022c081aSHong Zhang } 1405f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeRHSFunction(quadts,ts->ptime,ts->vec_sol,ts->vec_costintegrand)); 1415f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(quadts->vec_sol,th->time_step0*th->Theta,ts->vec_costintegrand)); 142022c081aSHong Zhang } else { 1435f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeRHSFunction(quadts,th->stage_time,th->X,ts->vec_costintegrand)); 1445f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(quadts->vec_sol,th->time_step0,ts->vec_costintegrand)); 145022c081aSHong Zhang } 146022c081aSHong Zhang PetscFunctionReturn(0); 147022c081aSHong Zhang } 148022c081aSHong Zhang 149b1cb36f3SHong Zhang static PetscErrorCode TSForwardCostIntegral_Theta(TS ts) 150b1cb36f3SHong Zhang { 151b1cb36f3SHong Zhang TS_Theta *th = (TS_Theta*)ts->data; 152cd4cee2dSHong Zhang TS quadts = ts->quadraturets; 153b1cb36f3SHong Zhang 154b1cb36f3SHong Zhang PetscFunctionBegin; 155b1cb36f3SHong Zhang /* backup cost integral */ 1565f80ce2aSJacob Faibussowitsch CHKERRQ(VecCopy(quadts->vec_sol,th->VecCostIntegral0)); 1575f80ce2aSJacob Faibussowitsch CHKERRQ(TSThetaEvaluateCostIntegral(ts)); 158b1cb36f3SHong Zhang PetscFunctionReturn(0); 159b1cb36f3SHong Zhang } 160b1cb36f3SHong Zhang 161b1cb36f3SHong Zhang static PetscErrorCode TSAdjointCostIntegral_Theta(TS ts) 162b1cb36f3SHong Zhang { 1631a352fa8SHong Zhang TS_Theta *th = (TS_Theta*)ts->data; 164b1cb36f3SHong Zhang 165b1cb36f3SHong Zhang PetscFunctionBegin; 1661a352fa8SHong Zhang /* Like TSForwardCostIntegral(), the adjoint cost integral evaluation relies on ptime0 and time_step0. */ 1671a352fa8SHong Zhang th->ptime0 = ts->ptime + ts->time_step; 1681a352fa8SHong Zhang th->time_step0 = -ts->time_step; 1695f80ce2aSJacob Faibussowitsch CHKERRQ(TSThetaEvaluateCostIntegral(ts)); 17024655328SShri PetscFunctionReturn(0); 17124655328SShri } 17224655328SShri 173470880abSPatrick Sanan static PetscErrorCode TSTheta_SNESSolve(TS ts,Vec b,Vec x) 1741566a47fSLisandro Dalcin { 1751566a47fSLisandro Dalcin PetscInt nits,lits; 1761566a47fSLisandro Dalcin 1771566a47fSLisandro Dalcin PetscFunctionBegin; 1785f80ce2aSJacob Faibussowitsch CHKERRQ(SNESSolve(ts->snes,b,x)); 1795f80ce2aSJacob Faibussowitsch CHKERRQ(SNESGetIterationNumber(ts->snes,&nits)); 1805f80ce2aSJacob Faibussowitsch CHKERRQ(SNESGetLinearSolveIterations(ts->snes,&lits)); 1811566a47fSLisandro Dalcin ts->snes_its += nits; ts->ksp_its += lits; 1821566a47fSLisandro Dalcin PetscFunctionReturn(0); 1831566a47fSLisandro Dalcin } 1841566a47fSLisandro Dalcin 185193ac0bcSJed Brown static PetscErrorCode TSStep_Theta(TS ts) 186316643e7SJed Brown { 187316643e7SJed Brown TS_Theta *th = (TS_Theta*)ts->data; 1881566a47fSLisandro Dalcin PetscInt rejections = 0; 1894957b756SLisandro Dalcin PetscBool stageok,accept = PETSC_TRUE; 1901566a47fSLisandro Dalcin PetscReal next_time_step = ts->time_step; 191316643e7SJed Brown 192316643e7SJed Brown PetscFunctionBegin; 1931566a47fSLisandro Dalcin if (!ts->steprollback) { 1945f80ce2aSJacob Faibussowitsch if (th->vec_sol_prev) CHKERRQ(VecCopy(th->X0,th->vec_sol_prev)); 1955f80ce2aSJacob Faibussowitsch CHKERRQ(VecCopy(ts->vec_sol,th->X0)); 1961566a47fSLisandro Dalcin } 1971566a47fSLisandro Dalcin 1981566a47fSLisandro Dalcin th->status = TS_STEP_INCOMPLETE; 19999260352SHong Zhang while (!ts->reason && th->status != TS_STEP_COMPLETE) { 2003e05ceb1SHong Zhang th->shift = 1/(th->Theta*ts->time_step); 2011566a47fSLisandro Dalcin th->stage_time = ts->ptime + (th->endpoint ? (PetscReal)1 : th->Theta)*ts->time_step; 2025f80ce2aSJacob Faibussowitsch CHKERRQ(VecCopy(th->X0,th->X)); 203fecfb714SLisandro Dalcin if (th->extrapolate && !ts->steprestart) { 2045f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(th->X,1/th->shift,th->Xdot)); 205be5899b3SLisandro Dalcin } 206eb284becSJed Brown if (th->endpoint) { /* This formulation assumes linear time-independent mass matrix */ 2075f80ce2aSJacob Faibussowitsch if (!th->affine) CHKERRQ(VecDuplicate(ts->vec_sol,&th->affine)); 2085f80ce2aSJacob Faibussowitsch CHKERRQ(VecZeroEntries(th->Xdot)); 2095f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeIFunction(ts,ts->ptime,th->X0,th->Xdot,th->affine,PETSC_FALSE)); 2105f80ce2aSJacob Faibussowitsch CHKERRQ(VecScale(th->affine,(th->Theta-1)/th->Theta)); 2111566a47fSLisandro Dalcin } else if (th->affine) { /* Just in case th->endpoint is changed between calls to TSStep_Theta() */ 2125f80ce2aSJacob Faibussowitsch CHKERRQ(VecZeroEntries(th->affine)); 213eb284becSJed Brown } 2145f80ce2aSJacob Faibussowitsch CHKERRQ(TSPreStage(ts,th->stage_time)); 2155f80ce2aSJacob Faibussowitsch CHKERRQ(TSTheta_SNESSolve(ts,th->affine,th->X)); 2165f80ce2aSJacob Faibussowitsch CHKERRQ(TSPostStage(ts,th->stage_time,0,&th->X)); 2175f80ce2aSJacob Faibussowitsch CHKERRQ(TSAdaptCheckStage(ts->adapt,ts,th->stage_time,th->X,&stageok)); 218fecfb714SLisandro Dalcin if (!stageok) goto reject_step; 219051f2191SLisandro Dalcin 220051f2191SLisandro Dalcin th->status = TS_STEP_PENDING; 2211566a47fSLisandro Dalcin if (th->endpoint) { 2225f80ce2aSJacob Faibussowitsch CHKERRQ(VecCopy(th->X,ts->vec_sol)); 2231566a47fSLisandro Dalcin } else { 2245f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPBYPCZ(th->Xdot,-th->shift,th->shift,0,th->X0,th->X)); 2255f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(ts->vec_sol,ts->time_step,th->Xdot)); 2261566a47fSLisandro Dalcin } 2275f80ce2aSJacob Faibussowitsch CHKERRQ(TSAdaptChoose(ts->adapt,ts,ts->time_step,NULL,&next_time_step,&accept)); 2281566a47fSLisandro Dalcin th->status = accept ? TS_STEP_COMPLETE : TS_STEP_INCOMPLETE; 2291566a47fSLisandro Dalcin if (!accept) { 2305f80ce2aSJacob Faibussowitsch CHKERRQ(VecCopy(th->X0,ts->vec_sol)); 231be5899b3SLisandro Dalcin ts->time_step = next_time_step; 232be5899b3SLisandro Dalcin goto reject_step; 233051f2191SLisandro Dalcin } 2343b1890cdSShri Abhyankar 235715f1b00SHong Zhang if (ts->forward_solve || ts->costintegralfwd) { /* Save the info for the later use in cost integral evaluation */ 2361a352fa8SHong Zhang th->ptime0 = ts->ptime; 2371a352fa8SHong Zhang th->time_step0 = ts->time_step; 23817145e75SHong Zhang } 2392b5a38e1SLisandro Dalcin ts->ptime += ts->time_step; 240cdbf8f93SLisandro Dalcin ts->time_step = next_time_step; 241051f2191SLisandro Dalcin break; 242051f2191SLisandro Dalcin 243051f2191SLisandro Dalcin reject_step: 244fecfb714SLisandro Dalcin ts->reject++; accept = PETSC_FALSE; 2451566a47fSLisandro Dalcin if (!ts->reason && ++rejections > ts->max_reject && ts->max_reject >= 0) { 246051f2191SLisandro Dalcin ts->reason = TS_DIVERGED_STEP_REJECTED; 2475f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo(ts,"Step=%D, step rejections %D greater than current TS allowed, stopping solve\n",ts->steps,rejections)); 2483b1890cdSShri Abhyankar } 2493b1890cdSShri Abhyankar } 250316643e7SJed Brown PetscFunctionReturn(0); 251316643e7SJed Brown } 252316643e7SJed Brown 253c9681e5dSHong Zhang static PetscErrorCode TSAdjointStepBEuler_Private(TS ts) 254c9681e5dSHong Zhang { 255c9681e5dSHong Zhang TS_Theta *th = (TS_Theta*)ts->data; 256cd4cee2dSHong Zhang TS quadts = ts->quadraturets; 257c9681e5dSHong Zhang Vec *VecsDeltaLam = th->VecsDeltaLam,*VecsDeltaMu = th->VecsDeltaMu,*VecsSensiTemp = th->VecsSensiTemp; 258c9681e5dSHong Zhang Vec *VecsDeltaLam2 = th->VecsDeltaLam2,*VecsDeltaMu2 = th->VecsDeltaMu2,*VecsSensi2Temp = th->VecsSensi2Temp; 259c9681e5dSHong Zhang PetscInt nadj; 2607207e0fdSHong Zhang Mat J,Jpre,quadJ = NULL,quadJp = NULL; 261c9681e5dSHong Zhang KSP ksp; 262c9681e5dSHong Zhang PetscScalar *xarr; 263077c4feaSHong Zhang TSEquationType eqtype; 264077c4feaSHong Zhang PetscBool isexplicitode = PETSC_FALSE; 2651a352fa8SHong Zhang PetscReal adjoint_time_step; 266c9681e5dSHong Zhang 267c9681e5dSHong Zhang PetscFunctionBegin; 2685f80ce2aSJacob Faibussowitsch CHKERRQ(TSGetEquationType(ts,&eqtype)); 269077c4feaSHong Zhang if (eqtype == TS_EQ_ODE_EXPLICIT) { 270077c4feaSHong Zhang isexplicitode = PETSC_TRUE; 271077c4feaSHong Zhang VecsDeltaLam = ts->vecs_sensi; 272077c4feaSHong Zhang VecsDeltaLam2 = ts->vecs_sensi2; 273077c4feaSHong Zhang } 274c9681e5dSHong Zhang th->status = TS_STEP_INCOMPLETE; 2755f80ce2aSJacob Faibussowitsch CHKERRQ(SNESGetKSP(ts->snes,&ksp)); 2765f80ce2aSJacob Faibussowitsch CHKERRQ(TSGetIJacobian(ts,&J,&Jpre,NULL,NULL)); 2777207e0fdSHong Zhang if (quadts) { 2785f80ce2aSJacob Faibussowitsch CHKERRQ(TSGetRHSJacobian(quadts,&quadJ,NULL,NULL,NULL)); 2795f80ce2aSJacob Faibussowitsch CHKERRQ(TSGetRHSJacobianP(quadts,&quadJp,NULL,NULL)); 2807207e0fdSHong Zhang } 281c9681e5dSHong Zhang 2821a352fa8SHong Zhang th->stage_time = ts->ptime; 2831a352fa8SHong Zhang adjoint_time_step = -ts->time_step; /* always positive since time_step is negative */ 284c9681e5dSHong Zhang 28533f72c5dSHong Zhang /* Build RHS for first-order adjoint lambda_{n+1}/h + r_u^T(n+1) */ 2867207e0fdSHong Zhang if (quadts) { 2875f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeRHSJacobian(quadts,th->stage_time,ts->vec_sol,quadJ,NULL)); 2887207e0fdSHong Zhang } 289cd4cee2dSHong Zhang 290c9681e5dSHong Zhang for (nadj=0; nadj<ts->numcost; nadj++) { 2915f80ce2aSJacob Faibussowitsch CHKERRQ(VecCopy(ts->vecs_sensi[nadj],VecsSensiTemp[nadj])); 2925f80ce2aSJacob Faibussowitsch CHKERRQ(VecScale(VecsSensiTemp[nadj],1./adjoint_time_step)); /* lambda_{n+1}/h */ 293cd4cee2dSHong Zhang if (quadJ) { 2945f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetColumn(quadJ,nadj,&xarr)); 2955f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(ts->vec_drdu_col,xarr)); 2965f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(VecsSensiTemp[nadj],1.,ts->vec_drdu_col)); 2975f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(ts->vec_drdu_col)); 2985f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreColumn(quadJ,&xarr)); 299c9681e5dSHong Zhang } 300c9681e5dSHong Zhang } 301c9681e5dSHong Zhang 302c9681e5dSHong Zhang /* Build LHS for first-order adjoint */ 303c87ba875SIvan Yashchuk th->shift = 1./adjoint_time_step; 3045f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeSNESJacobian(ts,ts->vec_sol,J,Jpre)); 3055f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetOperators(ksp,J,Jpre)); 306c9681e5dSHong Zhang 307c9681e5dSHong Zhang /* Solve stage equation LHS*lambda_s = RHS for first-order adjoint */ 308c9681e5dSHong Zhang for (nadj=0; nadj<ts->numcost; nadj++) { 309c9681e5dSHong Zhang KSPConvergedReason kspreason; 3105f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSolveTranspose(ksp,VecsSensiTemp[nadj],VecsDeltaLam[nadj])); 3115f80ce2aSJacob Faibussowitsch CHKERRQ(KSPGetConvergedReason(ksp,&kspreason)); 312c9681e5dSHong Zhang if (kspreason < 0) { 313c9681e5dSHong Zhang ts->reason = TSADJOINT_DIVERGED_LINEAR_SOLVE; 3145f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo(ts,"Step=%D, %Dth cost function, transposed linear solve fails, stopping 1st-order adjoint solve\n",ts->steps,nadj)); 315c9681e5dSHong Zhang } 316c9681e5dSHong Zhang } 317c9681e5dSHong Zhang 318c9681e5dSHong Zhang if (ts->vecs_sensi2) { /* U_{n+1} */ 319c9681e5dSHong Zhang /* Get w1 at t_{n+1} from TLM matrix */ 3205f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetColumn(ts->mat_sensip,0,&xarr)); 3215f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(ts->vec_sensip_col,xarr)); 322c9681e5dSHong Zhang /* lambda_s^T F_UU w_1 */ 3235f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeIHessianProductFunctionUU(ts,th->stage_time,ts->vec_sol,VecsDeltaLam,ts->vec_sensip_col,ts->vecs_fuu)); 324c9681e5dSHong Zhang /* lambda_s^T F_UP w_2 */ 3255f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeIHessianProductFunctionUP(ts,th->stage_time,ts->vec_sol,VecsDeltaLam,ts->vec_dir,ts->vecs_fup)); 326c9681e5dSHong Zhang for (nadj=0; nadj<ts->numcost; nadj++) { /* compute the residual */ 3275f80ce2aSJacob Faibussowitsch CHKERRQ(VecCopy(ts->vecs_sensi2[nadj],VecsSensi2Temp[nadj])); 3285f80ce2aSJacob Faibussowitsch CHKERRQ(VecScale(VecsSensi2Temp[nadj],1./adjoint_time_step)); 3295f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(VecsSensi2Temp[nadj],-1.,ts->vecs_fuu[nadj])); 330c9681e5dSHong Zhang if (ts->vecs_fup) { 3315f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(VecsSensi2Temp[nadj],-1.,ts->vecs_fup[nadj])); 332c9681e5dSHong Zhang } 333c9681e5dSHong Zhang } 334c9681e5dSHong Zhang /* Solve stage equation LHS X = RHS for second-order adjoint */ 335c9681e5dSHong Zhang for (nadj=0; nadj<ts->numcost; nadj++) { 33605c9950eSHong Zhang KSPConvergedReason kspreason; 3375f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSolveTranspose(ksp,VecsSensi2Temp[nadj],VecsDeltaLam2[nadj])); 3385f80ce2aSJacob Faibussowitsch CHKERRQ(KSPGetConvergedReason(ksp,&kspreason)); 33905c9950eSHong Zhang if (kspreason < 0) { 34005c9950eSHong Zhang ts->reason = TSADJOINT_DIVERGED_LINEAR_SOLVE; 3415f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo(ts,"Step=%D, %Dth cost function, transposed linear solve fails, stopping 2nd-order adjoint solve\n",ts->steps,nadj)); 34205c9950eSHong Zhang } 343c9681e5dSHong Zhang } 344c9681e5dSHong Zhang } 345c9681e5dSHong Zhang 346c9681e5dSHong Zhang /* Update sensitivities, and evaluate integrals if there is any */ 347077c4feaSHong Zhang if (!isexplicitode) { 3483e05ceb1SHong Zhang th->shift = 0.0; 3495f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeSNESJacobian(ts,ts->vec_sol,J,Jpre)); 3505f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetOperators(ksp,J,Jpre)); 351c9681e5dSHong Zhang for (nadj=0; nadj<ts->numcost; nadj++) { 35233f72c5dSHong Zhang /* Add f_U \lambda_s to the original RHS */ 3535f80ce2aSJacob Faibussowitsch CHKERRQ(VecScale(VecsSensiTemp[nadj],-1.)); 3545f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultTransposeAdd(J,VecsDeltaLam[nadj],VecsSensiTemp[nadj],VecsSensiTemp[nadj])); 3555f80ce2aSJacob Faibussowitsch CHKERRQ(VecScale(VecsSensiTemp[nadj],-adjoint_time_step)); 3565f80ce2aSJacob Faibussowitsch CHKERRQ(VecCopy(VecsSensiTemp[nadj],ts->vecs_sensi[nadj])); 357c9681e5dSHong Zhang if (ts->vecs_sensi2) { 3585f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultTransposeAdd(J,VecsDeltaLam2[nadj],VecsSensi2Temp[nadj],VecsSensi2Temp[nadj])); 3595f80ce2aSJacob Faibussowitsch CHKERRQ(VecScale(VecsSensi2Temp[nadj],-adjoint_time_step)); 3605f80ce2aSJacob Faibussowitsch CHKERRQ(VecCopy(VecsSensi2Temp[nadj],ts->vecs_sensi2[nadj])); 361c9681e5dSHong Zhang } 362c9681e5dSHong Zhang } 363077c4feaSHong Zhang } 364c9681e5dSHong Zhang if (ts->vecs_sensip) { 3655f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPBYPCZ(th->Xdot,-1./adjoint_time_step,1.0/adjoint_time_step,0,th->X0,ts->vec_sol)); 3665f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeIJacobianP(ts,th->stage_time,ts->vec_sol,th->Xdot,1./adjoint_time_step,ts->Jacp,PETSC_FALSE)); /* get -f_p */ 3677207e0fdSHong Zhang if (quadts) { 3685f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeRHSJacobianP(quadts,th->stage_time,ts->vec_sol,quadJp)); 3697207e0fdSHong Zhang } 370c9681e5dSHong Zhang if (ts->vecs_sensi2p) { 371c9681e5dSHong Zhang /* lambda_s^T F_PU w_1 */ 3725f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeIHessianProductFunctionPU(ts,th->stage_time,ts->vec_sol,VecsDeltaLam,ts->vec_sensip_col,ts->vecs_fpu)); 37333f72c5dSHong Zhang /* lambda_s^T F_PP w_2 */ 3745f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeIHessianProductFunctionPP(ts,th->stage_time,ts->vec_sol,VecsDeltaLam,ts->vec_dir,ts->vecs_fpp)); 375c9681e5dSHong Zhang } 376cd4cee2dSHong Zhang 377c9681e5dSHong Zhang for (nadj=0; nadj<ts->numcost; nadj++) { 3785f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultTranspose(ts->Jacp,VecsDeltaLam[nadj],VecsDeltaMu[nadj])); 3795f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(ts->vecs_sensip[nadj],-adjoint_time_step,VecsDeltaMu[nadj])); 380cd4cee2dSHong Zhang if (quadJp) { 3815f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetColumn(quadJp,nadj,&xarr)); 3825f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(ts->vec_drdp_col,xarr)); 3835f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(ts->vecs_sensip[nadj],adjoint_time_step,ts->vec_drdp_col)); 3845f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(ts->vec_drdp_col)); 3855f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreColumn(quadJp,&xarr)); 38633f72c5dSHong Zhang } 387c9681e5dSHong Zhang if (ts->vecs_sensi2p) { 3885f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultTranspose(ts->Jacp,VecsDeltaLam2[nadj],VecsDeltaMu2[nadj])); 3895f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(ts->vecs_sensi2p[nadj],-adjoint_time_step,VecsDeltaMu2[nadj])); 390c9681e5dSHong Zhang if (ts->vecs_fpu) { 3915f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(ts->vecs_sensi2p[nadj],-adjoint_time_step,ts->vecs_fpu[nadj])); 392c9681e5dSHong Zhang } 393c9681e5dSHong Zhang if (ts->vecs_fpp) { 3945f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(ts->vecs_sensi2p[nadj],-adjoint_time_step,ts->vecs_fpp[nadj])); 395c9681e5dSHong Zhang } 396c9681e5dSHong Zhang } 397c9681e5dSHong Zhang } 398c9681e5dSHong Zhang } 399c9681e5dSHong Zhang 400c9681e5dSHong Zhang if (ts->vecs_sensi2) { 4015f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(ts->vec_sensip_col)); 4025f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreColumn(ts->mat_sensip,&xarr)); 403c9681e5dSHong Zhang } 404c9681e5dSHong Zhang th->status = TS_STEP_COMPLETE; 405c9681e5dSHong Zhang PetscFunctionReturn(0); 406c9681e5dSHong Zhang } 407c9681e5dSHong Zhang 40842f2b339SBarry Smith static PetscErrorCode TSAdjointStep_Theta(TS ts) 4092ca6e920SHong Zhang { 4102ca6e920SHong Zhang TS_Theta *th = (TS_Theta*)ts->data; 411cd4cee2dSHong Zhang TS quadts = ts->quadraturets; 412b5e0532dSHong Zhang Vec *VecsDeltaLam = th->VecsDeltaLam,*VecsDeltaMu = th->VecsDeltaMu,*VecsSensiTemp = th->VecsSensiTemp; 413b5b4017aSHong Zhang Vec *VecsDeltaLam2 = th->VecsDeltaLam2,*VecsDeltaMu2 = th->VecsDeltaMu2,*VecsSensi2Temp = th->VecsSensi2Temp; 4142ca6e920SHong Zhang PetscInt nadj; 4157207e0fdSHong Zhang Mat J,Jpre,quadJ = NULL,quadJp = NULL; 4162ca6e920SHong Zhang KSP ksp; 417b5b4017aSHong Zhang PetscScalar *xarr; 4181a352fa8SHong Zhang PetscReal adjoint_time_step; 4191a352fa8SHong Zhang PetscReal adjoint_ptime; /* end time of the adjoint time step (ts->ptime is the start time, ususally ts->ptime is larger than adjoint_ptime) */ 4202ca6e920SHong Zhang 4212ca6e920SHong Zhang PetscFunctionBegin; 422c9681e5dSHong Zhang if (th->Theta == 1.) { 4235f80ce2aSJacob Faibussowitsch CHKERRQ(TSAdjointStepBEuler_Private(ts)); 424c9681e5dSHong Zhang PetscFunctionReturn(0); 425c9681e5dSHong Zhang } 4262ca6e920SHong Zhang th->status = TS_STEP_INCOMPLETE; 4275f80ce2aSJacob Faibussowitsch CHKERRQ(SNESGetKSP(ts->snes,&ksp)); 4285f80ce2aSJacob Faibussowitsch CHKERRQ(TSGetIJacobian(ts,&J,&Jpre,NULL,NULL)); 4297207e0fdSHong Zhang if (quadts) { 4305f80ce2aSJacob Faibussowitsch CHKERRQ(TSGetRHSJacobian(quadts,&quadJ,NULL,NULL,NULL)); 4315f80ce2aSJacob Faibussowitsch CHKERRQ(TSGetRHSJacobianP(quadts,&quadJp,NULL,NULL)); 4327207e0fdSHong Zhang } 433b5e0532dSHong Zhang /* If endpoint=1, th->ptime and th->X0 will be used; if endpoint=0, th->stage_time and th->X will be used. */ 4341a352fa8SHong Zhang th->stage_time = th->endpoint ? ts->ptime : (ts->ptime+(1.-th->Theta)*ts->time_step); 4351a352fa8SHong Zhang adjoint_ptime = ts->ptime + ts->time_step; 4361a352fa8SHong Zhang adjoint_time_step = -ts->time_step; /* always positive since time_step is negative */ 4372ca6e920SHong Zhang 43882ad9101SHong Zhang if (!th->endpoint) { 4395072d23cSHong Zhang /* recover th->X0 using vec_sol and the stage value th->X */ 4405f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPBYPCZ(th->X0,1.0/(1.0-th->Theta),th->Theta/(th->Theta-1.0),0,th->X,ts->vec_sol)); 44182ad9101SHong Zhang } 44282ad9101SHong Zhang 443b5b4017aSHong Zhang /* Build RHS for first-order adjoint */ 44433f72c5dSHong Zhang /* Cost function has an integral term */ 4457207e0fdSHong Zhang if (quadts) { 44605755b9cSHong Zhang if (th->endpoint) { 4475f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeRHSJacobian(quadts,th->stage_time,ts->vec_sol,quadJ,NULL)); 44805755b9cSHong Zhang } else { 4495f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeRHSJacobian(quadts,th->stage_time,th->X,quadJ,NULL)); 45005755b9cSHong Zhang } 4517207e0fdSHong Zhang } 45233f72c5dSHong Zhang 453abc2977eSBarry Smith for (nadj=0; nadj<ts->numcost; nadj++) { 4545f80ce2aSJacob Faibussowitsch CHKERRQ(VecCopy(ts->vecs_sensi[nadj],VecsSensiTemp[nadj])); 4555f80ce2aSJacob Faibussowitsch CHKERRQ(VecScale(VecsSensiTemp[nadj],1./(th->Theta*adjoint_time_step))); 456cd4cee2dSHong Zhang if (quadJ) { 4575f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetColumn(quadJ,nadj,&xarr)); 4585f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(ts->vec_drdu_col,xarr)); 4595f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(VecsSensiTemp[nadj],1.,ts->vec_drdu_col)); 4605f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(ts->vec_drdu_col)); 4615f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreColumn(quadJ,&xarr)); 46236eaed60SHong Zhang } 4632ca6e920SHong Zhang } 4643c54f92cSHong Zhang 465b5b4017aSHong Zhang /* Build LHS for first-order adjoint */ 4661a352fa8SHong Zhang th->shift = 1./(th->Theta*adjoint_time_step); 4673c54f92cSHong Zhang if (th->endpoint) { 4685f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeSNESJacobian(ts,ts->vec_sol,J,Jpre)); 4693c54f92cSHong Zhang } else { 4705f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeSNESJacobian(ts,th->X,J,Jpre)); 4713c54f92cSHong Zhang } 4725f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetOperators(ksp,J,Jpre)); 4732ca6e920SHong Zhang 474b5b4017aSHong Zhang /* Solve stage equation LHS*lambda_s = RHS for first-order adjoint */ 475abc2977eSBarry Smith for (nadj=0; nadj<ts->numcost; nadj++) { 4761d14d03bSHong Zhang KSPConvergedReason kspreason; 4775f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSolveTranspose(ksp,VecsSensiTemp[nadj],VecsDeltaLam[nadj])); 4785f80ce2aSJacob Faibussowitsch CHKERRQ(KSPGetConvergedReason(ksp,&kspreason)); 4791d14d03bSHong Zhang if (kspreason < 0) { 4801d14d03bSHong Zhang ts->reason = TSADJOINT_DIVERGED_LINEAR_SOLVE; 4815f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo(ts,"Step=%D, %Dth cost function, transposed linear solve fails, stopping 1st-order adjoint solve\n",ts->steps,nadj)); 4821d14d03bSHong Zhang } 4832ca6e920SHong Zhang } 4843c54f92cSHong Zhang 4851d14d03bSHong Zhang /* Second-order adjoint */ 486b5b4017aSHong Zhang if (ts->vecs_sensi2) { /* U_{n+1} */ 4873c633725SBarry Smith PetscCheck(th->endpoint,PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Operation not implemented in TS_Theta"); 488b5b4017aSHong Zhang /* Get w1 at t_{n+1} from TLM matrix */ 4895f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetColumn(ts->mat_sensip,0,&xarr)); 4905f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(ts->vec_sensip_col,xarr)); 491b5b4017aSHong Zhang /* lambda_s^T F_UU w_1 */ 4925f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeIHessianProductFunctionUU(ts,th->stage_time,ts->vec_sol,VecsDeltaLam,ts->vec_sensip_col,ts->vecs_fuu)); 4935f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(ts->vec_sensip_col)); 4945f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreColumn(ts->mat_sensip,&xarr)); 495b5b4017aSHong Zhang /* lambda_s^T F_UP w_2 */ 4965f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeIHessianProductFunctionUP(ts,th->stage_time,ts->vec_sol,VecsDeltaLam,ts->vec_dir,ts->vecs_fup)); 497b5b4017aSHong Zhang for (nadj=0; nadj<ts->numcost; nadj++) { /* compute the residual */ 4985f80ce2aSJacob Faibussowitsch CHKERRQ(VecCopy(ts->vecs_sensi2[nadj],VecsSensi2Temp[nadj])); 4995f80ce2aSJacob Faibussowitsch CHKERRQ(VecScale(VecsSensi2Temp[nadj],th->shift)); 5005f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(VecsSensi2Temp[nadj],-1.,ts->vecs_fuu[nadj])); 501b5b4017aSHong Zhang if (ts->vecs_fup) { 5025f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(VecsSensi2Temp[nadj],-1.,ts->vecs_fup[nadj])); 503b5b4017aSHong Zhang } 504b5b4017aSHong Zhang } 505b5b4017aSHong Zhang /* Solve stage equation LHS X = RHS for second-order adjoint */ 506b5b4017aSHong Zhang for (nadj=0; nadj<ts->numcost; nadj++) { 5071d14d03bSHong Zhang KSPConvergedReason kspreason; 5085f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSolveTranspose(ksp,VecsSensi2Temp[nadj],VecsDeltaLam2[nadj])); 5095f80ce2aSJacob Faibussowitsch CHKERRQ(KSPGetConvergedReason(ksp,&kspreason)); 5101d14d03bSHong Zhang if (kspreason < 0) { 5111d14d03bSHong Zhang ts->reason = TSADJOINT_DIVERGED_LINEAR_SOLVE; 5125f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo(ts,"Step=%D, %Dth cost function, transposed linear solve fails, stopping 2nd-order adjoint solve\n",ts->steps,nadj)); 5131d14d03bSHong Zhang } 514b5b4017aSHong Zhang } 515b5b4017aSHong Zhang } 516b5b4017aSHong Zhang 51736eaed60SHong Zhang /* Update sensitivities, and evaluate integrals if there is any */ 5181d14d03bSHong Zhang if (th->endpoint) { /* two-stage Theta methods with th->Theta!=1, th->Theta==1 leads to BEuler */ 5191a352fa8SHong Zhang th->shift = 1./((th->Theta-1.)*adjoint_time_step); 5201a352fa8SHong Zhang th->stage_time = adjoint_ptime; 5215f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeSNESJacobian(ts,th->X0,J,Jpre)); 5225f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetOperators(ksp,J,Jpre)); 52333f72c5dSHong Zhang /* R_U at t_n */ 5247207e0fdSHong Zhang if (quadts) { 5255f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeRHSJacobian(quadts,adjoint_ptime,th->X0,quadJ,NULL)); 5267207e0fdSHong Zhang } 527abc2977eSBarry Smith for (nadj=0; nadj<ts->numcost; nadj++) { 5285f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultTranspose(J,VecsDeltaLam[nadj],ts->vecs_sensi[nadj])); 529cd4cee2dSHong Zhang if (quadJ) { 5305f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetColumn(quadJ,nadj,&xarr)); 5315f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(ts->vec_drdu_col,xarr)); 5325f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(ts->vecs_sensi[nadj],-1.,ts->vec_drdu_col)); 5335f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(ts->vec_drdu_col)); 5345f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreColumn(quadJ,&xarr)); 535b5b4017aSHong Zhang } 5365f80ce2aSJacob Faibussowitsch CHKERRQ(VecScale(ts->vecs_sensi[nadj],1./th->shift)); 537b5b4017aSHong Zhang } 5381d14d03bSHong Zhang 5391d14d03bSHong Zhang /* Second-order adjoint */ 5401d14d03bSHong Zhang if (ts->vecs_sensi2) { /* U_n */ 541b5b4017aSHong Zhang /* Get w1 at t_n from TLM matrix */ 5425f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetColumn(th->MatFwdSensip0,0,&xarr)); 5435f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(ts->vec_sensip_col,xarr)); 544b5b4017aSHong Zhang /* lambda_s^T F_UU w_1 */ 5455f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeIHessianProductFunctionUU(ts,adjoint_ptime,th->X0,VecsDeltaLam,ts->vec_sensip_col,ts->vecs_fuu)); 5465f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(ts->vec_sensip_col)); 5475f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreColumn(th->MatFwdSensip0,&xarr)); 548b5b4017aSHong Zhang /* lambda_s^T F_UU w_2 */ 5495f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeIHessianProductFunctionUP(ts,adjoint_ptime,th->X0,VecsDeltaLam,ts->vec_dir,ts->vecs_fup)); 550b5b4017aSHong Zhang for (nadj=0; nadj<ts->numcost; nadj++) { 55133f72c5dSHong 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 */ 5525f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultTranspose(J,VecsDeltaLam2[nadj],ts->vecs_sensi2[nadj])); 5535f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(ts->vecs_sensi2[nadj],1.,ts->vecs_fuu[nadj])); 554b5b4017aSHong Zhang if (ts->vecs_fup) { 5555f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(ts->vecs_sensi2[nadj],1.,ts->vecs_fup[nadj])); 556b5b4017aSHong Zhang } 5575f80ce2aSJacob Faibussowitsch CHKERRQ(VecScale(ts->vecs_sensi2[nadj],1./th->shift)); 558b5b4017aSHong Zhang } 559b5e0532dSHong Zhang } 5603fd52205SHong Zhang 561c586f2e8SHong Zhang th->stage_time = ts->ptime; /* recover the old value */ 562c586f2e8SHong Zhang 5633fd52205SHong Zhang if (ts->vecs_sensip) { /* sensitivities wrt parameters */ 564b5b4017aSHong Zhang /* U_{n+1} */ 56582ad9101SHong Zhang th->shift = 1.0/(adjoint_time_step*th->Theta); 5665f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPBYPCZ(th->Xdot,-th->shift,th->shift,0,th->X0,ts->vec_sol)); 5675f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeIJacobianP(ts,th->stage_time,ts->vec_sol,th->Xdot,-1./(th->Theta*adjoint_time_step),ts->Jacp,PETSC_FALSE)); 5687207e0fdSHong Zhang if (quadts) { 5695f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeRHSJacobianP(quadts,th->stage_time,ts->vec_sol,quadJp)); 5707207e0fdSHong Zhang } 571abc2977eSBarry Smith for (nadj=0; nadj<ts->numcost; nadj++) { 5725f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultTranspose(ts->Jacp,VecsDeltaLam[nadj],VecsDeltaMu[nadj])); 5735f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(ts->vecs_sensip[nadj],-adjoint_time_step*th->Theta,VecsDeltaMu[nadj])); 5743b711c3fSHong Zhang if (quadJp) { 5755f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetColumn(quadJp,nadj,&xarr)); 5765f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(ts->vec_drdp_col,xarr)); 5775f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(ts->vecs_sensip[nadj],adjoint_time_step*th->Theta,ts->vec_drdp_col)); 5785f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(ts->vec_drdp_col)); 5795f80ce2aSJacob Faibussowitsch CHKERRQ(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 */ 5845f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetColumn(ts->mat_sensip,0,&xarr)); 5855f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(ts->vec_sensip_col,xarr)); 586b5b4017aSHong Zhang /* lambda_s^T F_PU w_1 */ 5875f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeIHessianProductFunctionPU(ts,th->stage_time,ts->vec_sol,VecsDeltaLam,ts->vec_sensip_col,ts->vecs_fpu)); 5885f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(ts->vec_sensip_col)); 5895f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreColumn(ts->mat_sensip,&xarr)); 59033f72c5dSHong Zhang 591b5b4017aSHong Zhang /* lambda_s^T F_PP w_2 */ 5925f80ce2aSJacob Faibussowitsch CHKERRQ(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) */ 5955f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultTranspose(ts->Jacp,VecsDeltaLam2[nadj],VecsDeltaMu2[nadj])); 5965f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(ts->vecs_sensi2p[nadj],-adjoint_time_step*th->Theta,VecsDeltaMu2[nadj])); 597b5b4017aSHong Zhang if (ts->vecs_fpu) { 5985f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(ts->vecs_sensi2p[nadj],-adjoint_time_step*th->Theta,ts->vecs_fpu[nadj])); 599b5b4017aSHong Zhang } 600b5b4017aSHong Zhang if (ts->vecs_fpp) { 6015f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(ts->vecs_sensi2p[nadj],-adjoint_time_step*th->Theta,ts->vecs_fpp[nadj])); 602b5b4017aSHong Zhang } 603b5b4017aSHong Zhang } 604b5b4017aSHong Zhang } 605b5b4017aSHong Zhang 606b5b4017aSHong Zhang /* U_s */ 6075f80ce2aSJacob Faibussowitsch CHKERRQ(VecZeroEntries(th->Xdot)); 6085f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeIJacobianP(ts,adjoint_ptime,th->X0,th->Xdot,1./((th->Theta-1.0)*adjoint_time_step),ts->Jacp,PETSC_FALSE)); 6097207e0fdSHong Zhang if (quadts) { 6105f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeRHSJacobianP(quadts,adjoint_ptime,th->X0,quadJp)); 6117207e0fdSHong Zhang } 612abc2977eSBarry Smith for (nadj=0; nadj<ts->numcost; nadj++) { 6135f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultTranspose(ts->Jacp,VecsDeltaLam[nadj],VecsDeltaMu[nadj])); 6145f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(ts->vecs_sensip[nadj],-adjoint_time_step*(1.0-th->Theta),VecsDeltaMu[nadj])); 6153b711c3fSHong Zhang if (quadJp) { 6165f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetColumn(quadJp,nadj,&xarr)); 6175f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(ts->vec_drdp_col,xarr)); 6185f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(ts->vecs_sensip[nadj],adjoint_time_step*(1.0-th->Theta),ts->vec_drdp_col)); 6195f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(ts->vec_drdp_col)); 6205f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreColumn(quadJp,&xarr)); 6213b711c3fSHong Zhang } 62233f72c5dSHong Zhang if (ts->vecs_sensi2p) { /* second-order */ 62333f72c5dSHong Zhang /* Get w1 at t_n from TLM matrix */ 6245f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetColumn(th->MatFwdSensip0,0,&xarr)); 6255f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(ts->vec_sensip_col,xarr)); 626b5b4017aSHong Zhang /* lambda_s^T F_PU w_1 */ 6275f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeIHessianProductFunctionPU(ts,adjoint_ptime,th->X0,VecsDeltaLam,ts->vec_sensip_col,ts->vecs_fpu)); 6285f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(ts->vec_sensip_col)); 6295f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreColumn(th->MatFwdSensip0,&xarr)); 630b5b4017aSHong Zhang /* lambda_s^T F_PP w_2 */ 6315f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeIHessianProductFunctionPP(ts,adjoint_ptime,th->X0,VecsDeltaLam,ts->vec_dir,ts->vecs_fpp)); 632b5b4017aSHong Zhang for (nadj=0; nadj<ts->numcost; nadj++) { 63333f72c5dSHong 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) */ 6345f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultTranspose(ts->Jacp,VecsDeltaLam2[nadj],VecsDeltaMu2[nadj])); 6355f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(ts->vecs_sensi2p[nadj],-adjoint_time_step*(1.0-th->Theta),VecsDeltaMu2[nadj])); 636b5b4017aSHong Zhang if (ts->vecs_fpu) { 6375f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(ts->vecs_sensi2p[nadj],-adjoint_time_step*(1.0-th->Theta),ts->vecs_fpu[nadj])); 638b5e0532dSHong Zhang } 639b5b4017aSHong Zhang if (ts->vecs_fpp) { 6405f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(ts->vecs_sensi2p[nadj],-adjoint_time_step*(1.0-th->Theta),ts->vecs_fpp[nadj])); 641b5b4017aSHong Zhang } 64236eaed60SHong Zhang } 64336eaed60SHong Zhang } 6443fd52205SHong Zhang } 645b5e0532dSHong Zhang } 6463fd52205SHong Zhang } else { /* one-stage case */ 6473e05ceb1SHong Zhang th->shift = 0.0; 6485f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeSNESJacobian(ts,th->X,J,Jpre)); /* get -f_y */ 6495f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetOperators(ksp,J,Jpre)); 6507207e0fdSHong Zhang if (quadts) { 6515f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeRHSJacobian(quadts,th->stage_time,th->X,quadJ,NULL)); 6527207e0fdSHong Zhang } 653abc2977eSBarry Smith for (nadj=0; nadj<ts->numcost; nadj++) { 6545f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultTranspose(J,VecsDeltaLam[nadj],VecsSensiTemp[nadj])); 6555f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(ts->vecs_sensi[nadj],-adjoint_time_step,VecsSensiTemp[nadj])); 656cd4cee2dSHong Zhang if (quadJ) { 6575f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetColumn(quadJ,nadj,&xarr)); 6585f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(ts->vec_drdu_col,xarr)); 6595f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(ts->vecs_sensi[nadj],adjoint_time_step,ts->vec_drdu_col)); 6605f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(ts->vec_drdu_col)); 6615f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreColumn(quadJ,&xarr)); 66236eaed60SHong Zhang } 6632ca6e920SHong Zhang } 6643fd52205SHong Zhang if (ts->vecs_sensip) { 66582ad9101SHong Zhang th->shift = 1.0/(adjoint_time_step*th->Theta); 6665f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPBYPCZ(th->Xdot,-th->shift,th->shift,0,th->X0,th->X)); 6675f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeIJacobianP(ts,th->stage_time,th->X,th->Xdot,th->shift,ts->Jacp,PETSC_FALSE)); 6687207e0fdSHong Zhang if (quadts) { 6695f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeRHSJacobianP(quadts,th->stage_time,th->X,quadJp)); 6707207e0fdSHong Zhang } 671abc2977eSBarry Smith for (nadj=0; nadj<ts->numcost; nadj++) { 6725f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultTranspose(ts->Jacp,VecsDeltaLam[nadj],VecsDeltaMu[nadj])); 6735f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(ts->vecs_sensip[nadj],-adjoint_time_step,VecsDeltaMu[nadj])); 674cd4cee2dSHong Zhang if (quadJp) { 6755f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetColumn(quadJp,nadj,&xarr)); 6765f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(ts->vec_drdp_col,xarr)); 6775f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(ts->vecs_sensip[nadj],adjoint_time_step,ts->vec_drdp_col)); 6785f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(ts->vec_drdp_col)); 6795f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreColumn(quadJp,&xarr)); 68036eaed60SHong Zhang } 68136eaed60SHong Zhang } 6823fd52205SHong Zhang } 6832ca6e920SHong Zhang } 6842ca6e920SHong Zhang 6852ca6e920SHong Zhang th->status = TS_STEP_COMPLETE; 6862ca6e920SHong Zhang PetscFunctionReturn(0); 6872ca6e920SHong Zhang } 6882ca6e920SHong Zhang 689cd652676SJed Brown static PetscErrorCode TSInterpolate_Theta(TS ts,PetscReal t,Vec X) 690cd652676SJed Brown { 691cd652676SJed Brown TS_Theta *th = (TS_Theta*)ts->data; 692be5899b3SLisandro Dalcin PetscReal dt = t - ts->ptime; 693cd652676SJed Brown 694cd652676SJed Brown PetscFunctionBegin; 6955f80ce2aSJacob Faibussowitsch CHKERRQ(VecCopy(ts->vec_sol,th->X)); 696be5899b3SLisandro Dalcin if (th->endpoint) dt *= th->Theta; 6975f80ce2aSJacob Faibussowitsch CHKERRQ(VecWAXPY(X,dt,th->Xdot,th->X)); 698cd652676SJed Brown PetscFunctionReturn(0); 699cd652676SJed Brown } 700cd652676SJed Brown 7011566a47fSLisandro Dalcin static PetscErrorCode TSEvaluateWLTE_Theta(TS ts,NormType wnormtype,PetscInt *order,PetscReal *wlte) 7021566a47fSLisandro Dalcin { 7031566a47fSLisandro Dalcin TS_Theta *th = (TS_Theta*)ts->data; 7041566a47fSLisandro Dalcin Vec X = ts->vec_sol; /* X = solution */ 7051566a47fSLisandro Dalcin Vec Y = th->vec_lte_work; /* Y = X + LTE */ 7067453f775SEmil Constantinescu PetscReal wltea,wlter; 7071566a47fSLisandro Dalcin 7081566a47fSLisandro Dalcin PetscFunctionBegin; 7092ffb9264SLisandro Dalcin if (!th->vec_sol_prev) {*wlte = -1; PetscFunctionReturn(0);} 7101566a47fSLisandro Dalcin /* Cannot compute LTE in first step or in restart after event */ 711fecfb714SLisandro Dalcin if (ts->steprestart) {*wlte = -1; PetscFunctionReturn(0);} 7121566a47fSLisandro Dalcin /* Compute LTE using backward differences with non-constant time step */ 713fecfb714SLisandro Dalcin { 714be5899b3SLisandro Dalcin PetscReal h = ts->time_step, h_prev = ts->ptime - ts->ptime_prev; 715be5899b3SLisandro Dalcin PetscReal a = 1 + h_prev/h; 7161566a47fSLisandro Dalcin PetscScalar scal[3]; Vec vecs[3]; 7171566a47fSLisandro Dalcin scal[0] = +1/a; scal[1] = -1/(a-1); scal[2] = +1/(a*(a-1)); 7181566a47fSLisandro Dalcin vecs[0] = X; vecs[1] = th->X0; vecs[2] = th->vec_sol_prev; 7195f80ce2aSJacob Faibussowitsch CHKERRQ(VecCopy(X,Y)); 7205f80ce2aSJacob Faibussowitsch CHKERRQ(VecMAXPY(Y,3,scal,vecs)); 7215f80ce2aSJacob Faibussowitsch CHKERRQ(TSErrorWeightedNorm(ts,X,Y,wnormtype,wlte,&wltea,&wlter)); 7221566a47fSLisandro Dalcin } 7231566a47fSLisandro Dalcin if (order) *order = 2; 7241566a47fSLisandro Dalcin PetscFunctionReturn(0); 7251566a47fSLisandro Dalcin } 7261566a47fSLisandro Dalcin 7271566a47fSLisandro Dalcin static PetscErrorCode TSRollBack_Theta(TS ts) 7281566a47fSLisandro Dalcin { 7291566a47fSLisandro Dalcin TS_Theta *th = (TS_Theta*)ts->data; 7307207e0fdSHong Zhang TS quadts = ts->quadraturets; 7311566a47fSLisandro Dalcin 7321566a47fSLisandro Dalcin PetscFunctionBegin; 7335f80ce2aSJacob Faibussowitsch CHKERRQ(VecCopy(th->X0,ts->vec_sol)); 734cd4cee2dSHong Zhang if (quadts && ts->costintegralfwd) { 7355f80ce2aSJacob Faibussowitsch CHKERRQ(VecCopy(th->VecCostIntegral0,quadts->vec_sol)); 7361566a47fSLisandro Dalcin } 737715f1b00SHong Zhang th->status = TS_STEP_INCOMPLETE; 73813b1b0ffSHong Zhang if (ts->mat_sensip) { 7395f80ce2aSJacob Faibussowitsch CHKERRQ(MatCopy(th->MatFwdSensip0,ts->mat_sensip,SAME_NONZERO_PATTERN)); 7406f92202bSHong Zhang } 7417207e0fdSHong Zhang if (quadts && quadts->mat_sensip) { 7425f80ce2aSJacob Faibussowitsch CHKERRQ(MatCopy(th->MatIntegralSensip0,quadts->mat_sensip,SAME_NONZERO_PATTERN)); 7436f92202bSHong Zhang } 744715f1b00SHong Zhang PetscFunctionReturn(0); 745715f1b00SHong Zhang } 746715f1b00SHong Zhang 747715f1b00SHong Zhang static PetscErrorCode TSForwardStep_Theta(TS ts) 748715f1b00SHong Zhang { 749715f1b00SHong Zhang TS_Theta *th = (TS_Theta*)ts->data; 750cd4cee2dSHong Zhang TS quadts = ts->quadraturets; 75113b1b0ffSHong Zhang Mat MatDeltaFwdSensip = th->MatDeltaFwdSensip; 752b5b4017aSHong Zhang Vec VecDeltaFwdSensipCol = th->VecDeltaFwdSensipCol; 7537207e0fdSHong Zhang PetscInt ntlm; 754715f1b00SHong Zhang KSP ksp; 7557207e0fdSHong Zhang Mat J,Jpre,quadJ = NULL,quadJp = NULL; 75613b1b0ffSHong Zhang PetscScalar *barr,*xarr; 7571a352fa8SHong Zhang PetscReal previous_shift; 758715f1b00SHong Zhang 759715f1b00SHong Zhang PetscFunctionBegin; 7601a352fa8SHong Zhang previous_shift = th->shift; 7615f80ce2aSJacob Faibussowitsch CHKERRQ(MatCopy(ts->mat_sensip,th->MatFwdSensip0,SAME_NONZERO_PATTERN)); 76213b1b0ffSHong Zhang 7637207e0fdSHong Zhang if (quadts && quadts->mat_sensip) { 7645f80ce2aSJacob Faibussowitsch CHKERRQ(MatCopy(quadts->mat_sensip,th->MatIntegralSensip0,SAME_NONZERO_PATTERN)); 7656f92202bSHong Zhang } 7665f80ce2aSJacob Faibussowitsch CHKERRQ(SNESGetKSP(ts->snes,&ksp)); 7675f80ce2aSJacob Faibussowitsch CHKERRQ(TSGetIJacobian(ts,&J,&Jpre,NULL,NULL)); 7687207e0fdSHong Zhang if (quadts) { 7695f80ce2aSJacob Faibussowitsch CHKERRQ(TSGetRHSJacobian(quadts,&quadJ,NULL,NULL,NULL)); 7705f80ce2aSJacob Faibussowitsch CHKERRQ(TSGetRHSJacobianP(quadts,&quadJp,NULL,NULL)); 7717207e0fdSHong Zhang } 772715f1b00SHong Zhang 773715f1b00SHong Zhang /* Build RHS */ 774715f1b00SHong Zhang if (th->endpoint) { /* 2-stage method*/ 7751a352fa8SHong Zhang th->shift = 1./((th->Theta-1.)*th->time_step0); 7765f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeIJacobian(ts,th->ptime0,th->X0,th->Xdot,th->shift,J,Jpre,PETSC_FALSE)); 7775f80ce2aSJacob Faibussowitsch CHKERRQ(MatMatMult(J,ts->mat_sensip,MAT_REUSE_MATRIX,PETSC_DEFAULT,&MatDeltaFwdSensip)); 7785f80ce2aSJacob Faibussowitsch CHKERRQ(MatScale(MatDeltaFwdSensip,(th->Theta-1.)/th->Theta)); 779715f1b00SHong Zhang 780022c081aSHong Zhang /* Add the f_p forcing terms */ 7810e11c21fSHong Zhang if (ts->Jacp) { 7825f80ce2aSJacob Faibussowitsch CHKERRQ(VecZeroEntries(th->Xdot)); 7835f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeIJacobianP(ts,th->ptime0,th->X0,th->Xdot,th->shift,ts->Jacp,PETSC_FALSE)); 7845f80ce2aSJacob Faibussowitsch CHKERRQ(MatAXPY(MatDeltaFwdSensip,(th->Theta-1.)/th->Theta,ts->Jacp,SUBSET_NONZERO_PATTERN)); 78582ad9101SHong Zhang th->shift = previous_shift; 7865f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPBYPCZ(th->Xdot,-th->shift,th->shift,0,th->X0,ts->vec_sol)); 7875f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeIJacobianP(ts,th->stage_time,ts->vec_sol,th->Xdot,th->shift,ts->Jacp,PETSC_FALSE)); 7885f80ce2aSJacob Faibussowitsch CHKERRQ(MatAXPY(MatDeltaFwdSensip,-1.,ts->Jacp,SUBSET_NONZERO_PATTERN)); 7890e11c21fSHong Zhang } 790715f1b00SHong Zhang } else { /* 1-stage method */ 7913e05ceb1SHong Zhang th->shift = 0.0; 7925f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeIJacobian(ts,th->stage_time,th->X,th->Xdot,th->shift,J,Jpre,PETSC_FALSE)); 7935f80ce2aSJacob Faibussowitsch CHKERRQ(MatMatMult(J,ts->mat_sensip,MAT_REUSE_MATRIX,PETSC_DEFAULT,&MatDeltaFwdSensip)); 7945f80ce2aSJacob Faibussowitsch CHKERRQ(MatScale(MatDeltaFwdSensip,-1.)); 79513b1b0ffSHong Zhang 796022c081aSHong Zhang /* Add the f_p forcing terms */ 7970e11c21fSHong Zhang if (ts->Jacp) { 79882ad9101SHong Zhang th->shift = previous_shift; 7995f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPBYPCZ(th->Xdot,-th->shift,th->shift,0,th->X0,th->X)); 8005f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeIJacobianP(ts,th->stage_time,th->X,th->Xdot,th->shift,ts->Jacp,PETSC_FALSE)); 8015f80ce2aSJacob Faibussowitsch CHKERRQ(MatAXPY(MatDeltaFwdSensip,-1.,ts->Jacp,SUBSET_NONZERO_PATTERN)); 802715f1b00SHong Zhang } 8030e11c21fSHong Zhang } 804715f1b00SHong Zhang 805715f1b00SHong Zhang /* Build LHS */ 8061a352fa8SHong Zhang th->shift = previous_shift; /* recover the previous shift used in TSStep_Theta() */ 807715f1b00SHong Zhang if (th->endpoint) { 8085f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeIJacobian(ts,th->stage_time,ts->vec_sol,th->Xdot,th->shift,J,Jpre,PETSC_FALSE)); 809715f1b00SHong Zhang } else { 8105f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeIJacobian(ts,th->stage_time,th->X,th->Xdot,th->shift,J,Jpre,PETSC_FALSE)); 811715f1b00SHong Zhang } 8125f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetOperators(ksp,J,Jpre)); 813715f1b00SHong Zhang 814715f1b00SHong Zhang /* 815715f1b00SHong Zhang Evaluate the first stage of integral gradients with the 2-stage method: 816c9ad9de0SHong Zhang drdu|t_n*S(t_n) + drdp|t_n 817715f1b00SHong Zhang This is done before the linear solve because the sensitivity variable S(t_n) will be propagated to S(t_{n+1}) 818715f1b00SHong Zhang */ 819715f1b00SHong Zhang if (th->endpoint) { /* 2-stage method only */ 8207207e0fdSHong Zhang if (quadts && quadts->mat_sensip) { 8215f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeRHSJacobian(quadts,th->ptime0,th->X0,quadJ,NULL)); 8225f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeRHSJacobianP(quadts,th->ptime0,th->X0,quadJp)); 8235f80ce2aSJacob Faibussowitsch CHKERRQ(MatTransposeMatMult(ts->mat_sensip,quadJ,MAT_REUSE_MATRIX,PETSC_DEFAULT,&th->MatIntegralSensipTemp)); 8245f80ce2aSJacob Faibussowitsch CHKERRQ(MatAXPY(th->MatIntegralSensipTemp,1,quadJp,SAME_NONZERO_PATTERN)); 8255f80ce2aSJacob Faibussowitsch CHKERRQ(MatAXPY(quadts->mat_sensip,th->time_step0*(1.-th->Theta),th->MatIntegralSensipTemp,SAME_NONZERO_PATTERN)); 826715f1b00SHong Zhang } 827715f1b00SHong Zhang } 828715f1b00SHong Zhang 829715f1b00SHong Zhang /* Solve the tangent linear equation for forward sensitivities to parameters */ 830022c081aSHong Zhang for (ntlm=0; ntlm<th->num_tlm; ntlm++) { 831b5b4017aSHong Zhang KSPConvergedReason kspreason; 8325f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetColumn(MatDeltaFwdSensip,ntlm,&barr)); 8335f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(VecDeltaFwdSensipCol,barr)); 834715f1b00SHong Zhang if (th->endpoint) { 8355f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetColumn(ts->mat_sensip,ntlm,&xarr)); 8365f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(ts->vec_sensip_col,xarr)); 8375f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSolve(ksp,VecDeltaFwdSensipCol,ts->vec_sensip_col)); 8385f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(ts->vec_sensip_col)); 8395f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreColumn(ts->mat_sensip,&xarr)); 840715f1b00SHong Zhang } else { 8415f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSolve(ksp,VecDeltaFwdSensipCol,VecDeltaFwdSensipCol)); 842715f1b00SHong Zhang } 8435f80ce2aSJacob Faibussowitsch CHKERRQ(KSPGetConvergedReason(ksp,&kspreason)); 844b5b4017aSHong Zhang if (kspreason < 0) { 845b5b4017aSHong Zhang ts->reason = TSFORWARD_DIVERGED_LINEAR_SOLVE; 8465f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo(ts,"Step=%D, %Dth tangent linear solve, linear solve fails, stopping tangent linear solve\n",ts->steps,ntlm)); 847b5b4017aSHong Zhang } 8485f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(VecDeltaFwdSensipCol)); 8495f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreColumn(MatDeltaFwdSensip,&barr)); 850715f1b00SHong Zhang } 851715f1b00SHong Zhang 85213b1b0ffSHong Zhang /* 85313b1b0ffSHong Zhang Evaluate the second stage of integral gradients with the 2-stage method: 854c9ad9de0SHong Zhang drdu|t_{n+1}*S(t_{n+1}) + drdp|t_{n+1} 85513b1b0ffSHong Zhang */ 8567207e0fdSHong Zhang if (quadts && quadts->mat_sensip) { 85713b1b0ffSHong Zhang if (!th->endpoint) { 8585f80ce2aSJacob Faibussowitsch CHKERRQ(MatAXPY(ts->mat_sensip,1,MatDeltaFwdSensip,SAME_NONZERO_PATTERN)); /* stage sensitivity */ 8595f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeRHSJacobian(quadts,th->stage_time,th->X,quadJ,NULL)); 8605f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeRHSJacobianP(quadts,th->stage_time,th->X,quadJp)); 8615f80ce2aSJacob Faibussowitsch CHKERRQ(MatTransposeMatMult(ts->mat_sensip,quadJ,MAT_REUSE_MATRIX,PETSC_DEFAULT,&th->MatIntegralSensipTemp)); 8625f80ce2aSJacob Faibussowitsch CHKERRQ(MatAXPY(th->MatIntegralSensipTemp,1,quadJp,SAME_NONZERO_PATTERN)); 8635f80ce2aSJacob Faibussowitsch CHKERRQ(MatAXPY(quadts->mat_sensip,th->time_step0,th->MatIntegralSensipTemp,SAME_NONZERO_PATTERN)); 8645f80ce2aSJacob Faibussowitsch CHKERRQ(MatAXPY(ts->mat_sensip,(1.-th->Theta)/th->Theta,MatDeltaFwdSensip,SAME_NONZERO_PATTERN)); 86513b1b0ffSHong Zhang } else { 8665f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeRHSJacobian(quadts,th->stage_time,ts->vec_sol,quadJ,NULL)); 8675f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeRHSJacobianP(quadts,th->stage_time,ts->vec_sol,quadJp)); 8685f80ce2aSJacob Faibussowitsch CHKERRQ(MatTransposeMatMult(ts->mat_sensip,quadJ,MAT_REUSE_MATRIX,PETSC_DEFAULT,&th->MatIntegralSensipTemp)); 8695f80ce2aSJacob Faibussowitsch CHKERRQ(MatAXPY(th->MatIntegralSensipTemp,1,quadJp,SAME_NONZERO_PATTERN)); 8705f80ce2aSJacob Faibussowitsch CHKERRQ(MatAXPY(quadts->mat_sensip,th->time_step0*th->Theta,th->MatIntegralSensipTemp,SAME_NONZERO_PATTERN)); 87113b1b0ffSHong Zhang } 87213b1b0ffSHong Zhang } else { 87313b1b0ffSHong Zhang if (!th->endpoint) { 8745f80ce2aSJacob Faibussowitsch CHKERRQ(MatAXPY(ts->mat_sensip,1./th->Theta,MatDeltaFwdSensip,SAME_NONZERO_PATTERN)); 875715f1b00SHong Zhang } 876715f1b00SHong Zhang } 8771566a47fSLisandro Dalcin PetscFunctionReturn(0); 8781566a47fSLisandro Dalcin } 8791566a47fSLisandro Dalcin 880cc4f23bcSHong Zhang static PetscErrorCode TSForwardGetStages_Theta(TS ts,PetscInt *ns,Mat *stagesensip[]) 8816affb6f8SHong Zhang { 8826affb6f8SHong Zhang TS_Theta *th = (TS_Theta*)ts->data; 8836affb6f8SHong Zhang 8846affb6f8SHong Zhang PetscFunctionBegin; 8857409eceaSHong Zhang if (ns) { 8867409eceaSHong Zhang if (!th->endpoint && th->Theta != 1.0) *ns = 1; /* midpoint form */ 8877409eceaSHong Zhang else *ns = 2; /* endpoint form */ 8887409eceaSHong Zhang } 8895072d23cSHong Zhang if (stagesensip) { 890cc4f23bcSHong Zhang if (!th->endpoint && th->Theta != 1.0) { 8917409eceaSHong Zhang th->MatFwdStages[0] = th->MatDeltaFwdSensip; 892cc4f23bcSHong Zhang } else { 893cc4f23bcSHong Zhang th->MatFwdStages[0] = th->MatFwdSensip0; 894cc4f23bcSHong Zhang th->MatFwdStages[1] = ts->mat_sensip; /* stiffly accurate */ 895cc4f23bcSHong Zhang } 896cc4f23bcSHong Zhang *stagesensip = th->MatFwdStages; 8975072d23cSHong Zhang } 8986affb6f8SHong Zhang PetscFunctionReturn(0); 8996affb6f8SHong Zhang } 9006affb6f8SHong Zhang 901316643e7SJed Brown /*------------------------------------------------------------*/ 902277b19d0SLisandro Dalcin static PetscErrorCode TSReset_Theta(TS ts) 903316643e7SJed Brown { 904316643e7SJed Brown TS_Theta *th = (TS_Theta*)ts->data; 905316643e7SJed Brown 906316643e7SJed Brown PetscFunctionBegin; 9075f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&th->X)); 9085f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&th->Xdot)); 9095f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&th->X0)); 9105f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&th->affine)); 9111566a47fSLisandro Dalcin 9125f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&th->vec_sol_prev)); 9135f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&th->vec_lte_work)); 9141566a47fSLisandro Dalcin 9155f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&th->VecCostIntegral0)); 916277b19d0SLisandro Dalcin PetscFunctionReturn(0); 917277b19d0SLisandro Dalcin } 918277b19d0SLisandro Dalcin 919ece46509SHong Zhang static PetscErrorCode TSAdjointReset_Theta(TS ts) 920ece46509SHong Zhang { 921ece46509SHong Zhang TS_Theta *th = (TS_Theta*)ts->data; 922ece46509SHong Zhang 923ece46509SHong Zhang PetscFunctionBegin; 9245f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroyVecs(ts->numcost,&th->VecsDeltaLam)); 9255f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroyVecs(ts->numcost,&th->VecsDeltaMu)); 9265f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroyVecs(ts->numcost,&th->VecsDeltaLam2)); 9275f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroyVecs(ts->numcost,&th->VecsDeltaMu2)); 9285f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroyVecs(ts->numcost,&th->VecsSensiTemp)); 9295f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroyVecs(ts->numcost,&th->VecsSensi2Temp)); 930ece46509SHong Zhang PetscFunctionReturn(0); 931ece46509SHong Zhang } 932ece46509SHong Zhang 933277b19d0SLisandro Dalcin static PetscErrorCode TSDestroy_Theta(TS ts) 934277b19d0SLisandro Dalcin { 935277b19d0SLisandro Dalcin PetscFunctionBegin; 9365f80ce2aSJacob Faibussowitsch CHKERRQ(TSReset_Theta(ts)); 937b3a6b972SJed Brown if (ts->dm) { 9385f80ce2aSJacob Faibussowitsch CHKERRQ(DMCoarsenHookRemove(ts->dm,DMCoarsenHook_TSTheta,DMRestrictHook_TSTheta,ts)); 9395f80ce2aSJacob Faibussowitsch CHKERRQ(DMSubDomainHookRemove(ts->dm,DMSubDomainHook_TSTheta,DMSubDomainRestrictHook_TSTheta,ts)); 940b3a6b972SJed Brown } 9415f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(ts->data)); 9425f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectComposeFunction((PetscObject)ts,"TSThetaGetTheta_C",NULL)); 9435f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectComposeFunction((PetscObject)ts,"TSThetaSetTheta_C",NULL)); 9445f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectComposeFunction((PetscObject)ts,"TSThetaGetEndpoint_C",NULL)); 9455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectComposeFunction((PetscObject)ts,"TSThetaSetEndpoint_C",NULL)); 946316643e7SJed Brown PetscFunctionReturn(0); 947316643e7SJed Brown } 948316643e7SJed Brown 949316643e7SJed Brown /* 950316643e7SJed Brown This defines the nonlinear equation that is to be solved with SNES 9512b5a38e1SLisandro Dalcin G(U) = F[t0+Theta*dt, U, (U-U0)*shift] = 0 9520fd10508SMatthew Knepley 9530fd10508SMatthew Knepley Note that U here is the stage argument. This means that U = U_{n+1} only if endpoint = true, 9540fd10508SMatthew Knepley otherwise U = theta U_{n+1} + (1 - theta) U0, which for the case of implicit midpoint is 9550fd10508SMatthew Knepley U = (U_{n+1} + U0)/2 956316643e7SJed Brown */ 9570f5c6efeSJed Brown static PetscErrorCode SNESTSFormFunction_Theta(SNES snes,Vec x,Vec y,TS ts) 958316643e7SJed Brown { 959316643e7SJed Brown TS_Theta *th = (TS_Theta*)ts->data; 9607445fe48SJed Brown Vec X0,Xdot; 9617445fe48SJed Brown DM dm,dmsave; 9623e05ceb1SHong Zhang PetscReal shift = th->shift; 963316643e7SJed Brown 964316643e7SJed Brown PetscFunctionBegin; 9655f80ce2aSJacob Faibussowitsch CHKERRQ(SNESGetDM(snes,&dm)); 9665a3a76d0SJed Brown /* When using the endpoint variant, this is actually 1/Theta * Xdot */ 9675f80ce2aSJacob Faibussowitsch CHKERRQ(TSThetaGetX0AndXdot(ts,dm,&X0,&Xdot)); 968494ce9fcSHong Zhang if (x != X0) { 9695f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPBYPCZ(Xdot,-shift,shift,0,X0,x)); 970494ce9fcSHong Zhang } else { 9715f80ce2aSJacob Faibussowitsch CHKERRQ(VecZeroEntries(Xdot)); 972494ce9fcSHong Zhang } 9737445fe48SJed Brown /* DM monkey-business allows user code to call TSGetDM() inside of functions evaluated on levels of FAS */ 9747445fe48SJed Brown dmsave = ts->dm; 9757445fe48SJed Brown ts->dm = dm; 9765f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeIFunction(ts,th->stage_time,x,Xdot,y,PETSC_FALSE)); 9777445fe48SJed Brown ts->dm = dmsave; 9785f80ce2aSJacob Faibussowitsch CHKERRQ(TSThetaRestoreX0AndXdot(ts,dm,&X0,&Xdot)); 979316643e7SJed Brown PetscFunctionReturn(0); 980316643e7SJed Brown } 981316643e7SJed Brown 982d1e9a80fSBarry Smith static PetscErrorCode SNESTSFormJacobian_Theta(SNES snes,Vec x,Mat A,Mat B,TS ts) 983316643e7SJed Brown { 984316643e7SJed Brown TS_Theta *th = (TS_Theta*)ts->data; 9857445fe48SJed Brown Vec Xdot; 9867445fe48SJed Brown DM dm,dmsave; 9873e05ceb1SHong Zhang PetscReal shift = th->shift; 988316643e7SJed Brown 989316643e7SJed Brown PetscFunctionBegin; 9905f80ce2aSJacob Faibussowitsch CHKERRQ(SNESGetDM(snes,&dm)); 991be5899b3SLisandro Dalcin /* Xdot has already been computed in SNESTSFormFunction_Theta (SNES guarantees this) */ 9925f80ce2aSJacob Faibussowitsch CHKERRQ(TSThetaGetX0AndXdot(ts,dm,NULL,&Xdot)); 9937445fe48SJed Brown 9947445fe48SJed Brown dmsave = ts->dm; 9957445fe48SJed Brown ts->dm = dm; 9965f80ce2aSJacob Faibussowitsch CHKERRQ(TSComputeIJacobian(ts,th->stage_time,x,Xdot,shift,A,B,PETSC_FALSE)); 9977445fe48SJed Brown ts->dm = dmsave; 9985f80ce2aSJacob Faibussowitsch CHKERRQ(TSThetaRestoreX0AndXdot(ts,dm,NULL,&Xdot)); 999316643e7SJed Brown PetscFunctionReturn(0); 1000316643e7SJed Brown } 1001316643e7SJed Brown 1002715f1b00SHong Zhang static PetscErrorCode TSForwardSetUp_Theta(TS ts) 1003715f1b00SHong Zhang { 1004715f1b00SHong Zhang TS_Theta *th = (TS_Theta*)ts->data; 10057207e0fdSHong Zhang TS quadts = ts->quadraturets; 1006715f1b00SHong Zhang 1007715f1b00SHong Zhang PetscFunctionBegin; 1008022c081aSHong Zhang /* combine sensitivities to parameters and sensitivities to initial values into one array */ 100913b1b0ffSHong Zhang th->num_tlm = ts->num_parameters; 10105f80ce2aSJacob Faibussowitsch CHKERRQ(MatDuplicate(ts->mat_sensip,MAT_DO_NOT_COPY_VALUES,&th->MatDeltaFwdSensip)); 10117207e0fdSHong Zhang if (quadts && quadts->mat_sensip) { 10125f80ce2aSJacob Faibussowitsch CHKERRQ(MatDuplicate(quadts->mat_sensip,MAT_DO_NOT_COPY_VALUES,&th->MatIntegralSensipTemp)); 10135f80ce2aSJacob Faibussowitsch CHKERRQ(MatDuplicate(quadts->mat_sensip,MAT_DO_NOT_COPY_VALUES,&th->MatIntegralSensip0)); 1014715f1b00SHong Zhang } 10156f92202bSHong Zhang /* backup sensitivity results for roll-backs */ 10165f80ce2aSJacob Faibussowitsch CHKERRQ(MatDuplicate(ts->mat_sensip,MAT_DO_NOT_COPY_VALUES,&th->MatFwdSensip0)); 101713b1b0ffSHong Zhang 10185f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(ts->vec_sol,&th->VecDeltaFwdSensipCol)); 1019715f1b00SHong Zhang PetscFunctionReturn(0); 1020715f1b00SHong Zhang } 1021715f1b00SHong Zhang 10227adebddeSHong Zhang static PetscErrorCode TSForwardReset_Theta(TS ts) 10237adebddeSHong Zhang { 10247adebddeSHong Zhang TS_Theta *th = (TS_Theta*)ts->data; 10257207e0fdSHong Zhang TS quadts = ts->quadraturets; 10267adebddeSHong Zhang 10277adebddeSHong Zhang PetscFunctionBegin; 10287207e0fdSHong Zhang if (quadts && quadts->mat_sensip) { 10295f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&th->MatIntegralSensipTemp)); 10305f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&th->MatIntegralSensip0)); 10317adebddeSHong Zhang } 10325f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&th->VecDeltaFwdSensipCol)); 10335f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&th->MatDeltaFwdSensip)); 10345f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&th->MatFwdSensip0)); 10357adebddeSHong Zhang PetscFunctionReturn(0); 10367adebddeSHong Zhang } 10377adebddeSHong Zhang 1038316643e7SJed Brown static PetscErrorCode TSSetUp_Theta(TS ts) 1039316643e7SJed Brown { 1040316643e7SJed Brown TS_Theta *th = (TS_Theta*)ts->data; 1041cd4cee2dSHong Zhang TS quadts = ts->quadraturets; 10422ffb9264SLisandro Dalcin PetscBool match; 1043316643e7SJed Brown 1044316643e7SJed Brown PetscFunctionBegin; 1045cd4cee2dSHong Zhang if (!th->VecCostIntegral0 && quadts && ts->costintegralfwd) { /* back up cost integral */ 10465f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(quadts->vec_sol,&th->VecCostIntegral0)); 1047b1cb36f3SHong Zhang } 104839d13666SHong Zhang if (!th->X) { 10495f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(ts->vec_sol,&th->X)); 105039d13666SHong Zhang } 105139d13666SHong Zhang if (!th->Xdot) { 10525f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(ts->vec_sol,&th->Xdot)); 105339d13666SHong Zhang } 105439d13666SHong Zhang if (!th->X0) { 10555f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(ts->vec_sol,&th->X0)); 105639d13666SHong Zhang } 10571566a47fSLisandro Dalcin if (th->endpoint) { 10585f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(ts->vec_sol,&th->affine)); 10597445fe48SJed Brown } 10603b1890cdSShri Abhyankar 10611566a47fSLisandro Dalcin th->order = (th->Theta == 0.5) ? 2 : 1; 106220d49056SMatthew G. Knepley th->shift = 1/(th->Theta*ts->time_step); 10631566a47fSLisandro Dalcin 10645f80ce2aSJacob Faibussowitsch CHKERRQ(TSGetDM(ts,&ts->dm)); 10655f80ce2aSJacob Faibussowitsch CHKERRQ(DMCoarsenHookAdd(ts->dm,DMCoarsenHook_TSTheta,DMRestrictHook_TSTheta,ts)); 10665f80ce2aSJacob Faibussowitsch CHKERRQ(DMSubDomainHookAdd(ts->dm,DMSubDomainHook_TSTheta,DMSubDomainRestrictHook_TSTheta,ts)); 10671566a47fSLisandro Dalcin 10685f80ce2aSJacob Faibussowitsch CHKERRQ(TSGetAdapt(ts,&ts->adapt)); 10695f80ce2aSJacob Faibussowitsch CHKERRQ(TSAdaptCandidatesClear(ts->adapt)); 10705f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject)ts->adapt,TSADAPTNONE,&match)); 10712ffb9264SLisandro Dalcin if (!match) { 10725f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(ts->vec_sol,&th->vec_sol_prev)); 10735f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(ts->vec_sol,&th->vec_lte_work)); 10743b1890cdSShri Abhyankar } 10755f80ce2aSJacob Faibussowitsch CHKERRQ(TSGetSNES(ts,&ts->snes)); 1076cc4f23bcSHong Zhang 1077cc4f23bcSHong Zhang ts->stifflyaccurate = (!th->endpoint && th->Theta != 1.0) ? PETSC_FALSE : PETSC_TRUE; 1078b4dd3bf9SBarry Smith PetscFunctionReturn(0); 1079b4dd3bf9SBarry Smith } 10800c7376e5SHong Zhang 1081b4dd3bf9SBarry Smith /*------------------------------------------------------------*/ 1082b4dd3bf9SBarry Smith 1083b4dd3bf9SBarry Smith static PetscErrorCode TSAdjointSetUp_Theta(TS ts) 1084b4dd3bf9SBarry Smith { 1085b4dd3bf9SBarry Smith TS_Theta *th = (TS_Theta*)ts->data; 1086b4dd3bf9SBarry Smith 1087b4dd3bf9SBarry Smith PetscFunctionBegin; 10885f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicateVecs(ts->vecs_sensi[0],ts->numcost,&th->VecsDeltaLam)); 10895f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicateVecs(ts->vecs_sensi[0],ts->numcost,&th->VecsSensiTemp)); 10902ca6e920SHong Zhang if (ts->vecs_sensip) { 10915f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicateVecs(ts->vecs_sensip[0],ts->numcost,&th->VecsDeltaMu)); 10922ca6e920SHong Zhang } 1093b5b4017aSHong Zhang if (ts->vecs_sensi2) { 10945f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicateVecs(ts->vecs_sensi[0],ts->numcost,&th->VecsDeltaLam2)); 10955f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicateVecs(ts->vecs_sensi2[0],ts->numcost,&th->VecsSensi2Temp)); 109667633408SHong Zhang /* hack ts to make implicit TS solver work when users provide only explicit versions of callbacks (RHSFunction,RHSJacobian,RHSHessian etc.) */ 109767633408SHong Zhang if (!ts->ihessianproduct_fuu) ts->vecs_fuu = ts->vecs_guu; 109867633408SHong Zhang if (!ts->ihessianproduct_fup) ts->vecs_fup = ts->vecs_gup; 1099b5b4017aSHong Zhang } 1100c9681e5dSHong Zhang if (ts->vecs_sensi2p) { 11015f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicateVecs(ts->vecs_sensi2p[0],ts->numcost,&th->VecsDeltaMu2)); 110267633408SHong Zhang /* hack ts to make implicit TS solver work when users provide only explicit versions of callbacks (RHSFunction,RHSJacobian,RHSHessian etc.) */ 110367633408SHong Zhang if (!ts->ihessianproduct_fpu) ts->vecs_fpu = ts->vecs_gpu; 110467633408SHong Zhang if (!ts->ihessianproduct_fpp) ts->vecs_fpp = ts->vecs_gpp; 1105b5b4017aSHong Zhang } 1106316643e7SJed Brown PetscFunctionReturn(0); 1107316643e7SJed Brown } 1108316643e7SJed Brown 11094416b707SBarry Smith static PetscErrorCode TSSetFromOptions_Theta(PetscOptionItems *PetscOptionsObject,TS ts) 1110316643e7SJed Brown { 1111316643e7SJed Brown TS_Theta *th = (TS_Theta*)ts->data; 1112316643e7SJed Brown 1113316643e7SJed Brown PetscFunctionBegin; 11145f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsHead(PetscOptionsObject,"Theta ODE solver options")); 1115316643e7SJed Brown { 11165f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsReal("-ts_theta_theta","Location of stage (0<Theta<=1)","TSThetaSetTheta",th->Theta,&th->Theta,NULL)); 11175f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-ts_theta_endpoint","Use the endpoint instead of midpoint form of the Theta method","TSThetaSetEndpoint",th->endpoint,&th->endpoint,NULL)); 11185f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-ts_theta_initial_guess_extrapolate","Extrapolate stage initial guess from previous solution (sometimes unstable)","TSThetaSetExtrapolate",th->extrapolate,&th->extrapolate,NULL)); 1119316643e7SJed Brown } 11205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsTail()); 1121316643e7SJed Brown PetscFunctionReturn(0); 1122316643e7SJed Brown } 1123316643e7SJed Brown 1124316643e7SJed Brown static PetscErrorCode TSView_Theta(TS ts,PetscViewer viewer) 1125316643e7SJed Brown { 1126316643e7SJed Brown TS_Theta *th = (TS_Theta*)ts->data; 1127ace3abfcSBarry Smith PetscBool iascii; 1128316643e7SJed Brown 1129316643e7SJed Brown PetscFunctionBegin; 11305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii)); 1131316643e7SJed Brown if (iascii) { 11325f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer," Theta=%g\n",(double)th->Theta)); 11335f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer," Extrapolation=%s\n",th->extrapolate ? "yes" : "no")); 1134316643e7SJed Brown } 1135316643e7SJed Brown PetscFunctionReturn(0); 1136316643e7SJed Brown } 1137316643e7SJed Brown 1138560360afSLisandro Dalcin static PetscErrorCode TSThetaGetTheta_Theta(TS ts,PetscReal *theta) 11390de4c49aSJed Brown { 11400de4c49aSJed Brown TS_Theta *th = (TS_Theta*)ts->data; 11410de4c49aSJed Brown 11420de4c49aSJed Brown PetscFunctionBegin; 11430de4c49aSJed Brown *theta = th->Theta; 11440de4c49aSJed Brown PetscFunctionReturn(0); 11450de4c49aSJed Brown } 11460de4c49aSJed Brown 1147560360afSLisandro Dalcin static PetscErrorCode TSThetaSetTheta_Theta(TS ts,PetscReal theta) 11480de4c49aSJed Brown { 11490de4c49aSJed Brown TS_Theta *th = (TS_Theta*)ts->data; 11500de4c49aSJed Brown 11510de4c49aSJed Brown PetscFunctionBegin; 11522c71b3e2SJacob Faibussowitsch PetscCheckFalse(theta <= 0 || 1 < theta,PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Theta %g not in range (0,1]",(double)theta); 11530de4c49aSJed Brown th->Theta = theta; 11541566a47fSLisandro Dalcin th->order = (th->Theta == 0.5) ? 2 : 1; 11550de4c49aSJed Brown PetscFunctionReturn(0); 11560de4c49aSJed Brown } 1157eb284becSJed Brown 1158560360afSLisandro Dalcin static PetscErrorCode TSThetaGetEndpoint_Theta(TS ts,PetscBool *endpoint) 115926f2ff8fSLisandro Dalcin { 116026f2ff8fSLisandro Dalcin TS_Theta *th = (TS_Theta*)ts->data; 116126f2ff8fSLisandro Dalcin 116226f2ff8fSLisandro Dalcin PetscFunctionBegin; 116326f2ff8fSLisandro Dalcin *endpoint = th->endpoint; 116426f2ff8fSLisandro Dalcin PetscFunctionReturn(0); 116526f2ff8fSLisandro Dalcin } 116626f2ff8fSLisandro Dalcin 1167560360afSLisandro Dalcin static PetscErrorCode TSThetaSetEndpoint_Theta(TS ts,PetscBool flg) 1168eb284becSJed Brown { 1169eb284becSJed Brown TS_Theta *th = (TS_Theta*)ts->data; 1170eb284becSJed Brown 1171eb284becSJed Brown PetscFunctionBegin; 1172eb284becSJed Brown th->endpoint = flg; 1173eb284becSJed Brown PetscFunctionReturn(0); 1174eb284becSJed Brown } 11750de4c49aSJed Brown 1176f9c1d6abSBarry Smith #if defined(PETSC_HAVE_COMPLEX) 1177f9c1d6abSBarry Smith static PetscErrorCode TSComputeLinearStability_Theta(TS ts,PetscReal xr,PetscReal xi,PetscReal *yr,PetscReal *yi) 1178f9c1d6abSBarry Smith { 1179f9c1d6abSBarry Smith PetscComplex z = xr + xi*PETSC_i,f; 1180f9c1d6abSBarry Smith TS_Theta *th = (TS_Theta*)ts->data; 11813fd8ae06SJed Brown const PetscReal one = 1.0; 1182f9c1d6abSBarry Smith 1183f9c1d6abSBarry Smith PetscFunctionBegin; 11843fd8ae06SJed Brown f = (one + (one - th->Theta)*z)/(one - th->Theta*z); 1185f9c1d6abSBarry Smith *yr = PetscRealPartComplex(f); 1186f9c1d6abSBarry Smith *yi = PetscImaginaryPartComplex(f); 1187f9c1d6abSBarry Smith PetscFunctionReturn(0); 1188f9c1d6abSBarry Smith } 1189f9c1d6abSBarry Smith #endif 1190f9c1d6abSBarry Smith 1191cc4f23bcSHong Zhang static PetscErrorCode TSGetStages_Theta(TS ts,PetscInt *ns,Vec *Y[]) 119242682096SHong Zhang { 119342682096SHong Zhang TS_Theta *th = (TS_Theta*)ts->data; 119442682096SHong Zhang 119542682096SHong Zhang PetscFunctionBegin; 11967409eceaSHong Zhang if (ns) { 11977409eceaSHong Zhang if (!th->endpoint && th->Theta != 1.0) *ns = 1; /* midpoint form */ 11987409eceaSHong Zhang else *ns = 2; /* endpoint form */ 11997409eceaSHong Zhang } 12005072d23cSHong Zhang if (Y) { 1201cc4f23bcSHong Zhang if (!th->endpoint && th->Theta != 1.0) { 12027409eceaSHong Zhang th->Stages[0] = th->X; 1203cc4f23bcSHong Zhang } else { 1204cc4f23bcSHong Zhang th->Stages[0] = th->X0; 1205cc4f23bcSHong Zhang th->Stages[1] = ts->vec_sol; /* stiffly accurate */ 1206cc4f23bcSHong Zhang } 1207cc4f23bcSHong Zhang *Y = th->Stages; 12085072d23cSHong Zhang } 120942682096SHong Zhang PetscFunctionReturn(0); 121042682096SHong Zhang } 1211f9c1d6abSBarry Smith 1212316643e7SJed Brown /* ------------------------------------------------------------ */ 1213316643e7SJed Brown /*MC 121496f5712cSJed Brown TSTHETA - DAE solver using the implicit Theta method 1215316643e7SJed Brown 1216316643e7SJed Brown Level: beginner 1217316643e7SJed Brown 12184eb428fdSBarry Smith Options Database: 1219c82ed962SBarry Smith + -ts_theta_theta <Theta> - Location of stage (0<Theta<=1) 1220c82ed962SBarry Smith . -ts_theta_endpoint <flag> - Use the endpoint (like Crank-Nicholson) instead of midpoint form of the Theta method 122103842d09SLisandro Dalcin - -ts_theta_initial_guess_extrapolate <flg> - Extrapolate stage initial guess from previous solution (sometimes unstable) 12224eb428fdSBarry Smith 1223eb284becSJed Brown Notes: 12240c3ba866SJed Brown $ -ts_type theta -ts_theta_theta 1.0 corresponds to backward Euler (TSBEULER) 12250c3ba866SJed Brown $ -ts_type theta -ts_theta_theta 0.5 corresponds to the implicit midpoint rule 12264eb428fdSBarry Smith $ -ts_type theta -ts_theta_theta 0.5 -ts_theta_endpoint corresponds to Crank-Nicholson (TSCN) 12274eb428fdSBarry Smith 12287409eceaSHong 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. 1229eb284becSJed Brown 12307409eceaSHong Zhang The midpoint variant is cast as a 1-stage implicit Runge-Kutta method. 1231eb284becSJed Brown 1232eb284becSJed Brown .vb 1233eb284becSJed Brown Theta | Theta 1234eb284becSJed Brown ------------- 1235eb284becSJed Brown | 1 1236eb284becSJed Brown .ve 1237eb284becSJed Brown 1238eb284becSJed Brown For the default Theta=0.5, this is also known as the implicit midpoint rule. 1239eb284becSJed Brown 1240eb284becSJed Brown When the endpoint variant is chosen, the method becomes a 2-stage method with first stage explicit: 1241eb284becSJed Brown 1242eb284becSJed Brown .vb 1243eb284becSJed Brown 0 | 0 0 1244eb284becSJed Brown 1 | 1-Theta Theta 1245eb284becSJed Brown ------------------- 1246eb284becSJed Brown | 1-Theta Theta 1247eb284becSJed Brown .ve 1248eb284becSJed Brown 1249eb284becSJed Brown For the default Theta=0.5, this is the trapezoid rule (also known as Crank-Nicolson, see TSCN). 1250eb284becSJed Brown 1251eb284becSJed Brown To apply a diagonally implicit RK method to DAE, the stage formula 1252eb284becSJed Brown 1253eb284becSJed Brown $ Y_i = X + h sum_j a_ij Y'_j 1254eb284becSJed Brown 12554eb428fdSBarry Smith is interpreted as a formula for Y'_i in terms of Y_i and known values (Y'_j, j<i) 1256eb284becSJed Brown 1257eb284becSJed Brown .seealso: TSCreate(), TS, TSSetType(), TSCN, TSBEULER, TSThetaSetTheta(), TSThetaSetEndpoint() 1258316643e7SJed Brown 1259316643e7SJed Brown M*/ 12608cc058d9SJed Brown PETSC_EXTERN PetscErrorCode TSCreate_Theta(TS ts) 1261316643e7SJed Brown { 1262316643e7SJed Brown TS_Theta *th; 1263316643e7SJed Brown 1264316643e7SJed Brown PetscFunctionBegin; 1265277b19d0SLisandro Dalcin ts->ops->reset = TSReset_Theta; 1266ece46509SHong Zhang ts->ops->adjointreset = TSAdjointReset_Theta; 1267316643e7SJed Brown ts->ops->destroy = TSDestroy_Theta; 1268316643e7SJed Brown ts->ops->view = TSView_Theta; 1269316643e7SJed Brown ts->ops->setup = TSSetUp_Theta; 127042f2b339SBarry Smith ts->ops->adjointsetup = TSAdjointSetUp_Theta; 1271ece46509SHong Zhang ts->ops->adjointreset = TSAdjointReset_Theta; 1272316643e7SJed Brown ts->ops->step = TSStep_Theta; 1273cd652676SJed Brown ts->ops->interpolate = TSInterpolate_Theta; 12741566a47fSLisandro Dalcin ts->ops->evaluatewlte = TSEvaluateWLTE_Theta; 127524655328SShri ts->ops->rollback = TSRollBack_Theta; 1276316643e7SJed Brown ts->ops->setfromoptions = TSSetFromOptions_Theta; 12770f5c6efeSJed Brown ts->ops->snesfunction = SNESTSFormFunction_Theta; 12780f5c6efeSJed Brown ts->ops->snesjacobian = SNESTSFormJacobian_Theta; 1279f9c1d6abSBarry Smith #if defined(PETSC_HAVE_COMPLEX) 1280f9c1d6abSBarry Smith ts->ops->linearstability = TSComputeLinearStability_Theta; 1281f9c1d6abSBarry Smith #endif 128242682096SHong Zhang ts->ops->getstages = TSGetStages_Theta; 128342f2b339SBarry Smith ts->ops->adjointstep = TSAdjointStep_Theta; 1284b1cb36f3SHong Zhang ts->ops->adjointintegral = TSAdjointCostIntegral_Theta; 1285b1cb36f3SHong Zhang ts->ops->forwardintegral = TSForwardCostIntegral_Theta; 12862ffb9264SLisandro Dalcin ts->default_adapt_type = TSADAPTNONE; 12876affb6f8SHong Zhang 1288715f1b00SHong Zhang ts->ops->forwardsetup = TSForwardSetUp_Theta; 12897adebddeSHong Zhang ts->ops->forwardreset = TSForwardReset_Theta; 1290715f1b00SHong Zhang ts->ops->forwardstep = TSForwardStep_Theta; 12916affb6f8SHong Zhang ts->ops->forwardgetstages = TSForwardGetStages_Theta; 1292316643e7SJed Brown 1293efd4aadfSBarry Smith ts->usessnes = PETSC_TRUE; 1294efd4aadfSBarry Smith 12955f80ce2aSJacob Faibussowitsch CHKERRQ(PetscNewLog(ts,&th)); 1296316643e7SJed Brown ts->data = (void*)th; 1297316643e7SJed Brown 1298715f1b00SHong Zhang th->VecsDeltaLam = NULL; 1299715f1b00SHong Zhang th->VecsDeltaMu = NULL; 1300715f1b00SHong Zhang th->VecsSensiTemp = NULL; 1301b5b4017aSHong Zhang th->VecsSensi2Temp = NULL; 1302715f1b00SHong Zhang 13036f700aefSJed Brown th->extrapolate = PETSC_FALSE; 1304316643e7SJed Brown th->Theta = 0.5; 13051566a47fSLisandro Dalcin th->order = 2; 13065f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectComposeFunction((PetscObject)ts,"TSThetaGetTheta_C",TSThetaGetTheta_Theta)); 13075f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectComposeFunction((PetscObject)ts,"TSThetaSetTheta_C",TSThetaSetTheta_Theta)); 13085f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectComposeFunction((PetscObject)ts,"TSThetaGetEndpoint_C",TSThetaGetEndpoint_Theta)); 13095f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectComposeFunction((PetscObject)ts,"TSThetaSetEndpoint_C",TSThetaSetEndpoint_Theta)); 1310316643e7SJed Brown PetscFunctionReturn(0); 1311316643e7SJed Brown } 13120de4c49aSJed Brown 13130de4c49aSJed Brown /*@ 13140de4c49aSJed Brown TSThetaGetTheta - Get the abscissa of the stage in (0,1]. 13150de4c49aSJed Brown 13160de4c49aSJed Brown Not Collective 13170de4c49aSJed Brown 13180de4c49aSJed Brown Input Parameter: 13190de4c49aSJed Brown . ts - timestepping context 13200de4c49aSJed Brown 13210de4c49aSJed Brown Output Parameter: 13220de4c49aSJed Brown . theta - stage abscissa 13230de4c49aSJed Brown 13240de4c49aSJed Brown Note: 13250de4c49aSJed Brown Use of this function is normally only required to hack TSTHETA to use a modified integration scheme. 13260de4c49aSJed Brown 13270de4c49aSJed Brown Level: Advanced 13280de4c49aSJed Brown 13290de4c49aSJed Brown .seealso: TSThetaSetTheta() 13300de4c49aSJed Brown @*/ 13317087cfbeSBarry Smith PetscErrorCode TSThetaGetTheta(TS ts,PetscReal *theta) 13320de4c49aSJed Brown { 13330de4c49aSJed Brown PetscFunctionBegin; 1334afb20b64SJed Brown PetscValidHeaderSpecific(ts,TS_CLASSID,1); 13350de4c49aSJed Brown PetscValidPointer(theta,2); 13365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscUseMethod(ts,"TSThetaGetTheta_C",(TS,PetscReal*),(ts,theta))); 13370de4c49aSJed Brown PetscFunctionReturn(0); 13380de4c49aSJed Brown } 13390de4c49aSJed Brown 13400de4c49aSJed Brown /*@ 13410de4c49aSJed Brown TSThetaSetTheta - Set the abscissa of the stage in (0,1]. 13420de4c49aSJed Brown 13430de4c49aSJed Brown Not Collective 13440de4c49aSJed Brown 1345d8d19677SJose E. Roman Input Parameters: 13460de4c49aSJed Brown + ts - timestepping context 13470de4c49aSJed Brown - theta - stage abscissa 13480de4c49aSJed Brown 13490de4c49aSJed Brown Options Database: 135067b8a455SSatish Balay . -ts_theta_theta <theta> - set theta 13510de4c49aSJed Brown 13520de4c49aSJed Brown Level: Intermediate 13530de4c49aSJed Brown 13540de4c49aSJed Brown .seealso: TSThetaGetTheta() 13550de4c49aSJed Brown @*/ 13567087cfbeSBarry Smith PetscErrorCode TSThetaSetTheta(TS ts,PetscReal theta) 13570de4c49aSJed Brown { 13580de4c49aSJed Brown PetscFunctionBegin; 1359afb20b64SJed Brown PetscValidHeaderSpecific(ts,TS_CLASSID,1); 13605f80ce2aSJacob Faibussowitsch CHKERRQ(PetscTryMethod(ts,"TSThetaSetTheta_C",(TS,PetscReal),(ts,theta))); 13610de4c49aSJed Brown PetscFunctionReturn(0); 13620de4c49aSJed Brown } 1363f33bbcb6SJed Brown 136426f2ff8fSLisandro Dalcin /*@ 136526f2ff8fSLisandro Dalcin TSThetaGetEndpoint - Gets whether to use the endpoint variant of the method (e.g. trapezoid/Crank-Nicolson instead of midpoint rule). 136626f2ff8fSLisandro Dalcin 136726f2ff8fSLisandro Dalcin Not Collective 136826f2ff8fSLisandro Dalcin 136926f2ff8fSLisandro Dalcin Input Parameter: 137026f2ff8fSLisandro Dalcin . ts - timestepping context 137126f2ff8fSLisandro Dalcin 137226f2ff8fSLisandro Dalcin Output Parameter: 137326f2ff8fSLisandro Dalcin . endpoint - PETSC_TRUE when using the endpoint variant 137426f2ff8fSLisandro Dalcin 137526f2ff8fSLisandro Dalcin Level: Advanced 137626f2ff8fSLisandro Dalcin 137726f2ff8fSLisandro Dalcin .seealso: TSThetaSetEndpoint(), TSTHETA, TSCN 137826f2ff8fSLisandro Dalcin @*/ 137926f2ff8fSLisandro Dalcin PetscErrorCode TSThetaGetEndpoint(TS ts,PetscBool *endpoint) 138026f2ff8fSLisandro Dalcin { 138126f2ff8fSLisandro Dalcin PetscFunctionBegin; 138226f2ff8fSLisandro Dalcin PetscValidHeaderSpecific(ts,TS_CLASSID,1); 138326f2ff8fSLisandro Dalcin PetscValidPointer(endpoint,2); 13845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscUseMethod(ts,"TSThetaGetEndpoint_C",(TS,PetscBool*),(ts,endpoint))); 138526f2ff8fSLisandro Dalcin PetscFunctionReturn(0); 138626f2ff8fSLisandro Dalcin } 138726f2ff8fSLisandro Dalcin 1388eb284becSJed Brown /*@ 1389eb284becSJed Brown TSThetaSetEndpoint - Sets whether to use the endpoint variant of the method (e.g. trapezoid/Crank-Nicolson instead of midpoint rule). 1390eb284becSJed Brown 1391eb284becSJed Brown Not Collective 1392eb284becSJed Brown 1393d8d19677SJose E. Roman Input Parameters: 1394eb284becSJed Brown + ts - timestepping context 1395eb284becSJed Brown - flg - PETSC_TRUE to use the endpoint variant 1396eb284becSJed Brown 1397eb284becSJed Brown Options Database: 139867b8a455SSatish Balay . -ts_theta_endpoint <flg> - use the endpoint variant 1399eb284becSJed Brown 1400eb284becSJed Brown Level: Intermediate 1401eb284becSJed Brown 1402eb284becSJed Brown .seealso: TSTHETA, TSCN 1403eb284becSJed Brown @*/ 1404eb284becSJed Brown PetscErrorCode TSThetaSetEndpoint(TS ts,PetscBool flg) 1405eb284becSJed Brown { 1406eb284becSJed Brown PetscFunctionBegin; 1407eb284becSJed Brown PetscValidHeaderSpecific(ts,TS_CLASSID,1); 14085f80ce2aSJacob Faibussowitsch CHKERRQ(PetscTryMethod(ts,"TSThetaSetEndpoint_C",(TS,PetscBool),(ts,flg))); 1409eb284becSJed Brown PetscFunctionReturn(0); 1410eb284becSJed Brown } 1411eb284becSJed Brown 1412f33bbcb6SJed Brown /* 1413f33bbcb6SJed Brown * TSBEULER and TSCN are straightforward specializations of TSTHETA. 1414f33bbcb6SJed Brown * The creation functions for these specializations are below. 1415f33bbcb6SJed Brown */ 1416f33bbcb6SJed Brown 14171566a47fSLisandro Dalcin static PetscErrorCode TSSetUp_BEuler(TS ts) 14181566a47fSLisandro Dalcin { 14191566a47fSLisandro Dalcin TS_Theta *th = (TS_Theta*)ts->data; 14201566a47fSLisandro Dalcin 14211566a47fSLisandro Dalcin PetscFunctionBegin; 14222c71b3e2SJacob Faibussowitsch PetscCheckFalse(th->Theta != 1.0,PetscObjectComm((PetscObject)ts),PETSC_ERR_OPT_OVERWRITE,"Can not change the default value (1) of theta when using backward Euler"); 1423*28b400f6SJacob 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"); 14245f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetUp_Theta(ts)); 14251566a47fSLisandro Dalcin PetscFunctionReturn(0); 14261566a47fSLisandro Dalcin } 14271566a47fSLisandro Dalcin 1428f33bbcb6SJed Brown static PetscErrorCode TSView_BEuler(TS ts,PetscViewer viewer) 1429f33bbcb6SJed Brown { 1430f33bbcb6SJed Brown PetscFunctionBegin; 1431f33bbcb6SJed Brown PetscFunctionReturn(0); 1432f33bbcb6SJed Brown } 1433f33bbcb6SJed Brown 1434f33bbcb6SJed Brown /*MC 1435f33bbcb6SJed Brown TSBEULER - ODE solver using the implicit backward Euler method 1436f33bbcb6SJed Brown 1437f33bbcb6SJed Brown Level: beginner 1438f33bbcb6SJed Brown 14394eb428fdSBarry Smith Notes: 1440c7eb6c99SShri Abhyankar TSBEULER is equivalent to TSTHETA with Theta=1.0 14414eb428fdSBarry Smith 14421566a47fSLisandro Dalcin $ -ts_type theta -ts_theta_theta 1.0 14434eb428fdSBarry Smith 1444f33bbcb6SJed Brown .seealso: TSCreate(), TS, TSSetType(), TSEULER, TSCN, TSTHETA 1445f33bbcb6SJed Brown 1446f33bbcb6SJed Brown M*/ 14478cc058d9SJed Brown PETSC_EXTERN PetscErrorCode TSCreate_BEuler(TS ts) 1448f33bbcb6SJed Brown { 1449f33bbcb6SJed Brown PetscFunctionBegin; 14505f80ce2aSJacob Faibussowitsch CHKERRQ(TSCreate_Theta(ts)); 14515f80ce2aSJacob Faibussowitsch CHKERRQ(TSThetaSetTheta(ts,1.0)); 14525f80ce2aSJacob Faibussowitsch CHKERRQ(TSThetaSetEndpoint(ts,PETSC_FALSE)); 14530c7376e5SHong Zhang ts->ops->setup = TSSetUp_BEuler; 1454f33bbcb6SJed Brown ts->ops->view = TSView_BEuler; 1455f33bbcb6SJed Brown PetscFunctionReturn(0); 1456f33bbcb6SJed Brown } 1457f33bbcb6SJed Brown 14581566a47fSLisandro Dalcin static PetscErrorCode TSSetUp_CN(TS ts) 14591566a47fSLisandro Dalcin { 14601566a47fSLisandro Dalcin TS_Theta *th = (TS_Theta*)ts->data; 14611566a47fSLisandro Dalcin 14621566a47fSLisandro Dalcin PetscFunctionBegin; 14632c71b3e2SJacob Faibussowitsch PetscCheckFalse(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"); 14643c633725SBarry 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"); 14655f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetUp_Theta(ts)); 14661566a47fSLisandro Dalcin PetscFunctionReturn(0); 14671566a47fSLisandro Dalcin } 14681566a47fSLisandro Dalcin 1469f33bbcb6SJed Brown static PetscErrorCode TSView_CN(TS ts,PetscViewer viewer) 1470f33bbcb6SJed Brown { 1471f33bbcb6SJed Brown PetscFunctionBegin; 1472f33bbcb6SJed Brown PetscFunctionReturn(0); 1473f33bbcb6SJed Brown } 1474f33bbcb6SJed Brown 1475f33bbcb6SJed Brown /*MC 1476f33bbcb6SJed Brown TSCN - ODE solver using the implicit Crank-Nicolson method. 1477f33bbcb6SJed Brown 1478f33bbcb6SJed Brown Level: beginner 1479f33bbcb6SJed Brown 1480f33bbcb6SJed Brown Notes: 14817cf5af47SJed Brown TSCN is equivalent to TSTHETA with Theta=0.5 and the "endpoint" option set. I.e. 14827cf5af47SJed Brown 14837cf5af47SJed Brown $ -ts_type theta -ts_theta_theta 0.5 -ts_theta_endpoint 1484f33bbcb6SJed Brown 1485f33bbcb6SJed Brown .seealso: TSCreate(), TS, TSSetType(), TSBEULER, TSTHETA 1486f33bbcb6SJed Brown 1487f33bbcb6SJed Brown M*/ 14888cc058d9SJed Brown PETSC_EXTERN PetscErrorCode TSCreate_CN(TS ts) 1489f33bbcb6SJed Brown { 1490f33bbcb6SJed Brown PetscFunctionBegin; 14915f80ce2aSJacob Faibussowitsch CHKERRQ(TSCreate_Theta(ts)); 14925f80ce2aSJacob Faibussowitsch CHKERRQ(TSThetaSetTheta(ts,0.5)); 14935f80ce2aSJacob Faibussowitsch CHKERRQ(TSThetaSetEndpoint(ts,PETSC_TRUE)); 14940c7376e5SHong Zhang ts->ops->setup = TSSetUp_CN; 1495f33bbcb6SJed Brown ts->ops->view = TSView_CN; 1496f33bbcb6SJed Brown PetscFunctionReturn(0); 1497f33bbcb6SJed Brown } 1498