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; 12*cc4f23bcSHong Zhang Vec Stages[2]; /* Storage for stage solutions */ 13*cc4f23bcSHong 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 */ 30*cc4f23bcSHong 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 PetscErrorCode ierr; 497445fe48SJed Brown 507445fe48SJed Brown PetscFunctionBegin; 517445fe48SJed Brown if (X0) { 527445fe48SJed Brown if (dm && dm != ts->dm) { 530d0b770aSPeter Brune ierr = DMGetNamedGlobalVector(dm,"TSTheta_X0",X0);CHKERRQ(ierr); 547445fe48SJed Brown } else *X0 = ts->vec_sol; 557445fe48SJed Brown } 567445fe48SJed Brown if (Xdot) { 577445fe48SJed Brown if (dm && dm != ts->dm) { 580d0b770aSPeter Brune ierr = DMGetNamedGlobalVector(dm,"TSTheta_Xdot",Xdot);CHKERRQ(ierr); 597445fe48SJed Brown } else *Xdot = th->Xdot; 607445fe48SJed Brown } 617445fe48SJed Brown PetscFunctionReturn(0); 627445fe48SJed Brown } 637445fe48SJed Brown 640d0b770aSPeter Brune static PetscErrorCode TSThetaRestoreX0AndXdot(TS ts,DM dm,Vec *X0,Vec *Xdot) 650d0b770aSPeter Brune { 660d0b770aSPeter Brune PetscErrorCode ierr; 670d0b770aSPeter Brune 680d0b770aSPeter Brune PetscFunctionBegin; 690d0b770aSPeter Brune if (X0) { 700d0b770aSPeter Brune if (dm && dm != ts->dm) { 710d0b770aSPeter Brune ierr = DMRestoreNamedGlobalVector(dm,"TSTheta_X0",X0);CHKERRQ(ierr); 720d0b770aSPeter Brune } 730d0b770aSPeter Brune } 740d0b770aSPeter Brune if (Xdot) { 750d0b770aSPeter Brune if (dm && dm != ts->dm) { 760d0b770aSPeter Brune ierr = DMRestoreNamedGlobalVector(dm,"TSTheta_Xdot",Xdot);CHKERRQ(ierr); 770d0b770aSPeter Brune } 780d0b770aSPeter Brune } 790d0b770aSPeter Brune PetscFunctionReturn(0); 800d0b770aSPeter Brune } 810d0b770aSPeter Brune 827445fe48SJed Brown static PetscErrorCode DMCoarsenHook_TSTheta(DM fine,DM coarse,void *ctx) 837445fe48SJed Brown { 847445fe48SJed Brown PetscFunctionBegin; 857445fe48SJed Brown PetscFunctionReturn(0); 867445fe48SJed Brown } 877445fe48SJed Brown 887445fe48SJed Brown static PetscErrorCode DMRestrictHook_TSTheta(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse,void *ctx) 897445fe48SJed Brown { 907445fe48SJed Brown TS ts = (TS)ctx; 917445fe48SJed Brown PetscErrorCode ierr; 927445fe48SJed Brown Vec X0,Xdot,X0_c,Xdot_c; 937445fe48SJed Brown 947445fe48SJed Brown PetscFunctionBegin; 957445fe48SJed Brown ierr = TSThetaGetX0AndXdot(ts,fine,&X0,&Xdot);CHKERRQ(ierr); 967445fe48SJed Brown ierr = TSThetaGetX0AndXdot(ts,coarse,&X0_c,&Xdot_c);CHKERRQ(ierr); 977445fe48SJed Brown ierr = MatRestrict(restrct,X0,X0_c);CHKERRQ(ierr); 987445fe48SJed Brown ierr = MatRestrict(restrct,Xdot,Xdot_c);CHKERRQ(ierr); 997445fe48SJed Brown ierr = VecPointwiseMult(X0_c,rscale,X0_c);CHKERRQ(ierr); 1007445fe48SJed Brown ierr = VecPointwiseMult(Xdot_c,rscale,Xdot_c);CHKERRQ(ierr); 1010d0b770aSPeter Brune ierr = TSThetaRestoreX0AndXdot(ts,fine,&X0,&Xdot);CHKERRQ(ierr); 1020d0b770aSPeter Brune ierr = TSThetaRestoreX0AndXdot(ts,coarse,&X0_c,&Xdot_c);CHKERRQ(ierr); 1037445fe48SJed Brown PetscFunctionReturn(0); 1047445fe48SJed Brown } 1057445fe48SJed Brown 106258e1594SPeter Brune static PetscErrorCode DMSubDomainHook_TSTheta(DM dm,DM subdm,void *ctx) 107258e1594SPeter Brune { 108258e1594SPeter Brune PetscFunctionBegin; 109258e1594SPeter Brune PetscFunctionReturn(0); 110258e1594SPeter Brune } 111258e1594SPeter Brune 112258e1594SPeter Brune static PetscErrorCode DMSubDomainRestrictHook_TSTheta(DM dm,VecScatter gscat,VecScatter lscat,DM subdm,void *ctx) 113258e1594SPeter Brune { 114258e1594SPeter Brune TS ts = (TS)ctx; 115258e1594SPeter Brune PetscErrorCode ierr; 116258e1594SPeter Brune Vec X0,Xdot,X0_sub,Xdot_sub; 117258e1594SPeter Brune 118258e1594SPeter Brune PetscFunctionBegin; 119258e1594SPeter Brune ierr = TSThetaGetX0AndXdot(ts,dm,&X0,&Xdot);CHKERRQ(ierr); 120258e1594SPeter Brune ierr = TSThetaGetX0AndXdot(ts,subdm,&X0_sub,&Xdot_sub);CHKERRQ(ierr); 121258e1594SPeter Brune 122258e1594SPeter Brune ierr = VecScatterBegin(gscat,X0,X0_sub,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 123258e1594SPeter Brune ierr = VecScatterEnd(gscat,X0,X0_sub,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 124258e1594SPeter Brune 125258e1594SPeter Brune ierr = VecScatterBegin(gscat,Xdot,Xdot_sub,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 126258e1594SPeter Brune ierr = VecScatterEnd(gscat,Xdot,Xdot_sub,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 127258e1594SPeter Brune 128258e1594SPeter Brune ierr = TSThetaRestoreX0AndXdot(ts,dm,&X0,&Xdot);CHKERRQ(ierr); 129258e1594SPeter Brune ierr = TSThetaRestoreX0AndXdot(ts,subdm,&X0_sub,&Xdot_sub);CHKERRQ(ierr); 130258e1594SPeter Brune PetscFunctionReturn(0); 131258e1594SPeter Brune } 132258e1594SPeter Brune 133022c081aSHong Zhang static PetscErrorCode TSThetaEvaluateCostIntegral(TS ts) 134022c081aSHong Zhang { 135022c081aSHong Zhang TS_Theta *th = (TS_Theta*)ts->data; 136cd4cee2dSHong Zhang TS quadts = ts->quadraturets; 137022c081aSHong Zhang PetscErrorCode ierr; 138022c081aSHong Zhang 139022c081aSHong Zhang PetscFunctionBegin; 140022c081aSHong Zhang if (th->endpoint) { 141022c081aSHong Zhang /* Evolve ts->vec_costintegral to compute integrals */ 142022c081aSHong Zhang if (th->Theta!=1.0) { 1431a352fa8SHong Zhang ierr = TSComputeRHSFunction(quadts,th->ptime0,th->X0,ts->vec_costintegrand);CHKERRQ(ierr); 1441a352fa8SHong Zhang ierr = VecAXPY(quadts->vec_sol,th->time_step0*(1.0-th->Theta),ts->vec_costintegrand);CHKERRQ(ierr); 145022c081aSHong Zhang } 146cd4cee2dSHong Zhang ierr = TSComputeRHSFunction(quadts,ts->ptime,ts->vec_sol,ts->vec_costintegrand);CHKERRQ(ierr); 1471a352fa8SHong Zhang ierr = VecAXPY(quadts->vec_sol,th->time_step0*th->Theta,ts->vec_costintegrand);CHKERRQ(ierr); 148022c081aSHong Zhang } else { 149cd4cee2dSHong Zhang ierr = TSComputeRHSFunction(quadts,th->stage_time,th->X,ts->vec_costintegrand);CHKERRQ(ierr); 1501a352fa8SHong Zhang ierr = VecAXPY(quadts->vec_sol,th->time_step0,ts->vec_costintegrand);CHKERRQ(ierr); 151022c081aSHong Zhang } 152022c081aSHong Zhang PetscFunctionReturn(0); 153022c081aSHong Zhang } 154022c081aSHong Zhang 155b1cb36f3SHong Zhang static PetscErrorCode TSForwardCostIntegral_Theta(TS ts) 156b1cb36f3SHong Zhang { 157b1cb36f3SHong Zhang TS_Theta *th = (TS_Theta*)ts->data; 158cd4cee2dSHong Zhang TS quadts = ts->quadraturets; 159b1cb36f3SHong Zhang PetscErrorCode ierr; 160b1cb36f3SHong Zhang 161b1cb36f3SHong Zhang PetscFunctionBegin; 162b1cb36f3SHong Zhang /* backup cost integral */ 163cd4cee2dSHong Zhang ierr = VecCopy(quadts->vec_sol,th->VecCostIntegral0);CHKERRQ(ierr); 164022c081aSHong Zhang ierr = TSThetaEvaluateCostIntegral(ts);CHKERRQ(ierr); 165b1cb36f3SHong Zhang PetscFunctionReturn(0); 166b1cb36f3SHong Zhang } 167b1cb36f3SHong Zhang 168b1cb36f3SHong Zhang static PetscErrorCode TSAdjointCostIntegral_Theta(TS ts) 169b1cb36f3SHong Zhang { 1701a352fa8SHong Zhang TS_Theta *th = (TS_Theta*)ts->data; 171b1cb36f3SHong Zhang PetscErrorCode ierr; 172b1cb36f3SHong Zhang 173b1cb36f3SHong Zhang PetscFunctionBegin; 1741a352fa8SHong Zhang /* Like TSForwardCostIntegral(), the adjoint cost integral evaluation relies on ptime0 and time_step0. */ 1751a352fa8SHong Zhang th->ptime0 = ts->ptime + ts->time_step; 1761a352fa8SHong Zhang th->time_step0 = -ts->time_step; 177022c081aSHong Zhang ierr = TSThetaEvaluateCostIntegral(ts);CHKERRQ(ierr); 17824655328SShri PetscFunctionReturn(0); 17924655328SShri } 18024655328SShri 181470880abSPatrick Sanan static PetscErrorCode TSTheta_SNESSolve(TS ts,Vec b,Vec x) 1821566a47fSLisandro Dalcin { 1831566a47fSLisandro Dalcin PetscInt nits,lits; 1841566a47fSLisandro Dalcin PetscErrorCode ierr; 1851566a47fSLisandro Dalcin 1861566a47fSLisandro Dalcin PetscFunctionBegin; 1871566a47fSLisandro Dalcin ierr = SNESSolve(ts->snes,b,x);CHKERRQ(ierr); 1881566a47fSLisandro Dalcin ierr = SNESGetIterationNumber(ts->snes,&nits);CHKERRQ(ierr); 1891566a47fSLisandro Dalcin ierr = SNESGetLinearSolveIterations(ts->snes,&lits);CHKERRQ(ierr); 1901566a47fSLisandro Dalcin ts->snes_its += nits; ts->ksp_its += lits; 1911566a47fSLisandro Dalcin PetscFunctionReturn(0); 1921566a47fSLisandro Dalcin } 1931566a47fSLisandro Dalcin 194193ac0bcSJed Brown static PetscErrorCode TSStep_Theta(TS ts) 195316643e7SJed Brown { 196316643e7SJed Brown TS_Theta *th = (TS_Theta*)ts->data; 1971566a47fSLisandro Dalcin PetscInt rejections = 0; 1984957b756SLisandro Dalcin PetscBool stageok,accept = PETSC_TRUE; 1991566a47fSLisandro Dalcin PetscReal next_time_step = ts->time_step; 200051f2191SLisandro Dalcin PetscErrorCode ierr; 201316643e7SJed Brown 202316643e7SJed Brown PetscFunctionBegin; 2031566a47fSLisandro Dalcin if (!ts->steprollback) { 2042ffb9264SLisandro Dalcin if (th->vec_sol_prev) { ierr = VecCopy(th->X0,th->vec_sol_prev);CHKERRQ(ierr); } 2053b1890cdSShri Abhyankar ierr = VecCopy(ts->vec_sol,th->X0);CHKERRQ(ierr); 2061566a47fSLisandro Dalcin } 2071566a47fSLisandro Dalcin 2081566a47fSLisandro Dalcin th->status = TS_STEP_INCOMPLETE; 20999260352SHong Zhang while (!ts->reason && th->status != TS_STEP_COMPLETE) { 2103e05ceb1SHong Zhang th->shift = 1/(th->Theta*ts->time_step); 2111566a47fSLisandro Dalcin th->stage_time = ts->ptime + (th->endpoint ? (PetscReal)1 : th->Theta)*ts->time_step; 212be5899b3SLisandro Dalcin ierr = VecCopy(th->X0,th->X);CHKERRQ(ierr); 213fecfb714SLisandro Dalcin if (th->extrapolate && !ts->steprestart) { 2143e05ceb1SHong Zhang ierr = VecAXPY(th->X,1/th->shift,th->Xdot);CHKERRQ(ierr); 215be5899b3SLisandro Dalcin } 216eb284becSJed Brown if (th->endpoint) { /* This formulation assumes linear time-independent mass matrix */ 217eb284becSJed Brown if (!th->affine) {ierr = VecDuplicate(ts->vec_sol,&th->affine);CHKERRQ(ierr);} 2181566a47fSLisandro Dalcin ierr = VecZeroEntries(th->Xdot);CHKERRQ(ierr); 2191566a47fSLisandro Dalcin ierr = TSComputeIFunction(ts,ts->ptime,th->X0,th->Xdot,th->affine,PETSC_FALSE);CHKERRQ(ierr); 2201566a47fSLisandro Dalcin ierr = VecScale(th->affine,(th->Theta-1)/th->Theta);CHKERRQ(ierr); 2211566a47fSLisandro Dalcin } else if (th->affine) { /* Just in case th->endpoint is changed between calls to TSStep_Theta() */ 2221566a47fSLisandro Dalcin ierr = VecZeroEntries(th->affine);CHKERRQ(ierr); 223eb284becSJed Brown } 224be5899b3SLisandro Dalcin ierr = TSPreStage(ts,th->stage_time);CHKERRQ(ierr); 225470880abSPatrick Sanan ierr = TSTheta_SNESSolve(ts,th->affine,th->X);CHKERRQ(ierr); 226be5899b3SLisandro Dalcin ierr = TSPostStage(ts,th->stage_time,0,&th->X);CHKERRQ(ierr); 2271566a47fSLisandro Dalcin ierr = TSAdaptCheckStage(ts->adapt,ts,th->stage_time,th->X,&stageok);CHKERRQ(ierr); 228fecfb714SLisandro Dalcin if (!stageok) goto reject_step; 229051f2191SLisandro Dalcin 230051f2191SLisandro Dalcin th->status = TS_STEP_PENDING; 2311566a47fSLisandro Dalcin if (th->endpoint) { 2321566a47fSLisandro Dalcin ierr = VecCopy(th->X,ts->vec_sol);CHKERRQ(ierr); 2331566a47fSLisandro Dalcin } else { 2343e05ceb1SHong Zhang ierr = VecAXPBYPCZ(th->Xdot,-th->shift,th->shift,0,th->X0,th->X);CHKERRQ(ierr); 2351566a47fSLisandro Dalcin ierr = VecAXPY(ts->vec_sol,ts->time_step,th->Xdot);CHKERRQ(ierr); 2361566a47fSLisandro Dalcin } 2371566a47fSLisandro Dalcin ierr = TSAdaptChoose(ts->adapt,ts,ts->time_step,NULL,&next_time_step,&accept);CHKERRQ(ierr); 2381566a47fSLisandro Dalcin th->status = accept ? TS_STEP_COMPLETE : TS_STEP_INCOMPLETE; 2391566a47fSLisandro Dalcin if (!accept) { 2401566a47fSLisandro Dalcin ierr = VecCopy(th->X0,ts->vec_sol);CHKERRQ(ierr); 241be5899b3SLisandro Dalcin ts->time_step = next_time_step; 242be5899b3SLisandro Dalcin goto reject_step; 243051f2191SLisandro Dalcin } 2443b1890cdSShri Abhyankar 245715f1b00SHong Zhang if (ts->forward_solve || ts->costintegralfwd) { /* Save the info for the later use in cost integral evaluation */ 2461a352fa8SHong Zhang th->ptime0 = ts->ptime; 2471a352fa8SHong Zhang th->time_step0 = ts->time_step; 24817145e75SHong Zhang } 2492b5a38e1SLisandro Dalcin ts->ptime += ts->time_step; 250cdbf8f93SLisandro Dalcin ts->time_step = next_time_step; 251051f2191SLisandro Dalcin break; 252051f2191SLisandro Dalcin 253051f2191SLisandro Dalcin reject_step: 254fecfb714SLisandro Dalcin ts->reject++; accept = PETSC_FALSE; 2551566a47fSLisandro Dalcin if (!ts->reason && ++rejections > ts->max_reject && ts->max_reject >= 0) { 256051f2191SLisandro Dalcin ts->reason = TS_DIVERGED_STEP_REJECTED; 2571566a47fSLisandro Dalcin ierr = PetscInfo2(ts,"Step=%D, step rejections %D greater than current TS allowed, stopping solve\n",ts->steps,rejections);CHKERRQ(ierr); 2583b1890cdSShri Abhyankar } 2593b1890cdSShri Abhyankar } 260316643e7SJed Brown PetscFunctionReturn(0); 261316643e7SJed Brown } 262316643e7SJed Brown 263c9681e5dSHong Zhang static PetscErrorCode TSAdjointStepBEuler_Private(TS ts) 264c9681e5dSHong Zhang { 265c9681e5dSHong Zhang TS_Theta *th = (TS_Theta*)ts->data; 266cd4cee2dSHong Zhang TS quadts = ts->quadraturets; 267c9681e5dSHong Zhang Vec *VecsDeltaLam = th->VecsDeltaLam,*VecsDeltaMu = th->VecsDeltaMu,*VecsSensiTemp = th->VecsSensiTemp; 268c9681e5dSHong Zhang Vec *VecsDeltaLam2 = th->VecsDeltaLam2,*VecsDeltaMu2 = th->VecsDeltaMu2,*VecsSensi2Temp = th->VecsSensi2Temp; 269c9681e5dSHong Zhang PetscInt nadj; 2707207e0fdSHong Zhang Mat J,Jpre,quadJ = NULL,quadJp = NULL; 271c9681e5dSHong Zhang KSP ksp; 272c9681e5dSHong Zhang PetscScalar *xarr; 273077c4feaSHong Zhang TSEquationType eqtype; 274077c4feaSHong Zhang PetscBool isexplicitode = PETSC_FALSE; 2751a352fa8SHong Zhang PetscReal adjoint_time_step; 276c9681e5dSHong Zhang PetscErrorCode ierr; 277c9681e5dSHong Zhang 278c9681e5dSHong Zhang PetscFunctionBegin; 279077c4feaSHong Zhang ierr = TSGetEquationType(ts,&eqtype);CHKERRQ(ierr); 280077c4feaSHong Zhang if (eqtype == TS_EQ_ODE_EXPLICIT) { 281077c4feaSHong Zhang isexplicitode = PETSC_TRUE; 282077c4feaSHong Zhang VecsDeltaLam = ts->vecs_sensi; 283077c4feaSHong Zhang VecsDeltaLam2 = ts->vecs_sensi2; 284077c4feaSHong Zhang } 285c9681e5dSHong Zhang th->status = TS_STEP_INCOMPLETE; 286c9681e5dSHong Zhang ierr = SNESGetKSP(ts->snes,&ksp);CHKERRQ(ierr); 287cd4cee2dSHong Zhang ierr = TSGetIJacobian(ts,&J,&Jpre,NULL,NULL);CHKERRQ(ierr); 2887207e0fdSHong Zhang if (quadts) { 289cd4cee2dSHong Zhang ierr = TSGetRHSJacobian(quadts,&quadJ,NULL,NULL,NULL);CHKERRQ(ierr); 290cd4cee2dSHong Zhang ierr = TSGetRHSJacobianP(quadts,&quadJp,NULL,NULL);CHKERRQ(ierr); 2917207e0fdSHong Zhang } 292c9681e5dSHong Zhang 2931a352fa8SHong Zhang th->stage_time = ts->ptime; 2941a352fa8SHong Zhang adjoint_time_step = -ts->time_step; /* always positive since time_step is negative */ 295c9681e5dSHong Zhang 29633f72c5dSHong Zhang /* Build RHS for first-order adjoint lambda_{n+1}/h + r_u^T(n+1) */ 2977207e0fdSHong Zhang if (quadts) { 29882ad9101SHong Zhang ierr = TSComputeRHSJacobian(quadts,th->stage_time,ts->vec_sol,quadJ,NULL);CHKERRQ(ierr); 2997207e0fdSHong Zhang } 300cd4cee2dSHong Zhang 301c9681e5dSHong Zhang for (nadj=0; nadj<ts->numcost; nadj++) { 302c9681e5dSHong Zhang ierr = VecCopy(ts->vecs_sensi[nadj],VecsSensiTemp[nadj]);CHKERRQ(ierr); 3031a352fa8SHong Zhang ierr = VecScale(VecsSensiTemp[nadj],1./adjoint_time_step);CHKERRQ(ierr); /* lambda_{n+1}/h */ 304cd4cee2dSHong Zhang if (quadJ) { 305cd4cee2dSHong Zhang ierr = MatDenseGetColumn(quadJ,nadj,&xarr);CHKERRQ(ierr); 306cd4cee2dSHong Zhang ierr = VecPlaceArray(ts->vec_drdu_col,xarr);CHKERRQ(ierr); 307cd4cee2dSHong Zhang ierr = VecAXPY(VecsSensiTemp[nadj],1.,ts->vec_drdu_col);CHKERRQ(ierr); 308cd4cee2dSHong Zhang ierr = VecResetArray(ts->vec_drdu_col);CHKERRQ(ierr); 309cd4cee2dSHong Zhang ierr = MatDenseRestoreColumn(quadJ,&xarr);CHKERRQ(ierr); 310c9681e5dSHong Zhang } 311c9681e5dSHong Zhang } 312c9681e5dSHong Zhang 313c9681e5dSHong Zhang /* Build LHS for first-order adjoint */ 314c87ba875SIvan Yashchuk th->shift = 1./adjoint_time_step; 31582ad9101SHong Zhang ierr = TSComputeSNESJacobian(ts,ts->vec_sol,J,Jpre);CHKERRQ(ierr); 31604f7482eSHong Zhang ierr = KSPSetOperators(ksp,J,Jpre);CHKERRQ(ierr); 317c9681e5dSHong Zhang 318c9681e5dSHong Zhang /* Solve stage equation LHS*lambda_s = RHS for first-order adjoint */ 319c9681e5dSHong Zhang for (nadj=0; nadj<ts->numcost; nadj++) { 320c9681e5dSHong Zhang KSPConvergedReason kspreason; 321c9681e5dSHong Zhang ierr = KSPSolveTranspose(ksp,VecsSensiTemp[nadj],VecsDeltaLam[nadj]);CHKERRQ(ierr); 322c9681e5dSHong Zhang ierr = KSPGetConvergedReason(ksp,&kspreason);CHKERRQ(ierr); 323c9681e5dSHong Zhang if (kspreason < 0) { 324c9681e5dSHong Zhang ts->reason = TSADJOINT_DIVERGED_LINEAR_SOLVE; 32529b3c8a1SHong Zhang ierr = PetscInfo2(ts,"Step=%D, %Dth cost function, transposed linear solve fails, stopping 1st-order adjoint solve\n",ts->steps,nadj);CHKERRQ(ierr); 326c9681e5dSHong Zhang } 327c9681e5dSHong Zhang } 328c9681e5dSHong Zhang 329c9681e5dSHong Zhang if (ts->vecs_sensi2) { /* U_{n+1} */ 330c9681e5dSHong Zhang /* Get w1 at t_{n+1} from TLM matrix */ 331c9681e5dSHong Zhang ierr = MatDenseGetColumn(ts->mat_sensip,0,&xarr);CHKERRQ(ierr); 332c9681e5dSHong Zhang ierr = VecPlaceArray(ts->vec_sensip_col,xarr);CHKERRQ(ierr); 333c9681e5dSHong Zhang /* lambda_s^T F_UU w_1 */ 33482ad9101SHong Zhang ierr = TSComputeIHessianProductFunctionUU(ts,th->stage_time,ts->vec_sol,VecsDeltaLam,ts->vec_sensip_col,ts->vecs_fuu);CHKERRQ(ierr); 335c9681e5dSHong Zhang /* lambda_s^T F_UP w_2 */ 33682ad9101SHong Zhang ierr = TSComputeIHessianProductFunctionUP(ts,th->stage_time,ts->vec_sol,VecsDeltaLam,ts->vec_dir,ts->vecs_fup);CHKERRQ(ierr); 337c9681e5dSHong Zhang for (nadj=0; nadj<ts->numcost; nadj++) { /* compute the residual */ 338c9681e5dSHong Zhang ierr = VecCopy(ts->vecs_sensi2[nadj],VecsSensi2Temp[nadj]);CHKERRQ(ierr); 3391a352fa8SHong Zhang ierr = VecScale(VecsSensi2Temp[nadj],1./adjoint_time_step);CHKERRQ(ierr); 34033f72c5dSHong Zhang ierr = VecAXPY(VecsSensi2Temp[nadj],-1.,ts->vecs_fuu[nadj]);CHKERRQ(ierr); 341c9681e5dSHong Zhang if (ts->vecs_fup) { 34233f72c5dSHong Zhang ierr = VecAXPY(VecsSensi2Temp[nadj],-1.,ts->vecs_fup[nadj]);CHKERRQ(ierr); 343c9681e5dSHong Zhang } 344c9681e5dSHong Zhang } 345c9681e5dSHong Zhang /* Solve stage equation LHS X = RHS for second-order adjoint */ 346c9681e5dSHong Zhang for (nadj=0; nadj<ts->numcost; nadj++) { 34705c9950eSHong Zhang KSPConvergedReason kspreason; 348c9681e5dSHong Zhang ierr = KSPSolveTranspose(ksp,VecsSensi2Temp[nadj],VecsDeltaLam2[nadj]);CHKERRQ(ierr); 34905c9950eSHong Zhang ierr = KSPGetConvergedReason(ksp,&kspreason);CHKERRQ(ierr); 35005c9950eSHong Zhang if (kspreason < 0) { 35105c9950eSHong Zhang ts->reason = TSADJOINT_DIVERGED_LINEAR_SOLVE; 35229b3c8a1SHong Zhang ierr = PetscInfo2(ts,"Step=%D, %Dth cost function, transposed linear solve fails, stopping 2nd-order adjoint solve\n",ts->steps,nadj);CHKERRQ(ierr); 35305c9950eSHong Zhang } 354c9681e5dSHong Zhang } 355c9681e5dSHong Zhang } 356c9681e5dSHong Zhang 357c9681e5dSHong Zhang /* Update sensitivities, and evaluate integrals if there is any */ 358077c4feaSHong Zhang if (!isexplicitode) { 3593e05ceb1SHong Zhang th->shift = 0.0; 36082ad9101SHong Zhang ierr = TSComputeSNESJacobian(ts,ts->vec_sol,J,Jpre);CHKERRQ(ierr); 36104f7482eSHong Zhang ierr = KSPSetOperators(ksp,J,Jpre);CHKERRQ(ierr); 362c9681e5dSHong Zhang ierr = MatScale(J,-1.);CHKERRQ(ierr); 363c9681e5dSHong Zhang for (nadj=0; nadj<ts->numcost; nadj++) { 36433f72c5dSHong Zhang /* Add f_U \lambda_s to the original RHS */ 365c9681e5dSHong Zhang ierr = MatMultTransposeAdd(J,VecsDeltaLam[nadj],VecsSensiTemp[nadj],VecsSensiTemp[nadj]);CHKERRQ(ierr); 3661a352fa8SHong Zhang ierr = VecScale(VecsSensiTemp[nadj],adjoint_time_step);CHKERRQ(ierr); 367c9681e5dSHong Zhang ierr = VecCopy(VecsSensiTemp[nadj],ts->vecs_sensi[nadj]);CHKERRQ(ierr); 368c9681e5dSHong Zhang if (ts->vecs_sensi2) { 369c9681e5dSHong Zhang ierr = MatMultTransposeAdd(J,VecsDeltaLam2[nadj],VecsSensi2Temp[nadj],VecsSensi2Temp[nadj]);CHKERRQ(ierr); 3701a352fa8SHong Zhang ierr = VecScale(VecsSensi2Temp[nadj],adjoint_time_step);CHKERRQ(ierr); 371c9681e5dSHong Zhang ierr = VecCopy(VecsSensi2Temp[nadj],ts->vecs_sensi2[nadj]);CHKERRQ(ierr); 372c9681e5dSHong Zhang } 373c9681e5dSHong Zhang } 374077c4feaSHong Zhang } 375c9681e5dSHong Zhang if (ts->vecs_sensip) { 37682ad9101SHong Zhang ierr = VecAXPBYPCZ(th->Xdot,-1./adjoint_time_step,1.0/adjoint_time_step,0,th->X0,ts->vec_sol);CHKERRQ(ierr); 37782ad9101SHong Zhang ierr = TSComputeIJacobianP(ts,th->stage_time,ts->vec_sol,th->Xdot,1./adjoint_time_step,ts->Jacp,PETSC_FALSE);CHKERRQ(ierr); /* get -f_p */ 3787207e0fdSHong Zhang if (quadts) { 37982ad9101SHong Zhang ierr = TSComputeRHSJacobianP(quadts,th->stage_time,ts->vec_sol,quadJp);CHKERRQ(ierr); 3807207e0fdSHong Zhang } 381c9681e5dSHong Zhang if (ts->vecs_sensi2p) { 382c9681e5dSHong Zhang /* lambda_s^T F_PU w_1 */ 38382ad9101SHong Zhang ierr = TSComputeIHessianProductFunctionPU(ts,th->stage_time,ts->vec_sol,VecsDeltaLam,ts->vec_sensip_col,ts->vecs_fpu);CHKERRQ(ierr); 38433f72c5dSHong Zhang /* lambda_s^T F_PP w_2 */ 38582ad9101SHong Zhang ierr = TSComputeIHessianProductFunctionPP(ts,th->stage_time,ts->vec_sol,VecsDeltaLam,ts->vec_dir,ts->vecs_fpp);CHKERRQ(ierr); 386c9681e5dSHong Zhang } 387cd4cee2dSHong Zhang 388c9681e5dSHong Zhang for (nadj=0; nadj<ts->numcost; nadj++) { 389c9681e5dSHong Zhang ierr = MatMultTranspose(ts->Jacp,VecsDeltaLam[nadj],VecsDeltaMu[nadj]);CHKERRQ(ierr); 3901a352fa8SHong Zhang ierr = VecAXPY(ts->vecs_sensip[nadj],-adjoint_time_step,VecsDeltaMu[nadj]);CHKERRQ(ierr); 391cd4cee2dSHong Zhang if (quadJp) { 392cd4cee2dSHong Zhang ierr = MatDenseGetColumn(quadJp,nadj,&xarr);CHKERRQ(ierr); 393cd4cee2dSHong Zhang ierr = VecPlaceArray(ts->vec_drdp_col,xarr);CHKERRQ(ierr); 3941a352fa8SHong Zhang ierr = VecAXPY(ts->vecs_sensip[nadj],adjoint_time_step,ts->vec_drdp_col);CHKERRQ(ierr); 395cd4cee2dSHong Zhang ierr = VecResetArray(ts->vec_drdp_col);CHKERRQ(ierr); 396cd4cee2dSHong Zhang ierr = MatDenseRestoreColumn(quadJp,&xarr);CHKERRQ(ierr); 39733f72c5dSHong Zhang } 398c9681e5dSHong Zhang if (ts->vecs_sensi2p) { 399c9681e5dSHong Zhang ierr = MatMultTranspose(ts->Jacp,VecsDeltaLam2[nadj],VecsDeltaMu2[nadj]);CHKERRQ(ierr); 4001a352fa8SHong Zhang ierr = VecAXPY(ts->vecs_sensi2p[nadj],-adjoint_time_step,VecsDeltaMu2[nadj]);CHKERRQ(ierr); 401c9681e5dSHong Zhang if (ts->vecs_fpu) { 4021a352fa8SHong Zhang ierr = VecAXPY(ts->vecs_sensi2p[nadj],-adjoint_time_step,ts->vecs_fpu[nadj]);CHKERRQ(ierr); 403c9681e5dSHong Zhang } 404c9681e5dSHong Zhang if (ts->vecs_fpp) { 4051a352fa8SHong Zhang ierr = VecAXPY(ts->vecs_sensi2p[nadj],-adjoint_time_step,ts->vecs_fpp[nadj]);CHKERRQ(ierr); 406c9681e5dSHong Zhang } 407c9681e5dSHong Zhang } 408c9681e5dSHong Zhang } 409c9681e5dSHong Zhang } 410c9681e5dSHong Zhang 411c9681e5dSHong Zhang if (ts->vecs_sensi2) { 412c9681e5dSHong Zhang ierr = VecResetArray(ts->vec_sensip_col);CHKERRQ(ierr); 413c9681e5dSHong Zhang ierr = MatDenseRestoreColumn(ts->mat_sensip,&xarr);CHKERRQ(ierr); 414c9681e5dSHong Zhang } 415c9681e5dSHong Zhang th->status = TS_STEP_COMPLETE; 416c9681e5dSHong Zhang PetscFunctionReturn(0); 417c9681e5dSHong Zhang } 418c9681e5dSHong Zhang 41942f2b339SBarry Smith static PetscErrorCode TSAdjointStep_Theta(TS ts) 4202ca6e920SHong Zhang { 4212ca6e920SHong Zhang TS_Theta *th = (TS_Theta*)ts->data; 422cd4cee2dSHong Zhang TS quadts = ts->quadraturets; 423b5e0532dSHong Zhang Vec *VecsDeltaLam = th->VecsDeltaLam,*VecsDeltaMu = th->VecsDeltaMu,*VecsSensiTemp = th->VecsSensiTemp; 424b5b4017aSHong Zhang Vec *VecsDeltaLam2 = th->VecsDeltaLam2,*VecsDeltaMu2 = th->VecsDeltaMu2,*VecsSensi2Temp = th->VecsSensi2Temp; 4252ca6e920SHong Zhang PetscInt nadj; 4267207e0fdSHong Zhang Mat J,Jpre,quadJ = NULL,quadJp = NULL; 4272ca6e920SHong Zhang KSP ksp; 428b5b4017aSHong Zhang PetscScalar *xarr; 4291a352fa8SHong Zhang PetscReal adjoint_time_step; 4301a352fa8SHong 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) */ 431b5b4017aSHong Zhang PetscErrorCode ierr; 4322ca6e920SHong Zhang 4332ca6e920SHong Zhang PetscFunctionBegin; 434c9681e5dSHong Zhang if (th->Theta == 1.) { 435c9681e5dSHong Zhang ierr = TSAdjointStepBEuler_Private(ts);CHKERRQ(ierr); 436c9681e5dSHong Zhang PetscFunctionReturn(0); 437c9681e5dSHong Zhang } 4382ca6e920SHong Zhang th->status = TS_STEP_INCOMPLETE; 439302440fdSBarry Smith ierr = SNESGetKSP(ts->snes,&ksp);CHKERRQ(ierr); 440cd4cee2dSHong Zhang ierr = TSGetIJacobian(ts,&J,&Jpre,NULL,NULL);CHKERRQ(ierr); 4417207e0fdSHong Zhang if (quadts) { 442cd4cee2dSHong Zhang ierr = TSGetRHSJacobian(quadts,&quadJ,NULL,NULL,NULL);CHKERRQ(ierr); 443cd4cee2dSHong Zhang ierr = TSGetRHSJacobianP(quadts,&quadJp,NULL,NULL);CHKERRQ(ierr); 4447207e0fdSHong Zhang } 445b5e0532dSHong Zhang /* If endpoint=1, th->ptime and th->X0 will be used; if endpoint=0, th->stage_time and th->X will be used. */ 4461a352fa8SHong Zhang th->stage_time = th->endpoint ? ts->ptime : (ts->ptime+(1.-th->Theta)*ts->time_step); 4471a352fa8SHong Zhang adjoint_ptime = ts->ptime + ts->time_step; 4481a352fa8SHong Zhang adjoint_time_step = -ts->time_step; /* always positive since time_step is negative */ 4492ca6e920SHong Zhang 45082ad9101SHong Zhang if (!th->endpoint) { 4515072d23cSHong Zhang /* recover th->X0 using vec_sol and the stage value th->X */ 4525072d23cSHong Zhang ierr = VecAXPBYPCZ(th->X0,1.0/(1.0-th->Theta),th->Theta/(th->Theta-1.0),0,th->X,ts->vec_sol);CHKERRQ(ierr); 45382ad9101SHong Zhang } 45482ad9101SHong Zhang 455b5b4017aSHong Zhang /* Build RHS for first-order adjoint */ 45633f72c5dSHong Zhang /* Cost function has an integral term */ 4577207e0fdSHong Zhang if (quadts) { 45805755b9cSHong Zhang if (th->endpoint) { 459cd4cee2dSHong Zhang ierr = TSComputeRHSJacobian(quadts,th->stage_time,ts->vec_sol,quadJ,NULL);CHKERRQ(ierr); 46005755b9cSHong Zhang } else { 461cd4cee2dSHong Zhang ierr = TSComputeRHSJacobian(quadts,th->stage_time,th->X,quadJ,NULL);CHKERRQ(ierr); 46205755b9cSHong Zhang } 4637207e0fdSHong Zhang } 46433f72c5dSHong Zhang 465abc2977eSBarry Smith for (nadj=0; nadj<ts->numcost; nadj++) { 466b5e0532dSHong Zhang ierr = VecCopy(ts->vecs_sensi[nadj],VecsSensiTemp[nadj]);CHKERRQ(ierr); 4671a352fa8SHong Zhang ierr = VecScale(VecsSensiTemp[nadj],1./(th->Theta*adjoint_time_step));CHKERRQ(ierr); 468cd4cee2dSHong Zhang if (quadJ) { 469cd4cee2dSHong Zhang ierr = MatDenseGetColumn(quadJ,nadj,&xarr);CHKERRQ(ierr); 470cd4cee2dSHong Zhang ierr = VecPlaceArray(ts->vec_drdu_col,xarr);CHKERRQ(ierr); 471cd4cee2dSHong Zhang ierr = VecAXPY(VecsSensiTemp[nadj],1.,ts->vec_drdu_col);CHKERRQ(ierr); 472cd4cee2dSHong Zhang ierr = VecResetArray(ts->vec_drdu_col);CHKERRQ(ierr); 473cd4cee2dSHong Zhang ierr = MatDenseRestoreColumn(quadJ,&xarr);CHKERRQ(ierr); 47436eaed60SHong Zhang } 4752ca6e920SHong Zhang } 4763c54f92cSHong Zhang 477b5b4017aSHong Zhang /* Build LHS for first-order adjoint */ 4781a352fa8SHong Zhang th->shift = 1./(th->Theta*adjoint_time_step); 4793c54f92cSHong Zhang if (th->endpoint) { 48004f7482eSHong Zhang ierr = TSComputeSNESJacobian(ts,ts->vec_sol,J,Jpre);CHKERRQ(ierr); 4813c54f92cSHong Zhang } else { 48204f7482eSHong Zhang ierr = TSComputeSNESJacobian(ts,th->X,J,Jpre);CHKERRQ(ierr); 4833c54f92cSHong Zhang } 484cd4cee2dSHong Zhang ierr = KSPSetOperators(ksp,J,Jpre);CHKERRQ(ierr); 4852ca6e920SHong Zhang 486b5b4017aSHong Zhang /* Solve stage equation LHS*lambda_s = RHS for first-order adjoint */ 487abc2977eSBarry Smith for (nadj=0; nadj<ts->numcost; nadj++) { 4881d14d03bSHong Zhang KSPConvergedReason kspreason; 489b5e0532dSHong Zhang ierr = KSPSolveTranspose(ksp,VecsSensiTemp[nadj],VecsDeltaLam[nadj]);CHKERRQ(ierr); 4901d14d03bSHong Zhang ierr = KSPGetConvergedReason(ksp,&kspreason);CHKERRQ(ierr); 4911d14d03bSHong Zhang if (kspreason < 0) { 4921d14d03bSHong Zhang ts->reason = TSADJOINT_DIVERGED_LINEAR_SOLVE; 49329b3c8a1SHong Zhang ierr = PetscInfo2(ts,"Step=%D, %Dth cost function, transposed linear solve fails, stopping 1st-order adjoint solve\n",ts->steps,nadj);CHKERRQ(ierr); 4941d14d03bSHong Zhang } 4952ca6e920SHong Zhang } 4963c54f92cSHong Zhang 4971d14d03bSHong Zhang /* Second-order adjoint */ 498b5b4017aSHong Zhang if (ts->vecs_sensi2) { /* U_{n+1} */ 499b5b4017aSHong Zhang if (!th->endpoint) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Operation not implemented in TS_Theta"); 500b5b4017aSHong Zhang /* Get w1 at t_{n+1} from TLM matrix */ 501b5b4017aSHong Zhang ierr = MatDenseGetColumn(ts->mat_sensip,0,&xarr);CHKERRQ(ierr); 502b5b4017aSHong Zhang ierr = VecPlaceArray(ts->vec_sensip_col,xarr);CHKERRQ(ierr); 503b5b4017aSHong Zhang /* lambda_s^T F_UU w_1 */ 504b1e111ebSHong Zhang ierr = TSComputeIHessianProductFunctionUU(ts,th->stage_time,ts->vec_sol,VecsDeltaLam,ts->vec_sensip_col,ts->vecs_fuu);CHKERRQ(ierr); 505b5b4017aSHong Zhang ierr = VecResetArray(ts->vec_sensip_col);CHKERRQ(ierr); 506b5b4017aSHong Zhang ierr = MatDenseRestoreColumn(ts->mat_sensip,&xarr);CHKERRQ(ierr); 507b5b4017aSHong Zhang /* lambda_s^T F_UP w_2 */ 508b1e111ebSHong Zhang ierr = TSComputeIHessianProductFunctionUP(ts,th->stage_time,ts->vec_sol,VecsDeltaLam,ts->vec_dir,ts->vecs_fup);CHKERRQ(ierr); 509b5b4017aSHong Zhang for (nadj=0; nadj<ts->numcost; nadj++) { /* compute the residual */ 510b5b4017aSHong Zhang ierr = VecCopy(ts->vecs_sensi2[nadj],VecsSensi2Temp[nadj]);CHKERRQ(ierr); 5113e05ceb1SHong Zhang ierr = VecScale(VecsSensi2Temp[nadj],th->shift);CHKERRQ(ierr); 51233f72c5dSHong Zhang ierr = VecAXPY(VecsSensi2Temp[nadj],-1.,ts->vecs_fuu[nadj]);CHKERRQ(ierr); 513b5b4017aSHong Zhang if (ts->vecs_fup) { 51433f72c5dSHong Zhang ierr = VecAXPY(VecsSensi2Temp[nadj],-1.,ts->vecs_fup[nadj]);CHKERRQ(ierr); 515b5b4017aSHong Zhang } 516b5b4017aSHong Zhang } 517b5b4017aSHong Zhang /* Solve stage equation LHS X = RHS for second-order adjoint */ 518b5b4017aSHong Zhang for (nadj=0; nadj<ts->numcost; nadj++) { 5191d14d03bSHong Zhang KSPConvergedReason kspreason; 5201d14d03bSHong Zhang ierr = KSPSolveTranspose(ksp,VecsSensi2Temp[nadj],VecsDeltaLam2[nadj]);CHKERRQ(ierr); 5211d14d03bSHong Zhang ierr = KSPGetConvergedReason(ksp,&kspreason);CHKERRQ(ierr); 5221d14d03bSHong Zhang if (kspreason < 0) { 5231d14d03bSHong Zhang ts->reason = TSADJOINT_DIVERGED_LINEAR_SOLVE; 52429b3c8a1SHong Zhang ierr = PetscInfo2(ts,"Step=%D, %Dth cost function, transposed linear solve fails, stopping 2nd-order adjoint solve\n",ts->steps,nadj);CHKERRQ(ierr); 5251d14d03bSHong Zhang } 526b5b4017aSHong Zhang } 527b5b4017aSHong Zhang } 528b5b4017aSHong Zhang 52936eaed60SHong Zhang /* Update sensitivities, and evaluate integrals if there is any */ 5301d14d03bSHong Zhang if (th->endpoint) { /* two-stage Theta methods with th->Theta!=1, th->Theta==1 leads to BEuler */ 5311a352fa8SHong Zhang th->shift = 1./((th->Theta-1.)*adjoint_time_step); 5321a352fa8SHong Zhang th->stage_time = adjoint_ptime; 53304f7482eSHong Zhang ierr = TSComputeSNESJacobian(ts,th->X0,J,Jpre);CHKERRQ(ierr); 53404f7482eSHong Zhang ierr = KSPSetOperators(ksp,J,Jpre);CHKERRQ(ierr); 53533f72c5dSHong Zhang /* R_U at t_n */ 5367207e0fdSHong Zhang if (quadts) { 5371a352fa8SHong Zhang ierr = TSComputeRHSJacobian(quadts,adjoint_ptime,th->X0,quadJ,NULL);CHKERRQ(ierr); 5387207e0fdSHong Zhang } 539abc2977eSBarry Smith for (nadj=0; nadj<ts->numcost; nadj++) { 540b5e0532dSHong Zhang ierr = MatMultTranspose(J,VecsDeltaLam[nadj],ts->vecs_sensi[nadj]);CHKERRQ(ierr); 541cd4cee2dSHong Zhang if (quadJ) { 542cd4cee2dSHong Zhang ierr = MatDenseGetColumn(quadJ,nadj,&xarr);CHKERRQ(ierr); 543cd4cee2dSHong Zhang ierr = VecPlaceArray(ts->vec_drdu_col,xarr);CHKERRQ(ierr); 544cd4cee2dSHong Zhang ierr = VecAXPY(ts->vecs_sensi[nadj],-1.,ts->vec_drdu_col);CHKERRQ(ierr); 545cd4cee2dSHong Zhang ierr = VecResetArray(ts->vec_drdu_col);CHKERRQ(ierr); 546cd4cee2dSHong Zhang ierr = MatDenseRestoreColumn(quadJ,&xarr);CHKERRQ(ierr); 547b5b4017aSHong Zhang } 5483e05ceb1SHong Zhang ierr = VecScale(ts->vecs_sensi[nadj],1./th->shift);CHKERRQ(ierr); 549b5b4017aSHong Zhang } 5501d14d03bSHong Zhang 5511d14d03bSHong Zhang /* Second-order adjoint */ 5521d14d03bSHong Zhang if (ts->vecs_sensi2) { /* U_n */ 553b5b4017aSHong Zhang /* Get w1 at t_n from TLM matrix */ 554b5b4017aSHong Zhang ierr = MatDenseGetColumn(th->MatFwdSensip0,0,&xarr);CHKERRQ(ierr); 555b5b4017aSHong Zhang ierr = VecPlaceArray(ts->vec_sensip_col,xarr);CHKERRQ(ierr); 556b5b4017aSHong Zhang /* lambda_s^T F_UU w_1 */ 5571a352fa8SHong Zhang ierr = TSComputeIHessianProductFunctionUU(ts,adjoint_ptime,th->X0,VecsDeltaLam,ts->vec_sensip_col,ts->vecs_fuu);CHKERRQ(ierr); 558b5b4017aSHong Zhang ierr = VecResetArray(ts->vec_sensip_col);CHKERRQ(ierr); 55933f72c5dSHong Zhang ierr = MatDenseRestoreColumn(th->MatFwdSensip0,&xarr);CHKERRQ(ierr); 560b5b4017aSHong Zhang /* lambda_s^T F_UU w_2 */ 5611a352fa8SHong Zhang ierr = TSComputeIHessianProductFunctionUP(ts,adjoint_ptime,th->X0,VecsDeltaLam,ts->vec_dir,ts->vecs_fup);CHKERRQ(ierr); 562b5b4017aSHong Zhang for (nadj=0; nadj<ts->numcost; nadj++) { 56333f72c5dSHong 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 */ 564b5b4017aSHong Zhang ierr = MatMultTranspose(J,VecsDeltaLam2[nadj],ts->vecs_sensi2[nadj]);CHKERRQ(ierr); 56533f72c5dSHong Zhang ierr = VecAXPY(ts->vecs_sensi2[nadj],1.,ts->vecs_fuu[nadj]);CHKERRQ(ierr); 566b5b4017aSHong Zhang if (ts->vecs_fup) { 56733f72c5dSHong Zhang ierr = VecAXPY(ts->vecs_sensi2[nadj],1.,ts->vecs_fup[nadj]);CHKERRQ(ierr); 568b5b4017aSHong Zhang } 5693e05ceb1SHong Zhang ierr = VecScale(ts->vecs_sensi2[nadj],1./th->shift);CHKERRQ(ierr); 570b5b4017aSHong Zhang } 571b5e0532dSHong Zhang } 5723fd52205SHong Zhang 573c586f2e8SHong Zhang th->stage_time = ts->ptime; /* recover the old value */ 574c586f2e8SHong Zhang 5753fd52205SHong Zhang if (ts->vecs_sensip) { /* sensitivities wrt parameters */ 576b5b4017aSHong Zhang /* U_{n+1} */ 57782ad9101SHong Zhang th->shift = 1.0/(adjoint_time_step*th->Theta); 57882ad9101SHong Zhang ierr = VecAXPBYPCZ(th->Xdot,-th->shift,th->shift,0,th->X0,ts->vec_sol);CHKERRQ(ierr); 5791a352fa8SHong Zhang ierr = TSComputeIJacobianP(ts,th->stage_time,ts->vec_sol,th->Xdot,-1./(th->Theta*adjoint_time_step),ts->Jacp,PETSC_FALSE);CHKERRQ(ierr); 5807207e0fdSHong Zhang if (quadts) { 581cd4cee2dSHong Zhang ierr = TSComputeRHSJacobianP(quadts,th->stage_time,ts->vec_sol,quadJp);CHKERRQ(ierr); 5827207e0fdSHong Zhang } 583abc2977eSBarry Smith for (nadj=0; nadj<ts->numcost; nadj++) { 584b5e0532dSHong Zhang ierr = MatMultTranspose(ts->Jacp,VecsDeltaLam[nadj],VecsDeltaMu[nadj]);CHKERRQ(ierr); 5851a352fa8SHong Zhang ierr = VecAXPY(ts->vecs_sensip[nadj],-adjoint_time_step*th->Theta,VecsDeltaMu[nadj]);CHKERRQ(ierr); 5863b711c3fSHong Zhang if (quadJp) { 5873b711c3fSHong Zhang ierr = MatDenseGetColumn(quadJp,nadj,&xarr);CHKERRQ(ierr); 5883b711c3fSHong Zhang ierr = VecPlaceArray(ts->vec_drdp_col,xarr);CHKERRQ(ierr); 5893b711c3fSHong Zhang ierr = VecAXPY(ts->vecs_sensip[nadj],adjoint_time_step*th->Theta,ts->vec_drdp_col);CHKERRQ(ierr); 5903b711c3fSHong Zhang ierr = VecResetArray(ts->vec_drdp_col);CHKERRQ(ierr); 5913b711c3fSHong Zhang ierr = MatDenseRestoreColumn(quadJp,&xarr);CHKERRQ(ierr); 5923b711c3fSHong Zhang } 5933fd52205SHong Zhang } 59433f72c5dSHong Zhang if (ts->vecs_sensi2p) { /* second-order */ 59533f72c5dSHong Zhang /* Get w1 at t_{n+1} from TLM matrix */ 59633f72c5dSHong Zhang ierr = MatDenseGetColumn(ts->mat_sensip,0,&xarr);CHKERRQ(ierr); 59733f72c5dSHong Zhang ierr = VecPlaceArray(ts->vec_sensip_col,xarr);CHKERRQ(ierr); 598b5b4017aSHong Zhang /* lambda_s^T F_PU w_1 */ 599b1e111ebSHong Zhang ierr = TSComputeIHessianProductFunctionPU(ts,th->stage_time,ts->vec_sol,VecsDeltaLam,ts->vec_sensip_col,ts->vecs_fpu);CHKERRQ(ierr); 60033f72c5dSHong Zhang ierr = VecResetArray(ts->vec_sensip_col);CHKERRQ(ierr); 60133f72c5dSHong Zhang ierr = MatDenseRestoreColumn(ts->mat_sensip,&xarr);CHKERRQ(ierr); 60233f72c5dSHong Zhang 603b5b4017aSHong Zhang /* lambda_s^T F_PP w_2 */ 604b1e111ebSHong Zhang ierr = TSComputeIHessianProductFunctionPP(ts,th->stage_time,ts->vec_sol,VecsDeltaLam,ts->vec_dir,ts->vecs_fpp);CHKERRQ(ierr); 605b5b4017aSHong Zhang for (nadj=0; nadj<ts->numcost; nadj++) { 60633f72c5dSHong 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) */ 607b5b4017aSHong Zhang ierr = MatMultTranspose(ts->Jacp,VecsDeltaLam2[nadj],VecsDeltaMu2[nadj]);CHKERRQ(ierr); 6081a352fa8SHong Zhang ierr = VecAXPY(ts->vecs_sensi2p[nadj],-adjoint_time_step*th->Theta,VecsDeltaMu2[nadj]);CHKERRQ(ierr); 609b5b4017aSHong Zhang if (ts->vecs_fpu) { 6101a352fa8SHong Zhang ierr = VecAXPY(ts->vecs_sensi2p[nadj],-adjoint_time_step*th->Theta,ts->vecs_fpu[nadj]);CHKERRQ(ierr); 611b5b4017aSHong Zhang } 612b5b4017aSHong Zhang if (ts->vecs_fpp) { 6131a352fa8SHong Zhang ierr = VecAXPY(ts->vecs_sensi2p[nadj],-adjoint_time_step*th->Theta,ts->vecs_fpp[nadj]);CHKERRQ(ierr); 614b5b4017aSHong Zhang } 615b5b4017aSHong Zhang } 616b5b4017aSHong Zhang } 617b5b4017aSHong Zhang 618b5b4017aSHong Zhang /* U_s */ 61982ad9101SHong Zhang ierr = VecZeroEntries(th->Xdot);CHKERRQ(ierr); 6201a352fa8SHong Zhang ierr = TSComputeIJacobianP(ts,adjoint_ptime,th->X0,th->Xdot,1./((th->Theta-1.0)*adjoint_time_step),ts->Jacp,PETSC_FALSE);CHKERRQ(ierr); 6217207e0fdSHong Zhang if (quadts) { 6221a352fa8SHong Zhang ierr = TSComputeRHSJacobianP(quadts,adjoint_ptime,th->X0,quadJp);CHKERRQ(ierr); 6237207e0fdSHong Zhang } 624abc2977eSBarry Smith for (nadj=0; nadj<ts->numcost; nadj++) { 625b5e0532dSHong Zhang ierr = MatMultTranspose(ts->Jacp,VecsDeltaLam[nadj],VecsDeltaMu[nadj]);CHKERRQ(ierr); 6261a352fa8SHong Zhang ierr = VecAXPY(ts->vecs_sensip[nadj],-adjoint_time_step*(1.0-th->Theta),VecsDeltaMu[nadj]);CHKERRQ(ierr); 6273b711c3fSHong Zhang if (quadJp) { 6283b711c3fSHong Zhang ierr = MatDenseGetColumn(quadJp,nadj,&xarr);CHKERRQ(ierr); 6293b711c3fSHong Zhang ierr = VecPlaceArray(ts->vec_drdp_col,xarr);CHKERRQ(ierr); 6303b711c3fSHong Zhang ierr = VecAXPY(ts->vecs_sensip[nadj],adjoint_time_step*(1.0-th->Theta),ts->vec_drdp_col);CHKERRQ(ierr); 6313b711c3fSHong Zhang ierr = VecResetArray(ts->vec_drdp_col);CHKERRQ(ierr); 6323b711c3fSHong Zhang ierr = MatDenseRestoreColumn(quadJp,&xarr);CHKERRQ(ierr); 6333b711c3fSHong Zhang } 63433f72c5dSHong Zhang if (ts->vecs_sensi2p) { /* second-order */ 63533f72c5dSHong Zhang /* Get w1 at t_n from TLM matrix */ 63633f72c5dSHong Zhang ierr = MatDenseGetColumn(th->MatFwdSensip0,0,&xarr);CHKERRQ(ierr); 63733f72c5dSHong Zhang ierr = VecPlaceArray(ts->vec_sensip_col,xarr);CHKERRQ(ierr); 638b5b4017aSHong Zhang /* lambda_s^T F_PU w_1 */ 6391a352fa8SHong Zhang ierr = TSComputeIHessianProductFunctionPU(ts,adjoint_ptime,th->X0,VecsDeltaLam,ts->vec_sensip_col,ts->vecs_fpu);CHKERRQ(ierr); 64033f72c5dSHong Zhang ierr = VecResetArray(ts->vec_sensip_col);CHKERRQ(ierr); 64133f72c5dSHong Zhang ierr = MatDenseRestoreColumn(th->MatFwdSensip0,&xarr);CHKERRQ(ierr); 642b5b4017aSHong Zhang /* lambda_s^T F_PP w_2 */ 6431a352fa8SHong Zhang ierr = TSComputeIHessianProductFunctionPP(ts,adjoint_ptime,th->X0,VecsDeltaLam,ts->vec_dir,ts->vecs_fpp);CHKERRQ(ierr); 644b5b4017aSHong Zhang for (nadj=0; nadj<ts->numcost; nadj++) { 64533f72c5dSHong 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) */ 646b5b4017aSHong Zhang ierr = MatMultTranspose(ts->Jacp,VecsDeltaLam2[nadj],VecsDeltaMu2[nadj]);CHKERRQ(ierr); 6471a352fa8SHong Zhang ierr = VecAXPY(ts->vecs_sensi2p[nadj],-adjoint_time_step*(1.0-th->Theta),VecsDeltaMu2[nadj]);CHKERRQ(ierr); 648b5b4017aSHong Zhang if (ts->vecs_fpu) { 6491a352fa8SHong Zhang ierr = VecAXPY(ts->vecs_sensi2p[nadj],-adjoint_time_step*(1.0-th->Theta),ts->vecs_fpu[nadj]);CHKERRQ(ierr); 650b5e0532dSHong Zhang } 651b5b4017aSHong Zhang if (ts->vecs_fpp) { 6521a352fa8SHong Zhang ierr = VecAXPY(ts->vecs_sensi2p[nadj],-adjoint_time_step*(1.0-th->Theta),ts->vecs_fpp[nadj]);CHKERRQ(ierr); 653b5b4017aSHong Zhang } 65436eaed60SHong Zhang } 65536eaed60SHong Zhang } 6563fd52205SHong Zhang } 657b5e0532dSHong Zhang } 6583fd52205SHong Zhang } else { /* one-stage case */ 6593e05ceb1SHong Zhang th->shift = 0.0; 66004f7482eSHong Zhang ierr = TSComputeSNESJacobian(ts,th->X,J,Jpre);CHKERRQ(ierr); /* get -f_y */ 66104f7482eSHong Zhang ierr = KSPSetOperators(ksp,J,Jpre);CHKERRQ(ierr); 6627207e0fdSHong Zhang if (quadts) { 663cd4cee2dSHong Zhang ierr = TSComputeRHSJacobian(quadts,th->stage_time,th->X,quadJ,NULL);CHKERRQ(ierr); 6647207e0fdSHong Zhang } 665abc2977eSBarry Smith for (nadj=0; nadj<ts->numcost; nadj++) { 666b5e0532dSHong Zhang ierr = MatMultTranspose(J,VecsDeltaLam[nadj],VecsSensiTemp[nadj]);CHKERRQ(ierr); 6671a352fa8SHong Zhang ierr = VecAXPY(ts->vecs_sensi[nadj],-adjoint_time_step,VecsSensiTemp[nadj]);CHKERRQ(ierr); 668cd4cee2dSHong Zhang if (quadJ) { 669cd4cee2dSHong Zhang ierr = MatDenseGetColumn(quadJ,nadj,&xarr);CHKERRQ(ierr); 670cd4cee2dSHong Zhang ierr = VecPlaceArray(ts->vec_drdu_col,xarr);CHKERRQ(ierr); 6711a352fa8SHong Zhang ierr = VecAXPY(ts->vecs_sensi[nadj],adjoint_time_step,ts->vec_drdu_col);CHKERRQ(ierr); 672cd4cee2dSHong Zhang ierr = VecResetArray(ts->vec_drdu_col);CHKERRQ(ierr); 673cd4cee2dSHong Zhang ierr = MatDenseRestoreColumn(quadJ,&xarr);CHKERRQ(ierr); 67436eaed60SHong Zhang } 6752ca6e920SHong Zhang } 6763fd52205SHong Zhang if (ts->vecs_sensip) { 67782ad9101SHong Zhang th->shift = 1.0/(adjoint_time_step*th->Theta); 67882ad9101SHong Zhang ierr = VecAXPBYPCZ(th->Xdot,-th->shift,th->shift,0,th->X0,th->X);CHKERRQ(ierr); 6793e05ceb1SHong Zhang ierr = TSComputeIJacobianP(ts,th->stage_time,th->X,th->Xdot,th->shift,ts->Jacp,PETSC_FALSE);CHKERRQ(ierr); 6807207e0fdSHong Zhang if (quadts) { 681cd4cee2dSHong Zhang ierr = TSComputeRHSJacobianP(quadts,th->stage_time,th->X,quadJp);CHKERRQ(ierr); 6827207e0fdSHong Zhang } 683abc2977eSBarry Smith for (nadj=0; nadj<ts->numcost; nadj++) { 68433f72c5dSHong Zhang ierr = MatMultTranspose(ts->Jacp,VecsDeltaLam[nadj],VecsDeltaMu[nadj]);CHKERRQ(ierr); 6851a352fa8SHong Zhang ierr = VecAXPY(ts->vecs_sensip[nadj],-adjoint_time_step,VecsDeltaMu[nadj]);CHKERRQ(ierr); 686cd4cee2dSHong Zhang if (quadJp) { 687cd4cee2dSHong Zhang ierr = MatDenseGetColumn(quadJp,nadj,&xarr);CHKERRQ(ierr); 688cd4cee2dSHong Zhang ierr = VecPlaceArray(ts->vec_drdp_col,xarr);CHKERRQ(ierr); 6891a352fa8SHong Zhang ierr = VecAXPY(ts->vecs_sensip[nadj],adjoint_time_step,ts->vec_drdp_col);CHKERRQ(ierr); 690cd4cee2dSHong Zhang ierr = VecResetArray(ts->vec_drdp_col);CHKERRQ(ierr); 691cd4cee2dSHong Zhang ierr = MatDenseRestoreColumn(quadJp,&xarr);CHKERRQ(ierr); 69236eaed60SHong Zhang } 69336eaed60SHong Zhang } 6943fd52205SHong Zhang } 6952ca6e920SHong Zhang } 6962ca6e920SHong Zhang 6972ca6e920SHong Zhang th->status = TS_STEP_COMPLETE; 6982ca6e920SHong Zhang PetscFunctionReturn(0); 6992ca6e920SHong Zhang } 7002ca6e920SHong Zhang 701cd652676SJed Brown static PetscErrorCode TSInterpolate_Theta(TS ts,PetscReal t,Vec X) 702cd652676SJed Brown { 703cd652676SJed Brown TS_Theta *th = (TS_Theta*)ts->data; 704be5899b3SLisandro Dalcin PetscReal dt = t - ts->ptime; 705cd652676SJed Brown PetscErrorCode ierr; 706cd652676SJed Brown 707cd652676SJed Brown PetscFunctionBegin; 708a43b19c4SJed Brown ierr = VecCopy(ts->vec_sol,th->X);CHKERRQ(ierr); 709be5899b3SLisandro Dalcin if (th->endpoint) dt *= th->Theta; 710be5899b3SLisandro Dalcin ierr = VecWAXPY(X,dt,th->Xdot,th->X);CHKERRQ(ierr); 711cd652676SJed Brown PetscFunctionReturn(0); 712cd652676SJed Brown } 713cd652676SJed Brown 7141566a47fSLisandro Dalcin static PetscErrorCode TSEvaluateWLTE_Theta(TS ts,NormType wnormtype,PetscInt *order,PetscReal *wlte) 7151566a47fSLisandro Dalcin { 7161566a47fSLisandro Dalcin TS_Theta *th = (TS_Theta*)ts->data; 7171566a47fSLisandro Dalcin Vec X = ts->vec_sol; /* X = solution */ 7181566a47fSLisandro Dalcin Vec Y = th->vec_lte_work; /* Y = X + LTE */ 7197453f775SEmil Constantinescu PetscReal wltea,wlter; 7201566a47fSLisandro Dalcin PetscErrorCode ierr; 7211566a47fSLisandro Dalcin 7221566a47fSLisandro Dalcin PetscFunctionBegin; 7232ffb9264SLisandro Dalcin if (!th->vec_sol_prev) {*wlte = -1; PetscFunctionReturn(0);} 7241566a47fSLisandro Dalcin /* Cannot compute LTE in first step or in restart after event */ 725fecfb714SLisandro Dalcin if (ts->steprestart) {*wlte = -1; PetscFunctionReturn(0);} 7261566a47fSLisandro Dalcin /* Compute LTE using backward differences with non-constant time step */ 727fecfb714SLisandro Dalcin { 728be5899b3SLisandro Dalcin PetscReal h = ts->time_step, h_prev = ts->ptime - ts->ptime_prev; 729be5899b3SLisandro Dalcin PetscReal a = 1 + h_prev/h; 7301566a47fSLisandro Dalcin PetscScalar scal[3]; Vec vecs[3]; 7311566a47fSLisandro Dalcin scal[0] = +1/a; scal[1] = -1/(a-1); scal[2] = +1/(a*(a-1)); 7321566a47fSLisandro Dalcin vecs[0] = X; vecs[1] = th->X0; vecs[2] = th->vec_sol_prev; 7331566a47fSLisandro Dalcin ierr = VecCopy(X,Y);CHKERRQ(ierr); 7341566a47fSLisandro Dalcin ierr = VecMAXPY(Y,3,scal,vecs);CHKERRQ(ierr); 7357453f775SEmil Constantinescu ierr = TSErrorWeightedNorm(ts,X,Y,wnormtype,wlte,&wltea,&wlter);CHKERRQ(ierr); 7361566a47fSLisandro Dalcin } 7371566a47fSLisandro Dalcin if (order) *order = 2; 7381566a47fSLisandro Dalcin PetscFunctionReturn(0); 7391566a47fSLisandro Dalcin } 7401566a47fSLisandro Dalcin 7411566a47fSLisandro Dalcin static PetscErrorCode TSRollBack_Theta(TS ts) 7421566a47fSLisandro Dalcin { 7431566a47fSLisandro Dalcin TS_Theta *th = (TS_Theta*)ts->data; 7447207e0fdSHong Zhang TS quadts = ts->quadraturets; 7451566a47fSLisandro Dalcin PetscErrorCode ierr; 7461566a47fSLisandro Dalcin 7471566a47fSLisandro Dalcin PetscFunctionBegin; 7481566a47fSLisandro Dalcin ierr = VecCopy(th->X0,ts->vec_sol);CHKERRQ(ierr); 749cd4cee2dSHong Zhang if (quadts && ts->costintegralfwd) { 750cd4cee2dSHong Zhang ierr = VecCopy(th->VecCostIntegral0,quadts->vec_sol);CHKERRQ(ierr); 7511566a47fSLisandro Dalcin } 752715f1b00SHong Zhang th->status = TS_STEP_INCOMPLETE; 75313b1b0ffSHong Zhang if (ts->mat_sensip) { 75413b1b0ffSHong Zhang ierr = MatCopy(th->MatFwdSensip0,ts->mat_sensip,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 7556f92202bSHong Zhang } 7567207e0fdSHong Zhang if (quadts && quadts->mat_sensip) { 7577207e0fdSHong Zhang ierr = MatCopy(th->MatIntegralSensip0,quadts->mat_sensip,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 7586f92202bSHong Zhang } 759715f1b00SHong Zhang PetscFunctionReturn(0); 760715f1b00SHong Zhang } 761715f1b00SHong Zhang 762715f1b00SHong Zhang static PetscErrorCode TSForwardStep_Theta(TS ts) 763715f1b00SHong Zhang { 764715f1b00SHong Zhang TS_Theta *th = (TS_Theta*)ts->data; 765cd4cee2dSHong Zhang TS quadts = ts->quadraturets; 76613b1b0ffSHong Zhang Mat MatDeltaFwdSensip = th->MatDeltaFwdSensip; 767b5b4017aSHong Zhang Vec VecDeltaFwdSensipCol = th->VecDeltaFwdSensipCol; 7687207e0fdSHong Zhang PetscInt ntlm; 769715f1b00SHong Zhang KSP ksp; 7707207e0fdSHong Zhang Mat J,Jpre,quadJ = NULL,quadJp = NULL; 77113b1b0ffSHong Zhang PetscScalar *barr,*xarr; 7721a352fa8SHong Zhang PetscReal previous_shift; 773715f1b00SHong Zhang PetscErrorCode ierr; 774715f1b00SHong Zhang 775715f1b00SHong Zhang PetscFunctionBegin; 7761a352fa8SHong Zhang previous_shift = th->shift; 77713b1b0ffSHong Zhang ierr = MatCopy(ts->mat_sensip,th->MatFwdSensip0,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 77813b1b0ffSHong Zhang 7797207e0fdSHong Zhang if (quadts && quadts->mat_sensip) { 7807207e0fdSHong Zhang ierr = MatCopy(quadts->mat_sensip,th->MatIntegralSensip0,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 7816f92202bSHong Zhang } 782715f1b00SHong Zhang ierr = SNESGetKSP(ts->snes,&ksp);CHKERRQ(ierr); 783cd4cee2dSHong Zhang ierr = TSGetIJacobian(ts,&J,&Jpre,NULL,NULL);CHKERRQ(ierr); 7847207e0fdSHong Zhang if (quadts) { 785cd4cee2dSHong Zhang ierr = TSGetRHSJacobian(quadts,&quadJ,NULL,NULL,NULL);CHKERRQ(ierr); 786cd4cee2dSHong Zhang ierr = TSGetRHSJacobianP(quadts,&quadJp,NULL,NULL);CHKERRQ(ierr); 7877207e0fdSHong Zhang } 788715f1b00SHong Zhang 789715f1b00SHong Zhang /* Build RHS */ 790715f1b00SHong Zhang if (th->endpoint) { /* 2-stage method*/ 7911a352fa8SHong Zhang th->shift = 1./((th->Theta-1.)*th->time_step0); 7921a352fa8SHong Zhang ierr = TSComputeIJacobian(ts,th->ptime0,th->X0,th->Xdot,th->shift,J,Jpre,PETSC_FALSE);CHKERRQ(ierr); 79313b1b0ffSHong Zhang ierr = MatMatMult(J,ts->mat_sensip,MAT_REUSE_MATRIX,PETSC_DEFAULT,&MatDeltaFwdSensip);CHKERRQ(ierr); 79413b1b0ffSHong Zhang ierr = MatScale(MatDeltaFwdSensip,(th->Theta-1.)/th->Theta);CHKERRQ(ierr); 795715f1b00SHong Zhang 796022c081aSHong Zhang /* Add the f_p forcing terms */ 7970e11c21fSHong Zhang if (ts->Jacp) { 79882ad9101SHong Zhang ierr = VecZeroEntries(th->Xdot);CHKERRQ(ierr); 7991a352fa8SHong Zhang ierr = TSComputeIJacobianP(ts,th->ptime0,th->X0,th->Xdot,th->shift,ts->Jacp,PETSC_FALSE);CHKERRQ(ierr); 80033f72c5dSHong Zhang ierr = MatAXPY(MatDeltaFwdSensip,(th->Theta-1.)/th->Theta,ts->Jacp,SUBSET_NONZERO_PATTERN);CHKERRQ(ierr); 80182ad9101SHong Zhang th->shift = previous_shift; 80282ad9101SHong Zhang ierr = VecAXPBYPCZ(th->Xdot,-th->shift,th->shift,0,th->X0,ts->vec_sol);CHKERRQ(ierr); 8033e05ceb1SHong Zhang ierr = TSComputeIJacobianP(ts,th->stage_time,ts->vec_sol,th->Xdot,th->shift,ts->Jacp,PETSC_FALSE);CHKERRQ(ierr); 80433f72c5dSHong Zhang ierr = MatAXPY(MatDeltaFwdSensip,-1.,ts->Jacp,SUBSET_NONZERO_PATTERN);CHKERRQ(ierr); 8050e11c21fSHong Zhang } 806715f1b00SHong Zhang } else { /* 1-stage method */ 8073e05ceb1SHong Zhang th->shift = 0.0; 8083e05ceb1SHong Zhang ierr = TSComputeIJacobian(ts,th->stage_time,th->X,th->Xdot,th->shift,J,Jpre,PETSC_FALSE);CHKERRQ(ierr); 80913b1b0ffSHong Zhang ierr = MatMatMult(J,ts->mat_sensip,MAT_REUSE_MATRIX,PETSC_DEFAULT,&MatDeltaFwdSensip);CHKERRQ(ierr); 81013b1b0ffSHong Zhang ierr = MatScale(MatDeltaFwdSensip,-1.);CHKERRQ(ierr); 81113b1b0ffSHong Zhang 812022c081aSHong Zhang /* Add the f_p forcing terms */ 8130e11c21fSHong Zhang if (ts->Jacp) { 81482ad9101SHong Zhang th->shift = previous_shift; 81582ad9101SHong Zhang ierr = VecAXPBYPCZ(th->Xdot,-th->shift,th->shift,0,th->X0,th->X);CHKERRQ(ierr); 8163e05ceb1SHong Zhang ierr = TSComputeIJacobianP(ts,th->stage_time,th->X,th->Xdot,th->shift,ts->Jacp,PETSC_FALSE);CHKERRQ(ierr); 81733f72c5dSHong Zhang ierr = MatAXPY(MatDeltaFwdSensip,-1.,ts->Jacp,SUBSET_NONZERO_PATTERN);CHKERRQ(ierr); 818715f1b00SHong Zhang } 8190e11c21fSHong Zhang } 820715f1b00SHong Zhang 821715f1b00SHong Zhang /* Build LHS */ 8221a352fa8SHong Zhang th->shift = previous_shift; /* recover the previous shift used in TSStep_Theta() */ 823715f1b00SHong Zhang if (th->endpoint) { 8243e05ceb1SHong Zhang ierr = TSComputeIJacobian(ts,th->stage_time,ts->vec_sol,th->Xdot,th->shift,J,Jpre,PETSC_FALSE);CHKERRQ(ierr); 825715f1b00SHong Zhang } else { 8263e05ceb1SHong Zhang ierr = TSComputeIJacobian(ts,th->stage_time,th->X,th->Xdot,th->shift,J,Jpre,PETSC_FALSE);CHKERRQ(ierr); 827715f1b00SHong Zhang } 828cd4cee2dSHong Zhang ierr = KSPSetOperators(ksp,J,Jpre);CHKERRQ(ierr); 829715f1b00SHong Zhang 830715f1b00SHong Zhang /* 831715f1b00SHong Zhang Evaluate the first stage of integral gradients with the 2-stage method: 832c9ad9de0SHong Zhang drdu|t_n*S(t_n) + drdp|t_n 833715f1b00SHong Zhang This is done before the linear solve because the sensitivity variable S(t_n) will be propagated to S(t_{n+1}) 834715f1b00SHong Zhang */ 835715f1b00SHong Zhang if (th->endpoint) { /* 2-stage method only */ 8367207e0fdSHong Zhang if (quadts && quadts->mat_sensip) { 8371a352fa8SHong Zhang ierr = TSComputeRHSJacobian(quadts,th->ptime0,th->X0,quadJ,NULL);CHKERRQ(ierr); 8381a352fa8SHong Zhang ierr = TSComputeRHSJacobianP(quadts,th->ptime0,th->X0,quadJp);CHKERRQ(ierr); 8397207e0fdSHong Zhang ierr = MatTransposeMatMult(ts->mat_sensip,quadJ,MAT_REUSE_MATRIX,PETSC_DEFAULT,&th->MatIntegralSensipTemp);CHKERRQ(ierr); 8407207e0fdSHong Zhang ierr = MatAXPY(th->MatIntegralSensipTemp,1,quadJp,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 8411a352fa8SHong Zhang ierr = MatAXPY(quadts->mat_sensip,th->time_step0*(1.-th->Theta),th->MatIntegralSensipTemp,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 842715f1b00SHong Zhang } 843715f1b00SHong Zhang } 844715f1b00SHong Zhang 845715f1b00SHong Zhang /* Solve the tangent linear equation for forward sensitivities to parameters */ 846022c081aSHong Zhang for (ntlm=0; ntlm<th->num_tlm; ntlm++) { 847b5b4017aSHong Zhang KSPConvergedReason kspreason; 84813b1b0ffSHong Zhang ierr = MatDenseGetColumn(MatDeltaFwdSensip,ntlm,&barr);CHKERRQ(ierr); 849b5b4017aSHong Zhang ierr = VecPlaceArray(VecDeltaFwdSensipCol,barr);CHKERRQ(ierr); 850715f1b00SHong Zhang if (th->endpoint) { 85113b1b0ffSHong Zhang ierr = MatDenseGetColumn(ts->mat_sensip,ntlm,&xarr);CHKERRQ(ierr); 852b5b4017aSHong Zhang ierr = VecPlaceArray(ts->vec_sensip_col,xarr);CHKERRQ(ierr); 853b5b4017aSHong Zhang ierr = KSPSolve(ksp,VecDeltaFwdSensipCol,ts->vec_sensip_col);CHKERRQ(ierr); 854b5b4017aSHong Zhang ierr = VecResetArray(ts->vec_sensip_col);CHKERRQ(ierr); 85513b1b0ffSHong Zhang ierr = MatDenseRestoreColumn(ts->mat_sensip,&xarr);CHKERRQ(ierr); 856715f1b00SHong Zhang } else { 857b5b4017aSHong Zhang ierr = KSPSolve(ksp,VecDeltaFwdSensipCol,VecDeltaFwdSensipCol);CHKERRQ(ierr); 858715f1b00SHong Zhang } 859b5b4017aSHong Zhang ierr = KSPGetConvergedReason(ksp,&kspreason);CHKERRQ(ierr); 860b5b4017aSHong Zhang if (kspreason < 0) { 861b5b4017aSHong Zhang ts->reason = TSFORWARD_DIVERGED_LINEAR_SOLVE; 862b5b4017aSHong Zhang ierr = PetscInfo2(ts,"Step=%D, %Dth tangent linear solve, linear solve fails, stopping tangent linear solve\n",ts->steps,ntlm);CHKERRQ(ierr); 863b5b4017aSHong Zhang } 864b5b4017aSHong Zhang ierr = VecResetArray(VecDeltaFwdSensipCol);CHKERRQ(ierr); 86513b1b0ffSHong Zhang ierr = MatDenseRestoreColumn(MatDeltaFwdSensip,&barr);CHKERRQ(ierr); 866715f1b00SHong Zhang } 867715f1b00SHong Zhang 86813b1b0ffSHong Zhang /* 86913b1b0ffSHong Zhang Evaluate the second stage of integral gradients with the 2-stage method: 870c9ad9de0SHong Zhang drdu|t_{n+1}*S(t_{n+1}) + drdp|t_{n+1} 87113b1b0ffSHong Zhang */ 8727207e0fdSHong Zhang if (quadts && quadts->mat_sensip) { 87313b1b0ffSHong Zhang if (!th->endpoint) { 8747207e0fdSHong Zhang ierr = MatAXPY(ts->mat_sensip,1,MatDeltaFwdSensip,SAME_NONZERO_PATTERN);CHKERRQ(ierr); /* stage sensitivity */ 875cd4cee2dSHong Zhang ierr = TSComputeRHSJacobian(quadts,th->stage_time,th->X,quadJ,NULL);CHKERRQ(ierr); 876cd4cee2dSHong Zhang ierr = TSComputeRHSJacobianP(quadts,th->stage_time,th->X,quadJp);CHKERRQ(ierr); 8777207e0fdSHong Zhang ierr = MatTransposeMatMult(ts->mat_sensip,quadJ,MAT_REUSE_MATRIX,PETSC_DEFAULT,&th->MatIntegralSensipTemp);CHKERRQ(ierr); 8787207e0fdSHong Zhang ierr = MatAXPY(th->MatIntegralSensipTemp,1,quadJp,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 8791a352fa8SHong Zhang ierr = MatAXPY(quadts->mat_sensip,th->time_step0,th->MatIntegralSensipTemp,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 88013b1b0ffSHong Zhang ierr = MatAXPY(ts->mat_sensip,(1.-th->Theta)/th->Theta,MatDeltaFwdSensip,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 88113b1b0ffSHong Zhang } else { 882cd4cee2dSHong Zhang ierr = TSComputeRHSJacobian(quadts,th->stage_time,ts->vec_sol,quadJ,NULL);CHKERRQ(ierr); 883cd4cee2dSHong Zhang ierr = TSComputeRHSJacobianP(quadts,th->stage_time,ts->vec_sol,quadJp);CHKERRQ(ierr); 8847207e0fdSHong Zhang ierr = MatTransposeMatMult(ts->mat_sensip,quadJ,MAT_REUSE_MATRIX,PETSC_DEFAULT,&th->MatIntegralSensipTemp);CHKERRQ(ierr); 8857207e0fdSHong Zhang ierr = MatAXPY(th->MatIntegralSensipTemp,1,quadJp,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 8861a352fa8SHong Zhang ierr = MatAXPY(quadts->mat_sensip,th->time_step0*th->Theta,th->MatIntegralSensipTemp,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 88713b1b0ffSHong Zhang } 88813b1b0ffSHong Zhang } else { 88913b1b0ffSHong Zhang if (!th->endpoint) { 89013b1b0ffSHong Zhang ierr = MatAXPY(ts->mat_sensip,1./th->Theta,MatDeltaFwdSensip,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 891715f1b00SHong Zhang } 892715f1b00SHong Zhang } 8931566a47fSLisandro Dalcin PetscFunctionReturn(0); 8941566a47fSLisandro Dalcin } 8951566a47fSLisandro Dalcin 896*cc4f23bcSHong Zhang static PetscErrorCode TSForwardGetStages_Theta(TS ts,PetscInt *ns,Mat *stagesensip[]) 8976affb6f8SHong Zhang { 8986affb6f8SHong Zhang TS_Theta *th = (TS_Theta*)ts->data; 8996affb6f8SHong Zhang 9006affb6f8SHong Zhang PetscFunctionBegin; 901*cc4f23bcSHong Zhang if (ns) *ns = 2; 9025072d23cSHong Zhang if (stagesensip) { 903*cc4f23bcSHong Zhang if (!th->endpoint && th->Theta != 1.0) { 904*cc4f23bcSHong Zhang th->MatFwdStages[0] = th->MatFwdSensip0; 905*cc4f23bcSHong Zhang th->MatFwdStages[1] = th->MatDeltaFwdSensip; 906*cc4f23bcSHong Zhang } else { 907*cc4f23bcSHong Zhang th->MatFwdStages[0] = th->MatFwdSensip0; 908*cc4f23bcSHong Zhang th->MatFwdStages[1] = ts->mat_sensip; /* stiffly accurate */ 909*cc4f23bcSHong Zhang } 910*cc4f23bcSHong Zhang *stagesensip = th->MatFwdStages; 9115072d23cSHong Zhang } 9126affb6f8SHong Zhang PetscFunctionReturn(0); 9136affb6f8SHong Zhang } 9146affb6f8SHong Zhang 915316643e7SJed Brown /*------------------------------------------------------------*/ 916277b19d0SLisandro Dalcin static PetscErrorCode TSReset_Theta(TS ts) 917316643e7SJed Brown { 918316643e7SJed Brown TS_Theta *th = (TS_Theta*)ts->data; 919316643e7SJed Brown PetscErrorCode ierr; 920316643e7SJed Brown 921316643e7SJed Brown PetscFunctionBegin; 9226bf464f9SBarry Smith ierr = VecDestroy(&th->X);CHKERRQ(ierr); 9236bf464f9SBarry Smith ierr = VecDestroy(&th->Xdot);CHKERRQ(ierr); 9243b1890cdSShri Abhyankar ierr = VecDestroy(&th->X0);CHKERRQ(ierr); 925eb284becSJed Brown ierr = VecDestroy(&th->affine);CHKERRQ(ierr); 9261566a47fSLisandro Dalcin 9271566a47fSLisandro Dalcin ierr = VecDestroy(&th->vec_sol_prev);CHKERRQ(ierr); 9281566a47fSLisandro Dalcin ierr = VecDestroy(&th->vec_lte_work);CHKERRQ(ierr); 9291566a47fSLisandro Dalcin 930b1cb36f3SHong Zhang ierr = VecDestroy(&th->VecCostIntegral0);CHKERRQ(ierr); 931277b19d0SLisandro Dalcin PetscFunctionReturn(0); 932277b19d0SLisandro Dalcin } 933277b19d0SLisandro Dalcin 934ece46509SHong Zhang static PetscErrorCode TSAdjointReset_Theta(TS ts) 935ece46509SHong Zhang { 936ece46509SHong Zhang TS_Theta *th = (TS_Theta*)ts->data; 937ece46509SHong Zhang PetscErrorCode ierr; 938ece46509SHong Zhang 939ece46509SHong Zhang PetscFunctionBegin; 940ece46509SHong Zhang ierr = VecDestroyVecs(ts->numcost,&th->VecsDeltaLam);CHKERRQ(ierr); 941ece46509SHong Zhang ierr = VecDestroyVecs(ts->numcost,&th->VecsDeltaMu);CHKERRQ(ierr); 942ece46509SHong Zhang ierr = VecDestroyVecs(ts->numcost,&th->VecsDeltaLam2);CHKERRQ(ierr); 943ece46509SHong Zhang ierr = VecDestroyVecs(ts->numcost,&th->VecsDeltaMu2);CHKERRQ(ierr); 944ece46509SHong Zhang ierr = VecDestroyVecs(ts->numcost,&th->VecsSensiTemp);CHKERRQ(ierr); 945ece46509SHong Zhang ierr = VecDestroyVecs(ts->numcost,&th->VecsSensi2Temp);CHKERRQ(ierr); 946ece46509SHong Zhang PetscFunctionReturn(0); 947ece46509SHong Zhang } 948ece46509SHong Zhang 949277b19d0SLisandro Dalcin static PetscErrorCode TSDestroy_Theta(TS ts) 950277b19d0SLisandro Dalcin { 951277b19d0SLisandro Dalcin PetscErrorCode ierr; 952277b19d0SLisandro Dalcin 953277b19d0SLisandro Dalcin PetscFunctionBegin; 954277b19d0SLisandro Dalcin ierr = TSReset_Theta(ts);CHKERRQ(ierr); 955b3a6b972SJed Brown if (ts->dm) { 956b3a6b972SJed Brown ierr = DMCoarsenHookRemove(ts->dm,DMCoarsenHook_TSTheta,DMRestrictHook_TSTheta,ts);CHKERRQ(ierr); 957b3a6b972SJed Brown ierr = DMSubDomainHookRemove(ts->dm,DMSubDomainHook_TSTheta,DMSubDomainRestrictHook_TSTheta,ts);CHKERRQ(ierr); 958b3a6b972SJed Brown } 959277b19d0SLisandro Dalcin ierr = PetscFree(ts->data);CHKERRQ(ierr); 960bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)ts,"TSThetaGetTheta_C",NULL);CHKERRQ(ierr); 961bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)ts,"TSThetaSetTheta_C",NULL);CHKERRQ(ierr); 962bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)ts,"TSThetaGetEndpoint_C",NULL);CHKERRQ(ierr); 963bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)ts,"TSThetaSetEndpoint_C",NULL);CHKERRQ(ierr); 964316643e7SJed Brown PetscFunctionReturn(0); 965316643e7SJed Brown } 966316643e7SJed Brown 967316643e7SJed Brown /* 968316643e7SJed Brown This defines the nonlinear equation that is to be solved with SNES 9692b5a38e1SLisandro Dalcin G(U) = F[t0+Theta*dt, U, (U-U0)*shift] = 0 9700fd10508SMatthew Knepley 9710fd10508SMatthew Knepley Note that U here is the stage argument. This means that U = U_{n+1} only if endpoint = true, 9720fd10508SMatthew Knepley otherwise U = theta U_{n+1} + (1 - theta) U0, which for the case of implicit midpoint is 9730fd10508SMatthew Knepley U = (U_{n+1} + U0)/2 974316643e7SJed Brown */ 9750f5c6efeSJed Brown static PetscErrorCode SNESTSFormFunction_Theta(SNES snes,Vec x,Vec y,TS ts) 976316643e7SJed Brown { 977316643e7SJed Brown TS_Theta *th = (TS_Theta*)ts->data; 978316643e7SJed Brown PetscErrorCode ierr; 9797445fe48SJed Brown Vec X0,Xdot; 9807445fe48SJed Brown DM dm,dmsave; 9813e05ceb1SHong Zhang PetscReal shift = th->shift; 982316643e7SJed Brown 983316643e7SJed Brown PetscFunctionBegin; 9847445fe48SJed Brown ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 9855a3a76d0SJed Brown /* When using the endpoint variant, this is actually 1/Theta * Xdot */ 9867445fe48SJed Brown ierr = TSThetaGetX0AndXdot(ts,dm,&X0,&Xdot);CHKERRQ(ierr); 987494ce9fcSHong Zhang if (x != X0) { 988b296d7d5SJed Brown ierr = VecAXPBYPCZ(Xdot,-shift,shift,0,X0,x);CHKERRQ(ierr); 989494ce9fcSHong Zhang } else { 990494ce9fcSHong Zhang ierr = VecZeroEntries(Xdot);CHKERRQ(ierr); 991494ce9fcSHong Zhang } 9927445fe48SJed Brown /* DM monkey-business allows user code to call TSGetDM() inside of functions evaluated on levels of FAS */ 9937445fe48SJed Brown dmsave = ts->dm; 9947445fe48SJed Brown ts->dm = dm; 9957445fe48SJed Brown ierr = TSComputeIFunction(ts,th->stage_time,x,Xdot,y,PETSC_FALSE);CHKERRQ(ierr); 9967445fe48SJed Brown ts->dm = dmsave; 9970d0b770aSPeter Brune ierr = TSThetaRestoreX0AndXdot(ts,dm,&X0,&Xdot);CHKERRQ(ierr); 998316643e7SJed Brown PetscFunctionReturn(0); 999316643e7SJed Brown } 1000316643e7SJed Brown 1001d1e9a80fSBarry Smith static PetscErrorCode SNESTSFormJacobian_Theta(SNES snes,Vec x,Mat A,Mat B,TS ts) 1002316643e7SJed Brown { 1003316643e7SJed Brown TS_Theta *th = (TS_Theta*)ts->data; 1004316643e7SJed Brown PetscErrorCode ierr; 10057445fe48SJed Brown Vec Xdot; 10067445fe48SJed Brown DM dm,dmsave; 10073e05ceb1SHong Zhang PetscReal shift = th->shift; 1008316643e7SJed Brown 1009316643e7SJed Brown PetscFunctionBegin; 10107445fe48SJed Brown ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 1011be5899b3SLisandro Dalcin /* Xdot has already been computed in SNESTSFormFunction_Theta (SNES guarantees this) */ 10120298fd71SBarry Smith ierr = TSThetaGetX0AndXdot(ts,dm,NULL,&Xdot);CHKERRQ(ierr); 10137445fe48SJed Brown 10147445fe48SJed Brown dmsave = ts->dm; 10157445fe48SJed Brown ts->dm = dm; 1016d1e9a80fSBarry Smith ierr = TSComputeIJacobian(ts,th->stage_time,x,Xdot,shift,A,B,PETSC_FALSE);CHKERRQ(ierr); 10177445fe48SJed Brown ts->dm = dmsave; 10180298fd71SBarry Smith ierr = TSThetaRestoreX0AndXdot(ts,dm,NULL,&Xdot);CHKERRQ(ierr); 1019316643e7SJed Brown PetscFunctionReturn(0); 1020316643e7SJed Brown } 1021316643e7SJed Brown 1022715f1b00SHong Zhang static PetscErrorCode TSForwardSetUp_Theta(TS ts) 1023715f1b00SHong Zhang { 1024715f1b00SHong Zhang TS_Theta *th = (TS_Theta*)ts->data; 10257207e0fdSHong Zhang TS quadts = ts->quadraturets; 1026715f1b00SHong Zhang PetscErrorCode ierr; 1027715f1b00SHong Zhang 1028715f1b00SHong Zhang PetscFunctionBegin; 1029022c081aSHong Zhang /* combine sensitivities to parameters and sensitivities to initial values into one array */ 103013b1b0ffSHong Zhang th->num_tlm = ts->num_parameters; 103113b1b0ffSHong Zhang ierr = MatDuplicate(ts->mat_sensip,MAT_DO_NOT_COPY_VALUES,&th->MatDeltaFwdSensip);CHKERRQ(ierr); 10327207e0fdSHong Zhang if (quadts && quadts->mat_sensip) { 10337207e0fdSHong Zhang ierr = MatDuplicate(quadts->mat_sensip,MAT_DO_NOT_COPY_VALUES,&th->MatIntegralSensipTemp);CHKERRQ(ierr); 10347207e0fdSHong Zhang ierr = MatDuplicate(quadts->mat_sensip,MAT_DO_NOT_COPY_VALUES,&th->MatIntegralSensip0);CHKERRQ(ierr); 1035715f1b00SHong Zhang } 10366f92202bSHong Zhang /* backup sensitivity results for roll-backs */ 103713b1b0ffSHong Zhang ierr = MatDuplicate(ts->mat_sensip,MAT_DO_NOT_COPY_VALUES,&th->MatFwdSensip0);CHKERRQ(ierr); 103813b1b0ffSHong Zhang 1039b5b4017aSHong Zhang ierr = VecDuplicate(ts->vec_sol,&th->VecDeltaFwdSensipCol);CHKERRQ(ierr); 1040715f1b00SHong Zhang PetscFunctionReturn(0); 1041715f1b00SHong Zhang } 1042715f1b00SHong Zhang 10437adebddeSHong Zhang static PetscErrorCode TSForwardReset_Theta(TS ts) 10447adebddeSHong Zhang { 10457adebddeSHong Zhang TS_Theta *th = (TS_Theta*)ts->data; 10467207e0fdSHong Zhang TS quadts = ts->quadraturets; 10477adebddeSHong Zhang PetscErrorCode ierr; 10487adebddeSHong Zhang 10497adebddeSHong Zhang PetscFunctionBegin; 10507207e0fdSHong Zhang if (quadts && quadts->mat_sensip) { 10517207e0fdSHong Zhang ierr = MatDestroy(&th->MatIntegralSensipTemp);CHKERRQ(ierr); 10527207e0fdSHong Zhang ierr = MatDestroy(&th->MatIntegralSensip0);CHKERRQ(ierr); 10537adebddeSHong Zhang } 10547adebddeSHong Zhang ierr = VecDestroy(&th->VecDeltaFwdSensipCol);CHKERRQ(ierr); 10557adebddeSHong Zhang ierr = MatDestroy(&th->MatDeltaFwdSensip);CHKERRQ(ierr); 10567adebddeSHong Zhang ierr = MatDestroy(&th->MatFwdSensip0);CHKERRQ(ierr); 10577adebddeSHong Zhang PetscFunctionReturn(0); 10587adebddeSHong Zhang } 10597adebddeSHong Zhang 1060316643e7SJed Brown static PetscErrorCode TSSetUp_Theta(TS ts) 1061316643e7SJed Brown { 1062316643e7SJed Brown TS_Theta *th = (TS_Theta*)ts->data; 1063cd4cee2dSHong Zhang TS quadts = ts->quadraturets; 10642ffb9264SLisandro Dalcin PetscBool match; 1065316643e7SJed Brown PetscErrorCode ierr; 1066316643e7SJed Brown 1067316643e7SJed Brown PetscFunctionBegin; 1068cd4cee2dSHong Zhang if (!th->VecCostIntegral0 && quadts && ts->costintegralfwd) { /* back up cost integral */ 1069cd4cee2dSHong Zhang ierr = VecDuplicate(quadts->vec_sol,&th->VecCostIntegral0);CHKERRQ(ierr); 1070b1cb36f3SHong Zhang } 107139d13666SHong Zhang if (!th->X) { 1072316643e7SJed Brown ierr = VecDuplicate(ts->vec_sol,&th->X);CHKERRQ(ierr); 107339d13666SHong Zhang } 107439d13666SHong Zhang if (!th->Xdot) { 1075316643e7SJed Brown ierr = VecDuplicate(ts->vec_sol,&th->Xdot);CHKERRQ(ierr); 107639d13666SHong Zhang } 107739d13666SHong Zhang if (!th->X0) { 10783b1890cdSShri Abhyankar ierr = VecDuplicate(ts->vec_sol,&th->X0);CHKERRQ(ierr); 107939d13666SHong Zhang } 10801566a47fSLisandro Dalcin if (th->endpoint) { 10811566a47fSLisandro Dalcin ierr = VecDuplicate(ts->vec_sol,&th->affine);CHKERRQ(ierr); 10827445fe48SJed Brown } 10833b1890cdSShri Abhyankar 10841566a47fSLisandro Dalcin th->order = (th->Theta == 0.5) ? 2 : 1; 108520d49056SMatthew G. Knepley th->shift = 1/(th->Theta*ts->time_step); 10861566a47fSLisandro Dalcin 10871566a47fSLisandro Dalcin ierr = TSGetDM(ts,&ts->dm);CHKERRQ(ierr); 10881566a47fSLisandro Dalcin ierr = DMCoarsenHookAdd(ts->dm,DMCoarsenHook_TSTheta,DMRestrictHook_TSTheta,ts);CHKERRQ(ierr); 10891566a47fSLisandro Dalcin ierr = DMSubDomainHookAdd(ts->dm,DMSubDomainHook_TSTheta,DMSubDomainRestrictHook_TSTheta,ts);CHKERRQ(ierr); 10901566a47fSLisandro Dalcin 10911566a47fSLisandro Dalcin ierr = TSGetAdapt(ts,&ts->adapt);CHKERRQ(ierr); 10921566a47fSLisandro Dalcin ierr = TSAdaptCandidatesClear(ts->adapt);CHKERRQ(ierr); 10932ffb9264SLisandro Dalcin ierr = PetscObjectTypeCompare((PetscObject)ts->adapt,TSADAPTNONE,&match);CHKERRQ(ierr); 10942ffb9264SLisandro Dalcin if (!match) { 10951566a47fSLisandro Dalcin ierr = VecDuplicate(ts->vec_sol,&th->vec_sol_prev);CHKERRQ(ierr); 10961566a47fSLisandro Dalcin ierr = VecDuplicate(ts->vec_sol,&th->vec_lte_work);CHKERRQ(ierr); 10973b1890cdSShri Abhyankar } 10981566a47fSLisandro Dalcin ierr = TSGetSNES(ts,&ts->snes);CHKERRQ(ierr); 1099*cc4f23bcSHong Zhang 1100*cc4f23bcSHong Zhang ts->stifflyaccurate = (!th->endpoint && th->Theta != 1.0) ? PETSC_FALSE : PETSC_TRUE; 1101b4dd3bf9SBarry Smith PetscFunctionReturn(0); 1102b4dd3bf9SBarry Smith } 11030c7376e5SHong Zhang 1104b4dd3bf9SBarry Smith /*------------------------------------------------------------*/ 1105b4dd3bf9SBarry Smith 1106b4dd3bf9SBarry Smith static PetscErrorCode TSAdjointSetUp_Theta(TS ts) 1107b4dd3bf9SBarry Smith { 1108b4dd3bf9SBarry Smith TS_Theta *th = (TS_Theta*)ts->data; 1109b4dd3bf9SBarry Smith PetscErrorCode ierr; 1110b4dd3bf9SBarry Smith 1111b4dd3bf9SBarry Smith PetscFunctionBegin; 1112b5e0532dSHong Zhang ierr = VecDuplicateVecs(ts->vecs_sensi[0],ts->numcost,&th->VecsDeltaLam);CHKERRQ(ierr); 1113b5b4017aSHong Zhang ierr = VecDuplicateVecs(ts->vecs_sensi[0],ts->numcost,&th->VecsSensiTemp);CHKERRQ(ierr); 11142ca6e920SHong Zhang if (ts->vecs_sensip) { 1115b5e0532dSHong Zhang ierr = VecDuplicateVecs(ts->vecs_sensip[0],ts->numcost,&th->VecsDeltaMu);CHKERRQ(ierr); 11162ca6e920SHong Zhang } 1117b5b4017aSHong Zhang if (ts->vecs_sensi2) { 1118b5b4017aSHong Zhang ierr = VecDuplicateVecs(ts->vecs_sensi[0],ts->numcost,&th->VecsDeltaLam2);CHKERRQ(ierr); 1119b5b4017aSHong Zhang ierr = VecDuplicateVecs(ts->vecs_sensi2[0],ts->numcost,&th->VecsSensi2Temp);CHKERRQ(ierr); 112067633408SHong Zhang /* hack ts to make implicit TS solver work when users provide only explicit versions of callbacks (RHSFunction,RHSJacobian,RHSHessian etc.) */ 112167633408SHong Zhang if (!ts->ihessianproduct_fuu) ts->vecs_fuu = ts->vecs_guu; 112267633408SHong Zhang if (!ts->ihessianproduct_fup) ts->vecs_fup = ts->vecs_gup; 1123b5b4017aSHong Zhang } 1124c9681e5dSHong Zhang if (ts->vecs_sensi2p) { 1125c9681e5dSHong Zhang ierr = VecDuplicateVecs(ts->vecs_sensi2p[0],ts->numcost,&th->VecsDeltaMu2);CHKERRQ(ierr); 112667633408SHong Zhang /* hack ts to make implicit TS solver work when users provide only explicit versions of callbacks (RHSFunction,RHSJacobian,RHSHessian etc.) */ 112767633408SHong Zhang if (!ts->ihessianproduct_fpu) ts->vecs_fpu = ts->vecs_gpu; 112867633408SHong Zhang if (!ts->ihessianproduct_fpp) ts->vecs_fpp = ts->vecs_gpp; 1129b5b4017aSHong Zhang } 1130316643e7SJed Brown PetscFunctionReturn(0); 1131316643e7SJed Brown } 1132316643e7SJed Brown 11334416b707SBarry Smith static PetscErrorCode TSSetFromOptions_Theta(PetscOptionItems *PetscOptionsObject,TS ts) 1134316643e7SJed Brown { 1135316643e7SJed Brown TS_Theta *th = (TS_Theta*)ts->data; 1136316643e7SJed Brown PetscErrorCode ierr; 1137316643e7SJed Brown 1138316643e7SJed Brown PetscFunctionBegin; 1139e55864a3SBarry Smith ierr = PetscOptionsHead(PetscOptionsObject,"Theta ODE solver options");CHKERRQ(ierr); 1140316643e7SJed Brown { 11410298fd71SBarry Smith ierr = PetscOptionsReal("-ts_theta_theta","Location of stage (0<Theta<=1)","TSThetaSetTheta",th->Theta,&th->Theta,NULL);CHKERRQ(ierr); 11420298fd71SBarry 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); 114303842d09SLisandro 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); 1144316643e7SJed Brown } 1145316643e7SJed Brown ierr = PetscOptionsTail();CHKERRQ(ierr); 1146316643e7SJed Brown PetscFunctionReturn(0); 1147316643e7SJed Brown } 1148316643e7SJed Brown 1149316643e7SJed Brown static PetscErrorCode TSView_Theta(TS ts,PetscViewer viewer) 1150316643e7SJed Brown { 1151316643e7SJed Brown TS_Theta *th = (TS_Theta*)ts->data; 1152ace3abfcSBarry Smith PetscBool iascii; 1153316643e7SJed Brown PetscErrorCode ierr; 1154316643e7SJed Brown 1155316643e7SJed Brown PetscFunctionBegin; 1156251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 1157316643e7SJed Brown if (iascii) { 11587c8652ddSBarry Smith ierr = PetscViewerASCIIPrintf(viewer," Theta=%g\n",(double)th->Theta);CHKERRQ(ierr); 1159ace68cafSJed Brown ierr = PetscViewerASCIIPrintf(viewer," Extrapolation=%s\n",th->extrapolate ? "yes" : "no");CHKERRQ(ierr); 1160316643e7SJed Brown } 1161316643e7SJed Brown PetscFunctionReturn(0); 1162316643e7SJed Brown } 1163316643e7SJed Brown 1164560360afSLisandro Dalcin static PetscErrorCode TSThetaGetTheta_Theta(TS ts,PetscReal *theta) 11650de4c49aSJed Brown { 11660de4c49aSJed Brown TS_Theta *th = (TS_Theta*)ts->data; 11670de4c49aSJed Brown 11680de4c49aSJed Brown PetscFunctionBegin; 11690de4c49aSJed Brown *theta = th->Theta; 11700de4c49aSJed Brown PetscFunctionReturn(0); 11710de4c49aSJed Brown } 11720de4c49aSJed Brown 1173560360afSLisandro Dalcin static PetscErrorCode TSThetaSetTheta_Theta(TS ts,PetscReal theta) 11740de4c49aSJed Brown { 11750de4c49aSJed Brown TS_Theta *th = (TS_Theta*)ts->data; 11760de4c49aSJed Brown 11770de4c49aSJed Brown PetscFunctionBegin; 11787c8652ddSBarry Smith if (theta <= 0 || 1 < theta) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Theta %g not in range (0,1]",(double)theta); 11790de4c49aSJed Brown th->Theta = theta; 11801566a47fSLisandro Dalcin th->order = (th->Theta == 0.5) ? 2 : 1; 11810de4c49aSJed Brown PetscFunctionReturn(0); 11820de4c49aSJed Brown } 1183eb284becSJed Brown 1184560360afSLisandro Dalcin static PetscErrorCode TSThetaGetEndpoint_Theta(TS ts,PetscBool *endpoint) 118526f2ff8fSLisandro Dalcin { 118626f2ff8fSLisandro Dalcin TS_Theta *th = (TS_Theta*)ts->data; 118726f2ff8fSLisandro Dalcin 118826f2ff8fSLisandro Dalcin PetscFunctionBegin; 118926f2ff8fSLisandro Dalcin *endpoint = th->endpoint; 119026f2ff8fSLisandro Dalcin PetscFunctionReturn(0); 119126f2ff8fSLisandro Dalcin } 119226f2ff8fSLisandro Dalcin 1193560360afSLisandro Dalcin static PetscErrorCode TSThetaSetEndpoint_Theta(TS ts,PetscBool flg) 1194eb284becSJed Brown { 1195eb284becSJed Brown TS_Theta *th = (TS_Theta*)ts->data; 1196eb284becSJed Brown 1197eb284becSJed Brown PetscFunctionBegin; 1198eb284becSJed Brown th->endpoint = flg; 1199eb284becSJed Brown PetscFunctionReturn(0); 1200eb284becSJed Brown } 12010de4c49aSJed Brown 1202f9c1d6abSBarry Smith #if defined(PETSC_HAVE_COMPLEX) 1203f9c1d6abSBarry Smith static PetscErrorCode TSComputeLinearStability_Theta(TS ts,PetscReal xr,PetscReal xi,PetscReal *yr,PetscReal *yi) 1204f9c1d6abSBarry Smith { 1205f9c1d6abSBarry Smith PetscComplex z = xr + xi*PETSC_i,f; 1206f9c1d6abSBarry Smith TS_Theta *th = (TS_Theta*)ts->data; 12073fd8ae06SJed Brown const PetscReal one = 1.0; 1208f9c1d6abSBarry Smith 1209f9c1d6abSBarry Smith PetscFunctionBegin; 12103fd8ae06SJed Brown f = (one + (one - th->Theta)*z)/(one - th->Theta*z); 1211f9c1d6abSBarry Smith *yr = PetscRealPartComplex(f); 1212f9c1d6abSBarry Smith *yi = PetscImaginaryPartComplex(f); 1213f9c1d6abSBarry Smith PetscFunctionReturn(0); 1214f9c1d6abSBarry Smith } 1215f9c1d6abSBarry Smith #endif 1216f9c1d6abSBarry Smith 1217*cc4f23bcSHong Zhang static PetscErrorCode TSGetStages_Theta(TS ts,PetscInt *ns,Vec *Y[]) 121842682096SHong Zhang { 121942682096SHong Zhang TS_Theta *th = (TS_Theta*)ts->data; 122042682096SHong Zhang 122142682096SHong Zhang PetscFunctionBegin; 1222*cc4f23bcSHong Zhang if (ns) *ns = 2; 12235072d23cSHong Zhang if (Y) { 1224*cc4f23bcSHong Zhang if (!th->endpoint && th->Theta != 1.0) { 1225*cc4f23bcSHong Zhang th->Stages[0] = th->X0; /* useful for recovering Xdot, which is needed for sensitivity analysis of systems involving a parameterized mass matrix. */ 1226*cc4f23bcSHong Zhang th->Stages[1] = th->X; 1227*cc4f23bcSHong Zhang } else { 1228*cc4f23bcSHong Zhang th->Stages[0] = th->X0; 1229*cc4f23bcSHong Zhang th->Stages[1] = ts->vec_sol; /* stiffly accurate */ 1230*cc4f23bcSHong Zhang } 1231*cc4f23bcSHong Zhang *Y = th->Stages; 12325072d23cSHong Zhang } 123342682096SHong Zhang PetscFunctionReturn(0); 123442682096SHong Zhang } 1235f9c1d6abSBarry Smith 1236316643e7SJed Brown /* ------------------------------------------------------------ */ 1237316643e7SJed Brown /*MC 123896f5712cSJed Brown TSTHETA - DAE solver using the implicit Theta method 1239316643e7SJed Brown 1240316643e7SJed Brown Level: beginner 1241316643e7SJed Brown 12424eb428fdSBarry Smith Options Database: 1243c82ed962SBarry Smith + -ts_theta_theta <Theta> - Location of stage (0<Theta<=1) 1244c82ed962SBarry Smith . -ts_theta_endpoint <flag> - Use the endpoint (like Crank-Nicholson) instead of midpoint form of the Theta method 124503842d09SLisandro Dalcin - -ts_theta_initial_guess_extrapolate <flg> - Extrapolate stage initial guess from previous solution (sometimes unstable) 12464eb428fdSBarry Smith 1247eb284becSJed Brown Notes: 12480c3ba866SJed Brown $ -ts_type theta -ts_theta_theta 1.0 corresponds to backward Euler (TSBEULER) 12490c3ba866SJed Brown $ -ts_type theta -ts_theta_theta 0.5 corresponds to the implicit midpoint rule 12504eb428fdSBarry Smith $ -ts_type theta -ts_theta_theta 0.5 -ts_theta_endpoint corresponds to Crank-Nicholson (TSCN) 12514eb428fdSBarry Smith 1252eb284becSJed Brown This method can be applied to DAE. 1253eb284becSJed Brown 1254eb284becSJed Brown This method is cast as a 1-stage implicit Runge-Kutta method. 1255eb284becSJed Brown 1256eb284becSJed Brown .vb 1257eb284becSJed Brown Theta | Theta 1258eb284becSJed Brown ------------- 1259eb284becSJed Brown | 1 1260eb284becSJed Brown .ve 1261eb284becSJed Brown 1262eb284becSJed Brown For the default Theta=0.5, this is also known as the implicit midpoint rule. 1263eb284becSJed Brown 1264eb284becSJed Brown When the endpoint variant is chosen, the method becomes a 2-stage method with first stage explicit: 1265eb284becSJed Brown 1266eb284becSJed Brown .vb 1267eb284becSJed Brown 0 | 0 0 1268eb284becSJed Brown 1 | 1-Theta Theta 1269eb284becSJed Brown ------------------- 1270eb284becSJed Brown | 1-Theta Theta 1271eb284becSJed Brown .ve 1272eb284becSJed Brown 1273eb284becSJed Brown For the default Theta=0.5, this is the trapezoid rule (also known as Crank-Nicolson, see TSCN). 1274eb284becSJed Brown 1275eb284becSJed Brown To apply a diagonally implicit RK method to DAE, the stage formula 1276eb284becSJed Brown 1277eb284becSJed Brown $ Y_i = X + h sum_j a_ij Y'_j 1278eb284becSJed Brown 12794eb428fdSBarry Smith is interpreted as a formula for Y'_i in terms of Y_i and known values (Y'_j, j<i) 1280eb284becSJed Brown 1281eb284becSJed Brown .seealso: TSCreate(), TS, TSSetType(), TSCN, TSBEULER, TSThetaSetTheta(), TSThetaSetEndpoint() 1282316643e7SJed Brown 1283316643e7SJed Brown M*/ 12848cc058d9SJed Brown PETSC_EXTERN PetscErrorCode TSCreate_Theta(TS ts) 1285316643e7SJed Brown { 1286316643e7SJed Brown TS_Theta *th; 1287316643e7SJed Brown PetscErrorCode ierr; 1288316643e7SJed Brown 1289316643e7SJed Brown PetscFunctionBegin; 1290277b19d0SLisandro Dalcin ts->ops->reset = TSReset_Theta; 1291ece46509SHong Zhang ts->ops->adjointreset = TSAdjointReset_Theta; 1292316643e7SJed Brown ts->ops->destroy = TSDestroy_Theta; 1293316643e7SJed Brown ts->ops->view = TSView_Theta; 1294316643e7SJed Brown ts->ops->setup = TSSetUp_Theta; 129542f2b339SBarry Smith ts->ops->adjointsetup = TSAdjointSetUp_Theta; 1296ece46509SHong Zhang ts->ops->adjointreset = TSAdjointReset_Theta; 1297316643e7SJed Brown ts->ops->step = TSStep_Theta; 1298cd652676SJed Brown ts->ops->interpolate = TSInterpolate_Theta; 12991566a47fSLisandro Dalcin ts->ops->evaluatewlte = TSEvaluateWLTE_Theta; 130024655328SShri ts->ops->rollback = TSRollBack_Theta; 1301316643e7SJed Brown ts->ops->setfromoptions = TSSetFromOptions_Theta; 13020f5c6efeSJed Brown ts->ops->snesfunction = SNESTSFormFunction_Theta; 13030f5c6efeSJed Brown ts->ops->snesjacobian = SNESTSFormJacobian_Theta; 1304f9c1d6abSBarry Smith #if defined(PETSC_HAVE_COMPLEX) 1305f9c1d6abSBarry Smith ts->ops->linearstability = TSComputeLinearStability_Theta; 1306f9c1d6abSBarry Smith #endif 130742682096SHong Zhang ts->ops->getstages = TSGetStages_Theta; 130842f2b339SBarry Smith ts->ops->adjointstep = TSAdjointStep_Theta; 1309b1cb36f3SHong Zhang ts->ops->adjointintegral = TSAdjointCostIntegral_Theta; 1310b1cb36f3SHong Zhang ts->ops->forwardintegral = TSForwardCostIntegral_Theta; 13112ffb9264SLisandro Dalcin ts->default_adapt_type = TSADAPTNONE; 13126affb6f8SHong Zhang 1313715f1b00SHong Zhang ts->ops->forwardsetup = TSForwardSetUp_Theta; 13147adebddeSHong Zhang ts->ops->forwardreset = TSForwardReset_Theta; 1315715f1b00SHong Zhang ts->ops->forwardstep = TSForwardStep_Theta; 13166affb6f8SHong Zhang ts->ops->forwardgetstages = TSForwardGetStages_Theta; 1317316643e7SJed Brown 1318efd4aadfSBarry Smith ts->usessnes = PETSC_TRUE; 1319efd4aadfSBarry Smith 1320b00a9115SJed Brown ierr = PetscNewLog(ts,&th);CHKERRQ(ierr); 1321316643e7SJed Brown ts->data = (void*)th; 1322316643e7SJed Brown 1323715f1b00SHong Zhang th->VecsDeltaLam = NULL; 1324715f1b00SHong Zhang th->VecsDeltaMu = NULL; 1325715f1b00SHong Zhang th->VecsSensiTemp = NULL; 1326b5b4017aSHong Zhang th->VecsSensi2Temp = NULL; 1327715f1b00SHong Zhang 13286f700aefSJed Brown th->extrapolate = PETSC_FALSE; 1329316643e7SJed Brown th->Theta = 0.5; 13301566a47fSLisandro Dalcin th->order = 2; 1331bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)ts,"TSThetaGetTheta_C",TSThetaGetTheta_Theta);CHKERRQ(ierr); 1332bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)ts,"TSThetaSetTheta_C",TSThetaSetTheta_Theta);CHKERRQ(ierr); 1333bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)ts,"TSThetaGetEndpoint_C",TSThetaGetEndpoint_Theta);CHKERRQ(ierr); 1334bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)ts,"TSThetaSetEndpoint_C",TSThetaSetEndpoint_Theta);CHKERRQ(ierr); 1335316643e7SJed Brown PetscFunctionReturn(0); 1336316643e7SJed Brown } 13370de4c49aSJed Brown 13380de4c49aSJed Brown /*@ 13390de4c49aSJed Brown TSThetaGetTheta - Get the abscissa of the stage in (0,1]. 13400de4c49aSJed Brown 13410de4c49aSJed Brown Not Collective 13420de4c49aSJed Brown 13430de4c49aSJed Brown Input Parameter: 13440de4c49aSJed Brown . ts - timestepping context 13450de4c49aSJed Brown 13460de4c49aSJed Brown Output Parameter: 13470de4c49aSJed Brown . theta - stage abscissa 13480de4c49aSJed Brown 13490de4c49aSJed Brown Note: 13500de4c49aSJed Brown Use of this function is normally only required to hack TSTHETA to use a modified integration scheme. 13510de4c49aSJed Brown 13520de4c49aSJed Brown Level: Advanced 13530de4c49aSJed Brown 13540de4c49aSJed Brown .seealso: TSThetaSetTheta() 13550de4c49aSJed Brown @*/ 13567087cfbeSBarry Smith PetscErrorCode TSThetaGetTheta(TS ts,PetscReal *theta) 13570de4c49aSJed Brown { 13584ac538c5SBarry Smith PetscErrorCode ierr; 13590de4c49aSJed Brown 13600de4c49aSJed Brown PetscFunctionBegin; 1361afb20b64SJed Brown PetscValidHeaderSpecific(ts,TS_CLASSID,1); 13620de4c49aSJed Brown PetscValidPointer(theta,2); 13634ac538c5SBarry Smith ierr = PetscUseMethod(ts,"TSThetaGetTheta_C",(TS,PetscReal*),(ts,theta));CHKERRQ(ierr); 13640de4c49aSJed Brown PetscFunctionReturn(0); 13650de4c49aSJed Brown } 13660de4c49aSJed Brown 13670de4c49aSJed Brown /*@ 13680de4c49aSJed Brown TSThetaSetTheta - Set the abscissa of the stage in (0,1]. 13690de4c49aSJed Brown 13700de4c49aSJed Brown Not Collective 13710de4c49aSJed Brown 13720de4c49aSJed Brown Input Parameter: 13730de4c49aSJed Brown + ts - timestepping context 13740de4c49aSJed Brown - theta - stage abscissa 13750de4c49aSJed Brown 13760de4c49aSJed Brown Options Database: 13770de4c49aSJed Brown . -ts_theta_theta <theta> 13780de4c49aSJed Brown 13790de4c49aSJed Brown Level: Intermediate 13800de4c49aSJed Brown 13810de4c49aSJed Brown .seealso: TSThetaGetTheta() 13820de4c49aSJed Brown @*/ 13837087cfbeSBarry Smith PetscErrorCode TSThetaSetTheta(TS ts,PetscReal theta) 13840de4c49aSJed Brown { 13854ac538c5SBarry Smith PetscErrorCode ierr; 13860de4c49aSJed Brown 13870de4c49aSJed Brown PetscFunctionBegin; 1388afb20b64SJed Brown PetscValidHeaderSpecific(ts,TS_CLASSID,1); 13894ac538c5SBarry Smith ierr = PetscTryMethod(ts,"TSThetaSetTheta_C",(TS,PetscReal),(ts,theta));CHKERRQ(ierr); 13900de4c49aSJed Brown PetscFunctionReturn(0); 13910de4c49aSJed Brown } 1392f33bbcb6SJed Brown 139326f2ff8fSLisandro Dalcin /*@ 139426f2ff8fSLisandro Dalcin TSThetaGetEndpoint - Gets whether to use the endpoint variant of the method (e.g. trapezoid/Crank-Nicolson instead of midpoint rule). 139526f2ff8fSLisandro Dalcin 139626f2ff8fSLisandro Dalcin Not Collective 139726f2ff8fSLisandro Dalcin 139826f2ff8fSLisandro Dalcin Input Parameter: 139926f2ff8fSLisandro Dalcin . ts - timestepping context 140026f2ff8fSLisandro Dalcin 140126f2ff8fSLisandro Dalcin Output Parameter: 140226f2ff8fSLisandro Dalcin . endpoint - PETSC_TRUE when using the endpoint variant 140326f2ff8fSLisandro Dalcin 140426f2ff8fSLisandro Dalcin Level: Advanced 140526f2ff8fSLisandro Dalcin 140626f2ff8fSLisandro Dalcin .seealso: TSThetaSetEndpoint(), TSTHETA, TSCN 140726f2ff8fSLisandro Dalcin @*/ 140826f2ff8fSLisandro Dalcin PetscErrorCode TSThetaGetEndpoint(TS ts,PetscBool *endpoint) 140926f2ff8fSLisandro Dalcin { 141026f2ff8fSLisandro Dalcin PetscErrorCode ierr; 141126f2ff8fSLisandro Dalcin 141226f2ff8fSLisandro Dalcin PetscFunctionBegin; 141326f2ff8fSLisandro Dalcin PetscValidHeaderSpecific(ts,TS_CLASSID,1); 141426f2ff8fSLisandro Dalcin PetscValidPointer(endpoint,2); 1415163d334eSBarry Smith ierr = PetscUseMethod(ts,"TSThetaGetEndpoint_C",(TS,PetscBool*),(ts,endpoint));CHKERRQ(ierr); 141626f2ff8fSLisandro Dalcin PetscFunctionReturn(0); 141726f2ff8fSLisandro Dalcin } 141826f2ff8fSLisandro Dalcin 1419eb284becSJed Brown /*@ 1420eb284becSJed Brown TSThetaSetEndpoint - Sets whether to use the endpoint variant of the method (e.g. trapezoid/Crank-Nicolson instead of midpoint rule). 1421eb284becSJed Brown 1422eb284becSJed Brown Not Collective 1423eb284becSJed Brown 1424eb284becSJed Brown Input Parameter: 1425eb284becSJed Brown + ts - timestepping context 1426eb284becSJed Brown - flg - PETSC_TRUE to use the endpoint variant 1427eb284becSJed Brown 1428eb284becSJed Brown Options Database: 1429eb284becSJed Brown . -ts_theta_endpoint <flg> 1430eb284becSJed Brown 1431eb284becSJed Brown Level: Intermediate 1432eb284becSJed Brown 1433eb284becSJed Brown .seealso: TSTHETA, TSCN 1434eb284becSJed Brown @*/ 1435eb284becSJed Brown PetscErrorCode TSThetaSetEndpoint(TS ts,PetscBool flg) 1436eb284becSJed Brown { 1437eb284becSJed Brown PetscErrorCode ierr; 1438eb284becSJed Brown 1439eb284becSJed Brown PetscFunctionBegin; 1440eb284becSJed Brown PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1441eb284becSJed Brown ierr = PetscTryMethod(ts,"TSThetaSetEndpoint_C",(TS,PetscBool),(ts,flg));CHKERRQ(ierr); 1442eb284becSJed Brown PetscFunctionReturn(0); 1443eb284becSJed Brown } 1444eb284becSJed Brown 1445f33bbcb6SJed Brown /* 1446f33bbcb6SJed Brown * TSBEULER and TSCN are straightforward specializations of TSTHETA. 1447f33bbcb6SJed Brown * The creation functions for these specializations are below. 1448f33bbcb6SJed Brown */ 1449f33bbcb6SJed Brown 14501566a47fSLisandro Dalcin static PetscErrorCode TSSetUp_BEuler(TS ts) 14511566a47fSLisandro Dalcin { 14521566a47fSLisandro Dalcin TS_Theta *th = (TS_Theta*)ts->data; 14531566a47fSLisandro Dalcin PetscErrorCode ierr; 14541566a47fSLisandro Dalcin 14551566a47fSLisandro Dalcin PetscFunctionBegin; 14561566a47fSLisandro 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"); 14571566a47fSLisandro 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"); 14581566a47fSLisandro Dalcin ierr = TSSetUp_Theta(ts);CHKERRQ(ierr); 14591566a47fSLisandro Dalcin PetscFunctionReturn(0); 14601566a47fSLisandro Dalcin } 14611566a47fSLisandro Dalcin 1462f33bbcb6SJed Brown static PetscErrorCode TSView_BEuler(TS ts,PetscViewer viewer) 1463f33bbcb6SJed Brown { 1464f33bbcb6SJed Brown PetscFunctionBegin; 1465f33bbcb6SJed Brown PetscFunctionReturn(0); 1466f33bbcb6SJed Brown } 1467f33bbcb6SJed Brown 1468f33bbcb6SJed Brown /*MC 1469f33bbcb6SJed Brown TSBEULER - ODE solver using the implicit backward Euler method 1470f33bbcb6SJed Brown 1471f33bbcb6SJed Brown Level: beginner 1472f33bbcb6SJed Brown 14734eb428fdSBarry Smith Notes: 1474c7eb6c99SShri Abhyankar TSBEULER is equivalent to TSTHETA with Theta=1.0 14754eb428fdSBarry Smith 14761566a47fSLisandro Dalcin $ -ts_type theta -ts_theta_theta 1.0 14774eb428fdSBarry Smith 1478f33bbcb6SJed Brown .seealso: TSCreate(), TS, TSSetType(), TSEULER, TSCN, TSTHETA 1479f33bbcb6SJed Brown 1480f33bbcb6SJed Brown M*/ 14818cc058d9SJed Brown PETSC_EXTERN PetscErrorCode TSCreate_BEuler(TS ts) 1482f33bbcb6SJed Brown { 1483f33bbcb6SJed Brown PetscErrorCode ierr; 1484f33bbcb6SJed Brown 1485f33bbcb6SJed Brown PetscFunctionBegin; 1486f33bbcb6SJed Brown ierr = TSCreate_Theta(ts);CHKERRQ(ierr); 1487f33bbcb6SJed Brown ierr = TSThetaSetTheta(ts,1.0);CHKERRQ(ierr); 14881566a47fSLisandro Dalcin ierr = TSThetaSetEndpoint(ts,PETSC_FALSE);CHKERRQ(ierr); 14890c7376e5SHong Zhang ts->ops->setup = TSSetUp_BEuler; 1490f33bbcb6SJed Brown ts->ops->view = TSView_BEuler; 1491f33bbcb6SJed Brown PetscFunctionReturn(0); 1492f33bbcb6SJed Brown } 1493f33bbcb6SJed Brown 14941566a47fSLisandro Dalcin static PetscErrorCode TSSetUp_CN(TS ts) 14951566a47fSLisandro Dalcin { 14961566a47fSLisandro Dalcin TS_Theta *th = (TS_Theta*)ts->data; 14971566a47fSLisandro Dalcin PetscErrorCode ierr; 14981566a47fSLisandro Dalcin 14991566a47fSLisandro Dalcin PetscFunctionBegin; 15001566a47fSLisandro 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"); 15011566a47fSLisandro 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"); 15021566a47fSLisandro Dalcin ierr = TSSetUp_Theta(ts);CHKERRQ(ierr); 15031566a47fSLisandro Dalcin PetscFunctionReturn(0); 15041566a47fSLisandro Dalcin } 15051566a47fSLisandro Dalcin 1506f33bbcb6SJed Brown static PetscErrorCode TSView_CN(TS ts,PetscViewer viewer) 1507f33bbcb6SJed Brown { 1508f33bbcb6SJed Brown PetscFunctionBegin; 1509f33bbcb6SJed Brown PetscFunctionReturn(0); 1510f33bbcb6SJed Brown } 1511f33bbcb6SJed Brown 1512f33bbcb6SJed Brown /*MC 1513f33bbcb6SJed Brown TSCN - ODE solver using the implicit Crank-Nicolson method. 1514f33bbcb6SJed Brown 1515f33bbcb6SJed Brown Level: beginner 1516f33bbcb6SJed Brown 1517f33bbcb6SJed Brown Notes: 15187cf5af47SJed Brown TSCN is equivalent to TSTHETA with Theta=0.5 and the "endpoint" option set. I.e. 15197cf5af47SJed Brown 15207cf5af47SJed Brown $ -ts_type theta -ts_theta_theta 0.5 -ts_theta_endpoint 1521f33bbcb6SJed Brown 1522f33bbcb6SJed Brown .seealso: TSCreate(), TS, TSSetType(), TSBEULER, TSTHETA 1523f33bbcb6SJed Brown 1524f33bbcb6SJed Brown M*/ 15258cc058d9SJed Brown PETSC_EXTERN PetscErrorCode TSCreate_CN(TS ts) 1526f33bbcb6SJed Brown { 1527f33bbcb6SJed Brown PetscErrorCode ierr; 1528f33bbcb6SJed Brown 1529f33bbcb6SJed Brown PetscFunctionBegin; 1530f33bbcb6SJed Brown ierr = TSCreate_Theta(ts);CHKERRQ(ierr); 1531f33bbcb6SJed Brown ierr = TSThetaSetTheta(ts,0.5);CHKERRQ(ierr); 1532eb284becSJed Brown ierr = TSThetaSetEndpoint(ts,PETSC_TRUE);CHKERRQ(ierr); 15330c7376e5SHong Zhang ts->ops->setup = TSSetUp_CN; 1534f33bbcb6SJed Brown ts->ops->view = TSView_CN; 1535f33bbcb6SJed Brown PetscFunctionReturn(0); 1536f33bbcb6SJed Brown } 1537