xref: /petsc/src/ts/impls/implicit/theta/theta.c (revision 030f984af8d8bb4c203755d35bded3c05b3d83ce)
1 /*
2   Code for timestepping with implicit Theta method
3 */
4 #include <petsc/private/tsimpl.h>                /*I   "petscts.h"   I*/
5 #include <petscsnes.h>
6 #include <petscdm.h>
7 #include <petscmat.h>
8 
9 typedef struct {
10   /* context for time stepping */
11   PetscReal    stage_time;
12   Vec          Stages[2];                 /* Storage for stage solutions */
13   Vec          X0,X,Xdot;                /* Storage for u^n, u^n + dt a_{11} k_1, and time derivative u^{n+1}_t */
14   Vec          affine;                   /* Affine vector needed for residual at beginning of step in endpoint formulation */
15   PetscReal    Theta;
16   PetscReal    shift;                    /* Shift parameter for SNES Jacobian, used by forward, TLM and adjoint */
17   PetscInt     order;
18   PetscBool    endpoint;
19   PetscBool    extrapolate;
20   TSStepStatus status;
21   Vec          VecCostIntegral0;         /* Backup for roll-backs due to events, used by cost integral */
22   PetscReal    ptime0;                   /* Backup for ts->ptime, the start time of current time step, used by TLM and cost integral */
23   PetscReal    time_step0;               /* Backup for ts->timestep, the step size of current time step, used by TLM and cost integral*/
24 
25   /* context for sensitivity analysis */
26   PetscInt     num_tlm;                  /* Total number of tangent linear equations */
27   Vec          *VecsDeltaLam;            /* Increment of the adjoint sensitivity w.r.t IC at stage */
28   Vec          *VecsDeltaMu;             /* Increment of the adjoint sensitivity w.r.t P at stage */
29   Vec          *VecsSensiTemp;           /* Vector to be multiplied with Jacobian transpose */
30   Mat          MatFwdStages[2];          /* TLM Stages */
31   Mat          MatDeltaFwdSensip;        /* Increment of the forward sensitivity at stage */
32   Vec          VecDeltaFwdSensipCol;     /* Working vector for holding one column of the sensitivity matrix */
33   Mat          MatFwdSensip0;            /* backup for roll-backs due to events */
34   Mat          MatIntegralSensipTemp;    /* Working vector for forward integral sensitivity */
35   Mat          MatIntegralSensip0;       /* backup for roll-backs due to events */
36   Vec          *VecsDeltaLam2;           /* Increment of the 2nd-order adjoint sensitivity w.r.t IC at stage */
37   Vec          *VecsDeltaMu2;            /* Increment of the 2nd-order adjoint sensitivity w.r.t P at stage */
38   Vec          *VecsSensi2Temp;          /* Working vectors that holds the residual for the second-order adjoint */
39   Vec          *VecsAffine;              /* Working vectors to store residuals */
40   /* context for error estimation */
41   Vec          vec_sol_prev;
42   Vec          vec_lte_work;
43 } TS_Theta;
44 
45 static PetscErrorCode TSThetaGetX0AndXdot(TS ts,DM dm,Vec *X0,Vec *Xdot)
46 {
47   TS_Theta       *th = (TS_Theta*)ts->data;
48   PetscErrorCode ierr;
49 
50   PetscFunctionBegin;
51   if (X0) {
52     if (dm && dm != ts->dm) {
53       ierr = DMGetNamedGlobalVector(dm,"TSTheta_X0",X0);CHKERRQ(ierr);
54     } else *X0 = ts->vec_sol;
55   }
56   if (Xdot) {
57     if (dm && dm != ts->dm) {
58       ierr = DMGetNamedGlobalVector(dm,"TSTheta_Xdot",Xdot);CHKERRQ(ierr);
59     } else *Xdot = th->Xdot;
60   }
61   PetscFunctionReturn(0);
62 }
63 
64 static PetscErrorCode TSThetaRestoreX0AndXdot(TS ts,DM dm,Vec *X0,Vec *Xdot)
65 {
66   PetscErrorCode ierr;
67 
68   PetscFunctionBegin;
69   if (X0) {
70     if (dm && dm != ts->dm) {
71       ierr = DMRestoreNamedGlobalVector(dm,"TSTheta_X0",X0);CHKERRQ(ierr);
72     }
73   }
74   if (Xdot) {
75     if (dm && dm != ts->dm) {
76       ierr = DMRestoreNamedGlobalVector(dm,"TSTheta_Xdot",Xdot);CHKERRQ(ierr);
77     }
78   }
79   PetscFunctionReturn(0);
80 }
81 
82 static PetscErrorCode DMCoarsenHook_TSTheta(DM fine,DM coarse,void *ctx)
83 {
84   PetscFunctionBegin;
85   PetscFunctionReturn(0);
86 }
87 
88 static PetscErrorCode DMRestrictHook_TSTheta(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse,void *ctx)
89 {
90   TS             ts = (TS)ctx;
91   PetscErrorCode ierr;
92   Vec            X0,Xdot,X0_c,Xdot_c;
93 
94   PetscFunctionBegin;
95   ierr = TSThetaGetX0AndXdot(ts,fine,&X0,&Xdot);CHKERRQ(ierr);
96   ierr = TSThetaGetX0AndXdot(ts,coarse,&X0_c,&Xdot_c);CHKERRQ(ierr);
97   ierr = MatRestrict(restrct,X0,X0_c);CHKERRQ(ierr);
98   ierr = MatRestrict(restrct,Xdot,Xdot_c);CHKERRQ(ierr);
99   ierr = VecPointwiseMult(X0_c,rscale,X0_c);CHKERRQ(ierr);
100   ierr = VecPointwiseMult(Xdot_c,rscale,Xdot_c);CHKERRQ(ierr);
101   ierr = TSThetaRestoreX0AndXdot(ts,fine,&X0,&Xdot);CHKERRQ(ierr);
102   ierr = TSThetaRestoreX0AndXdot(ts,coarse,&X0_c,&Xdot_c);CHKERRQ(ierr);
103   PetscFunctionReturn(0);
104 }
105 
106 static PetscErrorCode DMSubDomainHook_TSTheta(DM dm,DM subdm,void *ctx)
107 {
108   PetscFunctionBegin;
109   PetscFunctionReturn(0);
110 }
111 
112 static PetscErrorCode DMSubDomainRestrictHook_TSTheta(DM dm,VecScatter gscat,VecScatter lscat,DM subdm,void *ctx)
113 {
114   TS             ts = (TS)ctx;
115   PetscErrorCode ierr;
116   Vec            X0,Xdot,X0_sub,Xdot_sub;
117 
118   PetscFunctionBegin;
119   ierr = TSThetaGetX0AndXdot(ts,dm,&X0,&Xdot);CHKERRQ(ierr);
120   ierr = TSThetaGetX0AndXdot(ts,subdm,&X0_sub,&Xdot_sub);CHKERRQ(ierr);
121 
122   ierr = VecScatterBegin(gscat,X0,X0_sub,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
123   ierr = VecScatterEnd(gscat,X0,X0_sub,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
124 
125   ierr = VecScatterBegin(gscat,Xdot,Xdot_sub,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
126   ierr = VecScatterEnd(gscat,Xdot,Xdot_sub,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
127 
128   ierr = TSThetaRestoreX0AndXdot(ts,dm,&X0,&Xdot);CHKERRQ(ierr);
129   ierr = TSThetaRestoreX0AndXdot(ts,subdm,&X0_sub,&Xdot_sub);CHKERRQ(ierr);
130   PetscFunctionReturn(0);
131 }
132 
133 static PetscErrorCode TSThetaEvaluateCostIntegral(TS ts)
134 {
135   TS_Theta       *th = (TS_Theta*)ts->data;
136   TS             quadts = ts->quadraturets;
137   PetscErrorCode ierr;
138 
139   PetscFunctionBegin;
140   if (th->endpoint) {
141     /* Evolve ts->vec_costintegral to compute integrals */
142     if (th->Theta!=1.0) {
143       ierr = TSComputeRHSFunction(quadts,th->ptime0,th->X0,ts->vec_costintegrand);CHKERRQ(ierr);
144       ierr = VecAXPY(quadts->vec_sol,th->time_step0*(1.0-th->Theta),ts->vec_costintegrand);CHKERRQ(ierr);
145     }
146     ierr = TSComputeRHSFunction(quadts,ts->ptime,ts->vec_sol,ts->vec_costintegrand);CHKERRQ(ierr);
147     ierr = VecAXPY(quadts->vec_sol,th->time_step0*th->Theta,ts->vec_costintegrand);CHKERRQ(ierr);
148   } else {
149     ierr = TSComputeRHSFunction(quadts,th->stage_time,th->X,ts->vec_costintegrand);CHKERRQ(ierr);
150     ierr = VecAXPY(quadts->vec_sol,th->time_step0,ts->vec_costintegrand);CHKERRQ(ierr);
151   }
152   PetscFunctionReturn(0);
153 }
154 
155 static PetscErrorCode TSForwardCostIntegral_Theta(TS ts)
156 {
157   TS_Theta       *th = (TS_Theta*)ts->data;
158   TS             quadts = ts->quadraturets;
159   PetscErrorCode ierr;
160 
161   PetscFunctionBegin;
162   /* backup cost integral */
163   ierr = VecCopy(quadts->vec_sol,th->VecCostIntegral0);CHKERRQ(ierr);
164   ierr = TSThetaEvaluateCostIntegral(ts);CHKERRQ(ierr);
165   PetscFunctionReturn(0);
166 }
167 
168 static PetscErrorCode TSAdjointCostIntegral_Theta(TS ts)
169 {
170   TS_Theta       *th = (TS_Theta*)ts->data;
171   PetscErrorCode ierr;
172 
173   PetscFunctionBegin;
174   /* Like TSForwardCostIntegral(), the adjoint cost integral evaluation relies on ptime0 and time_step0. */
175   th->ptime0     = ts->ptime + ts->time_step;
176   th->time_step0 = -ts->time_step;
177   ierr = TSThetaEvaluateCostIntegral(ts);CHKERRQ(ierr);
178   PetscFunctionReturn(0);
179 }
180 
181 static PetscErrorCode TSTheta_SNESSolve(TS ts,Vec b,Vec x)
182 {
183   PetscInt       nits,lits;
184   PetscErrorCode ierr;
185 
186   PetscFunctionBegin;
187   ierr = SNESSolve(ts->snes,b,x);CHKERRQ(ierr);
188   ierr = SNESGetIterationNumber(ts->snes,&nits);CHKERRQ(ierr);
189   ierr = SNESGetLinearSolveIterations(ts->snes,&lits);CHKERRQ(ierr);
190   ts->snes_its += nits; ts->ksp_its += lits;
191   PetscFunctionReturn(0);
192 }
193 
194 static PetscErrorCode TSStep_Theta(TS ts)
195 {
196   TS_Theta       *th = (TS_Theta*)ts->data;
197   PetscInt       rejections = 0;
198   PetscBool      stageok,accept = PETSC_TRUE;
199   PetscReal      next_time_step = ts->time_step;
200   PetscErrorCode ierr;
201 
202   PetscFunctionBegin;
203   if (!ts->steprollback) {
204     if (th->vec_sol_prev) { ierr = VecCopy(th->X0,th->vec_sol_prev);CHKERRQ(ierr); }
205     ierr = VecCopy(ts->vec_sol,th->X0);CHKERRQ(ierr);
206   }
207 
208   th->status     = TS_STEP_INCOMPLETE;
209   while (!ts->reason && th->status != TS_STEP_COMPLETE) {
210     th->shift      = 1/(th->Theta*ts->time_step);
211     th->stage_time = ts->ptime + (th->endpoint ? (PetscReal)1 : th->Theta)*ts->time_step;
212     ierr = VecCopy(th->X0,th->X);CHKERRQ(ierr);
213     if (th->extrapolate && !ts->steprestart) {
214       ierr = VecAXPY(th->X,1/th->shift,th->Xdot);CHKERRQ(ierr);
215     }
216     if (th->endpoint) { /* This formulation assumes linear time-independent mass matrix */
217       if (!th->affine) {ierr = VecDuplicate(ts->vec_sol,&th->affine);CHKERRQ(ierr);}
218       ierr = VecZeroEntries(th->Xdot);CHKERRQ(ierr);
219       ierr = TSComputeIFunction(ts,ts->ptime,th->X0,th->Xdot,th->affine,PETSC_FALSE);CHKERRQ(ierr);
220       ierr = VecScale(th->affine,(th->Theta-1)/th->Theta);CHKERRQ(ierr);
221     } else if (th->affine) { /* Just in case th->endpoint is changed between calls to TSStep_Theta() */
222       ierr = VecZeroEntries(th->affine);CHKERRQ(ierr);
223     }
224     ierr = TSPreStage(ts,th->stage_time);CHKERRQ(ierr);
225     ierr = TSTheta_SNESSolve(ts,th->affine,th->X);CHKERRQ(ierr);
226     ierr = TSPostStage(ts,th->stage_time,0,&th->X);CHKERRQ(ierr);
227     ierr = TSAdaptCheckStage(ts->adapt,ts,th->stage_time,th->X,&stageok);CHKERRQ(ierr);
228     if (!stageok) goto reject_step;
229 
230     th->status = TS_STEP_PENDING;
231     if (th->endpoint) {
232       ierr = VecCopy(th->X,ts->vec_sol);CHKERRQ(ierr);
233     } else {
234       ierr = VecAXPBYPCZ(th->Xdot,-th->shift,th->shift,0,th->X0,th->X);CHKERRQ(ierr);
235       ierr = VecAXPY(ts->vec_sol,ts->time_step,th->Xdot);CHKERRQ(ierr);
236     }
237     ierr = TSAdaptChoose(ts->adapt,ts,ts->time_step,NULL,&next_time_step,&accept);CHKERRQ(ierr);
238     th->status = accept ? TS_STEP_COMPLETE : TS_STEP_INCOMPLETE;
239     if (!accept) {
240       ierr = VecCopy(th->X0,ts->vec_sol);CHKERRQ(ierr);
241       ts->time_step = next_time_step;
242       goto reject_step;
243     }
244 
245     if (ts->forward_solve || ts->costintegralfwd) { /* Save the info for the later use in cost integral evaluation */
246       th->ptime0     = ts->ptime;
247       th->time_step0 = ts->time_step;
248     }
249     ts->ptime += ts->time_step;
250     ts->time_step = next_time_step;
251     break;
252 
253   reject_step:
254     ts->reject++; accept = PETSC_FALSE;
255     if (!ts->reason && ++rejections > ts->max_reject && ts->max_reject >= 0) {
256       ts->reason = TS_DIVERGED_STEP_REJECTED;
257       ierr = PetscInfo2(ts,"Step=%D, step rejections %D greater than current TS allowed, stopping solve\n",ts->steps,rejections);CHKERRQ(ierr);
258     }
259   }
260   PetscFunctionReturn(0);
261 }
262 
263 static PetscErrorCode TSAdjointStepBEuler_Private(TS ts)
264 {
265   TS_Theta       *th = (TS_Theta*)ts->data;
266   TS             quadts = ts->quadraturets;
267   Vec            *VecsDeltaLam = th->VecsDeltaLam,*VecsDeltaMu = th->VecsDeltaMu,*VecsSensiTemp = th->VecsSensiTemp;
268   Vec            *VecsDeltaLam2 = th->VecsDeltaLam2,*VecsDeltaMu2 = th->VecsDeltaMu2,*VecsSensi2Temp = th->VecsSensi2Temp;
269   PetscInt       nadj;
270   Mat            J,Jpre,quadJ = NULL,quadJp = NULL;
271   KSP            ksp;
272   PetscScalar    *xarr;
273   TSEquationType eqtype;
274   PetscBool      isexplicitode = PETSC_FALSE;
275   PetscReal      adjoint_time_step;
276   PetscErrorCode ierr;
277 
278   PetscFunctionBegin;
279   ierr = TSGetEquationType(ts,&eqtype);CHKERRQ(ierr);
280   if (eqtype == TS_EQ_ODE_EXPLICIT) {
281     isexplicitode  = PETSC_TRUE;
282     VecsDeltaLam  = ts->vecs_sensi;
283     VecsDeltaLam2 = ts->vecs_sensi2;
284   }
285   th->status = TS_STEP_INCOMPLETE;
286   ierr = SNESGetKSP(ts->snes,&ksp);CHKERRQ(ierr);
287   ierr = TSGetIJacobian(ts,&J,&Jpre,NULL,NULL);CHKERRQ(ierr);
288   if (quadts) {
289     ierr = TSGetRHSJacobian(quadts,&quadJ,NULL,NULL,NULL);CHKERRQ(ierr);
290     ierr = TSGetRHSJacobianP(quadts,&quadJp,NULL,NULL);CHKERRQ(ierr);
291   }
292 
293   th->stage_time    = ts->ptime;
294   adjoint_time_step = -ts->time_step; /* always positive since time_step is negative */
295 
296   /* Build RHS for first-order adjoint lambda_{n+1}/h + r_u^T(n+1) */
297   if (quadts) {
298     ierr = TSComputeRHSJacobian(quadts,th->stage_time,ts->vec_sol,quadJ,NULL);CHKERRQ(ierr);
299   }
300 
301   for (nadj=0; nadj<ts->numcost; nadj++) {
302     ierr = VecCopy(ts->vecs_sensi[nadj],VecsSensiTemp[nadj]);CHKERRQ(ierr);
303     ierr = VecScale(VecsSensiTemp[nadj],1./adjoint_time_step);CHKERRQ(ierr); /* lambda_{n+1}/h */
304     if (quadJ) {
305       ierr = MatDenseGetColumn(quadJ,nadj,&xarr);CHKERRQ(ierr);
306       ierr = VecPlaceArray(ts->vec_drdu_col,xarr);CHKERRQ(ierr);
307       ierr = VecAXPY(VecsSensiTemp[nadj],1.,ts->vec_drdu_col);CHKERRQ(ierr);
308       ierr = VecResetArray(ts->vec_drdu_col);CHKERRQ(ierr);
309       ierr = MatDenseRestoreColumn(quadJ,&xarr);CHKERRQ(ierr);
310     }
311   }
312 
313   /* Build LHS for first-order adjoint */
314   th->shift = 1./adjoint_time_step;
315   ierr = TSComputeSNESJacobian(ts,ts->vec_sol,J,Jpre);CHKERRQ(ierr);
316   ierr = KSPSetOperators(ksp,J,Jpre);CHKERRQ(ierr);
317 
318   /* Solve stage equation LHS*lambda_s = RHS for first-order adjoint */
319   for (nadj=0; nadj<ts->numcost; nadj++) {
320     KSPConvergedReason kspreason;
321     ierr = KSPSolveTranspose(ksp,VecsSensiTemp[nadj],VecsDeltaLam[nadj]);CHKERRQ(ierr);
322     ierr = KSPGetConvergedReason(ksp,&kspreason);CHKERRQ(ierr);
323     if (kspreason < 0) {
324       ts->reason = TSADJOINT_DIVERGED_LINEAR_SOLVE;
325       ierr = PetscInfo2(ts,"Step=%D, %Dth cost function, transposed linear solve fails, stopping 1st-order adjoint solve\n",ts->steps,nadj);CHKERRQ(ierr);
326     }
327   }
328 
329   if (ts->vecs_sensi2) { /* U_{n+1} */
330     /* Get w1 at t_{n+1} from TLM matrix */
331     ierr = MatDenseGetColumn(ts->mat_sensip,0,&xarr);CHKERRQ(ierr);
332     ierr = VecPlaceArray(ts->vec_sensip_col,xarr);CHKERRQ(ierr);
333     /* lambda_s^T F_UU w_1 */
334     ierr = TSComputeIHessianProductFunctionUU(ts,th->stage_time,ts->vec_sol,VecsDeltaLam,ts->vec_sensip_col,ts->vecs_fuu);CHKERRQ(ierr);
335     /* lambda_s^T F_UP w_2 */
336     ierr = TSComputeIHessianProductFunctionUP(ts,th->stage_time,ts->vec_sol,VecsDeltaLam,ts->vec_dir,ts->vecs_fup);CHKERRQ(ierr);
337     for (nadj=0; nadj<ts->numcost; nadj++) { /* compute the residual */
338       ierr = VecCopy(ts->vecs_sensi2[nadj],VecsSensi2Temp[nadj]);CHKERRQ(ierr);
339       ierr = VecScale(VecsSensi2Temp[nadj],1./adjoint_time_step);CHKERRQ(ierr);
340       ierr = VecAXPY(VecsSensi2Temp[nadj],-1.,ts->vecs_fuu[nadj]);CHKERRQ(ierr);
341       if (ts->vecs_fup) {
342         ierr = VecAXPY(VecsSensi2Temp[nadj],-1.,ts->vecs_fup[nadj]);CHKERRQ(ierr);
343       }
344     }
345     /* Solve stage equation LHS X = RHS for second-order adjoint */
346     for (nadj=0; nadj<ts->numcost; nadj++) {
347       KSPConvergedReason kspreason;
348       ierr = KSPSolveTranspose(ksp,VecsSensi2Temp[nadj],VecsDeltaLam2[nadj]);CHKERRQ(ierr);
349       ierr = KSPGetConvergedReason(ksp,&kspreason);CHKERRQ(ierr);
350       if (kspreason < 0) {
351         ts->reason = TSADJOINT_DIVERGED_LINEAR_SOLVE;
352         ierr = PetscInfo2(ts,"Step=%D, %Dth cost function, transposed linear solve fails, stopping 2nd-order adjoint solve\n",ts->steps,nadj);CHKERRQ(ierr);
353       }
354     }
355   }
356 
357   /* Update sensitivities, and evaluate integrals if there is any */
358   if (!isexplicitode) {
359     th->shift = 0.0;
360     ierr = TSComputeSNESJacobian(ts,ts->vec_sol,J,Jpre);CHKERRQ(ierr);
361     ierr = KSPSetOperators(ksp,J,Jpre);CHKERRQ(ierr);
362     ierr = MatScale(J,-1.);CHKERRQ(ierr);
363     for (nadj=0; nadj<ts->numcost; nadj++) {
364       /* Add f_U \lambda_s to the original RHS */
365       ierr = MatMultTransposeAdd(J,VecsDeltaLam[nadj],VecsSensiTemp[nadj],VecsSensiTemp[nadj]);CHKERRQ(ierr);
366       ierr = VecScale(VecsSensiTemp[nadj],adjoint_time_step);CHKERRQ(ierr);
367       ierr = VecCopy(VecsSensiTemp[nadj],ts->vecs_sensi[nadj]);CHKERRQ(ierr);
368       if (ts->vecs_sensi2) {
369         ierr = MatMultTransposeAdd(J,VecsDeltaLam2[nadj],VecsSensi2Temp[nadj],VecsSensi2Temp[nadj]);CHKERRQ(ierr);
370         ierr = VecScale(VecsSensi2Temp[nadj],adjoint_time_step);CHKERRQ(ierr);
371         ierr = VecCopy(VecsSensi2Temp[nadj],ts->vecs_sensi2[nadj]);CHKERRQ(ierr);
372       }
373     }
374   }
375   if (ts->vecs_sensip) {
376     ierr = VecAXPBYPCZ(th->Xdot,-1./adjoint_time_step,1.0/adjoint_time_step,0,th->X0,ts->vec_sol);CHKERRQ(ierr);
377     ierr = TSComputeIJacobianP(ts,th->stage_time,ts->vec_sol,th->Xdot,1./adjoint_time_step,ts->Jacp,PETSC_FALSE);CHKERRQ(ierr); /* get -f_p */
378     if (quadts) {
379       ierr = TSComputeRHSJacobianP(quadts,th->stage_time,ts->vec_sol,quadJp);CHKERRQ(ierr);
380     }
381     if (ts->vecs_sensi2p) {
382       /* lambda_s^T F_PU w_1 */
383       ierr = TSComputeIHessianProductFunctionPU(ts,th->stage_time,ts->vec_sol,VecsDeltaLam,ts->vec_sensip_col,ts->vecs_fpu);CHKERRQ(ierr);
384       /* lambda_s^T F_PP w_2 */
385       ierr = TSComputeIHessianProductFunctionPP(ts,th->stage_time,ts->vec_sol,VecsDeltaLam,ts->vec_dir,ts->vecs_fpp);CHKERRQ(ierr);
386     }
387 
388     for (nadj=0; nadj<ts->numcost; nadj++) {
389       ierr = MatMultTranspose(ts->Jacp,VecsDeltaLam[nadj],VecsDeltaMu[nadj]);CHKERRQ(ierr);
390       ierr = VecAXPY(ts->vecs_sensip[nadj],-adjoint_time_step,VecsDeltaMu[nadj]);CHKERRQ(ierr);
391       if (quadJp) {
392         ierr = MatDenseGetColumn(quadJp,nadj,&xarr);CHKERRQ(ierr);
393         ierr = VecPlaceArray(ts->vec_drdp_col,xarr);CHKERRQ(ierr);
394         ierr = VecAXPY(ts->vecs_sensip[nadj],adjoint_time_step,ts->vec_drdp_col);CHKERRQ(ierr);
395         ierr = VecResetArray(ts->vec_drdp_col);CHKERRQ(ierr);
396         ierr = MatDenseRestoreColumn(quadJp,&xarr);CHKERRQ(ierr);
397       }
398       if (ts->vecs_sensi2p) {
399         ierr = MatMultTranspose(ts->Jacp,VecsDeltaLam2[nadj],VecsDeltaMu2[nadj]);CHKERRQ(ierr);
400         ierr = VecAXPY(ts->vecs_sensi2p[nadj],-adjoint_time_step,VecsDeltaMu2[nadj]);CHKERRQ(ierr);
401         if (ts->vecs_fpu) {
402           ierr = VecAXPY(ts->vecs_sensi2p[nadj],-adjoint_time_step,ts->vecs_fpu[nadj]);CHKERRQ(ierr);
403         }
404         if (ts->vecs_fpp) {
405           ierr = VecAXPY(ts->vecs_sensi2p[nadj],-adjoint_time_step,ts->vecs_fpp[nadj]);CHKERRQ(ierr);
406         }
407       }
408     }
409   }
410 
411   if (ts->vecs_sensi2) {
412     ierr = VecResetArray(ts->vec_sensip_col);CHKERRQ(ierr);
413     ierr = MatDenseRestoreColumn(ts->mat_sensip,&xarr);CHKERRQ(ierr);
414   }
415   th->status = TS_STEP_COMPLETE;
416   PetscFunctionReturn(0);
417 }
418 
419 static PetscErrorCode TSAdjointStep_Theta(TS ts)
420 {
421   TS_Theta       *th = (TS_Theta*)ts->data;
422   TS             quadts = ts->quadraturets;
423   Vec            *VecsDeltaLam = th->VecsDeltaLam,*VecsDeltaMu = th->VecsDeltaMu,*VecsSensiTemp = th->VecsSensiTemp;
424   Vec            *VecsDeltaLam2 = th->VecsDeltaLam2,*VecsDeltaMu2 = th->VecsDeltaMu2,*VecsSensi2Temp = th->VecsSensi2Temp;
425   PetscInt       nadj;
426   Mat            J,Jpre,quadJ = NULL,quadJp = NULL;
427   KSP            ksp;
428   PetscScalar    *xarr;
429   PetscReal      adjoint_time_step;
430   PetscReal      adjoint_ptime; /* end time of the adjoint time step (ts->ptime is the start time, ususally ts->ptime is larger than adjoint_ptime) */
431   PetscErrorCode ierr;
432 
433   PetscFunctionBegin;
434   if (th->Theta == 1.) {
435     ierr = TSAdjointStepBEuler_Private(ts);CHKERRQ(ierr);
436     PetscFunctionReturn(0);
437   }
438   th->status = TS_STEP_INCOMPLETE;
439   ierr = SNESGetKSP(ts->snes,&ksp);CHKERRQ(ierr);
440   ierr = TSGetIJacobian(ts,&J,&Jpre,NULL,NULL);CHKERRQ(ierr);
441   if (quadts) {
442     ierr = TSGetRHSJacobian(quadts,&quadJ,NULL,NULL,NULL);CHKERRQ(ierr);
443     ierr = TSGetRHSJacobianP(quadts,&quadJp,NULL,NULL);CHKERRQ(ierr);
444   }
445   /* If endpoint=1, th->ptime and th->X0 will be used; if endpoint=0, th->stage_time and th->X will be used. */
446   th->stage_time    = th->endpoint ? ts->ptime : (ts->ptime+(1.-th->Theta)*ts->time_step);
447   adjoint_ptime     = ts->ptime + ts->time_step;
448   adjoint_time_step = -ts->time_step;  /* always positive since time_step is negative */
449 
450   if (!th->endpoint) {
451     /* recover th->X0 using vec_sol and the stage value th->X */
452     ierr = VecAXPBYPCZ(th->X0,1.0/(1.0-th->Theta),th->Theta/(th->Theta-1.0),0,th->X,ts->vec_sol);CHKERRQ(ierr);
453   }
454 
455   /* Build RHS for first-order adjoint */
456   /* Cost function has an integral term */
457   if (quadts) {
458     if (th->endpoint) {
459       ierr = TSComputeRHSJacobian(quadts,th->stage_time,ts->vec_sol,quadJ,NULL);CHKERRQ(ierr);
460     } else {
461       ierr = TSComputeRHSJacobian(quadts,th->stage_time,th->X,quadJ,NULL);CHKERRQ(ierr);
462     }
463   }
464 
465   for (nadj=0; nadj<ts->numcost; nadj++) {
466     ierr = VecCopy(ts->vecs_sensi[nadj],VecsSensiTemp[nadj]);CHKERRQ(ierr);
467     ierr = VecScale(VecsSensiTemp[nadj],1./(th->Theta*adjoint_time_step));CHKERRQ(ierr);
468     if (quadJ) {
469       ierr = MatDenseGetColumn(quadJ,nadj,&xarr);CHKERRQ(ierr);
470       ierr = VecPlaceArray(ts->vec_drdu_col,xarr);CHKERRQ(ierr);
471       ierr = VecAXPY(VecsSensiTemp[nadj],1.,ts->vec_drdu_col);CHKERRQ(ierr);
472       ierr = VecResetArray(ts->vec_drdu_col);CHKERRQ(ierr);
473       ierr = MatDenseRestoreColumn(quadJ,&xarr);CHKERRQ(ierr);
474     }
475   }
476 
477   /* Build LHS for first-order adjoint */
478   th->shift = 1./(th->Theta*adjoint_time_step);
479   if (th->endpoint) {
480     ierr = TSComputeSNESJacobian(ts,ts->vec_sol,J,Jpre);CHKERRQ(ierr);
481   } else {
482     ierr = TSComputeSNESJacobian(ts,th->X,J,Jpre);CHKERRQ(ierr);
483   }
484   ierr = KSPSetOperators(ksp,J,Jpre);CHKERRQ(ierr);
485 
486   /* Solve stage equation LHS*lambda_s = RHS for first-order adjoint */
487   for (nadj=0; nadj<ts->numcost; nadj++) {
488     KSPConvergedReason kspreason;
489     ierr = KSPSolveTranspose(ksp,VecsSensiTemp[nadj],VecsDeltaLam[nadj]);CHKERRQ(ierr);
490     ierr = KSPGetConvergedReason(ksp,&kspreason);CHKERRQ(ierr);
491     if (kspreason < 0) {
492       ts->reason = TSADJOINT_DIVERGED_LINEAR_SOLVE;
493       ierr = PetscInfo2(ts,"Step=%D, %Dth cost function, transposed linear solve fails, stopping 1st-order adjoint solve\n",ts->steps,nadj);CHKERRQ(ierr);
494     }
495   }
496 
497   /* Second-order adjoint */
498   if (ts->vecs_sensi2) { /* U_{n+1} */
499     if (!th->endpoint) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Operation not implemented in TS_Theta");
500     /* Get w1 at t_{n+1} from TLM matrix */
501     ierr = MatDenseGetColumn(ts->mat_sensip,0,&xarr);CHKERRQ(ierr);
502     ierr = VecPlaceArray(ts->vec_sensip_col,xarr);CHKERRQ(ierr);
503     /* lambda_s^T F_UU w_1 */
504     ierr = TSComputeIHessianProductFunctionUU(ts,th->stage_time,ts->vec_sol,VecsDeltaLam,ts->vec_sensip_col,ts->vecs_fuu);CHKERRQ(ierr);
505     ierr = VecResetArray(ts->vec_sensip_col);CHKERRQ(ierr);
506     ierr = MatDenseRestoreColumn(ts->mat_sensip,&xarr);CHKERRQ(ierr);
507     /* lambda_s^T F_UP w_2 */
508     ierr = TSComputeIHessianProductFunctionUP(ts,th->stage_time,ts->vec_sol,VecsDeltaLam,ts->vec_dir,ts->vecs_fup);CHKERRQ(ierr);
509     for (nadj=0; nadj<ts->numcost; nadj++) { /* compute the residual */
510       ierr = VecCopy(ts->vecs_sensi2[nadj],VecsSensi2Temp[nadj]);CHKERRQ(ierr);
511       ierr = VecScale(VecsSensi2Temp[nadj],th->shift);CHKERRQ(ierr);
512       ierr = VecAXPY(VecsSensi2Temp[nadj],-1.,ts->vecs_fuu[nadj]);CHKERRQ(ierr);
513       if (ts->vecs_fup) {
514         ierr = VecAXPY(VecsSensi2Temp[nadj],-1.,ts->vecs_fup[nadj]);CHKERRQ(ierr);
515       }
516     }
517     /* Solve stage equation LHS X = RHS for second-order adjoint */
518     for (nadj=0; nadj<ts->numcost; nadj++) {
519       KSPConvergedReason kspreason;
520       ierr = KSPSolveTranspose(ksp,VecsSensi2Temp[nadj],VecsDeltaLam2[nadj]);CHKERRQ(ierr);
521       ierr = KSPGetConvergedReason(ksp,&kspreason);CHKERRQ(ierr);
522       if (kspreason < 0) {
523         ts->reason = TSADJOINT_DIVERGED_LINEAR_SOLVE;
524         ierr = PetscInfo2(ts,"Step=%D, %Dth cost function, transposed linear solve fails, stopping 2nd-order adjoint solve\n",ts->steps,nadj);CHKERRQ(ierr);
525       }
526     }
527   }
528 
529   /* Update sensitivities, and evaluate integrals if there is any */
530   if (th->endpoint) { /* two-stage Theta methods with th->Theta!=1, th->Theta==1 leads to BEuler */
531     th->shift      = 1./((th->Theta-1.)*adjoint_time_step);
532     th->stage_time = adjoint_ptime;
533     ierr           = TSComputeSNESJacobian(ts,th->X0,J,Jpre);CHKERRQ(ierr);
534     ierr           = KSPSetOperators(ksp,J,Jpre);CHKERRQ(ierr);
535     /* R_U at t_n */
536     if (quadts) {
537       ierr = TSComputeRHSJacobian(quadts,adjoint_ptime,th->X0,quadJ,NULL);CHKERRQ(ierr);
538     }
539     for (nadj=0; nadj<ts->numcost; nadj++) {
540       ierr = MatMultTranspose(J,VecsDeltaLam[nadj],ts->vecs_sensi[nadj]);CHKERRQ(ierr);
541       if (quadJ) {
542         ierr = MatDenseGetColumn(quadJ,nadj,&xarr);CHKERRQ(ierr);
543         ierr = VecPlaceArray(ts->vec_drdu_col,xarr);CHKERRQ(ierr);
544         ierr = VecAXPY(ts->vecs_sensi[nadj],-1.,ts->vec_drdu_col);CHKERRQ(ierr);
545         ierr = VecResetArray(ts->vec_drdu_col);CHKERRQ(ierr);
546         ierr = MatDenseRestoreColumn(quadJ,&xarr);CHKERRQ(ierr);
547       }
548       ierr = VecScale(ts->vecs_sensi[nadj],1./th->shift);CHKERRQ(ierr);
549     }
550 
551     /* Second-order adjoint */
552     if (ts->vecs_sensi2) { /* U_n */
553       /* Get w1 at t_n from TLM matrix */
554       ierr = MatDenseGetColumn(th->MatFwdSensip0,0,&xarr);CHKERRQ(ierr);
555       ierr = VecPlaceArray(ts->vec_sensip_col,xarr);CHKERRQ(ierr);
556       /* lambda_s^T F_UU w_1 */
557       ierr = TSComputeIHessianProductFunctionUU(ts,adjoint_ptime,th->X0,VecsDeltaLam,ts->vec_sensip_col,ts->vecs_fuu);CHKERRQ(ierr);
558       ierr = VecResetArray(ts->vec_sensip_col);CHKERRQ(ierr);
559       ierr = MatDenseRestoreColumn(th->MatFwdSensip0,&xarr);CHKERRQ(ierr);
560       /* lambda_s^T F_UU w_2 */
561       ierr = TSComputeIHessianProductFunctionUP(ts,adjoint_ptime,th->X0,VecsDeltaLam,ts->vec_dir,ts->vecs_fup);CHKERRQ(ierr);
562       for (nadj=0; nadj<ts->numcost; nadj++) {
563         /* 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  */
564         ierr = MatMultTranspose(J,VecsDeltaLam2[nadj],ts->vecs_sensi2[nadj]);CHKERRQ(ierr);
565         ierr = VecAXPY(ts->vecs_sensi2[nadj],1.,ts->vecs_fuu[nadj]);CHKERRQ(ierr);
566         if (ts->vecs_fup) {
567           ierr = VecAXPY(ts->vecs_sensi2[nadj],1.,ts->vecs_fup[nadj]);CHKERRQ(ierr);
568         }
569         ierr = VecScale(ts->vecs_sensi2[nadj],1./th->shift);CHKERRQ(ierr);
570       }
571     }
572 
573     th->stage_time = ts->ptime; /* recover the old value */
574 
575     if (ts->vecs_sensip) { /* sensitivities wrt parameters */
576       /* U_{n+1} */
577       th->shift = 1.0/(adjoint_time_step*th->Theta);
578       ierr = VecAXPBYPCZ(th->Xdot,-th->shift,th->shift,0,th->X0,ts->vec_sol);CHKERRQ(ierr);
579       ierr = TSComputeIJacobianP(ts,th->stage_time,ts->vec_sol,th->Xdot,-1./(th->Theta*adjoint_time_step),ts->Jacp,PETSC_FALSE);CHKERRQ(ierr);
580       if (quadts) {
581         ierr = TSComputeRHSJacobianP(quadts,th->stage_time,ts->vec_sol,quadJp);CHKERRQ(ierr);
582       }
583       for (nadj=0; nadj<ts->numcost; nadj++) {
584         ierr = MatMultTranspose(ts->Jacp,VecsDeltaLam[nadj],VecsDeltaMu[nadj]);CHKERRQ(ierr);
585         ierr = VecAXPY(ts->vecs_sensip[nadj],-adjoint_time_step*th->Theta,VecsDeltaMu[nadj]);CHKERRQ(ierr);
586         if (quadJp) {
587           ierr = MatDenseGetColumn(quadJp,nadj,&xarr);CHKERRQ(ierr);
588           ierr = VecPlaceArray(ts->vec_drdp_col,xarr);CHKERRQ(ierr);
589           ierr = VecAXPY(ts->vecs_sensip[nadj],adjoint_time_step*th->Theta,ts->vec_drdp_col);CHKERRQ(ierr);
590           ierr = VecResetArray(ts->vec_drdp_col);CHKERRQ(ierr);
591           ierr = MatDenseRestoreColumn(quadJp,&xarr);CHKERRQ(ierr);
592         }
593       }
594       if (ts->vecs_sensi2p) { /* second-order */
595         /* Get w1 at t_{n+1} from TLM matrix */
596         ierr = MatDenseGetColumn(ts->mat_sensip,0,&xarr);CHKERRQ(ierr);
597         ierr = VecPlaceArray(ts->vec_sensip_col,xarr);CHKERRQ(ierr);
598         /* lambda_s^T F_PU w_1 */
599         ierr = TSComputeIHessianProductFunctionPU(ts,th->stage_time,ts->vec_sol,VecsDeltaLam,ts->vec_sensip_col,ts->vecs_fpu);CHKERRQ(ierr);
600         ierr = VecResetArray(ts->vec_sensip_col);CHKERRQ(ierr);
601         ierr = MatDenseRestoreColumn(ts->mat_sensip,&xarr);CHKERRQ(ierr);
602 
603         /* lambda_s^T F_PP w_2 */
604         ierr = TSComputeIHessianProductFunctionPP(ts,th->stage_time,ts->vec_sol,VecsDeltaLam,ts->vec_dir,ts->vecs_fpp);CHKERRQ(ierr);
605         for (nadj=0; nadj<ts->numcost; nadj++) {
606           /* 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)  */
607           ierr = MatMultTranspose(ts->Jacp,VecsDeltaLam2[nadj],VecsDeltaMu2[nadj]);CHKERRQ(ierr);
608           ierr = VecAXPY(ts->vecs_sensi2p[nadj],-adjoint_time_step*th->Theta,VecsDeltaMu2[nadj]);CHKERRQ(ierr);
609           if (ts->vecs_fpu) {
610             ierr = VecAXPY(ts->vecs_sensi2p[nadj],-adjoint_time_step*th->Theta,ts->vecs_fpu[nadj]);CHKERRQ(ierr);
611           }
612           if (ts->vecs_fpp) {
613             ierr = VecAXPY(ts->vecs_sensi2p[nadj],-adjoint_time_step*th->Theta,ts->vecs_fpp[nadj]);CHKERRQ(ierr);
614           }
615         }
616       }
617 
618       /* U_s */
619       ierr = VecZeroEntries(th->Xdot);CHKERRQ(ierr);
620       ierr = TSComputeIJacobianP(ts,adjoint_ptime,th->X0,th->Xdot,1./((th->Theta-1.0)*adjoint_time_step),ts->Jacp,PETSC_FALSE);CHKERRQ(ierr);
621       if (quadts) {
622         ierr = TSComputeRHSJacobianP(quadts,adjoint_ptime,th->X0,quadJp);CHKERRQ(ierr);
623       }
624       for (nadj=0; nadj<ts->numcost; nadj++) {
625         ierr = MatMultTranspose(ts->Jacp,VecsDeltaLam[nadj],VecsDeltaMu[nadj]);CHKERRQ(ierr);
626         ierr = VecAXPY(ts->vecs_sensip[nadj],-adjoint_time_step*(1.0-th->Theta),VecsDeltaMu[nadj]);CHKERRQ(ierr);
627         if (quadJp) {
628           ierr = MatDenseGetColumn(quadJp,nadj,&xarr);CHKERRQ(ierr);
629           ierr = VecPlaceArray(ts->vec_drdp_col,xarr);CHKERRQ(ierr);
630           ierr = VecAXPY(ts->vecs_sensip[nadj],adjoint_time_step*(1.0-th->Theta),ts->vec_drdp_col);CHKERRQ(ierr);
631           ierr = VecResetArray(ts->vec_drdp_col);CHKERRQ(ierr);
632           ierr = MatDenseRestoreColumn(quadJp,&xarr);CHKERRQ(ierr);
633         }
634         if (ts->vecs_sensi2p) { /* second-order */
635           /* Get w1 at t_n from TLM matrix */
636           ierr = MatDenseGetColumn(th->MatFwdSensip0,0,&xarr);CHKERRQ(ierr);
637           ierr = VecPlaceArray(ts->vec_sensip_col,xarr);CHKERRQ(ierr);
638           /* lambda_s^T F_PU w_1 */
639           ierr = TSComputeIHessianProductFunctionPU(ts,adjoint_ptime,th->X0,VecsDeltaLam,ts->vec_sensip_col,ts->vecs_fpu);CHKERRQ(ierr);
640           ierr = VecResetArray(ts->vec_sensip_col);CHKERRQ(ierr);
641           ierr = MatDenseRestoreColumn(th->MatFwdSensip0,&xarr);CHKERRQ(ierr);
642           /* lambda_s^T F_PP w_2 */
643           ierr = TSComputeIHessianProductFunctionPP(ts,adjoint_ptime,th->X0,VecsDeltaLam,ts->vec_dir,ts->vecs_fpp);CHKERRQ(ierr);
644           for (nadj=0; nadj<ts->numcost; nadj++) {
645             /* 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) */
646             ierr = MatMultTranspose(ts->Jacp,VecsDeltaLam2[nadj],VecsDeltaMu2[nadj]);CHKERRQ(ierr);
647             ierr = VecAXPY(ts->vecs_sensi2p[nadj],-adjoint_time_step*(1.0-th->Theta),VecsDeltaMu2[nadj]);CHKERRQ(ierr);
648             if (ts->vecs_fpu) {
649               ierr = VecAXPY(ts->vecs_sensi2p[nadj],-adjoint_time_step*(1.0-th->Theta),ts->vecs_fpu[nadj]);CHKERRQ(ierr);
650             }
651             if (ts->vecs_fpp) {
652               ierr = VecAXPY(ts->vecs_sensi2p[nadj],-adjoint_time_step*(1.0-th->Theta),ts->vecs_fpp[nadj]);CHKERRQ(ierr);
653             }
654           }
655         }
656       }
657     }
658   } else { /* one-stage case */
659     th->shift = 0.0;
660     ierr      = TSComputeSNESJacobian(ts,th->X,J,Jpre);CHKERRQ(ierr); /* get -f_y */
661     ierr      = KSPSetOperators(ksp,J,Jpre);CHKERRQ(ierr);
662     if (quadts) {
663       ierr  = TSComputeRHSJacobian(quadts,th->stage_time,th->X,quadJ,NULL);CHKERRQ(ierr);
664     }
665     for (nadj=0; nadj<ts->numcost; nadj++) {
666       ierr = MatMultTranspose(J,VecsDeltaLam[nadj],VecsSensiTemp[nadj]);CHKERRQ(ierr);
667       ierr = VecAXPY(ts->vecs_sensi[nadj],-adjoint_time_step,VecsSensiTemp[nadj]);CHKERRQ(ierr);
668       if (quadJ) {
669         ierr = MatDenseGetColumn(quadJ,nadj,&xarr);CHKERRQ(ierr);
670         ierr = VecPlaceArray(ts->vec_drdu_col,xarr);CHKERRQ(ierr);
671         ierr = VecAXPY(ts->vecs_sensi[nadj],adjoint_time_step,ts->vec_drdu_col);CHKERRQ(ierr);
672         ierr = VecResetArray(ts->vec_drdu_col);CHKERRQ(ierr);
673         ierr = MatDenseRestoreColumn(quadJ,&xarr);CHKERRQ(ierr);
674       }
675     }
676     if (ts->vecs_sensip) {
677       th->shift = 1.0/(adjoint_time_step*th->Theta);
678       ierr = VecAXPBYPCZ(th->Xdot,-th->shift,th->shift,0,th->X0,th->X);CHKERRQ(ierr);
679       ierr = TSComputeIJacobianP(ts,th->stage_time,th->X,th->Xdot,th->shift,ts->Jacp,PETSC_FALSE);CHKERRQ(ierr);
680       if (quadts) {
681         ierr = TSComputeRHSJacobianP(quadts,th->stage_time,th->X,quadJp);CHKERRQ(ierr);
682       }
683       for (nadj=0; nadj<ts->numcost; nadj++) {
684         ierr = MatMultTranspose(ts->Jacp,VecsDeltaLam[nadj],VecsDeltaMu[nadj]);CHKERRQ(ierr);
685         ierr = VecAXPY(ts->vecs_sensip[nadj],-adjoint_time_step,VecsDeltaMu[nadj]);CHKERRQ(ierr);
686         if (quadJp) {
687           ierr = MatDenseGetColumn(quadJp,nadj,&xarr);CHKERRQ(ierr);
688           ierr = VecPlaceArray(ts->vec_drdp_col,xarr);CHKERRQ(ierr);
689           ierr = VecAXPY(ts->vecs_sensip[nadj],adjoint_time_step,ts->vec_drdp_col);CHKERRQ(ierr);
690           ierr = VecResetArray(ts->vec_drdp_col);CHKERRQ(ierr);
691           ierr = MatDenseRestoreColumn(quadJp,&xarr);CHKERRQ(ierr);
692         }
693       }
694     }
695   }
696 
697   th->status = TS_STEP_COMPLETE;
698   PetscFunctionReturn(0);
699 }
700 
701 static PetscErrorCode TSInterpolate_Theta(TS ts,PetscReal t,Vec X)
702 {
703   TS_Theta       *th = (TS_Theta*)ts->data;
704   PetscReal      dt  = t - ts->ptime;
705   PetscErrorCode ierr;
706 
707   PetscFunctionBegin;
708   ierr = VecCopy(ts->vec_sol,th->X);CHKERRQ(ierr);
709   if (th->endpoint) dt *= th->Theta;
710   ierr = VecWAXPY(X,dt,th->Xdot,th->X);CHKERRQ(ierr);
711   PetscFunctionReturn(0);
712 }
713 
714 static PetscErrorCode TSEvaluateWLTE_Theta(TS ts,NormType wnormtype,PetscInt *order,PetscReal *wlte)
715 {
716   TS_Theta       *th = (TS_Theta*)ts->data;
717   Vec            X = ts->vec_sol;      /* X = solution */
718   Vec            Y = th->vec_lte_work; /* Y = X + LTE  */
719   PetscReal      wltea,wlter;
720   PetscErrorCode ierr;
721 
722   PetscFunctionBegin;
723   if (!th->vec_sol_prev) {*wlte = -1; PetscFunctionReturn(0);}
724   /* Cannot compute LTE in first step or in restart after event */
725   if (ts->steprestart) {*wlte = -1; PetscFunctionReturn(0);}
726   /* Compute LTE using backward differences with non-constant time step */
727   {
728     PetscReal   h = ts->time_step, h_prev = ts->ptime - ts->ptime_prev;
729     PetscReal   a = 1 + h_prev/h;
730     PetscScalar scal[3]; Vec vecs[3];
731     scal[0] = +1/a; scal[1] = -1/(a-1); scal[2] = +1/(a*(a-1));
732     vecs[0] = X;    vecs[1] = th->X0;   vecs[2] = th->vec_sol_prev;
733     ierr = VecCopy(X,Y);CHKERRQ(ierr);
734     ierr = VecMAXPY(Y,3,scal,vecs);CHKERRQ(ierr);
735     ierr = TSErrorWeightedNorm(ts,X,Y,wnormtype,wlte,&wltea,&wlter);CHKERRQ(ierr);
736   }
737   if (order) *order = 2;
738   PetscFunctionReturn(0);
739 }
740 
741 static PetscErrorCode TSRollBack_Theta(TS ts)
742 {
743   TS_Theta       *th = (TS_Theta*)ts->data;
744   TS             quadts = ts->quadraturets;
745   PetscErrorCode ierr;
746 
747   PetscFunctionBegin;
748   ierr = VecCopy(th->X0,ts->vec_sol);CHKERRQ(ierr);
749   if (quadts && ts->costintegralfwd) {
750     ierr = VecCopy(th->VecCostIntegral0,quadts->vec_sol);CHKERRQ(ierr);
751   }
752   th->status = TS_STEP_INCOMPLETE;
753   if (ts->mat_sensip) {
754     ierr = MatCopy(th->MatFwdSensip0,ts->mat_sensip,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
755   }
756   if (quadts && quadts->mat_sensip) {
757     ierr = MatCopy(th->MatIntegralSensip0,quadts->mat_sensip,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
758   }
759   PetscFunctionReturn(0);
760 }
761 
762 static PetscErrorCode TSForwardStep_Theta(TS ts)
763 {
764   TS_Theta       *th = (TS_Theta*)ts->data;
765   TS             quadts = ts->quadraturets;
766   Mat            MatDeltaFwdSensip = th->MatDeltaFwdSensip;
767   Vec            VecDeltaFwdSensipCol = th->VecDeltaFwdSensipCol;
768   PetscInt       ntlm;
769   KSP            ksp;
770   Mat            J,Jpre,quadJ = NULL,quadJp = NULL;
771   PetscScalar    *barr,*xarr;
772   PetscReal      previous_shift;
773   PetscErrorCode ierr;
774 
775   PetscFunctionBegin;
776   previous_shift = th->shift;
777   ierr = MatCopy(ts->mat_sensip,th->MatFwdSensip0,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
778 
779   if (quadts && quadts->mat_sensip) {
780     ierr = MatCopy(quadts->mat_sensip,th->MatIntegralSensip0,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
781   }
782   ierr = SNESGetKSP(ts->snes,&ksp);CHKERRQ(ierr);
783   ierr = TSGetIJacobian(ts,&J,&Jpre,NULL,NULL);CHKERRQ(ierr);
784   if (quadts) {
785     ierr = TSGetRHSJacobian(quadts,&quadJ,NULL,NULL,NULL);CHKERRQ(ierr);
786     ierr = TSGetRHSJacobianP(quadts,&quadJp,NULL,NULL);CHKERRQ(ierr);
787   }
788 
789   /* Build RHS */
790   if (th->endpoint) { /* 2-stage method*/
791     th->shift = 1./((th->Theta-1.)*th->time_step0);
792     ierr = TSComputeIJacobian(ts,th->ptime0,th->X0,th->Xdot,th->shift,J,Jpre,PETSC_FALSE);CHKERRQ(ierr);
793     ierr = MatMatMult(J,ts->mat_sensip,MAT_REUSE_MATRIX,PETSC_DEFAULT,&MatDeltaFwdSensip);CHKERRQ(ierr);
794     ierr = MatScale(MatDeltaFwdSensip,(th->Theta-1.)/th->Theta);CHKERRQ(ierr);
795 
796     /* Add the f_p forcing terms */
797     if (ts->Jacp) {
798       ierr = VecZeroEntries(th->Xdot);CHKERRQ(ierr);
799       ierr = TSComputeIJacobianP(ts,th->ptime0,th->X0,th->Xdot,th->shift,ts->Jacp,PETSC_FALSE);CHKERRQ(ierr);
800       ierr = MatAXPY(MatDeltaFwdSensip,(th->Theta-1.)/th->Theta,ts->Jacp,SUBSET_NONZERO_PATTERN);CHKERRQ(ierr);
801       th->shift = previous_shift;
802       ierr = VecAXPBYPCZ(th->Xdot,-th->shift,th->shift,0,th->X0,ts->vec_sol);CHKERRQ(ierr);
803       ierr = TSComputeIJacobianP(ts,th->stage_time,ts->vec_sol,th->Xdot,th->shift,ts->Jacp,PETSC_FALSE);CHKERRQ(ierr);
804       ierr = MatAXPY(MatDeltaFwdSensip,-1.,ts->Jacp,SUBSET_NONZERO_PATTERN);CHKERRQ(ierr);
805     }
806   } else { /* 1-stage method */
807     th->shift = 0.0;
808     ierr = TSComputeIJacobian(ts,th->stage_time,th->X,th->Xdot,th->shift,J,Jpre,PETSC_FALSE);CHKERRQ(ierr);
809     ierr = MatMatMult(J,ts->mat_sensip,MAT_REUSE_MATRIX,PETSC_DEFAULT,&MatDeltaFwdSensip);CHKERRQ(ierr);
810     ierr = MatScale(MatDeltaFwdSensip,-1.);CHKERRQ(ierr);
811 
812     /* Add the f_p forcing terms */
813     if (ts->Jacp) {
814       th->shift = previous_shift;
815       ierr = VecAXPBYPCZ(th->Xdot,-th->shift,th->shift,0,th->X0,th->X);CHKERRQ(ierr);
816       ierr = TSComputeIJacobianP(ts,th->stage_time,th->X,th->Xdot,th->shift,ts->Jacp,PETSC_FALSE);CHKERRQ(ierr);
817       ierr = MatAXPY(MatDeltaFwdSensip,-1.,ts->Jacp,SUBSET_NONZERO_PATTERN);CHKERRQ(ierr);
818     }
819   }
820 
821   /* Build LHS */
822   th->shift = previous_shift; /* recover the previous shift used in TSStep_Theta() */
823   if (th->endpoint) {
824     ierr = TSComputeIJacobian(ts,th->stage_time,ts->vec_sol,th->Xdot,th->shift,J,Jpre,PETSC_FALSE);CHKERRQ(ierr);
825   } else {
826     ierr = TSComputeIJacobian(ts,th->stage_time,th->X,th->Xdot,th->shift,J,Jpre,PETSC_FALSE);CHKERRQ(ierr);
827   }
828   ierr = KSPSetOperators(ksp,J,Jpre);CHKERRQ(ierr);
829 
830   /*
831     Evaluate the first stage of integral gradients with the 2-stage method:
832     drdu|t_n*S(t_n) + drdp|t_n
833     This is done before the linear solve because the sensitivity variable S(t_n) will be propagated to S(t_{n+1})
834   */
835   if (th->endpoint) { /* 2-stage method only */
836     if (quadts && quadts->mat_sensip) {
837       ierr = TSComputeRHSJacobian(quadts,th->ptime0,th->X0,quadJ,NULL);CHKERRQ(ierr);
838       ierr = TSComputeRHSJacobianP(quadts,th->ptime0,th->X0,quadJp);CHKERRQ(ierr);
839       ierr = MatTransposeMatMult(ts->mat_sensip,quadJ,MAT_REUSE_MATRIX,PETSC_DEFAULT,&th->MatIntegralSensipTemp);CHKERRQ(ierr);
840       ierr = MatAXPY(th->MatIntegralSensipTemp,1,quadJp,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
841       ierr = MatAXPY(quadts->mat_sensip,th->time_step0*(1.-th->Theta),th->MatIntegralSensipTemp,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
842     }
843   }
844 
845   /* Solve the tangent linear equation for forward sensitivities to parameters */
846   for (ntlm=0; ntlm<th->num_tlm; ntlm++) {
847     KSPConvergedReason kspreason;
848     ierr = MatDenseGetColumn(MatDeltaFwdSensip,ntlm,&barr);CHKERRQ(ierr);
849     ierr = VecPlaceArray(VecDeltaFwdSensipCol,barr);CHKERRQ(ierr);
850     if (th->endpoint) {
851       ierr = MatDenseGetColumn(ts->mat_sensip,ntlm,&xarr);CHKERRQ(ierr);
852       ierr = VecPlaceArray(ts->vec_sensip_col,xarr);CHKERRQ(ierr);
853       ierr = KSPSolve(ksp,VecDeltaFwdSensipCol,ts->vec_sensip_col);CHKERRQ(ierr);
854       ierr = VecResetArray(ts->vec_sensip_col);CHKERRQ(ierr);
855       ierr = MatDenseRestoreColumn(ts->mat_sensip,&xarr);CHKERRQ(ierr);
856     } else {
857       ierr = KSPSolve(ksp,VecDeltaFwdSensipCol,VecDeltaFwdSensipCol);CHKERRQ(ierr);
858     }
859     ierr = KSPGetConvergedReason(ksp,&kspreason);CHKERRQ(ierr);
860     if (kspreason < 0) {
861       ts->reason = TSFORWARD_DIVERGED_LINEAR_SOLVE;
862       ierr = PetscInfo2(ts,"Step=%D, %Dth tangent linear solve, linear solve fails, stopping tangent linear solve\n",ts->steps,ntlm);CHKERRQ(ierr);
863     }
864     ierr = VecResetArray(VecDeltaFwdSensipCol);CHKERRQ(ierr);
865     ierr = MatDenseRestoreColumn(MatDeltaFwdSensip,&barr);CHKERRQ(ierr);
866   }
867 
868   /*
869     Evaluate the second stage of integral gradients with the 2-stage method:
870     drdu|t_{n+1}*S(t_{n+1}) + drdp|t_{n+1}
871   */
872   if (quadts && quadts->mat_sensip) {
873     if (!th->endpoint) {
874       ierr = MatAXPY(ts->mat_sensip,1,MatDeltaFwdSensip,SAME_NONZERO_PATTERN);CHKERRQ(ierr); /* stage sensitivity */
875       ierr = TSComputeRHSJacobian(quadts,th->stage_time,th->X,quadJ,NULL);CHKERRQ(ierr);
876       ierr = TSComputeRHSJacobianP(quadts,th->stage_time,th->X,quadJp);CHKERRQ(ierr);
877       ierr = MatTransposeMatMult(ts->mat_sensip,quadJ,MAT_REUSE_MATRIX,PETSC_DEFAULT,&th->MatIntegralSensipTemp);CHKERRQ(ierr);
878       ierr = MatAXPY(th->MatIntegralSensipTemp,1,quadJp,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
879       ierr = MatAXPY(quadts->mat_sensip,th->time_step0,th->MatIntegralSensipTemp,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
880       ierr = MatAXPY(ts->mat_sensip,(1.-th->Theta)/th->Theta,MatDeltaFwdSensip,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
881     } else {
882       ierr = TSComputeRHSJacobian(quadts,th->stage_time,ts->vec_sol,quadJ,NULL);CHKERRQ(ierr);
883       ierr = TSComputeRHSJacobianP(quadts,th->stage_time,ts->vec_sol,quadJp);CHKERRQ(ierr);
884       ierr = MatTransposeMatMult(ts->mat_sensip,quadJ,MAT_REUSE_MATRIX,PETSC_DEFAULT,&th->MatIntegralSensipTemp);CHKERRQ(ierr);
885       ierr = MatAXPY(th->MatIntegralSensipTemp,1,quadJp,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
886       ierr = MatAXPY(quadts->mat_sensip,th->time_step0*th->Theta,th->MatIntegralSensipTemp,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
887     }
888   } else {
889     if (!th->endpoint) {
890       ierr = MatAXPY(ts->mat_sensip,1./th->Theta,MatDeltaFwdSensip,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
891     }
892   }
893   PetscFunctionReturn(0);
894 }
895 
896 static PetscErrorCode TSForwardGetStages_Theta(TS ts,PetscInt *ns,Mat *stagesensip[])
897 {
898   TS_Theta       *th = (TS_Theta*)ts->data;
899 
900   PetscFunctionBegin;
901   if (ns) {
902     if (!th->endpoint && th->Theta != 1.0) *ns = 1; /* midpoint form */
903     else *ns = 2; /* endpoint form */
904   }
905   if (stagesensip) {
906     if (!th->endpoint && th->Theta != 1.0) {
907       th->MatFwdStages[0] = th->MatDeltaFwdSensip;
908     } else {
909       th->MatFwdStages[0] = th->MatFwdSensip0;
910       th->MatFwdStages[1] = ts->mat_sensip; /* stiffly accurate */
911     }
912     *stagesensip = th->MatFwdStages;
913   }
914   PetscFunctionReturn(0);
915 }
916 
917 /*------------------------------------------------------------*/
918 static PetscErrorCode TSReset_Theta(TS ts)
919 {
920   TS_Theta       *th = (TS_Theta*)ts->data;
921   PetscErrorCode ierr;
922 
923   PetscFunctionBegin;
924   ierr = VecDestroy(&th->X);CHKERRQ(ierr);
925   ierr = VecDestroy(&th->Xdot);CHKERRQ(ierr);
926   ierr = VecDestroy(&th->X0);CHKERRQ(ierr);
927   ierr = VecDestroy(&th->affine);CHKERRQ(ierr);
928 
929   ierr = VecDestroy(&th->vec_sol_prev);CHKERRQ(ierr);
930   ierr = VecDestroy(&th->vec_lte_work);CHKERRQ(ierr);
931 
932   ierr = VecDestroy(&th->VecCostIntegral0);CHKERRQ(ierr);
933   PetscFunctionReturn(0);
934 }
935 
936 static PetscErrorCode TSAdjointReset_Theta(TS ts)
937 {
938   TS_Theta       *th = (TS_Theta*)ts->data;
939   PetscErrorCode ierr;
940 
941   PetscFunctionBegin;
942   ierr = VecDestroyVecs(ts->numcost,&th->VecsDeltaLam);CHKERRQ(ierr);
943   ierr = VecDestroyVecs(ts->numcost,&th->VecsDeltaMu);CHKERRQ(ierr);
944   ierr = VecDestroyVecs(ts->numcost,&th->VecsDeltaLam2);CHKERRQ(ierr);
945   ierr = VecDestroyVecs(ts->numcost,&th->VecsDeltaMu2);CHKERRQ(ierr);
946   ierr = VecDestroyVecs(ts->numcost,&th->VecsSensiTemp);CHKERRQ(ierr);
947   ierr = VecDestroyVecs(ts->numcost,&th->VecsSensi2Temp);CHKERRQ(ierr);
948   PetscFunctionReturn(0);
949 }
950 
951 static PetscErrorCode TSDestroy_Theta(TS ts)
952 {
953   PetscErrorCode ierr;
954 
955   PetscFunctionBegin;
956   ierr = TSReset_Theta(ts);CHKERRQ(ierr);
957   if (ts->dm) {
958     ierr = DMCoarsenHookRemove(ts->dm,DMCoarsenHook_TSTheta,DMRestrictHook_TSTheta,ts);CHKERRQ(ierr);
959     ierr = DMSubDomainHookRemove(ts->dm,DMSubDomainHook_TSTheta,DMSubDomainRestrictHook_TSTheta,ts);CHKERRQ(ierr);
960   }
961   ierr = PetscFree(ts->data);CHKERRQ(ierr);
962   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSThetaGetTheta_C",NULL);CHKERRQ(ierr);
963   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSThetaSetTheta_C",NULL);CHKERRQ(ierr);
964   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSThetaGetEndpoint_C",NULL);CHKERRQ(ierr);
965   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSThetaSetEndpoint_C",NULL);CHKERRQ(ierr);
966   PetscFunctionReturn(0);
967 }
968 
969 /*
970   This defines the nonlinear equation that is to be solved with SNES
971   G(U) = F[t0+Theta*dt, U, (U-U0)*shift] = 0
972 
973   Note that U here is the stage argument. This means that U = U_{n+1} only if endpoint = true,
974   otherwise U = theta U_{n+1} + (1 - theta) U0, which for the case of implicit midpoint is
975   U = (U_{n+1} + U0)/2
976 */
977 static PetscErrorCode SNESTSFormFunction_Theta(SNES snes,Vec x,Vec y,TS ts)
978 {
979   TS_Theta       *th = (TS_Theta*)ts->data;
980   PetscErrorCode ierr;
981   Vec            X0,Xdot;
982   DM             dm,dmsave;
983   PetscReal      shift = th->shift;
984 
985   PetscFunctionBegin;
986   ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr);
987   /* When using the endpoint variant, this is actually 1/Theta * Xdot */
988   ierr = TSThetaGetX0AndXdot(ts,dm,&X0,&Xdot);CHKERRQ(ierr);
989   if (x != X0) {
990     ierr = VecAXPBYPCZ(Xdot,-shift,shift,0,X0,x);CHKERRQ(ierr);
991   } else {
992     ierr = VecZeroEntries(Xdot);CHKERRQ(ierr);
993   }
994   /* DM monkey-business allows user code to call TSGetDM() inside of functions evaluated on levels of FAS */
995   dmsave = ts->dm;
996   ts->dm = dm;
997   ierr   = TSComputeIFunction(ts,th->stage_time,x,Xdot,y,PETSC_FALSE);CHKERRQ(ierr);
998   ts->dm = dmsave;
999   ierr   = TSThetaRestoreX0AndXdot(ts,dm,&X0,&Xdot);CHKERRQ(ierr);
1000   PetscFunctionReturn(0);
1001 }
1002 
1003 static PetscErrorCode SNESTSFormJacobian_Theta(SNES snes,Vec x,Mat A,Mat B,TS ts)
1004 {
1005   TS_Theta       *th = (TS_Theta*)ts->data;
1006   PetscErrorCode ierr;
1007   Vec            Xdot;
1008   DM             dm,dmsave;
1009   PetscReal      shift = th->shift;
1010 
1011   PetscFunctionBegin;
1012   ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr);
1013   /* Xdot has already been computed in SNESTSFormFunction_Theta (SNES guarantees this) */
1014   ierr = TSThetaGetX0AndXdot(ts,dm,NULL,&Xdot);CHKERRQ(ierr);
1015 
1016   dmsave = ts->dm;
1017   ts->dm = dm;
1018   ierr   = TSComputeIJacobian(ts,th->stage_time,x,Xdot,shift,A,B,PETSC_FALSE);CHKERRQ(ierr);
1019   ts->dm = dmsave;
1020   ierr   = TSThetaRestoreX0AndXdot(ts,dm,NULL,&Xdot);CHKERRQ(ierr);
1021   PetscFunctionReturn(0);
1022 }
1023 
1024 static PetscErrorCode TSForwardSetUp_Theta(TS ts)
1025 {
1026   TS_Theta       *th = (TS_Theta*)ts->data;
1027   TS             quadts = ts->quadraturets;
1028   PetscErrorCode ierr;
1029 
1030   PetscFunctionBegin;
1031   /* combine sensitivities to parameters and sensitivities to initial values into one array */
1032   th->num_tlm = ts->num_parameters;
1033   ierr = MatDuplicate(ts->mat_sensip,MAT_DO_NOT_COPY_VALUES,&th->MatDeltaFwdSensip);CHKERRQ(ierr);
1034   if (quadts && quadts->mat_sensip) {
1035     ierr = MatDuplicate(quadts->mat_sensip,MAT_DO_NOT_COPY_VALUES,&th->MatIntegralSensipTemp);CHKERRQ(ierr);
1036     ierr = MatDuplicate(quadts->mat_sensip,MAT_DO_NOT_COPY_VALUES,&th->MatIntegralSensip0);CHKERRQ(ierr);
1037   }
1038   /* backup sensitivity results for roll-backs */
1039   ierr = MatDuplicate(ts->mat_sensip,MAT_DO_NOT_COPY_VALUES,&th->MatFwdSensip0);CHKERRQ(ierr);
1040 
1041   ierr = VecDuplicate(ts->vec_sol,&th->VecDeltaFwdSensipCol);CHKERRQ(ierr);
1042   PetscFunctionReturn(0);
1043 }
1044 
1045 static PetscErrorCode TSForwardReset_Theta(TS ts)
1046 {
1047   TS_Theta       *th = (TS_Theta*)ts->data;
1048   TS             quadts = ts->quadraturets;
1049   PetscErrorCode ierr;
1050 
1051   PetscFunctionBegin;
1052   if (quadts && quadts->mat_sensip) {
1053     ierr = MatDestroy(&th->MatIntegralSensipTemp);CHKERRQ(ierr);
1054     ierr = MatDestroy(&th->MatIntegralSensip0);CHKERRQ(ierr);
1055   }
1056   ierr = VecDestroy(&th->VecDeltaFwdSensipCol);CHKERRQ(ierr);
1057   ierr = MatDestroy(&th->MatDeltaFwdSensip);CHKERRQ(ierr);
1058   ierr = MatDestroy(&th->MatFwdSensip0);CHKERRQ(ierr);
1059   PetscFunctionReturn(0);
1060 }
1061 
1062 static PetscErrorCode TSSetUp_Theta(TS ts)
1063 {
1064   TS_Theta       *th = (TS_Theta*)ts->data;
1065   TS             quadts = ts->quadraturets;
1066   PetscBool      match;
1067   PetscErrorCode ierr;
1068 
1069   PetscFunctionBegin;
1070   if (!th->VecCostIntegral0 && quadts && ts->costintegralfwd) { /* back up cost integral */
1071     ierr = VecDuplicate(quadts->vec_sol,&th->VecCostIntegral0);CHKERRQ(ierr);
1072   }
1073   if (!th->X) {
1074     ierr = VecDuplicate(ts->vec_sol,&th->X);CHKERRQ(ierr);
1075   }
1076   if (!th->Xdot) {
1077     ierr = VecDuplicate(ts->vec_sol,&th->Xdot);CHKERRQ(ierr);
1078   }
1079   if (!th->X0) {
1080     ierr = VecDuplicate(ts->vec_sol,&th->X0);CHKERRQ(ierr);
1081   }
1082   if (th->endpoint) {
1083     ierr = VecDuplicate(ts->vec_sol,&th->affine);CHKERRQ(ierr);
1084   }
1085 
1086   th->order = (th->Theta == 0.5) ? 2 : 1;
1087   th->shift = 1/(th->Theta*ts->time_step);
1088 
1089   ierr = TSGetDM(ts,&ts->dm);CHKERRQ(ierr);
1090   ierr = DMCoarsenHookAdd(ts->dm,DMCoarsenHook_TSTheta,DMRestrictHook_TSTheta,ts);CHKERRQ(ierr);
1091   ierr = DMSubDomainHookAdd(ts->dm,DMSubDomainHook_TSTheta,DMSubDomainRestrictHook_TSTheta,ts);CHKERRQ(ierr);
1092 
1093   ierr = TSGetAdapt(ts,&ts->adapt);CHKERRQ(ierr);
1094   ierr = TSAdaptCandidatesClear(ts->adapt);CHKERRQ(ierr);
1095   ierr = PetscObjectTypeCompare((PetscObject)ts->adapt,TSADAPTNONE,&match);CHKERRQ(ierr);
1096   if (!match) {
1097     ierr = VecDuplicate(ts->vec_sol,&th->vec_sol_prev);CHKERRQ(ierr);
1098     ierr = VecDuplicate(ts->vec_sol,&th->vec_lte_work);CHKERRQ(ierr);
1099   }
1100   ierr = TSGetSNES(ts,&ts->snes);CHKERRQ(ierr);
1101 
1102   ts->stifflyaccurate = (!th->endpoint && th->Theta != 1.0) ? PETSC_FALSE : PETSC_TRUE;
1103   PetscFunctionReturn(0);
1104 }
1105 
1106 /*------------------------------------------------------------*/
1107 
1108 static PetscErrorCode TSAdjointSetUp_Theta(TS ts)
1109 {
1110   TS_Theta       *th = (TS_Theta*)ts->data;
1111   PetscErrorCode ierr;
1112 
1113   PetscFunctionBegin;
1114   ierr = VecDuplicateVecs(ts->vecs_sensi[0],ts->numcost,&th->VecsDeltaLam);CHKERRQ(ierr);
1115   ierr = VecDuplicateVecs(ts->vecs_sensi[0],ts->numcost,&th->VecsSensiTemp);CHKERRQ(ierr);
1116   if (ts->vecs_sensip) {
1117     ierr = VecDuplicateVecs(ts->vecs_sensip[0],ts->numcost,&th->VecsDeltaMu);CHKERRQ(ierr);
1118   }
1119   if (ts->vecs_sensi2) {
1120     ierr = VecDuplicateVecs(ts->vecs_sensi[0],ts->numcost,&th->VecsDeltaLam2);CHKERRQ(ierr);
1121     ierr = VecDuplicateVecs(ts->vecs_sensi2[0],ts->numcost,&th->VecsSensi2Temp);CHKERRQ(ierr);
1122     /* hack ts to make implicit TS solver work when users provide only explicit versions of callbacks (RHSFunction,RHSJacobian,RHSHessian etc.) */
1123     if (!ts->ihessianproduct_fuu) ts->vecs_fuu = ts->vecs_guu;
1124     if (!ts->ihessianproduct_fup) ts->vecs_fup = ts->vecs_gup;
1125   }
1126   if (ts->vecs_sensi2p) {
1127     ierr = VecDuplicateVecs(ts->vecs_sensi2p[0],ts->numcost,&th->VecsDeltaMu2);CHKERRQ(ierr);
1128     /* hack ts to make implicit TS solver work when users provide only explicit versions of callbacks (RHSFunction,RHSJacobian,RHSHessian etc.) */
1129     if (!ts->ihessianproduct_fpu) ts->vecs_fpu = ts->vecs_gpu;
1130     if (!ts->ihessianproduct_fpp) ts->vecs_fpp = ts->vecs_gpp;
1131   }
1132   PetscFunctionReturn(0);
1133 }
1134 
1135 static PetscErrorCode TSSetFromOptions_Theta(PetscOptionItems *PetscOptionsObject,TS ts)
1136 {
1137   TS_Theta       *th = (TS_Theta*)ts->data;
1138   PetscErrorCode ierr;
1139 
1140   PetscFunctionBegin;
1141   ierr = PetscOptionsHead(PetscOptionsObject,"Theta ODE solver options");CHKERRQ(ierr);
1142   {
1143     ierr = PetscOptionsReal("-ts_theta_theta","Location of stage (0<Theta<=1)","TSThetaSetTheta",th->Theta,&th->Theta,NULL);CHKERRQ(ierr);
1144     ierr = PetscOptionsBool("-ts_theta_endpoint","Use the endpoint instead of midpoint form of the Theta method","TSThetaSetEndpoint",th->endpoint,&th->endpoint,NULL);CHKERRQ(ierr);
1145     ierr = PetscOptionsBool("-ts_theta_initial_guess_extrapolate","Extrapolate stage initial guess from previous solution (sometimes unstable)","TSThetaSetExtrapolate",th->extrapolate,&th->extrapolate,NULL);CHKERRQ(ierr);
1146   }
1147   ierr = PetscOptionsTail();CHKERRQ(ierr);
1148   PetscFunctionReturn(0);
1149 }
1150 
1151 static PetscErrorCode TSView_Theta(TS ts,PetscViewer viewer)
1152 {
1153   TS_Theta       *th = (TS_Theta*)ts->data;
1154   PetscBool      iascii;
1155   PetscErrorCode ierr;
1156 
1157   PetscFunctionBegin;
1158   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
1159   if (iascii) {
1160     ierr = PetscViewerASCIIPrintf(viewer,"  Theta=%g\n",(double)th->Theta);CHKERRQ(ierr);
1161     ierr = PetscViewerASCIIPrintf(viewer,"  Extrapolation=%s\n",th->extrapolate ? "yes" : "no");CHKERRQ(ierr);
1162   }
1163   PetscFunctionReturn(0);
1164 }
1165 
1166 static PetscErrorCode TSThetaGetTheta_Theta(TS ts,PetscReal *theta)
1167 {
1168   TS_Theta *th = (TS_Theta*)ts->data;
1169 
1170   PetscFunctionBegin;
1171   *theta = th->Theta;
1172   PetscFunctionReturn(0);
1173 }
1174 
1175 static PetscErrorCode TSThetaSetTheta_Theta(TS ts,PetscReal theta)
1176 {
1177   TS_Theta *th = (TS_Theta*)ts->data;
1178 
1179   PetscFunctionBegin;
1180   if (theta <= 0 || 1 < theta) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Theta %g not in range (0,1]",(double)theta);
1181   th->Theta = theta;
1182   th->order = (th->Theta == 0.5) ? 2 : 1;
1183   PetscFunctionReturn(0);
1184 }
1185 
1186 static PetscErrorCode TSThetaGetEndpoint_Theta(TS ts,PetscBool *endpoint)
1187 {
1188   TS_Theta *th = (TS_Theta*)ts->data;
1189 
1190   PetscFunctionBegin;
1191   *endpoint = th->endpoint;
1192   PetscFunctionReturn(0);
1193 }
1194 
1195 static PetscErrorCode TSThetaSetEndpoint_Theta(TS ts,PetscBool flg)
1196 {
1197   TS_Theta *th = (TS_Theta*)ts->data;
1198 
1199   PetscFunctionBegin;
1200   th->endpoint = flg;
1201   PetscFunctionReturn(0);
1202 }
1203 
1204 #if defined(PETSC_HAVE_COMPLEX)
1205 static PetscErrorCode TSComputeLinearStability_Theta(TS ts,PetscReal xr,PetscReal xi,PetscReal *yr,PetscReal *yi)
1206 {
1207   PetscComplex   z   = xr + xi*PETSC_i,f;
1208   TS_Theta       *th = (TS_Theta*)ts->data;
1209   const PetscReal one = 1.0;
1210 
1211   PetscFunctionBegin;
1212   f   = (one + (one - th->Theta)*z)/(one - th->Theta*z);
1213   *yr = PetscRealPartComplex(f);
1214   *yi = PetscImaginaryPartComplex(f);
1215   PetscFunctionReturn(0);
1216 }
1217 #endif
1218 
1219 static PetscErrorCode TSGetStages_Theta(TS ts,PetscInt *ns,Vec *Y[])
1220 {
1221   TS_Theta       *th = (TS_Theta*)ts->data;
1222 
1223   PetscFunctionBegin;
1224   if (ns) {
1225     if (!th->endpoint && th->Theta != 1.0) *ns = 1; /* midpoint form */
1226     else *ns = 2; /* endpoint form */
1227   }
1228   if (Y) {
1229     if (!th->endpoint && th->Theta != 1.0) {
1230       th->Stages[0] = th->X;
1231     } else {
1232       th->Stages[0] = th->X0;
1233       th->Stages[1] = ts->vec_sol; /* stiffly accurate */
1234     }
1235     *Y = th->Stages;
1236   }
1237   PetscFunctionReturn(0);
1238 }
1239 
1240 /* ------------------------------------------------------------ */
1241 /*MC
1242       TSTHETA - DAE solver using the implicit Theta method
1243 
1244    Level: beginner
1245 
1246    Options Database:
1247 +  -ts_theta_theta <Theta> - Location of stage (0<Theta<=1)
1248 .  -ts_theta_endpoint <flag> - Use the endpoint (like Crank-Nicholson) instead of midpoint form of the Theta method
1249 -  -ts_theta_initial_guess_extrapolate <flg> - Extrapolate stage initial guess from previous solution (sometimes unstable)
1250 
1251    Notes:
1252 $  -ts_type theta -ts_theta_theta 1.0 corresponds to backward Euler (TSBEULER)
1253 $  -ts_type theta -ts_theta_theta 0.5 corresponds to the implicit midpoint rule
1254 $  -ts_type theta -ts_theta_theta 0.5 -ts_theta_endpoint corresponds to Crank-Nicholson (TSCN)
1255 
1256    The endpoint variant of the Theta method and backward Euler can be applied to DAE. The midpoint variant is not suitable for DAEs because it is not stiffly accurate.
1257 
1258    The midpoint variant is cast as a 1-stage implicit Runge-Kutta method.
1259 
1260 .vb
1261   Theta | Theta
1262   -------------
1263         |  1
1264 .ve
1265 
1266    For the default Theta=0.5, this is also known as the implicit midpoint rule.
1267 
1268    When the endpoint variant is chosen, the method becomes a 2-stage method with first stage explicit:
1269 
1270 .vb
1271   0 | 0         0
1272   1 | 1-Theta   Theta
1273   -------------------
1274     | 1-Theta   Theta
1275 .ve
1276 
1277    For the default Theta=0.5, this is the trapezoid rule (also known as Crank-Nicolson, see TSCN).
1278 
1279    To apply a diagonally implicit RK method to DAE, the stage formula
1280 
1281 $  Y_i = X + h sum_j a_ij Y'_j
1282 
1283    is interpreted as a formula for Y'_i in terms of Y_i and known values (Y'_j, j<i)
1284 
1285 .seealso:  TSCreate(), TS, TSSetType(), TSCN, TSBEULER, TSThetaSetTheta(), TSThetaSetEndpoint()
1286 
1287 M*/
1288 PETSC_EXTERN PetscErrorCode TSCreate_Theta(TS ts)
1289 {
1290   TS_Theta       *th;
1291   PetscErrorCode ierr;
1292 
1293   PetscFunctionBegin;
1294   ts->ops->reset           = TSReset_Theta;
1295   ts->ops->adjointreset    = TSAdjointReset_Theta;
1296   ts->ops->destroy         = TSDestroy_Theta;
1297   ts->ops->view            = TSView_Theta;
1298   ts->ops->setup           = TSSetUp_Theta;
1299   ts->ops->adjointsetup    = TSAdjointSetUp_Theta;
1300   ts->ops->adjointreset    = TSAdjointReset_Theta;
1301   ts->ops->step            = TSStep_Theta;
1302   ts->ops->interpolate     = TSInterpolate_Theta;
1303   ts->ops->evaluatewlte    = TSEvaluateWLTE_Theta;
1304   ts->ops->rollback        = TSRollBack_Theta;
1305   ts->ops->setfromoptions  = TSSetFromOptions_Theta;
1306   ts->ops->snesfunction    = SNESTSFormFunction_Theta;
1307   ts->ops->snesjacobian    = SNESTSFormJacobian_Theta;
1308 #if defined(PETSC_HAVE_COMPLEX)
1309   ts->ops->linearstability = TSComputeLinearStability_Theta;
1310 #endif
1311   ts->ops->getstages       = TSGetStages_Theta;
1312   ts->ops->adjointstep     = TSAdjointStep_Theta;
1313   ts->ops->adjointintegral = TSAdjointCostIntegral_Theta;
1314   ts->ops->forwardintegral = TSForwardCostIntegral_Theta;
1315   ts->default_adapt_type   = TSADAPTNONE;
1316 
1317   ts->ops->forwardsetup     = TSForwardSetUp_Theta;
1318   ts->ops->forwardreset     = TSForwardReset_Theta;
1319   ts->ops->forwardstep      = TSForwardStep_Theta;
1320   ts->ops->forwardgetstages = TSForwardGetStages_Theta;
1321 
1322   ts->usessnes = PETSC_TRUE;
1323 
1324   ierr = PetscNewLog(ts,&th);CHKERRQ(ierr);
1325   ts->data = (void*)th;
1326 
1327   th->VecsDeltaLam    = NULL;
1328   th->VecsDeltaMu     = NULL;
1329   th->VecsSensiTemp   = NULL;
1330   th->VecsSensi2Temp  = NULL;
1331 
1332   th->extrapolate = PETSC_FALSE;
1333   th->Theta       = 0.5;
1334   th->order       = 2;
1335   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSThetaGetTheta_C",TSThetaGetTheta_Theta);CHKERRQ(ierr);
1336   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSThetaSetTheta_C",TSThetaSetTheta_Theta);CHKERRQ(ierr);
1337   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSThetaGetEndpoint_C",TSThetaGetEndpoint_Theta);CHKERRQ(ierr);
1338   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSThetaSetEndpoint_C",TSThetaSetEndpoint_Theta);CHKERRQ(ierr);
1339   PetscFunctionReturn(0);
1340 }
1341 
1342 /*@
1343   TSThetaGetTheta - Get the abscissa of the stage in (0,1].
1344 
1345   Not Collective
1346 
1347   Input Parameter:
1348 .  ts - timestepping context
1349 
1350   Output Parameter:
1351 .  theta - stage abscissa
1352 
1353   Note:
1354   Use of this function is normally only required to hack TSTHETA to use a modified integration scheme.
1355 
1356   Level: Advanced
1357 
1358 .seealso: TSThetaSetTheta()
1359 @*/
1360 PetscErrorCode  TSThetaGetTheta(TS ts,PetscReal *theta)
1361 {
1362   PetscErrorCode ierr;
1363 
1364   PetscFunctionBegin;
1365   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1366   PetscValidPointer(theta,2);
1367   ierr = PetscUseMethod(ts,"TSThetaGetTheta_C",(TS,PetscReal*),(ts,theta));CHKERRQ(ierr);
1368   PetscFunctionReturn(0);
1369 }
1370 
1371 /*@
1372   TSThetaSetTheta - Set the abscissa of the stage in (0,1].
1373 
1374   Not Collective
1375 
1376   Input Parameter:
1377 +  ts - timestepping context
1378 -  theta - stage abscissa
1379 
1380   Options Database:
1381 .  -ts_theta_theta <theta>
1382 
1383   Level: Intermediate
1384 
1385 .seealso: TSThetaGetTheta()
1386 @*/
1387 PetscErrorCode  TSThetaSetTheta(TS ts,PetscReal theta)
1388 {
1389   PetscErrorCode ierr;
1390 
1391   PetscFunctionBegin;
1392   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1393   ierr = PetscTryMethod(ts,"TSThetaSetTheta_C",(TS,PetscReal),(ts,theta));CHKERRQ(ierr);
1394   PetscFunctionReturn(0);
1395 }
1396 
1397 /*@
1398   TSThetaGetEndpoint - Gets whether to use the endpoint variant of the method (e.g. trapezoid/Crank-Nicolson instead of midpoint rule).
1399 
1400   Not Collective
1401 
1402   Input Parameter:
1403 .  ts - timestepping context
1404 
1405   Output Parameter:
1406 .  endpoint - PETSC_TRUE when using the endpoint variant
1407 
1408   Level: Advanced
1409 
1410 .seealso: TSThetaSetEndpoint(), TSTHETA, TSCN
1411 @*/
1412 PetscErrorCode TSThetaGetEndpoint(TS ts,PetscBool *endpoint)
1413 {
1414   PetscErrorCode ierr;
1415 
1416   PetscFunctionBegin;
1417   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1418   PetscValidPointer(endpoint,2);
1419   ierr = PetscUseMethod(ts,"TSThetaGetEndpoint_C",(TS,PetscBool*),(ts,endpoint));CHKERRQ(ierr);
1420   PetscFunctionReturn(0);
1421 }
1422 
1423 /*@
1424   TSThetaSetEndpoint - Sets whether to use the endpoint variant of the method (e.g. trapezoid/Crank-Nicolson instead of midpoint rule).
1425 
1426   Not Collective
1427 
1428   Input Parameter:
1429 +  ts - timestepping context
1430 -  flg - PETSC_TRUE to use the endpoint variant
1431 
1432   Options Database:
1433 .  -ts_theta_endpoint <flg>
1434 
1435   Level: Intermediate
1436 
1437 .seealso: TSTHETA, TSCN
1438 @*/
1439 PetscErrorCode TSThetaSetEndpoint(TS ts,PetscBool flg)
1440 {
1441   PetscErrorCode ierr;
1442 
1443   PetscFunctionBegin;
1444   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1445   ierr = PetscTryMethod(ts,"TSThetaSetEndpoint_C",(TS,PetscBool),(ts,flg));CHKERRQ(ierr);
1446   PetscFunctionReturn(0);
1447 }
1448 
1449 /*
1450  * TSBEULER and TSCN are straightforward specializations of TSTHETA.
1451  * The creation functions for these specializations are below.
1452  */
1453 
1454 static PetscErrorCode TSSetUp_BEuler(TS ts)
1455 {
1456   TS_Theta       *th = (TS_Theta*)ts->data;
1457   PetscErrorCode ierr;
1458 
1459   PetscFunctionBegin;
1460   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");
1461   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");
1462   ierr = TSSetUp_Theta(ts);CHKERRQ(ierr);
1463   PetscFunctionReturn(0);
1464 }
1465 
1466 static PetscErrorCode TSView_BEuler(TS ts,PetscViewer viewer)
1467 {
1468   PetscFunctionBegin;
1469   PetscFunctionReturn(0);
1470 }
1471 
1472 /*MC
1473       TSBEULER - ODE solver using the implicit backward Euler method
1474 
1475   Level: beginner
1476 
1477   Notes:
1478   TSBEULER is equivalent to TSTHETA with Theta=1.0
1479 
1480 $  -ts_type theta -ts_theta_theta 1.0
1481 
1482 .seealso:  TSCreate(), TS, TSSetType(), TSEULER, TSCN, TSTHETA
1483 
1484 M*/
1485 PETSC_EXTERN PetscErrorCode TSCreate_BEuler(TS ts)
1486 {
1487   PetscErrorCode ierr;
1488 
1489   PetscFunctionBegin;
1490   ierr = TSCreate_Theta(ts);CHKERRQ(ierr);
1491   ierr = TSThetaSetTheta(ts,1.0);CHKERRQ(ierr);
1492   ierr = TSThetaSetEndpoint(ts,PETSC_FALSE);CHKERRQ(ierr);
1493   ts->ops->setup = TSSetUp_BEuler;
1494   ts->ops->view  = TSView_BEuler;
1495   PetscFunctionReturn(0);
1496 }
1497 
1498 static PetscErrorCode TSSetUp_CN(TS ts)
1499 {
1500   TS_Theta       *th = (TS_Theta*)ts->data;
1501   PetscErrorCode ierr;
1502 
1503   PetscFunctionBegin;
1504   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");
1505   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");
1506   ierr = TSSetUp_Theta(ts);CHKERRQ(ierr);
1507   PetscFunctionReturn(0);
1508 }
1509 
1510 static PetscErrorCode TSView_CN(TS ts,PetscViewer viewer)
1511 {
1512   PetscFunctionBegin;
1513   PetscFunctionReturn(0);
1514 }
1515 
1516 /*MC
1517       TSCN - ODE solver using the implicit Crank-Nicolson method.
1518 
1519   Level: beginner
1520 
1521   Notes:
1522   TSCN is equivalent to TSTHETA with Theta=0.5 and the "endpoint" option set. I.e.
1523 
1524 $  -ts_type theta -ts_theta_theta 0.5 -ts_theta_endpoint
1525 
1526 .seealso:  TSCreate(), TS, TSSetType(), TSBEULER, TSTHETA
1527 
1528 M*/
1529 PETSC_EXTERN PetscErrorCode TSCreate_CN(TS ts)
1530 {
1531   PetscErrorCode ierr;
1532 
1533   PetscFunctionBegin;
1534   ierr = TSCreate_Theta(ts);CHKERRQ(ierr);
1535   ierr = TSThetaSetTheta(ts,0.5);CHKERRQ(ierr);
1536   ierr = TSThetaSetEndpoint(ts,PETSC_TRUE);CHKERRQ(ierr);
1537   ts->ops->setup = TSSetUp_CN;
1538   ts->ops->view  = TSView_CN;
1539   PetscFunctionReturn(0);
1540 }
1541