xref: /petsc/src/ts/interface/sensitivity/tssen.c (revision 487a658c8b32ba712a1dc8280daad2fd70c1dcd9)
1 #include <petsc/private/tsimpl.h>        /*I "petscts.h"  I*/
2 #include <petscdraw.h>
3 
4 PetscLogEvent TS_AdjointStep, TS_ForwardStep;
5 
6 /* ------------------------ Sensitivity Context ---------------------------*/
7 
8 /*@C
9   TSSetRHSJacobianP - Sets the function that computes the Jacobian of G w.r.t. the parameters p where y_t = G(y,p,t), as well as the location to store the matrix.
10 
11   Logically Collective on TS
12 
13   Input Parameters:
14 + ts   - The TS context obtained from TSCreate()
15 - func - The function
16 
17   Calling sequence of func:
18 $ func (TS ts,PetscReal t,Vec y,Mat A,void *ctx);
19 +   t - current timestep
20 .   y - input vector (current ODE solution)
21 .   A - output matrix
22 -   ctx - [optional] user-defined function context
23 
24   Level: intermediate
25 
26   Notes:
27     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
28 
29 .keywords: TS, sensitivity
30 .seealso:
31 @*/
32 PetscErrorCode TSSetRHSJacobianP(TS ts,Mat Amat,PetscErrorCode (*func)(TS,PetscReal,Vec,Mat,void*),void *ctx)
33 {
34   PetscErrorCode ierr;
35 
36   PetscFunctionBegin;
37   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
38   PetscValidHeaderSpecific(Amat,MAT_CLASSID,2);
39 
40   ts->rhsjacobianp    = func;
41   ts->rhsjacobianpctx = ctx;
42   if(Amat) {
43     ierr = PetscObjectReference((PetscObject)Amat);CHKERRQ(ierr);
44     ierr = MatDestroy(&ts->Jacp);CHKERRQ(ierr);
45     ts->Jacp = Amat;
46   }
47   PetscFunctionReturn(0);
48 }
49 
50 /*@C
51   TSComputeRHSJacobianP - Runs the user-defined JacobianP function.
52 
53   Collective on TS
54 
55   Input Parameters:
56 . ts   - The TS context obtained from TSCreate()
57 
58   Level: developer
59 
60 .keywords: TS, sensitivity
61 .seealso: TSSetRHSJacobianP()
62 @*/
63 PetscErrorCode TSComputeRHSJacobianP(TS ts,PetscReal t,Vec X,Mat Amat)
64 {
65   PetscErrorCode ierr;
66 
67   PetscFunctionBegin;
68   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
69   PetscValidHeaderSpecific(X,VEC_CLASSID,3);
70   PetscValidPointer(Amat,4);
71 
72   PetscStackPush("TS user JacobianP function for sensitivity analysis");
73   ierr = (*ts->rhsjacobianp)(ts,t,X,Amat,ts->rhsjacobianpctx); CHKERRQ(ierr);
74   PetscStackPop;
75   PetscFunctionReturn(0);
76 }
77 
78 /*@C
79     TSSetCostIntegrand - Sets the routine for evaluating the integral term in one or more cost functions
80 
81     Logically Collective on TS
82 
83     Input Parameters:
84 +   ts - the TS context obtained from TSCreate()
85 .   numcost - number of gradients to be computed, this is the number of cost functions
86 .   costintegral - vector that stores the integral values
87 .   rf - routine for evaluating the integrand function
88 .   drdyf - function that computes the gradients of the r's with respect to y
89 .   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)
90 .   fwd - flag indicating whether to evaluate cost integral in the forward run or the adjoint run
91 -   ctx - [optional] user-defined context for private data for the function evaluation routine (may be NULL)
92 
93     Calling sequence of rf:
94 $   PetscErrorCode rf(TS ts,PetscReal t,Vec y,Vec f,void *ctx);
95 
96     Calling sequence of drdyf:
97 $   PetscErroCode drdyf(TS ts,PetscReal t,Vec y,Vec *drdy,void *ctx);
98 
99     Calling sequence of drdpf:
100 $   PetscErroCode drdpf(TS ts,PetscReal t,Vec y,Vec *drdp,void *ctx);
101 
102     Level: intermediate
103 
104     Notes:
105     For optimization there is usually a single cost function (numcost = 1). For sensitivities there may be multiple cost functions
106 
107 .keywords: TS, sensitivity analysis, timestep, set, quadrature, function
108 
109 .seealso: TSSetRHSJacobianP(), TSGetCostGradients(), TSSetCostGradients()
110 @*/
111 PetscErrorCode TSSetCostIntegrand(TS ts,PetscInt numcost,Vec costintegral,PetscErrorCode (*rf)(TS,PetscReal,Vec,Vec,void*),
112                                                           PetscErrorCode (*drdyf)(TS,PetscReal,Vec,Vec*,void*),
113                                                           PetscErrorCode (*drdpf)(TS,PetscReal,Vec,Vec*,void*),
114                                                           PetscBool fwd,void *ctx)
115 {
116   PetscErrorCode ierr;
117 
118   PetscFunctionBegin;
119   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
120   if (costintegral) PetscValidHeaderSpecific(costintegral,VEC_CLASSID,3);
121   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()");
122   if (!ts->numcost) ts->numcost=numcost;
123 
124   if (costintegral) {
125     ierr = PetscObjectReference((PetscObject)costintegral);CHKERRQ(ierr);
126     ierr = VecDestroy(&ts->vec_costintegral);CHKERRQ(ierr);
127     ts->vec_costintegral = costintegral;
128   } else {
129     if (!ts->vec_costintegral) { /* Create a seq vec if user does not provide one */
130       ierr = VecCreateSeq(PETSC_COMM_SELF,numcost,&ts->vec_costintegral);CHKERRQ(ierr);
131     } else {
132       ierr = VecSet(ts->vec_costintegral,0.0);CHKERRQ(ierr);
133     }
134   }
135   if (!ts->vec_costintegrand) {
136     ierr = VecDuplicate(ts->vec_costintegral,&ts->vec_costintegrand);CHKERRQ(ierr);
137   } else {
138     ierr = VecSet(ts->vec_costintegrand,0.0);CHKERRQ(ierr);
139   }
140   ts->costintegralfwd  = fwd; /* Evaluate the cost integral in forward run if fwd is true */
141   ts->costintegrand    = rf;
142   ts->costintegrandctx = ctx;
143   ts->drdyfunction     = drdyf;
144   ts->drdpfunction     = drdpf;
145   PetscFunctionReturn(0);
146 }
147 
148 /*@
149    TSGetCostIntegral - Returns the values of the integral term in the cost functions.
150    It is valid to call the routine after a backward run.
151 
152    Not Collective
153 
154    Input Parameter:
155 .  ts - the TS context obtained from TSCreate()
156 
157    Output Parameter:
158 .  v - the vector containing the integrals for each cost function
159 
160    Level: intermediate
161 
162 .seealso: TSSetCostIntegrand()
163 
164 .keywords: TS, sensitivity analysis
165 @*/
166 PetscErrorCode  TSGetCostIntegral(TS ts,Vec *v)
167 {
168   PetscFunctionBegin;
169   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
170   PetscValidPointer(v,2);
171   *v = ts->vec_costintegral;
172   PetscFunctionReturn(0);
173 }
174 
175 /*@
176    TSComputeCostIntegrand - Evaluates the integral function in the cost functions.
177 
178    Input Parameters:
179 +  ts - the TS context
180 .  t - current time
181 -  y - state vector, i.e. current solution
182 
183    Output Parameter:
184 .  q - vector of size numcost to hold the outputs
185 
186    Note:
187    Most users should not need to explicitly call this routine, as it
188    is used internally within the sensitivity analysis context.
189 
190    Level: developer
191 
192 .keywords: TS, compute
193 
194 .seealso: TSSetCostIntegrand()
195 @*/
196 PetscErrorCode TSComputeCostIntegrand(TS ts,PetscReal t,Vec y,Vec q)
197 {
198   PetscErrorCode ierr;
199 
200   PetscFunctionBegin;
201   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
202   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
203   PetscValidHeaderSpecific(q,VEC_CLASSID,4);
204 
205   ierr = PetscLogEventBegin(TS_FunctionEval,ts,y,q,0);CHKERRQ(ierr);
206   if (ts->costintegrand) {
207     PetscStackPush("TS user integrand in the cost function");
208     ierr = (*ts->costintegrand)(ts,t,y,q,ts->costintegrandctx);CHKERRQ(ierr);
209     PetscStackPop;
210   } else {
211     ierr = VecZeroEntries(q);CHKERRQ(ierr);
212   }
213 
214   ierr = PetscLogEventEnd(TS_FunctionEval,ts,y,q,0);CHKERRQ(ierr);
215   PetscFunctionReturn(0);
216 }
217 
218 /*@
219   TSComputeDRDYFunction - Runs the user-defined DRDY function.
220 
221   Collective on TS
222 
223   Input Parameters:
224 . ts   - The TS context obtained from TSCreate()
225 
226   Notes:
227   TSAdjointComputeDRDYFunction() is typically used for sensitivity implementation,
228   so most users would not generally call this routine themselves.
229 
230   Level: developer
231 
232 .keywords: TS, sensitivity
233 .seealso: TSSetCostIntegrand()
234 @*/
235 PetscErrorCode TSComputeDRDYFunction(TS ts,PetscReal t,Vec y,Vec *drdy)
236 {
237   PetscErrorCode ierr;
238 
239   PetscFunctionBegin;
240   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
241   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
242 
243   PetscStackPush("TS user DRDY function for sensitivity analysis");
244   ierr = (*ts->drdyfunction)(ts,t,y,drdy,ts->costintegrandctx); CHKERRQ(ierr);
245   PetscStackPop;
246   PetscFunctionReturn(0);
247 }
248 
249 /*@
250   TSComputeDRDPFunction - Runs the user-defined DRDP function.
251 
252   Collective on TS
253 
254   Input Parameters:
255 . ts   - The TS context obtained from TSCreate()
256 
257   Notes:
258   TSDRDPFunction() is typically used for sensitivity implementation,
259   so most users would not generally call this routine themselves.
260 
261   Level: developer
262 
263 .keywords: TS, sensitivity
264 .seealso: TSSetCostIntegrand()
265 @*/
266 PetscErrorCode TSComputeDRDPFunction(TS ts,PetscReal t,Vec y,Vec *drdp)
267 {
268   PetscErrorCode ierr;
269 
270   PetscFunctionBegin;
271   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
272   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
273 
274   PetscStackPush("TS user DRDP function for sensitivity analysis");
275   ierr = (*ts->drdpfunction)(ts,t,y,drdp,ts->costintegrandctx); CHKERRQ(ierr);
276   PetscStackPop;
277   PetscFunctionReturn(0);
278 }
279 
280 /* --------------------------- Adjoint sensitivity ---------------------------*/
281 
282 /*@
283    TSSetCostGradients - Sets the initial value of the gradients of the cost function w.r.t. initial values and w.r.t. the problem parameters
284       for use by the TSAdjoint routines.
285 
286    Logically Collective on TS and Vec
287 
288    Input Parameters:
289 +  ts - the TS context obtained from TSCreate()
290 .  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
291 -  mu - gradients with respect to the parameters, the number of entries in these vectors is the same as the number of parameters
292 
293    Level: beginner
294 
295    Notes:
296     the entries in these vectors must be correctly initialized with the values lamda_i = df/dy|finaltime  mu_i = df/dp|finaltime
297 
298    After TSAdjointSolve() is called the lamba and the mu contain the computed sensitivities
299 
300 .keywords: TS, timestep, set, sensitivity, initial values
301 @*/
302 PetscErrorCode TSSetCostGradients(TS ts,PetscInt numcost,Vec *lambda,Vec *mu)
303 {
304   PetscFunctionBegin;
305   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
306   PetscValidPointer(lambda,2);
307   ts->vecs_sensi  = lambda;
308   ts->vecs_sensip = mu;
309   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");
310   ts->numcost  = numcost;
311   PetscFunctionReturn(0);
312 }
313 
314 /*@
315    TSGetCostGradients - Returns the gradients from the TSAdjointSolve()
316 
317    Not Collective, but Vec returned is parallel if TS is parallel
318 
319    Input Parameter:
320 .  ts - the TS context obtained from TSCreate()
321 
322    Output Parameter:
323 +  lambda - vectors containing the gradients of the cost functions with respect to the ODE/DAE solution variables
324 -  mu - vectors containing the gradients of the cost functions with respect to the problem parameters
325 
326    Level: intermediate
327 
328 .seealso: TSGetTimeStep()
329 
330 .keywords: TS, timestep, get, sensitivity
331 @*/
332 PetscErrorCode TSGetCostGradients(TS ts,PetscInt *numcost,Vec **lambda,Vec **mu)
333 {
334   PetscFunctionBegin;
335   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
336   if (numcost) *numcost = ts->numcost;
337   if (lambda)  *lambda  = ts->vecs_sensi;
338   if (mu)      *mu      = ts->vecs_sensip;
339   PetscFunctionReturn(0);
340 }
341 
342 /*@
343    TSAdjointSetUp - Sets up the internal data structures for the later use
344    of an adjoint solver
345 
346    Collective on TS
347 
348    Input Parameter:
349 .  ts - the TS context obtained from TSCreate()
350 
351    Level: advanced
352 
353 .keywords: TS, timestep, setup
354 
355 .seealso: TSCreate(), TSAdjointStep(), TSSetCostGradients()
356 @*/
357 PetscErrorCode TSAdjointSetUp(TS ts)
358 {
359   PetscErrorCode ierr;
360 
361   PetscFunctionBegin;
362   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
363   if (ts->adjointsetupcalled) PetscFunctionReturn(0);
364   if (!ts->vecs_sensi) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONGSTATE,"Must call TSSetCostGradients() first");
365   if (ts->vecs_sensip && !ts->Jacp) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONGSTATE,"Must call TSAdjointSetRHSJacobian() first");
366 
367   if (ts->vec_costintegral) { /* if there is integral in the cost function */
368     ierr = VecDuplicateVecs(ts->vecs_sensi[0],ts->numcost,&ts->vecs_drdy);CHKERRQ(ierr);
369     if (ts->vecs_sensip){
370       ierr = VecDuplicateVecs(ts->vecs_sensip[0],ts->numcost,&ts->vecs_drdp);CHKERRQ(ierr);
371     }
372   }
373 
374   if (ts->ops->adjointsetup) {
375     ierr = (*ts->ops->adjointsetup)(ts);CHKERRQ(ierr);
376   }
377   ts->adjointsetupcalled = PETSC_TRUE;
378   PetscFunctionReturn(0);
379 }
380 
381 /*@
382    TSAdjointSetSteps - Sets the number of steps the adjoint solver should take backward in time
383 
384    Logically Collective on TS
385 
386    Input Parameters:
387 +  ts - the TS context obtained from TSCreate()
388 .  steps - number of steps to use
389 
390    Level: intermediate
391 
392    Notes:
393     Normally one does not call this and TSAdjointSolve() integrates back to the original timestep. One can call this
394           so as to integrate back to less than the original timestep
395 
396 .keywords: TS, timestep, set, maximum, iterations
397 
398 .seealso: TSSetExactFinalTime()
399 @*/
400 PetscErrorCode  TSAdjointSetSteps(TS ts,PetscInt steps)
401 {
402   PetscFunctionBegin;
403   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
404   PetscValidLogicalCollectiveInt(ts,steps,2);
405   if (steps < 0) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Cannot step back a negative number of steps");
406   if (steps > ts->steps) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Cannot step back more than the total number of forward steps");
407   ts->adjoint_max_steps = steps;
408   PetscFunctionReturn(0);
409 }
410 
411 /*@C
412   TSAdjointSetRHSJacobian - Deprecated, use TSSetRHSJacobianP()
413 
414   Level: deprecated
415 
416 @*/
417 PetscErrorCode TSAdjointSetRHSJacobian(TS ts,Mat Amat,PetscErrorCode (*func)(TS,PetscReal,Vec,Mat,void*),void *ctx)
418 {
419   PetscErrorCode ierr;
420 
421   PetscFunctionBegin;
422   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
423   PetscValidHeaderSpecific(Amat,MAT_CLASSID,2);
424 
425   ts->rhsjacobianp    = func;
426   ts->rhsjacobianpctx = ctx;
427   if(Amat) {
428     ierr = PetscObjectReference((PetscObject)Amat);CHKERRQ(ierr);
429     ierr = MatDestroy(&ts->Jacp);CHKERRQ(ierr);
430     ts->Jacp = Amat;
431   }
432   PetscFunctionReturn(0);
433 }
434 
435 /*@C
436   TSAdjointComputeRHSJacobian - Deprecated, use TSComputeRHSJacobianP()
437 
438   Level: deprecated
439 
440 @*/
441 PetscErrorCode TSAdjointComputeRHSJacobian(TS ts,PetscReal t,Vec X,Mat Amat)
442 {
443   PetscErrorCode ierr;
444 
445   PetscFunctionBegin;
446   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
447   PetscValidHeaderSpecific(X,VEC_CLASSID,3);
448   PetscValidPointer(Amat,4);
449 
450   PetscStackPush("TS user JacobianP function for sensitivity analysis");
451   ierr = (*ts->rhsjacobianp)(ts,t,X,Amat,ts->rhsjacobianpctx); CHKERRQ(ierr);
452   PetscStackPop;
453   PetscFunctionReturn(0);
454 }
455 
456 /*@
457   TSAdjointComputeDRDYFunction - Deprecated, use TSComputeDRDYFunction()
458 
459   Level: deprecated
460 
461 @*/
462 PetscErrorCode TSAdjointComputeDRDYFunction(TS ts,PetscReal t,Vec y,Vec *drdy)
463 {
464   PetscErrorCode ierr;
465 
466   PetscFunctionBegin;
467   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
468   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
469 
470   PetscStackPush("TS user DRDY function for sensitivity analysis");
471   ierr = (*ts->drdyfunction)(ts,t,y,drdy,ts->costintegrandctx); CHKERRQ(ierr);
472   PetscStackPop;
473   PetscFunctionReturn(0);
474 }
475 
476 /*@
477   TSAdjointComputeDRDPFunction - Deprecated, use TSComputeDRDPFunction()
478 
479   Level: deprecated
480 
481 @*/
482 PetscErrorCode TSAdjointComputeDRDPFunction(TS ts,PetscReal t,Vec y,Vec *drdp)
483 {
484   PetscErrorCode ierr;
485 
486   PetscFunctionBegin;
487   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
488   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
489 
490   PetscStackPush("TS user DRDP function for sensitivity analysis");
491   ierr = (*ts->drdpfunction)(ts,t,y,drdp,ts->costintegrandctx); CHKERRQ(ierr);
492   PetscStackPop;
493   PetscFunctionReturn(0);
494 }
495 
496 /*@C
497    TSAdjointMonitorSensi - monitors the first lambda sensitivity
498 
499    Level: intermediate
500 
501 .keywords: TS, set, monitor
502 
503 .seealso: TSAdjointMonitorSet()
504 @*/
505 PetscErrorCode TSAdjointMonitorSensi(TS ts,PetscInt step,PetscReal ptime,Vec v,PetscInt numcost,Vec *lambda,Vec *mu,PetscViewerAndFormat *vf)
506 {
507   PetscErrorCode ierr;
508   PetscViewer    viewer = vf->viewer;
509 
510   PetscFunctionBegin;
511   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,4);
512   ierr = PetscViewerPushFormat(viewer,vf->format);CHKERRQ(ierr);
513   ierr = VecView(lambda[0],viewer);CHKERRQ(ierr);
514   ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
515   PetscFunctionReturn(0);
516 }
517 
518 /*@C
519    TSAdjointMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user
520 
521    Collective on TS
522 
523    Input Parameters:
524 +  ts - TS object you wish to monitor
525 .  name - the monitor type one is seeking
526 .  help - message indicating what monitoring is done
527 .  manual - manual page for the monitor
528 .  monitor - the monitor function
529 -  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
530 
531    Level: developer
532 
533 .seealso: PetscOptionsGetViewer(), PetscOptionsGetReal(), PetscOptionsHasName(), PetscOptionsGetString(),
534           PetscOptionsGetIntArray(), PetscOptionsGetRealArray(), PetscOptionsBool()
535           PetscOptionsInt(), PetscOptionsString(), PetscOptionsReal(), PetscOptionsBool(),
536           PetscOptionsName(), PetscOptionsBegin(), PetscOptionsEnd(), PetscOptionsHead(),
537           PetscOptionsStringArray(),PetscOptionsRealArray(), PetscOptionsScalar(),
538           PetscOptionsBoolGroupBegin(), PetscOptionsBoolGroup(), PetscOptionsBoolGroupEnd(),
539           PetscOptionsFList(), PetscOptionsEList()
540 @*/
541 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*))
542 {
543   PetscErrorCode    ierr;
544   PetscViewer       viewer;
545   PetscViewerFormat format;
546   PetscBool         flg;
547 
548   PetscFunctionBegin;
549   ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject)ts),((PetscObject)ts)->prefix,name,&viewer,&format,&flg);CHKERRQ(ierr);
550   if (flg) {
551     PetscViewerAndFormat *vf;
552     ierr = PetscViewerAndFormatCreate(viewer,format,&vf);CHKERRQ(ierr);
553     ierr = PetscObjectDereference((PetscObject)viewer);CHKERRQ(ierr);
554     if (monitorsetup) {
555       ierr = (*monitorsetup)(ts,vf);CHKERRQ(ierr);
556     }
557     ierr = TSAdjointMonitorSet(ts,(PetscErrorCode (*)(TS,PetscInt,PetscReal,Vec,PetscInt,Vec*,Vec*,void*))monitor,vf,(PetscErrorCode (*)(void**))PetscViewerAndFormatDestroy);CHKERRQ(ierr);
558   }
559   PetscFunctionReturn(0);
560 }
561 
562 /*@C
563    TSAdjointMonitorSet - Sets an ADDITIONAL function that is to be used at every
564    timestep to display the iteration's  progress.
565 
566    Logically Collective on TS
567 
568    Input Parameters:
569 +  ts - the TS context obtained from TSCreate()
570 .  adjointmonitor - monitoring routine
571 .  adjointmctx - [optional] user-defined context for private data for the
572              monitor routine (use NULL if no context is desired)
573 -  adjointmonitordestroy - [optional] routine that frees monitor context
574           (may be NULL)
575 
576    Calling sequence of monitor:
577 $    int adjointmonitor(TS ts,PetscInt steps,PetscReal time,Vec u,PetscInt numcost,Vec *lambda, Vec *mu,void *adjointmctx)
578 
579 +    ts - the TS context
580 .    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
581                                been interpolated to)
582 .    time - current time
583 .    u - current iterate
584 .    numcost - number of cost functionos
585 .    lambda - sensitivities to initial conditions
586 .    mu - sensitivities to parameters
587 -    adjointmctx - [optional] adjoint monitoring context
588 
589    Notes:
590    This routine adds an additional monitor to the list of monitors that
591    already has been loaded.
592 
593    Fortran Notes:
594     Only a single monitor function can be set for each TS object
595 
596    Level: intermediate
597 
598 .keywords: TS, timestep, set, adjoint, monitor
599 
600 .seealso: TSAdjointMonitorCancel()
601 @*/
602 PetscErrorCode TSAdjointMonitorSet(TS ts,PetscErrorCode (*adjointmonitor)(TS,PetscInt,PetscReal,Vec,PetscInt,Vec*,Vec*,void*),void *adjointmctx,PetscErrorCode (*adjointmdestroy)(void**))
603 {
604   PetscErrorCode ierr;
605   PetscInt       i;
606   PetscBool      identical;
607 
608   PetscFunctionBegin;
609   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
610   for (i=0; i<ts->numbermonitors;i++) {
611     ierr = PetscMonitorCompare((PetscErrorCode (*)(void))adjointmonitor,adjointmctx,adjointmdestroy,(PetscErrorCode (*)(void))ts->adjointmonitor[i],ts->adjointmonitorcontext[i],ts->adjointmonitordestroy[i],&identical);CHKERRQ(ierr);
612     if (identical) PetscFunctionReturn(0);
613   }
614   if (ts->numberadjointmonitors >= MAXTSMONITORS) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Too many adjoint monitors set");
615   ts->adjointmonitor[ts->numberadjointmonitors]          = adjointmonitor;
616   ts->adjointmonitordestroy[ts->numberadjointmonitors]   = adjointmdestroy;
617   ts->adjointmonitorcontext[ts->numberadjointmonitors++] = (void*)adjointmctx;
618   PetscFunctionReturn(0);
619 }
620 
621 /*@C
622    TSAdjointMonitorCancel - Clears all the adjoint monitors that have been set on a time-step object.
623 
624    Logically Collective on TS
625 
626    Input Parameters:
627 .  ts - the TS context obtained from TSCreate()
628 
629    Notes:
630    There is no way to remove a single, specific monitor.
631 
632    Level: intermediate
633 
634 .keywords: TS, timestep, set, adjoint, monitor
635 
636 .seealso: TSAdjointMonitorSet()
637 @*/
638 PetscErrorCode TSAdjointMonitorCancel(TS ts)
639 {
640   PetscErrorCode ierr;
641   PetscInt       i;
642 
643   PetscFunctionBegin;
644   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
645   for (i=0; i<ts->numberadjointmonitors; i++) {
646     if (ts->adjointmonitordestroy[i]) {
647       ierr = (*ts->adjointmonitordestroy[i])(&ts->adjointmonitorcontext[i]);CHKERRQ(ierr);
648     }
649   }
650   ts->numberadjointmonitors = 0;
651   PetscFunctionReturn(0);
652 }
653 
654 /*@C
655    TSAdjointMonitorDefault - the default monitor of adjoint computations
656 
657    Level: intermediate
658 
659 .keywords: TS, set, monitor
660 
661 .seealso: TSAdjointMonitorSet()
662 @*/
663 PetscErrorCode TSAdjointMonitorDefault(TS ts,PetscInt step,PetscReal ptime,Vec v,PetscInt numcost,Vec *lambda,Vec *mu,PetscViewerAndFormat *vf)
664 {
665   PetscErrorCode ierr;
666   PetscViewer    viewer = vf->viewer;
667 
668   PetscFunctionBegin;
669   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,4);
670   ierr = PetscViewerPushFormat(viewer,vf->format);CHKERRQ(ierr);
671   ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)ts)->tablevel);CHKERRQ(ierr);
672   ierr = PetscViewerASCIIPrintf(viewer,"%D TS dt %g time %g%s",step,(double)ts->time_step,(double)ptime,ts->steprollback ? " (r)\n" : "\n");CHKERRQ(ierr);
673   ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)ts)->tablevel);CHKERRQ(ierr);
674   ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
675   PetscFunctionReturn(0);
676 }
677 
678 /*@C
679    TSAdjointMonitorDrawSensi - Monitors progress of the adjoint TS solvers by calling
680    VecView() for the sensitivities to initial states at each timestep
681 
682    Collective on TS
683 
684    Input Parameters:
685 +  ts - the TS context
686 .  step - current time-step
687 .  ptime - current time
688 .  u - current state
689 .  numcost - number of cost functions
690 .  lambda - sensitivities to initial conditions
691 .  mu - sensitivities to parameters
692 -  dummy - either a viewer or NULL
693 
694    Level: intermediate
695 
696 .keywords: TS,  vector, adjoint, monitor, view
697 
698 .seealso: TSAdjointMonitorSet(), TSAdjointMonitorDefault(), VecView()
699 @*/
700 PetscErrorCode TSAdjointMonitorDrawSensi(TS ts,PetscInt step,PetscReal ptime,Vec u,PetscInt numcost,Vec *lambda,Vec *mu,void *dummy)
701 {
702   PetscErrorCode   ierr;
703   TSMonitorDrawCtx ictx = (TSMonitorDrawCtx)dummy;
704   PetscDraw        draw;
705   PetscReal        xl,yl,xr,yr,h;
706   char             time[32];
707 
708   PetscFunctionBegin;
709   if (!(((ictx->howoften > 0) && (!(step % ictx->howoften))) || ((ictx->howoften == -1) && ts->reason))) PetscFunctionReturn(0);
710 
711   ierr = VecView(lambda[0],ictx->viewer);CHKERRQ(ierr);
712   ierr = PetscViewerDrawGetDraw(ictx->viewer,0,&draw);CHKERRQ(ierr);
713   ierr = PetscSNPrintf(time,32,"Timestep %d Time %g",(int)step,(double)ptime);CHKERRQ(ierr);
714   ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
715   h    = yl + .95*(yr - yl);
716   ierr = PetscDrawStringCentered(draw,.5*(xl+xr),h,PETSC_DRAW_BLACK,time);CHKERRQ(ierr);
717   ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
718   PetscFunctionReturn(0);
719 }
720 
721 /*
722    TSAdjointSetFromOptions - Sets various TSAdjoint parameters from user options.
723 
724    Collective on TSAdjoint
725 
726    Input Parameter:
727 .  ts - the TS context
728 
729    Options Database Keys:
730 +  -ts_adjoint_solve <yes,no> After solving the ODE/DAE solve the adjoint problem (requires -ts_save_trajectory)
731 .  -ts_adjoint_monitor - print information at each adjoint time step
732 -  -ts_adjoint_monitor_draw_sensi - monitor the sensitivity of the first cost function wrt initial conditions (lambda[0]) graphically
733 
734    Level: developer
735 
736    Notes:
737     This is not normally called directly by users
738 
739 .keywords: TS, trajectory, timestep, set, options, database
740 
741 .seealso: TSSetSaveTrajectory(), TSTrajectorySetUp()
742 */
743 PetscErrorCode TSAdjointSetFromOptions(PetscOptionItems *PetscOptionsObject,TS ts)
744 {
745   PetscBool      tflg,opt;
746   PetscErrorCode ierr;
747 
748   PetscFunctionBegin;
749   PetscValidHeaderSpecific(ts,TS_CLASSID,2);
750   ierr = PetscOptionsHead(PetscOptionsObject,"TS Adjoint options");CHKERRQ(ierr);
751   tflg = ts->adjoint_solve ? PETSC_TRUE : PETSC_FALSE;
752   ierr = PetscOptionsBool("-ts_adjoint_solve","Solve the adjoint problem immediately after solving the forward problem","",tflg,&tflg,&opt);CHKERRQ(ierr);
753   if (opt) {
754     ierr = TSSetSaveTrajectory(ts);CHKERRQ(ierr);
755     ts->adjoint_solve = tflg;
756   }
757   ierr = TSAdjointMonitorSetFromOptions(ts,"-ts_adjoint_monitor","Monitor adjoint timestep size","TSAdjointMonitorDefault",TSAdjointMonitorDefault,NULL);CHKERRQ(ierr);
758   ierr = TSAdjointMonitorSetFromOptions(ts,"-ts_adjoint_monitor_sensi","Monitor sensitivity in the adjoint computation","TSAdjointMonitorSensi",TSAdjointMonitorSensi,NULL);CHKERRQ(ierr);
759   opt  = PETSC_FALSE;
760   ierr = PetscOptionsName("-ts_adjoint_monitor_draw_sensi","Monitor adjoint sensitivities (lambda only) graphically","TSAdjointMonitorDrawSensi",&opt);CHKERRQ(ierr);
761   if (opt) {
762     TSMonitorDrawCtx ctx;
763     PetscInt         howoften = 1;
764 
765     ierr = PetscOptionsInt("-ts_adjoint_monitor_draw_sensi","Monitor adjoint sensitivities (lambda only) graphically","TSAdjointMonitorDrawSensi",howoften,&howoften,NULL);CHKERRQ(ierr);
766     ierr = TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts),0,0,PETSC_DECIDE,PETSC_DECIDE,300,300,howoften,&ctx);CHKERRQ(ierr);
767     ierr = TSAdjointMonitorSet(ts,TSAdjointMonitorDrawSensi,ctx,(PetscErrorCode (*)(void**))TSMonitorDrawCtxDestroy);CHKERRQ(ierr);
768   }
769   PetscFunctionReturn(0);
770 }
771 
772 /*@
773    TSAdjointStep - Steps one time step backward in the adjoint run
774 
775    Collective on TS
776 
777    Input Parameter:
778 .  ts - the TS context obtained from TSCreate()
779 
780    Level: intermediate
781 
782 .keywords: TS, adjoint, step
783 
784 .seealso: TSAdjointSetUp(), TSAdjointSolve()
785 @*/
786 PetscErrorCode TSAdjointStep(TS ts)
787 {
788   DM               dm;
789   PetscErrorCode   ierr;
790 
791   PetscFunctionBegin;
792   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
793   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
794   ierr = TSAdjointSetUp(ts);CHKERRQ(ierr);
795 
796   ierr = VecViewFromOptions(ts->vec_sol,(PetscObject)ts,"-ts_view_solution");CHKERRQ(ierr);
797 
798   ts->reason = TS_CONVERGED_ITERATING;
799   ts->ptime_prev = ts->ptime;
800   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);
801   ierr = PetscLogEventBegin(TS_AdjointStep,ts,0,0,0);CHKERRQ(ierr);
802   ierr = (*ts->ops->adjointstep)(ts);CHKERRQ(ierr);
803   ierr = PetscLogEventEnd(TS_AdjointStep,ts,0,0,0);CHKERRQ(ierr);
804   ts->adjoint_steps++; ts->steps--;
805 
806   if (ts->reason < 0) {
807     if (ts->errorifstepfailed) {
808       if (ts->reason == TS_DIVERGED_NONLINEAR_SOLVE) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_NOT_CONVERGED,"TSStep has failed due to %s, increase -ts_max_snes_failures or make negative to attempt recovery",TSConvergedReasons[ts->reason]);
809       else if (ts->reason == TS_DIVERGED_STEP_REJECTED) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_NOT_CONVERGED,"TSStep has failed due to %s, increase -ts_max_reject or make negative to attempt recovery",TSConvergedReasons[ts->reason]);
810       else SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_NOT_CONVERGED,"TSStep has failed due to %s",TSConvergedReasons[ts->reason]);
811     }
812   } else if (!ts->reason) {
813     if (ts->adjoint_steps >= ts->adjoint_max_steps) ts->reason = TS_CONVERGED_ITS;
814   }
815   PetscFunctionReturn(0);
816 }
817 
818 /*@
819    TSAdjointSolve - Solves the discrete ajoint problem for an ODE/DAE
820 
821    Collective on TS
822 
823    Input Parameter:
824 .  ts - the TS context obtained from TSCreate()
825 
826    Options Database:
827 . -ts_adjoint_view_solution <viewerinfo> - views the first gradient with respect to the initial values
828 
829    Level: intermediate
830 
831    Notes:
832    This must be called after a call to TSSolve() that solves the forward problem
833 
834    By default this will integrate back to the initial time, one can use TSAdjointSetSteps() to step back to a later time
835 
836 .keywords: TS, timestep, solve
837 
838 .seealso: TSCreate(), TSSetCostGradients(), TSSetSolution(), TSAdjointStep()
839 @*/
840 PetscErrorCode TSAdjointSolve(TS ts)
841 {
842   PetscErrorCode    ierr;
843 
844   PetscFunctionBegin;
845   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
846   ierr = TSAdjointSetUp(ts);CHKERRQ(ierr);
847 
848   /* reset time step and iteration counters */
849   ts->adjoint_steps     = 0;
850   ts->ksp_its           = 0;
851   ts->snes_its          = 0;
852   ts->num_snes_failures = 0;
853   ts->reject            = 0;
854   ts->reason            = TS_CONVERGED_ITERATING;
855 
856   if (!ts->adjoint_max_steps) ts->adjoint_max_steps = ts->steps;
857   if (ts->adjoint_steps >= ts->adjoint_max_steps) ts->reason = TS_CONVERGED_ITS;
858 
859   while (!ts->reason) {
860     ierr = TSTrajectoryGet(ts->trajectory,ts,ts->steps,&ts->ptime);CHKERRQ(ierr);
861     ierr = TSAdjointMonitor(ts,ts->steps,ts->ptime,ts->vec_sol,ts->numcost,ts->vecs_sensi,ts->vecs_sensip);CHKERRQ(ierr);
862     ierr = TSAdjointEventHandler(ts);CHKERRQ(ierr);
863     ierr = TSAdjointStep(ts);CHKERRQ(ierr);
864     if (ts->vec_costintegral && !ts->costintegralfwd) {
865       ierr = TSAdjointCostIntegral(ts);CHKERRQ(ierr);
866     }
867   }
868   ierr = TSTrajectoryGet(ts->trajectory,ts,ts->steps,&ts->ptime);CHKERRQ(ierr);
869   ierr = TSAdjointMonitor(ts,ts->steps,ts->ptime,ts->vec_sol,ts->numcost,ts->vecs_sensi,ts->vecs_sensip);CHKERRQ(ierr);
870   ts->solvetime = ts->ptime;
871   ierr = TSTrajectoryViewFromOptions(ts->trajectory,NULL,"-ts_trajectory_view");CHKERRQ(ierr);
872   ierr = VecViewFromOptions(ts->vecs_sensi[0],(PetscObject) ts, "-ts_adjoint_view_solution");CHKERRQ(ierr);
873   ts->adjoint_max_steps = 0;
874   PetscFunctionReturn(0);
875 }
876 
877 /*@C
878    TSAdjointMonitor - Runs all user-provided adjoint monitor routines set using TSAdjointMonitorSet()
879 
880    Collective on TS
881 
882    Input Parameters:
883 +  ts - time stepping context obtained from TSCreate()
884 .  step - step number that has just completed
885 .  ptime - model time of the state
886 .  u - state at the current model time
887 .  numcost - number of cost functions (dimension of lambda  or mu)
888 .  lambda - vectors containing the gradients of the cost functions with respect to the ODE/DAE solution variables
889 -  mu - vectors containing the gradients of the cost functions with respect to the problem parameters
890 
891    Notes:
892    TSAdjointMonitor() is typically used automatically within the time stepping implementations.
893    Users would almost never call this routine directly.
894 
895    Level: developer
896 
897 .keywords: TS, timestep
898 @*/
899 PetscErrorCode TSAdjointMonitor(TS ts,PetscInt step,PetscReal ptime,Vec u,PetscInt numcost,Vec *lambda, Vec *mu)
900 {
901   PetscErrorCode ierr;
902   PetscInt       i,n = ts->numberadjointmonitors;
903 
904   PetscFunctionBegin;
905   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
906   PetscValidHeaderSpecific(u,VEC_CLASSID,4);
907   ierr = VecLockPush(u);CHKERRQ(ierr);
908   for (i=0; i<n; i++) {
909     ierr = (*ts->adjointmonitor[i])(ts,step,ptime,u,numcost,lambda,mu,ts->adjointmonitorcontext[i]);CHKERRQ(ierr);
910   }
911   ierr = VecLockPop(u);CHKERRQ(ierr);
912   PetscFunctionReturn(0);
913 }
914 
915 /*@
916  TSAdjointCostIntegral - Evaluate the cost integral in the adjoint run.
917 
918  Collective on TS
919 
920  Input Arguments:
921  .  ts - time stepping context
922 
923  Level: advanced
924 
925  Notes:
926  This function cannot be called until TSAdjointStep() has been completed.
927 
928  .seealso: TSAdjointSolve(), TSAdjointStep
929  @*/
930 PetscErrorCode TSAdjointCostIntegral(TS ts)
931 {
932     PetscErrorCode ierr;
933     PetscValidHeaderSpecific(ts,TS_CLASSID,1);
934     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);
935     ierr = (*ts->ops->adjointintegral)(ts);CHKERRQ(ierr);
936     PetscFunctionReturn(0);
937 }
938 
939 /* ------------------ Forward (tangent linear) sensitivity  ------------------*/
940 
941 /*@
942   TSForwardSetUp - Sets up the internal data structures for the later use
943   of forward sensitivity analysis
944 
945   Collective on TS
946 
947   Input Parameter:
948 . ts - the TS context obtained from TSCreate()
949 
950   Level: advanced
951 
952 .keywords: TS, forward sensitivity, setup
953 
954 .seealso: TSCreate(), TSDestroy(), TSSetUp()
955 @*/
956 PetscErrorCode TSForwardSetUp(TS ts)
957 {
958   PetscErrorCode ierr;
959 
960   PetscFunctionBegin;
961   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
962   if (ts->forwardsetupcalled) PetscFunctionReturn(0);
963   if (ts->vec_costintegral && !ts->vecs_integral_sensip ) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call TSForwardSetIntegralGradients() before TSSetCostIntegrand()");
964   if (ts->vecs_integral_sensip) {
965     ierr = VecDuplicateVecs(ts->vec_sol,ts->numcost,&ts->vecs_drdy);CHKERRQ(ierr);
966     ierr = VecDuplicateVecs(ts->vecs_integral_sensip[0],ts->numcost,&ts->vecs_drdp);CHKERRQ(ierr);
967   }
968 
969   if (ts->ops->forwardsetup) {
970     ierr = (*ts->ops->forwardsetup)(ts);CHKERRQ(ierr);
971   }
972   ts->forwardsetupcalled = PETSC_TRUE;
973   PetscFunctionReturn(0);
974 }
975 
976 /*@
977   TSForwardSetIntegralGradients - Set the vectors holding forward sensitivities of the integral term.
978 
979   Input Parameter:
980 . ts- the TS context obtained from TSCreate()
981 . numfwdint- number of integrals
982 . vp = the vectors containing the gradients for each integral w.r.t. parameters
983 
984   Level: intermediate
985 
986 .keywords: TS, forward sensitivity
987 
988 .seealso: TSForwardGetSensitivities(), TSForwardSetIntegralGradients(), TSForwardGetIntegralGradients(), TSForwardStep()
989 @*/
990 PetscErrorCode TSForwardSetIntegralGradients(TS ts,PetscInt numfwdint,Vec *vp)
991 {
992   PetscFunctionBegin;
993   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
994   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()");
995   if (!ts->numcost) ts->numcost = numfwdint;
996 
997   ts->vecs_integral_sensip = vp;
998   PetscFunctionReturn(0);
999 }
1000 
1001 /*@
1002   TSForwardGetIntegralGradients - Returns the forward sensitivities ofthe integral term.
1003 
1004   Input Parameter:
1005 . ts- the TS context obtained from TSCreate()
1006 
1007   Output Parameter:
1008 . vp = the vectors containing the gradients for each integral w.r.t. parameters
1009 
1010   Level: intermediate
1011 
1012 .keywords: TS, forward sensitivity
1013 
1014 .seealso: TSForwardSetSensitivities(), TSForwardSetIntegralGradients(), TSForwardGetIntegralGradients(), TSForwardStep()
1015 @*/
1016 PetscErrorCode TSForwardGetIntegralGradients(TS ts,PetscInt *numfwdint,Vec **vp)
1017 {
1018   PetscFunctionBegin;
1019   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1020   PetscValidPointer(vp,3);
1021   if (numfwdint) *numfwdint = ts->numcost;
1022   if (vp) *vp = ts->vecs_integral_sensip;
1023   PetscFunctionReturn(0);
1024 }
1025 
1026 /*@
1027   TSForwardStep - Compute the forward sensitivity for one time step.
1028 
1029   Collective on TS
1030 
1031   Input Arguments:
1032 . ts - time stepping context
1033 
1034   Level: advanced
1035 
1036   Notes:
1037   This function cannot be called until TSStep() has been completed.
1038 
1039 .keywords: TS, forward sensitivity
1040 
1041 .seealso: TSForwardSetSensitivities(), TSForwardGetSensitivities(), TSForwardSetIntegralGradients(), TSForwardGetIntegralGradients(), TSForwardSetUp()
1042 @*/
1043 PetscErrorCode TSForwardStep(TS ts)
1044 {
1045   PetscErrorCode ierr;
1046   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1047   if (!ts->ops->forwardstep) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"%s does not provide forward sensitivity analysis",((PetscObject)ts)->type_name);
1048   ierr = PetscLogEventBegin(TS_ForwardStep,ts,0,0,0);CHKERRQ(ierr);
1049   ierr = (*ts->ops->forwardstep)(ts);CHKERRQ(ierr);
1050   ierr = PetscLogEventEnd(TS_ForwardStep,ts,0,0,0);CHKERRQ(ierr);
1051   PetscFunctionReturn(0);
1052 }
1053 
1054 /*@
1055   TSForwardSetSensitivities - Sets the initial value of the trajectory sensitivities of solution  w.r.t. the problem parameters and initial values.
1056 
1057   Logically Collective on TS and Vec
1058 
1059   Input Parameters:
1060 + ts - the TS context obtained from TSCreate()
1061 . nump - number of parameters
1062 - Smat - sensitivities with respect to the parameters, the number of entries in these vectors is the same as the number of parameters
1063 
1064   Level: beginner
1065 
1066   Notes:
1067   Forward sensitivity is also called 'trajectory sensitivity' in some fields such as power systems.
1068   This function turns on a flag to trigger TSSolve() to compute forward sensitivities automatically.
1069   You must call this function before TSSolve().
1070   The entries in the sensitivity matrix must be correctly initialized with the values S = dy/dp|startingtime.
1071 
1072 .keywords: TS, timestep, set, forward sensitivity, initial values
1073 
1074 .seealso: TSForwardGetSensitivities(), TSForwardSetIntegralGradients(), TSForwardGetIntegralGradients(), TSForwardStep()
1075 @*/
1076 PetscErrorCode TSForwardSetSensitivities(TS ts,PetscInt nump,Mat Smat)
1077 {
1078   PetscErrorCode ierr;
1079 
1080   PetscFunctionBegin;
1081   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1082   PetscValidHeaderSpecific(Smat,MAT_CLASSID,3);
1083   ts->forward_solve  = PETSC_TRUE;
1084   ts->num_parameters = nump;
1085   ierr = PetscObjectReference((PetscObject)Smat);CHKERRQ(ierr);
1086   ierr = MatDestroy(&ts->mat_sensip);CHKERRQ(ierr);
1087   ts->mat_sensip = Smat;
1088   PetscFunctionReturn(0);
1089 }
1090 
1091 /*@
1092   TSForwardGetSensitivities - Returns the trajectory sensitivities
1093 
1094   Not Collective, but Vec returned is parallel if TS is parallel
1095 
1096   Output Parameter:
1097 + ts - the TS context obtained from TSCreate()
1098 . nump - number of parameters
1099 - Smat - sensitivities with respect to the parameters, the number of entries in these vectors is the same as the number of parameters
1100 
1101   Level: intermediate
1102 
1103 .keywords: TS, forward sensitivity
1104 
1105 .seealso: TSForwardSetSensitivities(), TSForwardSetIntegralGradients(), TSForwardGetIntegralGradients(), TSForwardStep()
1106 @*/
1107 PetscErrorCode TSForwardGetSensitivities(TS ts,PetscInt *nump,Mat *Smat)
1108 {
1109   PetscFunctionBegin;
1110   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1111   if (nump) *nump = ts->num_parameters;
1112   if (Smat) *Smat = ts->mat_sensip;
1113   PetscFunctionReturn(0);
1114 }
1115 
1116 /*@
1117    TSForwardCostIntegral - Evaluate the cost integral in the forward run.
1118 
1119    Collective on TS
1120 
1121    Input Arguments:
1122 .  ts - time stepping context
1123 
1124    Level: advanced
1125 
1126    Notes:
1127    This function cannot be called until TSStep() has been completed.
1128 
1129 .seealso: TSSolve(), TSAdjointCostIntegral()
1130 @*/
1131 PetscErrorCode TSForwardCostIntegral(TS ts)
1132 {
1133   PetscErrorCode ierr;
1134   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1135   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);
1136   ierr = (*ts->ops->forwardintegral)(ts);CHKERRQ(ierr);
1137   PetscFunctionReturn(0);
1138 }
1139