xref: /petsc/src/ts/interface/sensitivity/tssen.c (revision 67633408d522965edf5ab8f4896ab7156f142302)
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 
487*67633408SHong 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;
491*67633408SHong Zhang   }
492*67633408SHong Zhang   /* does not consider IMEX for now, so either IHessian or RHSHessian will be calculated, using the same output VHV */
493*67633408SHong Zhang   if (ts->rhshessianproduct_guu) {
494*67633408SHong Zhang     PetscInt nadj;
495*67633408SHong Zhang     ierr = TSComputeRHSHessianProductFunction1(ts,t,U,Vl,Vr,VHV);CHKERRQ(ierr);
496*67633408SHong Zhang     for (nadj=0; nadj<ts->numcost; nadj++) {
497*67633408SHong Zhang       ierr = VecScale(VHV[nadj],-1);CHKERRQ(ierr);
498*67633408SHong Zhang     }
499*67633408SHong 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 
530*67633408SHong 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;
534*67633408SHong Zhang   }
535*67633408SHong Zhang   /* does not consider IMEX for now, so either IHessian or RHSHessian will be calculated, using the same output VHV */
536*67633408SHong Zhang   if (ts->rhshessianproduct_gup) {
537*67633408SHong Zhang     PetscInt nadj;
538*67633408SHong Zhang     ierr = TSComputeRHSHessianProductFunction2(ts,t,U,Vl,Vr,VHV);CHKERRQ(ierr);
539*67633408SHong Zhang     for (nadj=0; nadj<ts->numcost; nadj++) {
540*67633408SHong Zhang       ierr = VecScale(VHV[nadj],-1);CHKERRQ(ierr);
541*67633408SHong Zhang     }
542*67633408SHong 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 
573*67633408SHong 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;
577*67633408SHong Zhang   }
578*67633408SHong Zhang   /* does not consider IMEX for now, so either IHessian or RHSHessian will be calculated, using the same output VHV */
579*67633408SHong Zhang   if (ts->rhshessianproduct_gpu) {
580*67633408SHong Zhang     PetscInt nadj;
581*67633408SHong Zhang     ierr = TSComputeRHSHessianProductFunction3(ts,t,U,Vl,Vr,VHV);CHKERRQ(ierr);
582*67633408SHong Zhang     for (nadj=0; nadj<ts->numcost; nadj++) {
583*67633408SHong Zhang       ierr = VecScale(VHV[nadj],-1);CHKERRQ(ierr);
584*67633408SHong Zhang     }
585*67633408SHong 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 
616*67633408SHong 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;
620*67633408SHong Zhang   }
621*67633408SHong Zhang   /* does not consider IMEX for now, so either IHessian or RHSHessian will be calculated, using the same output VHV */
622*67633408SHong Zhang   if (ts->rhshessianproduct_gpp) {
623*67633408SHong Zhang     PetscInt nadj;
624*67633408SHong Zhang     ierr = TSComputeRHSHessianProductFunction4(ts,t,U,Vl,Vr,VHV);CHKERRQ(ierr);
625*67633408SHong Zhang     for (nadj=0; nadj<ts->numcost; nadj++) {
626*67633408SHong Zhang       ierr = VecScale(VHV[nadj],-1);CHKERRQ(ierr);
627*67633408SHong Zhang     }
628*67633408SHong Zhang   }
629b5b4017aSHong Zhang   PetscFunctionReturn(0);
630b5b4017aSHong Zhang }
631b5b4017aSHong Zhang 
632814e85d6SHong Zhang /* --------------------------- Adjoint sensitivity ---------------------------*/
633814e85d6SHong Zhang 
634814e85d6SHong Zhang /*@
635814e85d6SHong 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
636814e85d6SHong Zhang       for use by the TSAdjoint routines.
637814e85d6SHong Zhang 
638814e85d6SHong Zhang    Logically Collective on TS and Vec
639814e85d6SHong Zhang 
640814e85d6SHong Zhang    Input Parameters:
641814e85d6SHong Zhang +  ts - the TS context obtained from TSCreate()
642814e85d6SHong 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
643814e85d6SHong Zhang -  mu - gradients with respect to the parameters, the number of entries in these vectors is the same as the number of parameters
644814e85d6SHong Zhang 
645814e85d6SHong Zhang    Level: beginner
646814e85d6SHong Zhang 
647814e85d6SHong Zhang    Notes:
648814e85d6SHong Zhang     the entries in these vectors must be correctly initialized with the values lamda_i = df/dy|finaltime  mu_i = df/dp|finaltime
649814e85d6SHong Zhang 
650814e85d6SHong Zhang    After TSAdjointSolve() is called the lamba and the mu contain the computed sensitivities
651814e85d6SHong Zhang 
652814e85d6SHong Zhang .keywords: TS, timestep, set, sensitivity, initial values
653b5b4017aSHong Zhang 
654b5b4017aSHong Zhang .seealso TSGetCostGradients()
655814e85d6SHong Zhang @*/
656814e85d6SHong Zhang PetscErrorCode TSSetCostGradients(TS ts,PetscInt numcost,Vec *lambda,Vec *mu)
657814e85d6SHong Zhang {
658814e85d6SHong Zhang   PetscFunctionBegin;
659814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
660814e85d6SHong Zhang   PetscValidPointer(lambda,2);
661814e85d6SHong Zhang   ts->vecs_sensi  = lambda;
662814e85d6SHong Zhang   ts->vecs_sensip = mu;
663814e85d6SHong 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");
664814e85d6SHong Zhang   ts->numcost  = numcost;
665814e85d6SHong Zhang   PetscFunctionReturn(0);
666814e85d6SHong Zhang }
667814e85d6SHong Zhang 
668814e85d6SHong Zhang /*@
669814e85d6SHong Zhang    TSGetCostGradients - Returns the gradients from the TSAdjointSolve()
670814e85d6SHong Zhang 
671814e85d6SHong Zhang    Not Collective, but Vec returned is parallel if TS is parallel
672814e85d6SHong Zhang 
673814e85d6SHong Zhang    Input Parameter:
674814e85d6SHong Zhang .  ts - the TS context obtained from TSCreate()
675814e85d6SHong Zhang 
676814e85d6SHong Zhang    Output Parameter:
677814e85d6SHong Zhang +  lambda - vectors containing the gradients of the cost functions with respect to the ODE/DAE solution variables
678814e85d6SHong Zhang -  mu - vectors containing the gradients of the cost functions with respect to the problem parameters
679814e85d6SHong Zhang 
680814e85d6SHong Zhang    Level: intermediate
681814e85d6SHong Zhang 
682814e85d6SHong Zhang .keywords: TS, timestep, get, sensitivity
683b5b4017aSHong Zhang 
684b5b4017aSHong Zhang .seealso: TSSetCostGradients()
685814e85d6SHong Zhang @*/
686814e85d6SHong Zhang PetscErrorCode TSGetCostGradients(TS ts,PetscInt *numcost,Vec **lambda,Vec **mu)
687814e85d6SHong Zhang {
688814e85d6SHong Zhang   PetscFunctionBegin;
689814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
690814e85d6SHong Zhang   if (numcost) *numcost = ts->numcost;
691814e85d6SHong Zhang   if (lambda)  *lambda  = ts->vecs_sensi;
692814e85d6SHong Zhang   if (mu)      *mu      = ts->vecs_sensip;
693814e85d6SHong Zhang   PetscFunctionReturn(0);
694814e85d6SHong Zhang }
695814e85d6SHong Zhang 
696814e85d6SHong Zhang /*@
697b5b4017aSHong 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
698b5b4017aSHong Zhang       for use by the TSAdjoint routines.
699b5b4017aSHong Zhang 
700b5b4017aSHong Zhang    Logically Collective on TS and Vec
701b5b4017aSHong Zhang 
702b5b4017aSHong Zhang    Input Parameters:
703b5b4017aSHong Zhang +  ts - the TS context obtained from TSCreate()
704b5b4017aSHong Zhang .  numcost - number of cost functions
705b5b4017aSHong 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
706b5b4017aSHong 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
707b5b4017aSHong Zhang -  dir - the direction vector that are multiplied with the Hessian of the cost functions
708b5b4017aSHong Zhang 
709b5b4017aSHong Zhang    Level: beginner
710b5b4017aSHong Zhang 
711b5b4017aSHong Zhang    Notes: Hessian of the cost function is completely different from Hessian of the ODE/DAE system
712b5b4017aSHong Zhang 
713b5b4017aSHong Zhang    For second-order adjoint, one needs to call this function and then TSAdjointInitializeForward() before TSSolve().
714b5b4017aSHong Zhang 
715b5b4017aSHong 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.
716b5b4017aSHong Zhang 
7173fca9621SHong Zhang    Passing NULL for lambda2 disables the second-order calculation.
718b5b4017aSHong Zhang .keywords: TS, sensitivity, second-order adjoint
719b5b4017aSHong Zhang 
720b5b4017aSHong Zhang .seealso: TSAdjointInitializeForward()
721b5b4017aSHong Zhang @*/
722b5b4017aSHong Zhang PetscErrorCode TSSetCostHessianProducts(TS ts,PetscInt numcost,Vec *lambda2,Vec *mu2,Vec dir)
723b5b4017aSHong Zhang {
724b5b4017aSHong Zhang   PetscFunctionBegin;
725b5b4017aSHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
726b5b4017aSHong 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");
727b5b4017aSHong Zhang   ts->numcost       = numcost;
728b5b4017aSHong Zhang   ts->vecs_sensi2   = lambda2;
72933f72c5dSHong Zhang   ts->vecs_sensi2p  = mu2;
730b5b4017aSHong Zhang   ts->vec_dir       = dir;
731b5b4017aSHong Zhang   PetscFunctionReturn(0);
732b5b4017aSHong Zhang }
733b5b4017aSHong Zhang 
734b5b4017aSHong Zhang /*@
735b5b4017aSHong Zhang    TSGetCostHessianProducts - Returns the gradients from the TSAdjointSolve()
736b5b4017aSHong Zhang 
737b5b4017aSHong Zhang    Not Collective, but Vec returned is parallel if TS is parallel
738b5b4017aSHong Zhang 
739b5b4017aSHong Zhang    Input Parameter:
740b5b4017aSHong Zhang .  ts - the TS context obtained from TSCreate()
741b5b4017aSHong Zhang 
742b5b4017aSHong Zhang    Output Parameter:
743b5b4017aSHong Zhang +  numcost - number of cost functions
744b5b4017aSHong 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
745b5b4017aSHong 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
746b5b4017aSHong Zhang -  dir - the direction vector that are multiplied with the Hessian of the cost functions
747b5b4017aSHong Zhang 
748b5b4017aSHong Zhang    Level: intermediate
749b5b4017aSHong Zhang 
750b5b4017aSHong Zhang .keywords: TS, sensitivity, second-order adjoint
751b5b4017aSHong Zhang 
752b5b4017aSHong Zhang .seealso: TSSetCostHessianProducts()
753b5b4017aSHong Zhang @*/
754b5b4017aSHong Zhang PetscErrorCode TSGetCostHessianProducts(TS ts,PetscInt *numcost,Vec **lambda2,Vec **mu2, Vec *dir)
755b5b4017aSHong Zhang {
756b5b4017aSHong Zhang   PetscFunctionBegin;
757b5b4017aSHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
758b5b4017aSHong Zhang   if (numcost) *numcost = ts->numcost;
759b5b4017aSHong Zhang   if (lambda2) *lambda2 = ts->vecs_sensi2;
76033f72c5dSHong Zhang   if (mu2)     *mu2     = ts->vecs_sensi2p;
761b5b4017aSHong Zhang   if (dir)     *dir     = ts->vec_dir;
762b5b4017aSHong Zhang   PetscFunctionReturn(0);
763b5b4017aSHong Zhang }
764b5b4017aSHong Zhang 
765b5b4017aSHong Zhang /*@
766b5b4017aSHong Zhang   TSAdjointInitializeForward - Trigger the tangent linear solver and initialize the forward sensitivities
767b5b4017aSHong Zhang 
768b5b4017aSHong Zhang   Logically Collective on TS and Mat
769b5b4017aSHong Zhang 
770b5b4017aSHong Zhang   Input Parameters:
771b5b4017aSHong Zhang +  ts - the TS context obtained from TSCreate()
772b5b4017aSHong Zhang -  didp - the derivative of initial values w.r.t. parameters
773b5b4017aSHong Zhang 
774b5b4017aSHong Zhang   Level: intermediate
775b5b4017aSHong Zhang 
776b5b4017aSHong 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.
777b5b4017aSHong Zhang 
778b5b4017aSHong Zhang .keywords: TS, sensitivity, second-order adjoint
779b5b4017aSHong Zhang 
780b5b4017aSHong Zhang .seealso: TSSetCostHessianProducts()
781b5b4017aSHong Zhang @*/
782b5b4017aSHong Zhang PetscErrorCode TSAdjointInitializeForward(TS ts,Mat didp)
783b5b4017aSHong Zhang {
78433f72c5dSHong Zhang   Mat            A;
78533f72c5dSHong Zhang   Vec            sp;
78633f72c5dSHong Zhang   PetscScalar    *xarr;
78733f72c5dSHong Zhang   PetscInt       lsize;
788b5b4017aSHong Zhang   PetscErrorCode ierr;
789b5b4017aSHong Zhang 
790b5b4017aSHong Zhang   PetscFunctionBegin;
791b5b4017aSHong Zhang   ts->forward_solve = PETSC_TRUE; /* turn on tangent linear mode */
792b5b4017aSHong Zhang   if (!ts->vecs_sensi2) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Must call TSSetCostHessianProducts() first");
79333f72c5dSHong Zhang   if (!ts->vec_dir) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Directional vector is missing. Call TSSetCostHessianProducts() to set it.");
79433f72c5dSHong Zhang   /* create a single-column dense matrix */
79533f72c5dSHong Zhang   ierr = VecGetLocalSize(ts->vec_sol,&lsize);CHKERRQ(ierr);
79633f72c5dSHong Zhang   ierr = MatCreateDense(PETSC_COMM_WORLD,lsize,PETSC_DECIDE,PETSC_DECIDE,1,NULL,&A);CHKERRQ(ierr);
79733f72c5dSHong Zhang 
79833f72c5dSHong Zhang   ierr = VecDuplicate(ts->vec_sol,&sp);CHKERRQ(ierr);
79933f72c5dSHong Zhang   ierr = MatDenseGetColumn(A,0,&xarr);CHKERRQ(ierr);
80033f72c5dSHong Zhang   ierr = VecPlaceArray(sp,xarr);CHKERRQ(ierr);
80133f72c5dSHong Zhang   if (ts->vecs_sensi2p) { /* TLM variable initialized as 2*dIdP*dir */
80233f72c5dSHong Zhang     if (didp) {
80333f72c5dSHong Zhang       ierr = MatMult(didp,ts->vec_dir,sp);CHKERRQ(ierr);
80433f72c5dSHong Zhang       ierr = VecScale(sp,2.);CHKERRQ(ierr);
80533f72c5dSHong Zhang     } else {
80633f72c5dSHong Zhang       ierr = VecZeroEntries(sp);CHKERRQ(ierr);
80733f72c5dSHong Zhang     }
80833f72c5dSHong Zhang   } else { /* TLM variable initialized as dir */
80933f72c5dSHong Zhang     ierr = VecCopy(ts->vec_dir,sp);CHKERRQ(ierr);
81033f72c5dSHong Zhang   }
81133f72c5dSHong Zhang   ierr = VecResetArray(sp);CHKERRQ(ierr);
81233f72c5dSHong Zhang   ierr = MatDenseRestoreColumn(A,&xarr);CHKERRQ(ierr);
81333f72c5dSHong Zhang   ierr = VecDestroy(&sp);CHKERRQ(ierr);
81433f72c5dSHong Zhang 
81533f72c5dSHong Zhang   ierr = TSForwardSetInitialSensitivities(ts,A);CHKERRQ(ierr); /* if didp is NULL, identity matrix is assumed */
81633f72c5dSHong Zhang 
81733f72c5dSHong Zhang   ierr = MatDestroy(&A);CHKERRQ(ierr);
818b5b4017aSHong Zhang   PetscFunctionReturn(0);
819b5b4017aSHong Zhang }
820b5b4017aSHong Zhang 
821b5b4017aSHong Zhang /*@
822814e85d6SHong Zhang    TSAdjointSetUp - Sets up the internal data structures for the later use
823814e85d6SHong Zhang    of an adjoint solver
824814e85d6SHong Zhang 
825814e85d6SHong Zhang    Collective on TS
826814e85d6SHong Zhang 
827814e85d6SHong Zhang    Input Parameter:
828814e85d6SHong Zhang .  ts - the TS context obtained from TSCreate()
829814e85d6SHong Zhang 
830814e85d6SHong Zhang    Level: advanced
831814e85d6SHong Zhang 
832814e85d6SHong Zhang .keywords: TS, timestep, setup
833814e85d6SHong Zhang 
834814e85d6SHong Zhang .seealso: TSCreate(), TSAdjointStep(), TSSetCostGradients()
835814e85d6SHong Zhang @*/
836814e85d6SHong Zhang PetscErrorCode TSAdjointSetUp(TS ts)
837814e85d6SHong Zhang {
838814e85d6SHong Zhang   PetscErrorCode ierr;
839814e85d6SHong Zhang 
840814e85d6SHong Zhang   PetscFunctionBegin;
841814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
842814e85d6SHong Zhang   if (ts->adjointsetupcalled) PetscFunctionReturn(0);
843814e85d6SHong Zhang   if (!ts->vecs_sensi) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONGSTATE,"Must call TSSetCostGradients() first");
84433f72c5dSHong Zhang   if (ts->vecs_sensip && !ts->Jacp && !ts->Jacprhs) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONGSTATE,"Must call TSSetRHSJacobianP() or TSSetIJacobianP() first");
84533f72c5dSHong Zhang 
84633f72c5dSHong Zhang   if (!ts->Jacp && ts->Jacprhs) ts->Jacp = ts->Jacprhs;
847814e85d6SHong Zhang 
848814e85d6SHong Zhang   if (ts->vec_costintegral) { /* if there is integral in the cost function */
849c9ad9de0SHong Zhang     ierr = VecDuplicateVecs(ts->vecs_sensi[0],ts->numcost,&ts->vecs_drdu);CHKERRQ(ierr);
850814e85d6SHong Zhang     if (ts->vecs_sensip){
851814e85d6SHong Zhang       ierr = VecDuplicateVecs(ts->vecs_sensip[0],ts->numcost,&ts->vecs_drdp);CHKERRQ(ierr);
852814e85d6SHong Zhang     }
853814e85d6SHong Zhang   }
854814e85d6SHong Zhang 
855814e85d6SHong Zhang   if (ts->ops->adjointsetup) {
856814e85d6SHong Zhang     ierr = (*ts->ops->adjointsetup)(ts);CHKERRQ(ierr);
857814e85d6SHong Zhang   }
858814e85d6SHong Zhang   ts->adjointsetupcalled = PETSC_TRUE;
859814e85d6SHong Zhang   PetscFunctionReturn(0);
860814e85d6SHong Zhang }
861814e85d6SHong Zhang 
862814e85d6SHong Zhang /*@
863ece46509SHong Zhang    TSAdjointReset - Resets a TSAdjoint context and removes any allocated Vecs and Mats.
864ece46509SHong Zhang 
865ece46509SHong Zhang    Collective on TS
866ece46509SHong Zhang 
867ece46509SHong Zhang    Input Parameter:
868ece46509SHong Zhang .  ts - the TS context obtained from TSCreate()
869ece46509SHong Zhang 
870ece46509SHong Zhang    Level: beginner
871ece46509SHong Zhang 
872ece46509SHong Zhang .keywords: TS, timestep, reset
873ece46509SHong Zhang 
874ece46509SHong Zhang .seealso: TSCreate(), TSAdjointSetup(), TSADestroy()
875ece46509SHong Zhang @*/
876ece46509SHong Zhang PetscErrorCode TSAdjointReset(TS ts)
877ece46509SHong Zhang {
878ece46509SHong Zhang   PetscErrorCode ierr;
879ece46509SHong Zhang 
880ece46509SHong Zhang   PetscFunctionBegin;
881ece46509SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
882ece46509SHong Zhang   if (ts->ops->adjointreset) {
883ece46509SHong Zhang     ierr = (*ts->ops->adjointreset)(ts);CHKERRQ(ierr);
884ece46509SHong Zhang   }
885cda2db4bSHong Zhang   if (ts->vec_dir) { /* second-order adjoint */
886cda2db4bSHong Zhang     ierr = TSForwardReset(ts);CHKERRQ(ierr);
887cda2db4bSHong Zhang   }
888ece46509SHong Zhang   ts->vecs_sensi         = NULL;
889ece46509SHong Zhang   ts->vecs_sensip        = NULL;
890ece46509SHong Zhang   ts->vecs_sensi2        = NULL;
89133f72c5dSHong Zhang   ts->vecs_sensi2p       = NULL;
892ece46509SHong Zhang   ts->vec_dir            = NULL;
893ece46509SHong Zhang   ts->adjointsetupcalled = PETSC_FALSE;
894ece46509SHong Zhang   PetscFunctionReturn(0);
895ece46509SHong Zhang }
896ece46509SHong Zhang 
897ece46509SHong Zhang /*@
898814e85d6SHong Zhang    TSAdjointSetSteps - Sets the number of steps the adjoint solver should take backward in time
899814e85d6SHong Zhang 
900814e85d6SHong Zhang    Logically Collective on TS
901814e85d6SHong Zhang 
902814e85d6SHong Zhang    Input Parameters:
903814e85d6SHong Zhang +  ts - the TS context obtained from TSCreate()
904814e85d6SHong Zhang .  steps - number of steps to use
905814e85d6SHong Zhang 
906814e85d6SHong Zhang    Level: intermediate
907814e85d6SHong Zhang 
908814e85d6SHong Zhang    Notes:
909814e85d6SHong Zhang     Normally one does not call this and TSAdjointSolve() integrates back to the original timestep. One can call this
910814e85d6SHong Zhang           so as to integrate back to less than the original timestep
911814e85d6SHong Zhang 
912814e85d6SHong Zhang .keywords: TS, timestep, set, maximum, iterations
913814e85d6SHong Zhang 
914814e85d6SHong Zhang .seealso: TSSetExactFinalTime()
915814e85d6SHong Zhang @*/
916814e85d6SHong Zhang PetscErrorCode TSAdjointSetSteps(TS ts,PetscInt steps)
917814e85d6SHong Zhang {
918814e85d6SHong Zhang   PetscFunctionBegin;
919814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
920814e85d6SHong Zhang   PetscValidLogicalCollectiveInt(ts,steps,2);
921814e85d6SHong Zhang   if (steps < 0) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Cannot step back a negative number of steps");
922814e85d6SHong Zhang   if (steps > ts->steps) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Cannot step back more than the total number of forward steps");
923814e85d6SHong Zhang   ts->adjoint_max_steps = steps;
924814e85d6SHong Zhang   PetscFunctionReturn(0);
925814e85d6SHong Zhang }
926814e85d6SHong Zhang 
927814e85d6SHong Zhang /*@C
928814e85d6SHong Zhang   TSAdjointSetRHSJacobian - Deprecated, use TSSetRHSJacobianP()
929814e85d6SHong Zhang 
930814e85d6SHong Zhang   Level: deprecated
931814e85d6SHong Zhang 
932814e85d6SHong Zhang @*/
933814e85d6SHong Zhang PetscErrorCode TSAdjointSetRHSJacobian(TS ts,Mat Amat,PetscErrorCode (*func)(TS,PetscReal,Vec,Mat,void*),void *ctx)
934814e85d6SHong Zhang {
935814e85d6SHong Zhang   PetscErrorCode ierr;
936814e85d6SHong Zhang 
937814e85d6SHong Zhang   PetscFunctionBegin;
938814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
939814e85d6SHong Zhang   PetscValidHeaderSpecific(Amat,MAT_CLASSID,2);
940814e85d6SHong Zhang 
941814e85d6SHong Zhang   ts->rhsjacobianp    = func;
942814e85d6SHong Zhang   ts->rhsjacobianpctx = ctx;
943814e85d6SHong Zhang   if(Amat) {
944814e85d6SHong Zhang     ierr = PetscObjectReference((PetscObject)Amat);CHKERRQ(ierr);
945814e85d6SHong Zhang     ierr = MatDestroy(&ts->Jacp);CHKERRQ(ierr);
946814e85d6SHong Zhang     ts->Jacp = Amat;
947814e85d6SHong Zhang   }
948814e85d6SHong Zhang   PetscFunctionReturn(0);
949814e85d6SHong Zhang }
950814e85d6SHong Zhang 
951814e85d6SHong Zhang /*@C
952814e85d6SHong Zhang   TSAdjointComputeRHSJacobian - Deprecated, use TSComputeRHSJacobianP()
953814e85d6SHong Zhang 
954814e85d6SHong Zhang   Level: deprecated
955814e85d6SHong Zhang 
956814e85d6SHong Zhang @*/
957c9ad9de0SHong Zhang PetscErrorCode TSAdjointComputeRHSJacobian(TS ts,PetscReal t,Vec U,Mat Amat)
958814e85d6SHong Zhang {
959814e85d6SHong Zhang   PetscErrorCode ierr;
960814e85d6SHong Zhang 
961814e85d6SHong Zhang   PetscFunctionBegin;
962814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
963c9ad9de0SHong Zhang   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
964814e85d6SHong Zhang   PetscValidPointer(Amat,4);
965814e85d6SHong Zhang 
966814e85d6SHong Zhang   PetscStackPush("TS user JacobianP function for sensitivity analysis");
967c9ad9de0SHong Zhang   ierr = (*ts->rhsjacobianp)(ts,t,U,Amat,ts->rhsjacobianpctx); CHKERRQ(ierr);
968814e85d6SHong Zhang   PetscStackPop;
969814e85d6SHong Zhang   PetscFunctionReturn(0);
970814e85d6SHong Zhang }
971814e85d6SHong Zhang 
972814e85d6SHong Zhang /*@
973c9ad9de0SHong Zhang   TSAdjointComputeDRDYFunction - Deprecated, use TSComputeDRDUFunction()
974814e85d6SHong Zhang 
975814e85d6SHong Zhang   Level: deprecated
976814e85d6SHong Zhang 
977814e85d6SHong Zhang @*/
978c9ad9de0SHong Zhang PetscErrorCode TSAdjointComputeDRDYFunction(TS ts,PetscReal t,Vec U,Vec *DRDU)
979814e85d6SHong Zhang {
980814e85d6SHong Zhang   PetscErrorCode ierr;
981814e85d6SHong Zhang 
982814e85d6SHong Zhang   PetscFunctionBegin;
983814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
984c9ad9de0SHong Zhang   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
985814e85d6SHong Zhang 
986814e85d6SHong Zhang   PetscStackPush("TS user DRDY function for sensitivity analysis");
987c9ad9de0SHong Zhang   ierr = (*ts->drdufunction)(ts,t,U,DRDU,ts->costintegrandctx); CHKERRQ(ierr);
988814e85d6SHong Zhang   PetscStackPop;
989814e85d6SHong Zhang   PetscFunctionReturn(0);
990814e85d6SHong Zhang }
991814e85d6SHong Zhang 
992814e85d6SHong Zhang /*@
993814e85d6SHong Zhang   TSAdjointComputeDRDPFunction - Deprecated, use TSComputeDRDPFunction()
994814e85d6SHong Zhang 
995814e85d6SHong Zhang   Level: deprecated
996814e85d6SHong Zhang 
997814e85d6SHong Zhang @*/
998c9ad9de0SHong Zhang PetscErrorCode TSAdjointComputeDRDPFunction(TS ts,PetscReal t,Vec U,Vec *DRDP)
999814e85d6SHong Zhang {
1000814e85d6SHong Zhang   PetscErrorCode ierr;
1001814e85d6SHong Zhang 
1002814e85d6SHong Zhang   PetscFunctionBegin;
1003814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1004c9ad9de0SHong Zhang   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
1005814e85d6SHong Zhang 
1006814e85d6SHong Zhang   PetscStackPush("TS user DRDP function for sensitivity analysis");
1007c9ad9de0SHong Zhang   ierr = (*ts->drdpfunction)(ts,t,U,DRDP,ts->costintegrandctx); CHKERRQ(ierr);
1008814e85d6SHong Zhang   PetscStackPop;
1009814e85d6SHong Zhang   PetscFunctionReturn(0);
1010814e85d6SHong Zhang }
1011814e85d6SHong Zhang 
1012814e85d6SHong Zhang /*@C
1013814e85d6SHong Zhang    TSAdjointMonitorSensi - monitors the first lambda sensitivity
1014814e85d6SHong Zhang 
1015814e85d6SHong Zhang    Level: intermediate
1016814e85d6SHong Zhang 
1017814e85d6SHong Zhang .keywords: TS, set, monitor
1018814e85d6SHong Zhang 
1019814e85d6SHong Zhang .seealso: TSAdjointMonitorSet()
1020814e85d6SHong Zhang @*/
1021814e85d6SHong Zhang PetscErrorCode TSAdjointMonitorSensi(TS ts,PetscInt step,PetscReal ptime,Vec v,PetscInt numcost,Vec *lambda,Vec *mu,PetscViewerAndFormat *vf)
1022814e85d6SHong Zhang {
1023814e85d6SHong Zhang   PetscErrorCode ierr;
1024814e85d6SHong Zhang   PetscViewer    viewer = vf->viewer;
1025814e85d6SHong Zhang 
1026814e85d6SHong Zhang   PetscFunctionBegin;
1027814e85d6SHong Zhang   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,4);
1028814e85d6SHong Zhang   ierr = PetscViewerPushFormat(viewer,vf->format);CHKERRQ(ierr);
1029814e85d6SHong Zhang   ierr = VecView(lambda[0],viewer);CHKERRQ(ierr);
1030814e85d6SHong Zhang   ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
1031814e85d6SHong Zhang   PetscFunctionReturn(0);
1032814e85d6SHong Zhang }
1033814e85d6SHong Zhang 
1034814e85d6SHong Zhang /*@C
1035814e85d6SHong Zhang    TSAdjointMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user
1036814e85d6SHong Zhang 
1037814e85d6SHong Zhang    Collective on TS
1038814e85d6SHong Zhang 
1039814e85d6SHong Zhang    Input Parameters:
1040814e85d6SHong Zhang +  ts - TS object you wish to monitor
1041814e85d6SHong Zhang .  name - the monitor type one is seeking
1042814e85d6SHong Zhang .  help - message indicating what monitoring is done
1043814e85d6SHong Zhang .  manual - manual page for the monitor
1044814e85d6SHong Zhang .  monitor - the monitor function
1045814e85d6SHong 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
1046814e85d6SHong Zhang 
1047814e85d6SHong Zhang    Level: developer
1048814e85d6SHong Zhang 
1049814e85d6SHong Zhang .seealso: PetscOptionsGetViewer(), PetscOptionsGetReal(), PetscOptionsHasName(), PetscOptionsGetString(),
1050814e85d6SHong Zhang           PetscOptionsGetIntArray(), PetscOptionsGetRealArray(), PetscOptionsBool()
1051814e85d6SHong Zhang           PetscOptionsInt(), PetscOptionsString(), PetscOptionsReal(), PetscOptionsBool(),
1052814e85d6SHong Zhang           PetscOptionsName(), PetscOptionsBegin(), PetscOptionsEnd(), PetscOptionsHead(),
1053814e85d6SHong Zhang           PetscOptionsStringArray(),PetscOptionsRealArray(), PetscOptionsScalar(),
1054814e85d6SHong Zhang           PetscOptionsBoolGroupBegin(), PetscOptionsBoolGroup(), PetscOptionsBoolGroupEnd(),
1055814e85d6SHong Zhang           PetscOptionsFList(), PetscOptionsEList()
1056814e85d6SHong Zhang @*/
1057814e85d6SHong 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*))
1058814e85d6SHong Zhang {
1059814e85d6SHong Zhang   PetscErrorCode    ierr;
1060814e85d6SHong Zhang   PetscViewer       viewer;
1061814e85d6SHong Zhang   PetscViewerFormat format;
1062814e85d6SHong Zhang   PetscBool         flg;
1063814e85d6SHong Zhang 
1064814e85d6SHong Zhang   PetscFunctionBegin;
106516413a6aSBarry Smith   ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject)ts),((PetscObject) ts)->options,((PetscObject)ts)->prefix,name,&viewer,&format,&flg);CHKERRQ(ierr);
1066814e85d6SHong Zhang   if (flg) {
1067814e85d6SHong Zhang     PetscViewerAndFormat *vf;
1068814e85d6SHong Zhang     ierr = PetscViewerAndFormatCreate(viewer,format,&vf);CHKERRQ(ierr);
1069814e85d6SHong Zhang     ierr = PetscObjectDereference((PetscObject)viewer);CHKERRQ(ierr);
1070814e85d6SHong Zhang     if (monitorsetup) {
1071814e85d6SHong Zhang       ierr = (*monitorsetup)(ts,vf);CHKERRQ(ierr);
1072814e85d6SHong Zhang     }
1073814e85d6SHong Zhang     ierr = TSAdjointMonitorSet(ts,(PetscErrorCode (*)(TS,PetscInt,PetscReal,Vec,PetscInt,Vec*,Vec*,void*))monitor,vf,(PetscErrorCode (*)(void**))PetscViewerAndFormatDestroy);CHKERRQ(ierr);
1074814e85d6SHong Zhang   }
1075814e85d6SHong Zhang   PetscFunctionReturn(0);
1076814e85d6SHong Zhang }
1077814e85d6SHong Zhang 
1078814e85d6SHong Zhang /*@C
1079814e85d6SHong Zhang    TSAdjointMonitorSet - Sets an ADDITIONAL function that is to be used at every
1080814e85d6SHong Zhang    timestep to display the iteration's  progress.
1081814e85d6SHong Zhang 
1082814e85d6SHong Zhang    Logically Collective on TS
1083814e85d6SHong Zhang 
1084814e85d6SHong Zhang    Input Parameters:
1085814e85d6SHong Zhang +  ts - the TS context obtained from TSCreate()
1086814e85d6SHong Zhang .  adjointmonitor - monitoring routine
1087814e85d6SHong Zhang .  adjointmctx - [optional] user-defined context for private data for the
1088814e85d6SHong Zhang              monitor routine (use NULL if no context is desired)
1089814e85d6SHong Zhang -  adjointmonitordestroy - [optional] routine that frees monitor context
1090814e85d6SHong Zhang           (may be NULL)
1091814e85d6SHong Zhang 
1092814e85d6SHong Zhang    Calling sequence of monitor:
1093814e85d6SHong Zhang $    int adjointmonitor(TS ts,PetscInt steps,PetscReal time,Vec u,PetscInt numcost,Vec *lambda, Vec *mu,void *adjointmctx)
1094814e85d6SHong Zhang 
1095814e85d6SHong Zhang +    ts - the TS context
1096814e85d6SHong 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
1097814e85d6SHong Zhang                                been interpolated to)
1098814e85d6SHong Zhang .    time - current time
1099814e85d6SHong Zhang .    u - current iterate
1100814e85d6SHong Zhang .    numcost - number of cost functionos
1101814e85d6SHong Zhang .    lambda - sensitivities to initial conditions
1102814e85d6SHong Zhang .    mu - sensitivities to parameters
1103814e85d6SHong Zhang -    adjointmctx - [optional] adjoint monitoring context
1104814e85d6SHong Zhang 
1105814e85d6SHong Zhang    Notes:
1106814e85d6SHong Zhang    This routine adds an additional monitor to the list of monitors that
1107814e85d6SHong Zhang    already has been loaded.
1108814e85d6SHong Zhang 
1109814e85d6SHong Zhang    Fortran Notes:
1110814e85d6SHong Zhang     Only a single monitor function can be set for each TS object
1111814e85d6SHong Zhang 
1112814e85d6SHong Zhang    Level: intermediate
1113814e85d6SHong Zhang 
1114814e85d6SHong Zhang .keywords: TS, timestep, set, adjoint, monitor
1115814e85d6SHong Zhang 
1116814e85d6SHong Zhang .seealso: TSAdjointMonitorCancel()
1117814e85d6SHong Zhang @*/
1118814e85d6SHong Zhang PetscErrorCode TSAdjointMonitorSet(TS ts,PetscErrorCode (*adjointmonitor)(TS,PetscInt,PetscReal,Vec,PetscInt,Vec*,Vec*,void*),void *adjointmctx,PetscErrorCode (*adjointmdestroy)(void**))
1119814e85d6SHong Zhang {
1120814e85d6SHong Zhang   PetscErrorCode ierr;
1121814e85d6SHong Zhang   PetscInt       i;
1122814e85d6SHong Zhang   PetscBool      identical;
1123814e85d6SHong Zhang 
1124814e85d6SHong Zhang   PetscFunctionBegin;
1125814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1126814e85d6SHong Zhang   for (i=0; i<ts->numbermonitors;i++) {
1127814e85d6SHong Zhang     ierr = PetscMonitorCompare((PetscErrorCode (*)(void))adjointmonitor,adjointmctx,adjointmdestroy,(PetscErrorCode (*)(void))ts->adjointmonitor[i],ts->adjointmonitorcontext[i],ts->adjointmonitordestroy[i],&identical);CHKERRQ(ierr);
1128814e85d6SHong Zhang     if (identical) PetscFunctionReturn(0);
1129814e85d6SHong Zhang   }
1130814e85d6SHong Zhang   if (ts->numberadjointmonitors >= MAXTSMONITORS) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Too many adjoint monitors set");
1131814e85d6SHong Zhang   ts->adjointmonitor[ts->numberadjointmonitors]          = adjointmonitor;
1132814e85d6SHong Zhang   ts->adjointmonitordestroy[ts->numberadjointmonitors]   = adjointmdestroy;
1133814e85d6SHong Zhang   ts->adjointmonitorcontext[ts->numberadjointmonitors++] = (void*)adjointmctx;
1134814e85d6SHong Zhang   PetscFunctionReturn(0);
1135814e85d6SHong Zhang }
1136814e85d6SHong Zhang 
1137814e85d6SHong Zhang /*@C
1138814e85d6SHong Zhang    TSAdjointMonitorCancel - Clears all the adjoint monitors that have been set on a time-step object.
1139814e85d6SHong Zhang 
1140814e85d6SHong Zhang    Logically Collective on TS
1141814e85d6SHong Zhang 
1142814e85d6SHong Zhang    Input Parameters:
1143814e85d6SHong Zhang .  ts - the TS context obtained from TSCreate()
1144814e85d6SHong Zhang 
1145814e85d6SHong Zhang    Notes:
1146814e85d6SHong Zhang    There is no way to remove a single, specific monitor.
1147814e85d6SHong Zhang 
1148814e85d6SHong Zhang    Level: intermediate
1149814e85d6SHong Zhang 
1150814e85d6SHong Zhang .keywords: TS, timestep, set, adjoint, monitor
1151814e85d6SHong Zhang 
1152814e85d6SHong Zhang .seealso: TSAdjointMonitorSet()
1153814e85d6SHong Zhang @*/
1154814e85d6SHong Zhang PetscErrorCode TSAdjointMonitorCancel(TS ts)
1155814e85d6SHong Zhang {
1156814e85d6SHong Zhang   PetscErrorCode ierr;
1157814e85d6SHong Zhang   PetscInt       i;
1158814e85d6SHong Zhang 
1159814e85d6SHong Zhang   PetscFunctionBegin;
1160814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1161814e85d6SHong Zhang   for (i=0; i<ts->numberadjointmonitors; i++) {
1162814e85d6SHong Zhang     if (ts->adjointmonitordestroy[i]) {
1163814e85d6SHong Zhang       ierr = (*ts->adjointmonitordestroy[i])(&ts->adjointmonitorcontext[i]);CHKERRQ(ierr);
1164814e85d6SHong Zhang     }
1165814e85d6SHong Zhang   }
1166814e85d6SHong Zhang   ts->numberadjointmonitors = 0;
1167814e85d6SHong Zhang   PetscFunctionReturn(0);
1168814e85d6SHong Zhang }
1169814e85d6SHong Zhang 
1170814e85d6SHong Zhang /*@C
1171814e85d6SHong Zhang    TSAdjointMonitorDefault - the default monitor of adjoint computations
1172814e85d6SHong Zhang 
1173814e85d6SHong Zhang    Level: intermediate
1174814e85d6SHong Zhang 
1175814e85d6SHong Zhang .keywords: TS, set, monitor
1176814e85d6SHong Zhang 
1177814e85d6SHong Zhang .seealso: TSAdjointMonitorSet()
1178814e85d6SHong Zhang @*/
1179814e85d6SHong Zhang PetscErrorCode TSAdjointMonitorDefault(TS ts,PetscInt step,PetscReal ptime,Vec v,PetscInt numcost,Vec *lambda,Vec *mu,PetscViewerAndFormat *vf)
1180814e85d6SHong Zhang {
1181814e85d6SHong Zhang   PetscErrorCode ierr;
1182814e85d6SHong Zhang   PetscViewer    viewer = vf->viewer;
1183814e85d6SHong Zhang 
1184814e85d6SHong Zhang   PetscFunctionBegin;
1185814e85d6SHong Zhang   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,4);
1186814e85d6SHong Zhang   ierr = PetscViewerPushFormat(viewer,vf->format);CHKERRQ(ierr);
1187814e85d6SHong Zhang   ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)ts)->tablevel);CHKERRQ(ierr);
1188814e85d6SHong 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);
1189814e85d6SHong Zhang   ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)ts)->tablevel);CHKERRQ(ierr);
1190814e85d6SHong Zhang   ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
1191814e85d6SHong Zhang   PetscFunctionReturn(0);
1192814e85d6SHong Zhang }
1193814e85d6SHong Zhang 
1194814e85d6SHong Zhang /*@C
1195814e85d6SHong Zhang    TSAdjointMonitorDrawSensi - Monitors progress of the adjoint TS solvers by calling
1196814e85d6SHong Zhang    VecView() for the sensitivities to initial states at each timestep
1197814e85d6SHong Zhang 
1198814e85d6SHong Zhang    Collective on TS
1199814e85d6SHong Zhang 
1200814e85d6SHong Zhang    Input Parameters:
1201814e85d6SHong Zhang +  ts - the TS context
1202814e85d6SHong Zhang .  step - current time-step
1203814e85d6SHong Zhang .  ptime - current time
1204814e85d6SHong Zhang .  u - current state
1205814e85d6SHong Zhang .  numcost - number of cost functions
1206814e85d6SHong Zhang .  lambda - sensitivities to initial conditions
1207814e85d6SHong Zhang .  mu - sensitivities to parameters
1208814e85d6SHong Zhang -  dummy - either a viewer or NULL
1209814e85d6SHong Zhang 
1210814e85d6SHong Zhang    Level: intermediate
1211814e85d6SHong Zhang 
1212814e85d6SHong Zhang .keywords: TS,  vector, adjoint, monitor, view
1213814e85d6SHong Zhang 
1214814e85d6SHong Zhang .seealso: TSAdjointMonitorSet(), TSAdjointMonitorDefault(), VecView()
1215814e85d6SHong Zhang @*/
1216814e85d6SHong Zhang PetscErrorCode TSAdjointMonitorDrawSensi(TS ts,PetscInt step,PetscReal ptime,Vec u,PetscInt numcost,Vec *lambda,Vec *mu,void *dummy)
1217814e85d6SHong Zhang {
1218814e85d6SHong Zhang   PetscErrorCode   ierr;
1219814e85d6SHong Zhang   TSMonitorDrawCtx ictx = (TSMonitorDrawCtx)dummy;
1220814e85d6SHong Zhang   PetscDraw        draw;
1221814e85d6SHong Zhang   PetscReal        xl,yl,xr,yr,h;
1222814e85d6SHong Zhang   char             time[32];
1223814e85d6SHong Zhang 
1224814e85d6SHong Zhang   PetscFunctionBegin;
1225814e85d6SHong Zhang   if (!(((ictx->howoften > 0) && (!(step % ictx->howoften))) || ((ictx->howoften == -1) && ts->reason))) PetscFunctionReturn(0);
1226814e85d6SHong Zhang 
1227814e85d6SHong Zhang   ierr = VecView(lambda[0],ictx->viewer);CHKERRQ(ierr);
1228814e85d6SHong Zhang   ierr = PetscViewerDrawGetDraw(ictx->viewer,0,&draw);CHKERRQ(ierr);
1229814e85d6SHong Zhang   ierr = PetscSNPrintf(time,32,"Timestep %d Time %g",(int)step,(double)ptime);CHKERRQ(ierr);
1230814e85d6SHong Zhang   ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
1231814e85d6SHong Zhang   h    = yl + .95*(yr - yl);
1232814e85d6SHong Zhang   ierr = PetscDrawStringCentered(draw,.5*(xl+xr),h,PETSC_DRAW_BLACK,time);CHKERRQ(ierr);
1233814e85d6SHong Zhang   ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
1234814e85d6SHong Zhang   PetscFunctionReturn(0);
1235814e85d6SHong Zhang }
1236814e85d6SHong Zhang 
1237814e85d6SHong Zhang /*
1238814e85d6SHong Zhang    TSAdjointSetFromOptions - Sets various TSAdjoint parameters from user options.
1239814e85d6SHong Zhang 
1240814e85d6SHong Zhang    Collective on TSAdjoint
1241814e85d6SHong Zhang 
1242814e85d6SHong Zhang    Input Parameter:
1243814e85d6SHong Zhang .  ts - the TS context
1244814e85d6SHong Zhang 
1245814e85d6SHong Zhang    Options Database Keys:
1246814e85d6SHong Zhang +  -ts_adjoint_solve <yes,no> After solving the ODE/DAE solve the adjoint problem (requires -ts_save_trajectory)
1247814e85d6SHong Zhang .  -ts_adjoint_monitor - print information at each adjoint time step
1248814e85d6SHong Zhang -  -ts_adjoint_monitor_draw_sensi - monitor the sensitivity of the first cost function wrt initial conditions (lambda[0]) graphically
1249814e85d6SHong Zhang 
1250814e85d6SHong Zhang    Level: developer
1251814e85d6SHong Zhang 
1252814e85d6SHong Zhang    Notes:
1253814e85d6SHong Zhang     This is not normally called directly by users
1254814e85d6SHong Zhang 
1255814e85d6SHong Zhang .keywords: TS, trajectory, timestep, set, options, database
1256814e85d6SHong Zhang 
1257814e85d6SHong Zhang .seealso: TSSetSaveTrajectory(), TSTrajectorySetUp()
1258814e85d6SHong Zhang */
1259814e85d6SHong Zhang PetscErrorCode TSAdjointSetFromOptions(PetscOptionItems *PetscOptionsObject,TS ts)
1260814e85d6SHong Zhang {
1261814e85d6SHong Zhang   PetscBool      tflg,opt;
1262814e85d6SHong Zhang   PetscErrorCode ierr;
1263814e85d6SHong Zhang 
1264814e85d6SHong Zhang   PetscFunctionBegin;
1265814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,2);
1266814e85d6SHong Zhang   ierr = PetscOptionsHead(PetscOptionsObject,"TS Adjoint options");CHKERRQ(ierr);
1267814e85d6SHong Zhang   tflg = ts->adjoint_solve ? PETSC_TRUE : PETSC_FALSE;
1268814e85d6SHong Zhang   ierr = PetscOptionsBool("-ts_adjoint_solve","Solve the adjoint problem immediately after solving the forward problem","",tflg,&tflg,&opt);CHKERRQ(ierr);
1269814e85d6SHong Zhang   if (opt) {
1270814e85d6SHong Zhang     ierr = TSSetSaveTrajectory(ts);CHKERRQ(ierr);
1271814e85d6SHong Zhang     ts->adjoint_solve = tflg;
1272814e85d6SHong Zhang   }
1273814e85d6SHong Zhang   ierr = TSAdjointMonitorSetFromOptions(ts,"-ts_adjoint_monitor","Monitor adjoint timestep size","TSAdjointMonitorDefault",TSAdjointMonitorDefault,NULL);CHKERRQ(ierr);
1274814e85d6SHong Zhang   ierr = TSAdjointMonitorSetFromOptions(ts,"-ts_adjoint_monitor_sensi","Monitor sensitivity in the adjoint computation","TSAdjointMonitorSensi",TSAdjointMonitorSensi,NULL);CHKERRQ(ierr);
1275814e85d6SHong Zhang   opt  = PETSC_FALSE;
1276814e85d6SHong Zhang   ierr = PetscOptionsName("-ts_adjoint_monitor_draw_sensi","Monitor adjoint sensitivities (lambda only) graphically","TSAdjointMonitorDrawSensi",&opt);CHKERRQ(ierr);
1277814e85d6SHong Zhang   if (opt) {
1278814e85d6SHong Zhang     TSMonitorDrawCtx ctx;
1279814e85d6SHong Zhang     PetscInt         howoften = 1;
1280814e85d6SHong Zhang 
1281814e85d6SHong Zhang     ierr = PetscOptionsInt("-ts_adjoint_monitor_draw_sensi","Monitor adjoint sensitivities (lambda only) graphically","TSAdjointMonitorDrawSensi",howoften,&howoften,NULL);CHKERRQ(ierr);
1282814e85d6SHong Zhang     ierr = TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts),0,0,PETSC_DECIDE,PETSC_DECIDE,300,300,howoften,&ctx);CHKERRQ(ierr);
1283814e85d6SHong Zhang     ierr = TSAdjointMonitorSet(ts,TSAdjointMonitorDrawSensi,ctx,(PetscErrorCode (*)(void**))TSMonitorDrawCtxDestroy);CHKERRQ(ierr);
1284814e85d6SHong Zhang   }
1285814e85d6SHong Zhang   PetscFunctionReturn(0);
1286814e85d6SHong Zhang }
1287814e85d6SHong Zhang 
1288814e85d6SHong Zhang /*@
1289814e85d6SHong Zhang    TSAdjointStep - Steps one time step backward in the adjoint run
1290814e85d6SHong Zhang 
1291814e85d6SHong Zhang    Collective on TS
1292814e85d6SHong Zhang 
1293814e85d6SHong Zhang    Input Parameter:
1294814e85d6SHong Zhang .  ts - the TS context obtained from TSCreate()
1295814e85d6SHong Zhang 
1296814e85d6SHong Zhang    Level: intermediate
1297814e85d6SHong Zhang 
1298814e85d6SHong Zhang .keywords: TS, adjoint, step
1299814e85d6SHong Zhang 
1300814e85d6SHong Zhang .seealso: TSAdjointSetUp(), TSAdjointSolve()
1301814e85d6SHong Zhang @*/
1302814e85d6SHong Zhang PetscErrorCode TSAdjointStep(TS ts)
1303814e85d6SHong Zhang {
1304814e85d6SHong Zhang   DM               dm;
1305814e85d6SHong Zhang   PetscErrorCode   ierr;
1306814e85d6SHong Zhang 
1307814e85d6SHong Zhang   PetscFunctionBegin;
1308814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1309814e85d6SHong Zhang   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
1310814e85d6SHong Zhang   ierr = TSAdjointSetUp(ts);CHKERRQ(ierr);
1311814e85d6SHong Zhang 
1312814e85d6SHong Zhang   ts->reason = TS_CONVERGED_ITERATING;
1313814e85d6SHong Zhang   ts->ptime_prev = ts->ptime;
1314814e85d6SHong 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);
1315814e85d6SHong Zhang   ierr = PetscLogEventBegin(TS_AdjointStep,ts,0,0,0);CHKERRQ(ierr);
1316814e85d6SHong Zhang   ierr = (*ts->ops->adjointstep)(ts);CHKERRQ(ierr);
1317814e85d6SHong Zhang   ierr = PetscLogEventEnd(TS_AdjointStep,ts,0,0,0);CHKERRQ(ierr);
1318814e85d6SHong Zhang   ts->adjoint_steps++; ts->steps--;
1319814e85d6SHong Zhang 
1320814e85d6SHong Zhang   if (ts->reason < 0) {
1321814e85d6SHong Zhang     if (ts->errorifstepfailed) {
132205c9950eSHong 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]);
132305c9950eSHong Zhang       else SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_NOT_CONVERGED,"TSAdjointStep has failed due to %s",TSConvergedReasons[ts->reason]);
1324814e85d6SHong Zhang     }
1325814e85d6SHong Zhang   } else if (!ts->reason) {
1326814e85d6SHong Zhang     if (ts->adjoint_steps >= ts->adjoint_max_steps) ts->reason = TS_CONVERGED_ITS;
1327814e85d6SHong Zhang   }
1328814e85d6SHong Zhang   PetscFunctionReturn(0);
1329814e85d6SHong Zhang }
1330814e85d6SHong Zhang 
1331814e85d6SHong Zhang /*@
1332814e85d6SHong Zhang    TSAdjointSolve - Solves the discrete ajoint problem for an ODE/DAE
1333814e85d6SHong Zhang 
1334814e85d6SHong Zhang    Collective on TS
1335814e85d6SHong Zhang 
1336814e85d6SHong Zhang    Input Parameter:
1337814e85d6SHong Zhang .  ts - the TS context obtained from TSCreate()
1338814e85d6SHong Zhang 
1339814e85d6SHong Zhang    Options Database:
1340814e85d6SHong Zhang . -ts_adjoint_view_solution <viewerinfo> - views the first gradient with respect to the initial values
1341814e85d6SHong Zhang 
1342814e85d6SHong Zhang    Level: intermediate
1343814e85d6SHong Zhang 
1344814e85d6SHong Zhang    Notes:
1345814e85d6SHong Zhang    This must be called after a call to TSSolve() that solves the forward problem
1346814e85d6SHong Zhang 
1347814e85d6SHong Zhang    By default this will integrate back to the initial time, one can use TSAdjointSetSteps() to step back to a later time
1348814e85d6SHong Zhang 
1349814e85d6SHong Zhang .keywords: TS, timestep, solve
1350814e85d6SHong Zhang 
1351814e85d6SHong Zhang .seealso: TSCreate(), TSSetCostGradients(), TSSetSolution(), TSAdjointStep()
1352814e85d6SHong Zhang @*/
1353814e85d6SHong Zhang PetscErrorCode TSAdjointSolve(TS ts)
1354814e85d6SHong Zhang {
1355814e85d6SHong Zhang   PetscErrorCode    ierr;
1356814e85d6SHong Zhang 
1357814e85d6SHong Zhang   PetscFunctionBegin;
1358814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1359814e85d6SHong Zhang   ierr = TSAdjointSetUp(ts);CHKERRQ(ierr);
1360814e85d6SHong Zhang 
1361814e85d6SHong Zhang   /* reset time step and iteration counters */
1362814e85d6SHong Zhang   ts->adjoint_steps     = 0;
1363814e85d6SHong Zhang   ts->ksp_its           = 0;
1364814e85d6SHong Zhang   ts->snes_its          = 0;
1365814e85d6SHong Zhang   ts->num_snes_failures = 0;
1366814e85d6SHong Zhang   ts->reject            = 0;
1367814e85d6SHong Zhang   ts->reason            = TS_CONVERGED_ITERATING;
1368814e85d6SHong Zhang 
1369814e85d6SHong Zhang   if (!ts->adjoint_max_steps) ts->adjoint_max_steps = ts->steps;
1370814e85d6SHong Zhang   if (ts->adjoint_steps >= ts->adjoint_max_steps) ts->reason = TS_CONVERGED_ITS;
1371814e85d6SHong Zhang 
1372814e85d6SHong Zhang   while (!ts->reason) {
1373814e85d6SHong Zhang     ierr = TSTrajectoryGet(ts->trajectory,ts,ts->steps,&ts->ptime);CHKERRQ(ierr);
1374814e85d6SHong Zhang     ierr = TSAdjointMonitor(ts,ts->steps,ts->ptime,ts->vec_sol,ts->numcost,ts->vecs_sensi,ts->vecs_sensip);CHKERRQ(ierr);
1375814e85d6SHong Zhang     ierr = TSAdjointEventHandler(ts);CHKERRQ(ierr);
1376814e85d6SHong Zhang     ierr = TSAdjointStep(ts);CHKERRQ(ierr);
1377814e85d6SHong Zhang     if (ts->vec_costintegral && !ts->costintegralfwd) {
1378814e85d6SHong Zhang       ierr = TSAdjointCostIntegral(ts);CHKERRQ(ierr);
1379814e85d6SHong Zhang     }
1380814e85d6SHong Zhang   }
1381814e85d6SHong Zhang   ierr = TSTrajectoryGet(ts->trajectory,ts,ts->steps,&ts->ptime);CHKERRQ(ierr);
1382814e85d6SHong Zhang   ierr = TSAdjointMonitor(ts,ts->steps,ts->ptime,ts->vec_sol,ts->numcost,ts->vecs_sensi,ts->vecs_sensip);CHKERRQ(ierr);
1383814e85d6SHong Zhang   ts->solvetime = ts->ptime;
1384814e85d6SHong Zhang   ierr = TSTrajectoryViewFromOptions(ts->trajectory,NULL,"-ts_trajectory_view");CHKERRQ(ierr);
1385814e85d6SHong Zhang   ierr = VecViewFromOptions(ts->vecs_sensi[0],(PetscObject) ts, "-ts_adjoint_view_solution");CHKERRQ(ierr);
1386814e85d6SHong Zhang   ts->adjoint_max_steps = 0;
1387814e85d6SHong Zhang   PetscFunctionReturn(0);
1388814e85d6SHong Zhang }
1389814e85d6SHong Zhang 
1390814e85d6SHong Zhang /*@C
1391814e85d6SHong Zhang    TSAdjointMonitor - Runs all user-provided adjoint monitor routines set using TSAdjointMonitorSet()
1392814e85d6SHong Zhang 
1393814e85d6SHong Zhang    Collective on TS
1394814e85d6SHong Zhang 
1395814e85d6SHong Zhang    Input Parameters:
1396814e85d6SHong Zhang +  ts - time stepping context obtained from TSCreate()
1397814e85d6SHong Zhang .  step - step number that has just completed
1398814e85d6SHong Zhang .  ptime - model time of the state
1399814e85d6SHong Zhang .  u - state at the current model time
1400814e85d6SHong Zhang .  numcost - number of cost functions (dimension of lambda  or mu)
1401814e85d6SHong Zhang .  lambda - vectors containing the gradients of the cost functions with respect to the ODE/DAE solution variables
1402814e85d6SHong Zhang -  mu - vectors containing the gradients of the cost functions with respect to the problem parameters
1403814e85d6SHong Zhang 
1404814e85d6SHong Zhang    Notes:
1405814e85d6SHong Zhang    TSAdjointMonitor() is typically used automatically within the time stepping implementations.
1406814e85d6SHong Zhang    Users would almost never call this routine directly.
1407814e85d6SHong Zhang 
1408814e85d6SHong Zhang    Level: developer
1409814e85d6SHong Zhang 
1410814e85d6SHong Zhang .keywords: TS, timestep
1411814e85d6SHong Zhang @*/
1412814e85d6SHong Zhang PetscErrorCode TSAdjointMonitor(TS ts,PetscInt step,PetscReal ptime,Vec u,PetscInt numcost,Vec *lambda, Vec *mu)
1413814e85d6SHong Zhang {
1414814e85d6SHong Zhang   PetscErrorCode ierr;
1415814e85d6SHong Zhang   PetscInt       i,n = ts->numberadjointmonitors;
1416814e85d6SHong Zhang 
1417814e85d6SHong Zhang   PetscFunctionBegin;
1418814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1419814e85d6SHong Zhang   PetscValidHeaderSpecific(u,VEC_CLASSID,4);
14208860a134SJunchao Zhang   ierr = VecLockReadPush(u);CHKERRQ(ierr);
1421814e85d6SHong Zhang   for (i=0; i<n; i++) {
1422814e85d6SHong Zhang     ierr = (*ts->adjointmonitor[i])(ts,step,ptime,u,numcost,lambda,mu,ts->adjointmonitorcontext[i]);CHKERRQ(ierr);
1423814e85d6SHong Zhang   }
14248860a134SJunchao Zhang   ierr = VecLockReadPop(u);CHKERRQ(ierr);
1425814e85d6SHong Zhang   PetscFunctionReturn(0);
1426814e85d6SHong Zhang }
1427814e85d6SHong Zhang 
1428814e85d6SHong Zhang /*@
1429814e85d6SHong Zhang  TSAdjointCostIntegral - Evaluate the cost integral in the adjoint run.
1430814e85d6SHong Zhang 
1431814e85d6SHong Zhang  Collective on TS
1432814e85d6SHong Zhang 
1433814e85d6SHong Zhang  Input Arguments:
1434814e85d6SHong Zhang  .  ts - time stepping context
1435814e85d6SHong Zhang 
1436814e85d6SHong Zhang  Level: advanced
1437814e85d6SHong Zhang 
1438814e85d6SHong Zhang  Notes:
1439814e85d6SHong Zhang  This function cannot be called until TSAdjointStep() has been completed.
1440814e85d6SHong Zhang 
1441814e85d6SHong Zhang  .seealso: TSAdjointSolve(), TSAdjointStep
1442814e85d6SHong Zhang  @*/
1443814e85d6SHong Zhang PetscErrorCode TSAdjointCostIntegral(TS ts)
1444814e85d6SHong Zhang {
1445814e85d6SHong Zhang     PetscErrorCode ierr;
1446814e85d6SHong Zhang     PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1447814e85d6SHong 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);
1448814e85d6SHong Zhang     ierr = (*ts->ops->adjointintegral)(ts);CHKERRQ(ierr);
1449814e85d6SHong Zhang     PetscFunctionReturn(0);
1450814e85d6SHong Zhang }
1451814e85d6SHong Zhang 
1452814e85d6SHong Zhang /* ------------------ Forward (tangent linear) sensitivity  ------------------*/
1453814e85d6SHong Zhang 
1454814e85d6SHong Zhang /*@
1455814e85d6SHong Zhang   TSForwardSetUp - Sets up the internal data structures for the later use
1456814e85d6SHong Zhang   of forward sensitivity analysis
1457814e85d6SHong Zhang 
1458814e85d6SHong Zhang   Collective on TS
1459814e85d6SHong Zhang 
1460814e85d6SHong Zhang   Input Parameter:
1461814e85d6SHong Zhang . ts - the TS context obtained from TSCreate()
1462814e85d6SHong Zhang 
1463814e85d6SHong Zhang   Level: advanced
1464814e85d6SHong Zhang 
1465814e85d6SHong Zhang .keywords: TS, forward sensitivity, setup
1466814e85d6SHong Zhang 
1467814e85d6SHong Zhang .seealso: TSCreate(), TSDestroy(), TSSetUp()
1468814e85d6SHong Zhang @*/
1469814e85d6SHong Zhang PetscErrorCode TSForwardSetUp(TS ts)
1470814e85d6SHong Zhang {
1471814e85d6SHong Zhang   PetscErrorCode ierr;
1472814e85d6SHong Zhang 
1473814e85d6SHong Zhang   PetscFunctionBegin;
1474814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1475814e85d6SHong Zhang   if (ts->forwardsetupcalled) PetscFunctionReturn(0);
1476814e85d6SHong Zhang   if (ts->vec_costintegral && !ts->vecs_integral_sensip ) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call TSForwardSetIntegralGradients() before TSSetCostIntegrand()");
1477814e85d6SHong Zhang   if (ts->vecs_integral_sensip) {
1478c9ad9de0SHong Zhang     ierr = VecDuplicateVecs(ts->vec_sol,ts->numcost,&ts->vecs_drdu);CHKERRQ(ierr);
1479814e85d6SHong Zhang     ierr = VecDuplicateVecs(ts->vecs_integral_sensip[0],ts->numcost,&ts->vecs_drdp);CHKERRQ(ierr);
1480814e85d6SHong Zhang   }
148133f72c5dSHong Zhang   if (!ts->Jacp && ts->Jacprhs) ts->Jacp = ts->Jacprhs;
1482814e85d6SHong Zhang 
1483814e85d6SHong Zhang   if (ts->ops->forwardsetup) {
1484814e85d6SHong Zhang     ierr = (*ts->ops->forwardsetup)(ts);CHKERRQ(ierr);
1485814e85d6SHong Zhang   }
1486814e85d6SHong Zhang   ts->forwardsetupcalled = PETSC_TRUE;
1487814e85d6SHong Zhang   PetscFunctionReturn(0);
1488814e85d6SHong Zhang }
1489814e85d6SHong Zhang 
1490814e85d6SHong Zhang /*@
14917adebddeSHong Zhang   TSForwardReset - Reset the internal data structures used by forward sensitivity analysis
14927adebddeSHong Zhang 
14937adebddeSHong Zhang   Collective on TS
14947adebddeSHong Zhang 
14957adebddeSHong Zhang   Input Parameter:
14967adebddeSHong Zhang . ts - the TS context obtained from TSCreate()
14977adebddeSHong Zhang 
14987adebddeSHong Zhang   Level: advanced
14997adebddeSHong Zhang 
15007adebddeSHong Zhang .keywords: TS, forward sensitivity, reset
15017adebddeSHong Zhang 
15027adebddeSHong Zhang .seealso: TSCreate(), TSDestroy(), TSForwardSetUp()
15037adebddeSHong Zhang @*/
15047adebddeSHong Zhang PetscErrorCode TSForwardReset(TS ts)
15057adebddeSHong Zhang {
15067adebddeSHong Zhang   PetscErrorCode ierr;
15077adebddeSHong Zhang 
15087adebddeSHong Zhang   PetscFunctionBegin;
15097adebddeSHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
15107adebddeSHong Zhang   if (ts->ops->forwardreset) {
15117adebddeSHong Zhang     ierr = (*ts->ops->forwardreset)(ts);CHKERRQ(ierr);
15127adebddeSHong Zhang   }
15137adebddeSHong Zhang   ierr = MatDestroy(&ts->mat_sensip);CHKERRQ(ierr);
15147adebddeSHong Zhang   ts->vecs_integral_sensip = NULL;
15157adebddeSHong Zhang   ts->forward_solve        = PETSC_FALSE;
15167adebddeSHong Zhang   ts->forwardsetupcalled   = PETSC_FALSE;
15177adebddeSHong Zhang   PetscFunctionReturn(0);
15187adebddeSHong Zhang }
15197adebddeSHong Zhang 
15207adebddeSHong Zhang /*@
1521814e85d6SHong Zhang   TSForwardSetIntegralGradients - Set the vectors holding forward sensitivities of the integral term.
1522814e85d6SHong Zhang 
1523814e85d6SHong Zhang   Input Parameter:
1524814e85d6SHong Zhang . ts- the TS context obtained from TSCreate()
1525814e85d6SHong Zhang . numfwdint- number of integrals
1526814e85d6SHong Zhang . vp = the vectors containing the gradients for each integral w.r.t. parameters
1527814e85d6SHong Zhang 
1528814e85d6SHong Zhang   Level: intermediate
1529814e85d6SHong Zhang 
1530814e85d6SHong Zhang .keywords: TS, forward sensitivity
1531814e85d6SHong Zhang 
1532814e85d6SHong Zhang .seealso: TSForwardGetSensitivities(), TSForwardSetIntegralGradients(), TSForwardGetIntegralGradients(), TSForwardStep()
1533814e85d6SHong Zhang @*/
1534814e85d6SHong Zhang PetscErrorCode TSForwardSetIntegralGradients(TS ts,PetscInt numfwdint,Vec *vp)
1535814e85d6SHong Zhang {
1536814e85d6SHong Zhang   PetscFunctionBegin;
1537814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1538814e85d6SHong 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()");
1539814e85d6SHong Zhang   if (!ts->numcost) ts->numcost = numfwdint;
1540814e85d6SHong Zhang 
1541814e85d6SHong Zhang   ts->vecs_integral_sensip = vp;
1542814e85d6SHong Zhang   PetscFunctionReturn(0);
1543814e85d6SHong Zhang }
1544814e85d6SHong Zhang 
1545814e85d6SHong Zhang /*@
1546814e85d6SHong Zhang   TSForwardGetIntegralGradients - Returns the forward sensitivities ofthe integral term.
1547814e85d6SHong Zhang 
1548814e85d6SHong Zhang   Input Parameter:
1549814e85d6SHong Zhang . ts- the TS context obtained from TSCreate()
1550814e85d6SHong Zhang 
1551814e85d6SHong Zhang   Output Parameter:
1552814e85d6SHong Zhang . vp = the vectors containing the gradients for each integral w.r.t. parameters
1553814e85d6SHong Zhang 
1554814e85d6SHong Zhang   Level: intermediate
1555814e85d6SHong Zhang 
1556814e85d6SHong Zhang .keywords: TS, forward sensitivity
1557814e85d6SHong Zhang 
1558814e85d6SHong Zhang .seealso: TSForwardSetSensitivities(), TSForwardSetIntegralGradients(), TSForwardGetIntegralGradients(), TSForwardStep()
1559814e85d6SHong Zhang @*/
1560814e85d6SHong Zhang PetscErrorCode TSForwardGetIntegralGradients(TS ts,PetscInt *numfwdint,Vec **vp)
1561814e85d6SHong Zhang {
1562814e85d6SHong Zhang   PetscFunctionBegin;
1563814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1564814e85d6SHong Zhang   PetscValidPointer(vp,3);
1565814e85d6SHong Zhang   if (numfwdint) *numfwdint = ts->numcost;
1566814e85d6SHong Zhang   if (vp) *vp = ts->vecs_integral_sensip;
1567814e85d6SHong Zhang   PetscFunctionReturn(0);
1568814e85d6SHong Zhang }
1569814e85d6SHong Zhang 
1570814e85d6SHong Zhang /*@
1571814e85d6SHong Zhang   TSForwardStep - Compute the forward sensitivity for one time step.
1572814e85d6SHong Zhang 
1573814e85d6SHong Zhang   Collective on TS
1574814e85d6SHong Zhang 
1575814e85d6SHong Zhang   Input Arguments:
1576814e85d6SHong Zhang . ts - time stepping context
1577814e85d6SHong Zhang 
1578814e85d6SHong Zhang   Level: advanced
1579814e85d6SHong Zhang 
1580814e85d6SHong Zhang   Notes:
1581814e85d6SHong Zhang   This function cannot be called until TSStep() has been completed.
1582814e85d6SHong Zhang 
1583814e85d6SHong Zhang .keywords: TS, forward sensitivity
1584814e85d6SHong Zhang 
1585814e85d6SHong Zhang .seealso: TSForwardSetSensitivities(), TSForwardGetSensitivities(), TSForwardSetIntegralGradients(), TSForwardGetIntegralGradients(), TSForwardSetUp()
1586814e85d6SHong Zhang @*/
1587814e85d6SHong Zhang PetscErrorCode TSForwardStep(TS ts)
1588814e85d6SHong Zhang {
1589814e85d6SHong Zhang   PetscErrorCode ierr;
1590814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1591814e85d6SHong Zhang   if (!ts->ops->forwardstep) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"%s does not provide forward sensitivity analysis",((PetscObject)ts)->type_name);
1592814e85d6SHong Zhang   ierr = PetscLogEventBegin(TS_ForwardStep,ts,0,0,0);CHKERRQ(ierr);
1593814e85d6SHong Zhang   ierr = (*ts->ops->forwardstep)(ts);CHKERRQ(ierr);
1594814e85d6SHong Zhang   ierr = PetscLogEventEnd(TS_ForwardStep,ts,0,0,0);CHKERRQ(ierr);
1595814e85d6SHong Zhang   PetscFunctionReturn(0);
1596814e85d6SHong Zhang }
1597814e85d6SHong Zhang 
1598814e85d6SHong Zhang /*@
1599814e85d6SHong Zhang   TSForwardSetSensitivities - Sets the initial value of the trajectory sensitivities of solution  w.r.t. the problem parameters and initial values.
1600814e85d6SHong Zhang 
1601814e85d6SHong Zhang   Logically Collective on TS and Vec
1602814e85d6SHong Zhang 
1603814e85d6SHong Zhang   Input Parameters:
1604814e85d6SHong Zhang + ts - the TS context obtained from TSCreate()
1605814e85d6SHong Zhang . nump - number of parameters
1606814e85d6SHong Zhang - Smat - sensitivities with respect to the parameters, the number of entries in these vectors is the same as the number of parameters
1607814e85d6SHong Zhang 
1608814e85d6SHong Zhang   Level: beginner
1609814e85d6SHong Zhang 
1610814e85d6SHong Zhang   Notes:
1611814e85d6SHong Zhang   Forward sensitivity is also called 'trajectory sensitivity' in some fields such as power systems.
1612814e85d6SHong Zhang   This function turns on a flag to trigger TSSolve() to compute forward sensitivities automatically.
1613814e85d6SHong Zhang   You must call this function before TSSolve().
1614814e85d6SHong Zhang   The entries in the sensitivity matrix must be correctly initialized with the values S = dy/dp|startingtime.
1615814e85d6SHong Zhang 
1616814e85d6SHong Zhang .keywords: TS, timestep, set, forward sensitivity, initial values
1617814e85d6SHong Zhang 
1618814e85d6SHong Zhang .seealso: TSForwardGetSensitivities(), TSForwardSetIntegralGradients(), TSForwardGetIntegralGradients(), TSForwardStep()
1619814e85d6SHong Zhang @*/
1620814e85d6SHong Zhang PetscErrorCode TSForwardSetSensitivities(TS ts,PetscInt nump,Mat Smat)
1621814e85d6SHong Zhang {
1622814e85d6SHong Zhang   PetscErrorCode ierr;
1623814e85d6SHong Zhang 
1624814e85d6SHong Zhang   PetscFunctionBegin;
1625814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1626814e85d6SHong Zhang   PetscValidHeaderSpecific(Smat,MAT_CLASSID,3);
1627814e85d6SHong Zhang   ts->forward_solve  = PETSC_TRUE;
1628b5b4017aSHong Zhang   if (nump == PETSC_DEFAULT) {
1629b5b4017aSHong Zhang     ierr = MatGetSize(Smat,NULL,&ts->num_parameters);CHKERRQ(ierr);
1630b5b4017aSHong Zhang   } else ts->num_parameters = nump;
1631814e85d6SHong Zhang   ierr = PetscObjectReference((PetscObject)Smat);CHKERRQ(ierr);
1632814e85d6SHong Zhang   ierr = MatDestroy(&ts->mat_sensip);CHKERRQ(ierr);
1633814e85d6SHong Zhang   ts->mat_sensip = Smat;
1634814e85d6SHong Zhang   PetscFunctionReturn(0);
1635814e85d6SHong Zhang }
1636814e85d6SHong Zhang 
1637814e85d6SHong Zhang /*@
1638814e85d6SHong Zhang   TSForwardGetSensitivities - Returns the trajectory sensitivities
1639814e85d6SHong Zhang 
1640814e85d6SHong Zhang   Not Collective, but Vec returned is parallel if TS is parallel
1641814e85d6SHong Zhang 
1642814e85d6SHong Zhang   Output Parameter:
1643814e85d6SHong Zhang + ts - the TS context obtained from TSCreate()
1644814e85d6SHong Zhang . nump - number of parameters
1645814e85d6SHong Zhang - Smat - sensitivities with respect to the parameters, the number of entries in these vectors is the same as the number of parameters
1646814e85d6SHong Zhang 
1647814e85d6SHong Zhang   Level: intermediate
1648814e85d6SHong Zhang 
1649814e85d6SHong Zhang .keywords: TS, forward sensitivity
1650814e85d6SHong Zhang 
1651814e85d6SHong Zhang .seealso: TSForwardSetSensitivities(), TSForwardSetIntegralGradients(), TSForwardGetIntegralGradients(), TSForwardStep()
1652814e85d6SHong Zhang @*/
1653814e85d6SHong Zhang PetscErrorCode TSForwardGetSensitivities(TS ts,PetscInt *nump,Mat *Smat)
1654814e85d6SHong Zhang {
1655814e85d6SHong Zhang   PetscFunctionBegin;
1656814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1657814e85d6SHong Zhang   if (nump) *nump = ts->num_parameters;
1658814e85d6SHong Zhang   if (Smat) *Smat = ts->mat_sensip;
1659814e85d6SHong Zhang   PetscFunctionReturn(0);
1660814e85d6SHong Zhang }
1661814e85d6SHong Zhang 
1662814e85d6SHong Zhang /*@
1663814e85d6SHong Zhang    TSForwardCostIntegral - Evaluate the cost integral in the forward run.
1664814e85d6SHong Zhang 
1665814e85d6SHong Zhang    Collective on TS
1666814e85d6SHong Zhang 
1667814e85d6SHong Zhang    Input Arguments:
1668814e85d6SHong Zhang .  ts - time stepping context
1669814e85d6SHong Zhang 
1670814e85d6SHong Zhang    Level: advanced
1671814e85d6SHong Zhang 
1672814e85d6SHong Zhang    Notes:
1673814e85d6SHong Zhang    This function cannot be called until TSStep() has been completed.
1674814e85d6SHong Zhang 
1675814e85d6SHong Zhang .seealso: TSSolve(), TSAdjointCostIntegral()
1676814e85d6SHong Zhang @*/
1677814e85d6SHong Zhang PetscErrorCode TSForwardCostIntegral(TS ts)
1678814e85d6SHong Zhang {
1679814e85d6SHong Zhang   PetscErrorCode ierr;
1680814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1681814e85d6SHong 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);
1682814e85d6SHong Zhang   ierr = (*ts->ops->forwardintegral)(ts);CHKERRQ(ierr);
1683814e85d6SHong Zhang   PetscFunctionReturn(0);
1684814e85d6SHong Zhang }
1685b5b4017aSHong Zhang 
1686b5b4017aSHong Zhang /*@
1687b5b4017aSHong Zhang   TSForwardSetInitialSensitivities - Set initial values for tangent linear sensitivities
1688b5b4017aSHong Zhang 
1689b5b4017aSHong Zhang   Collective on TS and Mat
1690b5b4017aSHong Zhang 
1691b5b4017aSHong Zhang   Input Parameter
1692b5b4017aSHong Zhang + ts - the TS context obtained from TSCreate()
1693b5b4017aSHong Zhang - didp - parametric sensitivities of the initial condition
1694b5b4017aSHong Zhang 
1695b5b4017aSHong Zhang   Level: intermediate
1696b5b4017aSHong Zhang 
1697b5b4017aSHong 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.
1698b5b4017aSHong Zhang 
1699b5b4017aSHong Zhang .seealso: TSForwardSetSensitivities()
1700b5b4017aSHong Zhang @*/
1701b5b4017aSHong Zhang PetscErrorCode TSForwardSetInitialSensitivities(TS ts,Mat didp)
1702b5b4017aSHong Zhang {
1703b5b4017aSHong Zhang   PetscErrorCode ierr;
1704b5b4017aSHong Zhang 
1705b5b4017aSHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1706b5b4017aSHong Zhang   PetscValidHeaderSpecific(didp,MAT_CLASSID,2);
1707b5b4017aSHong Zhang   if (!ts->mat_sensip) {
1708b5b4017aSHong Zhang     ierr = TSForwardSetSensitivities(ts,PETSC_DEFAULT,didp);CHKERRQ(ierr);
1709b5b4017aSHong Zhang   }
1710b5b4017aSHong Zhang   PetscFunctionReturn(0);
1711b5b4017aSHong Zhang }
17126affb6f8SHong Zhang 
17136affb6f8SHong Zhang /*@
17146affb6f8SHong Zhang    TSForwardGetStages - Get the number of stages and the tangent linear sensitivities at the intermediate stages
17156affb6f8SHong Zhang 
17166affb6f8SHong Zhang    Input Parameter:
17176affb6f8SHong Zhang .  ts - the TS context obtained from TSCreate()
17186affb6f8SHong Zhang 
17196affb6f8SHong Zhang    Output Parameters:
17206affb6f8SHong Zhang +  ns - nu
17216affb6f8SHong Zhang -  S - tangent linear sensitivities at the intermediate stages
17226affb6f8SHong Zhang 
17236affb6f8SHong Zhang    Level: advanced
17246affb6f8SHong Zhang 
17256affb6f8SHong Zhang .keywords: TS, second-order adjoint, forward sensitivity
17266affb6f8SHong Zhang @*/
17276affb6f8SHong Zhang PetscErrorCode TSForwardGetStages(TS ts,PetscInt *ns,Mat **S)
17286affb6f8SHong Zhang {
17296affb6f8SHong Zhang   PetscErrorCode ierr;
17306affb6f8SHong Zhang 
17316affb6f8SHong Zhang   PetscFunctionBegin;
17326affb6f8SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
17336affb6f8SHong Zhang 
17346affb6f8SHong Zhang   if (!ts->ops->getstages) *S=NULL;
17356affb6f8SHong Zhang   else {
17366affb6f8SHong Zhang     ierr = (*ts->ops->forwardgetstages)(ts,ns,S);CHKERRQ(ierr);
17376affb6f8SHong Zhang   }
17386affb6f8SHong Zhang   PetscFunctionReturn(0);
17396affb6f8SHong Zhang }
1740