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; 121566a47fSLisandro Dalcin Vec X0,X,Xdot; /* Storage for stages and time derivative */ 131566a47fSLisandro Dalcin Vec affine; /* Affine vector needed for residual at beginning of step in endpoint formulation */ 141566a47fSLisandro Dalcin PetscReal Theta; 15715f1b00SHong Zhang PetscReal ptime; 16715f1b00SHong Zhang PetscReal time_step; 171566a47fSLisandro Dalcin PetscInt order; 181566a47fSLisandro Dalcin PetscBool endpoint; 191566a47fSLisandro Dalcin PetscBool extrapolate; 20715f1b00SHong Zhang TSStepStatus status; 21715f1b00SHong Zhang Vec VecCostIntegral0; /* Backup for roll-backs due to events */ 221566a47fSLisandro Dalcin 23715f1b00SHong Zhang /* context for sensitivity analysis */ 24022c081aSHong Zhang PetscInt num_tlm; /* Total number of tangent linear equations */ 25b5e0532dSHong Zhang Vec *VecsDeltaLam; /* Increment of the adjoint sensitivity w.r.t IC at stage */ 26b5e0532dSHong Zhang Vec *VecsDeltaMu; /* Increment of the adjoint sensitivity w.r.t P at stage */ 27b5e0532dSHong Zhang Vec *VecsSensiTemp; /* Vector to be timed with Jacobian transpose */ 28715f1b00SHong Zhang Vec *VecsDeltaFwdSensi; /* Increment of the forward sensitivity at stage */ 29715f1b00SHong Zhang Vec VecIntegralSensiTemp; /* Working vector for forward integral sensitivity */ 30715f1b00SHong Zhang Vec VecIntegralSensipTemp; /* Working vector for forward integral sensitivity */ 316f92202bSHong Zhang Vec *VecsFwdSensi0; /* backup for roll-backs due to events */ 326f92202bSHong Zhang Vec *VecsIntegralSensi0; /* backup for roll-backs due to events */ 336f92202bSHong Zhang Vec *VecsIntegralSensip0; /* backup for roll-backs due to events */ 341566a47fSLisandro Dalcin 35715f1b00SHong Zhang /* context for error estimation */ 361566a47fSLisandro Dalcin Vec vec_sol_prev; 371566a47fSLisandro Dalcin Vec vec_lte_work; 38316643e7SJed Brown } TS_Theta; 39316643e7SJed Brown 407445fe48SJed Brown static PetscErrorCode TSThetaGetX0AndXdot(TS ts,DM dm,Vec *X0,Vec *Xdot) 417445fe48SJed Brown { 427445fe48SJed Brown TS_Theta *th = (TS_Theta*)ts->data; 437445fe48SJed Brown PetscErrorCode ierr; 447445fe48SJed Brown 457445fe48SJed Brown PetscFunctionBegin; 467445fe48SJed Brown if (X0) { 477445fe48SJed Brown if (dm && dm != ts->dm) { 480d0b770aSPeter Brune ierr = DMGetNamedGlobalVector(dm,"TSTheta_X0",X0);CHKERRQ(ierr); 497445fe48SJed Brown } else *X0 = ts->vec_sol; 507445fe48SJed Brown } 517445fe48SJed Brown if (Xdot) { 527445fe48SJed Brown if (dm && dm != ts->dm) { 530d0b770aSPeter Brune ierr = DMGetNamedGlobalVector(dm,"TSTheta_Xdot",Xdot);CHKERRQ(ierr); 547445fe48SJed Brown } else *Xdot = th->Xdot; 557445fe48SJed Brown } 567445fe48SJed Brown PetscFunctionReturn(0); 577445fe48SJed Brown } 587445fe48SJed Brown 590d0b770aSPeter Brune static PetscErrorCode TSThetaRestoreX0AndXdot(TS ts,DM dm,Vec *X0,Vec *Xdot) 600d0b770aSPeter Brune { 610d0b770aSPeter Brune PetscErrorCode ierr; 620d0b770aSPeter Brune 630d0b770aSPeter Brune PetscFunctionBegin; 640d0b770aSPeter Brune if (X0) { 650d0b770aSPeter Brune if (dm && dm != ts->dm) { 660d0b770aSPeter Brune ierr = DMRestoreNamedGlobalVector(dm,"TSTheta_X0",X0);CHKERRQ(ierr); 670d0b770aSPeter Brune } 680d0b770aSPeter Brune } 690d0b770aSPeter Brune if (Xdot) { 700d0b770aSPeter Brune if (dm && dm != ts->dm) { 710d0b770aSPeter Brune ierr = DMRestoreNamedGlobalVector(dm,"TSTheta_Xdot",Xdot);CHKERRQ(ierr); 720d0b770aSPeter Brune } 730d0b770aSPeter Brune } 740d0b770aSPeter Brune PetscFunctionReturn(0); 750d0b770aSPeter Brune } 760d0b770aSPeter Brune 777445fe48SJed Brown static PetscErrorCode DMCoarsenHook_TSTheta(DM fine,DM coarse,void *ctx) 787445fe48SJed Brown { 797445fe48SJed Brown PetscFunctionBegin; 807445fe48SJed Brown PetscFunctionReturn(0); 817445fe48SJed Brown } 827445fe48SJed Brown 837445fe48SJed Brown static PetscErrorCode DMRestrictHook_TSTheta(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse,void *ctx) 847445fe48SJed Brown { 857445fe48SJed Brown TS ts = (TS)ctx; 867445fe48SJed Brown PetscErrorCode ierr; 877445fe48SJed Brown Vec X0,Xdot,X0_c,Xdot_c; 887445fe48SJed Brown 897445fe48SJed Brown PetscFunctionBegin; 907445fe48SJed Brown ierr = TSThetaGetX0AndXdot(ts,fine,&X0,&Xdot);CHKERRQ(ierr); 917445fe48SJed Brown ierr = TSThetaGetX0AndXdot(ts,coarse,&X0_c,&Xdot_c);CHKERRQ(ierr); 927445fe48SJed Brown ierr = MatRestrict(restrct,X0,X0_c);CHKERRQ(ierr); 937445fe48SJed Brown ierr = MatRestrict(restrct,Xdot,Xdot_c);CHKERRQ(ierr); 947445fe48SJed Brown ierr = VecPointwiseMult(X0_c,rscale,X0_c);CHKERRQ(ierr); 957445fe48SJed Brown ierr = VecPointwiseMult(Xdot_c,rscale,Xdot_c);CHKERRQ(ierr); 960d0b770aSPeter Brune ierr = TSThetaRestoreX0AndXdot(ts,fine,&X0,&Xdot);CHKERRQ(ierr); 970d0b770aSPeter Brune ierr = TSThetaRestoreX0AndXdot(ts,coarse,&X0_c,&Xdot_c);CHKERRQ(ierr); 987445fe48SJed Brown PetscFunctionReturn(0); 997445fe48SJed Brown } 1007445fe48SJed Brown 101258e1594SPeter Brune static PetscErrorCode DMSubDomainHook_TSTheta(DM dm,DM subdm,void *ctx) 102258e1594SPeter Brune { 103258e1594SPeter Brune PetscFunctionBegin; 104258e1594SPeter Brune PetscFunctionReturn(0); 105258e1594SPeter Brune } 106258e1594SPeter Brune 107258e1594SPeter Brune static PetscErrorCode DMSubDomainRestrictHook_TSTheta(DM dm,VecScatter gscat,VecScatter lscat,DM subdm,void *ctx) 108258e1594SPeter Brune { 109258e1594SPeter Brune TS ts = (TS)ctx; 110258e1594SPeter Brune PetscErrorCode ierr; 111258e1594SPeter Brune Vec X0,Xdot,X0_sub,Xdot_sub; 112258e1594SPeter Brune 113258e1594SPeter Brune PetscFunctionBegin; 114258e1594SPeter Brune ierr = TSThetaGetX0AndXdot(ts,dm,&X0,&Xdot);CHKERRQ(ierr); 115258e1594SPeter Brune ierr = TSThetaGetX0AndXdot(ts,subdm,&X0_sub,&Xdot_sub);CHKERRQ(ierr); 116258e1594SPeter Brune 117258e1594SPeter Brune ierr = VecScatterBegin(gscat,X0,X0_sub,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 118258e1594SPeter Brune ierr = VecScatterEnd(gscat,X0,X0_sub,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 119258e1594SPeter Brune 120258e1594SPeter Brune ierr = VecScatterBegin(gscat,Xdot,Xdot_sub,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 121258e1594SPeter Brune ierr = VecScatterEnd(gscat,Xdot,Xdot_sub,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 122258e1594SPeter Brune 123258e1594SPeter Brune ierr = TSThetaRestoreX0AndXdot(ts,dm,&X0,&Xdot);CHKERRQ(ierr); 124258e1594SPeter Brune ierr = TSThetaRestoreX0AndXdot(ts,subdm,&X0_sub,&Xdot_sub);CHKERRQ(ierr); 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; 131022c081aSHong Zhang PetscErrorCode ierr; 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) { 137022c081aSHong Zhang ierr = TSComputeCostIntegrand(ts,th->ptime,th->X0,ts->vec_costintegrand);CHKERRQ(ierr); 138022c081aSHong Zhang ierr = VecAXPY(ts->vec_costintegral,th->time_step*(1.0-th->Theta),ts->vec_costintegrand);CHKERRQ(ierr); 139022c081aSHong Zhang } 140022c081aSHong Zhang ierr = TSComputeCostIntegrand(ts,ts->ptime,ts->vec_sol,ts->vec_costintegrand);CHKERRQ(ierr); 141022c081aSHong Zhang ierr = VecAXPY(ts->vec_costintegral,th->time_step*th->Theta,ts->vec_costintegrand);CHKERRQ(ierr); 142022c081aSHong Zhang } else { 143022c081aSHong Zhang ierr = TSComputeCostIntegrand(ts,th->stage_time,th->X,ts->vec_costintegrand);CHKERRQ(ierr); 144022c081aSHong Zhang ierr = VecAXPY(ts->vec_costintegral,th->time_step,ts->vec_costintegrand);CHKERRQ(ierr); 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; 152b1cb36f3SHong Zhang PetscErrorCode ierr; 153b1cb36f3SHong Zhang 154b1cb36f3SHong Zhang PetscFunctionBegin; 155b1cb36f3SHong Zhang /* backup cost integral */ 156b1cb36f3SHong Zhang ierr = VecCopy(ts->vec_costintegral,th->VecCostIntegral0);CHKERRQ(ierr); 157022c081aSHong Zhang ierr = TSThetaEvaluateCostIntegral(ts);CHKERRQ(ierr); 158b1cb36f3SHong Zhang PetscFunctionReturn(0); 159b1cb36f3SHong Zhang } 160b1cb36f3SHong Zhang 161b1cb36f3SHong Zhang static PetscErrorCode TSAdjointCostIntegral_Theta(TS ts) 162b1cb36f3SHong Zhang { 163b1cb36f3SHong Zhang PetscErrorCode ierr; 164b1cb36f3SHong Zhang 165b1cb36f3SHong Zhang PetscFunctionBegin; 166022c081aSHong Zhang ierr = TSThetaEvaluateCostIntegral(ts);CHKERRQ(ierr); 16724655328SShri PetscFunctionReturn(0); 16824655328SShri } 16924655328SShri 1701566a47fSLisandro Dalcin static PetscErrorCode TS_SNESSolve(TS ts,Vec b,Vec x) 1711566a47fSLisandro Dalcin { 1721566a47fSLisandro Dalcin PetscInt nits,lits; 1731566a47fSLisandro Dalcin PetscErrorCode ierr; 1741566a47fSLisandro Dalcin 1751566a47fSLisandro Dalcin PetscFunctionBegin; 1761566a47fSLisandro Dalcin ierr = SNESSolve(ts->snes,b,x);CHKERRQ(ierr); 1771566a47fSLisandro Dalcin ierr = SNESGetIterationNumber(ts->snes,&nits);CHKERRQ(ierr); 1781566a47fSLisandro Dalcin ierr = SNESGetLinearSolveIterations(ts->snes,&lits);CHKERRQ(ierr); 1791566a47fSLisandro Dalcin ts->snes_its += nits; ts->ksp_its += lits; 1801566a47fSLisandro Dalcin PetscFunctionReturn(0); 1811566a47fSLisandro Dalcin } 1821566a47fSLisandro Dalcin 183193ac0bcSJed Brown static PetscErrorCode TSStep_Theta(TS ts) 184316643e7SJed Brown { 185316643e7SJed Brown TS_Theta *th = (TS_Theta*)ts->data; 1861566a47fSLisandro Dalcin PetscInt rejections = 0; 1874957b756SLisandro Dalcin PetscBool stageok,accept = PETSC_TRUE; 1881566a47fSLisandro Dalcin PetscReal next_time_step = ts->time_step; 189051f2191SLisandro Dalcin PetscErrorCode ierr; 190316643e7SJed Brown 191316643e7SJed Brown PetscFunctionBegin; 1921566a47fSLisandro Dalcin if (!ts->steprollback) { 1932ffb9264SLisandro Dalcin if (th->vec_sol_prev) { ierr = VecCopy(th->X0,th->vec_sol_prev);CHKERRQ(ierr); } 1943b1890cdSShri Abhyankar ierr = VecCopy(ts->vec_sol,th->X0);CHKERRQ(ierr); 1951566a47fSLisandro Dalcin } 1961566a47fSLisandro Dalcin 1971566a47fSLisandro Dalcin th->status = TS_STEP_INCOMPLETE; 1981566a47fSLisandro Dalcin while (!ts->reason && th->status != TS_STEP_COMPLETE) { 199715f1b00SHong Zhang 2001566a47fSLisandro Dalcin PetscReal shift = 1/(th->Theta*ts->time_step); 2011566a47fSLisandro Dalcin th->stage_time = ts->ptime + (th->endpoint ? (PetscReal)1 : th->Theta)*ts->time_step; 202316643e7SJed Brown 203be5899b3SLisandro Dalcin ierr = VecCopy(th->X0,th->X);CHKERRQ(ierr); 204fecfb714SLisandro Dalcin if (th->extrapolate && !ts->steprestart) { 205be5899b3SLisandro Dalcin ierr = VecAXPY(th->X,1/shift,th->Xdot);CHKERRQ(ierr); 206be5899b3SLisandro Dalcin } 207eb284becSJed Brown if (th->endpoint) { /* This formulation assumes linear time-independent mass matrix */ 208eb284becSJed Brown if (!th->affine) {ierr = VecDuplicate(ts->vec_sol,&th->affine);CHKERRQ(ierr);} 2091566a47fSLisandro Dalcin ierr = VecZeroEntries(th->Xdot);CHKERRQ(ierr); 2101566a47fSLisandro Dalcin ierr = TSComputeIFunction(ts,ts->ptime,th->X0,th->Xdot,th->affine,PETSC_FALSE);CHKERRQ(ierr); 2111566a47fSLisandro Dalcin ierr = VecScale(th->affine,(th->Theta-1)/th->Theta);CHKERRQ(ierr); 2121566a47fSLisandro Dalcin } else if (th->affine) { /* Just in case th->endpoint is changed between calls to TSStep_Theta() */ 2131566a47fSLisandro Dalcin ierr = VecZeroEntries(th->affine);CHKERRQ(ierr); 214eb284becSJed Brown } 215be5899b3SLisandro Dalcin ierr = TSPreStage(ts,th->stage_time);CHKERRQ(ierr); 2161566a47fSLisandro Dalcin ierr = TS_SNESSolve(ts,th->affine,th->X);CHKERRQ(ierr); 217be5899b3SLisandro Dalcin ierr = TSPostStage(ts,th->stage_time,0,&th->X);CHKERRQ(ierr); 2181566a47fSLisandro Dalcin ierr = TSAdaptCheckStage(ts->adapt,ts,th->stage_time,th->X,&stageok);CHKERRQ(ierr); 219fecfb714SLisandro Dalcin if (!stageok) goto reject_step; 220051f2191SLisandro Dalcin 221051f2191SLisandro Dalcin th->status = TS_STEP_PENDING; 2221566a47fSLisandro Dalcin if (th->endpoint) { 2231566a47fSLisandro Dalcin ierr = VecCopy(th->X,ts->vec_sol);CHKERRQ(ierr); 2241566a47fSLisandro Dalcin } else { 225cb3a5882SLisandro Dalcin ierr = VecAXPBYPCZ(th->Xdot,-shift,shift,0,th->X0,th->X);CHKERRQ(ierr); 2261566a47fSLisandro Dalcin ierr = VecAXPY(ts->vec_sol,ts->time_step,th->Xdot);CHKERRQ(ierr); 2271566a47fSLisandro Dalcin } 2281566a47fSLisandro Dalcin ierr = TSAdaptChoose(ts->adapt,ts,ts->time_step,NULL,&next_time_step,&accept);CHKERRQ(ierr); 2291566a47fSLisandro Dalcin th->status = accept ? TS_STEP_COMPLETE : TS_STEP_INCOMPLETE; 2301566a47fSLisandro Dalcin if (!accept) { 2311566a47fSLisandro Dalcin ierr = VecCopy(th->X0,ts->vec_sol);CHKERRQ(ierr); 232be5899b3SLisandro Dalcin ts->time_step = next_time_step; 233be5899b3SLisandro Dalcin goto reject_step; 234051f2191SLisandro Dalcin } 2353b1890cdSShri Abhyankar 236715f1b00SHong Zhang if (ts->forward_solve || ts->costintegralfwd) { /* Save the info for the later use in cost integral evaluation */ 237b1cb36f3SHong Zhang th->ptime = ts->ptime; 238b1cb36f3SHong Zhang th->time_step = ts->time_step; 23917145e75SHong Zhang } 2401566a47fSLisandro Dalcin 2412b5a38e1SLisandro Dalcin ts->ptime += ts->time_step; 242cdbf8f93SLisandro Dalcin ts->time_step = next_time_step; 243051f2191SLisandro Dalcin break; 244051f2191SLisandro Dalcin 245051f2191SLisandro Dalcin reject_step: 246fecfb714SLisandro Dalcin ts->reject++; accept = PETSC_FALSE; 2471566a47fSLisandro Dalcin if (!ts->reason && ++rejections > ts->max_reject && ts->max_reject >= 0) { 248051f2191SLisandro Dalcin ts->reason = TS_DIVERGED_STEP_REJECTED; 2491566a47fSLisandro Dalcin ierr = PetscInfo2(ts,"Step=%D, step rejections %D greater than current TS allowed, stopping solve\n",ts->steps,rejections);CHKERRQ(ierr); 2503b1890cdSShri Abhyankar } 2513b1890cdSShri Abhyankar } 252316643e7SJed Brown PetscFunctionReturn(0); 253316643e7SJed Brown } 254316643e7SJed Brown 25542f2b339SBarry Smith static PetscErrorCode TSAdjointStep_Theta(TS ts) 2562ca6e920SHong Zhang { 2572ca6e920SHong Zhang TS_Theta *th = (TS_Theta*)ts->data; 258b5e0532dSHong Zhang Vec *VecsDeltaLam = th->VecsDeltaLam,*VecsDeltaMu = th->VecsDeltaMu,*VecsSensiTemp = th->VecsSensiTemp; 2592ca6e920SHong Zhang PetscInt nadj; 2602ca6e920SHong Zhang PetscErrorCode ierr; 2612ca6e920SHong Zhang Mat J,Jp; 2622ca6e920SHong Zhang KSP ksp; 2632ca6e920SHong Zhang PetscReal shift; 2642ca6e920SHong Zhang 2652ca6e920SHong Zhang PetscFunctionBegin; 2662ca6e920SHong Zhang th->status = TS_STEP_INCOMPLETE; 267302440fdSBarry Smith ierr = SNESGetKSP(ts->snes,&ksp);CHKERRQ(ierr); 2682ca6e920SHong Zhang ierr = TSGetIJacobian(ts,&J,&Jp,NULL,NULL);CHKERRQ(ierr); 269b5e0532dSHong Zhang 270b5e0532dSHong Zhang /* If endpoint=1, th->ptime and th->X0 will be used; if endpoint=0, th->stage_time and th->X will be used. */ 271022c081aSHong Zhang th->stage_time = th->endpoint ? ts->ptime : (ts->ptime+(1.-th->Theta)*ts->time_step); /* time_step is negative*/ 272b5e0532dSHong Zhang th->ptime = ts->ptime + ts->time_step; 273022c081aSHong Zhang th->time_step = -ts->time_step; 2742ca6e920SHong Zhang 275a4cab896SHong Zhang /* Build RHS */ 2762c39e106SBarry Smith if (ts->vec_costintegral) { /* Cost function has an integral term */ 27705755b9cSHong Zhang if (th->endpoint) { 278022c081aSHong Zhang ierr = TSAdjointComputeDRDYFunction(ts,th->stage_time,ts->vec_sol,ts->vecs_drdy);CHKERRQ(ierr); 27905755b9cSHong Zhang } else { 280d4aa0a58SBarry Smith ierr = TSAdjointComputeDRDYFunction(ts,th->stage_time,th->X,ts->vecs_drdy);CHKERRQ(ierr); 28105755b9cSHong Zhang } 28205755b9cSHong Zhang } 283abc2977eSBarry Smith for (nadj=0; nadj<ts->numcost; nadj++) { 284b5e0532dSHong Zhang ierr = VecCopy(ts->vecs_sensi[nadj],VecsSensiTemp[nadj]);CHKERRQ(ierr); 285022c081aSHong Zhang ierr = VecScale(VecsSensiTemp[nadj],1./(th->Theta*th->time_step));CHKERRQ(ierr); 2862c39e106SBarry Smith if (ts->vec_costintegral) { 287b5e0532dSHong Zhang ierr = VecAXPY(VecsSensiTemp[nadj],1.,ts->vecs_drdy[nadj]);CHKERRQ(ierr); 28836eaed60SHong Zhang } 2892ca6e920SHong Zhang } 2903c54f92cSHong Zhang 2912ca6e920SHong Zhang /* Build LHS */ 292022c081aSHong Zhang shift = 1./(th->Theta*th->time_step); 2933c54f92cSHong Zhang if (th->endpoint) { 294022c081aSHong Zhang ierr = TSComputeIJacobian(ts,th->stage_time,ts->vec_sol,th->Xdot,shift,J,Jp,PETSC_FALSE);CHKERRQ(ierr); 2953c54f92cSHong Zhang } else { 2963c54f92cSHong Zhang ierr = TSComputeIJacobian(ts,th->stage_time,th->X,th->Xdot,shift,J,Jp,PETSC_FALSE);CHKERRQ(ierr); 2973c54f92cSHong Zhang } 2982ca6e920SHong Zhang ierr = KSPSetOperators(ksp,J,Jp);CHKERRQ(ierr); 2992ca6e920SHong Zhang 3002ca6e920SHong Zhang /* Solve LHS X = RHS */ 301abc2977eSBarry Smith for (nadj=0; nadj<ts->numcost; nadj++) { 302b5e0532dSHong Zhang ierr = KSPSolveTranspose(ksp,VecsSensiTemp[nadj],VecsDeltaLam[nadj]);CHKERRQ(ierr); 3032ca6e920SHong Zhang } 3043c54f92cSHong Zhang 30536eaed60SHong Zhang /* Update sensitivities, and evaluate integrals if there is any */ 306b5e0532dSHong Zhang if(th->endpoint) { /* two-stage case */ 307b5e0532dSHong Zhang if (th->Theta!=1.) { 308022c081aSHong Zhang shift = 1./((th->Theta-1.)*th->time_step); 309b5e0532dSHong Zhang ierr = TSComputeIJacobian(ts,th->ptime,th->X0,th->Xdot,shift,J,Jp,PETSC_FALSE);CHKERRQ(ierr); 3102c39e106SBarry Smith if (ts->vec_costintegral) { 311b5e0532dSHong Zhang ierr = TSAdjointComputeDRDYFunction(ts,th->ptime,th->X0,ts->vecs_drdy);CHKERRQ(ierr); 3128263dbbfSHong Zhang } 313abc2977eSBarry Smith for (nadj=0; nadj<ts->numcost; nadj++) { 314b5e0532dSHong Zhang ierr = MatMultTranspose(J,VecsDeltaLam[nadj],ts->vecs_sensi[nadj]);CHKERRQ(ierr); 3152c39e106SBarry Smith if (ts->vec_costintegral) { 31636eaed60SHong Zhang ierr = VecAXPY(ts->vecs_sensi[nadj],-1.,ts->vecs_drdy[nadj]);CHKERRQ(ierr); 31736eaed60SHong Zhang } 3183c54f92cSHong Zhang ierr = VecScale(ts->vecs_sensi[nadj],1./shift);CHKERRQ(ierr); 3192ca6e920SHong Zhang } 320b5e0532dSHong Zhang } else { /* backward Euler */ 321b5e0532dSHong Zhang shift = 0.0; 322022c081aSHong Zhang ierr = TSComputeIJacobian(ts,th->stage_time,ts->vec_sol,th->Xdot,shift,J,Jp,PETSC_FALSE);CHKERRQ(ierr); /* get -f_y */ 323b5e0532dSHong Zhang for (nadj=0; nadj<ts->numcost; nadj++) { 324b5e0532dSHong Zhang ierr = MatMultTranspose(J,VecsDeltaLam[nadj],VecsSensiTemp[nadj]);CHKERRQ(ierr); 325022c081aSHong Zhang ierr = VecAXPY(ts->vecs_sensi[nadj],-th->time_step,VecsSensiTemp[nadj]);CHKERRQ(ierr); 326b5e0532dSHong Zhang if (ts->vec_costintegral) { 327022c081aSHong Zhang ierr = VecAXPY(ts->vecs_sensi[nadj],th->time_step,ts->vecs_drdy[nadj]);CHKERRQ(ierr); 328b5e0532dSHong Zhang } 329b5e0532dSHong Zhang } 330b5e0532dSHong Zhang } 3313fd52205SHong Zhang 3323fd52205SHong Zhang if (ts->vecs_sensip) { /* sensitivities wrt parameters */ 333022c081aSHong Zhang ierr = TSAdjointComputeRHSJacobian(ts,th->stage_time,ts->vec_sol,ts->Jacp);CHKERRQ(ierr); 334abc2977eSBarry Smith for (nadj=0; nadj<ts->numcost; nadj++) { 335b5e0532dSHong Zhang ierr = MatMultTranspose(ts->Jacp,VecsDeltaLam[nadj],VecsDeltaMu[nadj]);CHKERRQ(ierr); 336022c081aSHong Zhang ierr = VecAXPY(ts->vecs_sensip[nadj],th->time_step*th->Theta,VecsDeltaMu[nadj]);CHKERRQ(ierr); 3373fd52205SHong Zhang } 338b5e0532dSHong Zhang if (th->Theta!=1.) { 339b5e0532dSHong Zhang ierr = TSAdjointComputeRHSJacobian(ts,th->ptime,th->X0,ts->Jacp);CHKERRQ(ierr); 340abc2977eSBarry Smith for (nadj=0; nadj<ts->numcost; nadj++) { 341b5e0532dSHong Zhang ierr = MatMultTranspose(ts->Jacp,VecsDeltaLam[nadj],VecsDeltaMu[nadj]);CHKERRQ(ierr); 342022c081aSHong Zhang ierr = VecAXPY(ts->vecs_sensip[nadj],th->time_step*(1.-th->Theta),VecsDeltaMu[nadj]);CHKERRQ(ierr); 343b5e0532dSHong Zhang } 3443fd52205SHong Zhang } 3452c39e106SBarry Smith if (ts->vec_costintegral) { 346022c081aSHong Zhang ierr = TSAdjointComputeDRDPFunction(ts,th->stage_time,ts->vec_sol,ts->vecs_drdp);CHKERRQ(ierr); 347abc2977eSBarry Smith for (nadj=0; nadj<ts->numcost; nadj++) { 348022c081aSHong Zhang ierr = VecAXPY(ts->vecs_sensip[nadj],th->time_step*th->Theta,ts->vecs_drdp[nadj]);CHKERRQ(ierr); 34936eaed60SHong Zhang } 350b5e0532dSHong Zhang if (th->Theta!=1.) { 351b5e0532dSHong Zhang ierr = TSAdjointComputeDRDPFunction(ts,th->ptime,th->X0,ts->vecs_drdp);CHKERRQ(ierr); 352abc2977eSBarry Smith for (nadj=0; nadj<ts->numcost; nadj++) { 353022c081aSHong Zhang ierr = VecAXPY(ts->vecs_sensip[nadj],th->time_step*(1.-th->Theta),ts->vecs_drdp[nadj]);CHKERRQ(ierr); 35436eaed60SHong Zhang } 35536eaed60SHong Zhang } 3563fd52205SHong Zhang } 357b5e0532dSHong Zhang } 3583fd52205SHong Zhang } else { /* one-stage case */ 3593c54f92cSHong Zhang shift = 0.0; 360a2ae3dd2SHong Zhang ierr = TSComputeIJacobian(ts,th->stage_time,th->X,th->Xdot,shift,J,Jp,PETSC_FALSE);CHKERRQ(ierr); /* get -f_y */ 3612c39e106SBarry Smith if (ts->vec_costintegral) { 362d4aa0a58SBarry Smith ierr = TSAdjointComputeDRDYFunction(ts,th->stage_time,th->X,ts->vecs_drdy);CHKERRQ(ierr); 3633c54f92cSHong Zhang } 364abc2977eSBarry Smith for (nadj=0; nadj<ts->numcost; nadj++) { 365b5e0532dSHong Zhang ierr = MatMultTranspose(J,VecsDeltaLam[nadj],VecsSensiTemp[nadj]);CHKERRQ(ierr); 366022c081aSHong Zhang ierr = VecAXPY(ts->vecs_sensi[nadj],-th->time_step,VecsSensiTemp[nadj]);CHKERRQ(ierr); 3672c39e106SBarry Smith if (ts->vec_costintegral) { 368022c081aSHong Zhang ierr = VecAXPY(ts->vecs_sensi[nadj],th->time_step,ts->vecs_drdy[nadj]);CHKERRQ(ierr); 36936eaed60SHong Zhang } 3702ca6e920SHong Zhang } 3713fd52205SHong Zhang if (ts->vecs_sensip) { 3725bf8c567SBarry Smith ierr = TSAdjointComputeRHSJacobian(ts,th->stage_time,th->X,ts->Jacp);CHKERRQ(ierr); 373abc2977eSBarry Smith for (nadj=0; nadj<ts->numcost; nadj++) { 374b5e0532dSHong Zhang ierr = MatMultTranspose(ts->Jacp,VecsDeltaLam[nadj],VecsDeltaMu[nadj]);CHKERRQ(ierr); 375022c081aSHong Zhang ierr = VecAXPY(ts->vecs_sensip[nadj],th->time_step,VecsDeltaMu[nadj]);CHKERRQ(ierr); 3763fd52205SHong Zhang } 3772c39e106SBarry Smith if (ts->vec_costintegral) { 378d4aa0a58SBarry Smith ierr = TSAdjointComputeDRDPFunction(ts,th->stage_time,th->X,ts->vecs_drdp);CHKERRQ(ierr); 379abc2977eSBarry Smith for (nadj=0; nadj<ts->numcost; nadj++) { 380022c081aSHong Zhang ierr = VecAXPY(ts->vecs_sensip[nadj],th->time_step,ts->vecs_drdp[nadj]);CHKERRQ(ierr); 38136eaed60SHong Zhang } 38236eaed60SHong Zhang } 3833fd52205SHong Zhang } 3842ca6e920SHong Zhang } 3852ca6e920SHong Zhang 3862ca6e920SHong Zhang th->status = TS_STEP_COMPLETE; 3872ca6e920SHong Zhang PetscFunctionReturn(0); 3882ca6e920SHong Zhang } 3892ca6e920SHong Zhang 390cd652676SJed Brown static PetscErrorCode TSInterpolate_Theta(TS ts,PetscReal t,Vec X) 391cd652676SJed Brown { 392cd652676SJed Brown TS_Theta *th = (TS_Theta*)ts->data; 393be5899b3SLisandro Dalcin PetscReal dt = t - ts->ptime; 394cd652676SJed Brown PetscErrorCode ierr; 395cd652676SJed Brown 396cd652676SJed Brown PetscFunctionBegin; 397a43b19c4SJed Brown ierr = VecCopy(ts->vec_sol,th->X);CHKERRQ(ierr); 398be5899b3SLisandro Dalcin if (th->endpoint) dt *= th->Theta; 399be5899b3SLisandro Dalcin ierr = VecWAXPY(X,dt,th->Xdot,th->X);CHKERRQ(ierr); 400cd652676SJed Brown PetscFunctionReturn(0); 401cd652676SJed Brown } 402cd652676SJed Brown 4031566a47fSLisandro Dalcin static PetscErrorCode TSEvaluateWLTE_Theta(TS ts,NormType wnormtype,PetscInt *order,PetscReal *wlte) 4041566a47fSLisandro Dalcin { 4051566a47fSLisandro Dalcin TS_Theta *th = (TS_Theta*)ts->data; 4061566a47fSLisandro Dalcin Vec X = ts->vec_sol; /* X = solution */ 4071566a47fSLisandro Dalcin Vec Y = th->vec_lte_work; /* Y = X + LTE */ 4087453f775SEmil Constantinescu PetscReal wltea,wlter; 4091566a47fSLisandro Dalcin PetscErrorCode ierr; 4101566a47fSLisandro Dalcin 4111566a47fSLisandro Dalcin PetscFunctionBegin; 4122ffb9264SLisandro Dalcin if (!th->vec_sol_prev) {*wlte = -1; PetscFunctionReturn(0);} 4131566a47fSLisandro Dalcin /* Cannot compute LTE in first step or in restart after event */ 414fecfb714SLisandro Dalcin if (ts->steprestart) {*wlte = -1; PetscFunctionReturn(0);} 4151566a47fSLisandro Dalcin /* Compute LTE using backward differences with non-constant time step */ 416fecfb714SLisandro Dalcin { 417be5899b3SLisandro Dalcin PetscReal h = ts->time_step, h_prev = ts->ptime - ts->ptime_prev; 418be5899b3SLisandro Dalcin PetscReal a = 1 + h_prev/h; 4191566a47fSLisandro Dalcin PetscScalar scal[3]; Vec vecs[3]; 4201566a47fSLisandro Dalcin scal[0] = +1/a; scal[1] = -1/(a-1); scal[2] = +1/(a*(a-1)); 4211566a47fSLisandro Dalcin vecs[0] = X; vecs[1] = th->X0; vecs[2] = th->vec_sol_prev; 4221566a47fSLisandro Dalcin ierr = VecCopy(X,Y);CHKERRQ(ierr); 4231566a47fSLisandro Dalcin ierr = VecMAXPY(Y,3,scal,vecs);CHKERRQ(ierr); 4247453f775SEmil Constantinescu ierr = TSErrorWeightedNorm(ts,X,Y,wnormtype,wlte,&wltea,&wlter);CHKERRQ(ierr); 4251566a47fSLisandro Dalcin } 4261566a47fSLisandro Dalcin if (order) *order = 2; 4271566a47fSLisandro Dalcin PetscFunctionReturn(0); 4281566a47fSLisandro Dalcin } 4291566a47fSLisandro Dalcin 4301566a47fSLisandro Dalcin static PetscErrorCode TSRollBack_Theta(TS ts) 4311566a47fSLisandro Dalcin { 4321566a47fSLisandro Dalcin TS_Theta *th = (TS_Theta*)ts->data; 433022c081aSHong Zhang PetscInt ntlm,ncost; 4341566a47fSLisandro Dalcin PetscErrorCode ierr; 4351566a47fSLisandro Dalcin 4361566a47fSLisandro Dalcin PetscFunctionBegin; 4371566a47fSLisandro Dalcin ierr = VecCopy(th->X0,ts->vec_sol);CHKERRQ(ierr); 4381566a47fSLisandro Dalcin if (ts->vec_costintegral && ts->costintegralfwd) { 4391566a47fSLisandro Dalcin ierr = VecCopy(th->VecCostIntegral0,ts->vec_costintegral);CHKERRQ(ierr); 4401566a47fSLisandro Dalcin } 441715f1b00SHong Zhang th->status = TS_STEP_INCOMPLETE; 4426f92202bSHong Zhang 443022c081aSHong Zhang for (ntlm=0;ntlm<th->num_tlm;ntlm++) { 444022c081aSHong Zhang ierr = VecCopy(th->VecsFwdSensi0[ntlm],ts->vecs_fwdsensipacked[ntlm]);CHKERRQ(ierr); 4456f92202bSHong Zhang } 4466f92202bSHong Zhang if (ts->vecs_integral_sensi) { 4476f92202bSHong Zhang for (ncost=0;ncost<ts->numcost;ncost++) { 4486f92202bSHong Zhang ierr = VecCopy(th->VecsIntegralSensi0[ncost],ts->vecs_integral_sensi[ncost]);CHKERRQ(ierr); 4496f92202bSHong Zhang } 4506f92202bSHong Zhang } 4516f92202bSHong Zhang if (ts->vecs_integral_sensip) { 4526f92202bSHong Zhang for (ncost=0;ncost<ts->numcost;ncost++) { 4536f92202bSHong Zhang ierr = VecCopy(th->VecsIntegralSensip0[ncost],ts->vecs_integral_sensip[ncost]);CHKERRQ(ierr); 4546f92202bSHong Zhang } 4556f92202bSHong Zhang } 456715f1b00SHong Zhang PetscFunctionReturn(0); 457715f1b00SHong Zhang } 458715f1b00SHong Zhang 459022c081aSHong Zhang static PetscErrorCode TSThetaIntegrandDerivative(TS ts,PetscInt numtlm,Vec DRncostDY,Vec* s,Vec DRncostDP,Vec VecIntegrandDerivative) 460715f1b00SHong Zhang { 461022c081aSHong Zhang PetscInt ntlm,low,high; 462715f1b00SHong Zhang PetscScalar *v; 463715f1b00SHong Zhang PetscErrorCode ierr; 464715f1b00SHong Zhang 465715f1b00SHong Zhang PetscFunctionBegin; 466715f1b00SHong Zhang 467022c081aSHong Zhang ierr = VecGetOwnershipRange(VecIntegrandDerivative,&low,&high);CHKERRQ(ierr); 468715f1b00SHong Zhang ierr = VecGetArray(VecIntegrandDerivative,&v);CHKERRQ(ierr); 469022c081aSHong Zhang for (ntlm=low; ntlm<high; ntlm++) { 470022c081aSHong Zhang ierr = VecDot(DRncostDY,s[ntlm],&v[ntlm-low]);CHKERRQ(ierr); 471715f1b00SHong Zhang } 472715f1b00SHong Zhang ierr = VecRestoreArray(VecIntegrandDerivative,&v);CHKERRQ(ierr); 473715f1b00SHong Zhang if (DRncostDP) { 474715f1b00SHong Zhang ierr = VecAXPY(VecIntegrandDerivative,1.,DRncostDP);CHKERRQ(ierr); 475715f1b00SHong Zhang } 476715f1b00SHong Zhang PetscFunctionReturn(0); 477715f1b00SHong Zhang } 478715f1b00SHong Zhang 479715f1b00SHong Zhang static PetscErrorCode TSForwardStep_Theta(TS ts) 480715f1b00SHong Zhang { 481715f1b00SHong Zhang TS_Theta *th = (TS_Theta*)ts->data; 482715f1b00SHong Zhang Vec *VecsDeltaFwdSensi = th->VecsDeltaFwdSensi; 483022c081aSHong Zhang PetscInt ntlm,ncost,np; 484715f1b00SHong Zhang KSP ksp; 485715f1b00SHong Zhang Mat J,Jp; 486715f1b00SHong Zhang PetscReal shift; 487715f1b00SHong Zhang PetscErrorCode ierr; 488715f1b00SHong Zhang 489715f1b00SHong Zhang PetscFunctionBegin; 490022c081aSHong Zhang for (ntlm=0; ntlm<th->num_tlm; ntlm++) { 491022c081aSHong Zhang ierr = VecCopy(ts->vecs_fwdsensipacked[ntlm],th->VecsFwdSensi0[ntlm]);CHKERRQ(ierr); 4926f92202bSHong Zhang } 4936f92202bSHong Zhang for (ncost=0; ncost<ts->numcost; ncost++) { 494022c081aSHong Zhang if (ts->vecs_integral_sensi) { 4956f92202bSHong Zhang ierr = VecCopy(ts->vecs_integral_sensi[ncost],th->VecsIntegralSensi0[ncost]);CHKERRQ(ierr); 4966f92202bSHong Zhang } 4976f92202bSHong Zhang if (ts->vecs_integral_sensip) { 4986f92202bSHong Zhang ierr = VecCopy(ts->vecs_integral_sensip[ncost],th->VecsIntegralSensip0[ncost]);CHKERRQ(ierr); 4996f92202bSHong Zhang } 5006f92202bSHong Zhang } 5016f92202bSHong Zhang 502715f1b00SHong Zhang ierr = SNESGetKSP(ts->snes,&ksp);CHKERRQ(ierr); 503715f1b00SHong Zhang ierr = TSGetIJacobian(ts,&J,&Jp,NULL,NULL);CHKERRQ(ierr); 504715f1b00SHong Zhang 505715f1b00SHong Zhang /* Build RHS */ 506715f1b00SHong Zhang if (th->endpoint) { /* 2-stage method*/ 507715f1b00SHong Zhang shift = 1./((th->Theta-1.)*th->time_step); 508715f1b00SHong Zhang ierr = TSComputeIJacobian(ts,th->ptime,th->X0,th->Xdot,shift,J,Jp,PETSC_FALSE);CHKERRQ(ierr); 509715f1b00SHong Zhang 510022c081aSHong Zhang for (ntlm=0; ntlm<th->num_tlm; ntlm++) { 511*7f79407eSBarry Smith ierr = MatMult(J,ts->vecs_fwdsensipacked[ntlm],VecsDeltaFwdSensi[ntlm]);CHKERRQ(ierr); 512*7f79407eSBarry Smith ierr = VecScale(VecsDeltaFwdSensi[ntlm],(th->Theta-1.)/th->Theta);CHKERRQ(ierr); 513022c081aSHong Zhang } 514022c081aSHong Zhang /* Add the f_p forcing terms */ 515715f1b00SHong Zhang ierr = TSForwardComputeRHSJacobianP(ts,th->ptime,th->X0,ts->vecs_jacp);CHKERRQ(ierr); 516022c081aSHong Zhang for (np=0; np<ts->num_parameters; np++) { 517022c081aSHong Zhang ierr = VecAXPY(VecsDeltaFwdSensi[np+ts->num_initialvalues],(1.-th->Theta)/th->Theta,ts->vecs_jacp[np]);CHKERRQ(ierr); 518715f1b00SHong Zhang } 519715f1b00SHong Zhang ierr = TSForwardComputeRHSJacobianP(ts,th->stage_time,ts->vec_sol,ts->vecs_jacp);CHKERRQ(ierr); 520022c081aSHong Zhang for (np=0; np<ts->num_parameters; np++) { 521022c081aSHong Zhang ierr = VecAXPY(VecsDeltaFwdSensi[np+ts->num_initialvalues],1,ts->vecs_jacp[np]);CHKERRQ(ierr); 522715f1b00SHong Zhang } 523715f1b00SHong Zhang } else { /* 1-stage method */ 524715f1b00SHong Zhang shift = 0.0; 525715f1b00SHong Zhang ierr = TSComputeIJacobian(ts,th->stage_time,th->X,th->Xdot,shift,J,Jp,PETSC_FALSE);CHKERRQ(ierr); 526022c081aSHong Zhang for (ntlm=0; ntlm<ts->num_parameters; ntlm++) { 527*7f79407eSBarry Smith ierr = MatMult(J,ts->vecs_fwdsensipacked[ntlm],VecsDeltaFwdSensi[ntlm]);CHKERRQ(ierr); 528*7f79407eSBarry Smith ierr = VecScale(VecsDeltaFwdSensi[ntlm],-1);CHKERRQ(ierr); 529715f1b00SHong Zhang } 530022c081aSHong Zhang /* Add the f_p forcing terms */ 531715f1b00SHong Zhang ierr = TSForwardComputeRHSJacobianP(ts,th->stage_time,th->X,ts->vecs_jacp);CHKERRQ(ierr); 532022c081aSHong Zhang for (np=0; np<ts->num_parameters; np++) { 533022c081aSHong Zhang ierr = VecAXPY(VecsDeltaFwdSensi[np+ts->num_initialvalues],1,ts->vecs_jacp[np]);CHKERRQ(ierr); 534715f1b00SHong Zhang } 535715f1b00SHong Zhang } 536715f1b00SHong Zhang 537715f1b00SHong Zhang /* Build LHS */ 538715f1b00SHong Zhang shift = 1/(th->Theta*th->time_step); 539715f1b00SHong Zhang if (th->endpoint) { 540715f1b00SHong Zhang ierr = TSComputeIJacobian(ts,th->stage_time,ts->vec_sol,th->Xdot,shift,J,Jp,PETSC_FALSE);CHKERRQ(ierr); 541715f1b00SHong Zhang } else { 542715f1b00SHong Zhang ierr = TSComputeIJacobian(ts,th->stage_time,th->X,th->Xdot,shift,J,Jp,PETSC_FALSE);CHKERRQ(ierr); 543715f1b00SHong Zhang } 544715f1b00SHong Zhang ierr = KSPSetOperators(ksp,J,Jp);CHKERRQ(ierr); 545715f1b00SHong Zhang 546715f1b00SHong Zhang /* 547715f1b00SHong Zhang Evaluate the first stage of integral gradients with the 2-stage method: 548715f1b00SHong Zhang drdy|t_n*S(t_n) + drdp|t_n 549715f1b00SHong Zhang This is done before the linear solve because the sensitivity variable S(t_n) will be propagated to S(t_{n+1}) 550715f1b00SHong Zhang It is important to note that sensitivitesi to parameters (sensip) and sensitivities to initial values (sensi) are independent of each other, but integral sensip relies on sensip and integral sensi requires sensi 551715f1b00SHong Zhang */ 552715f1b00SHong Zhang if (th->endpoint) { /* 2-stage method only */ 553715f1b00SHong Zhang if (ts->vecs_integral_sensi || ts->vecs_integral_sensip) { 554715f1b00SHong Zhang ierr = TSAdjointComputeDRDYFunction(ts,th->ptime,th->X0,ts->vecs_drdy);CHKERRQ(ierr); 555715f1b00SHong Zhang } 556715f1b00SHong Zhang if (ts->vecs_integral_sensip) { 557715f1b00SHong Zhang ierr = TSAdjointComputeDRDPFunction(ts,th->ptime,th->X0,ts->vecs_drdp);CHKERRQ(ierr); 558715f1b00SHong Zhang for (ncost=0; ncost<ts->numcost; ncost++) { 559*7f79407eSBarry Smith ierr = TSThetaIntegrandDerivative(ts,ts->num_parameters,ts->vecs_drdy[ncost],&ts->vecs_fwdsensipacked[ts->num_initialvalues],ts->vecs_drdp[ncost],th->VecIntegralSensipTemp);CHKERRQ(ierr); 560715f1b00SHong Zhang ierr = VecAXPY(ts->vecs_integral_sensip[ncost],th->time_step*(1.-th->Theta),th->VecIntegralSensipTemp);CHKERRQ(ierr); 561715f1b00SHong Zhang } 562715f1b00SHong Zhang } 563715f1b00SHong Zhang if (ts->vecs_integral_sensi) { 564715f1b00SHong Zhang for (ncost=0; ncost<ts->numcost; ncost++) { 565*7f79407eSBarry Smith ierr = TSThetaIntegrandDerivative(ts,ts->num_initialvalues,ts->vecs_drdy[ncost],ts->vecs_fwdsensipacked,NULL,th->VecIntegralSensiTemp);CHKERRQ(ierr); 566715f1b00SHong Zhang ierr = VecAXPY(ts->vecs_integral_sensi[ncost],th->time_step*(1.-th->Theta),th->VecIntegralSensiTemp);CHKERRQ(ierr); 567715f1b00SHong Zhang } 568715f1b00SHong Zhang } 569715f1b00SHong Zhang } 570715f1b00SHong Zhang 571715f1b00SHong Zhang /* Solve the tangent linear equation for forward sensitivities to parameters */ 572022c081aSHong Zhang for (ntlm=0; ntlm<th->num_tlm; ntlm++) { 573715f1b00SHong Zhang if (th->endpoint) { 574*7f79407eSBarry Smith ierr = KSPSolve(ksp,VecsDeltaFwdSensi[ntlm],ts->vecs_fwdsensipacked[ntlm]);CHKERRQ(ierr); 575715f1b00SHong Zhang } else { 576*7f79407eSBarry Smith ierr = KSPSolve(ksp,VecsDeltaFwdSensi[ntlm],VecsDeltaFwdSensi[ntlm]);CHKERRQ(ierr); 577*7f79407eSBarry Smith ierr = VecAXPY(ts->vecs_fwdsensipacked[ntlm],1.,VecsDeltaFwdSensi[ntlm]);CHKERRQ(ierr); 578715f1b00SHong Zhang } 579715f1b00SHong Zhang } 580715f1b00SHong Zhang /*Evaluate the second stage of integral gradients with the 2-stage method: 581715f1b00SHong Zhang drdy|t_{n+1}*S(t_{n+1}) + drdp|t_{n+1} 582715f1b00SHong Zhang */ 583715f1b00SHong Zhang if (ts->vecs_integral_sensi || ts->vecs_integral_sensip) { 584715f1b00SHong Zhang ierr = TSAdjointComputeDRDYFunction(ts,th->stage_time,th->X,ts->vecs_drdy);CHKERRQ(ierr); 585715f1b00SHong Zhang } 586715f1b00SHong Zhang if (ts->vecs_integral_sensip) { 587715f1b00SHong Zhang ierr = TSAdjointComputeDRDPFunction(ts,th->stage_time,th->X,ts->vecs_drdp);CHKERRQ(ierr); 588715f1b00SHong Zhang for (ncost=0; ncost<ts->numcost; ncost++) { 589*7f79407eSBarry Smith ierr = TSThetaIntegrandDerivative(ts,ts->num_parameters,ts->vecs_drdy[ncost],&ts->vecs_fwdsensipacked[ts->num_initialvalues],ts->vecs_drdp[ncost],th->VecIntegralSensipTemp);CHKERRQ(ierr); 590715f1b00SHong Zhang if (th->endpoint) { 591715f1b00SHong Zhang ierr = VecAXPY(ts->vecs_integral_sensip[ncost],th->time_step*th->Theta,th->VecIntegralSensipTemp);CHKERRQ(ierr); 592715f1b00SHong Zhang } else { 593715f1b00SHong Zhang ierr = VecAXPY(ts->vecs_integral_sensip[ncost],th->time_step,th->VecIntegralSensipTemp);CHKERRQ(ierr); 594715f1b00SHong Zhang } 595715f1b00SHong Zhang } 596715f1b00SHong Zhang } 597715f1b00SHong Zhang if (ts->vecs_integral_sensi) { 598715f1b00SHong Zhang for (ncost=0; ncost<ts->numcost; ncost++) { 599*7f79407eSBarry Smith ierr = TSThetaIntegrandDerivative(ts,ts->num_initialvalues,ts->vecs_drdy[ncost],ts->vecs_fwdsensipacked,NULL,th->VecIntegralSensiTemp);CHKERRQ(ierr); 600715f1b00SHong Zhang if (th->endpoint) { 601715f1b00SHong Zhang ierr = VecAXPY(ts->vecs_integral_sensi[ncost],th->time_step*th->Theta,th->VecIntegralSensiTemp);CHKERRQ(ierr); 602715f1b00SHong Zhang } else { 603715f1b00SHong Zhang ierr = VecAXPY(ts->vecs_integral_sensi[ncost],th->time_step,th->VecIntegralSensiTemp);CHKERRQ(ierr); 604715f1b00SHong Zhang } 605715f1b00SHong Zhang } 606715f1b00SHong Zhang } 607715f1b00SHong Zhang 608715f1b00SHong Zhang if (!th->endpoint) { /* VecsDeltaFwdSensip are the increment for the stage values for the 1-stage method */ 609022c081aSHong Zhang for (ntlm=0; ntlm<th->num_tlm; ntlm++) { 610*7f79407eSBarry Smith ierr = VecAXPY(ts->vecs_fwdsensipacked[ntlm],(1.-th->Theta)/th->Theta,VecsDeltaFwdSensi[ntlm]);CHKERRQ(ierr); 611715f1b00SHong Zhang } 612715f1b00SHong Zhang } 6131566a47fSLisandro Dalcin PetscFunctionReturn(0); 6141566a47fSLisandro Dalcin } 6151566a47fSLisandro Dalcin 616316643e7SJed Brown /*------------------------------------------------------------*/ 617277b19d0SLisandro Dalcin static PetscErrorCode TSReset_Theta(TS ts) 618316643e7SJed Brown { 619316643e7SJed Brown TS_Theta *th = (TS_Theta*)ts->data; 620316643e7SJed Brown PetscErrorCode ierr; 621316643e7SJed Brown 622316643e7SJed Brown PetscFunctionBegin; 6236bf464f9SBarry Smith ierr = VecDestroy(&th->X);CHKERRQ(ierr); 6246bf464f9SBarry Smith ierr = VecDestroy(&th->Xdot);CHKERRQ(ierr); 6253b1890cdSShri Abhyankar ierr = VecDestroy(&th->X0);CHKERRQ(ierr); 626eb284becSJed Brown ierr = VecDestroy(&th->affine);CHKERRQ(ierr); 6271566a47fSLisandro Dalcin 6281566a47fSLisandro Dalcin ierr = VecDestroy(&th->vec_sol_prev);CHKERRQ(ierr); 6291566a47fSLisandro Dalcin ierr = VecDestroy(&th->vec_lte_work);CHKERRQ(ierr); 6301566a47fSLisandro Dalcin 631b1cb36f3SHong Zhang ierr = VecDestroy(&th->VecCostIntegral0);CHKERRQ(ierr); 632715f1b00SHong Zhang if (ts->forward_solve) { 633022c081aSHong Zhang ierr = VecDestroyVecs(th->num_tlm,&th->VecsDeltaFwdSensi);CHKERRQ(ierr); 634022c081aSHong Zhang ierr = VecDestroyVecs(th->num_tlm,&th->VecsFwdSensi0);CHKERRQ(ierr); 635715f1b00SHong Zhang if (ts->vecs_integral_sensi) { 636715f1b00SHong Zhang ierr = VecDestroy(&th->VecIntegralSensiTemp);CHKERRQ(ierr); 6376f92202bSHong Zhang ierr = VecDestroyVecs(ts->numcost,&th->VecsIntegralSensi0);CHKERRQ(ierr); 638715f1b00SHong Zhang } 639715f1b00SHong Zhang if (ts->vecs_integral_sensip) { 640715f1b00SHong Zhang ierr = VecDestroy(&th->VecIntegralSensipTemp);CHKERRQ(ierr); 6416f92202bSHong Zhang ierr = VecDestroyVecs(ts->numcost,&th->VecsIntegralSensip0);CHKERRQ(ierr); 642715f1b00SHong Zhang } 643715f1b00SHong Zhang } 644b5e0532dSHong Zhang ierr = VecDestroyVecs(ts->numcost,&th->VecsDeltaLam);CHKERRQ(ierr); 645b5e0532dSHong Zhang ierr = VecDestroyVecs(ts->numcost,&th->VecsDeltaMu);CHKERRQ(ierr); 646b5e0532dSHong Zhang ierr = VecDestroyVecs(ts->numcost,&th->VecsSensiTemp);CHKERRQ(ierr); 647715f1b00SHong Zhang 648277b19d0SLisandro Dalcin PetscFunctionReturn(0); 649277b19d0SLisandro Dalcin } 650277b19d0SLisandro Dalcin 651277b19d0SLisandro Dalcin static PetscErrorCode TSDestroy_Theta(TS ts) 652277b19d0SLisandro Dalcin { 653277b19d0SLisandro Dalcin PetscErrorCode ierr; 654277b19d0SLisandro Dalcin 655277b19d0SLisandro Dalcin PetscFunctionBegin; 656277b19d0SLisandro Dalcin ierr = TSReset_Theta(ts);CHKERRQ(ierr); 657277b19d0SLisandro Dalcin ierr = PetscFree(ts->data);CHKERRQ(ierr); 658bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)ts,"TSThetaGetTheta_C",NULL);CHKERRQ(ierr); 659bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)ts,"TSThetaSetTheta_C",NULL);CHKERRQ(ierr); 660bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)ts,"TSThetaGetEndpoint_C",NULL);CHKERRQ(ierr); 661bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)ts,"TSThetaSetEndpoint_C",NULL);CHKERRQ(ierr); 662316643e7SJed Brown PetscFunctionReturn(0); 663316643e7SJed Brown } 664316643e7SJed Brown 665316643e7SJed Brown /* 666316643e7SJed Brown This defines the nonlinear equation that is to be solved with SNES 6672b5a38e1SLisandro Dalcin G(U) = F[t0+Theta*dt, U, (U-U0)*shift] = 0 668316643e7SJed Brown */ 6690f5c6efeSJed Brown static PetscErrorCode SNESTSFormFunction_Theta(SNES snes,Vec x,Vec y,TS ts) 670316643e7SJed Brown { 671316643e7SJed Brown TS_Theta *th = (TS_Theta*)ts->data; 672316643e7SJed Brown PetscErrorCode ierr; 6737445fe48SJed Brown Vec X0,Xdot; 6747445fe48SJed Brown DM dm,dmsave; 6751566a47fSLisandro Dalcin PetscReal shift = 1/(th->Theta*ts->time_step); 676316643e7SJed Brown 677316643e7SJed Brown PetscFunctionBegin; 6787445fe48SJed Brown ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 6795a3a76d0SJed Brown /* When using the endpoint variant, this is actually 1/Theta * Xdot */ 6807445fe48SJed Brown ierr = TSThetaGetX0AndXdot(ts,dm,&X0,&Xdot);CHKERRQ(ierr); 681b296d7d5SJed Brown ierr = VecAXPBYPCZ(Xdot,-shift,shift,0,X0,x);CHKERRQ(ierr); 6827445fe48SJed Brown 6837445fe48SJed Brown /* DM monkey-business allows user code to call TSGetDM() inside of functions evaluated on levels of FAS */ 6847445fe48SJed Brown dmsave = ts->dm; 6857445fe48SJed Brown ts->dm = dm; 6867445fe48SJed Brown ierr = TSComputeIFunction(ts,th->stage_time,x,Xdot,y,PETSC_FALSE);CHKERRQ(ierr); 6877445fe48SJed Brown ts->dm = dmsave; 6880d0b770aSPeter Brune ierr = TSThetaRestoreX0AndXdot(ts,dm,&X0,&Xdot);CHKERRQ(ierr); 689316643e7SJed Brown PetscFunctionReturn(0); 690316643e7SJed Brown } 691316643e7SJed Brown 692d1e9a80fSBarry Smith static PetscErrorCode SNESTSFormJacobian_Theta(SNES snes,Vec x,Mat A,Mat B,TS ts) 693316643e7SJed Brown { 694316643e7SJed Brown TS_Theta *th = (TS_Theta*)ts->data; 695316643e7SJed Brown PetscErrorCode ierr; 6967445fe48SJed Brown Vec Xdot; 6977445fe48SJed Brown DM dm,dmsave; 6981566a47fSLisandro Dalcin PetscReal shift = 1/(th->Theta*ts->time_step); 699316643e7SJed Brown 700316643e7SJed Brown PetscFunctionBegin; 7017445fe48SJed Brown ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 702be5899b3SLisandro Dalcin /* Xdot has already been computed in SNESTSFormFunction_Theta (SNES guarantees this) */ 7030298fd71SBarry Smith ierr = TSThetaGetX0AndXdot(ts,dm,NULL,&Xdot);CHKERRQ(ierr); 7047445fe48SJed Brown 7057445fe48SJed Brown dmsave = ts->dm; 7067445fe48SJed Brown ts->dm = dm; 707d1e9a80fSBarry Smith ierr = TSComputeIJacobian(ts,th->stage_time,x,Xdot,shift,A,B,PETSC_FALSE);CHKERRQ(ierr); 7087445fe48SJed Brown ts->dm = dmsave; 7090298fd71SBarry Smith ierr = TSThetaRestoreX0AndXdot(ts,dm,NULL,&Xdot);CHKERRQ(ierr); 710316643e7SJed Brown PetscFunctionReturn(0); 711316643e7SJed Brown } 712316643e7SJed Brown 713715f1b00SHong Zhang static PetscErrorCode TSForwardSetUp_Theta(TS ts) 714715f1b00SHong Zhang { 715715f1b00SHong Zhang TS_Theta *th = (TS_Theta*)ts->data; 716715f1b00SHong Zhang PetscErrorCode ierr; 717715f1b00SHong Zhang 718715f1b00SHong Zhang PetscFunctionBegin; 719022c081aSHong Zhang /* combine sensitivities to parameters and sensitivities to initial values into one array */ 720022c081aSHong Zhang th->num_tlm = ts->num_parameters + ts->num_initialvalues; 721022c081aSHong Zhang ierr = VecDuplicateVecs(ts->vecs_fwdsensipacked[0],th->num_tlm,&th->VecsDeltaFwdSensi);CHKERRQ(ierr); 722715f1b00SHong Zhang if (ts->vecs_integral_sensi) { 723715f1b00SHong Zhang ierr = VecDuplicate(ts->vecs_integral_sensi[0],&th->VecIntegralSensiTemp);CHKERRQ(ierr); 724715f1b00SHong Zhang } 725715f1b00SHong Zhang if (ts->vecs_integral_sensip) { 726715f1b00SHong Zhang ierr = VecDuplicate(ts->vecs_integral_sensip[0],&th->VecIntegralSensipTemp);CHKERRQ(ierr); 727715f1b00SHong Zhang } 7286f92202bSHong Zhang /* backup sensitivity results for roll-backs */ 729022c081aSHong Zhang ierr = VecDuplicateVecs(ts->vecs_fwdsensipacked[0],th->num_tlm,&th->VecsFwdSensi0);CHKERRQ(ierr); 7306f92202bSHong Zhang if (ts->vecs_integral_sensi) { 7316f92202bSHong Zhang ierr = VecDuplicateVecs(ts->vecs_integral_sensi[0],ts->numcost,&th->VecsIntegralSensi0);CHKERRQ(ierr); 7326f92202bSHong Zhang } 7336f92202bSHong Zhang if (ts->vecs_integral_sensip) { 7346f92202bSHong Zhang ierr = VecDuplicateVecs(ts->vecs_integral_sensip[0],ts->numcost,&th->VecsIntegralSensip0);CHKERRQ(ierr); 7356f92202bSHong Zhang } 736715f1b00SHong Zhang PetscFunctionReturn(0); 737715f1b00SHong Zhang } 738715f1b00SHong Zhang 739316643e7SJed Brown static PetscErrorCode TSSetUp_Theta(TS ts) 740316643e7SJed Brown { 741316643e7SJed Brown TS_Theta *th = (TS_Theta*)ts->data; 7422ffb9264SLisandro Dalcin PetscBool match; 743316643e7SJed Brown PetscErrorCode ierr; 744316643e7SJed Brown 745316643e7SJed Brown PetscFunctionBegin; 746b1cb36f3SHong Zhang if (!th->VecCostIntegral0 && ts->vec_costintegral && ts->costintegralfwd) { /* back up cost integral */ 747b1cb36f3SHong Zhang ierr = VecDuplicate(ts->vec_costintegral,&th->VecCostIntegral0);CHKERRQ(ierr); 748b1cb36f3SHong Zhang } 74939d13666SHong Zhang if (!th->X) { 750316643e7SJed Brown ierr = VecDuplicate(ts->vec_sol,&th->X);CHKERRQ(ierr); 75139d13666SHong Zhang } 75239d13666SHong Zhang if (!th->Xdot) { 753316643e7SJed Brown ierr = VecDuplicate(ts->vec_sol,&th->Xdot);CHKERRQ(ierr); 75439d13666SHong Zhang } 75539d13666SHong Zhang if (!th->X0) { 7563b1890cdSShri Abhyankar ierr = VecDuplicate(ts->vec_sol,&th->X0);CHKERRQ(ierr); 75739d13666SHong Zhang } 7581566a47fSLisandro Dalcin if (th->endpoint) { 7591566a47fSLisandro Dalcin ierr = VecDuplicate(ts->vec_sol,&th->affine);CHKERRQ(ierr); 7607445fe48SJed Brown } 7613b1890cdSShri Abhyankar 7621566a47fSLisandro Dalcin th->order = (th->Theta == 0.5) ? 2 : 1; 7631566a47fSLisandro Dalcin 7641566a47fSLisandro Dalcin ierr = TSGetDM(ts,&ts->dm);CHKERRQ(ierr); 7651566a47fSLisandro Dalcin ierr = DMCoarsenHookAdd(ts->dm,DMCoarsenHook_TSTheta,DMRestrictHook_TSTheta,ts);CHKERRQ(ierr); 7661566a47fSLisandro Dalcin ierr = DMSubDomainHookAdd(ts->dm,DMSubDomainHook_TSTheta,DMSubDomainRestrictHook_TSTheta,ts);CHKERRQ(ierr); 7671566a47fSLisandro Dalcin 7681566a47fSLisandro Dalcin ierr = TSGetAdapt(ts,&ts->adapt);CHKERRQ(ierr); 7691566a47fSLisandro Dalcin ierr = TSAdaptCandidatesClear(ts->adapt);CHKERRQ(ierr); 7702ffb9264SLisandro Dalcin ierr = PetscObjectTypeCompare((PetscObject)ts->adapt,TSADAPTNONE,&match);CHKERRQ(ierr); 7712ffb9264SLisandro Dalcin if (!match) { 7721566a47fSLisandro Dalcin ierr = VecDuplicate(ts->vec_sol,&th->vec_sol_prev);CHKERRQ(ierr); 7731566a47fSLisandro Dalcin ierr = VecDuplicate(ts->vec_sol,&th->vec_lte_work);CHKERRQ(ierr); 7743b1890cdSShri Abhyankar } 7751566a47fSLisandro Dalcin ierr = TSGetSNES(ts,&ts->snes);CHKERRQ(ierr); 776b4dd3bf9SBarry Smith PetscFunctionReturn(0); 777b4dd3bf9SBarry Smith } 7780c7376e5SHong Zhang 779b4dd3bf9SBarry Smith /*------------------------------------------------------------*/ 780b4dd3bf9SBarry Smith 781b4dd3bf9SBarry Smith static PetscErrorCode TSAdjointSetUp_Theta(TS ts) 782b4dd3bf9SBarry Smith { 783b4dd3bf9SBarry Smith TS_Theta *th = (TS_Theta*)ts->data; 784b4dd3bf9SBarry Smith PetscErrorCode ierr; 785b4dd3bf9SBarry Smith 786b4dd3bf9SBarry Smith PetscFunctionBegin; 787b5e0532dSHong Zhang ierr = VecDuplicateVecs(ts->vecs_sensi[0],ts->numcost,&th->VecsDeltaLam);CHKERRQ(ierr); 7882ca6e920SHong Zhang if(ts->vecs_sensip) { 789b5e0532dSHong Zhang ierr = VecDuplicateVecs(ts->vecs_sensip[0],ts->numcost,&th->VecsDeltaMu);CHKERRQ(ierr); 7902ca6e920SHong Zhang } 791b5e0532dSHong Zhang ierr = VecDuplicateVecs(ts->vecs_sensi[0],ts->numcost,&th->VecsSensiTemp);CHKERRQ(ierr); 792316643e7SJed Brown PetscFunctionReturn(0); 793316643e7SJed Brown } 794316643e7SJed Brown 7954416b707SBarry Smith static PetscErrorCode TSSetFromOptions_Theta(PetscOptionItems *PetscOptionsObject,TS ts) 796316643e7SJed Brown { 797316643e7SJed Brown TS_Theta *th = (TS_Theta*)ts->data; 798316643e7SJed Brown PetscErrorCode ierr; 799316643e7SJed Brown 800316643e7SJed Brown PetscFunctionBegin; 801e55864a3SBarry Smith ierr = PetscOptionsHead(PetscOptionsObject,"Theta ODE solver options");CHKERRQ(ierr); 802316643e7SJed Brown { 8030298fd71SBarry Smith ierr = PetscOptionsReal("-ts_theta_theta","Location of stage (0<Theta<=1)","TSThetaSetTheta",th->Theta,&th->Theta,NULL);CHKERRQ(ierr); 8040298fd71SBarry Smith ierr = PetscOptionsBool("-ts_theta_endpoint","Use the endpoint instead of midpoint form of the Theta method","TSThetaSetEndpoint",th->endpoint,&th->endpoint,NULL);CHKERRQ(ierr); 80503842d09SLisandro Dalcin ierr = PetscOptionsBool("-ts_theta_initial_guess_extrapolate","Extrapolate stage initial guess from previous solution (sometimes unstable)","TSThetaSetExtrapolate",th->extrapolate,&th->extrapolate,NULL);CHKERRQ(ierr); 806316643e7SJed Brown } 807316643e7SJed Brown ierr = PetscOptionsTail();CHKERRQ(ierr); 808316643e7SJed Brown PetscFunctionReturn(0); 809316643e7SJed Brown } 810316643e7SJed Brown 811316643e7SJed Brown static PetscErrorCode TSView_Theta(TS ts,PetscViewer viewer) 812316643e7SJed Brown { 813316643e7SJed Brown TS_Theta *th = (TS_Theta*)ts->data; 814ace3abfcSBarry Smith PetscBool iascii; 815316643e7SJed Brown PetscErrorCode ierr; 816316643e7SJed Brown 817316643e7SJed Brown PetscFunctionBegin; 818251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 819316643e7SJed Brown if (iascii) { 8207c8652ddSBarry Smith ierr = PetscViewerASCIIPrintf(viewer," Theta=%g\n",(double)th->Theta);CHKERRQ(ierr); 821ace68cafSJed Brown ierr = PetscViewerASCIIPrintf(viewer," Extrapolation=%s\n",th->extrapolate ? "yes" : "no");CHKERRQ(ierr); 822316643e7SJed Brown } 823316643e7SJed Brown PetscFunctionReturn(0); 824316643e7SJed Brown } 825316643e7SJed Brown 826560360afSLisandro Dalcin static PetscErrorCode TSThetaGetTheta_Theta(TS ts,PetscReal *theta) 8270de4c49aSJed Brown { 8280de4c49aSJed Brown TS_Theta *th = (TS_Theta*)ts->data; 8290de4c49aSJed Brown 8300de4c49aSJed Brown PetscFunctionBegin; 8310de4c49aSJed Brown *theta = th->Theta; 8320de4c49aSJed Brown PetscFunctionReturn(0); 8330de4c49aSJed Brown } 8340de4c49aSJed Brown 835560360afSLisandro Dalcin static PetscErrorCode TSThetaSetTheta_Theta(TS ts,PetscReal theta) 8360de4c49aSJed Brown { 8370de4c49aSJed Brown TS_Theta *th = (TS_Theta*)ts->data; 8380de4c49aSJed Brown 8390de4c49aSJed Brown PetscFunctionBegin; 8407c8652ddSBarry Smith if (theta <= 0 || 1 < theta) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Theta %g not in range (0,1]",(double)theta); 8410de4c49aSJed Brown th->Theta = theta; 8421566a47fSLisandro Dalcin th->order = (th->Theta == 0.5) ? 2 : 1; 8430de4c49aSJed Brown PetscFunctionReturn(0); 8440de4c49aSJed Brown } 845eb284becSJed Brown 846560360afSLisandro Dalcin static PetscErrorCode TSThetaGetEndpoint_Theta(TS ts,PetscBool *endpoint) 84726f2ff8fSLisandro Dalcin { 84826f2ff8fSLisandro Dalcin TS_Theta *th = (TS_Theta*)ts->data; 84926f2ff8fSLisandro Dalcin 85026f2ff8fSLisandro Dalcin PetscFunctionBegin; 85126f2ff8fSLisandro Dalcin *endpoint = th->endpoint; 85226f2ff8fSLisandro Dalcin PetscFunctionReturn(0); 85326f2ff8fSLisandro Dalcin } 85426f2ff8fSLisandro Dalcin 855560360afSLisandro Dalcin static PetscErrorCode TSThetaSetEndpoint_Theta(TS ts,PetscBool flg) 856eb284becSJed Brown { 857eb284becSJed Brown TS_Theta *th = (TS_Theta*)ts->data; 858eb284becSJed Brown 859eb284becSJed Brown PetscFunctionBegin; 860eb284becSJed Brown th->endpoint = flg; 861eb284becSJed Brown PetscFunctionReturn(0); 862eb284becSJed Brown } 8630de4c49aSJed Brown 864f9c1d6abSBarry Smith #if defined(PETSC_HAVE_COMPLEX) 865f9c1d6abSBarry Smith static PetscErrorCode TSComputeLinearStability_Theta(TS ts,PetscReal xr,PetscReal xi,PetscReal *yr,PetscReal *yi) 866f9c1d6abSBarry Smith { 867f9c1d6abSBarry Smith PetscComplex z = xr + xi*PETSC_i,f; 868f9c1d6abSBarry Smith TS_Theta *th = (TS_Theta*)ts->data; 8693fd8ae06SJed Brown const PetscReal one = 1.0; 870f9c1d6abSBarry Smith 871f9c1d6abSBarry Smith PetscFunctionBegin; 8723fd8ae06SJed Brown f = (one + (one - th->Theta)*z)/(one - th->Theta*z); 873f9c1d6abSBarry Smith *yr = PetscRealPartComplex(f); 874f9c1d6abSBarry Smith *yi = PetscImaginaryPartComplex(f); 875f9c1d6abSBarry Smith PetscFunctionReturn(0); 876f9c1d6abSBarry Smith } 877f9c1d6abSBarry Smith #endif 878f9c1d6abSBarry Smith 87942682096SHong Zhang static PetscErrorCode TSGetStages_Theta(TS ts,PetscInt *ns,Vec **Y) 88042682096SHong Zhang { 88142682096SHong Zhang TS_Theta *th = (TS_Theta*)ts->data; 88242682096SHong Zhang 88342682096SHong Zhang PetscFunctionBegin; 8841566a47fSLisandro Dalcin if (ns) *ns = 1; 8851566a47fSLisandro Dalcin if (Y) *Y = th->endpoint ? &(th->X0) : &(th->X); 88642682096SHong Zhang PetscFunctionReturn(0); 88742682096SHong Zhang } 888f9c1d6abSBarry Smith 889316643e7SJed Brown /* ------------------------------------------------------------ */ 890316643e7SJed Brown /*MC 89196f5712cSJed Brown TSTHETA - DAE solver using the implicit Theta method 892316643e7SJed Brown 893316643e7SJed Brown Level: beginner 894316643e7SJed Brown 8954eb428fdSBarry Smith Options Database: 896c82ed962SBarry Smith + -ts_theta_theta <Theta> - Location of stage (0<Theta<=1) 897c82ed962SBarry Smith . -ts_theta_endpoint <flag> - Use the endpoint (like Crank-Nicholson) instead of midpoint form of the Theta method 89803842d09SLisandro Dalcin - -ts_theta_initial_guess_extrapolate <flg> - Extrapolate stage initial guess from previous solution (sometimes unstable) 8994eb428fdSBarry Smith 900eb284becSJed Brown Notes: 9010c3ba866SJed Brown $ -ts_type theta -ts_theta_theta 1.0 corresponds to backward Euler (TSBEULER) 9020c3ba866SJed Brown $ -ts_type theta -ts_theta_theta 0.5 corresponds to the implicit midpoint rule 9034eb428fdSBarry Smith $ -ts_type theta -ts_theta_theta 0.5 -ts_theta_endpoint corresponds to Crank-Nicholson (TSCN) 9044eb428fdSBarry Smith 905eb284becSJed Brown This method can be applied to DAE. 906eb284becSJed Brown 907eb284becSJed Brown This method is cast as a 1-stage implicit Runge-Kutta method. 908eb284becSJed Brown 909eb284becSJed Brown .vb 910eb284becSJed Brown Theta | Theta 911eb284becSJed Brown ------------- 912eb284becSJed Brown | 1 913eb284becSJed Brown .ve 914eb284becSJed Brown 915eb284becSJed Brown For the default Theta=0.5, this is also known as the implicit midpoint rule. 916eb284becSJed Brown 917eb284becSJed Brown When the endpoint variant is chosen, the method becomes a 2-stage method with first stage explicit: 918eb284becSJed Brown 919eb284becSJed Brown .vb 920eb284becSJed Brown 0 | 0 0 921eb284becSJed Brown 1 | 1-Theta Theta 922eb284becSJed Brown ------------------- 923eb284becSJed Brown | 1-Theta Theta 924eb284becSJed Brown .ve 925eb284becSJed Brown 926eb284becSJed Brown For the default Theta=0.5, this is the trapezoid rule (also known as Crank-Nicolson, see TSCN). 927eb284becSJed Brown 928eb284becSJed Brown To apply a diagonally implicit RK method to DAE, the stage formula 929eb284becSJed Brown 930eb284becSJed Brown $ Y_i = X + h sum_j a_ij Y'_j 931eb284becSJed Brown 9324eb428fdSBarry Smith is interpreted as a formula for Y'_i in terms of Y_i and known values (Y'_j, j<i) 933eb284becSJed Brown 934eb284becSJed Brown .seealso: TSCreate(), TS, TSSetType(), TSCN, TSBEULER, TSThetaSetTheta(), TSThetaSetEndpoint() 935316643e7SJed Brown 936316643e7SJed Brown M*/ 9378cc058d9SJed Brown PETSC_EXTERN PetscErrorCode TSCreate_Theta(TS ts) 938316643e7SJed Brown { 939316643e7SJed Brown TS_Theta *th; 940316643e7SJed Brown PetscErrorCode ierr; 941316643e7SJed Brown 942316643e7SJed Brown PetscFunctionBegin; 943277b19d0SLisandro Dalcin ts->ops->reset = TSReset_Theta; 944316643e7SJed Brown ts->ops->destroy = TSDestroy_Theta; 945316643e7SJed Brown ts->ops->view = TSView_Theta; 946316643e7SJed Brown ts->ops->setup = TSSetUp_Theta; 94742f2b339SBarry Smith ts->ops->adjointsetup = TSAdjointSetUp_Theta; 948316643e7SJed Brown ts->ops->step = TSStep_Theta; 949cd652676SJed Brown ts->ops->interpolate = TSInterpolate_Theta; 9501566a47fSLisandro Dalcin ts->ops->evaluatewlte = TSEvaluateWLTE_Theta; 95124655328SShri ts->ops->rollback = TSRollBack_Theta; 952316643e7SJed Brown ts->ops->setfromoptions = TSSetFromOptions_Theta; 9530f5c6efeSJed Brown ts->ops->snesfunction = SNESTSFormFunction_Theta; 9540f5c6efeSJed Brown ts->ops->snesjacobian = SNESTSFormJacobian_Theta; 955f9c1d6abSBarry Smith #if defined(PETSC_HAVE_COMPLEX) 956f9c1d6abSBarry Smith ts->ops->linearstability = TSComputeLinearStability_Theta; 957f9c1d6abSBarry Smith #endif 95842682096SHong Zhang ts->ops->getstages = TSGetStages_Theta; 95942f2b339SBarry Smith ts->ops->adjointstep = TSAdjointStep_Theta; 960b1cb36f3SHong Zhang ts->ops->adjointintegral = TSAdjointCostIntegral_Theta; 961b1cb36f3SHong Zhang ts->ops->forwardintegral = TSForwardCostIntegral_Theta; 9622ffb9264SLisandro Dalcin ts->default_adapt_type = TSADAPTNONE; 963715f1b00SHong Zhang ts->ops->forwardsetup = TSForwardSetUp_Theta; 964715f1b00SHong Zhang ts->ops->forwardstep = TSForwardStep_Theta; 965316643e7SJed Brown 966efd4aadfSBarry Smith ts->usessnes = PETSC_TRUE; 967efd4aadfSBarry Smith 968b00a9115SJed Brown ierr = PetscNewLog(ts,&th);CHKERRQ(ierr); 969316643e7SJed Brown ts->data = (void*)th; 970316643e7SJed Brown 971715f1b00SHong Zhang th->VecsDeltaLam = NULL; 972715f1b00SHong Zhang th->VecsDeltaMu = NULL; 973715f1b00SHong Zhang th->VecsSensiTemp = NULL; 974715f1b00SHong Zhang 9756f700aefSJed Brown th->extrapolate = PETSC_FALSE; 976316643e7SJed Brown th->Theta = 0.5; 9771566a47fSLisandro Dalcin th->order = 2; 978bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)ts,"TSThetaGetTheta_C",TSThetaGetTheta_Theta);CHKERRQ(ierr); 979bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)ts,"TSThetaSetTheta_C",TSThetaSetTheta_Theta);CHKERRQ(ierr); 980bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)ts,"TSThetaGetEndpoint_C",TSThetaGetEndpoint_Theta);CHKERRQ(ierr); 981bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)ts,"TSThetaSetEndpoint_C",TSThetaSetEndpoint_Theta);CHKERRQ(ierr); 982316643e7SJed Brown PetscFunctionReturn(0); 983316643e7SJed Brown } 9840de4c49aSJed Brown 9850de4c49aSJed Brown /*@ 9860de4c49aSJed Brown TSThetaGetTheta - Get the abscissa of the stage in (0,1]. 9870de4c49aSJed Brown 9880de4c49aSJed Brown Not Collective 9890de4c49aSJed Brown 9900de4c49aSJed Brown Input Parameter: 9910de4c49aSJed Brown . ts - timestepping context 9920de4c49aSJed Brown 9930de4c49aSJed Brown Output Parameter: 9940de4c49aSJed Brown . theta - stage abscissa 9950de4c49aSJed Brown 9960de4c49aSJed Brown Note: 9970de4c49aSJed Brown Use of this function is normally only required to hack TSTHETA to use a modified integration scheme. 9980de4c49aSJed Brown 9990de4c49aSJed Brown Level: Advanced 10000de4c49aSJed Brown 10010de4c49aSJed Brown .seealso: TSThetaSetTheta() 10020de4c49aSJed Brown @*/ 10037087cfbeSBarry Smith PetscErrorCode TSThetaGetTheta(TS ts,PetscReal *theta) 10040de4c49aSJed Brown { 10054ac538c5SBarry Smith PetscErrorCode ierr; 10060de4c49aSJed Brown 10070de4c49aSJed Brown PetscFunctionBegin; 1008afb20b64SJed Brown PetscValidHeaderSpecific(ts,TS_CLASSID,1); 10090de4c49aSJed Brown PetscValidPointer(theta,2); 10104ac538c5SBarry Smith ierr = PetscUseMethod(ts,"TSThetaGetTheta_C",(TS,PetscReal*),(ts,theta));CHKERRQ(ierr); 10110de4c49aSJed Brown PetscFunctionReturn(0); 10120de4c49aSJed Brown } 10130de4c49aSJed Brown 10140de4c49aSJed Brown /*@ 10150de4c49aSJed Brown TSThetaSetTheta - Set the abscissa of the stage in (0,1]. 10160de4c49aSJed Brown 10170de4c49aSJed Brown Not Collective 10180de4c49aSJed Brown 10190de4c49aSJed Brown Input Parameter: 10200de4c49aSJed Brown + ts - timestepping context 10210de4c49aSJed Brown - theta - stage abscissa 10220de4c49aSJed Brown 10230de4c49aSJed Brown Options Database: 10240de4c49aSJed Brown . -ts_theta_theta <theta> 10250de4c49aSJed Brown 10260de4c49aSJed Brown Level: Intermediate 10270de4c49aSJed Brown 10280de4c49aSJed Brown .seealso: TSThetaGetTheta() 10290de4c49aSJed Brown @*/ 10307087cfbeSBarry Smith PetscErrorCode TSThetaSetTheta(TS ts,PetscReal theta) 10310de4c49aSJed Brown { 10324ac538c5SBarry Smith PetscErrorCode ierr; 10330de4c49aSJed Brown 10340de4c49aSJed Brown PetscFunctionBegin; 1035afb20b64SJed Brown PetscValidHeaderSpecific(ts,TS_CLASSID,1); 10364ac538c5SBarry Smith ierr = PetscTryMethod(ts,"TSThetaSetTheta_C",(TS,PetscReal),(ts,theta));CHKERRQ(ierr); 10370de4c49aSJed Brown PetscFunctionReturn(0); 10380de4c49aSJed Brown } 1039f33bbcb6SJed Brown 104026f2ff8fSLisandro Dalcin /*@ 104126f2ff8fSLisandro Dalcin TSThetaGetEndpoint - Gets whether to use the endpoint variant of the method (e.g. trapezoid/Crank-Nicolson instead of midpoint rule). 104226f2ff8fSLisandro Dalcin 104326f2ff8fSLisandro Dalcin Not Collective 104426f2ff8fSLisandro Dalcin 104526f2ff8fSLisandro Dalcin Input Parameter: 104626f2ff8fSLisandro Dalcin . ts - timestepping context 104726f2ff8fSLisandro Dalcin 104826f2ff8fSLisandro Dalcin Output Parameter: 104926f2ff8fSLisandro Dalcin . endpoint - PETSC_TRUE when using the endpoint variant 105026f2ff8fSLisandro Dalcin 105126f2ff8fSLisandro Dalcin Level: Advanced 105226f2ff8fSLisandro Dalcin 105326f2ff8fSLisandro Dalcin .seealso: TSThetaSetEndpoint(), TSTHETA, TSCN 105426f2ff8fSLisandro Dalcin @*/ 105526f2ff8fSLisandro Dalcin PetscErrorCode TSThetaGetEndpoint(TS ts,PetscBool *endpoint) 105626f2ff8fSLisandro Dalcin { 105726f2ff8fSLisandro Dalcin PetscErrorCode ierr; 105826f2ff8fSLisandro Dalcin 105926f2ff8fSLisandro Dalcin PetscFunctionBegin; 106026f2ff8fSLisandro Dalcin PetscValidHeaderSpecific(ts,TS_CLASSID,1); 106126f2ff8fSLisandro Dalcin PetscValidPointer(endpoint,2); 1062163d334eSBarry Smith ierr = PetscUseMethod(ts,"TSThetaGetEndpoint_C",(TS,PetscBool*),(ts,endpoint));CHKERRQ(ierr); 106326f2ff8fSLisandro Dalcin PetscFunctionReturn(0); 106426f2ff8fSLisandro Dalcin } 106526f2ff8fSLisandro Dalcin 1066eb284becSJed Brown /*@ 1067eb284becSJed Brown TSThetaSetEndpoint - Sets whether to use the endpoint variant of the method (e.g. trapezoid/Crank-Nicolson instead of midpoint rule). 1068eb284becSJed Brown 1069eb284becSJed Brown Not Collective 1070eb284becSJed Brown 1071eb284becSJed Brown Input Parameter: 1072eb284becSJed Brown + ts - timestepping context 1073eb284becSJed Brown - flg - PETSC_TRUE to use the endpoint variant 1074eb284becSJed Brown 1075eb284becSJed Brown Options Database: 1076eb284becSJed Brown . -ts_theta_endpoint <flg> 1077eb284becSJed Brown 1078eb284becSJed Brown Level: Intermediate 1079eb284becSJed Brown 1080eb284becSJed Brown .seealso: TSTHETA, TSCN 1081eb284becSJed Brown @*/ 1082eb284becSJed Brown PetscErrorCode TSThetaSetEndpoint(TS ts,PetscBool flg) 1083eb284becSJed Brown { 1084eb284becSJed Brown PetscErrorCode ierr; 1085eb284becSJed Brown 1086eb284becSJed Brown PetscFunctionBegin; 1087eb284becSJed Brown PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1088eb284becSJed Brown ierr = PetscTryMethod(ts,"TSThetaSetEndpoint_C",(TS,PetscBool),(ts,flg));CHKERRQ(ierr); 1089eb284becSJed Brown PetscFunctionReturn(0); 1090eb284becSJed Brown } 1091eb284becSJed Brown 1092f33bbcb6SJed Brown /* 1093f33bbcb6SJed Brown * TSBEULER and TSCN are straightforward specializations of TSTHETA. 1094f33bbcb6SJed Brown * The creation functions for these specializations are below. 1095f33bbcb6SJed Brown */ 1096f33bbcb6SJed Brown 10971566a47fSLisandro Dalcin static PetscErrorCode TSSetUp_BEuler(TS ts) 10981566a47fSLisandro Dalcin { 10991566a47fSLisandro Dalcin TS_Theta *th = (TS_Theta*)ts->data; 11001566a47fSLisandro Dalcin PetscErrorCode ierr; 11011566a47fSLisandro Dalcin 11021566a47fSLisandro Dalcin PetscFunctionBegin; 11031566a47fSLisandro Dalcin if (th->Theta != 1.0) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_OPT_OVERWRITE,"Can not change the default value (1) of theta when using backward Euler\n"); 11041566a47fSLisandro Dalcin if (th->endpoint) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_OPT_OVERWRITE,"Can not change to the endpoint form of the Theta methods when using backward Euler\n"); 11051566a47fSLisandro Dalcin ierr = TSSetUp_Theta(ts);CHKERRQ(ierr); 11061566a47fSLisandro Dalcin PetscFunctionReturn(0); 11071566a47fSLisandro Dalcin } 11081566a47fSLisandro Dalcin 1109f33bbcb6SJed Brown static PetscErrorCode TSView_BEuler(TS ts,PetscViewer viewer) 1110f33bbcb6SJed Brown { 1111f33bbcb6SJed Brown PetscFunctionBegin; 1112f33bbcb6SJed Brown PetscFunctionReturn(0); 1113f33bbcb6SJed Brown } 1114f33bbcb6SJed Brown 1115f33bbcb6SJed Brown /*MC 1116f33bbcb6SJed Brown TSBEULER - ODE solver using the implicit backward Euler method 1117f33bbcb6SJed Brown 1118f33bbcb6SJed Brown Level: beginner 1119f33bbcb6SJed Brown 11204eb428fdSBarry Smith Notes: 1121c7eb6c99SShri Abhyankar TSBEULER is equivalent to TSTHETA with Theta=1.0 11224eb428fdSBarry Smith 11231566a47fSLisandro Dalcin $ -ts_type theta -ts_theta_theta 1.0 11244eb428fdSBarry Smith 1125f33bbcb6SJed Brown .seealso: TSCreate(), TS, TSSetType(), TSEULER, TSCN, TSTHETA 1126f33bbcb6SJed Brown 1127f33bbcb6SJed Brown M*/ 11288cc058d9SJed Brown PETSC_EXTERN PetscErrorCode TSCreate_BEuler(TS ts) 1129f33bbcb6SJed Brown { 1130f33bbcb6SJed Brown PetscErrorCode ierr; 1131f33bbcb6SJed Brown 1132f33bbcb6SJed Brown PetscFunctionBegin; 1133f33bbcb6SJed Brown ierr = TSCreate_Theta(ts);CHKERRQ(ierr); 1134f33bbcb6SJed Brown ierr = TSThetaSetTheta(ts,1.0);CHKERRQ(ierr); 11351566a47fSLisandro Dalcin ierr = TSThetaSetEndpoint(ts,PETSC_FALSE);CHKERRQ(ierr); 11360c7376e5SHong Zhang ts->ops->setup = TSSetUp_BEuler; 1137f33bbcb6SJed Brown ts->ops->view = TSView_BEuler; 1138f33bbcb6SJed Brown PetscFunctionReturn(0); 1139f33bbcb6SJed Brown } 1140f33bbcb6SJed Brown 11411566a47fSLisandro Dalcin static PetscErrorCode TSSetUp_CN(TS ts) 11421566a47fSLisandro Dalcin { 11431566a47fSLisandro Dalcin TS_Theta *th = (TS_Theta*)ts->data; 11441566a47fSLisandro Dalcin PetscErrorCode ierr; 11451566a47fSLisandro Dalcin 11461566a47fSLisandro Dalcin PetscFunctionBegin; 11471566a47fSLisandro Dalcin if (th->Theta != 0.5) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_OPT_OVERWRITE,"Can not change the default value (0.5) of theta when using Crank-Nicolson\n"); 11481566a47fSLisandro Dalcin if (!th->endpoint) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_OPT_OVERWRITE,"Can not change to the midpoint form of the Theta methods when using Crank-Nicolson\n"); 11491566a47fSLisandro Dalcin ierr = TSSetUp_Theta(ts);CHKERRQ(ierr); 11501566a47fSLisandro Dalcin PetscFunctionReturn(0); 11511566a47fSLisandro Dalcin } 11521566a47fSLisandro Dalcin 1153f33bbcb6SJed Brown static PetscErrorCode TSView_CN(TS ts,PetscViewer viewer) 1154f33bbcb6SJed Brown { 1155f33bbcb6SJed Brown PetscFunctionBegin; 1156f33bbcb6SJed Brown PetscFunctionReturn(0); 1157f33bbcb6SJed Brown } 1158f33bbcb6SJed Brown 1159f33bbcb6SJed Brown /*MC 1160f33bbcb6SJed Brown TSCN - ODE solver using the implicit Crank-Nicolson method. 1161f33bbcb6SJed Brown 1162f33bbcb6SJed Brown Level: beginner 1163f33bbcb6SJed Brown 1164f33bbcb6SJed Brown Notes: 11657cf5af47SJed Brown TSCN is equivalent to TSTHETA with Theta=0.5 and the "endpoint" option set. I.e. 11667cf5af47SJed Brown 11677cf5af47SJed Brown $ -ts_type theta -ts_theta_theta 0.5 -ts_theta_endpoint 1168f33bbcb6SJed Brown 1169f33bbcb6SJed Brown .seealso: TSCreate(), TS, TSSetType(), TSBEULER, TSTHETA 1170f33bbcb6SJed Brown 1171f33bbcb6SJed Brown M*/ 11728cc058d9SJed Brown PETSC_EXTERN PetscErrorCode TSCreate_CN(TS ts) 1173f33bbcb6SJed Brown { 1174f33bbcb6SJed Brown PetscErrorCode ierr; 1175f33bbcb6SJed Brown 1176f33bbcb6SJed Brown PetscFunctionBegin; 1177f33bbcb6SJed Brown ierr = TSCreate_Theta(ts);CHKERRQ(ierr); 1178f33bbcb6SJed Brown ierr = TSThetaSetTheta(ts,0.5);CHKERRQ(ierr); 1179eb284becSJed Brown ierr = TSThetaSetEndpoint(ts,PETSC_TRUE);CHKERRQ(ierr); 11800c7376e5SHong Zhang ts->ops->setup = TSSetUp_CN; 1181f33bbcb6SJed Brown ts->ops->view = TSView_CN; 1182f33bbcb6SJed Brown PetscFunctionReturn(0); 1183f33bbcb6SJed Brown } 1184