xref: /petsc/src/ts/interface/sensitivity/tssen.c (revision 13af1a74d217ab121f5f45cf6cdd8dc51f8ba927)
1814e85d6SHong Zhang #include <petsc/private/tsimpl.h>        /*I "petscts.h"  I*/
2814e85d6SHong Zhang #include <petscdraw.h>
3814e85d6SHong Zhang 
433f72c5dSHong Zhang PetscLogEvent TS_AdjointStep,TS_ForwardStep,TS_JacobianPEval;
5814e85d6SHong Zhang 
6814e85d6SHong Zhang /* ------------------------ Sensitivity Context ---------------------------*/
7814e85d6SHong Zhang 
8814e85d6SHong Zhang /*@C
9b5b4017aSHong Zhang   TSSetRHSJacobianP - Sets the function that computes the Jacobian of G w.r.t. the parameters P where U_t = G(U,P,t), as well as the location to store the matrix.
10814e85d6SHong Zhang 
11814e85d6SHong Zhang   Logically Collective on TS
12814e85d6SHong Zhang 
13814e85d6SHong Zhang   Input Parameters:
14b5b4017aSHong Zhang + ts - TS context obtained from TSCreate()
15b5b4017aSHong Zhang . Amat - JacobianP matrix
16b5b4017aSHong Zhang . func - function
17b5b4017aSHong Zhang - ctx - [optional] user-defined function context
18814e85d6SHong Zhang 
19814e85d6SHong Zhang   Calling sequence of func:
20814e85d6SHong Zhang $ func (TS ts,PetscReal t,Vec y,Mat A,void *ctx);
21814e85d6SHong Zhang +   t - current timestep
22c9ad9de0SHong Zhang .   U - input vector (current ODE solution)
23814e85d6SHong Zhang .   A - output matrix
24814e85d6SHong Zhang -   ctx - [optional] user-defined function context
25814e85d6SHong Zhang 
26814e85d6SHong Zhang   Level: intermediate
27814e85d6SHong Zhang 
28814e85d6SHong Zhang   Notes:
29814e85d6SHong Zhang     Amat has the same number of rows and the same row parallel layout as u, Amat has the same number of columns and parallel layout as p
30814e85d6SHong Zhang 
31814e85d6SHong Zhang .keywords: TS, sensitivity
32814e85d6SHong Zhang .seealso:
33814e85d6SHong Zhang @*/
34814e85d6SHong Zhang PetscErrorCode TSSetRHSJacobianP(TS ts,Mat Amat,PetscErrorCode (*func)(TS,PetscReal,Vec,Mat,void*),void *ctx)
35814e85d6SHong Zhang {
36814e85d6SHong Zhang   PetscErrorCode ierr;
37814e85d6SHong Zhang 
38814e85d6SHong Zhang   PetscFunctionBegin;
39814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
40814e85d6SHong Zhang   PetscValidHeaderSpecific(Amat,MAT_CLASSID,2);
41814e85d6SHong Zhang 
42814e85d6SHong Zhang   ts->rhsjacobianp    = func;
43814e85d6SHong Zhang   ts->rhsjacobianpctx = ctx;
44814e85d6SHong Zhang   if(Amat) {
45814e85d6SHong Zhang     ierr = PetscObjectReference((PetscObject)Amat);CHKERRQ(ierr);
4633f72c5dSHong Zhang     ierr = MatDestroy(&ts->Jacprhs);CHKERRQ(ierr);
4733f72c5dSHong Zhang     ts->Jacprhs = Amat;
48814e85d6SHong Zhang   }
49814e85d6SHong Zhang   PetscFunctionReturn(0);
50814e85d6SHong Zhang }
51814e85d6SHong Zhang 
52814e85d6SHong Zhang /*@C
53814e85d6SHong Zhang   TSComputeRHSJacobianP - Runs the user-defined JacobianP function.
54814e85d6SHong Zhang 
55814e85d6SHong Zhang   Collective on TS
56814e85d6SHong Zhang 
57814e85d6SHong Zhang   Input Parameters:
58814e85d6SHong Zhang . ts   - The TS context obtained from TSCreate()
59814e85d6SHong Zhang 
60814e85d6SHong Zhang   Level: developer
61814e85d6SHong Zhang 
62814e85d6SHong Zhang .keywords: TS, sensitivity
63814e85d6SHong Zhang .seealso: TSSetRHSJacobianP()
64814e85d6SHong Zhang @*/
65c9ad9de0SHong Zhang PetscErrorCode TSComputeRHSJacobianP(TS ts,PetscReal t,Vec U,Mat Amat)
66814e85d6SHong Zhang {
67814e85d6SHong Zhang   PetscErrorCode ierr;
68814e85d6SHong Zhang 
69814e85d6SHong Zhang   PetscFunctionBegin;
7033f72c5dSHong Zhang   if (!Amat) PetscFunctionReturn(0);
71814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
72c9ad9de0SHong Zhang   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
73814e85d6SHong Zhang 
74814e85d6SHong Zhang   PetscStackPush("TS user JacobianP function for sensitivity analysis");
75c9ad9de0SHong Zhang   ierr = (*ts->rhsjacobianp)(ts,t,U,Amat,ts->rhsjacobianpctx);CHKERRQ(ierr);
76814e85d6SHong Zhang   PetscStackPop;
77814e85d6SHong Zhang   PetscFunctionReturn(0);
78814e85d6SHong Zhang }
79814e85d6SHong Zhang 
80814e85d6SHong Zhang /*@C
8133f72c5dSHong Zhang   TSSetIJacobianP - Sets the function that computes the Jacobian of F w.r.t. the parameters P where F(Udot,U,t) = G(U,P,t), as well as the location to store the matrix.
8233f72c5dSHong Zhang 
8333f72c5dSHong Zhang   Logically Collective on TS
8433f72c5dSHong Zhang 
8533f72c5dSHong Zhang   Input Parameters:
8633f72c5dSHong Zhang + ts - TS context obtained from TSCreate()
8733f72c5dSHong Zhang . Amat - JacobianP matrix
8833f72c5dSHong Zhang . func - function
8933f72c5dSHong Zhang - ctx - [optional] user-defined function context
9033f72c5dSHong Zhang 
9133f72c5dSHong Zhang   Calling sequence of func:
9233f72c5dSHong Zhang $ func (TS ts,PetscReal t,Vec y,Mat A,void *ctx);
9333f72c5dSHong Zhang +   t - current timestep
9433f72c5dSHong Zhang .   U - input vector (current ODE solution)
9533f72c5dSHong Zhang .   Udot - time derivative of state vector
9633f72c5dSHong Zhang .   shift - shift to apply, see note below
9733f72c5dSHong Zhang .   A - output matrix
9833f72c5dSHong Zhang -   ctx - [optional] user-defined function context
9933f72c5dSHong Zhang 
10033f72c5dSHong Zhang   Level: intermediate
10133f72c5dSHong Zhang 
10233f72c5dSHong Zhang   Notes:
10333f72c5dSHong Zhang     Amat has the same number of rows and the same row parallel layout as u, Amat has the same number of columns and parallel layout as p
10433f72c5dSHong Zhang 
10533f72c5dSHong Zhang .keywords: TS, sensitivity
10633f72c5dSHong Zhang .seealso:
10733f72c5dSHong Zhang @*/
10833f72c5dSHong Zhang PetscErrorCode TSSetIJacobianP(TS ts,Mat Amat,PetscErrorCode (*func)(TS,PetscReal,Vec,Vec,PetscReal,Mat,void*),void *ctx)
10933f72c5dSHong Zhang {
11033f72c5dSHong Zhang   PetscErrorCode ierr;
11133f72c5dSHong Zhang 
11233f72c5dSHong Zhang   PetscFunctionBegin;
11333f72c5dSHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
11433f72c5dSHong Zhang   PetscValidHeaderSpecific(Amat,MAT_CLASSID,2);
11533f72c5dSHong Zhang 
11633f72c5dSHong Zhang   ts->ijacobianp    = func;
11733f72c5dSHong Zhang   ts->ijacobianpctx = ctx;
11833f72c5dSHong Zhang   if(Amat) {
11933f72c5dSHong Zhang     ierr = PetscObjectReference((PetscObject)Amat);CHKERRQ(ierr);
12033f72c5dSHong Zhang     ierr = MatDestroy(&ts->Jacp);CHKERRQ(ierr);
12133f72c5dSHong Zhang     ts->Jacp = Amat;
12233f72c5dSHong Zhang   }
12333f72c5dSHong Zhang   PetscFunctionReturn(0);
12433f72c5dSHong Zhang }
12533f72c5dSHong Zhang 
12633f72c5dSHong Zhang /*@C
12733f72c5dSHong Zhang   TSComputeIJacobianP - Runs the user-defined IJacobianP function.
12833f72c5dSHong Zhang 
12933f72c5dSHong Zhang   Collective on TS
13033f72c5dSHong Zhang 
13133f72c5dSHong Zhang   Input Parameters:
13233f72c5dSHong Zhang + ts - the TS context
13333f72c5dSHong Zhang . t - current timestep
13433f72c5dSHong Zhang . U - state vector
13533f72c5dSHong Zhang . Udot - time derivative of state vector
13633f72c5dSHong Zhang . shift - shift to apply, see note below
13733f72c5dSHong Zhang - imex - flag indicates if the method is IMEX so that the RHSJacobian should be kept separate
13833f72c5dSHong Zhang 
13933f72c5dSHong Zhang   Output Parameters:
14033f72c5dSHong Zhang . A - Jacobian matrix
14133f72c5dSHong Zhang 
14233f72c5dSHong Zhang   Level: developer
14333f72c5dSHong Zhang 
14433f72c5dSHong Zhang .keywords: TS, sensitivity
14533f72c5dSHong Zhang .seealso: TSSetIJacobianP()
14633f72c5dSHong Zhang @*/
14733f72c5dSHong Zhang PetscErrorCode TSComputeIJacobianP(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal shift,Mat Amat,PetscBool imex)
14833f72c5dSHong Zhang {
14933f72c5dSHong Zhang   PetscErrorCode ierr;
15033f72c5dSHong Zhang 
15133f72c5dSHong Zhang   PetscFunctionBegin;
15233f72c5dSHong Zhang   if (!Amat) PetscFunctionReturn(0);
15333f72c5dSHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
15433f72c5dSHong Zhang   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
15533f72c5dSHong Zhang   PetscValidHeaderSpecific(Udot,VEC_CLASSID,4);
15633f72c5dSHong Zhang 
15733f72c5dSHong Zhang   ierr = PetscLogEventBegin(TS_JacobianPEval,ts,U,Amat,0);CHKERRQ(ierr);
15833f72c5dSHong Zhang   if (ts->ijacobianp) {
15933f72c5dSHong Zhang     PetscStackPush("TS user JacobianP function for sensitivity analysis");
16033f72c5dSHong Zhang     ierr = (*ts->ijacobianp)(ts,t,U,Udot,shift,Amat,ts->ijacobianpctx);CHKERRQ(ierr);
16133f72c5dSHong Zhang     PetscStackPop;
16233f72c5dSHong Zhang   }
16333f72c5dSHong Zhang   if (imex) {
16433f72c5dSHong Zhang     if (!ts->ijacobianp) {  /* system was written as Udot = G(t,U) */
16533f72c5dSHong Zhang       PetscBool assembled;
16633f72c5dSHong Zhang       ierr = MatZeroEntries(Amat);CHKERRQ(ierr);
16733f72c5dSHong Zhang       ierr = MatAssembled(Amat,&assembled);CHKERRQ(ierr);
16833f72c5dSHong Zhang       if (!assembled) {
16933f72c5dSHong Zhang         ierr = MatAssemblyBegin(Amat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
17033f72c5dSHong Zhang         ierr = MatAssemblyEnd(Amat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
17133f72c5dSHong Zhang       }
17233f72c5dSHong Zhang     }
17333f72c5dSHong Zhang   } else {
17433f72c5dSHong Zhang     if (ts->rhsjacobianp) {
17533f72c5dSHong Zhang       ierr = TSComputeRHSJacobianP(ts,t,U,ts->Jacprhs);CHKERRQ(ierr);
17633f72c5dSHong Zhang     }
17733f72c5dSHong Zhang     if (ts->Jacprhs == Amat) { /* No IJacobian, so we only have the RHS matrix */
17833f72c5dSHong Zhang       ierr = MatScale(Amat,-1);CHKERRQ(ierr);
17933f72c5dSHong Zhang     } else if (ts->Jacprhs) { /* Both IJacobian and RHSJacobian */
18033f72c5dSHong Zhang       MatStructure axpy = DIFFERENT_NONZERO_PATTERN;
18133f72c5dSHong Zhang       if (!ts->ijacobianp) { /* No IJacobianp provided, but we have a separate RHS matrix */
18233f72c5dSHong Zhang         ierr = MatZeroEntries(Amat);CHKERRQ(ierr);
18333f72c5dSHong Zhang       }
18433f72c5dSHong Zhang       ierr = MatAXPY(Amat,-1,ts->Jacprhs,axpy);CHKERRQ(ierr);
18533f72c5dSHong Zhang     }
18633f72c5dSHong Zhang   }
18733f72c5dSHong Zhang   ierr = PetscLogEventEnd(TS_JacobianPEval,ts,U,Amat,0);CHKERRQ(ierr);
18833f72c5dSHong Zhang   PetscFunctionReturn(0);
18933f72c5dSHong Zhang }
19033f72c5dSHong Zhang 
19133f72c5dSHong Zhang /*@C
192814e85d6SHong Zhang     TSSetCostIntegrand - Sets the routine for evaluating the integral term in one or more cost functions
193814e85d6SHong Zhang 
194814e85d6SHong Zhang     Logically Collective on TS
195814e85d6SHong Zhang 
196814e85d6SHong Zhang     Input Parameters:
197814e85d6SHong Zhang +   ts - the TS context obtained from TSCreate()
198814e85d6SHong Zhang .   numcost - number of gradients to be computed, this is the number of cost functions
199814e85d6SHong Zhang .   costintegral - vector that stores the integral values
200814e85d6SHong Zhang .   rf - routine for evaluating the integrand function
201c9ad9de0SHong Zhang .   drduf - function that computes the gradients of the r's with respect to u
202814e85d6SHong Zhang .   drdpf - function that computes the gradients of the r's with respect to p, can be NULL if parametric sensitivity is not desired (mu=NULL)
203814e85d6SHong Zhang .   fwd - flag indicating whether to evaluate cost integral in the forward run or the adjoint run
204814e85d6SHong Zhang -   ctx - [optional] user-defined context for private data for the function evaluation routine (may be NULL)
205814e85d6SHong Zhang 
206814e85d6SHong Zhang     Calling sequence of rf:
207c9ad9de0SHong Zhang $   PetscErrorCode rf(TS ts,PetscReal t,Vec U,Vec F,void *ctx);
208814e85d6SHong Zhang 
209c9ad9de0SHong Zhang     Calling sequence of drduf:
210c9ad9de0SHong Zhang $   PetscErroCode drduf(TS ts,PetscReal t,Vec U,Vec *dRdU,void *ctx);
211814e85d6SHong Zhang 
212814e85d6SHong Zhang     Calling sequence of drdpf:
213c9ad9de0SHong Zhang $   PetscErroCode drdpf(TS ts,PetscReal t,Vec U,Vec *dRdP,void *ctx);
214814e85d6SHong Zhang 
215814e85d6SHong Zhang     Level: intermediate
216814e85d6SHong Zhang 
217814e85d6SHong Zhang     Notes:
218814e85d6SHong Zhang     For optimization there is usually a single cost function (numcost = 1). For sensitivities there may be multiple cost functions
219814e85d6SHong Zhang 
220814e85d6SHong Zhang .keywords: TS, sensitivity analysis, timestep, set, quadrature, function
221814e85d6SHong Zhang 
222814e85d6SHong Zhang .seealso: TSSetRHSJacobianP(), TSGetCostGradients(), TSSetCostGradients()
223814e85d6SHong Zhang @*/
224814e85d6SHong Zhang PetscErrorCode TSSetCostIntegrand(TS ts,PetscInt numcost,Vec costintegral,PetscErrorCode (*rf)(TS,PetscReal,Vec,Vec,void*),
225c9ad9de0SHong Zhang                                                           PetscErrorCode (*drduf)(TS,PetscReal,Vec,Vec*,void*),
226814e85d6SHong Zhang                                                           PetscErrorCode (*drdpf)(TS,PetscReal,Vec,Vec*,void*),
227814e85d6SHong Zhang                                                           PetscBool fwd,void *ctx)
228814e85d6SHong Zhang {
229814e85d6SHong Zhang   PetscErrorCode ierr;
230814e85d6SHong Zhang 
231814e85d6SHong Zhang   PetscFunctionBegin;
232814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
233814e85d6SHong Zhang   if (costintegral) PetscValidHeaderSpecific(costintegral,VEC_CLASSID,3);
234814e85d6SHong Zhang   if (ts->numcost && ts->numcost!=numcost) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"The number of cost functions (2rd parameter of TSSetCostIntegrand()) is inconsistent with the one set by TSSetCostGradients() or TSForwardSetIntegralGradients()");
235814e85d6SHong Zhang   if (!ts->numcost) ts->numcost=numcost;
236814e85d6SHong Zhang 
237814e85d6SHong Zhang   if (costintegral) {
238814e85d6SHong Zhang     ierr = PetscObjectReference((PetscObject)costintegral);CHKERRQ(ierr);
239814e85d6SHong Zhang     ierr = VecDestroy(&ts->vec_costintegral);CHKERRQ(ierr);
240814e85d6SHong Zhang     ts->vec_costintegral = costintegral;
241814e85d6SHong Zhang   } else {
242814e85d6SHong Zhang     if (!ts->vec_costintegral) { /* Create a seq vec if user does not provide one */
243814e85d6SHong Zhang       ierr = VecCreateSeq(PETSC_COMM_SELF,numcost,&ts->vec_costintegral);CHKERRQ(ierr);
244814e85d6SHong Zhang     } else {
245814e85d6SHong Zhang       ierr = VecSet(ts->vec_costintegral,0.0);CHKERRQ(ierr);
246814e85d6SHong Zhang     }
247814e85d6SHong Zhang   }
248814e85d6SHong Zhang   if (!ts->vec_costintegrand) {
249814e85d6SHong Zhang     ierr = VecDuplicate(ts->vec_costintegral,&ts->vec_costintegrand);CHKERRQ(ierr);
250814e85d6SHong Zhang   } else {
251814e85d6SHong Zhang     ierr = VecSet(ts->vec_costintegrand,0.0);CHKERRQ(ierr);
252814e85d6SHong Zhang   }
253814e85d6SHong Zhang   ts->costintegralfwd  = fwd; /* Evaluate the cost integral in forward run if fwd is true */
254814e85d6SHong Zhang   ts->costintegrand    = rf;
255814e85d6SHong Zhang   ts->costintegrandctx = ctx;
256c9ad9de0SHong Zhang   ts->drdufunction     = drduf;
257814e85d6SHong Zhang   ts->drdpfunction     = drdpf;
258814e85d6SHong Zhang   PetscFunctionReturn(0);
259814e85d6SHong Zhang }
260814e85d6SHong Zhang 
261b5b4017aSHong Zhang /*@C
262814e85d6SHong Zhang    TSGetCostIntegral - Returns the values of the integral term in the cost functions.
263814e85d6SHong Zhang    It is valid to call the routine after a backward run.
264814e85d6SHong Zhang 
265814e85d6SHong Zhang    Not Collective
266814e85d6SHong Zhang 
267814e85d6SHong Zhang    Input Parameter:
268814e85d6SHong Zhang .  ts - the TS context obtained from TSCreate()
269814e85d6SHong Zhang 
270814e85d6SHong Zhang    Output Parameter:
271814e85d6SHong Zhang .  v - the vector containing the integrals for each cost function
272814e85d6SHong Zhang 
273814e85d6SHong Zhang    Level: intermediate
274814e85d6SHong Zhang 
275814e85d6SHong Zhang .seealso: TSSetCostIntegrand()
276814e85d6SHong Zhang 
277814e85d6SHong Zhang .keywords: TS, sensitivity analysis
278814e85d6SHong Zhang @*/
279814e85d6SHong Zhang PetscErrorCode  TSGetCostIntegral(TS ts,Vec *v)
280814e85d6SHong Zhang {
281814e85d6SHong Zhang   PetscFunctionBegin;
282814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
283814e85d6SHong Zhang   PetscValidPointer(v,2);
284814e85d6SHong Zhang   *v = ts->vec_costintegral;
285814e85d6SHong Zhang   PetscFunctionReturn(0);
286814e85d6SHong Zhang }
287814e85d6SHong Zhang 
288b5b4017aSHong Zhang /*@C
289814e85d6SHong Zhang    TSComputeCostIntegrand - Evaluates the integral function in the cost functions.
290814e85d6SHong Zhang 
291814e85d6SHong Zhang    Input Parameters:
292814e85d6SHong Zhang +  ts - the TS context
293814e85d6SHong Zhang .  t - current time
294c9ad9de0SHong Zhang -  U - state vector, i.e. current solution
295814e85d6SHong Zhang 
296814e85d6SHong Zhang    Output Parameter:
297c9ad9de0SHong Zhang .  Q - vector of size numcost to hold the outputs
298814e85d6SHong Zhang 
299814e85d6SHong Zhang    Note:
300814e85d6SHong Zhang    Most users should not need to explicitly call this routine, as it
301814e85d6SHong Zhang    is used internally within the sensitivity analysis context.
302814e85d6SHong Zhang 
303814e85d6SHong Zhang    Level: developer
304814e85d6SHong Zhang 
305814e85d6SHong Zhang .keywords: TS, compute
306814e85d6SHong Zhang 
307814e85d6SHong Zhang .seealso: TSSetCostIntegrand()
308814e85d6SHong Zhang @*/
309c9ad9de0SHong Zhang PetscErrorCode TSComputeCostIntegrand(TS ts,PetscReal t,Vec U,Vec Q)
310814e85d6SHong Zhang {
311814e85d6SHong Zhang   PetscErrorCode ierr;
312814e85d6SHong Zhang 
313814e85d6SHong Zhang   PetscFunctionBegin;
314814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
315c9ad9de0SHong Zhang   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
316c9ad9de0SHong Zhang   PetscValidHeaderSpecific(Q,VEC_CLASSID,4);
317814e85d6SHong Zhang 
318c9ad9de0SHong Zhang   ierr = PetscLogEventBegin(TS_FunctionEval,ts,U,Q,0);CHKERRQ(ierr);
319814e85d6SHong Zhang   if (ts->costintegrand) {
320814e85d6SHong Zhang     PetscStackPush("TS user integrand in the cost function");
321c9ad9de0SHong Zhang     ierr = (*ts->costintegrand)(ts,t,U,Q,ts->costintegrandctx);CHKERRQ(ierr);
322814e85d6SHong Zhang     PetscStackPop;
323814e85d6SHong Zhang   } else {
324c9ad9de0SHong Zhang     ierr = VecZeroEntries(Q);CHKERRQ(ierr);
325814e85d6SHong Zhang   }
326814e85d6SHong Zhang 
327c9ad9de0SHong Zhang   ierr = PetscLogEventEnd(TS_FunctionEval,ts,U,Q,0);CHKERRQ(ierr);
328814e85d6SHong Zhang   PetscFunctionReturn(0);
329814e85d6SHong Zhang }
330814e85d6SHong Zhang 
331b5b4017aSHong Zhang /*@C
332c9ad9de0SHong Zhang   TSComputeDRDUFunction - Runs the user-defined DRDU function.
333814e85d6SHong Zhang 
334814e85d6SHong Zhang   Collective on TS
335814e85d6SHong Zhang 
336814e85d6SHong Zhang   Input Parameters:
337c9ad9de0SHong Zhang + ts - the TS context obtained from TSCreate()
338c9ad9de0SHong Zhang . t - current time
339c9ad9de0SHong Zhang - U - stata vector
340c9ad9de0SHong Zhang 
341c9ad9de0SHong Zhang   Output Parameters:
342b5b4017aSHong Zhang . DRDU - vector array to hold the outputs
343814e85d6SHong Zhang 
344814e85d6SHong Zhang   Notes:
345c9ad9de0SHong Zhang   TSComputeDRDUFunction() is typically used for sensitivity implementation,
346814e85d6SHong Zhang   so most users would not generally call this routine themselves.
347814e85d6SHong Zhang 
348814e85d6SHong Zhang   Level: developer
349814e85d6SHong Zhang 
350814e85d6SHong Zhang .keywords: TS, sensitivity
351814e85d6SHong Zhang .seealso: TSSetCostIntegrand()
352814e85d6SHong Zhang @*/
353c9ad9de0SHong Zhang PetscErrorCode TSComputeDRDUFunction(TS ts,PetscReal t,Vec U,Vec *DRDU)
354814e85d6SHong Zhang {
355814e85d6SHong Zhang   PetscErrorCode ierr;
356814e85d6SHong Zhang 
357814e85d6SHong Zhang   PetscFunctionBegin;
35833f72c5dSHong Zhang   if (!DRDU) PetscFunctionReturn(0);
359814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
360c9ad9de0SHong Zhang   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
361814e85d6SHong Zhang 
362c9ad9de0SHong Zhang   PetscStackPush("TS user DRDU function for sensitivity analysis");
363c9ad9de0SHong Zhang   ierr = (*ts->drdufunction)(ts,t,U,DRDU,ts->costintegrandctx); CHKERRQ(ierr);
364814e85d6SHong Zhang   PetscStackPop;
365814e85d6SHong Zhang   PetscFunctionReturn(0);
366814e85d6SHong Zhang }
367814e85d6SHong Zhang 
368b5b4017aSHong Zhang /*@C
369814e85d6SHong Zhang   TSComputeDRDPFunction - Runs the user-defined DRDP function.
370814e85d6SHong Zhang 
371814e85d6SHong Zhang   Collective on TS
372814e85d6SHong Zhang 
373814e85d6SHong Zhang   Input Parameters:
374c9ad9de0SHong Zhang + ts - the TS context obtained from TSCreate()
375c9ad9de0SHong Zhang . t - current time
376c9ad9de0SHong Zhang - U - stata vector
377c9ad9de0SHong Zhang 
378c9ad9de0SHong Zhang   Output Parameters:
379b5b4017aSHong Zhang . DRDP - vector array to hold the outputs
380814e85d6SHong Zhang 
381814e85d6SHong Zhang   Notes:
382c9ad9de0SHong Zhang   TSComputeDRDPFunction() is typically used for sensitivity implementation,
383814e85d6SHong Zhang   so most users would not generally call this routine themselves.
384814e85d6SHong Zhang 
385814e85d6SHong Zhang   Level: developer
386814e85d6SHong Zhang 
387814e85d6SHong Zhang .keywords: TS, sensitivity
388814e85d6SHong Zhang .seealso: TSSetCostIntegrand()
389814e85d6SHong Zhang @*/
390c9ad9de0SHong Zhang PetscErrorCode TSComputeDRDPFunction(TS ts,PetscReal t,Vec U,Vec *DRDP)
391814e85d6SHong Zhang {
392814e85d6SHong Zhang   PetscErrorCode ierr;
393814e85d6SHong Zhang 
394814e85d6SHong Zhang   PetscFunctionBegin;
39533f72c5dSHong Zhang   if (!DRDP) PetscFunctionReturn(0);
396814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
397c9ad9de0SHong Zhang   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
398814e85d6SHong Zhang 
399814e85d6SHong Zhang   PetscStackPush("TS user DRDP function for sensitivity analysis");
400c9ad9de0SHong Zhang   ierr = (*ts->drdpfunction)(ts,t,U,DRDP,ts->costintegrandctx); CHKERRQ(ierr);
401814e85d6SHong Zhang   PetscStackPop;
402814e85d6SHong Zhang   PetscFunctionReturn(0);
403814e85d6SHong Zhang }
404814e85d6SHong Zhang 
405b5b4017aSHong Zhang /*@C
406b5b4017aSHong Zhang   TSSetIHessianProduct - Sets the function that computes the vector-Hessian-vector product. The Hessian is the second-order derivative of F (IFunction) w.r.t. the state variable.
407b5b4017aSHong Zhang 
408b5b4017aSHong Zhang   Logically Collective on TS
409b5b4017aSHong Zhang 
410b5b4017aSHong Zhang   Input Parameters:
411b5b4017aSHong Zhang + ts - TS context obtained from TSCreate()
412b5b4017aSHong Zhang . ihp1 - an array of vectors storing the result of vector-Hessian-vector product for F_UU
413b5b4017aSHong Zhang . hessianproductfunc1 - vector-Hessian-vector product function for F_UU
414b5b4017aSHong Zhang . ihp2 - an array of vectors storing the result of vector-Hessian-vector product for F_UP
415b5b4017aSHong Zhang . hessianproductfunc2 - vector-Hessian-vector product function for F_UP
416b5b4017aSHong Zhang . ihp3 - an array of vectors storing the result of vector-Hessian-vector product for F_PU
417b5b4017aSHong Zhang . hessianproductfunc3 - vector-Hessian-vector product function for F_PU
418b5b4017aSHong Zhang . ihp4 - an array of vectors storing the result of vector-Hessian-vector product for F_PP
419b5b4017aSHong Zhang . hessianproductfunc4 - vector-Hessian-vector product function for F_PP
420b5b4017aSHong Zhang 
421b5b4017aSHong Zhang   Calling sequence of ihessianproductfunc:
422b5b4017aSHong Zhang $ ihessianproductfunc (TS ts,PetscReal t,Vec U,Vec Vl,Vec Vr,Vec VHV,void *ctx);
423b5b4017aSHong Zhang +   t - current timestep
424b5b4017aSHong Zhang .   U - input vector (current ODE solution)
425b5b4017aSHong Zhang .   Vl - input vector to be left-multiplied with the Hessian
426b5b4017aSHong Zhang .   Vr - input vector to be right-multiplied with the Hessian
427b5b4017aSHong Zhang .   VHV - output vector for vector-Hessian-vector product
428b5b4017aSHong Zhang -   ctx - [optional] user-defined function context
429b5b4017aSHong Zhang 
430b5b4017aSHong Zhang   Level: intermediate
431b5b4017aSHong Zhang 
432b5b4017aSHong Zhang Note: The first Hessian function and the working array are required.
433b5b4017aSHong Zhang 
434b5b4017aSHong Zhang .keywords: TS, sensitivity
435b5b4017aSHong Zhang 
436b5b4017aSHong Zhang .seealso:
437b5b4017aSHong Zhang @*/
438b5b4017aSHong Zhang PetscErrorCode TSSetIHessianProduct(TS ts,Vec *ihp1,PetscErrorCode (*ihessianproductfunc1)(TS,PetscReal,Vec,Vec*,Vec,Vec*,void*),
439b5b4017aSHong Zhang                                           Vec *ihp2,PetscErrorCode (*ihessianproductfunc2)(TS,PetscReal,Vec,Vec*,Vec,Vec*,void*),
440b5b4017aSHong Zhang                                           Vec *ihp3,PetscErrorCode (*ihessianproductfunc3)(TS,PetscReal,Vec,Vec*,Vec,Vec*,void*),
441b5b4017aSHong Zhang                                           Vec *ihp4,PetscErrorCode (*ihessianproductfunc4)(TS,PetscReal,Vec,Vec*,Vec,Vec*,void*),
442b5b4017aSHong Zhang                                     void *ctx)
443b5b4017aSHong Zhang {
444b5b4017aSHong Zhang   PetscFunctionBegin;
445b5b4017aSHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
446b5b4017aSHong Zhang   PetscValidPointer(ihp1,2);
447b5b4017aSHong Zhang 
448b5b4017aSHong Zhang   ts->ihessianproductctx = ctx;
449b5b4017aSHong Zhang   if (ihp1) ts->vecs_fuu = ihp1;
450b5b4017aSHong Zhang   if (ihp2) ts->vecs_fup = ihp2;
451b5b4017aSHong Zhang   if (ihp3) ts->vecs_fpu = ihp3;
452b5b4017aSHong Zhang   if (ihp4) ts->vecs_fpp = ihp4;
453b5b4017aSHong Zhang   ts->ihessianproduct_fuu = ihessianproductfunc1;
454b5b4017aSHong Zhang   ts->ihessianproduct_fup = ihessianproductfunc2;
455b5b4017aSHong Zhang   ts->ihessianproduct_fpu = ihessianproductfunc3;
456b5b4017aSHong Zhang   ts->ihessianproduct_fpp = ihessianproductfunc4;
457b5b4017aSHong Zhang   PetscFunctionReturn(0);
458b5b4017aSHong Zhang }
459b5b4017aSHong Zhang 
460b5b4017aSHong Zhang /*@C
461b5b4017aSHong Zhang   TSComputeIHessianProductFunction1 - Runs the user-defined vector-Hessian-vector product function for Fuu.
462b5b4017aSHong Zhang 
463b5b4017aSHong Zhang   Collective on TS
464b5b4017aSHong Zhang 
465b5b4017aSHong Zhang   Input Parameters:
466b5b4017aSHong Zhang . ts   - The TS context obtained from TSCreate()
467b5b4017aSHong Zhang 
468b5b4017aSHong Zhang   Notes:
469b5b4017aSHong Zhang   TSComputeIHessianProductFunction1() is typically used for sensitivity implementation,
470b5b4017aSHong Zhang   so most users would not generally call this routine themselves.
471b5b4017aSHong Zhang 
472b5b4017aSHong Zhang   Level: developer
473b5b4017aSHong Zhang 
474b5b4017aSHong Zhang .keywords: TS, sensitivity
475b5b4017aSHong Zhang 
476b5b4017aSHong Zhang .seealso: TSSetIHessianProduct()
477b5b4017aSHong Zhang @*/
478b5b4017aSHong Zhang PetscErrorCode TSComputeIHessianProductFunction1(TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV)
479b5b4017aSHong Zhang {
480b5b4017aSHong Zhang   PetscErrorCode ierr;
481b5b4017aSHong Zhang 
482b5b4017aSHong Zhang   PetscFunctionBegin;
48333f72c5dSHong Zhang   if (!VHV) PetscFunctionReturn(0);
484b5b4017aSHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
485b5b4017aSHong Zhang   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
486b5b4017aSHong Zhang 
48767633408SHong Zhang   if (ts->ihessianproduct_fuu) {
488b5b4017aSHong Zhang     PetscStackPush("TS user IHessianProduct function 1 for sensitivity analysis");
489b5b4017aSHong Zhang     ierr = (*ts->ihessianproduct_fuu)(ts,t,U,Vl,Vr,VHV,ts->ihessianproductctx);CHKERRQ(ierr);
490b5b4017aSHong Zhang     PetscStackPop;
49167633408SHong Zhang   }
49267633408SHong Zhang   /* does not consider IMEX for now, so either IHessian or RHSHessian will be calculated, using the same output VHV */
49367633408SHong Zhang   if (ts->rhshessianproduct_guu) {
49467633408SHong Zhang     PetscInt nadj;
49567633408SHong Zhang     ierr = TSComputeRHSHessianProductFunction1(ts,t,U,Vl,Vr,VHV);CHKERRQ(ierr);
49667633408SHong Zhang     for (nadj=0; nadj<ts->numcost; nadj++) {
49767633408SHong Zhang       ierr = VecScale(VHV[nadj],-1);CHKERRQ(ierr);
49867633408SHong Zhang     }
49967633408SHong Zhang   }
500b5b4017aSHong Zhang   PetscFunctionReturn(0);
501b5b4017aSHong Zhang }
502b5b4017aSHong Zhang 
503b5b4017aSHong Zhang /*@C
504b5b4017aSHong Zhang   TSComputeIHessianProductFunction2 - Runs the user-defined vector-Hessian-vector product function for Fup.
505b5b4017aSHong Zhang 
506b5b4017aSHong Zhang   Collective on TS
507b5b4017aSHong Zhang 
508b5b4017aSHong Zhang   Input Parameters:
509b5b4017aSHong Zhang . ts   - The TS context obtained from TSCreate()
510b5b4017aSHong Zhang 
511b5b4017aSHong Zhang   Notes:
512b5b4017aSHong Zhang   TSComputeIHessianProductFunction2() is typically used for sensitivity implementation,
513b5b4017aSHong Zhang   so most users would not generally call this routine themselves.
514b5b4017aSHong Zhang 
515b5b4017aSHong Zhang   Level: developer
516b5b4017aSHong Zhang 
517b5b4017aSHong Zhang .keywords: TS, sensitivity
518b5b4017aSHong Zhang 
519b5b4017aSHong Zhang .seealso: TSSetIHessianProduct()
520b5b4017aSHong Zhang @*/
521b5b4017aSHong Zhang PetscErrorCode TSComputeIHessianProductFunction2(TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV)
522b5b4017aSHong Zhang {
523b5b4017aSHong Zhang   PetscErrorCode ierr;
524b5b4017aSHong Zhang 
525b5b4017aSHong Zhang   PetscFunctionBegin;
52633f72c5dSHong Zhang   if (!VHV) PetscFunctionReturn(0);
527b5b4017aSHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
528b5b4017aSHong Zhang   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
529b5b4017aSHong Zhang 
53067633408SHong Zhang   if (ts->ihessianproduct_fup) {
531b5b4017aSHong Zhang     PetscStackPush("TS user IHessianProduct function 2 for sensitivity analysis");
532b5b4017aSHong Zhang     ierr = (*ts->ihessianproduct_fup)(ts,t,U,Vl,Vr,VHV,ts->ihessianproductctx);CHKERRQ(ierr);
533b5b4017aSHong Zhang     PetscStackPop;
53467633408SHong Zhang   }
53567633408SHong Zhang   /* does not consider IMEX for now, so either IHessian or RHSHessian will be calculated, using the same output VHV */
53667633408SHong Zhang   if (ts->rhshessianproduct_gup) {
53767633408SHong Zhang     PetscInt nadj;
53867633408SHong Zhang     ierr = TSComputeRHSHessianProductFunction2(ts,t,U,Vl,Vr,VHV);CHKERRQ(ierr);
53967633408SHong Zhang     for (nadj=0; nadj<ts->numcost; nadj++) {
54067633408SHong Zhang       ierr = VecScale(VHV[nadj],-1);CHKERRQ(ierr);
54167633408SHong Zhang     }
54267633408SHong Zhang   }
543b5b4017aSHong Zhang   PetscFunctionReturn(0);
544b5b4017aSHong Zhang }
545b5b4017aSHong Zhang 
546b5b4017aSHong Zhang /*@C
547b5b4017aSHong Zhang   TSComputeIHessianProductFunction3 - Runs the user-defined vector-Hessian-vector product function for Fpu.
548b5b4017aSHong Zhang 
549b5b4017aSHong Zhang   Collective on TS
550b5b4017aSHong Zhang 
551b5b4017aSHong Zhang   Input Parameters:
552b5b4017aSHong Zhang . ts   - The TS context obtained from TSCreate()
553b5b4017aSHong Zhang 
554b5b4017aSHong Zhang   Notes:
555b5b4017aSHong Zhang   TSComputeIHessianProductFunction3() is typically used for sensitivity implementation,
556b5b4017aSHong Zhang   so most users would not generally call this routine themselves.
557b5b4017aSHong Zhang 
558b5b4017aSHong Zhang   Level: developer
559b5b4017aSHong Zhang 
560b5b4017aSHong Zhang .keywords: TS, sensitivity
561b5b4017aSHong Zhang 
562b5b4017aSHong Zhang .seealso: TSSetIHessianProduct()
563b5b4017aSHong Zhang @*/
564b5b4017aSHong Zhang PetscErrorCode TSComputeIHessianProductFunction3(TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV)
565b5b4017aSHong Zhang {
566b5b4017aSHong Zhang   PetscErrorCode ierr;
567b5b4017aSHong Zhang 
568b5b4017aSHong Zhang   PetscFunctionBegin;
56933f72c5dSHong Zhang   if (!VHV) PetscFunctionReturn(0);
570b5b4017aSHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
571b5b4017aSHong Zhang   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
572b5b4017aSHong Zhang 
57367633408SHong Zhang   if (ts->ihessianproduct_fpu) {
574b5b4017aSHong Zhang     PetscStackPush("TS user IHessianProduct function 3 for sensitivity analysis");
575b5b4017aSHong Zhang     ierr = (*ts->ihessianproduct_fpu)(ts,t,U,Vl,Vr,VHV,ts->ihessianproductctx);CHKERRQ(ierr);
576b5b4017aSHong Zhang     PetscStackPop;
57767633408SHong Zhang   }
57867633408SHong Zhang   /* does not consider IMEX for now, so either IHessian or RHSHessian will be calculated, using the same output VHV */
57967633408SHong Zhang   if (ts->rhshessianproduct_gpu) {
58067633408SHong Zhang     PetscInt nadj;
58167633408SHong Zhang     ierr = TSComputeRHSHessianProductFunction3(ts,t,U,Vl,Vr,VHV);CHKERRQ(ierr);
58267633408SHong Zhang     for (nadj=0; nadj<ts->numcost; nadj++) {
58367633408SHong Zhang       ierr = VecScale(VHV[nadj],-1);CHKERRQ(ierr);
58467633408SHong Zhang     }
58567633408SHong Zhang   }
586b5b4017aSHong Zhang   PetscFunctionReturn(0);
587b5b4017aSHong Zhang }
588b5b4017aSHong Zhang 
589b5b4017aSHong Zhang /*@C
590b5b4017aSHong Zhang   TSComputeIHessianProductFunction4 - Runs the user-defined vector-Hessian-vector product function for Fpp.
591b5b4017aSHong Zhang 
592b5b4017aSHong Zhang   Collective on TS
593b5b4017aSHong Zhang 
594b5b4017aSHong Zhang   Input Parameters:
595b5b4017aSHong Zhang . ts   - The TS context obtained from TSCreate()
596b5b4017aSHong Zhang 
597b5b4017aSHong Zhang   Notes:
598b5b4017aSHong Zhang   TSComputeIHessianProductFunction4() is typically used for sensitivity implementation,
599b5b4017aSHong Zhang   so most users would not generally call this routine themselves.
600b5b4017aSHong Zhang 
601b5b4017aSHong Zhang   Level: developer
602b5b4017aSHong Zhang 
603b5b4017aSHong Zhang .keywords: TS, sensitivity
604b5b4017aSHong Zhang 
605b5b4017aSHong Zhang .seealso: TSSetIHessianProduct()
606b5b4017aSHong Zhang @*/
607b5b4017aSHong Zhang PetscErrorCode TSComputeIHessianProductFunction4(TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV)
608b5b4017aSHong Zhang {
609b5b4017aSHong Zhang   PetscErrorCode ierr;
610b5b4017aSHong Zhang 
611b5b4017aSHong Zhang   PetscFunctionBegin;
61233f72c5dSHong Zhang   if (!VHV) PetscFunctionReturn(0);
613b5b4017aSHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
614b5b4017aSHong Zhang   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
615b5b4017aSHong Zhang 
61667633408SHong Zhang   if (ts->ihessianproduct_fpp) {
617b5b4017aSHong Zhang     PetscStackPush("TS user IHessianProduct function 3 for sensitivity analysis");
618b5b4017aSHong Zhang     ierr = (*ts->ihessianproduct_fpp)(ts,t,U,Vl,Vr,VHV,ts->ihessianproductctx);CHKERRQ(ierr);
619b5b4017aSHong Zhang     PetscStackPop;
62067633408SHong Zhang   }
62167633408SHong Zhang   /* does not consider IMEX for now, so either IHessian or RHSHessian will be calculated, using the same output VHV */
62267633408SHong Zhang   if (ts->rhshessianproduct_gpp) {
62367633408SHong Zhang     PetscInt nadj;
62467633408SHong Zhang     ierr = TSComputeRHSHessianProductFunction4(ts,t,U,Vl,Vr,VHV);CHKERRQ(ierr);
62567633408SHong Zhang     for (nadj=0; nadj<ts->numcost; nadj++) {
62667633408SHong Zhang       ierr = VecScale(VHV[nadj],-1);CHKERRQ(ierr);
62767633408SHong Zhang     }
62867633408SHong Zhang   }
629b5b4017aSHong Zhang   PetscFunctionReturn(0);
630b5b4017aSHong Zhang }
631b5b4017aSHong Zhang 
632*13af1a74SHong Zhang /*@C
633*13af1a74SHong Zhang   TSSetRHSHessianProduct - Sets the function that computes the vecotr-Hessian-vector product. The Hessian is the second-order derivative of G (RHSFunction) w.r.t. the state variable.
634*13af1a74SHong Zhang 
635*13af1a74SHong Zhang   Logically Collective on TS
636*13af1a74SHong Zhang 
637*13af1a74SHong Zhang   Input Parameters:
638*13af1a74SHong Zhang + ts - TS context obtained from TSCreate()
639*13af1a74SHong Zhang . rhshp1 - an array of vectors storing the result of vector-Hessian-vector product for G_UU
640*13af1a74SHong Zhang . hessianproductfunc1 - vector-Hessian-vector product function for G_UU
641*13af1a74SHong Zhang . rhshp2 - an array of vectors storing the result of vector-Hessian-vector product for G_UP
642*13af1a74SHong Zhang . hessianproductfunc2 - vector-Hessian-vector product function for G_UP
643*13af1a74SHong Zhang . rhshp3 - an array of vectors storing the result of vector-Hessian-vector product for G_PU
644*13af1a74SHong Zhang . hessianproductfunc3 - vector-Hessian-vector product function for G_PU
645*13af1a74SHong Zhang . rhshp4 - an array of vectors storing the result of vector-Hessian-vector product for G_PP
646*13af1a74SHong Zhang . hessianproductfunc4 - vector-Hessian-vector product function for G_PP
647*13af1a74SHong Zhang 
648*13af1a74SHong Zhang   Calling sequence of ihessianproductfunc:
649*13af1a74SHong Zhang $ rhshessianproductfunc (TS ts,PetscReal t,Vec U,Vec Vl,Vec Vr,Vec VHV,void *ctx);
650*13af1a74SHong Zhang +   t - current timestep
651*13af1a74SHong Zhang .   U - input vector (current ODE solution)
652*13af1a74SHong Zhang .   Vl - input vector to be left-multiplied with the Hessian
653*13af1a74SHong Zhang .   Vr - input vector to be right-multiplied with the Hessian
654*13af1a74SHong Zhang .   VHV - output vector for vector-Hessian-vector product
655*13af1a74SHong Zhang -   ctx - [optional] user-defined function context
656*13af1a74SHong Zhang 
657*13af1a74SHong Zhang   Level: intermediate
658*13af1a74SHong Zhang 
659*13af1a74SHong Zhang Note: The first Hessian function and the working array are required.
660*13af1a74SHong Zhang 
661*13af1a74SHong Zhang .keywords: TS, sensitivity
662*13af1a74SHong Zhang 
663*13af1a74SHong Zhang .seealso:
664*13af1a74SHong Zhang @*/
665*13af1a74SHong Zhang PetscErrorCode TSSetRHSHessianProduct(TS ts,Vec *rhshp1,PetscErrorCode (*rhshessianproductfunc1)(TS,PetscReal,Vec,Vec*,Vec,Vec*,void*),
666*13af1a74SHong Zhang                                           Vec *rhshp2,PetscErrorCode (*rhshessianproductfunc2)(TS,PetscReal,Vec,Vec*,Vec,Vec*,void*),
667*13af1a74SHong Zhang                                           Vec *rhshp3,PetscErrorCode (*rhshessianproductfunc3)(TS,PetscReal,Vec,Vec*,Vec,Vec*,void*),
668*13af1a74SHong Zhang                                           Vec *rhshp4,PetscErrorCode (*rhshessianproductfunc4)(TS,PetscReal,Vec,Vec*,Vec,Vec*,void*),
669*13af1a74SHong Zhang                                     void *ctx)
670*13af1a74SHong Zhang {
671*13af1a74SHong Zhang   PetscFunctionBegin;
672*13af1a74SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
673*13af1a74SHong Zhang   PetscValidPointer(rhshp1,2);
674*13af1a74SHong Zhang 
675*13af1a74SHong Zhang   ts->rhshessianproductctx = ctx;
676*13af1a74SHong Zhang   if (rhshp1) ts->vecs_guu = rhshp1;
677*13af1a74SHong Zhang   if (rhshp2) ts->vecs_gup = rhshp2;
678*13af1a74SHong Zhang   if (rhshp3) ts->vecs_gpu = rhshp3;
679*13af1a74SHong Zhang   if (rhshp4) ts->vecs_gpp = rhshp4;
680*13af1a74SHong Zhang   ts->rhshessianproduct_guu = rhshessianproductfunc1;
681*13af1a74SHong Zhang   ts->rhshessianproduct_gup = rhshessianproductfunc2;
682*13af1a74SHong Zhang   ts->rhshessianproduct_gpu = rhshessianproductfunc3;
683*13af1a74SHong Zhang   ts->rhshessianproduct_gpp = rhshessianproductfunc4;
684*13af1a74SHong Zhang   PetscFunctionReturn(0);
685*13af1a74SHong Zhang }
686*13af1a74SHong Zhang 
687*13af1a74SHong Zhang /*@C
688*13af1a74SHong Zhang   TSComputeRHSHessianProductFunction1 - Runs the user-defined vector-Hessian-vector product function for Guu.
689*13af1a74SHong Zhang 
690*13af1a74SHong Zhang   Collective on TS
691*13af1a74SHong Zhang 
692*13af1a74SHong Zhang   Input Parameters:
693*13af1a74SHong Zhang . ts   - The TS context obtained from TSCreate()
694*13af1a74SHong Zhang 
695*13af1a74SHong Zhang   Notes:
696*13af1a74SHong Zhang   TSComputeRHSHessianProductFunction1() is typically used for sensitivity implementation,
697*13af1a74SHong Zhang   so most users would not generally call this routine themselves.
698*13af1a74SHong Zhang 
699*13af1a74SHong Zhang   Level: developer
700*13af1a74SHong Zhang 
701*13af1a74SHong Zhang .keywords: TS, sensitivity
702*13af1a74SHong Zhang 
703*13af1a74SHong Zhang .seealso: TSSetRHSHessianProduct()
704*13af1a74SHong Zhang @*/
705*13af1a74SHong Zhang PetscErrorCode TSComputeRHSHessianProductFunction1(TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV)
706*13af1a74SHong Zhang {
707*13af1a74SHong Zhang   PetscErrorCode ierr;
708*13af1a74SHong Zhang 
709*13af1a74SHong Zhang   PetscFunctionBegin;
710*13af1a74SHong Zhang   if (!VHV) PetscFunctionReturn(0);
711*13af1a74SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
712*13af1a74SHong Zhang   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
713*13af1a74SHong Zhang 
714*13af1a74SHong Zhang   PetscStackPush("TS user RHSHessianProduct function 1 for sensitivity analysis");
715*13af1a74SHong Zhang   ierr = (*ts->rhshessianproduct_guu)(ts,t,U,Vl,Vr,VHV,ts->rhshessianproductctx);CHKERRQ(ierr);
716*13af1a74SHong Zhang   PetscStackPop;
717*13af1a74SHong Zhang   PetscFunctionReturn(0);
718*13af1a74SHong Zhang }
719*13af1a74SHong Zhang 
720*13af1a74SHong Zhang /*@C
721*13af1a74SHong Zhang   TSComputeRHSHessianProductFunction2 - Runs the user-defined vector-Hessian-vector product function for Gup.
722*13af1a74SHong Zhang 
723*13af1a74SHong Zhang   Collective on TS
724*13af1a74SHong Zhang 
725*13af1a74SHong Zhang   Input Parameters:
726*13af1a74SHong Zhang . ts   - The TS context obtained from TSCreate()
727*13af1a74SHong Zhang 
728*13af1a74SHong Zhang   Notes:
729*13af1a74SHong Zhang   TSComputeRHSHessianProductFunction2() is typically used for sensitivity implementation,
730*13af1a74SHong Zhang   so most users would not generally call this routine themselves.
731*13af1a74SHong Zhang 
732*13af1a74SHong Zhang   Level: developer
733*13af1a74SHong Zhang 
734*13af1a74SHong Zhang .keywords: TS, sensitivity
735*13af1a74SHong Zhang 
736*13af1a74SHong Zhang .seealso: TSSetRHSHessianProduct()
737*13af1a74SHong Zhang @*/
738*13af1a74SHong Zhang PetscErrorCode TSComputeRHSHessianProductFunction2(TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV)
739*13af1a74SHong Zhang {
740*13af1a74SHong Zhang   PetscErrorCode ierr;
741*13af1a74SHong Zhang 
742*13af1a74SHong Zhang   PetscFunctionBegin;
743*13af1a74SHong Zhang   if (!VHV) PetscFunctionReturn(0);
744*13af1a74SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
745*13af1a74SHong Zhang   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
746*13af1a74SHong Zhang 
747*13af1a74SHong Zhang   PetscStackPush("TS user RHSHessianProduct function 2 for sensitivity analysis");
748*13af1a74SHong Zhang   ierr = (*ts->rhshessianproduct_gup)(ts,t,U,Vl,Vr,VHV,ts->rhshessianproductctx);CHKERRQ(ierr);
749*13af1a74SHong Zhang   PetscStackPop;
750*13af1a74SHong Zhang   PetscFunctionReturn(0);
751*13af1a74SHong Zhang }
752*13af1a74SHong Zhang 
753*13af1a74SHong Zhang /*@C
754*13af1a74SHong Zhang   TSComputeRHSHessianProductFunction3 - Runs the user-defined vector-Hessian-vector product function for Gpu.
755*13af1a74SHong Zhang 
756*13af1a74SHong Zhang   Collective on TS
757*13af1a74SHong Zhang 
758*13af1a74SHong Zhang   Input Parameters:
759*13af1a74SHong Zhang . ts   - The TS context obtained from TSCreate()
760*13af1a74SHong Zhang 
761*13af1a74SHong Zhang   Notes:
762*13af1a74SHong Zhang   TSComputeRHSHessianProductFunction3() is typically used for sensitivity implementation,
763*13af1a74SHong Zhang   so most users would not generally call this routine themselves.
764*13af1a74SHong Zhang 
765*13af1a74SHong Zhang   Level: developer
766*13af1a74SHong Zhang 
767*13af1a74SHong Zhang .keywords: TS, sensitivity
768*13af1a74SHong Zhang 
769*13af1a74SHong Zhang .seealso: TSSetRHSHessianProduct()
770*13af1a74SHong Zhang @*/
771*13af1a74SHong Zhang PetscErrorCode TSComputeRHSHessianProductFunction3(TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV)
772*13af1a74SHong Zhang {
773*13af1a74SHong Zhang   PetscErrorCode ierr;
774*13af1a74SHong Zhang 
775*13af1a74SHong Zhang   PetscFunctionBegin;
776*13af1a74SHong Zhang   if (!VHV) PetscFunctionReturn(0);
777*13af1a74SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
778*13af1a74SHong Zhang   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
779*13af1a74SHong Zhang 
780*13af1a74SHong Zhang   PetscStackPush("TS user RHSHessianProduct function 3 for sensitivity analysis");
781*13af1a74SHong Zhang   ierr = (*ts->rhshessianproduct_gpu)(ts,t,U,Vl,Vr,VHV,ts->rhshessianproductctx);CHKERRQ(ierr);
782*13af1a74SHong Zhang   PetscStackPop;
783*13af1a74SHong Zhang   PetscFunctionReturn(0);
784*13af1a74SHong Zhang }
785*13af1a74SHong Zhang 
786*13af1a74SHong Zhang /*@C
787*13af1a74SHong Zhang   TSComputeRHSHessianProductFunction4 - Runs the user-defined vector-Hessian-vector product function for Gpp.
788*13af1a74SHong Zhang 
789*13af1a74SHong Zhang   Collective on TS
790*13af1a74SHong Zhang 
791*13af1a74SHong Zhang   Input Parameters:
792*13af1a74SHong Zhang . ts   - The TS context obtained from TSCreate()
793*13af1a74SHong Zhang 
794*13af1a74SHong Zhang   Notes:
795*13af1a74SHong Zhang   TSComputeRHSHessianProductFunction4() is typically used for sensitivity implementation,
796*13af1a74SHong Zhang   so most users would not generally call this routine themselves.
797*13af1a74SHong Zhang 
798*13af1a74SHong Zhang   Level: developer
799*13af1a74SHong Zhang 
800*13af1a74SHong Zhang .keywords: TS, sensitivity
801*13af1a74SHong Zhang 
802*13af1a74SHong Zhang .seealso: TSSetRHSHessianProduct()
803*13af1a74SHong Zhang @*/
804*13af1a74SHong Zhang PetscErrorCode TSComputeRHSHessianProductFunction4(TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV)
805*13af1a74SHong Zhang {
806*13af1a74SHong Zhang   PetscErrorCode ierr;
807*13af1a74SHong Zhang 
808*13af1a74SHong Zhang   PetscFunctionBegin;
809*13af1a74SHong Zhang   if (!VHV) PetscFunctionReturn(0);
810*13af1a74SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
811*13af1a74SHong Zhang   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
812*13af1a74SHong Zhang 
813*13af1a74SHong Zhang   PetscStackPush("TS user RHSHessianProduct function 3 for sensitivity analysis");
814*13af1a74SHong Zhang   ierr = (*ts->rhshessianproduct_gpp)(ts,t,U,Vl,Vr,VHV,ts->rhshessianproductctx);CHKERRQ(ierr);
815*13af1a74SHong Zhang   PetscStackPop;
816*13af1a74SHong Zhang   PetscFunctionReturn(0);
817*13af1a74SHong Zhang }
818*13af1a74SHong Zhang 
819814e85d6SHong Zhang /* --------------------------- Adjoint sensitivity ---------------------------*/
820814e85d6SHong Zhang 
821814e85d6SHong Zhang /*@
822814e85d6SHong Zhang    TSSetCostGradients - Sets the initial value of the gradients of the cost function w.r.t. initial values and w.r.t. the problem parameters
823814e85d6SHong Zhang       for use by the TSAdjoint routines.
824814e85d6SHong Zhang 
825814e85d6SHong Zhang    Logically Collective on TS and Vec
826814e85d6SHong Zhang 
827814e85d6SHong Zhang    Input Parameters:
828814e85d6SHong Zhang +  ts - the TS context obtained from TSCreate()
829814e85d6SHong Zhang .  lambda - gradients with respect to the initial condition variables, the dimension and parallel layout of these vectors is the same as the ODE solution vector
830814e85d6SHong Zhang -  mu - gradients with respect to the parameters, the number of entries in these vectors is the same as the number of parameters
831814e85d6SHong Zhang 
832814e85d6SHong Zhang    Level: beginner
833814e85d6SHong Zhang 
834814e85d6SHong Zhang    Notes:
835814e85d6SHong Zhang     the entries in these vectors must be correctly initialized with the values lamda_i = df/dy|finaltime  mu_i = df/dp|finaltime
836814e85d6SHong Zhang 
837814e85d6SHong Zhang    After TSAdjointSolve() is called the lamba and the mu contain the computed sensitivities
838814e85d6SHong Zhang 
839814e85d6SHong Zhang .keywords: TS, timestep, set, sensitivity, initial values
840b5b4017aSHong Zhang 
841b5b4017aSHong Zhang .seealso TSGetCostGradients()
842814e85d6SHong Zhang @*/
843814e85d6SHong Zhang PetscErrorCode TSSetCostGradients(TS ts,PetscInt numcost,Vec *lambda,Vec *mu)
844814e85d6SHong Zhang {
845814e85d6SHong Zhang   PetscFunctionBegin;
846814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
847814e85d6SHong Zhang   PetscValidPointer(lambda,2);
848814e85d6SHong Zhang   ts->vecs_sensi  = lambda;
849814e85d6SHong Zhang   ts->vecs_sensip = mu;
850814e85d6SHong Zhang   if (ts->numcost && ts->numcost!=numcost) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"The number of cost functions (2rd parameter of TSSetCostIntegrand()) is inconsistent with the one set by TSSetCostIntegrand");
851814e85d6SHong Zhang   ts->numcost  = numcost;
852814e85d6SHong Zhang   PetscFunctionReturn(0);
853814e85d6SHong Zhang }
854814e85d6SHong Zhang 
855814e85d6SHong Zhang /*@
856814e85d6SHong Zhang    TSGetCostGradients - Returns the gradients from the TSAdjointSolve()
857814e85d6SHong Zhang 
858814e85d6SHong Zhang    Not Collective, but Vec returned is parallel if TS is parallel
859814e85d6SHong Zhang 
860814e85d6SHong Zhang    Input Parameter:
861814e85d6SHong Zhang .  ts - the TS context obtained from TSCreate()
862814e85d6SHong Zhang 
863814e85d6SHong Zhang    Output Parameter:
864814e85d6SHong Zhang +  lambda - vectors containing the gradients of the cost functions with respect to the ODE/DAE solution variables
865814e85d6SHong Zhang -  mu - vectors containing the gradients of the cost functions with respect to the problem parameters
866814e85d6SHong Zhang 
867814e85d6SHong Zhang    Level: intermediate
868814e85d6SHong Zhang 
869814e85d6SHong Zhang .keywords: TS, timestep, get, sensitivity
870b5b4017aSHong Zhang 
871b5b4017aSHong Zhang .seealso: TSSetCostGradients()
872814e85d6SHong Zhang @*/
873814e85d6SHong Zhang PetscErrorCode TSGetCostGradients(TS ts,PetscInt *numcost,Vec **lambda,Vec **mu)
874814e85d6SHong Zhang {
875814e85d6SHong Zhang   PetscFunctionBegin;
876814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
877814e85d6SHong Zhang   if (numcost) *numcost = ts->numcost;
878814e85d6SHong Zhang   if (lambda)  *lambda  = ts->vecs_sensi;
879814e85d6SHong Zhang   if (mu)      *mu      = ts->vecs_sensip;
880814e85d6SHong Zhang   PetscFunctionReturn(0);
881814e85d6SHong Zhang }
882814e85d6SHong Zhang 
883814e85d6SHong Zhang /*@
884b5b4017aSHong Zhang    TSSetCostHessianProducts - Sets the initial value of the Hessian-vector products of the cost function w.r.t. initial values and w.r.t. the problem parameters
885b5b4017aSHong Zhang       for use by the TSAdjoint routines.
886b5b4017aSHong Zhang 
887b5b4017aSHong Zhang    Logically Collective on TS and Vec
888b5b4017aSHong Zhang 
889b5b4017aSHong Zhang    Input Parameters:
890b5b4017aSHong Zhang +  ts - the TS context obtained from TSCreate()
891b5b4017aSHong Zhang .  numcost - number of cost functions
892b5b4017aSHong Zhang .  lambda2 - Hessian-vector product with respect to the initial condition variables, the dimension and parallel layout of these vectors is the same as the ODE solution vector
893b5b4017aSHong Zhang .  mu2 - Hessian-vector product with respect to the parameters, the number of entries in these vectors is the same as the number of parameters
894b5b4017aSHong Zhang -  dir - the direction vector that are multiplied with the Hessian of the cost functions
895b5b4017aSHong Zhang 
896b5b4017aSHong Zhang    Level: beginner
897b5b4017aSHong Zhang 
898b5b4017aSHong Zhang    Notes: Hessian of the cost function is completely different from Hessian of the ODE/DAE system
899b5b4017aSHong Zhang 
900b5b4017aSHong Zhang    For second-order adjoint, one needs to call this function and then TSAdjointInitializeForward() before TSSolve().
901b5b4017aSHong Zhang 
902b5b4017aSHong Zhang    After TSAdjointSolve() is called, the lamba2 and the mu2 will contain the computed second-order adjoint sensitivities, and can be used to produce Hessian-vector product (not the full Hessian matrix). Users must provide a direction vector; it is usually generated by an optimization solver.
903b5b4017aSHong Zhang 
9043fca9621SHong Zhang    Passing NULL for lambda2 disables the second-order calculation.
905b5b4017aSHong Zhang .keywords: TS, sensitivity, second-order adjoint
906b5b4017aSHong Zhang 
907b5b4017aSHong Zhang .seealso: TSAdjointInitializeForward()
908b5b4017aSHong Zhang @*/
909b5b4017aSHong Zhang PetscErrorCode TSSetCostHessianProducts(TS ts,PetscInt numcost,Vec *lambda2,Vec *mu2,Vec dir)
910b5b4017aSHong Zhang {
911b5b4017aSHong Zhang   PetscFunctionBegin;
912b5b4017aSHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
913b5b4017aSHong Zhang   if (ts->numcost && ts->numcost!=numcost) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"The number of cost functions (2rd parameter of TSSetCostIntegrand()) is inconsistent with the one set by TSSetCostIntegrand");
914b5b4017aSHong Zhang   ts->numcost       = numcost;
915b5b4017aSHong Zhang   ts->vecs_sensi2   = lambda2;
91633f72c5dSHong Zhang   ts->vecs_sensi2p  = mu2;
917b5b4017aSHong Zhang   ts->vec_dir       = dir;
918b5b4017aSHong Zhang   PetscFunctionReturn(0);
919b5b4017aSHong Zhang }
920b5b4017aSHong Zhang 
921b5b4017aSHong Zhang /*@
922b5b4017aSHong Zhang    TSGetCostHessianProducts - Returns the gradients from the TSAdjointSolve()
923b5b4017aSHong Zhang 
924b5b4017aSHong Zhang    Not Collective, but Vec returned is parallel if TS is parallel
925b5b4017aSHong Zhang 
926b5b4017aSHong Zhang    Input Parameter:
927b5b4017aSHong Zhang .  ts - the TS context obtained from TSCreate()
928b5b4017aSHong Zhang 
929b5b4017aSHong Zhang    Output Parameter:
930b5b4017aSHong Zhang +  numcost - number of cost functions
931b5b4017aSHong Zhang .  lambda2 - Hessian-vector product with respect to the initial condition variables, the dimension and parallel layout of these vectors is the same as the ODE solution vector
932b5b4017aSHong Zhang .  mu2 - Hessian-vector product with respect to the parameters, the number of entries in these vectors is the same as the number of parameters
933b5b4017aSHong Zhang -  dir - the direction vector that are multiplied with the Hessian of the cost functions
934b5b4017aSHong Zhang 
935b5b4017aSHong Zhang    Level: intermediate
936b5b4017aSHong Zhang 
937b5b4017aSHong Zhang .keywords: TS, sensitivity, second-order adjoint
938b5b4017aSHong Zhang 
939b5b4017aSHong Zhang .seealso: TSSetCostHessianProducts()
940b5b4017aSHong Zhang @*/
941b5b4017aSHong Zhang PetscErrorCode TSGetCostHessianProducts(TS ts,PetscInt *numcost,Vec **lambda2,Vec **mu2, Vec *dir)
942b5b4017aSHong Zhang {
943b5b4017aSHong Zhang   PetscFunctionBegin;
944b5b4017aSHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
945b5b4017aSHong Zhang   if (numcost) *numcost = ts->numcost;
946b5b4017aSHong Zhang   if (lambda2) *lambda2 = ts->vecs_sensi2;
94733f72c5dSHong Zhang   if (mu2)     *mu2     = ts->vecs_sensi2p;
948b5b4017aSHong Zhang   if (dir)     *dir     = ts->vec_dir;
949b5b4017aSHong Zhang   PetscFunctionReturn(0);
950b5b4017aSHong Zhang }
951b5b4017aSHong Zhang 
952b5b4017aSHong Zhang /*@
953b5b4017aSHong Zhang   TSAdjointInitializeForward - Trigger the tangent linear solver and initialize the forward sensitivities
954b5b4017aSHong Zhang 
955b5b4017aSHong Zhang   Logically Collective on TS and Mat
956b5b4017aSHong Zhang 
957b5b4017aSHong Zhang   Input Parameters:
958b5b4017aSHong Zhang +  ts - the TS context obtained from TSCreate()
959b5b4017aSHong Zhang -  didp - the derivative of initial values w.r.t. parameters
960b5b4017aSHong Zhang 
961b5b4017aSHong Zhang   Level: intermediate
962b5b4017aSHong Zhang 
963b5b4017aSHong Zhang   Notes: When computing sensitivies w.r.t. initial condition, set didp to NULL so that the solver will take it as an identity matrix mathematically.
964b5b4017aSHong Zhang 
965b5b4017aSHong Zhang .keywords: TS, sensitivity, second-order adjoint
966b5b4017aSHong Zhang 
967b5b4017aSHong Zhang .seealso: TSSetCostHessianProducts()
968b5b4017aSHong Zhang @*/
969b5b4017aSHong Zhang PetscErrorCode TSAdjointInitializeForward(TS ts,Mat didp)
970b5b4017aSHong Zhang {
97133f72c5dSHong Zhang   Mat            A;
97233f72c5dSHong Zhang   Vec            sp;
97333f72c5dSHong Zhang   PetscScalar    *xarr;
97433f72c5dSHong Zhang   PetscInt       lsize;
975b5b4017aSHong Zhang   PetscErrorCode ierr;
976b5b4017aSHong Zhang 
977b5b4017aSHong Zhang   PetscFunctionBegin;
978b5b4017aSHong Zhang   ts->forward_solve = PETSC_TRUE; /* turn on tangent linear mode */
979b5b4017aSHong Zhang   if (!ts->vecs_sensi2) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Must call TSSetCostHessianProducts() first");
98033f72c5dSHong Zhang   if (!ts->vec_dir) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Directional vector is missing. Call TSSetCostHessianProducts() to set it.");
98133f72c5dSHong Zhang   /* create a single-column dense matrix */
98233f72c5dSHong Zhang   ierr = VecGetLocalSize(ts->vec_sol,&lsize);CHKERRQ(ierr);
98333f72c5dSHong Zhang   ierr = MatCreateDense(PETSC_COMM_WORLD,lsize,PETSC_DECIDE,PETSC_DECIDE,1,NULL,&A);CHKERRQ(ierr);
98433f72c5dSHong Zhang 
98533f72c5dSHong Zhang   ierr = VecDuplicate(ts->vec_sol,&sp);CHKERRQ(ierr);
98633f72c5dSHong Zhang   ierr = MatDenseGetColumn(A,0,&xarr);CHKERRQ(ierr);
98733f72c5dSHong Zhang   ierr = VecPlaceArray(sp,xarr);CHKERRQ(ierr);
98833f72c5dSHong Zhang   if (ts->vecs_sensi2p) { /* TLM variable initialized as 2*dIdP*dir */
98933f72c5dSHong Zhang     if (didp) {
99033f72c5dSHong Zhang       ierr = MatMult(didp,ts->vec_dir,sp);CHKERRQ(ierr);
99133f72c5dSHong Zhang       ierr = VecScale(sp,2.);CHKERRQ(ierr);
99233f72c5dSHong Zhang     } else {
99333f72c5dSHong Zhang       ierr = VecZeroEntries(sp);CHKERRQ(ierr);
99433f72c5dSHong Zhang     }
99533f72c5dSHong Zhang   } else { /* TLM variable initialized as dir */
99633f72c5dSHong Zhang     ierr = VecCopy(ts->vec_dir,sp);CHKERRQ(ierr);
99733f72c5dSHong Zhang   }
99833f72c5dSHong Zhang   ierr = VecResetArray(sp);CHKERRQ(ierr);
99933f72c5dSHong Zhang   ierr = MatDenseRestoreColumn(A,&xarr);CHKERRQ(ierr);
100033f72c5dSHong Zhang   ierr = VecDestroy(&sp);CHKERRQ(ierr);
100133f72c5dSHong Zhang 
100233f72c5dSHong Zhang   ierr = TSForwardSetInitialSensitivities(ts,A);CHKERRQ(ierr); /* if didp is NULL, identity matrix is assumed */
100333f72c5dSHong Zhang 
100433f72c5dSHong Zhang   ierr = MatDestroy(&A);CHKERRQ(ierr);
1005b5b4017aSHong Zhang   PetscFunctionReturn(0);
1006b5b4017aSHong Zhang }
1007b5b4017aSHong Zhang 
1008b5b4017aSHong Zhang /*@
1009814e85d6SHong Zhang    TSAdjointSetUp - Sets up the internal data structures for the later use
1010814e85d6SHong Zhang    of an adjoint solver
1011814e85d6SHong Zhang 
1012814e85d6SHong Zhang    Collective on TS
1013814e85d6SHong Zhang 
1014814e85d6SHong Zhang    Input Parameter:
1015814e85d6SHong Zhang .  ts - the TS context obtained from TSCreate()
1016814e85d6SHong Zhang 
1017814e85d6SHong Zhang    Level: advanced
1018814e85d6SHong Zhang 
1019814e85d6SHong Zhang .keywords: TS, timestep, setup
1020814e85d6SHong Zhang 
1021814e85d6SHong Zhang .seealso: TSCreate(), TSAdjointStep(), TSSetCostGradients()
1022814e85d6SHong Zhang @*/
1023814e85d6SHong Zhang PetscErrorCode TSAdjointSetUp(TS ts)
1024814e85d6SHong Zhang {
1025814e85d6SHong Zhang   PetscErrorCode ierr;
1026814e85d6SHong Zhang 
1027814e85d6SHong Zhang   PetscFunctionBegin;
1028814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1029814e85d6SHong Zhang   if (ts->adjointsetupcalled) PetscFunctionReturn(0);
1030814e85d6SHong Zhang   if (!ts->vecs_sensi) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONGSTATE,"Must call TSSetCostGradients() first");
103133f72c5dSHong Zhang   if (ts->vecs_sensip && !ts->Jacp && !ts->Jacprhs) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONGSTATE,"Must call TSSetRHSJacobianP() or TSSetIJacobianP() first");
103233f72c5dSHong Zhang 
103333f72c5dSHong Zhang   if (!ts->Jacp && ts->Jacprhs) ts->Jacp = ts->Jacprhs;
1034814e85d6SHong Zhang 
1035814e85d6SHong Zhang   if (ts->vec_costintegral) { /* if there is integral in the cost function */
1036c9ad9de0SHong Zhang     ierr = VecDuplicateVecs(ts->vecs_sensi[0],ts->numcost,&ts->vecs_drdu);CHKERRQ(ierr);
1037814e85d6SHong Zhang     if (ts->vecs_sensip){
1038814e85d6SHong Zhang       ierr = VecDuplicateVecs(ts->vecs_sensip[0],ts->numcost,&ts->vecs_drdp);CHKERRQ(ierr);
1039814e85d6SHong Zhang     }
1040814e85d6SHong Zhang   }
1041814e85d6SHong Zhang 
1042814e85d6SHong Zhang   if (ts->ops->adjointsetup) {
1043814e85d6SHong Zhang     ierr = (*ts->ops->adjointsetup)(ts);CHKERRQ(ierr);
1044814e85d6SHong Zhang   }
1045814e85d6SHong Zhang   ts->adjointsetupcalled = PETSC_TRUE;
1046814e85d6SHong Zhang   PetscFunctionReturn(0);
1047814e85d6SHong Zhang }
1048814e85d6SHong Zhang 
1049814e85d6SHong Zhang /*@
1050ece46509SHong Zhang    TSAdjointReset - Resets a TSAdjoint context and removes any allocated Vecs and Mats.
1051ece46509SHong Zhang 
1052ece46509SHong Zhang    Collective on TS
1053ece46509SHong Zhang 
1054ece46509SHong Zhang    Input Parameter:
1055ece46509SHong Zhang .  ts - the TS context obtained from TSCreate()
1056ece46509SHong Zhang 
1057ece46509SHong Zhang    Level: beginner
1058ece46509SHong Zhang 
1059ece46509SHong Zhang .keywords: TS, timestep, reset
1060ece46509SHong Zhang 
1061ece46509SHong Zhang .seealso: TSCreate(), TSAdjointSetup(), TSADestroy()
1062ece46509SHong Zhang @*/
1063ece46509SHong Zhang PetscErrorCode TSAdjointReset(TS ts)
1064ece46509SHong Zhang {
1065ece46509SHong Zhang   PetscErrorCode ierr;
1066ece46509SHong Zhang 
1067ece46509SHong Zhang   PetscFunctionBegin;
1068ece46509SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1069ece46509SHong Zhang   if (ts->ops->adjointreset) {
1070ece46509SHong Zhang     ierr = (*ts->ops->adjointreset)(ts);CHKERRQ(ierr);
1071ece46509SHong Zhang   }
1072cda2db4bSHong Zhang   if (ts->vec_dir) { /* second-order adjoint */
1073cda2db4bSHong Zhang     ierr = TSForwardReset(ts);CHKERRQ(ierr);
1074cda2db4bSHong Zhang   }
1075ece46509SHong Zhang   ts->vecs_sensi         = NULL;
1076ece46509SHong Zhang   ts->vecs_sensip        = NULL;
1077ece46509SHong Zhang   ts->vecs_sensi2        = NULL;
107833f72c5dSHong Zhang   ts->vecs_sensi2p       = NULL;
1079ece46509SHong Zhang   ts->vec_dir            = NULL;
1080ece46509SHong Zhang   ts->adjointsetupcalled = PETSC_FALSE;
1081ece46509SHong Zhang   PetscFunctionReturn(0);
1082ece46509SHong Zhang }
1083ece46509SHong Zhang 
1084ece46509SHong Zhang /*@
1085814e85d6SHong Zhang    TSAdjointSetSteps - Sets the number of steps the adjoint solver should take backward in time
1086814e85d6SHong Zhang 
1087814e85d6SHong Zhang    Logically Collective on TS
1088814e85d6SHong Zhang 
1089814e85d6SHong Zhang    Input Parameters:
1090814e85d6SHong Zhang +  ts - the TS context obtained from TSCreate()
1091814e85d6SHong Zhang .  steps - number of steps to use
1092814e85d6SHong Zhang 
1093814e85d6SHong Zhang    Level: intermediate
1094814e85d6SHong Zhang 
1095814e85d6SHong Zhang    Notes:
1096814e85d6SHong Zhang     Normally one does not call this and TSAdjointSolve() integrates back to the original timestep. One can call this
1097814e85d6SHong Zhang           so as to integrate back to less than the original timestep
1098814e85d6SHong Zhang 
1099814e85d6SHong Zhang .keywords: TS, timestep, set, maximum, iterations
1100814e85d6SHong Zhang 
1101814e85d6SHong Zhang .seealso: TSSetExactFinalTime()
1102814e85d6SHong Zhang @*/
1103814e85d6SHong Zhang PetscErrorCode TSAdjointSetSteps(TS ts,PetscInt steps)
1104814e85d6SHong Zhang {
1105814e85d6SHong Zhang   PetscFunctionBegin;
1106814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1107814e85d6SHong Zhang   PetscValidLogicalCollectiveInt(ts,steps,2);
1108814e85d6SHong Zhang   if (steps < 0) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Cannot step back a negative number of steps");
1109814e85d6SHong Zhang   if (steps > ts->steps) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Cannot step back more than the total number of forward steps");
1110814e85d6SHong Zhang   ts->adjoint_max_steps = steps;
1111814e85d6SHong Zhang   PetscFunctionReturn(0);
1112814e85d6SHong Zhang }
1113814e85d6SHong Zhang 
1114814e85d6SHong Zhang /*@C
1115814e85d6SHong Zhang   TSAdjointSetRHSJacobian - Deprecated, use TSSetRHSJacobianP()
1116814e85d6SHong Zhang 
1117814e85d6SHong Zhang   Level: deprecated
1118814e85d6SHong Zhang 
1119814e85d6SHong Zhang @*/
1120814e85d6SHong Zhang PetscErrorCode TSAdjointSetRHSJacobian(TS ts,Mat Amat,PetscErrorCode (*func)(TS,PetscReal,Vec,Mat,void*),void *ctx)
1121814e85d6SHong Zhang {
1122814e85d6SHong Zhang   PetscErrorCode ierr;
1123814e85d6SHong Zhang 
1124814e85d6SHong Zhang   PetscFunctionBegin;
1125814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
1126814e85d6SHong Zhang   PetscValidHeaderSpecific(Amat,MAT_CLASSID,2);
1127814e85d6SHong Zhang 
1128814e85d6SHong Zhang   ts->rhsjacobianp    = func;
1129814e85d6SHong Zhang   ts->rhsjacobianpctx = ctx;
1130814e85d6SHong Zhang   if(Amat) {
1131814e85d6SHong Zhang     ierr = PetscObjectReference((PetscObject)Amat);CHKERRQ(ierr);
1132814e85d6SHong Zhang     ierr = MatDestroy(&ts->Jacp);CHKERRQ(ierr);
1133814e85d6SHong Zhang     ts->Jacp = Amat;
1134814e85d6SHong Zhang   }
1135814e85d6SHong Zhang   PetscFunctionReturn(0);
1136814e85d6SHong Zhang }
1137814e85d6SHong Zhang 
1138814e85d6SHong Zhang /*@C
1139814e85d6SHong Zhang   TSAdjointComputeRHSJacobian - Deprecated, use TSComputeRHSJacobianP()
1140814e85d6SHong Zhang 
1141814e85d6SHong Zhang   Level: deprecated
1142814e85d6SHong Zhang 
1143814e85d6SHong Zhang @*/
1144c9ad9de0SHong Zhang PetscErrorCode TSAdjointComputeRHSJacobian(TS ts,PetscReal t,Vec U,Mat Amat)
1145814e85d6SHong Zhang {
1146814e85d6SHong Zhang   PetscErrorCode ierr;
1147814e85d6SHong Zhang 
1148814e85d6SHong Zhang   PetscFunctionBegin;
1149814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1150c9ad9de0SHong Zhang   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
1151814e85d6SHong Zhang   PetscValidPointer(Amat,4);
1152814e85d6SHong Zhang 
1153814e85d6SHong Zhang   PetscStackPush("TS user JacobianP function for sensitivity analysis");
1154c9ad9de0SHong Zhang   ierr = (*ts->rhsjacobianp)(ts,t,U,Amat,ts->rhsjacobianpctx); CHKERRQ(ierr);
1155814e85d6SHong Zhang   PetscStackPop;
1156814e85d6SHong Zhang   PetscFunctionReturn(0);
1157814e85d6SHong Zhang }
1158814e85d6SHong Zhang 
1159814e85d6SHong Zhang /*@
1160c9ad9de0SHong Zhang   TSAdjointComputeDRDYFunction - Deprecated, use TSComputeDRDUFunction()
1161814e85d6SHong Zhang 
1162814e85d6SHong Zhang   Level: deprecated
1163814e85d6SHong Zhang 
1164814e85d6SHong Zhang @*/
1165c9ad9de0SHong Zhang PetscErrorCode TSAdjointComputeDRDYFunction(TS ts,PetscReal t,Vec U,Vec *DRDU)
1166814e85d6SHong Zhang {
1167814e85d6SHong Zhang   PetscErrorCode ierr;
1168814e85d6SHong Zhang 
1169814e85d6SHong Zhang   PetscFunctionBegin;
1170814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1171c9ad9de0SHong Zhang   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
1172814e85d6SHong Zhang 
1173814e85d6SHong Zhang   PetscStackPush("TS user DRDY function for sensitivity analysis");
1174c9ad9de0SHong Zhang   ierr = (*ts->drdufunction)(ts,t,U,DRDU,ts->costintegrandctx); CHKERRQ(ierr);
1175814e85d6SHong Zhang   PetscStackPop;
1176814e85d6SHong Zhang   PetscFunctionReturn(0);
1177814e85d6SHong Zhang }
1178814e85d6SHong Zhang 
1179814e85d6SHong Zhang /*@
1180814e85d6SHong Zhang   TSAdjointComputeDRDPFunction - Deprecated, use TSComputeDRDPFunction()
1181814e85d6SHong Zhang 
1182814e85d6SHong Zhang   Level: deprecated
1183814e85d6SHong Zhang 
1184814e85d6SHong Zhang @*/
1185c9ad9de0SHong Zhang PetscErrorCode TSAdjointComputeDRDPFunction(TS ts,PetscReal t,Vec U,Vec *DRDP)
1186814e85d6SHong Zhang {
1187814e85d6SHong Zhang   PetscErrorCode ierr;
1188814e85d6SHong Zhang 
1189814e85d6SHong Zhang   PetscFunctionBegin;
1190814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1191c9ad9de0SHong Zhang   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
1192814e85d6SHong Zhang 
1193814e85d6SHong Zhang   PetscStackPush("TS user DRDP function for sensitivity analysis");
1194c9ad9de0SHong Zhang   ierr = (*ts->drdpfunction)(ts,t,U,DRDP,ts->costintegrandctx); CHKERRQ(ierr);
1195814e85d6SHong Zhang   PetscStackPop;
1196814e85d6SHong Zhang   PetscFunctionReturn(0);
1197814e85d6SHong Zhang }
1198814e85d6SHong Zhang 
1199814e85d6SHong Zhang /*@C
1200814e85d6SHong Zhang    TSAdjointMonitorSensi - monitors the first lambda sensitivity
1201814e85d6SHong Zhang 
1202814e85d6SHong Zhang    Level: intermediate
1203814e85d6SHong Zhang 
1204814e85d6SHong Zhang .keywords: TS, set, monitor
1205814e85d6SHong Zhang 
1206814e85d6SHong Zhang .seealso: TSAdjointMonitorSet()
1207814e85d6SHong Zhang @*/
1208814e85d6SHong Zhang PetscErrorCode TSAdjointMonitorSensi(TS ts,PetscInt step,PetscReal ptime,Vec v,PetscInt numcost,Vec *lambda,Vec *mu,PetscViewerAndFormat *vf)
1209814e85d6SHong Zhang {
1210814e85d6SHong Zhang   PetscErrorCode ierr;
1211814e85d6SHong Zhang   PetscViewer    viewer = vf->viewer;
1212814e85d6SHong Zhang 
1213814e85d6SHong Zhang   PetscFunctionBegin;
1214814e85d6SHong Zhang   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,4);
1215814e85d6SHong Zhang   ierr = PetscViewerPushFormat(viewer,vf->format);CHKERRQ(ierr);
1216814e85d6SHong Zhang   ierr = VecView(lambda[0],viewer);CHKERRQ(ierr);
1217814e85d6SHong Zhang   ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
1218814e85d6SHong Zhang   PetscFunctionReturn(0);
1219814e85d6SHong Zhang }
1220814e85d6SHong Zhang 
1221814e85d6SHong Zhang /*@C
1222814e85d6SHong Zhang    TSAdjointMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user
1223814e85d6SHong Zhang 
1224814e85d6SHong Zhang    Collective on TS
1225814e85d6SHong Zhang 
1226814e85d6SHong Zhang    Input Parameters:
1227814e85d6SHong Zhang +  ts - TS object you wish to monitor
1228814e85d6SHong Zhang .  name - the monitor type one is seeking
1229814e85d6SHong Zhang .  help - message indicating what monitoring is done
1230814e85d6SHong Zhang .  manual - manual page for the monitor
1231814e85d6SHong Zhang .  monitor - the monitor function
1232814e85d6SHong Zhang -  monitorsetup - a function that is called once ONLY if the user selected this monitor that may set additional features of the TS or PetscViewer objects
1233814e85d6SHong Zhang 
1234814e85d6SHong Zhang    Level: developer
1235814e85d6SHong Zhang 
1236814e85d6SHong Zhang .seealso: PetscOptionsGetViewer(), PetscOptionsGetReal(), PetscOptionsHasName(), PetscOptionsGetString(),
1237814e85d6SHong Zhang           PetscOptionsGetIntArray(), PetscOptionsGetRealArray(), PetscOptionsBool()
1238814e85d6SHong Zhang           PetscOptionsInt(), PetscOptionsString(), PetscOptionsReal(), PetscOptionsBool(),
1239814e85d6SHong Zhang           PetscOptionsName(), PetscOptionsBegin(), PetscOptionsEnd(), PetscOptionsHead(),
1240814e85d6SHong Zhang           PetscOptionsStringArray(),PetscOptionsRealArray(), PetscOptionsScalar(),
1241814e85d6SHong Zhang           PetscOptionsBoolGroupBegin(), PetscOptionsBoolGroup(), PetscOptionsBoolGroupEnd(),
1242814e85d6SHong Zhang           PetscOptionsFList(), PetscOptionsEList()
1243814e85d6SHong Zhang @*/
1244814e85d6SHong Zhang PetscErrorCode TSAdjointMonitorSetFromOptions(TS ts,const char name[],const char help[], const char manual[],PetscErrorCode (*monitor)(TS,PetscInt,PetscReal,Vec,PetscInt,Vec*,Vec*,PetscViewerAndFormat*),PetscErrorCode (*monitorsetup)(TS,PetscViewerAndFormat*))
1245814e85d6SHong Zhang {
1246814e85d6SHong Zhang   PetscErrorCode    ierr;
1247814e85d6SHong Zhang   PetscViewer       viewer;
1248814e85d6SHong Zhang   PetscViewerFormat format;
1249814e85d6SHong Zhang   PetscBool         flg;
1250814e85d6SHong Zhang 
1251814e85d6SHong Zhang   PetscFunctionBegin;
125216413a6aSBarry Smith   ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject)ts),((PetscObject) ts)->options,((PetscObject)ts)->prefix,name,&viewer,&format,&flg);CHKERRQ(ierr);
1253814e85d6SHong Zhang   if (flg) {
1254814e85d6SHong Zhang     PetscViewerAndFormat *vf;
1255814e85d6SHong Zhang     ierr = PetscViewerAndFormatCreate(viewer,format,&vf);CHKERRQ(ierr);
1256814e85d6SHong Zhang     ierr = PetscObjectDereference((PetscObject)viewer);CHKERRQ(ierr);
1257814e85d6SHong Zhang     if (monitorsetup) {
1258814e85d6SHong Zhang       ierr = (*monitorsetup)(ts,vf);CHKERRQ(ierr);
1259814e85d6SHong Zhang     }
1260814e85d6SHong Zhang     ierr = TSAdjointMonitorSet(ts,(PetscErrorCode (*)(TS,PetscInt,PetscReal,Vec,PetscInt,Vec*,Vec*,void*))monitor,vf,(PetscErrorCode (*)(void**))PetscViewerAndFormatDestroy);CHKERRQ(ierr);
1261814e85d6SHong Zhang   }
1262814e85d6SHong Zhang   PetscFunctionReturn(0);
1263814e85d6SHong Zhang }
1264814e85d6SHong Zhang 
1265814e85d6SHong Zhang /*@C
1266814e85d6SHong Zhang    TSAdjointMonitorSet - Sets an ADDITIONAL function that is to be used at every
1267814e85d6SHong Zhang    timestep to display the iteration's  progress.
1268814e85d6SHong Zhang 
1269814e85d6SHong Zhang    Logically Collective on TS
1270814e85d6SHong Zhang 
1271814e85d6SHong Zhang    Input Parameters:
1272814e85d6SHong Zhang +  ts - the TS context obtained from TSCreate()
1273814e85d6SHong Zhang .  adjointmonitor - monitoring routine
1274814e85d6SHong Zhang .  adjointmctx - [optional] user-defined context for private data for the
1275814e85d6SHong Zhang              monitor routine (use NULL if no context is desired)
1276814e85d6SHong Zhang -  adjointmonitordestroy - [optional] routine that frees monitor context
1277814e85d6SHong Zhang           (may be NULL)
1278814e85d6SHong Zhang 
1279814e85d6SHong Zhang    Calling sequence of monitor:
1280814e85d6SHong Zhang $    int adjointmonitor(TS ts,PetscInt steps,PetscReal time,Vec u,PetscInt numcost,Vec *lambda, Vec *mu,void *adjointmctx)
1281814e85d6SHong Zhang 
1282814e85d6SHong Zhang +    ts - the TS context
1283814e85d6SHong Zhang .    steps - iteration number (after the final time step the monitor routine is called with a step of -1, this is at the final time which may have
1284814e85d6SHong Zhang                                been interpolated to)
1285814e85d6SHong Zhang .    time - current time
1286814e85d6SHong Zhang .    u - current iterate
1287814e85d6SHong Zhang .    numcost - number of cost functionos
1288814e85d6SHong Zhang .    lambda - sensitivities to initial conditions
1289814e85d6SHong Zhang .    mu - sensitivities to parameters
1290814e85d6SHong Zhang -    adjointmctx - [optional] adjoint monitoring context
1291814e85d6SHong Zhang 
1292814e85d6SHong Zhang    Notes:
1293814e85d6SHong Zhang    This routine adds an additional monitor to the list of monitors that
1294814e85d6SHong Zhang    already has been loaded.
1295814e85d6SHong Zhang 
1296814e85d6SHong Zhang    Fortran Notes:
1297814e85d6SHong Zhang     Only a single monitor function can be set for each TS object
1298814e85d6SHong Zhang 
1299814e85d6SHong Zhang    Level: intermediate
1300814e85d6SHong Zhang 
1301814e85d6SHong Zhang .keywords: TS, timestep, set, adjoint, monitor
1302814e85d6SHong Zhang 
1303814e85d6SHong Zhang .seealso: TSAdjointMonitorCancel()
1304814e85d6SHong Zhang @*/
1305814e85d6SHong Zhang PetscErrorCode TSAdjointMonitorSet(TS ts,PetscErrorCode (*adjointmonitor)(TS,PetscInt,PetscReal,Vec,PetscInt,Vec*,Vec*,void*),void *adjointmctx,PetscErrorCode (*adjointmdestroy)(void**))
1306814e85d6SHong Zhang {
1307814e85d6SHong Zhang   PetscErrorCode ierr;
1308814e85d6SHong Zhang   PetscInt       i;
1309814e85d6SHong Zhang   PetscBool      identical;
1310814e85d6SHong Zhang 
1311814e85d6SHong Zhang   PetscFunctionBegin;
1312814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1313814e85d6SHong Zhang   for (i=0; i<ts->numbermonitors;i++) {
1314814e85d6SHong Zhang     ierr = PetscMonitorCompare((PetscErrorCode (*)(void))adjointmonitor,adjointmctx,adjointmdestroy,(PetscErrorCode (*)(void))ts->adjointmonitor[i],ts->adjointmonitorcontext[i],ts->adjointmonitordestroy[i],&identical);CHKERRQ(ierr);
1315814e85d6SHong Zhang     if (identical) PetscFunctionReturn(0);
1316814e85d6SHong Zhang   }
1317814e85d6SHong Zhang   if (ts->numberadjointmonitors >= MAXTSMONITORS) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Too many adjoint monitors set");
1318814e85d6SHong Zhang   ts->adjointmonitor[ts->numberadjointmonitors]          = adjointmonitor;
1319814e85d6SHong Zhang   ts->adjointmonitordestroy[ts->numberadjointmonitors]   = adjointmdestroy;
1320814e85d6SHong Zhang   ts->adjointmonitorcontext[ts->numberadjointmonitors++] = (void*)adjointmctx;
1321814e85d6SHong Zhang   PetscFunctionReturn(0);
1322814e85d6SHong Zhang }
1323814e85d6SHong Zhang 
1324814e85d6SHong Zhang /*@C
1325814e85d6SHong Zhang    TSAdjointMonitorCancel - Clears all the adjoint monitors that have been set on a time-step object.
1326814e85d6SHong Zhang 
1327814e85d6SHong Zhang    Logically Collective on TS
1328814e85d6SHong Zhang 
1329814e85d6SHong Zhang    Input Parameters:
1330814e85d6SHong Zhang .  ts - the TS context obtained from TSCreate()
1331814e85d6SHong Zhang 
1332814e85d6SHong Zhang    Notes:
1333814e85d6SHong Zhang    There is no way to remove a single, specific monitor.
1334814e85d6SHong Zhang 
1335814e85d6SHong Zhang    Level: intermediate
1336814e85d6SHong Zhang 
1337814e85d6SHong Zhang .keywords: TS, timestep, set, adjoint, monitor
1338814e85d6SHong Zhang 
1339814e85d6SHong Zhang .seealso: TSAdjointMonitorSet()
1340814e85d6SHong Zhang @*/
1341814e85d6SHong Zhang PetscErrorCode TSAdjointMonitorCancel(TS ts)
1342814e85d6SHong Zhang {
1343814e85d6SHong Zhang   PetscErrorCode ierr;
1344814e85d6SHong Zhang   PetscInt       i;
1345814e85d6SHong Zhang 
1346814e85d6SHong Zhang   PetscFunctionBegin;
1347814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1348814e85d6SHong Zhang   for (i=0; i<ts->numberadjointmonitors; i++) {
1349814e85d6SHong Zhang     if (ts->adjointmonitordestroy[i]) {
1350814e85d6SHong Zhang       ierr = (*ts->adjointmonitordestroy[i])(&ts->adjointmonitorcontext[i]);CHKERRQ(ierr);
1351814e85d6SHong Zhang     }
1352814e85d6SHong Zhang   }
1353814e85d6SHong Zhang   ts->numberadjointmonitors = 0;
1354814e85d6SHong Zhang   PetscFunctionReturn(0);
1355814e85d6SHong Zhang }
1356814e85d6SHong Zhang 
1357814e85d6SHong Zhang /*@C
1358814e85d6SHong Zhang    TSAdjointMonitorDefault - the default monitor of adjoint computations
1359814e85d6SHong Zhang 
1360814e85d6SHong Zhang    Level: intermediate
1361814e85d6SHong Zhang 
1362814e85d6SHong Zhang .keywords: TS, set, monitor
1363814e85d6SHong Zhang 
1364814e85d6SHong Zhang .seealso: TSAdjointMonitorSet()
1365814e85d6SHong Zhang @*/
1366814e85d6SHong Zhang PetscErrorCode TSAdjointMonitorDefault(TS ts,PetscInt step,PetscReal ptime,Vec v,PetscInt numcost,Vec *lambda,Vec *mu,PetscViewerAndFormat *vf)
1367814e85d6SHong Zhang {
1368814e85d6SHong Zhang   PetscErrorCode ierr;
1369814e85d6SHong Zhang   PetscViewer    viewer = vf->viewer;
1370814e85d6SHong Zhang 
1371814e85d6SHong Zhang   PetscFunctionBegin;
1372814e85d6SHong Zhang   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,4);
1373814e85d6SHong Zhang   ierr = PetscViewerPushFormat(viewer,vf->format);CHKERRQ(ierr);
1374814e85d6SHong Zhang   ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)ts)->tablevel);CHKERRQ(ierr);
1375814e85d6SHong Zhang   ierr = PetscViewerASCIIPrintf(viewer,"%D TS dt %g time %g%s",step,(double)ts->time_step,(double)ptime,ts->steprollback ? " (r)\n" : "\n");CHKERRQ(ierr);
1376814e85d6SHong Zhang   ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)ts)->tablevel);CHKERRQ(ierr);
1377814e85d6SHong Zhang   ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
1378814e85d6SHong Zhang   PetscFunctionReturn(0);
1379814e85d6SHong Zhang }
1380814e85d6SHong Zhang 
1381814e85d6SHong Zhang /*@C
1382814e85d6SHong Zhang    TSAdjointMonitorDrawSensi - Monitors progress of the adjoint TS solvers by calling
1383814e85d6SHong Zhang    VecView() for the sensitivities to initial states at each timestep
1384814e85d6SHong Zhang 
1385814e85d6SHong Zhang    Collective on TS
1386814e85d6SHong Zhang 
1387814e85d6SHong Zhang    Input Parameters:
1388814e85d6SHong Zhang +  ts - the TS context
1389814e85d6SHong Zhang .  step - current time-step
1390814e85d6SHong Zhang .  ptime - current time
1391814e85d6SHong Zhang .  u - current state
1392814e85d6SHong Zhang .  numcost - number of cost functions
1393814e85d6SHong Zhang .  lambda - sensitivities to initial conditions
1394814e85d6SHong Zhang .  mu - sensitivities to parameters
1395814e85d6SHong Zhang -  dummy - either a viewer or NULL
1396814e85d6SHong Zhang 
1397814e85d6SHong Zhang    Level: intermediate
1398814e85d6SHong Zhang 
1399814e85d6SHong Zhang .keywords: TS,  vector, adjoint, monitor, view
1400814e85d6SHong Zhang 
1401814e85d6SHong Zhang .seealso: TSAdjointMonitorSet(), TSAdjointMonitorDefault(), VecView()
1402814e85d6SHong Zhang @*/
1403814e85d6SHong Zhang PetscErrorCode TSAdjointMonitorDrawSensi(TS ts,PetscInt step,PetscReal ptime,Vec u,PetscInt numcost,Vec *lambda,Vec *mu,void *dummy)
1404814e85d6SHong Zhang {
1405814e85d6SHong Zhang   PetscErrorCode   ierr;
1406814e85d6SHong Zhang   TSMonitorDrawCtx ictx = (TSMonitorDrawCtx)dummy;
1407814e85d6SHong Zhang   PetscDraw        draw;
1408814e85d6SHong Zhang   PetscReal        xl,yl,xr,yr,h;
1409814e85d6SHong Zhang   char             time[32];
1410814e85d6SHong Zhang 
1411814e85d6SHong Zhang   PetscFunctionBegin;
1412814e85d6SHong Zhang   if (!(((ictx->howoften > 0) && (!(step % ictx->howoften))) || ((ictx->howoften == -1) && ts->reason))) PetscFunctionReturn(0);
1413814e85d6SHong Zhang 
1414814e85d6SHong Zhang   ierr = VecView(lambda[0],ictx->viewer);CHKERRQ(ierr);
1415814e85d6SHong Zhang   ierr = PetscViewerDrawGetDraw(ictx->viewer,0,&draw);CHKERRQ(ierr);
1416814e85d6SHong Zhang   ierr = PetscSNPrintf(time,32,"Timestep %d Time %g",(int)step,(double)ptime);CHKERRQ(ierr);
1417814e85d6SHong Zhang   ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
1418814e85d6SHong Zhang   h    = yl + .95*(yr - yl);
1419814e85d6SHong Zhang   ierr = PetscDrawStringCentered(draw,.5*(xl+xr),h,PETSC_DRAW_BLACK,time);CHKERRQ(ierr);
1420814e85d6SHong Zhang   ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
1421814e85d6SHong Zhang   PetscFunctionReturn(0);
1422814e85d6SHong Zhang }
1423814e85d6SHong Zhang 
1424814e85d6SHong Zhang /*
1425814e85d6SHong Zhang    TSAdjointSetFromOptions - Sets various TSAdjoint parameters from user options.
1426814e85d6SHong Zhang 
1427814e85d6SHong Zhang    Collective on TSAdjoint
1428814e85d6SHong Zhang 
1429814e85d6SHong Zhang    Input Parameter:
1430814e85d6SHong Zhang .  ts - the TS context
1431814e85d6SHong Zhang 
1432814e85d6SHong Zhang    Options Database Keys:
1433814e85d6SHong Zhang +  -ts_adjoint_solve <yes,no> After solving the ODE/DAE solve the adjoint problem (requires -ts_save_trajectory)
1434814e85d6SHong Zhang .  -ts_adjoint_monitor - print information at each adjoint time step
1435814e85d6SHong Zhang -  -ts_adjoint_monitor_draw_sensi - monitor the sensitivity of the first cost function wrt initial conditions (lambda[0]) graphically
1436814e85d6SHong Zhang 
1437814e85d6SHong Zhang    Level: developer
1438814e85d6SHong Zhang 
1439814e85d6SHong Zhang    Notes:
1440814e85d6SHong Zhang     This is not normally called directly by users
1441814e85d6SHong Zhang 
1442814e85d6SHong Zhang .keywords: TS, trajectory, timestep, set, options, database
1443814e85d6SHong Zhang 
1444814e85d6SHong Zhang .seealso: TSSetSaveTrajectory(), TSTrajectorySetUp()
1445814e85d6SHong Zhang */
1446814e85d6SHong Zhang PetscErrorCode TSAdjointSetFromOptions(PetscOptionItems *PetscOptionsObject,TS ts)
1447814e85d6SHong Zhang {
1448814e85d6SHong Zhang   PetscBool      tflg,opt;
1449814e85d6SHong Zhang   PetscErrorCode ierr;
1450814e85d6SHong Zhang 
1451814e85d6SHong Zhang   PetscFunctionBegin;
1452814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,2);
1453814e85d6SHong Zhang   ierr = PetscOptionsHead(PetscOptionsObject,"TS Adjoint options");CHKERRQ(ierr);
1454814e85d6SHong Zhang   tflg = ts->adjoint_solve ? PETSC_TRUE : PETSC_FALSE;
1455814e85d6SHong Zhang   ierr = PetscOptionsBool("-ts_adjoint_solve","Solve the adjoint problem immediately after solving the forward problem","",tflg,&tflg,&opt);CHKERRQ(ierr);
1456814e85d6SHong Zhang   if (opt) {
1457814e85d6SHong Zhang     ierr = TSSetSaveTrajectory(ts);CHKERRQ(ierr);
1458814e85d6SHong Zhang     ts->adjoint_solve = tflg;
1459814e85d6SHong Zhang   }
1460814e85d6SHong Zhang   ierr = TSAdjointMonitorSetFromOptions(ts,"-ts_adjoint_monitor","Monitor adjoint timestep size","TSAdjointMonitorDefault",TSAdjointMonitorDefault,NULL);CHKERRQ(ierr);
1461814e85d6SHong Zhang   ierr = TSAdjointMonitorSetFromOptions(ts,"-ts_adjoint_monitor_sensi","Monitor sensitivity in the adjoint computation","TSAdjointMonitorSensi",TSAdjointMonitorSensi,NULL);CHKERRQ(ierr);
1462814e85d6SHong Zhang   opt  = PETSC_FALSE;
1463814e85d6SHong Zhang   ierr = PetscOptionsName("-ts_adjoint_monitor_draw_sensi","Monitor adjoint sensitivities (lambda only) graphically","TSAdjointMonitorDrawSensi",&opt);CHKERRQ(ierr);
1464814e85d6SHong Zhang   if (opt) {
1465814e85d6SHong Zhang     TSMonitorDrawCtx ctx;
1466814e85d6SHong Zhang     PetscInt         howoften = 1;
1467814e85d6SHong Zhang 
1468814e85d6SHong Zhang     ierr = PetscOptionsInt("-ts_adjoint_monitor_draw_sensi","Monitor adjoint sensitivities (lambda only) graphically","TSAdjointMonitorDrawSensi",howoften,&howoften,NULL);CHKERRQ(ierr);
1469814e85d6SHong Zhang     ierr = TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts),0,0,PETSC_DECIDE,PETSC_DECIDE,300,300,howoften,&ctx);CHKERRQ(ierr);
1470814e85d6SHong Zhang     ierr = TSAdjointMonitorSet(ts,TSAdjointMonitorDrawSensi,ctx,(PetscErrorCode (*)(void**))TSMonitorDrawCtxDestroy);CHKERRQ(ierr);
1471814e85d6SHong Zhang   }
1472814e85d6SHong Zhang   PetscFunctionReturn(0);
1473814e85d6SHong Zhang }
1474814e85d6SHong Zhang 
1475814e85d6SHong Zhang /*@
1476814e85d6SHong Zhang    TSAdjointStep - Steps one time step backward in the adjoint run
1477814e85d6SHong Zhang 
1478814e85d6SHong Zhang    Collective on TS
1479814e85d6SHong Zhang 
1480814e85d6SHong Zhang    Input Parameter:
1481814e85d6SHong Zhang .  ts - the TS context obtained from TSCreate()
1482814e85d6SHong Zhang 
1483814e85d6SHong Zhang    Level: intermediate
1484814e85d6SHong Zhang 
1485814e85d6SHong Zhang .keywords: TS, adjoint, step
1486814e85d6SHong Zhang 
1487814e85d6SHong Zhang .seealso: TSAdjointSetUp(), TSAdjointSolve()
1488814e85d6SHong Zhang @*/
1489814e85d6SHong Zhang PetscErrorCode TSAdjointStep(TS ts)
1490814e85d6SHong Zhang {
1491814e85d6SHong Zhang   DM               dm;
1492814e85d6SHong Zhang   PetscErrorCode   ierr;
1493814e85d6SHong Zhang 
1494814e85d6SHong Zhang   PetscFunctionBegin;
1495814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1496814e85d6SHong Zhang   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
1497814e85d6SHong Zhang   ierr = TSAdjointSetUp(ts);CHKERRQ(ierr);
1498814e85d6SHong Zhang 
1499814e85d6SHong Zhang   ts->reason = TS_CONVERGED_ITERATING;
1500814e85d6SHong Zhang   ts->ptime_prev = ts->ptime;
1501814e85d6SHong Zhang   if (!ts->ops->adjointstep) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_NOT_CONVERGED,"TSStep has failed because the adjoint of  %s has not been implemented, try other time stepping methods for adjoint sensitivity analysis",((PetscObject)ts)->type_name);
1502814e85d6SHong Zhang   ierr = PetscLogEventBegin(TS_AdjointStep,ts,0,0,0);CHKERRQ(ierr);
1503814e85d6SHong Zhang   ierr = (*ts->ops->adjointstep)(ts);CHKERRQ(ierr);
1504814e85d6SHong Zhang   ierr = PetscLogEventEnd(TS_AdjointStep,ts,0,0,0);CHKERRQ(ierr);
1505814e85d6SHong Zhang   ts->adjoint_steps++; ts->steps--;
1506814e85d6SHong Zhang 
1507814e85d6SHong Zhang   if (ts->reason < 0) {
1508814e85d6SHong Zhang     if (ts->errorifstepfailed) {
150905c9950eSHong Zhang       if (ts->reason == TSADJOINT_DIVERGED_LINEAR_SOLVE) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_NOT_CONVERGED,"TSAdjointStep has failed due to %s",TSConvergedReasons[ts->reason]);
151005c9950eSHong Zhang       else SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_NOT_CONVERGED,"TSAdjointStep has failed due to %s",TSConvergedReasons[ts->reason]);
1511814e85d6SHong Zhang     }
1512814e85d6SHong Zhang   } else if (!ts->reason) {
1513814e85d6SHong Zhang     if (ts->adjoint_steps >= ts->adjoint_max_steps) ts->reason = TS_CONVERGED_ITS;
1514814e85d6SHong Zhang   }
1515814e85d6SHong Zhang   PetscFunctionReturn(0);
1516814e85d6SHong Zhang }
1517814e85d6SHong Zhang 
1518814e85d6SHong Zhang /*@
1519814e85d6SHong Zhang    TSAdjointSolve - Solves the discrete ajoint problem for an ODE/DAE
1520814e85d6SHong Zhang 
1521814e85d6SHong Zhang    Collective on TS
1522814e85d6SHong Zhang 
1523814e85d6SHong Zhang    Input Parameter:
1524814e85d6SHong Zhang .  ts - the TS context obtained from TSCreate()
1525814e85d6SHong Zhang 
1526814e85d6SHong Zhang    Options Database:
1527814e85d6SHong Zhang . -ts_adjoint_view_solution <viewerinfo> - views the first gradient with respect to the initial values
1528814e85d6SHong Zhang 
1529814e85d6SHong Zhang    Level: intermediate
1530814e85d6SHong Zhang 
1531814e85d6SHong Zhang    Notes:
1532814e85d6SHong Zhang    This must be called after a call to TSSolve() that solves the forward problem
1533814e85d6SHong Zhang 
1534814e85d6SHong Zhang    By default this will integrate back to the initial time, one can use TSAdjointSetSteps() to step back to a later time
1535814e85d6SHong Zhang 
1536814e85d6SHong Zhang .keywords: TS, timestep, solve
1537814e85d6SHong Zhang 
1538814e85d6SHong Zhang .seealso: TSCreate(), TSSetCostGradients(), TSSetSolution(), TSAdjointStep()
1539814e85d6SHong Zhang @*/
1540814e85d6SHong Zhang PetscErrorCode TSAdjointSolve(TS ts)
1541814e85d6SHong Zhang {
1542814e85d6SHong Zhang   PetscErrorCode    ierr;
1543814e85d6SHong Zhang 
1544814e85d6SHong Zhang   PetscFunctionBegin;
1545814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1546814e85d6SHong Zhang   ierr = TSAdjointSetUp(ts);CHKERRQ(ierr);
1547814e85d6SHong Zhang 
1548814e85d6SHong Zhang   /* reset time step and iteration counters */
1549814e85d6SHong Zhang   ts->adjoint_steps     = 0;
1550814e85d6SHong Zhang   ts->ksp_its           = 0;
1551814e85d6SHong Zhang   ts->snes_its          = 0;
1552814e85d6SHong Zhang   ts->num_snes_failures = 0;
1553814e85d6SHong Zhang   ts->reject            = 0;
1554814e85d6SHong Zhang   ts->reason            = TS_CONVERGED_ITERATING;
1555814e85d6SHong Zhang 
1556814e85d6SHong Zhang   if (!ts->adjoint_max_steps) ts->adjoint_max_steps = ts->steps;
1557814e85d6SHong Zhang   if (ts->adjoint_steps >= ts->adjoint_max_steps) ts->reason = TS_CONVERGED_ITS;
1558814e85d6SHong Zhang 
1559814e85d6SHong Zhang   while (!ts->reason) {
1560814e85d6SHong Zhang     ierr = TSTrajectoryGet(ts->trajectory,ts,ts->steps,&ts->ptime);CHKERRQ(ierr);
1561814e85d6SHong Zhang     ierr = TSAdjointMonitor(ts,ts->steps,ts->ptime,ts->vec_sol,ts->numcost,ts->vecs_sensi,ts->vecs_sensip);CHKERRQ(ierr);
1562814e85d6SHong Zhang     ierr = TSAdjointEventHandler(ts);CHKERRQ(ierr);
1563814e85d6SHong Zhang     ierr = TSAdjointStep(ts);CHKERRQ(ierr);
1564814e85d6SHong Zhang     if (ts->vec_costintegral && !ts->costintegralfwd) {
1565814e85d6SHong Zhang       ierr = TSAdjointCostIntegral(ts);CHKERRQ(ierr);
1566814e85d6SHong Zhang     }
1567814e85d6SHong Zhang   }
1568814e85d6SHong Zhang   ierr = TSTrajectoryGet(ts->trajectory,ts,ts->steps,&ts->ptime);CHKERRQ(ierr);
1569814e85d6SHong Zhang   ierr = TSAdjointMonitor(ts,ts->steps,ts->ptime,ts->vec_sol,ts->numcost,ts->vecs_sensi,ts->vecs_sensip);CHKERRQ(ierr);
1570814e85d6SHong Zhang   ts->solvetime = ts->ptime;
1571814e85d6SHong Zhang   ierr = TSTrajectoryViewFromOptions(ts->trajectory,NULL,"-ts_trajectory_view");CHKERRQ(ierr);
1572814e85d6SHong Zhang   ierr = VecViewFromOptions(ts->vecs_sensi[0],(PetscObject) ts, "-ts_adjoint_view_solution");CHKERRQ(ierr);
1573814e85d6SHong Zhang   ts->adjoint_max_steps = 0;
1574814e85d6SHong Zhang   PetscFunctionReturn(0);
1575814e85d6SHong Zhang }
1576814e85d6SHong Zhang 
1577814e85d6SHong Zhang /*@C
1578814e85d6SHong Zhang    TSAdjointMonitor - Runs all user-provided adjoint monitor routines set using TSAdjointMonitorSet()
1579814e85d6SHong Zhang 
1580814e85d6SHong Zhang    Collective on TS
1581814e85d6SHong Zhang 
1582814e85d6SHong Zhang    Input Parameters:
1583814e85d6SHong Zhang +  ts - time stepping context obtained from TSCreate()
1584814e85d6SHong Zhang .  step - step number that has just completed
1585814e85d6SHong Zhang .  ptime - model time of the state
1586814e85d6SHong Zhang .  u - state at the current model time
1587814e85d6SHong Zhang .  numcost - number of cost functions (dimension of lambda  or mu)
1588814e85d6SHong Zhang .  lambda - vectors containing the gradients of the cost functions with respect to the ODE/DAE solution variables
1589814e85d6SHong Zhang -  mu - vectors containing the gradients of the cost functions with respect to the problem parameters
1590814e85d6SHong Zhang 
1591814e85d6SHong Zhang    Notes:
1592814e85d6SHong Zhang    TSAdjointMonitor() is typically used automatically within the time stepping implementations.
1593814e85d6SHong Zhang    Users would almost never call this routine directly.
1594814e85d6SHong Zhang 
1595814e85d6SHong Zhang    Level: developer
1596814e85d6SHong Zhang 
1597814e85d6SHong Zhang .keywords: TS, timestep
1598814e85d6SHong Zhang @*/
1599814e85d6SHong Zhang PetscErrorCode TSAdjointMonitor(TS ts,PetscInt step,PetscReal ptime,Vec u,PetscInt numcost,Vec *lambda, Vec *mu)
1600814e85d6SHong Zhang {
1601814e85d6SHong Zhang   PetscErrorCode ierr;
1602814e85d6SHong Zhang   PetscInt       i,n = ts->numberadjointmonitors;
1603814e85d6SHong Zhang 
1604814e85d6SHong Zhang   PetscFunctionBegin;
1605814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1606814e85d6SHong Zhang   PetscValidHeaderSpecific(u,VEC_CLASSID,4);
16078860a134SJunchao Zhang   ierr = VecLockReadPush(u);CHKERRQ(ierr);
1608814e85d6SHong Zhang   for (i=0; i<n; i++) {
1609814e85d6SHong Zhang     ierr = (*ts->adjointmonitor[i])(ts,step,ptime,u,numcost,lambda,mu,ts->adjointmonitorcontext[i]);CHKERRQ(ierr);
1610814e85d6SHong Zhang   }
16118860a134SJunchao Zhang   ierr = VecLockReadPop(u);CHKERRQ(ierr);
1612814e85d6SHong Zhang   PetscFunctionReturn(0);
1613814e85d6SHong Zhang }
1614814e85d6SHong Zhang 
1615814e85d6SHong Zhang /*@
1616814e85d6SHong Zhang  TSAdjointCostIntegral - Evaluate the cost integral in the adjoint run.
1617814e85d6SHong Zhang 
1618814e85d6SHong Zhang  Collective on TS
1619814e85d6SHong Zhang 
1620814e85d6SHong Zhang  Input Arguments:
1621814e85d6SHong Zhang  .  ts - time stepping context
1622814e85d6SHong Zhang 
1623814e85d6SHong Zhang  Level: advanced
1624814e85d6SHong Zhang 
1625814e85d6SHong Zhang  Notes:
1626814e85d6SHong Zhang  This function cannot be called until TSAdjointStep() has been completed.
1627814e85d6SHong Zhang 
1628814e85d6SHong Zhang  .seealso: TSAdjointSolve(), TSAdjointStep
1629814e85d6SHong Zhang  @*/
1630814e85d6SHong Zhang PetscErrorCode TSAdjointCostIntegral(TS ts)
1631814e85d6SHong Zhang {
1632814e85d6SHong Zhang     PetscErrorCode ierr;
1633814e85d6SHong Zhang     PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1634814e85d6SHong Zhang     if (!ts->ops->adjointintegral) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"%s does not provide integral evaluation in the adjoint run",((PetscObject)ts)->type_name);
1635814e85d6SHong Zhang     ierr = (*ts->ops->adjointintegral)(ts);CHKERRQ(ierr);
1636814e85d6SHong Zhang     PetscFunctionReturn(0);
1637814e85d6SHong Zhang }
1638814e85d6SHong Zhang 
1639814e85d6SHong Zhang /* ------------------ Forward (tangent linear) sensitivity  ------------------*/
1640814e85d6SHong Zhang 
1641814e85d6SHong Zhang /*@
1642814e85d6SHong Zhang   TSForwardSetUp - Sets up the internal data structures for the later use
1643814e85d6SHong Zhang   of forward sensitivity analysis
1644814e85d6SHong Zhang 
1645814e85d6SHong Zhang   Collective on TS
1646814e85d6SHong Zhang 
1647814e85d6SHong Zhang   Input Parameter:
1648814e85d6SHong Zhang . ts - the TS context obtained from TSCreate()
1649814e85d6SHong Zhang 
1650814e85d6SHong Zhang   Level: advanced
1651814e85d6SHong Zhang 
1652814e85d6SHong Zhang .keywords: TS, forward sensitivity, setup
1653814e85d6SHong Zhang 
1654814e85d6SHong Zhang .seealso: TSCreate(), TSDestroy(), TSSetUp()
1655814e85d6SHong Zhang @*/
1656814e85d6SHong Zhang PetscErrorCode TSForwardSetUp(TS ts)
1657814e85d6SHong Zhang {
1658814e85d6SHong Zhang   PetscErrorCode ierr;
1659814e85d6SHong Zhang 
1660814e85d6SHong Zhang   PetscFunctionBegin;
1661814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1662814e85d6SHong Zhang   if (ts->forwardsetupcalled) PetscFunctionReturn(0);
1663814e85d6SHong Zhang   if (ts->vec_costintegral && !ts->vecs_integral_sensip ) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call TSForwardSetIntegralGradients() before TSSetCostIntegrand()");
1664814e85d6SHong Zhang   if (ts->vecs_integral_sensip) {
1665c9ad9de0SHong Zhang     ierr = VecDuplicateVecs(ts->vec_sol,ts->numcost,&ts->vecs_drdu);CHKERRQ(ierr);
1666814e85d6SHong Zhang     ierr = VecDuplicateVecs(ts->vecs_integral_sensip[0],ts->numcost,&ts->vecs_drdp);CHKERRQ(ierr);
1667814e85d6SHong Zhang   }
166833f72c5dSHong Zhang   if (!ts->Jacp && ts->Jacprhs) ts->Jacp = ts->Jacprhs;
1669814e85d6SHong Zhang 
1670814e85d6SHong Zhang   if (ts->ops->forwardsetup) {
1671814e85d6SHong Zhang     ierr = (*ts->ops->forwardsetup)(ts);CHKERRQ(ierr);
1672814e85d6SHong Zhang   }
1673814e85d6SHong Zhang   ts->forwardsetupcalled = PETSC_TRUE;
1674814e85d6SHong Zhang   PetscFunctionReturn(0);
1675814e85d6SHong Zhang }
1676814e85d6SHong Zhang 
1677814e85d6SHong Zhang /*@
16787adebddeSHong Zhang   TSForwardReset - Reset the internal data structures used by forward sensitivity analysis
16797adebddeSHong Zhang 
16807adebddeSHong Zhang   Collective on TS
16817adebddeSHong Zhang 
16827adebddeSHong Zhang   Input Parameter:
16837adebddeSHong Zhang . ts - the TS context obtained from TSCreate()
16847adebddeSHong Zhang 
16857adebddeSHong Zhang   Level: advanced
16867adebddeSHong Zhang 
16877adebddeSHong Zhang .keywords: TS, forward sensitivity, reset
16887adebddeSHong Zhang 
16897adebddeSHong Zhang .seealso: TSCreate(), TSDestroy(), TSForwardSetUp()
16907adebddeSHong Zhang @*/
16917adebddeSHong Zhang PetscErrorCode TSForwardReset(TS ts)
16927adebddeSHong Zhang {
16937adebddeSHong Zhang   PetscErrorCode ierr;
16947adebddeSHong Zhang 
16957adebddeSHong Zhang   PetscFunctionBegin;
16967adebddeSHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
16977adebddeSHong Zhang   if (ts->ops->forwardreset) {
16987adebddeSHong Zhang     ierr = (*ts->ops->forwardreset)(ts);CHKERRQ(ierr);
16997adebddeSHong Zhang   }
17007adebddeSHong Zhang   ierr = MatDestroy(&ts->mat_sensip);CHKERRQ(ierr);
17017adebddeSHong Zhang   ts->vecs_integral_sensip = NULL;
17027adebddeSHong Zhang   ts->forward_solve        = PETSC_FALSE;
17037adebddeSHong Zhang   ts->forwardsetupcalled   = PETSC_FALSE;
17047adebddeSHong Zhang   PetscFunctionReturn(0);
17057adebddeSHong Zhang }
17067adebddeSHong Zhang 
17077adebddeSHong Zhang /*@
1708814e85d6SHong Zhang   TSForwardSetIntegralGradients - Set the vectors holding forward sensitivities of the integral term.
1709814e85d6SHong Zhang 
1710814e85d6SHong Zhang   Input Parameter:
1711814e85d6SHong Zhang . ts- the TS context obtained from TSCreate()
1712814e85d6SHong Zhang . numfwdint- number of integrals
1713814e85d6SHong Zhang . vp = the vectors containing the gradients for each integral w.r.t. parameters
1714814e85d6SHong Zhang 
1715814e85d6SHong Zhang   Level: intermediate
1716814e85d6SHong Zhang 
1717814e85d6SHong Zhang .keywords: TS, forward sensitivity
1718814e85d6SHong Zhang 
1719814e85d6SHong Zhang .seealso: TSForwardGetSensitivities(), TSForwardSetIntegralGradients(), TSForwardGetIntegralGradients(), TSForwardStep()
1720814e85d6SHong Zhang @*/
1721814e85d6SHong Zhang PetscErrorCode TSForwardSetIntegralGradients(TS ts,PetscInt numfwdint,Vec *vp)
1722814e85d6SHong Zhang {
1723814e85d6SHong Zhang   PetscFunctionBegin;
1724814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1725814e85d6SHong Zhang   if (ts->numcost && ts->numcost!=numfwdint) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"The number of cost functions (2rd parameter of TSSetCostIntegrand()) is inconsistent with the one set by TSSetCostIntegrand()");
1726814e85d6SHong Zhang   if (!ts->numcost) ts->numcost = numfwdint;
1727814e85d6SHong Zhang 
1728814e85d6SHong Zhang   ts->vecs_integral_sensip = vp;
1729814e85d6SHong Zhang   PetscFunctionReturn(0);
1730814e85d6SHong Zhang }
1731814e85d6SHong Zhang 
1732814e85d6SHong Zhang /*@
1733814e85d6SHong Zhang   TSForwardGetIntegralGradients - Returns the forward sensitivities ofthe integral term.
1734814e85d6SHong Zhang 
1735814e85d6SHong Zhang   Input Parameter:
1736814e85d6SHong Zhang . ts- the TS context obtained from TSCreate()
1737814e85d6SHong Zhang 
1738814e85d6SHong Zhang   Output Parameter:
1739814e85d6SHong Zhang . vp = the vectors containing the gradients for each integral w.r.t. parameters
1740814e85d6SHong Zhang 
1741814e85d6SHong Zhang   Level: intermediate
1742814e85d6SHong Zhang 
1743814e85d6SHong Zhang .keywords: TS, forward sensitivity
1744814e85d6SHong Zhang 
1745814e85d6SHong Zhang .seealso: TSForwardSetSensitivities(), TSForwardSetIntegralGradients(), TSForwardGetIntegralGradients(), TSForwardStep()
1746814e85d6SHong Zhang @*/
1747814e85d6SHong Zhang PetscErrorCode TSForwardGetIntegralGradients(TS ts,PetscInt *numfwdint,Vec **vp)
1748814e85d6SHong Zhang {
1749814e85d6SHong Zhang   PetscFunctionBegin;
1750814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1751814e85d6SHong Zhang   PetscValidPointer(vp,3);
1752814e85d6SHong Zhang   if (numfwdint) *numfwdint = ts->numcost;
1753814e85d6SHong Zhang   if (vp) *vp = ts->vecs_integral_sensip;
1754814e85d6SHong Zhang   PetscFunctionReturn(0);
1755814e85d6SHong Zhang }
1756814e85d6SHong Zhang 
1757814e85d6SHong Zhang /*@
1758814e85d6SHong Zhang   TSForwardStep - Compute the forward sensitivity for one time step.
1759814e85d6SHong Zhang 
1760814e85d6SHong Zhang   Collective on TS
1761814e85d6SHong Zhang 
1762814e85d6SHong Zhang   Input Arguments:
1763814e85d6SHong Zhang . ts - time stepping context
1764814e85d6SHong Zhang 
1765814e85d6SHong Zhang   Level: advanced
1766814e85d6SHong Zhang 
1767814e85d6SHong Zhang   Notes:
1768814e85d6SHong Zhang   This function cannot be called until TSStep() has been completed.
1769814e85d6SHong Zhang 
1770814e85d6SHong Zhang .keywords: TS, forward sensitivity
1771814e85d6SHong Zhang 
1772814e85d6SHong Zhang .seealso: TSForwardSetSensitivities(), TSForwardGetSensitivities(), TSForwardSetIntegralGradients(), TSForwardGetIntegralGradients(), TSForwardSetUp()
1773814e85d6SHong Zhang @*/
1774814e85d6SHong Zhang PetscErrorCode TSForwardStep(TS ts)
1775814e85d6SHong Zhang {
1776814e85d6SHong Zhang   PetscErrorCode ierr;
1777814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1778814e85d6SHong Zhang   if (!ts->ops->forwardstep) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"%s does not provide forward sensitivity analysis",((PetscObject)ts)->type_name);
1779814e85d6SHong Zhang   ierr = PetscLogEventBegin(TS_ForwardStep,ts,0,0,0);CHKERRQ(ierr);
1780814e85d6SHong Zhang   ierr = (*ts->ops->forwardstep)(ts);CHKERRQ(ierr);
1781814e85d6SHong Zhang   ierr = PetscLogEventEnd(TS_ForwardStep,ts,0,0,0);CHKERRQ(ierr);
1782814e85d6SHong Zhang   PetscFunctionReturn(0);
1783814e85d6SHong Zhang }
1784814e85d6SHong Zhang 
1785814e85d6SHong Zhang /*@
1786814e85d6SHong Zhang   TSForwardSetSensitivities - Sets the initial value of the trajectory sensitivities of solution  w.r.t. the problem parameters and initial values.
1787814e85d6SHong Zhang 
1788814e85d6SHong Zhang   Logically Collective on TS and Vec
1789814e85d6SHong Zhang 
1790814e85d6SHong Zhang   Input Parameters:
1791814e85d6SHong Zhang + ts - the TS context obtained from TSCreate()
1792814e85d6SHong Zhang . nump - number of parameters
1793814e85d6SHong Zhang - Smat - sensitivities with respect to the parameters, the number of entries in these vectors is the same as the number of parameters
1794814e85d6SHong Zhang 
1795814e85d6SHong Zhang   Level: beginner
1796814e85d6SHong Zhang 
1797814e85d6SHong Zhang   Notes:
1798814e85d6SHong Zhang   Forward sensitivity is also called 'trajectory sensitivity' in some fields such as power systems.
1799814e85d6SHong Zhang   This function turns on a flag to trigger TSSolve() to compute forward sensitivities automatically.
1800814e85d6SHong Zhang   You must call this function before TSSolve().
1801814e85d6SHong Zhang   The entries in the sensitivity matrix must be correctly initialized with the values S = dy/dp|startingtime.
1802814e85d6SHong Zhang 
1803814e85d6SHong Zhang .keywords: TS, timestep, set, forward sensitivity, initial values
1804814e85d6SHong Zhang 
1805814e85d6SHong Zhang .seealso: TSForwardGetSensitivities(), TSForwardSetIntegralGradients(), TSForwardGetIntegralGradients(), TSForwardStep()
1806814e85d6SHong Zhang @*/
1807814e85d6SHong Zhang PetscErrorCode TSForwardSetSensitivities(TS ts,PetscInt nump,Mat Smat)
1808814e85d6SHong Zhang {
1809814e85d6SHong Zhang   PetscErrorCode ierr;
1810814e85d6SHong Zhang 
1811814e85d6SHong Zhang   PetscFunctionBegin;
1812814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1813814e85d6SHong Zhang   PetscValidHeaderSpecific(Smat,MAT_CLASSID,3);
1814814e85d6SHong Zhang   ts->forward_solve  = PETSC_TRUE;
1815b5b4017aSHong Zhang   if (nump == PETSC_DEFAULT) {
1816b5b4017aSHong Zhang     ierr = MatGetSize(Smat,NULL,&ts->num_parameters);CHKERRQ(ierr);
1817b5b4017aSHong Zhang   } else ts->num_parameters = nump;
1818814e85d6SHong Zhang   ierr = PetscObjectReference((PetscObject)Smat);CHKERRQ(ierr);
1819814e85d6SHong Zhang   ierr = MatDestroy(&ts->mat_sensip);CHKERRQ(ierr);
1820814e85d6SHong Zhang   ts->mat_sensip = Smat;
1821814e85d6SHong Zhang   PetscFunctionReturn(0);
1822814e85d6SHong Zhang }
1823814e85d6SHong Zhang 
1824814e85d6SHong Zhang /*@
1825814e85d6SHong Zhang   TSForwardGetSensitivities - Returns the trajectory sensitivities
1826814e85d6SHong Zhang 
1827814e85d6SHong Zhang   Not Collective, but Vec returned is parallel if TS is parallel
1828814e85d6SHong Zhang 
1829814e85d6SHong Zhang   Output Parameter:
1830814e85d6SHong Zhang + ts - the TS context obtained from TSCreate()
1831814e85d6SHong Zhang . nump - number of parameters
1832814e85d6SHong Zhang - Smat - sensitivities with respect to the parameters, the number of entries in these vectors is the same as the number of parameters
1833814e85d6SHong Zhang 
1834814e85d6SHong Zhang   Level: intermediate
1835814e85d6SHong Zhang 
1836814e85d6SHong Zhang .keywords: TS, forward sensitivity
1837814e85d6SHong Zhang 
1838814e85d6SHong Zhang .seealso: TSForwardSetSensitivities(), TSForwardSetIntegralGradients(), TSForwardGetIntegralGradients(), TSForwardStep()
1839814e85d6SHong Zhang @*/
1840814e85d6SHong Zhang PetscErrorCode TSForwardGetSensitivities(TS ts,PetscInt *nump,Mat *Smat)
1841814e85d6SHong Zhang {
1842814e85d6SHong Zhang   PetscFunctionBegin;
1843814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1844814e85d6SHong Zhang   if (nump) *nump = ts->num_parameters;
1845814e85d6SHong Zhang   if (Smat) *Smat = ts->mat_sensip;
1846814e85d6SHong Zhang   PetscFunctionReturn(0);
1847814e85d6SHong Zhang }
1848814e85d6SHong Zhang 
1849814e85d6SHong Zhang /*@
1850814e85d6SHong Zhang    TSForwardCostIntegral - Evaluate the cost integral in the forward run.
1851814e85d6SHong Zhang 
1852814e85d6SHong Zhang    Collective on TS
1853814e85d6SHong Zhang 
1854814e85d6SHong Zhang    Input Arguments:
1855814e85d6SHong Zhang .  ts - time stepping context
1856814e85d6SHong Zhang 
1857814e85d6SHong Zhang    Level: advanced
1858814e85d6SHong Zhang 
1859814e85d6SHong Zhang    Notes:
1860814e85d6SHong Zhang    This function cannot be called until TSStep() has been completed.
1861814e85d6SHong Zhang 
1862814e85d6SHong Zhang .seealso: TSSolve(), TSAdjointCostIntegral()
1863814e85d6SHong Zhang @*/
1864814e85d6SHong Zhang PetscErrorCode TSForwardCostIntegral(TS ts)
1865814e85d6SHong Zhang {
1866814e85d6SHong Zhang   PetscErrorCode ierr;
1867814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1868814e85d6SHong Zhang   if (!ts->ops->forwardintegral) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"%s does not provide integral evaluation in the forward run",((PetscObject)ts)->type_name);
1869814e85d6SHong Zhang   ierr = (*ts->ops->forwardintegral)(ts);CHKERRQ(ierr);
1870814e85d6SHong Zhang   PetscFunctionReturn(0);
1871814e85d6SHong Zhang }
1872b5b4017aSHong Zhang 
1873b5b4017aSHong Zhang /*@
1874b5b4017aSHong Zhang   TSForwardSetInitialSensitivities - Set initial values for tangent linear sensitivities
1875b5b4017aSHong Zhang 
1876b5b4017aSHong Zhang   Collective on TS and Mat
1877b5b4017aSHong Zhang 
1878b5b4017aSHong Zhang   Input Parameter
1879b5b4017aSHong Zhang + ts - the TS context obtained from TSCreate()
1880b5b4017aSHong Zhang - didp - parametric sensitivities of the initial condition
1881b5b4017aSHong Zhang 
1882b5b4017aSHong Zhang   Level: intermediate
1883b5b4017aSHong Zhang 
1884b5b4017aSHong Zhang   Notes: TSSolve() allows users to pass the initial solution directly to TS. But the tangent linear variables cannot be initialized in this way. This function is used to set initial values for tangent linear variables.
1885b5b4017aSHong Zhang 
1886b5b4017aSHong Zhang .seealso: TSForwardSetSensitivities()
1887b5b4017aSHong Zhang @*/
1888b5b4017aSHong Zhang PetscErrorCode TSForwardSetInitialSensitivities(TS ts,Mat didp)
1889b5b4017aSHong Zhang {
1890b5b4017aSHong Zhang   PetscErrorCode ierr;
1891b5b4017aSHong Zhang 
1892b5b4017aSHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1893b5b4017aSHong Zhang   PetscValidHeaderSpecific(didp,MAT_CLASSID,2);
1894b5b4017aSHong Zhang   if (!ts->mat_sensip) {
1895b5b4017aSHong Zhang     ierr = TSForwardSetSensitivities(ts,PETSC_DEFAULT,didp);CHKERRQ(ierr);
1896b5b4017aSHong Zhang   }
1897b5b4017aSHong Zhang   PetscFunctionReturn(0);
1898b5b4017aSHong Zhang }
18996affb6f8SHong Zhang 
19006affb6f8SHong Zhang /*@
19016affb6f8SHong Zhang    TSForwardGetStages - Get the number of stages and the tangent linear sensitivities at the intermediate stages
19026affb6f8SHong Zhang 
19036affb6f8SHong Zhang    Input Parameter:
19046affb6f8SHong Zhang .  ts - the TS context obtained from TSCreate()
19056affb6f8SHong Zhang 
19066affb6f8SHong Zhang    Output Parameters:
19076affb6f8SHong Zhang +  ns - nu
19086affb6f8SHong Zhang -  S - tangent linear sensitivities at the intermediate stages
19096affb6f8SHong Zhang 
19106affb6f8SHong Zhang    Level: advanced
19116affb6f8SHong Zhang 
19126affb6f8SHong Zhang .keywords: TS, second-order adjoint, forward sensitivity
19136affb6f8SHong Zhang @*/
19146affb6f8SHong Zhang PetscErrorCode TSForwardGetStages(TS ts,PetscInt *ns,Mat **S)
19156affb6f8SHong Zhang {
19166affb6f8SHong Zhang   PetscErrorCode ierr;
19176affb6f8SHong Zhang 
19186affb6f8SHong Zhang   PetscFunctionBegin;
19196affb6f8SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
19206affb6f8SHong Zhang 
19216affb6f8SHong Zhang   if (!ts->ops->getstages) *S=NULL;
19226affb6f8SHong Zhang   else {
19236affb6f8SHong Zhang     ierr = (*ts->ops->forwardgetstages)(ts,ns,S);CHKERRQ(ierr);
19246affb6f8SHong Zhang   }
19256affb6f8SHong Zhang   PetscFunctionReturn(0);
19266affb6f8SHong Zhang }
1927