xref: /petsc/src/ts/interface/sensitivity/tssen.c (revision dbbe0bcd3f3a8fbab5a45420dc06f8387e5764c6)
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 
67f59fb53SHong Zhang /* #define TSADJOINT_STAGE */
77f59fb53SHong Zhang 
8814e85d6SHong Zhang /* ------------------------ Sensitivity Context ---------------------------*/
9814e85d6SHong Zhang 
10814e85d6SHong Zhang /*@C
11b5b4017aSHong 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.
12814e85d6SHong Zhang 
13814e85d6SHong Zhang   Logically Collective on TS
14814e85d6SHong Zhang 
15814e85d6SHong Zhang   Input Parameters:
16b5b4017aSHong Zhang + ts - TS context obtained from TSCreate()
17b5b4017aSHong Zhang . Amat - JacobianP matrix
18b5b4017aSHong Zhang . func - function
19b5b4017aSHong Zhang - ctx - [optional] user-defined function context
20814e85d6SHong Zhang 
21814e85d6SHong Zhang   Calling sequence of func:
22814e85d6SHong Zhang $ func (TS ts,PetscReal t,Vec y,Mat A,void *ctx);
23814e85d6SHong Zhang +   t - current timestep
24c9ad9de0SHong Zhang .   U - input vector (current ODE solution)
25814e85d6SHong Zhang .   A - output matrix
26814e85d6SHong Zhang -   ctx - [optional] user-defined function context
27814e85d6SHong Zhang 
28814e85d6SHong Zhang   Level: intermediate
29814e85d6SHong Zhang 
30814e85d6SHong Zhang   Notes:
31814e85d6SHong 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
32814e85d6SHong Zhang 
33db781477SPatrick Sanan .seealso: `TSGetRHSJacobianP()`
34814e85d6SHong Zhang @*/
35814e85d6SHong Zhang PetscErrorCode TSSetRHSJacobianP(TS ts,Mat Amat,PetscErrorCode (*func)(TS,PetscReal,Vec,Mat,void*),void *ctx)
36814e85d6SHong Zhang {
37814e85d6SHong Zhang   PetscFunctionBegin;
38814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
39814e85d6SHong Zhang   PetscValidHeaderSpecific(Amat,MAT_CLASSID,2);
40814e85d6SHong Zhang 
41814e85d6SHong Zhang   ts->rhsjacobianp    = func;
42814e85d6SHong Zhang   ts->rhsjacobianpctx = ctx;
43814e85d6SHong Zhang   if (Amat) {
449566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)Amat));
459566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&ts->Jacprhs));
4633f72c5dSHong Zhang     ts->Jacprhs = Amat;
47814e85d6SHong Zhang   }
48814e85d6SHong Zhang   PetscFunctionReturn(0);
49814e85d6SHong Zhang }
50814e85d6SHong Zhang 
51814e85d6SHong Zhang /*@C
52cd4cee2dSHong Zhang   TSGetRHSJacobianP - Gets 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.
53cd4cee2dSHong Zhang 
54cd4cee2dSHong Zhang   Logically Collective on TS
55cd4cee2dSHong Zhang 
56f899ff85SJose E. Roman   Input Parameter:
57cd4cee2dSHong Zhang . ts - TS context obtained from TSCreate()
58cd4cee2dSHong Zhang 
59cd4cee2dSHong Zhang   Output Parameters:
60cd4cee2dSHong Zhang + Amat - JacobianP matrix
61cd4cee2dSHong Zhang . func - function
62cd4cee2dSHong Zhang - ctx - [optional] user-defined function context
63cd4cee2dSHong Zhang 
64cd4cee2dSHong Zhang   Calling sequence of func:
65cd4cee2dSHong Zhang $ func (TS ts,PetscReal t,Vec y,Mat A,void *ctx);
66cd4cee2dSHong Zhang +   t - current timestep
67cd4cee2dSHong Zhang .   U - input vector (current ODE solution)
68cd4cee2dSHong Zhang .   A - output matrix
69cd4cee2dSHong Zhang -   ctx - [optional] user-defined function context
70cd4cee2dSHong Zhang 
71cd4cee2dSHong Zhang   Level: intermediate
72cd4cee2dSHong Zhang 
73cd4cee2dSHong Zhang   Notes:
74cd4cee2dSHong 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
75cd4cee2dSHong Zhang 
76db781477SPatrick Sanan .seealso: `TSSetRHSJacobianP()`
77cd4cee2dSHong Zhang @*/
78cd4cee2dSHong Zhang PetscErrorCode TSGetRHSJacobianP(TS ts,Mat *Amat,PetscErrorCode (**func)(TS,PetscReal,Vec,Mat,void*),void **ctx)
79cd4cee2dSHong Zhang {
80cd4cee2dSHong Zhang   PetscFunctionBegin;
81cd4cee2dSHong Zhang   if (func) *func = ts->rhsjacobianp;
82cd4cee2dSHong Zhang   if (ctx) *ctx  = ts->rhsjacobianpctx;
83cd4cee2dSHong Zhang   if (Amat) *Amat = ts->Jacprhs;
84cd4cee2dSHong Zhang   PetscFunctionReturn(0);
85cd4cee2dSHong Zhang }
86cd4cee2dSHong Zhang 
87cd4cee2dSHong Zhang /*@C
88814e85d6SHong Zhang   TSComputeRHSJacobianP - Runs the user-defined JacobianP function.
89814e85d6SHong Zhang 
90814e85d6SHong Zhang   Collective on TS
91814e85d6SHong Zhang 
92814e85d6SHong Zhang   Input Parameters:
93814e85d6SHong Zhang . ts   - The TS context obtained from TSCreate()
94814e85d6SHong Zhang 
95814e85d6SHong Zhang   Level: developer
96814e85d6SHong Zhang 
97db781477SPatrick Sanan .seealso: `TSSetRHSJacobianP()`
98814e85d6SHong Zhang @*/
99c9ad9de0SHong Zhang PetscErrorCode TSComputeRHSJacobianP(TS ts,PetscReal t,Vec U,Mat Amat)
100814e85d6SHong Zhang {
101814e85d6SHong Zhang   PetscFunctionBegin;
10233f72c5dSHong Zhang   if (!Amat) PetscFunctionReturn(0);
103814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
104c9ad9de0SHong Zhang   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
105814e85d6SHong Zhang 
106792fecdfSBarry Smith   PetscCallBack("TS callback JacobianP for sensitivity analysis",(*ts->rhsjacobianp)(ts,t,U,Amat,ts->rhsjacobianpctx));
107814e85d6SHong Zhang   PetscFunctionReturn(0);
108814e85d6SHong Zhang }
109814e85d6SHong Zhang 
110814e85d6SHong Zhang /*@C
11133f72c5dSHong 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.
11233f72c5dSHong Zhang 
11333f72c5dSHong Zhang   Logically Collective on TS
11433f72c5dSHong Zhang 
11533f72c5dSHong Zhang   Input Parameters:
11633f72c5dSHong Zhang + ts - TS context obtained from TSCreate()
11733f72c5dSHong Zhang . Amat - JacobianP matrix
11833f72c5dSHong Zhang . func - function
11933f72c5dSHong Zhang - ctx - [optional] user-defined function context
12033f72c5dSHong Zhang 
12133f72c5dSHong Zhang   Calling sequence of func:
12233f72c5dSHong Zhang $ func (TS ts,PetscReal t,Vec y,Mat A,void *ctx);
12333f72c5dSHong Zhang +   t - current timestep
12433f72c5dSHong Zhang .   U - input vector (current ODE solution)
12533f72c5dSHong Zhang .   Udot - time derivative of state vector
12633f72c5dSHong Zhang .   shift - shift to apply, see note below
12733f72c5dSHong Zhang .   A - output matrix
12833f72c5dSHong Zhang -   ctx - [optional] user-defined function context
12933f72c5dSHong Zhang 
13033f72c5dSHong Zhang   Level: intermediate
13133f72c5dSHong Zhang 
13233f72c5dSHong Zhang   Notes:
13333f72c5dSHong 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
13433f72c5dSHong Zhang 
13533f72c5dSHong Zhang .seealso:
13633f72c5dSHong Zhang @*/
13733f72c5dSHong Zhang PetscErrorCode TSSetIJacobianP(TS ts,Mat Amat,PetscErrorCode (*func)(TS,PetscReal,Vec,Vec,PetscReal,Mat,void*),void *ctx)
13833f72c5dSHong Zhang {
13933f72c5dSHong Zhang   PetscFunctionBegin;
14033f72c5dSHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
14133f72c5dSHong Zhang   PetscValidHeaderSpecific(Amat,MAT_CLASSID,2);
14233f72c5dSHong Zhang 
14333f72c5dSHong Zhang   ts->ijacobianp    = func;
14433f72c5dSHong Zhang   ts->ijacobianpctx = ctx;
14533f72c5dSHong Zhang   if (Amat) {
1469566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)Amat));
1479566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&ts->Jacp));
14833f72c5dSHong Zhang     ts->Jacp = Amat;
14933f72c5dSHong Zhang   }
15033f72c5dSHong Zhang   PetscFunctionReturn(0);
15133f72c5dSHong Zhang }
15233f72c5dSHong Zhang 
15333f72c5dSHong Zhang /*@C
15433f72c5dSHong Zhang   TSComputeIJacobianP - Runs the user-defined IJacobianP function.
15533f72c5dSHong Zhang 
15633f72c5dSHong Zhang   Collective on TS
15733f72c5dSHong Zhang 
15833f72c5dSHong Zhang   Input Parameters:
15933f72c5dSHong Zhang + ts - the TS context
16033f72c5dSHong Zhang . t - current timestep
16133f72c5dSHong Zhang . U - state vector
16233f72c5dSHong Zhang . Udot - time derivative of state vector
16333f72c5dSHong Zhang . shift - shift to apply, see note below
16433f72c5dSHong Zhang - imex - flag indicates if the method is IMEX so that the RHSJacobian should be kept separate
16533f72c5dSHong Zhang 
16633f72c5dSHong Zhang   Output Parameters:
16733f72c5dSHong Zhang . A - Jacobian matrix
16833f72c5dSHong Zhang 
16933f72c5dSHong Zhang   Level: developer
17033f72c5dSHong Zhang 
171db781477SPatrick Sanan .seealso: `TSSetIJacobianP()`
17233f72c5dSHong Zhang @*/
17333f72c5dSHong Zhang PetscErrorCode TSComputeIJacobianP(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal shift,Mat Amat,PetscBool imex)
17433f72c5dSHong Zhang {
17533f72c5dSHong Zhang   PetscFunctionBegin;
17633f72c5dSHong Zhang   if (!Amat) PetscFunctionReturn(0);
17733f72c5dSHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
17833f72c5dSHong Zhang   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
17933f72c5dSHong Zhang   PetscValidHeaderSpecific(Udot,VEC_CLASSID,4);
18033f72c5dSHong Zhang 
1819566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(TS_JacobianPEval,ts,U,Amat,0));
18233f72c5dSHong Zhang   if (ts->ijacobianp) {
183792fecdfSBarry Smith     PetscCallBack("TS callback JacobianP for sensitivity analysis",(*ts->ijacobianp)(ts,t,U,Udot,shift,Amat,ts->ijacobianpctx));
18433f72c5dSHong Zhang   }
18533f72c5dSHong Zhang   if (imex) {
18633f72c5dSHong Zhang     if (!ts->ijacobianp) {  /* system was written as Udot = G(t,U) */
18733f72c5dSHong Zhang       PetscBool assembled;
1889566063dSJacob Faibussowitsch       PetscCall(MatZeroEntries(Amat));
1899566063dSJacob Faibussowitsch       PetscCall(MatAssembled(Amat,&assembled));
19033f72c5dSHong Zhang       if (!assembled) {
1919566063dSJacob Faibussowitsch         PetscCall(MatAssemblyBegin(Amat,MAT_FINAL_ASSEMBLY));
1929566063dSJacob Faibussowitsch         PetscCall(MatAssemblyEnd(Amat,MAT_FINAL_ASSEMBLY));
19333f72c5dSHong Zhang       }
19433f72c5dSHong Zhang     }
19533f72c5dSHong Zhang   } else {
1961baa6e33SBarry Smith     if (ts->rhsjacobianp) PetscCall(TSComputeRHSJacobianP(ts,t,U,ts->Jacprhs));
19733f72c5dSHong Zhang     if (ts->Jacprhs == Amat) { /* No IJacobian, so we only have the RHS matrix */
1989566063dSJacob Faibussowitsch       PetscCall(MatScale(Amat,-1));
19933f72c5dSHong Zhang     } else if (ts->Jacprhs) { /* Both IJacobian and RHSJacobian */
20033f72c5dSHong Zhang       MatStructure axpy = DIFFERENT_NONZERO_PATTERN;
20133f72c5dSHong Zhang       if (!ts->ijacobianp) { /* No IJacobianp provided, but we have a separate RHS matrix */
2029566063dSJacob Faibussowitsch         PetscCall(MatZeroEntries(Amat));
20333f72c5dSHong Zhang       }
2049566063dSJacob Faibussowitsch       PetscCall(MatAXPY(Amat,-1,ts->Jacprhs,axpy));
20533f72c5dSHong Zhang     }
20633f72c5dSHong Zhang   }
2079566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(TS_JacobianPEval,ts,U,Amat,0));
20833f72c5dSHong Zhang   PetscFunctionReturn(0);
20933f72c5dSHong Zhang }
21033f72c5dSHong Zhang 
21133f72c5dSHong Zhang /*@C
212814e85d6SHong Zhang     TSSetCostIntegrand - Sets the routine for evaluating the integral term in one or more cost functions
213814e85d6SHong Zhang 
214814e85d6SHong Zhang     Logically Collective on TS
215814e85d6SHong Zhang 
216814e85d6SHong Zhang     Input Parameters:
217814e85d6SHong Zhang +   ts - the TS context obtained from TSCreate()
218814e85d6SHong Zhang .   numcost - number of gradients to be computed, this is the number of cost functions
219814e85d6SHong Zhang .   costintegral - vector that stores the integral values
220814e85d6SHong Zhang .   rf - routine for evaluating the integrand function
221c9ad9de0SHong Zhang .   drduf - function that computes the gradients of the r's with respect to u
222814e85d6SHong 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)
223814e85d6SHong Zhang .   fwd - flag indicating whether to evaluate cost integral in the forward run or the adjoint run
224814e85d6SHong Zhang -   ctx - [optional] user-defined context for private data for the function evaluation routine (may be NULL)
225814e85d6SHong Zhang 
226814e85d6SHong Zhang     Calling sequence of rf:
227c9ad9de0SHong Zhang $   PetscErrorCode rf(TS ts,PetscReal t,Vec U,Vec F,void *ctx);
228814e85d6SHong Zhang 
229c9ad9de0SHong Zhang     Calling sequence of drduf:
230c9ad9de0SHong Zhang $   PetscErroCode drduf(TS ts,PetscReal t,Vec U,Vec *dRdU,void *ctx);
231814e85d6SHong Zhang 
232814e85d6SHong Zhang     Calling sequence of drdpf:
233c9ad9de0SHong Zhang $   PetscErroCode drdpf(TS ts,PetscReal t,Vec U,Vec *dRdP,void *ctx);
234814e85d6SHong Zhang 
235cd4cee2dSHong Zhang     Level: deprecated
236814e85d6SHong Zhang 
237814e85d6SHong Zhang     Notes:
238814e85d6SHong Zhang     For optimization there is usually a single cost function (numcost = 1). For sensitivities there may be multiple cost functions
239814e85d6SHong Zhang 
240db781477SPatrick Sanan .seealso: `TSSetRHSJacobianP()`, `TSGetCostGradients()`, `TSSetCostGradients()`
241814e85d6SHong Zhang @*/
242814e85d6SHong Zhang PetscErrorCode TSSetCostIntegrand(TS ts,PetscInt numcost,Vec costintegral,PetscErrorCode (*rf)(TS,PetscReal,Vec,Vec,void*),
243c9ad9de0SHong Zhang                                                           PetscErrorCode (*drduf)(TS,PetscReal,Vec,Vec*,void*),
244814e85d6SHong Zhang                                                           PetscErrorCode (*drdpf)(TS,PetscReal,Vec,Vec*,void*),
245814e85d6SHong Zhang                                                           PetscBool fwd,void *ctx)
246814e85d6SHong Zhang {
247814e85d6SHong Zhang   PetscFunctionBegin;
248814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
249814e85d6SHong Zhang   if (costintegral) PetscValidHeaderSpecific(costintegral,VEC_CLASSID,3);
2503c633725SBarry Smith   PetscCheck(!ts->numcost || ts->numcost == numcost,PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"The number of cost functions (2nd parameter of TSSetCostIntegrand()) is inconsistent with the one set by TSSetCostGradients() or TSForwardSetIntegralGradients()");
251814e85d6SHong Zhang   if (!ts->numcost) ts->numcost=numcost;
252814e85d6SHong Zhang 
253814e85d6SHong Zhang   if (costintegral) {
2549566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)costintegral));
2559566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&ts->vec_costintegral));
256814e85d6SHong Zhang     ts->vec_costintegral = costintegral;
257814e85d6SHong Zhang   } else {
258814e85d6SHong Zhang     if (!ts->vec_costintegral) { /* Create a seq vec if user does not provide one */
2599566063dSJacob Faibussowitsch       PetscCall(VecCreateSeq(PETSC_COMM_SELF,numcost,&ts->vec_costintegral));
260814e85d6SHong Zhang     } else {
2619566063dSJacob Faibussowitsch       PetscCall(VecSet(ts->vec_costintegral,0.0));
262814e85d6SHong Zhang     }
263814e85d6SHong Zhang   }
264814e85d6SHong Zhang   if (!ts->vec_costintegrand) {
2659566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(ts->vec_costintegral,&ts->vec_costintegrand));
266814e85d6SHong Zhang   } else {
2679566063dSJacob Faibussowitsch     PetscCall(VecSet(ts->vec_costintegrand,0.0));
268814e85d6SHong Zhang   }
269814e85d6SHong Zhang   ts->costintegralfwd  = fwd; /* Evaluate the cost integral in forward run if fwd is true */
270814e85d6SHong Zhang   ts->costintegrand    = rf;
271814e85d6SHong Zhang   ts->costintegrandctx = ctx;
272c9ad9de0SHong Zhang   ts->drdufunction     = drduf;
273814e85d6SHong Zhang   ts->drdpfunction     = drdpf;
274814e85d6SHong Zhang   PetscFunctionReturn(0);
275814e85d6SHong Zhang }
276814e85d6SHong Zhang 
277b5b4017aSHong Zhang /*@C
278814e85d6SHong Zhang    TSGetCostIntegral - Returns the values of the integral term in the cost functions.
279814e85d6SHong Zhang    It is valid to call the routine after a backward run.
280814e85d6SHong Zhang 
281814e85d6SHong Zhang    Not Collective
282814e85d6SHong Zhang 
283814e85d6SHong Zhang    Input Parameter:
284814e85d6SHong Zhang .  ts - the TS context obtained from TSCreate()
285814e85d6SHong Zhang 
286814e85d6SHong Zhang    Output Parameter:
287814e85d6SHong Zhang .  v - the vector containing the integrals for each cost function
288814e85d6SHong Zhang 
289814e85d6SHong Zhang    Level: intermediate
290814e85d6SHong Zhang 
291db781477SPatrick Sanan .seealso: `TSSetCostIntegrand()`
292814e85d6SHong Zhang 
293814e85d6SHong Zhang @*/
294814e85d6SHong Zhang PetscErrorCode  TSGetCostIntegral(TS ts,Vec *v)
295814e85d6SHong Zhang {
296cd4cee2dSHong Zhang   TS             quadts;
297cd4cee2dSHong Zhang 
298814e85d6SHong Zhang   PetscFunctionBegin;
299814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
300814e85d6SHong Zhang   PetscValidPointer(v,2);
3019566063dSJacob Faibussowitsch   PetscCall(TSGetQuadratureTS(ts,NULL,&quadts));
302cd4cee2dSHong Zhang   *v = quadts->vec_sol;
303814e85d6SHong Zhang   PetscFunctionReturn(0);
304814e85d6SHong Zhang }
305814e85d6SHong Zhang 
306b5b4017aSHong Zhang /*@C
307814e85d6SHong Zhang    TSComputeCostIntegrand - Evaluates the integral function in the cost functions.
308814e85d6SHong Zhang 
309814e85d6SHong Zhang    Input Parameters:
310814e85d6SHong Zhang +  ts - the TS context
311814e85d6SHong Zhang .  t - current time
312c9ad9de0SHong Zhang -  U - state vector, i.e. current solution
313814e85d6SHong Zhang 
314814e85d6SHong Zhang    Output Parameter:
315c9ad9de0SHong Zhang .  Q - vector of size numcost to hold the outputs
316814e85d6SHong Zhang 
317369cf35fSHong Zhang    Notes:
318814e85d6SHong Zhang    Most users should not need to explicitly call this routine, as it
319814e85d6SHong Zhang    is used internally within the sensitivity analysis context.
320814e85d6SHong Zhang 
321cd4cee2dSHong Zhang    Level: deprecated
322814e85d6SHong Zhang 
323db781477SPatrick Sanan .seealso: `TSSetCostIntegrand()`
324814e85d6SHong Zhang @*/
325c9ad9de0SHong Zhang PetscErrorCode TSComputeCostIntegrand(TS ts,PetscReal t,Vec U,Vec Q)
326814e85d6SHong Zhang {
327814e85d6SHong Zhang   PetscFunctionBegin;
328814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
329c9ad9de0SHong Zhang   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
330c9ad9de0SHong Zhang   PetscValidHeaderSpecific(Q,VEC_CLASSID,4);
331814e85d6SHong Zhang 
3329566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(TS_FunctionEval,ts,U,Q,0));
333792fecdfSBarry Smith   if (ts->costintegrand) PetscCallBack("TS callback integrand in the cost function",(*ts->costintegrand)(ts,t,U,Q,ts->costintegrandctx));
334ef1023bdSBarry Smith   else PetscCall(VecZeroEntries(Q));
3359566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(TS_FunctionEval,ts,U,Q,0));
336814e85d6SHong Zhang   PetscFunctionReturn(0);
337814e85d6SHong Zhang }
338814e85d6SHong Zhang 
339b5b4017aSHong Zhang /*@C
340d76be551SHong Zhang   TSComputeDRDUFunction - Deprecated, use TSGetQuadratureTS() then TSComputeRHSJacobian()
341814e85d6SHong Zhang 
342d76be551SHong Zhang   Level: deprecated
343814e85d6SHong Zhang 
344814e85d6SHong Zhang @*/
345c9ad9de0SHong Zhang PetscErrorCode TSComputeDRDUFunction(TS ts,PetscReal t,Vec U,Vec *DRDU)
346814e85d6SHong Zhang {
347814e85d6SHong Zhang   PetscFunctionBegin;
34833f72c5dSHong Zhang   if (!DRDU) PetscFunctionReturn(0);
349814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
350c9ad9de0SHong Zhang   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
351814e85d6SHong Zhang 
352792fecdfSBarry Smith   PetscCallBack("TS callback DRDU for sensitivity analysis",(*ts->drdufunction)(ts,t,U,DRDU,ts->costintegrandctx));
353814e85d6SHong Zhang   PetscFunctionReturn(0);
354814e85d6SHong Zhang }
355814e85d6SHong Zhang 
356b5b4017aSHong Zhang /*@C
357d76be551SHong Zhang   TSComputeDRDPFunction - Deprecated, use TSGetQuadratureTS() then TSComputeRHSJacobianP()
358814e85d6SHong Zhang 
359d76be551SHong Zhang   Level: deprecated
360814e85d6SHong Zhang 
361814e85d6SHong Zhang @*/
362c9ad9de0SHong Zhang PetscErrorCode TSComputeDRDPFunction(TS ts,PetscReal t,Vec U,Vec *DRDP)
363814e85d6SHong Zhang {
364814e85d6SHong Zhang   PetscFunctionBegin;
36533f72c5dSHong Zhang   if (!DRDP) PetscFunctionReturn(0);
366814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
367c9ad9de0SHong Zhang   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
368814e85d6SHong Zhang 
369792fecdfSBarry Smith   PetscCallBack("TS callback DRDP for sensitivity analysis",(*ts->drdpfunction)(ts,t,U,DRDP,ts->costintegrandctx));
370814e85d6SHong Zhang   PetscFunctionReturn(0);
371814e85d6SHong Zhang }
372814e85d6SHong Zhang 
373b5b4017aSHong Zhang /*@C
374b5b4017aSHong 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.
375b5b4017aSHong Zhang 
376b5b4017aSHong Zhang   Logically Collective on TS
377b5b4017aSHong Zhang 
378b5b4017aSHong Zhang   Input Parameters:
379b5b4017aSHong Zhang + ts - TS context obtained from TSCreate()
380b5b4017aSHong Zhang . ihp1 - an array of vectors storing the result of vector-Hessian-vector product for F_UU
381b5b4017aSHong Zhang . hessianproductfunc1 - vector-Hessian-vector product function for F_UU
382b5b4017aSHong Zhang . ihp2 - an array of vectors storing the result of vector-Hessian-vector product for F_UP
383b5b4017aSHong Zhang . hessianproductfunc2 - vector-Hessian-vector product function for F_UP
384b5b4017aSHong Zhang . ihp3 - an array of vectors storing the result of vector-Hessian-vector product for F_PU
385b5b4017aSHong Zhang . hessianproductfunc3 - vector-Hessian-vector product function for F_PU
386b5b4017aSHong Zhang . ihp4 - an array of vectors storing the result of vector-Hessian-vector product for F_PP
387f0fc11ceSJed Brown - hessianproductfunc4 - vector-Hessian-vector product function for F_PP
388b5b4017aSHong Zhang 
389b5b4017aSHong Zhang   Calling sequence of ihessianproductfunc:
390369cf35fSHong Zhang $ ihessianproductfunc (TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV,void *ctx);
391b5b4017aSHong Zhang +   t - current timestep
392b5b4017aSHong Zhang .   U - input vector (current ODE solution)
393369cf35fSHong Zhang .   Vl - an array of input vectors to be left-multiplied with the Hessian
394b5b4017aSHong Zhang .   Vr - input vector to be right-multiplied with the Hessian
395369cf35fSHong Zhang .   VHV - an array of output vectors for vector-Hessian-vector product
396b5b4017aSHong Zhang -   ctx - [optional] user-defined function context
397b5b4017aSHong Zhang 
398b5b4017aSHong Zhang   Level: intermediate
399b5b4017aSHong Zhang 
400369cf35fSHong Zhang   Notes:
401369cf35fSHong Zhang   The first Hessian function and the working array are required.
402369cf35fSHong Zhang   As an example to implement the callback functions, the second callback function calculates the vector-Hessian-vector product
403369cf35fSHong Zhang   $ Vl_n^T*F_UP*Vr
404369cf35fSHong Zhang   where the vector Vl_n (n-th element in the array Vl) and Vr are of size N and M respectively, and the Hessian F_UP is of size N x N x M.
405369cf35fSHong Zhang   Each entry of F_UP corresponds to the derivative
406369cf35fSHong Zhang   $ F_UP[i][j][k] = \frac{\partial^2 F[i]}{\partial U[j] \partial P[k]}.
407369cf35fSHong Zhang   The result of the vector-Hessian-vector product for Vl_n needs to be stored in vector VHV_n with the j-th entry being
408369cf35fSHong Zhang   $ VHV_n[j] = \sum_i \sum_k {Vl_n[i] * F_UP[i][j][k] * Vr[k]}
409369cf35fSHong Zhang   If the cost function is a scalar, there will be only one vector in Vl and VHV.
410b5b4017aSHong Zhang 
411b5b4017aSHong Zhang .seealso:
412b5b4017aSHong Zhang @*/
413b5b4017aSHong Zhang PetscErrorCode TSSetIHessianProduct(TS ts,Vec *ihp1,PetscErrorCode (*ihessianproductfunc1)(TS,PetscReal,Vec,Vec*,Vec,Vec*,void*),
414b5b4017aSHong Zhang                                           Vec *ihp2,PetscErrorCode (*ihessianproductfunc2)(TS,PetscReal,Vec,Vec*,Vec,Vec*,void*),
415b5b4017aSHong Zhang                                           Vec *ihp3,PetscErrorCode (*ihessianproductfunc3)(TS,PetscReal,Vec,Vec*,Vec,Vec*,void*),
416b5b4017aSHong Zhang                                           Vec *ihp4,PetscErrorCode (*ihessianproductfunc4)(TS,PetscReal,Vec,Vec*,Vec,Vec*,void*),
417b5b4017aSHong Zhang                                     void *ctx)
418b5b4017aSHong Zhang {
419b5b4017aSHong Zhang   PetscFunctionBegin;
420b5b4017aSHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
421b5b4017aSHong Zhang   PetscValidPointer(ihp1,2);
422b5b4017aSHong Zhang 
423b5b4017aSHong Zhang   ts->ihessianproductctx = ctx;
424b5b4017aSHong Zhang   if (ihp1) ts->vecs_fuu = ihp1;
425b5b4017aSHong Zhang   if (ihp2) ts->vecs_fup = ihp2;
426b5b4017aSHong Zhang   if (ihp3) ts->vecs_fpu = ihp3;
427b5b4017aSHong Zhang   if (ihp4) ts->vecs_fpp = ihp4;
428b5b4017aSHong Zhang   ts->ihessianproduct_fuu = ihessianproductfunc1;
429b5b4017aSHong Zhang   ts->ihessianproduct_fup = ihessianproductfunc2;
430b5b4017aSHong Zhang   ts->ihessianproduct_fpu = ihessianproductfunc3;
431b5b4017aSHong Zhang   ts->ihessianproduct_fpp = ihessianproductfunc4;
432b5b4017aSHong Zhang   PetscFunctionReturn(0);
433b5b4017aSHong Zhang }
434b5b4017aSHong Zhang 
435b5b4017aSHong Zhang /*@C
436b1e111ebSHong Zhang   TSComputeIHessianProductFunctionUU - Runs the user-defined vector-Hessian-vector product function for Fuu.
437b5b4017aSHong Zhang 
438b5b4017aSHong Zhang   Collective on TS
439b5b4017aSHong Zhang 
440b5b4017aSHong Zhang   Input Parameters:
441b5b4017aSHong Zhang . ts   - The TS context obtained from TSCreate()
442b5b4017aSHong Zhang 
443b5b4017aSHong Zhang   Notes:
444b1e111ebSHong Zhang   TSComputeIHessianProductFunctionUU() is typically used for sensitivity implementation,
445b5b4017aSHong Zhang   so most users would not generally call this routine themselves.
446b5b4017aSHong Zhang 
447b5b4017aSHong Zhang   Level: developer
448b5b4017aSHong Zhang 
449db781477SPatrick Sanan .seealso: `TSSetIHessianProduct()`
450b5b4017aSHong Zhang @*/
451b1e111ebSHong Zhang PetscErrorCode TSComputeIHessianProductFunctionUU(TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV)
452b5b4017aSHong Zhang {
453b5b4017aSHong Zhang   PetscFunctionBegin;
45433f72c5dSHong Zhang   if (!VHV) PetscFunctionReturn(0);
455b5b4017aSHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
456b5b4017aSHong Zhang   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
457b5b4017aSHong Zhang 
458792fecdfSBarry Smith   if (ts->ihessianproduct_fuu) PetscCallBack("TS callback IHessianProduct 1 for sensitivity analysis",(*ts->ihessianproduct_fuu)(ts,t,U,Vl,Vr,VHV,ts->ihessianproductctx));
459ef1023bdSBarry Smith 
46067633408SHong Zhang   /* does not consider IMEX for now, so either IHessian or RHSHessian will be calculated, using the same output VHV */
46167633408SHong Zhang   if (ts->rhshessianproduct_guu) {
46267633408SHong Zhang     PetscInt nadj;
4639566063dSJacob Faibussowitsch     PetscCall(TSComputeRHSHessianProductFunctionUU(ts,t,U,Vl,Vr,VHV));
46467633408SHong Zhang     for (nadj=0; nadj<ts->numcost; nadj++) {
4659566063dSJacob Faibussowitsch       PetscCall(VecScale(VHV[nadj],-1));
46667633408SHong Zhang     }
46767633408SHong Zhang   }
468b5b4017aSHong Zhang   PetscFunctionReturn(0);
469b5b4017aSHong Zhang }
470b5b4017aSHong Zhang 
471b5b4017aSHong Zhang /*@C
472b1e111ebSHong Zhang   TSComputeIHessianProductFunctionUP - Runs the user-defined vector-Hessian-vector product function for Fup.
473b5b4017aSHong Zhang 
474b5b4017aSHong Zhang   Collective on TS
475b5b4017aSHong Zhang 
476b5b4017aSHong Zhang   Input Parameters:
477b5b4017aSHong Zhang . ts   - The TS context obtained from TSCreate()
478b5b4017aSHong Zhang 
479b5b4017aSHong Zhang   Notes:
480b1e111ebSHong Zhang   TSComputeIHessianProductFunctionUP() is typically used for sensitivity implementation,
481b5b4017aSHong Zhang   so most users would not generally call this routine themselves.
482b5b4017aSHong Zhang 
483b5b4017aSHong Zhang   Level: developer
484b5b4017aSHong Zhang 
485db781477SPatrick Sanan .seealso: `TSSetIHessianProduct()`
486b5b4017aSHong Zhang @*/
487b1e111ebSHong Zhang PetscErrorCode TSComputeIHessianProductFunctionUP(TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV)
488b5b4017aSHong Zhang {
489b5b4017aSHong Zhang   PetscFunctionBegin;
49033f72c5dSHong Zhang   if (!VHV) PetscFunctionReturn(0);
491b5b4017aSHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
492b5b4017aSHong Zhang   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
493b5b4017aSHong Zhang 
494792fecdfSBarry Smith   if (ts->ihessianproduct_fup) PetscCallBack("TS callback IHessianProduct 2 for sensitivity analysis",(*ts->ihessianproduct_fup)(ts,t,U,Vl,Vr,VHV,ts->ihessianproductctx));
495ef1023bdSBarry Smith 
49667633408SHong Zhang   /* does not consider IMEX for now, so either IHessian or RHSHessian will be calculated, using the same output VHV */
49767633408SHong Zhang   if (ts->rhshessianproduct_gup) {
49867633408SHong Zhang     PetscInt nadj;
4999566063dSJacob Faibussowitsch     PetscCall(TSComputeRHSHessianProductFunctionUP(ts,t,U,Vl,Vr,VHV));
50067633408SHong Zhang     for (nadj=0; nadj<ts->numcost; nadj++) {
5019566063dSJacob Faibussowitsch       PetscCall(VecScale(VHV[nadj],-1));
50267633408SHong Zhang     }
50367633408SHong Zhang   }
504b5b4017aSHong Zhang   PetscFunctionReturn(0);
505b5b4017aSHong Zhang }
506b5b4017aSHong Zhang 
507b5b4017aSHong Zhang /*@C
508b1e111ebSHong Zhang   TSComputeIHessianProductFunctionPU - Runs the user-defined vector-Hessian-vector product function for Fpu.
509b5b4017aSHong Zhang 
510b5b4017aSHong Zhang   Collective on TS
511b5b4017aSHong Zhang 
512b5b4017aSHong Zhang   Input Parameters:
513b5b4017aSHong Zhang . ts   - The TS context obtained from TSCreate()
514b5b4017aSHong Zhang 
515b5b4017aSHong Zhang   Notes:
516b1e111ebSHong Zhang   TSComputeIHessianProductFunctionPU() is typically used for sensitivity implementation,
517b5b4017aSHong Zhang   so most users would not generally call this routine themselves.
518b5b4017aSHong Zhang 
519b5b4017aSHong Zhang   Level: developer
520b5b4017aSHong Zhang 
521db781477SPatrick Sanan .seealso: `TSSetIHessianProduct()`
522b5b4017aSHong Zhang @*/
523b1e111ebSHong Zhang PetscErrorCode TSComputeIHessianProductFunctionPU(TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV)
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 
530792fecdfSBarry Smith   if (ts->ihessianproduct_fpu) PetscCallBack("TS callback IHessianProduct 3 for sensitivity analysis",(*ts->ihessianproduct_fpu)(ts,t,U,Vl,Vr,VHV,ts->ihessianproductctx));
531ef1023bdSBarry Smith 
53267633408SHong Zhang   /* does not consider IMEX for now, so either IHessian or RHSHessian will be calculated, using the same output VHV */
53367633408SHong Zhang   if (ts->rhshessianproduct_gpu) {
53467633408SHong Zhang     PetscInt nadj;
5359566063dSJacob Faibussowitsch     PetscCall(TSComputeRHSHessianProductFunctionPU(ts,t,U,Vl,Vr,VHV));
53667633408SHong Zhang     for (nadj=0; nadj<ts->numcost; nadj++) {
5379566063dSJacob Faibussowitsch       PetscCall(VecScale(VHV[nadj],-1));
53867633408SHong Zhang     }
53967633408SHong Zhang   }
540b5b4017aSHong Zhang   PetscFunctionReturn(0);
541b5b4017aSHong Zhang }
542b5b4017aSHong Zhang 
543b5b4017aSHong Zhang /*@C
544b1e111ebSHong Zhang   TSComputeIHessianProductFunctionPP - Runs the user-defined vector-Hessian-vector product function for Fpp.
545b5b4017aSHong Zhang 
546b5b4017aSHong Zhang   Collective on TS
547b5b4017aSHong Zhang 
548b5b4017aSHong Zhang   Input Parameters:
549b5b4017aSHong Zhang . ts   - The TS context obtained from TSCreate()
550b5b4017aSHong Zhang 
551b5b4017aSHong Zhang   Notes:
552b1e111ebSHong Zhang   TSComputeIHessianProductFunctionPP() is typically used for sensitivity implementation,
553b5b4017aSHong Zhang   so most users would not generally call this routine themselves.
554b5b4017aSHong Zhang 
555b5b4017aSHong Zhang   Level: developer
556b5b4017aSHong Zhang 
557db781477SPatrick Sanan .seealso: `TSSetIHessianProduct()`
558b5b4017aSHong Zhang @*/
559b1e111ebSHong Zhang PetscErrorCode TSComputeIHessianProductFunctionPP(TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV)
560b5b4017aSHong Zhang {
561b5b4017aSHong Zhang   PetscFunctionBegin;
56233f72c5dSHong Zhang   if (!VHV) PetscFunctionReturn(0);
563b5b4017aSHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
564b5b4017aSHong Zhang   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
565b5b4017aSHong Zhang 
566792fecdfSBarry Smith   if (ts->ihessianproduct_fpp) PetscCallBack("TS callback IHessianProduct 3 for sensitivity analysis",(*ts->ihessianproduct_fpp)(ts,t,U,Vl,Vr,VHV,ts->ihessianproductctx));
567ef1023bdSBarry Smith 
56867633408SHong Zhang   /* does not consider IMEX for now, so either IHessian or RHSHessian will be calculated, using the same output VHV */
56967633408SHong Zhang   if (ts->rhshessianproduct_gpp) {
57067633408SHong Zhang     PetscInt nadj;
5719566063dSJacob Faibussowitsch     PetscCall(TSComputeRHSHessianProductFunctionPP(ts,t,U,Vl,Vr,VHV));
57267633408SHong Zhang     for (nadj=0; nadj<ts->numcost; nadj++) {
5739566063dSJacob Faibussowitsch       PetscCall(VecScale(VHV[nadj],-1));
57467633408SHong Zhang     }
57567633408SHong Zhang   }
576b5b4017aSHong Zhang   PetscFunctionReturn(0);
577b5b4017aSHong Zhang }
578b5b4017aSHong Zhang 
57913af1a74SHong Zhang /*@C
5804c500f23SPierre Jolivet   TSSetRHSHessianProduct - Sets the function that computes the vector-Hessian-vector product. The Hessian is the second-order derivative of G (RHSFunction) w.r.t. the state variable.
58113af1a74SHong Zhang 
58213af1a74SHong Zhang   Logically Collective on TS
58313af1a74SHong Zhang 
58413af1a74SHong Zhang   Input Parameters:
58513af1a74SHong Zhang + ts - TS context obtained from TSCreate()
58613af1a74SHong Zhang . rhshp1 - an array of vectors storing the result of vector-Hessian-vector product for G_UU
58713af1a74SHong Zhang . hessianproductfunc1 - vector-Hessian-vector product function for G_UU
58813af1a74SHong Zhang . rhshp2 - an array of vectors storing the result of vector-Hessian-vector product for G_UP
58913af1a74SHong Zhang . hessianproductfunc2 - vector-Hessian-vector product function for G_UP
59013af1a74SHong Zhang . rhshp3 - an array of vectors storing the result of vector-Hessian-vector product for G_PU
59113af1a74SHong Zhang . hessianproductfunc3 - vector-Hessian-vector product function for G_PU
59213af1a74SHong Zhang . rhshp4 - an array of vectors storing the result of vector-Hessian-vector product for G_PP
593f0fc11ceSJed Brown - hessianproductfunc4 - vector-Hessian-vector product function for G_PP
59413af1a74SHong Zhang 
59513af1a74SHong Zhang   Calling sequence of ihessianproductfunc:
596369cf35fSHong Zhang $ rhshessianproductfunc (TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV,void *ctx);
59713af1a74SHong Zhang +   t - current timestep
59813af1a74SHong Zhang .   U - input vector (current ODE solution)
599369cf35fSHong Zhang .   Vl - an array of input vectors to be left-multiplied with the Hessian
60013af1a74SHong Zhang .   Vr - input vector to be right-multiplied with the Hessian
601369cf35fSHong Zhang .   VHV - an array of output vectors for vector-Hessian-vector product
60213af1a74SHong Zhang -   ctx - [optional] user-defined function context
60313af1a74SHong Zhang 
60413af1a74SHong Zhang   Level: intermediate
60513af1a74SHong Zhang 
606369cf35fSHong Zhang   Notes:
607369cf35fSHong Zhang   The first Hessian function and the working array are required.
608369cf35fSHong Zhang   As an example to implement the callback functions, the second callback function calculates the vector-Hessian-vector product
609369cf35fSHong Zhang   $ Vl_n^T*G_UP*Vr
610369cf35fSHong Zhang   where the vector Vl_n (n-th element in the array Vl) and Vr are of size N and M respectively, and the Hessian G_UP is of size N x N x M.
611369cf35fSHong Zhang   Each entry of G_UP corresponds to the derivative
612369cf35fSHong Zhang   $ G_UP[i][j][k] = \frac{\partial^2 G[i]}{\partial U[j] \partial P[k]}.
613369cf35fSHong Zhang   The result of the vector-Hessian-vector product for Vl_n needs to be stored in vector VHV_n with j-th entry being
614369cf35fSHong Zhang   $ VHV_n[j] = \sum_i \sum_k {Vl_n[i] * G_UP[i][j][k] * Vr[k]}
615369cf35fSHong Zhang   If the cost function is a scalar, there will be only one vector in Vl and VHV.
61613af1a74SHong Zhang 
61713af1a74SHong Zhang .seealso:
61813af1a74SHong Zhang @*/
61913af1a74SHong Zhang PetscErrorCode TSSetRHSHessianProduct(TS ts,Vec *rhshp1,PetscErrorCode (*rhshessianproductfunc1)(TS,PetscReal,Vec,Vec*,Vec,Vec*,void*),
62013af1a74SHong Zhang                                           Vec *rhshp2,PetscErrorCode (*rhshessianproductfunc2)(TS,PetscReal,Vec,Vec*,Vec,Vec*,void*),
62113af1a74SHong Zhang                                           Vec *rhshp3,PetscErrorCode (*rhshessianproductfunc3)(TS,PetscReal,Vec,Vec*,Vec,Vec*,void*),
62213af1a74SHong Zhang                                           Vec *rhshp4,PetscErrorCode (*rhshessianproductfunc4)(TS,PetscReal,Vec,Vec*,Vec,Vec*,void*),
62313af1a74SHong Zhang                                     void *ctx)
62413af1a74SHong Zhang {
62513af1a74SHong Zhang   PetscFunctionBegin;
62613af1a74SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
62713af1a74SHong Zhang   PetscValidPointer(rhshp1,2);
62813af1a74SHong Zhang 
62913af1a74SHong Zhang   ts->rhshessianproductctx = ctx;
63013af1a74SHong Zhang   if (rhshp1) ts->vecs_guu = rhshp1;
63113af1a74SHong Zhang   if (rhshp2) ts->vecs_gup = rhshp2;
63213af1a74SHong Zhang   if (rhshp3) ts->vecs_gpu = rhshp3;
63313af1a74SHong Zhang   if (rhshp4) ts->vecs_gpp = rhshp4;
63413af1a74SHong Zhang   ts->rhshessianproduct_guu = rhshessianproductfunc1;
63513af1a74SHong Zhang   ts->rhshessianproduct_gup = rhshessianproductfunc2;
63613af1a74SHong Zhang   ts->rhshessianproduct_gpu = rhshessianproductfunc3;
63713af1a74SHong Zhang   ts->rhshessianproduct_gpp = rhshessianproductfunc4;
63813af1a74SHong Zhang   PetscFunctionReturn(0);
63913af1a74SHong Zhang }
64013af1a74SHong Zhang 
64113af1a74SHong Zhang /*@C
642b1e111ebSHong Zhang   TSComputeRHSHessianProductFunctionUU - Runs the user-defined vector-Hessian-vector product function for Guu.
64313af1a74SHong Zhang 
64413af1a74SHong Zhang   Collective on TS
64513af1a74SHong Zhang 
64613af1a74SHong Zhang   Input Parameters:
64713af1a74SHong Zhang . ts   - The TS context obtained from TSCreate()
64813af1a74SHong Zhang 
64913af1a74SHong Zhang   Notes:
650b1e111ebSHong Zhang   TSComputeRHSHessianProductFunctionUU() is typically used for sensitivity implementation,
65113af1a74SHong Zhang   so most users would not generally call this routine themselves.
65213af1a74SHong Zhang 
65313af1a74SHong Zhang   Level: developer
65413af1a74SHong Zhang 
655db781477SPatrick Sanan .seealso: `TSSetRHSHessianProduct()`
65613af1a74SHong Zhang @*/
657b1e111ebSHong Zhang PetscErrorCode TSComputeRHSHessianProductFunctionUU(TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV)
65813af1a74SHong Zhang {
65913af1a74SHong Zhang   PetscFunctionBegin;
66013af1a74SHong Zhang   if (!VHV) PetscFunctionReturn(0);
66113af1a74SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
66213af1a74SHong Zhang   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
66313af1a74SHong Zhang 
664792fecdfSBarry Smith   PetscCallBack("TS callback RHSHessianProduct 1 for sensitivity analysis",(*ts->rhshessianproduct_guu)(ts,t,U,Vl,Vr,VHV,ts->rhshessianproductctx));
66513af1a74SHong Zhang   PetscFunctionReturn(0);
66613af1a74SHong Zhang }
66713af1a74SHong Zhang 
66813af1a74SHong Zhang /*@C
669b1e111ebSHong Zhang   TSComputeRHSHessianProductFunctionUP - Runs the user-defined vector-Hessian-vector product function for Gup.
67013af1a74SHong Zhang 
67113af1a74SHong Zhang   Collective on TS
67213af1a74SHong Zhang 
67313af1a74SHong Zhang   Input Parameters:
67413af1a74SHong Zhang . ts   - The TS context obtained from TSCreate()
67513af1a74SHong Zhang 
67613af1a74SHong Zhang   Notes:
677b1e111ebSHong Zhang   TSComputeRHSHessianProductFunctionUP() is typically used for sensitivity implementation,
67813af1a74SHong Zhang   so most users would not generally call this routine themselves.
67913af1a74SHong Zhang 
68013af1a74SHong Zhang   Level: developer
68113af1a74SHong Zhang 
682db781477SPatrick Sanan .seealso: `TSSetRHSHessianProduct()`
68313af1a74SHong Zhang @*/
684b1e111ebSHong Zhang PetscErrorCode TSComputeRHSHessianProductFunctionUP(TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV)
68513af1a74SHong Zhang {
68613af1a74SHong Zhang   PetscFunctionBegin;
68713af1a74SHong Zhang   if (!VHV) PetscFunctionReturn(0);
68813af1a74SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
68913af1a74SHong Zhang   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
69013af1a74SHong Zhang 
691792fecdfSBarry Smith   PetscCallBack("TS callback RHSHessianProduct 2 for sensitivity analysis",(*ts->rhshessianproduct_gup)(ts,t,U,Vl,Vr,VHV,ts->rhshessianproductctx));
69213af1a74SHong Zhang   PetscFunctionReturn(0);
69313af1a74SHong Zhang }
69413af1a74SHong Zhang 
69513af1a74SHong Zhang /*@C
696b1e111ebSHong Zhang   TSComputeRHSHessianProductFunctionPU - Runs the user-defined vector-Hessian-vector product function for Gpu.
69713af1a74SHong Zhang 
69813af1a74SHong Zhang   Collective on TS
69913af1a74SHong Zhang 
70013af1a74SHong Zhang   Input Parameters:
70113af1a74SHong Zhang . ts   - The TS context obtained from TSCreate()
70213af1a74SHong Zhang 
70313af1a74SHong Zhang   Notes:
704b1e111ebSHong Zhang   TSComputeRHSHessianProductFunctionPU() is typically used for sensitivity implementation,
70513af1a74SHong Zhang   so most users would not generally call this routine themselves.
70613af1a74SHong Zhang 
70713af1a74SHong Zhang   Level: developer
70813af1a74SHong Zhang 
709db781477SPatrick Sanan .seealso: `TSSetRHSHessianProduct()`
71013af1a74SHong Zhang @*/
711b1e111ebSHong Zhang PetscErrorCode TSComputeRHSHessianProductFunctionPU(TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV)
71213af1a74SHong Zhang {
71313af1a74SHong Zhang   PetscFunctionBegin;
71413af1a74SHong Zhang   if (!VHV) PetscFunctionReturn(0);
71513af1a74SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
71613af1a74SHong Zhang   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
71713af1a74SHong Zhang 
718792fecdfSBarry Smith   PetscCallBack("TS callback RHSHessianProduct 3 for sensitivity analysis",(*ts->rhshessianproduct_gpu)(ts,t,U,Vl,Vr,VHV,ts->rhshessianproductctx));
71913af1a74SHong Zhang   PetscFunctionReturn(0);
72013af1a74SHong Zhang }
72113af1a74SHong Zhang 
72213af1a74SHong Zhang /*@C
723b1e111ebSHong Zhang   TSComputeRHSHessianProductFunctionPP - Runs the user-defined vector-Hessian-vector product function for Gpp.
72413af1a74SHong Zhang 
72513af1a74SHong Zhang   Collective on TS
72613af1a74SHong Zhang 
72713af1a74SHong Zhang   Input Parameters:
72813af1a74SHong Zhang . ts   - The TS context obtained from TSCreate()
72913af1a74SHong Zhang 
73013af1a74SHong Zhang   Notes:
731b1e111ebSHong Zhang   TSComputeRHSHessianProductFunctionPP() is typically used for sensitivity implementation,
73213af1a74SHong Zhang   so most users would not generally call this routine themselves.
73313af1a74SHong Zhang 
73413af1a74SHong Zhang   Level: developer
73513af1a74SHong Zhang 
736db781477SPatrick Sanan .seealso: `TSSetRHSHessianProduct()`
73713af1a74SHong Zhang @*/
738b1e111ebSHong Zhang PetscErrorCode TSComputeRHSHessianProductFunctionPP(TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV)
73913af1a74SHong Zhang {
74013af1a74SHong Zhang   PetscFunctionBegin;
74113af1a74SHong Zhang   if (!VHV) PetscFunctionReturn(0);
74213af1a74SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
74313af1a74SHong Zhang   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
74413af1a74SHong Zhang 
745792fecdfSBarry Smith   PetscCallBack("TS callback RHSHessianProduct 3 for sensitivity analysis",(*ts->rhshessianproduct_gpp)(ts,t,U,Vl,Vr,VHV,ts->rhshessianproductctx));
74613af1a74SHong Zhang   PetscFunctionReturn(0);
74713af1a74SHong Zhang }
74813af1a74SHong Zhang 
749814e85d6SHong Zhang /* --------------------------- Adjoint sensitivity ---------------------------*/
750814e85d6SHong Zhang 
751814e85d6SHong Zhang /*@
752814e85d6SHong 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
753814e85d6SHong Zhang       for use by the TSAdjoint routines.
754814e85d6SHong Zhang 
755d083f849SBarry Smith    Logically Collective on TS
756814e85d6SHong Zhang 
757814e85d6SHong Zhang    Input Parameters:
758814e85d6SHong Zhang +  ts - the TS context obtained from TSCreate()
759d2fd7bfcSHong Zhang .  numcost - number of gradients to be computed, this is the number of cost functions
760814e85d6SHong 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
761814e85d6SHong Zhang -  mu - gradients with respect to the parameters, the number of entries in these vectors is the same as the number of parameters
762814e85d6SHong Zhang 
763814e85d6SHong Zhang    Level: beginner
764814e85d6SHong Zhang 
765814e85d6SHong Zhang    Notes:
766814e85d6SHong Zhang     the entries in these vectors must be correctly initialized with the values lamda_i = df/dy|finaltime  mu_i = df/dp|finaltime
767814e85d6SHong Zhang 
768814e85d6SHong Zhang    After TSAdjointSolve() is called the lamba and the mu contain the computed sensitivities
769814e85d6SHong Zhang 
770db781477SPatrick Sanan .seealso `TSGetCostGradients()`
771814e85d6SHong Zhang @*/
772814e85d6SHong Zhang PetscErrorCode TSSetCostGradients(TS ts,PetscInt numcost,Vec *lambda,Vec *mu)
773814e85d6SHong Zhang {
774814e85d6SHong Zhang   PetscFunctionBegin;
775814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
776064a246eSJacob Faibussowitsch   PetscValidPointer(lambda,3);
777814e85d6SHong Zhang   ts->vecs_sensi  = lambda;
778814e85d6SHong Zhang   ts->vecs_sensip = mu;
7793c633725SBarry Smith   PetscCheck(!ts->numcost || ts->numcost == numcost,PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"The number of cost functions (2nd parameter of TSSetCostIntegrand()) is inconsistent with the one set by TSSetCostIntegrand");
780814e85d6SHong Zhang   ts->numcost  = numcost;
781814e85d6SHong Zhang   PetscFunctionReturn(0);
782814e85d6SHong Zhang }
783814e85d6SHong Zhang 
784814e85d6SHong Zhang /*@
785814e85d6SHong Zhang    TSGetCostGradients - Returns the gradients from the TSAdjointSolve()
786814e85d6SHong Zhang 
787814e85d6SHong Zhang    Not Collective, but Vec returned is parallel if TS is parallel
788814e85d6SHong Zhang 
789814e85d6SHong Zhang    Input Parameter:
790814e85d6SHong Zhang .  ts - the TS context obtained from TSCreate()
791814e85d6SHong Zhang 
792d8d19677SJose E. Roman    Output Parameters:
7936b867d5aSJose E. Roman +  numcost - size of returned arrays
7946b867d5aSJose E. Roman .  lambda - vectors containing the gradients of the cost functions with respect to the ODE/DAE solution variables
795814e85d6SHong Zhang -  mu - vectors containing the gradients of the cost functions with respect to the problem parameters
796814e85d6SHong Zhang 
797814e85d6SHong Zhang    Level: intermediate
798814e85d6SHong Zhang 
799db781477SPatrick Sanan .seealso: `TSSetCostGradients()`
800814e85d6SHong Zhang @*/
801814e85d6SHong Zhang PetscErrorCode TSGetCostGradients(TS ts,PetscInt *numcost,Vec **lambda,Vec **mu)
802814e85d6SHong Zhang {
803814e85d6SHong Zhang   PetscFunctionBegin;
804814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
805814e85d6SHong Zhang   if (numcost) *numcost = ts->numcost;
806814e85d6SHong Zhang   if (lambda)  *lambda  = ts->vecs_sensi;
807814e85d6SHong Zhang   if (mu)      *mu      = ts->vecs_sensip;
808814e85d6SHong Zhang   PetscFunctionReturn(0);
809814e85d6SHong Zhang }
810814e85d6SHong Zhang 
811814e85d6SHong Zhang /*@
812b5b4017aSHong 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
813b5b4017aSHong Zhang       for use by the TSAdjoint routines.
814b5b4017aSHong Zhang 
815d083f849SBarry Smith    Logically Collective on TS
816b5b4017aSHong Zhang 
817b5b4017aSHong Zhang    Input Parameters:
818b5b4017aSHong Zhang +  ts - the TS context obtained from TSCreate()
819b5b4017aSHong Zhang .  numcost - number of cost functions
820b5b4017aSHong 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
821b5b4017aSHong 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
822b5b4017aSHong Zhang -  dir - the direction vector that are multiplied with the Hessian of the cost functions
823b5b4017aSHong Zhang 
824b5b4017aSHong Zhang    Level: beginner
825b5b4017aSHong Zhang 
826b5b4017aSHong Zhang    Notes: Hessian of the cost function is completely different from Hessian of the ODE/DAE system
827b5b4017aSHong Zhang 
828ecf68647SHong Zhang    For second-order adjoint, one needs to call this function and then TSAdjointSetForward() before TSSolve().
829b5b4017aSHong Zhang 
830b5b4017aSHong 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.
831b5b4017aSHong Zhang 
8323fca9621SHong Zhang    Passing NULL for lambda2 disables the second-order calculation.
833db781477SPatrick Sanan .seealso: `TSAdjointSetForward()`
834b5b4017aSHong Zhang @*/
835b5b4017aSHong Zhang PetscErrorCode TSSetCostHessianProducts(TS ts,PetscInt numcost,Vec *lambda2,Vec *mu2,Vec dir)
836b5b4017aSHong Zhang {
837b5b4017aSHong Zhang   PetscFunctionBegin;
838b5b4017aSHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
8393c633725SBarry Smith   PetscCheck(!ts->numcost || ts->numcost == numcost,PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"The number of cost functions (2nd parameter of TSSetCostIntegrand()) is inconsistent with the one set by TSSetCostIntegrand");
840b5b4017aSHong Zhang   ts->numcost       = numcost;
841b5b4017aSHong Zhang   ts->vecs_sensi2   = lambda2;
84233f72c5dSHong Zhang   ts->vecs_sensi2p  = mu2;
843b5b4017aSHong Zhang   ts->vec_dir       = dir;
844b5b4017aSHong Zhang   PetscFunctionReturn(0);
845b5b4017aSHong Zhang }
846b5b4017aSHong Zhang 
847b5b4017aSHong Zhang /*@
848b5b4017aSHong Zhang    TSGetCostHessianProducts - Returns the gradients from the TSAdjointSolve()
849b5b4017aSHong Zhang 
850b5b4017aSHong Zhang    Not Collective, but Vec returned is parallel if TS is parallel
851b5b4017aSHong Zhang 
852b5b4017aSHong Zhang    Input Parameter:
853b5b4017aSHong Zhang .  ts - the TS context obtained from TSCreate()
854b5b4017aSHong Zhang 
855d8d19677SJose E. Roman    Output Parameters:
856b5b4017aSHong Zhang +  numcost - number of cost functions
857b5b4017aSHong 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
858b5b4017aSHong 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
859b5b4017aSHong Zhang -  dir - the direction vector that are multiplied with the Hessian of the cost functions
860b5b4017aSHong Zhang 
861b5b4017aSHong Zhang    Level: intermediate
862b5b4017aSHong Zhang 
863db781477SPatrick Sanan .seealso: `TSSetCostHessianProducts()`
864b5b4017aSHong Zhang @*/
865b5b4017aSHong Zhang PetscErrorCode TSGetCostHessianProducts(TS ts,PetscInt *numcost,Vec **lambda2,Vec **mu2, Vec *dir)
866b5b4017aSHong Zhang {
867b5b4017aSHong Zhang   PetscFunctionBegin;
868b5b4017aSHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
869b5b4017aSHong Zhang   if (numcost) *numcost = ts->numcost;
870b5b4017aSHong Zhang   if (lambda2) *lambda2 = ts->vecs_sensi2;
87133f72c5dSHong Zhang   if (mu2)     *mu2     = ts->vecs_sensi2p;
872b5b4017aSHong Zhang   if (dir)     *dir     = ts->vec_dir;
873b5b4017aSHong Zhang   PetscFunctionReturn(0);
874b5b4017aSHong Zhang }
875b5b4017aSHong Zhang 
876b5b4017aSHong Zhang /*@
877ecf68647SHong Zhang   TSAdjointSetForward - Trigger the tangent linear solver and initialize the forward sensitivities
878b5b4017aSHong Zhang 
879d083f849SBarry Smith   Logically Collective on TS
880b5b4017aSHong Zhang 
881b5b4017aSHong Zhang   Input Parameters:
882b5b4017aSHong Zhang +  ts - the TS context obtained from TSCreate()
883b5b4017aSHong Zhang -  didp - the derivative of initial values w.r.t. parameters
884b5b4017aSHong Zhang 
885b5b4017aSHong Zhang   Level: intermediate
886b5b4017aSHong Zhang 
887ecf68647SHong 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. TSAdjoint does not reset the tangent linear solver automatically, TSAdjointResetForward() should be called to reset the tangent linear solver.
888b5b4017aSHong Zhang 
889db781477SPatrick Sanan .seealso: `TSSetCostHessianProducts()`, `TSAdjointResetForward()`
890b5b4017aSHong Zhang @*/
891ecf68647SHong Zhang PetscErrorCode TSAdjointSetForward(TS ts,Mat didp)
892b5b4017aSHong Zhang {
89333f72c5dSHong Zhang   Mat            A;
89433f72c5dSHong Zhang   Vec            sp;
89533f72c5dSHong Zhang   PetscScalar    *xarr;
89633f72c5dSHong Zhang   PetscInt       lsize;
897b5b4017aSHong Zhang 
898b5b4017aSHong Zhang   PetscFunctionBegin;
899b5b4017aSHong Zhang   ts->forward_solve = PETSC_TRUE; /* turn on tangent linear mode */
9003c633725SBarry Smith   PetscCheck(ts->vecs_sensi2,PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Must call TSSetCostHessianProducts() first");
9013c633725SBarry Smith   PetscCheck(ts->vec_dir,PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Directional vector is missing. Call TSSetCostHessianProducts() to set it.");
90233f72c5dSHong Zhang   /* create a single-column dense matrix */
9039566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(ts->vec_sol,&lsize));
9049566063dSJacob Faibussowitsch   PetscCall(MatCreateDense(PetscObjectComm((PetscObject)ts),lsize,PETSC_DECIDE,PETSC_DECIDE,1,NULL,&A));
90533f72c5dSHong Zhang 
9069566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(ts->vec_sol,&sp));
9079566063dSJacob Faibussowitsch   PetscCall(MatDenseGetColumn(A,0,&xarr));
9089566063dSJacob Faibussowitsch   PetscCall(VecPlaceArray(sp,xarr));
909ecf68647SHong Zhang   if (ts->vecs_sensi2p) { /* tangent linear variable initialized as 2*dIdP*dir */
91033f72c5dSHong Zhang     if (didp) {
9119566063dSJacob Faibussowitsch       PetscCall(MatMult(didp,ts->vec_dir,sp));
9129566063dSJacob Faibussowitsch       PetscCall(VecScale(sp,2.));
91333f72c5dSHong Zhang     } else {
9149566063dSJacob Faibussowitsch       PetscCall(VecZeroEntries(sp));
91533f72c5dSHong Zhang     }
916ecf68647SHong Zhang   } else { /* tangent linear variable initialized as dir */
9179566063dSJacob Faibussowitsch     PetscCall(VecCopy(ts->vec_dir,sp));
91833f72c5dSHong Zhang   }
9199566063dSJacob Faibussowitsch   PetscCall(VecResetArray(sp));
9209566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreColumn(A,&xarr));
9219566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&sp));
92233f72c5dSHong Zhang 
9239566063dSJacob Faibussowitsch   PetscCall(TSForwardSetInitialSensitivities(ts,A)); /* if didp is NULL, identity matrix is assumed */
92433f72c5dSHong Zhang 
9259566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&A));
926b5b4017aSHong Zhang   PetscFunctionReturn(0);
927b5b4017aSHong Zhang }
928b5b4017aSHong Zhang 
929b5b4017aSHong Zhang /*@
930ecf68647SHong Zhang   TSAdjointResetForward - Reset the tangent linear solver and destroy the tangent linear context
931ecf68647SHong Zhang 
932d083f849SBarry Smith   Logically Collective on TS
933ecf68647SHong Zhang 
934ecf68647SHong Zhang   Input Parameters:
935ecf68647SHong Zhang .  ts - the TS context obtained from TSCreate()
936ecf68647SHong Zhang 
937ecf68647SHong Zhang   Level: intermediate
938ecf68647SHong Zhang 
939db781477SPatrick Sanan .seealso: `TSAdjointSetForward()`
940ecf68647SHong Zhang @*/
941ecf68647SHong Zhang PetscErrorCode TSAdjointResetForward(TS ts)
942ecf68647SHong Zhang {
943ecf68647SHong Zhang   PetscFunctionBegin;
944ecf68647SHong Zhang   ts->forward_solve = PETSC_FALSE; /* turn off tangent linear mode */
9459566063dSJacob Faibussowitsch   PetscCall(TSForwardReset(ts));
946ecf68647SHong Zhang   PetscFunctionReturn(0);
947ecf68647SHong Zhang }
948ecf68647SHong Zhang 
949ecf68647SHong Zhang /*@
950814e85d6SHong Zhang    TSAdjointSetUp - Sets up the internal data structures for the later use
951814e85d6SHong Zhang    of an adjoint solver
952814e85d6SHong Zhang 
953814e85d6SHong Zhang    Collective on TS
954814e85d6SHong Zhang 
955814e85d6SHong Zhang    Input Parameter:
956814e85d6SHong Zhang .  ts - the TS context obtained from TSCreate()
957814e85d6SHong Zhang 
958814e85d6SHong Zhang    Level: advanced
959814e85d6SHong Zhang 
960db781477SPatrick Sanan .seealso: `TSCreate()`, `TSAdjointStep()`, `TSSetCostGradients()`
961814e85d6SHong Zhang @*/
962814e85d6SHong Zhang PetscErrorCode TSAdjointSetUp(TS ts)
963814e85d6SHong Zhang {
964881c1a9bSHong Zhang   TSTrajectory     tj;
965881c1a9bSHong Zhang   PetscBool        match;
966814e85d6SHong Zhang 
967814e85d6SHong Zhang   PetscFunctionBegin;
968814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
969814e85d6SHong Zhang   if (ts->adjointsetupcalled) PetscFunctionReturn(0);
9703c633725SBarry Smith   PetscCheck(ts->vecs_sensi,PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONGSTATE,"Must call TSSetCostGradients() first");
9713c633725SBarry Smith   PetscCheck(!ts->vecs_sensip || ts->Jacp || ts->Jacprhs,PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONGSTATE,"Must call TSSetRHSJacobianP() or TSSetIJacobianP() first");
9729566063dSJacob Faibussowitsch   PetscCall(TSGetTrajectory(ts,&tj));
9739566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)tj,TSTRAJECTORYBASIC,&match));
974881c1a9bSHong Zhang   if (match) {
975881c1a9bSHong Zhang     PetscBool solution_only;
9769566063dSJacob Faibussowitsch     PetscCall(TSTrajectoryGetSolutionOnly(tj,&solution_only));
9773c633725SBarry Smith     PetscCheck(!solution_only,PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"TSAdjoint cannot use the solution-only mode when choosing the Basic TSTrajectory type. Turn it off with -ts_trajectory_solution_only 0");
978881c1a9bSHong Zhang   }
9799566063dSJacob Faibussowitsch   PetscCall(TSTrajectorySetUseHistory(tj,PETSC_FALSE)); /* not use TSHistory */
98033f72c5dSHong Zhang 
981cd4cee2dSHong Zhang   if (ts->quadraturets) { /* if there is integral in the cost function */
9829566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(ts->vecs_sensi[0],&ts->vec_drdu_col));
983814e85d6SHong Zhang     if (ts->vecs_sensip) {
9849566063dSJacob Faibussowitsch       PetscCall(VecDuplicate(ts->vecs_sensip[0],&ts->vec_drdp_col));
985814e85d6SHong Zhang     }
986814e85d6SHong Zhang   }
987814e85d6SHong Zhang 
988*dbbe0bcdSBarry Smith   PetscTryTypeMethod(ts,adjointsetup);
989814e85d6SHong Zhang   ts->adjointsetupcalled = PETSC_TRUE;
990814e85d6SHong Zhang   PetscFunctionReturn(0);
991814e85d6SHong Zhang }
992814e85d6SHong Zhang 
993814e85d6SHong Zhang /*@
994ece46509SHong Zhang    TSAdjointReset - Resets a TSAdjoint context and removes any allocated Vecs and Mats.
995ece46509SHong Zhang 
996ece46509SHong Zhang    Collective on TS
997ece46509SHong Zhang 
998ece46509SHong Zhang    Input Parameter:
999ece46509SHong Zhang .  ts - the TS context obtained from TSCreate()
1000ece46509SHong Zhang 
1001ece46509SHong Zhang    Level: beginner
1002ece46509SHong Zhang 
1003db781477SPatrick Sanan .seealso: `TSCreate()`, `TSAdjointSetUp()`, `TSADestroy()`
1004ece46509SHong Zhang @*/
1005ece46509SHong Zhang PetscErrorCode TSAdjointReset(TS ts)
1006ece46509SHong Zhang {
1007ece46509SHong Zhang   PetscFunctionBegin;
1008ece46509SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1009*dbbe0bcdSBarry Smith   PetscTryTypeMethod(ts,adjointreset);
10107207e0fdSHong Zhang   if (ts->quadraturets) { /* if there is integral in the cost function */
10119566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&ts->vec_drdu_col));
10127207e0fdSHong Zhang     if (ts->vecs_sensip) {
10139566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&ts->vec_drdp_col));
10147207e0fdSHong Zhang     }
10157207e0fdSHong Zhang   }
1016ece46509SHong Zhang   ts->vecs_sensi         = NULL;
1017ece46509SHong Zhang   ts->vecs_sensip        = NULL;
1018ece46509SHong Zhang   ts->vecs_sensi2        = NULL;
101933f72c5dSHong Zhang   ts->vecs_sensi2p       = NULL;
1020ece46509SHong Zhang   ts->vec_dir            = NULL;
1021ece46509SHong Zhang   ts->adjointsetupcalled = PETSC_FALSE;
1022ece46509SHong Zhang   PetscFunctionReturn(0);
1023ece46509SHong Zhang }
1024ece46509SHong Zhang 
1025ece46509SHong Zhang /*@
1026814e85d6SHong Zhang    TSAdjointSetSteps - Sets the number of steps the adjoint solver should take backward in time
1027814e85d6SHong Zhang 
1028814e85d6SHong Zhang    Logically Collective on TS
1029814e85d6SHong Zhang 
1030814e85d6SHong Zhang    Input Parameters:
1031814e85d6SHong Zhang +  ts - the TS context obtained from TSCreate()
1032a2b725a8SWilliam Gropp -  steps - number of steps to use
1033814e85d6SHong Zhang 
1034814e85d6SHong Zhang    Level: intermediate
1035814e85d6SHong Zhang 
1036814e85d6SHong Zhang    Notes:
1037814e85d6SHong Zhang     Normally one does not call this and TSAdjointSolve() integrates back to the original timestep. One can call this
1038814e85d6SHong Zhang           so as to integrate back to less than the original timestep
1039814e85d6SHong Zhang 
1040db781477SPatrick Sanan .seealso: `TSSetExactFinalTime()`
1041814e85d6SHong Zhang @*/
1042814e85d6SHong Zhang PetscErrorCode TSAdjointSetSteps(TS ts,PetscInt steps)
1043814e85d6SHong Zhang {
1044814e85d6SHong Zhang   PetscFunctionBegin;
1045814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1046814e85d6SHong Zhang   PetscValidLogicalCollectiveInt(ts,steps,2);
10473c633725SBarry Smith   PetscCheck(steps >= 0,PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Cannot step back a negative number of steps");
10483c633725SBarry Smith   PetscCheck(steps <= ts->steps,PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Cannot step back more than the total number of forward steps");
1049814e85d6SHong Zhang   ts->adjoint_max_steps = steps;
1050814e85d6SHong Zhang   PetscFunctionReturn(0);
1051814e85d6SHong Zhang }
1052814e85d6SHong Zhang 
1053814e85d6SHong Zhang /*@C
1054814e85d6SHong Zhang   TSAdjointSetRHSJacobian - Deprecated, use TSSetRHSJacobianP()
1055814e85d6SHong Zhang 
1056814e85d6SHong Zhang   Level: deprecated
1057814e85d6SHong Zhang 
1058814e85d6SHong Zhang @*/
1059814e85d6SHong Zhang PetscErrorCode TSAdjointSetRHSJacobian(TS ts,Mat Amat,PetscErrorCode (*func)(TS,PetscReal,Vec,Mat,void*),void *ctx)
1060814e85d6SHong Zhang {
1061814e85d6SHong Zhang   PetscFunctionBegin;
1062814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
1063814e85d6SHong Zhang   PetscValidHeaderSpecific(Amat,MAT_CLASSID,2);
1064814e85d6SHong Zhang 
1065814e85d6SHong Zhang   ts->rhsjacobianp    = func;
1066814e85d6SHong Zhang   ts->rhsjacobianpctx = ctx;
1067814e85d6SHong Zhang   if (Amat) {
10689566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)Amat));
10699566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&ts->Jacp));
1070814e85d6SHong Zhang     ts->Jacp = Amat;
1071814e85d6SHong Zhang   }
1072814e85d6SHong Zhang   PetscFunctionReturn(0);
1073814e85d6SHong Zhang }
1074814e85d6SHong Zhang 
1075814e85d6SHong Zhang /*@C
1076814e85d6SHong Zhang   TSAdjointComputeRHSJacobian - Deprecated, use TSComputeRHSJacobianP()
1077814e85d6SHong Zhang 
1078814e85d6SHong Zhang   Level: deprecated
1079814e85d6SHong Zhang 
1080814e85d6SHong Zhang @*/
1081c9ad9de0SHong Zhang PetscErrorCode TSAdjointComputeRHSJacobian(TS ts,PetscReal t,Vec U,Mat Amat)
1082814e85d6SHong Zhang {
1083814e85d6SHong Zhang   PetscFunctionBegin;
1084814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1085c9ad9de0SHong Zhang   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
1086814e85d6SHong Zhang   PetscValidPointer(Amat,4);
1087814e85d6SHong Zhang 
1088792fecdfSBarry Smith   PetscCallBack("TS callback JacobianP for sensitivity analysis",(*ts->rhsjacobianp)(ts,t,U,Amat,ts->rhsjacobianpctx));
1089814e85d6SHong Zhang   PetscFunctionReturn(0);
1090814e85d6SHong Zhang }
1091814e85d6SHong Zhang 
1092814e85d6SHong Zhang /*@
1093d76be551SHong Zhang   TSAdjointComputeDRDYFunction - Deprecated, use TSGetQuadratureTS() then TSComputeRHSJacobian()
1094814e85d6SHong Zhang 
1095814e85d6SHong Zhang   Level: deprecated
1096814e85d6SHong Zhang 
1097814e85d6SHong Zhang @*/
1098c9ad9de0SHong Zhang PetscErrorCode TSAdjointComputeDRDYFunction(TS ts,PetscReal t,Vec U,Vec *DRDU)
1099814e85d6SHong Zhang {
1100814e85d6SHong Zhang   PetscFunctionBegin;
1101814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1102c9ad9de0SHong Zhang   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
1103814e85d6SHong Zhang 
1104792fecdfSBarry Smith   PetscCallBack("TS callback DRDY for sensitivity analysis",(*ts->drdufunction)(ts,t,U,DRDU,ts->costintegrandctx));
1105814e85d6SHong Zhang   PetscFunctionReturn(0);
1106814e85d6SHong Zhang }
1107814e85d6SHong Zhang 
1108814e85d6SHong Zhang /*@
1109d76be551SHong Zhang   TSAdjointComputeDRDPFunction - Deprecated, use TSGetQuadratureTS() then TSComputeRHSJacobianP()
1110814e85d6SHong Zhang 
1111814e85d6SHong Zhang   Level: deprecated
1112814e85d6SHong Zhang 
1113814e85d6SHong Zhang @*/
1114c9ad9de0SHong Zhang PetscErrorCode TSAdjointComputeDRDPFunction(TS ts,PetscReal t,Vec U,Vec *DRDP)
1115814e85d6SHong Zhang {
1116814e85d6SHong Zhang   PetscFunctionBegin;
1117814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1118c9ad9de0SHong Zhang   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
1119814e85d6SHong Zhang 
1120792fecdfSBarry Smith   PetscCallBack("TS callback DRDP for sensitivity analysis",(*ts->drdpfunction)(ts,t,U,DRDP,ts->costintegrandctx));
1121814e85d6SHong Zhang   PetscFunctionReturn(0);
1122814e85d6SHong Zhang }
1123814e85d6SHong Zhang 
1124814e85d6SHong Zhang /*@C
1125814e85d6SHong Zhang    TSAdjointMonitorSensi - monitors the first lambda sensitivity
1126814e85d6SHong Zhang 
1127814e85d6SHong Zhang    Level: intermediate
1128814e85d6SHong Zhang 
1129db781477SPatrick Sanan .seealso: `TSAdjointMonitorSet()`
1130814e85d6SHong Zhang @*/
1131814e85d6SHong Zhang PetscErrorCode TSAdjointMonitorSensi(TS ts,PetscInt step,PetscReal ptime,Vec v,PetscInt numcost,Vec *lambda,Vec *mu,PetscViewerAndFormat *vf)
1132814e85d6SHong Zhang {
1133814e85d6SHong Zhang   PetscViewer    viewer = vf->viewer;
1134814e85d6SHong Zhang 
1135814e85d6SHong Zhang   PetscFunctionBegin;
1136064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,8);
11379566063dSJacob Faibussowitsch   PetscCall(PetscViewerPushFormat(viewer,vf->format));
11389566063dSJacob Faibussowitsch   PetscCall(VecView(lambda[0],viewer));
11399566063dSJacob Faibussowitsch   PetscCall(PetscViewerPopFormat(viewer));
1140814e85d6SHong Zhang   PetscFunctionReturn(0);
1141814e85d6SHong Zhang }
1142814e85d6SHong Zhang 
1143814e85d6SHong Zhang /*@C
1144814e85d6SHong Zhang    TSAdjointMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user
1145814e85d6SHong Zhang 
1146814e85d6SHong Zhang    Collective on TS
1147814e85d6SHong Zhang 
1148814e85d6SHong Zhang    Input Parameters:
1149814e85d6SHong Zhang +  ts - TS object you wish to monitor
1150814e85d6SHong Zhang .  name - the monitor type one is seeking
1151814e85d6SHong Zhang .  help - message indicating what monitoring is done
1152814e85d6SHong Zhang .  manual - manual page for the monitor
1153814e85d6SHong Zhang .  monitor - the monitor function
1154814e85d6SHong 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
1155814e85d6SHong Zhang 
1156814e85d6SHong Zhang    Level: developer
1157814e85d6SHong Zhang 
1158db781477SPatrick Sanan .seealso: `PetscOptionsGetViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
1159db781477SPatrick Sanan           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
1160db781477SPatrick Sanan           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, `PetscOptionsBool()`,
1161db781477SPatrick Sanan           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1162c2e3fba1SPatrick Sanan           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1163db781477SPatrick Sanan           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1164db781477SPatrick Sanan           `PetscOptionsFList()`, `PetscOptionsEList()`
1165814e85d6SHong Zhang @*/
1166814e85d6SHong 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*))
1167814e85d6SHong Zhang {
1168814e85d6SHong Zhang   PetscViewer       viewer;
1169814e85d6SHong Zhang   PetscViewerFormat format;
1170814e85d6SHong Zhang   PetscBool         flg;
1171814e85d6SHong Zhang 
1172814e85d6SHong Zhang   PetscFunctionBegin;
11739566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)ts),((PetscObject) ts)->options,((PetscObject)ts)->prefix,name,&viewer,&format,&flg));
1174814e85d6SHong Zhang   if (flg) {
1175814e85d6SHong Zhang     PetscViewerAndFormat *vf;
11769566063dSJacob Faibussowitsch     PetscCall(PetscViewerAndFormatCreate(viewer,format,&vf));
11779566063dSJacob Faibussowitsch     PetscCall(PetscObjectDereference((PetscObject)viewer));
11781baa6e33SBarry Smith     if (monitorsetup) PetscCall((*monitorsetup)(ts,vf));
11799566063dSJacob Faibussowitsch     PetscCall(TSAdjointMonitorSet(ts,(PetscErrorCode (*)(TS,PetscInt,PetscReal,Vec,PetscInt,Vec*,Vec*,void*))monitor,vf,(PetscErrorCode (*)(void**))PetscViewerAndFormatDestroy));
1180814e85d6SHong Zhang   }
1181814e85d6SHong Zhang   PetscFunctionReturn(0);
1182814e85d6SHong Zhang }
1183814e85d6SHong Zhang 
1184814e85d6SHong Zhang /*@C
1185814e85d6SHong Zhang    TSAdjointMonitorSet - Sets an ADDITIONAL function that is to be used at every
1186814e85d6SHong Zhang    timestep to display the iteration's  progress.
1187814e85d6SHong Zhang 
1188814e85d6SHong Zhang    Logically Collective on TS
1189814e85d6SHong Zhang 
1190814e85d6SHong Zhang    Input Parameters:
1191814e85d6SHong Zhang +  ts - the TS context obtained from TSCreate()
1192814e85d6SHong Zhang .  adjointmonitor - monitoring routine
1193814e85d6SHong Zhang .  adjointmctx - [optional] user-defined context for private data for the
1194814e85d6SHong Zhang              monitor routine (use NULL if no context is desired)
1195814e85d6SHong Zhang -  adjointmonitordestroy - [optional] routine that frees monitor context
1196814e85d6SHong Zhang           (may be NULL)
1197814e85d6SHong Zhang 
1198814e85d6SHong Zhang    Calling sequence of monitor:
1199814e85d6SHong Zhang $    int adjointmonitor(TS ts,PetscInt steps,PetscReal time,Vec u,PetscInt numcost,Vec *lambda, Vec *mu,void *adjointmctx)
1200814e85d6SHong Zhang 
1201814e85d6SHong Zhang +    ts - the TS context
1202814e85d6SHong 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
1203814e85d6SHong Zhang                                been interpolated to)
1204814e85d6SHong Zhang .    time - current time
1205814e85d6SHong Zhang .    u - current iterate
1206814e85d6SHong Zhang .    numcost - number of cost functionos
1207814e85d6SHong Zhang .    lambda - sensitivities to initial conditions
1208814e85d6SHong Zhang .    mu - sensitivities to parameters
1209814e85d6SHong Zhang -    adjointmctx - [optional] adjoint monitoring context
1210814e85d6SHong Zhang 
1211814e85d6SHong Zhang    Notes:
1212814e85d6SHong Zhang    This routine adds an additional monitor to the list of monitors that
1213814e85d6SHong Zhang    already has been loaded.
1214814e85d6SHong Zhang 
1215814e85d6SHong Zhang    Fortran Notes:
1216814e85d6SHong Zhang     Only a single monitor function can be set for each TS object
1217814e85d6SHong Zhang 
1218814e85d6SHong Zhang    Level: intermediate
1219814e85d6SHong Zhang 
1220db781477SPatrick Sanan .seealso: `TSAdjointMonitorCancel()`
1221814e85d6SHong Zhang @*/
1222814e85d6SHong Zhang PetscErrorCode TSAdjointMonitorSet(TS ts,PetscErrorCode (*adjointmonitor)(TS,PetscInt,PetscReal,Vec,PetscInt,Vec*,Vec*,void*),void *adjointmctx,PetscErrorCode (*adjointmdestroy)(void**))
1223814e85d6SHong Zhang {
1224814e85d6SHong Zhang   PetscInt       i;
1225814e85d6SHong Zhang   PetscBool      identical;
1226814e85d6SHong Zhang 
1227814e85d6SHong Zhang   PetscFunctionBegin;
1228814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1229814e85d6SHong Zhang   for (i=0; i<ts->numbermonitors;i++) {
12309566063dSJacob Faibussowitsch     PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))adjointmonitor,adjointmctx,adjointmdestroy,(PetscErrorCode (*)(void))ts->adjointmonitor[i],ts->adjointmonitorcontext[i],ts->adjointmonitordestroy[i],&identical));
1231814e85d6SHong Zhang     if (identical) PetscFunctionReturn(0);
1232814e85d6SHong Zhang   }
12333c633725SBarry Smith   PetscCheck(ts->numberadjointmonitors < MAXTSMONITORS,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Too many adjoint monitors set");
1234814e85d6SHong Zhang   ts->adjointmonitor[ts->numberadjointmonitors]          = adjointmonitor;
1235814e85d6SHong Zhang   ts->adjointmonitordestroy[ts->numberadjointmonitors]   = adjointmdestroy;
1236814e85d6SHong Zhang   ts->adjointmonitorcontext[ts->numberadjointmonitors++] = (void*)adjointmctx;
1237814e85d6SHong Zhang   PetscFunctionReturn(0);
1238814e85d6SHong Zhang }
1239814e85d6SHong Zhang 
1240814e85d6SHong Zhang /*@C
1241814e85d6SHong Zhang    TSAdjointMonitorCancel - Clears all the adjoint monitors that have been set on a time-step object.
1242814e85d6SHong Zhang 
1243814e85d6SHong Zhang    Logically Collective on TS
1244814e85d6SHong Zhang 
1245814e85d6SHong Zhang    Input Parameters:
1246814e85d6SHong Zhang .  ts - the TS context obtained from TSCreate()
1247814e85d6SHong Zhang 
1248814e85d6SHong Zhang    Notes:
1249814e85d6SHong Zhang    There is no way to remove a single, specific monitor.
1250814e85d6SHong Zhang 
1251814e85d6SHong Zhang    Level: intermediate
1252814e85d6SHong Zhang 
1253db781477SPatrick Sanan .seealso: `TSAdjointMonitorSet()`
1254814e85d6SHong Zhang @*/
1255814e85d6SHong Zhang PetscErrorCode TSAdjointMonitorCancel(TS ts)
1256814e85d6SHong Zhang {
1257814e85d6SHong Zhang   PetscInt       i;
1258814e85d6SHong Zhang 
1259814e85d6SHong Zhang   PetscFunctionBegin;
1260814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1261814e85d6SHong Zhang   for (i=0; i<ts->numberadjointmonitors; i++) {
1262814e85d6SHong Zhang     if (ts->adjointmonitordestroy[i]) {
12639566063dSJacob Faibussowitsch       PetscCall((*ts->adjointmonitordestroy[i])(&ts->adjointmonitorcontext[i]));
1264814e85d6SHong Zhang     }
1265814e85d6SHong Zhang   }
1266814e85d6SHong Zhang   ts->numberadjointmonitors = 0;
1267814e85d6SHong Zhang   PetscFunctionReturn(0);
1268814e85d6SHong Zhang }
1269814e85d6SHong Zhang 
1270814e85d6SHong Zhang /*@C
1271814e85d6SHong Zhang    TSAdjointMonitorDefault - the default monitor of adjoint computations
1272814e85d6SHong Zhang 
1273814e85d6SHong Zhang    Level: intermediate
1274814e85d6SHong Zhang 
1275db781477SPatrick Sanan .seealso: `TSAdjointMonitorSet()`
1276814e85d6SHong Zhang @*/
1277814e85d6SHong Zhang PetscErrorCode TSAdjointMonitorDefault(TS ts,PetscInt step,PetscReal ptime,Vec v,PetscInt numcost,Vec *lambda,Vec *mu,PetscViewerAndFormat *vf)
1278814e85d6SHong Zhang {
1279814e85d6SHong Zhang   PetscViewer    viewer = vf->viewer;
1280814e85d6SHong Zhang 
1281814e85d6SHong Zhang   PetscFunctionBegin;
1282064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,8);
12839566063dSJacob Faibussowitsch   PetscCall(PetscViewerPushFormat(viewer,vf->format));
12849566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIAddTab(viewer,((PetscObject)ts)->tablevel));
128563a3b9bcSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer,"%" PetscInt_FMT " TS dt %g time %g%s",step,(double)ts->time_step,(double)ptime,ts->steprollback ? " (r)\n" : "\n"));
12869566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISubtractTab(viewer,((PetscObject)ts)->tablevel));
12879566063dSJacob Faibussowitsch   PetscCall(PetscViewerPopFormat(viewer));
1288814e85d6SHong Zhang   PetscFunctionReturn(0);
1289814e85d6SHong Zhang }
1290814e85d6SHong Zhang 
1291814e85d6SHong Zhang /*@C
1292814e85d6SHong Zhang    TSAdjointMonitorDrawSensi - Monitors progress of the adjoint TS solvers by calling
1293814e85d6SHong Zhang    VecView() for the sensitivities to initial states at each timestep
1294814e85d6SHong Zhang 
1295814e85d6SHong Zhang    Collective on TS
1296814e85d6SHong Zhang 
1297814e85d6SHong Zhang    Input Parameters:
1298814e85d6SHong Zhang +  ts - the TS context
1299814e85d6SHong Zhang .  step - current time-step
1300814e85d6SHong Zhang .  ptime - current time
1301814e85d6SHong Zhang .  u - current state
1302814e85d6SHong Zhang .  numcost - number of cost functions
1303814e85d6SHong Zhang .  lambda - sensitivities to initial conditions
1304814e85d6SHong Zhang .  mu - sensitivities to parameters
1305814e85d6SHong Zhang -  dummy - either a viewer or NULL
1306814e85d6SHong Zhang 
1307814e85d6SHong Zhang    Level: intermediate
1308814e85d6SHong Zhang 
1309db781477SPatrick Sanan .seealso: `TSAdjointMonitorSet()`, `TSAdjointMonitorDefault()`, `VecView()`
1310814e85d6SHong Zhang @*/
1311814e85d6SHong Zhang PetscErrorCode TSAdjointMonitorDrawSensi(TS ts,PetscInt step,PetscReal ptime,Vec u,PetscInt numcost,Vec *lambda,Vec *mu,void *dummy)
1312814e85d6SHong Zhang {
1313814e85d6SHong Zhang   TSMonitorDrawCtx ictx = (TSMonitorDrawCtx)dummy;
1314814e85d6SHong Zhang   PetscDraw        draw;
1315814e85d6SHong Zhang   PetscReal        xl,yl,xr,yr,h;
1316814e85d6SHong Zhang   char             time[32];
1317814e85d6SHong Zhang 
1318814e85d6SHong Zhang   PetscFunctionBegin;
1319814e85d6SHong Zhang   if (!(((ictx->howoften > 0) && (!(step % ictx->howoften))) || ((ictx->howoften == -1) && ts->reason))) PetscFunctionReturn(0);
1320814e85d6SHong Zhang 
13219566063dSJacob Faibussowitsch   PetscCall(VecView(lambda[0],ictx->viewer));
13229566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(ictx->viewer,0,&draw));
13239566063dSJacob Faibussowitsch   PetscCall(PetscSNPrintf(time,32,"Timestep %d Time %g",(int)step,(double)ptime));
13249566063dSJacob Faibussowitsch   PetscCall(PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr));
1325814e85d6SHong Zhang   h    = yl + .95*(yr - yl);
13269566063dSJacob Faibussowitsch   PetscCall(PetscDrawStringCentered(draw,.5*(xl+xr),h,PETSC_DRAW_BLACK,time));
13279566063dSJacob Faibussowitsch   PetscCall(PetscDrawFlush(draw));
1328814e85d6SHong Zhang   PetscFunctionReturn(0);
1329814e85d6SHong Zhang }
1330814e85d6SHong Zhang 
1331814e85d6SHong Zhang /*
1332814e85d6SHong Zhang    TSAdjointSetFromOptions - Sets various TSAdjoint parameters from user options.
1333814e85d6SHong Zhang 
1334814e85d6SHong Zhang    Collective on TSAdjoint
1335814e85d6SHong Zhang 
1336814e85d6SHong Zhang    Input Parameter:
1337814e85d6SHong Zhang .  ts - the TS context
1338814e85d6SHong Zhang 
1339814e85d6SHong Zhang    Options Database Keys:
1340814e85d6SHong Zhang +  -ts_adjoint_solve <yes,no> After solving the ODE/DAE solve the adjoint problem (requires -ts_save_trajectory)
1341814e85d6SHong Zhang .  -ts_adjoint_monitor - print information at each adjoint time step
1342814e85d6SHong Zhang -  -ts_adjoint_monitor_draw_sensi - monitor the sensitivity of the first cost function wrt initial conditions (lambda[0]) graphically
1343814e85d6SHong Zhang 
1344814e85d6SHong Zhang    Level: developer
1345814e85d6SHong Zhang 
1346814e85d6SHong Zhang    Notes:
1347814e85d6SHong Zhang     This is not normally called directly by users
1348814e85d6SHong Zhang 
1349db781477SPatrick Sanan .seealso: `TSSetSaveTrajectory()`, `TSTrajectorySetUp()`
1350814e85d6SHong Zhang */
1351*dbbe0bcdSBarry Smith PetscErrorCode TSAdjointSetFromOptions(TS ts,PetscOptionItems *PetscOptionsObject)
1352814e85d6SHong Zhang {
1353814e85d6SHong Zhang   PetscBool      tflg,opt;
1354814e85d6SHong Zhang 
1355814e85d6SHong Zhang   PetscFunctionBegin;
1356*dbbe0bcdSBarry Smith   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1357d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject,"TS Adjoint options");
1358814e85d6SHong Zhang   tflg = ts->adjoint_solve ? PETSC_TRUE : PETSC_FALSE;
13599566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-ts_adjoint_solve","Solve the adjoint problem immediately after solving the forward problem","",tflg,&tflg,&opt));
1360814e85d6SHong Zhang   if (opt) {
13619566063dSJacob Faibussowitsch     PetscCall(TSSetSaveTrajectory(ts));
1362814e85d6SHong Zhang     ts->adjoint_solve = tflg;
1363814e85d6SHong Zhang   }
13649566063dSJacob Faibussowitsch   PetscCall(TSAdjointMonitorSetFromOptions(ts,"-ts_adjoint_monitor","Monitor adjoint timestep size","TSAdjointMonitorDefault",TSAdjointMonitorDefault,NULL));
13659566063dSJacob Faibussowitsch   PetscCall(TSAdjointMonitorSetFromOptions(ts,"-ts_adjoint_monitor_sensi","Monitor sensitivity in the adjoint computation","TSAdjointMonitorSensi",TSAdjointMonitorSensi,NULL));
1366814e85d6SHong Zhang   opt  = PETSC_FALSE;
13679566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-ts_adjoint_monitor_draw_sensi","Monitor adjoint sensitivities (lambda only) graphically","TSAdjointMonitorDrawSensi",&opt));
1368814e85d6SHong Zhang   if (opt) {
1369814e85d6SHong Zhang     TSMonitorDrawCtx ctx;
1370814e85d6SHong Zhang     PetscInt         howoften = 1;
1371814e85d6SHong Zhang 
13729566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-ts_adjoint_monitor_draw_sensi","Monitor adjoint sensitivities (lambda only) graphically","TSAdjointMonitorDrawSensi",howoften,&howoften,NULL));
13739566063dSJacob Faibussowitsch     PetscCall(TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts),NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,300,300,howoften,&ctx));
13749566063dSJacob Faibussowitsch     PetscCall(TSAdjointMonitorSet(ts,TSAdjointMonitorDrawSensi,ctx,(PetscErrorCode (*)(void**))TSMonitorDrawCtxDestroy));
1375814e85d6SHong Zhang   }
1376814e85d6SHong Zhang   PetscFunctionReturn(0);
1377814e85d6SHong Zhang }
1378814e85d6SHong Zhang 
1379814e85d6SHong Zhang /*@
1380814e85d6SHong Zhang    TSAdjointStep - Steps one time step backward in the adjoint run
1381814e85d6SHong Zhang 
1382814e85d6SHong Zhang    Collective on TS
1383814e85d6SHong Zhang 
1384814e85d6SHong Zhang    Input Parameter:
1385814e85d6SHong Zhang .  ts - the TS context obtained from TSCreate()
1386814e85d6SHong Zhang 
1387814e85d6SHong Zhang    Level: intermediate
1388814e85d6SHong Zhang 
1389db781477SPatrick Sanan .seealso: `TSAdjointSetUp()`, `TSAdjointSolve()`
1390814e85d6SHong Zhang @*/
1391814e85d6SHong Zhang PetscErrorCode TSAdjointStep(TS ts)
1392814e85d6SHong Zhang {
1393814e85d6SHong Zhang   DM               dm;
1394814e85d6SHong Zhang 
1395814e85d6SHong Zhang   PetscFunctionBegin;
1396814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
13979566063dSJacob Faibussowitsch   PetscCall(TSGetDM(ts,&dm));
13989566063dSJacob Faibussowitsch   PetscCall(TSAdjointSetUp(ts));
13997b0e2f17SHong Zhang   ts->steps--; /* must decrease the step index before the adjoint step is taken. */
1400814e85d6SHong Zhang 
1401814e85d6SHong Zhang   ts->reason = TS_CONVERGED_ITERATING;
1402814e85d6SHong Zhang   ts->ptime_prev = ts->ptime;
14039566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(TS_AdjointStep,ts,0,0,0));
1404*dbbe0bcdSBarry Smith   PetscUseTypeMethod(ts,adjointstep);
14059566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(TS_AdjointStep,ts,0,0,0));
14067b0e2f17SHong Zhang   ts->adjoint_steps++;
1407814e85d6SHong Zhang 
1408814e85d6SHong Zhang   if (ts->reason < 0) {
14093c633725SBarry Smith     PetscCheck(!ts->errorifstepfailed,PetscObjectComm((PetscObject)ts),PETSC_ERR_NOT_CONVERGED,"TSAdjointStep has failed due to %s",TSConvergedReasons[ts->reason]);
1410814e85d6SHong Zhang   } else if (!ts->reason) {
1411814e85d6SHong Zhang     if (ts->adjoint_steps >= ts->adjoint_max_steps) ts->reason = TS_CONVERGED_ITS;
1412814e85d6SHong Zhang   }
1413814e85d6SHong Zhang   PetscFunctionReturn(0);
1414814e85d6SHong Zhang }
1415814e85d6SHong Zhang 
1416814e85d6SHong Zhang /*@
1417814e85d6SHong Zhang    TSAdjointSolve - Solves the discrete ajoint problem for an ODE/DAE
1418814e85d6SHong Zhang 
1419814e85d6SHong Zhang    Collective on TS
1420814e85d6SHong Zhang 
1421814e85d6SHong Zhang    Input Parameter:
1422814e85d6SHong Zhang .  ts - the TS context obtained from TSCreate()
1423814e85d6SHong Zhang 
1424814e85d6SHong Zhang    Options Database:
1425814e85d6SHong Zhang . -ts_adjoint_view_solution <viewerinfo> - views the first gradient with respect to the initial values
1426814e85d6SHong Zhang 
1427814e85d6SHong Zhang    Level: intermediate
1428814e85d6SHong Zhang 
1429814e85d6SHong Zhang    Notes:
1430814e85d6SHong Zhang    This must be called after a call to TSSolve() that solves the forward problem
1431814e85d6SHong Zhang 
1432814e85d6SHong Zhang    By default this will integrate back to the initial time, one can use TSAdjointSetSteps() to step back to a later time
1433814e85d6SHong Zhang 
1434db781477SPatrick Sanan .seealso: `TSCreate()`, `TSSetCostGradients()`, `TSSetSolution()`, `TSAdjointStep()`
1435814e85d6SHong Zhang @*/
1436814e85d6SHong Zhang PetscErrorCode TSAdjointSolve(TS ts)
1437814e85d6SHong Zhang {
1438f1d62c27SHong Zhang   static PetscBool cite = PETSC_FALSE;
14397f59fb53SHong Zhang #if defined(TSADJOINT_STAGE)
14407f59fb53SHong Zhang   PetscLogStage  adjoint_stage;
14417f59fb53SHong Zhang #endif
1442814e85d6SHong Zhang 
1443814e85d6SHong Zhang   PetscFunctionBegin;
1444814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1445421b783aSHong Zhang   PetscCall(PetscCitationsRegister("@article{Zhang2022tsadjoint,\n"
1446421b783aSHong Zhang                                  "  title         = {{PETSc TSAdjoint: A Discrete Adjoint ODE Solver for First-Order and Second-Order Sensitivity Analysis}},\n"
1447f1d62c27SHong Zhang                                  "  author        = {Zhang, Hong and Constantinescu, Emil M.  and Smith, Barry F.},\n"
1448421b783aSHong Zhang                                  "  journal       = {SIAM Journal on Scientific Computing},\n"
1449421b783aSHong Zhang                                  "  volume        = {44},\n"
1450421b783aSHong Zhang                                  "  number        = {1},\n"
1451421b783aSHong Zhang                                  "  pages         = {C1-C24},\n"
1452421b783aSHong Zhang                                  "  doi           = {10.1137/21M140078X},\n"
1453421b783aSHong Zhang                                  "  year          = {2022}\n}\n",&cite));
14547f59fb53SHong Zhang #if defined(TSADJOINT_STAGE)
14559566063dSJacob Faibussowitsch   PetscCall(PetscLogStageRegister("TSAdjoint",&adjoint_stage));
14569566063dSJacob Faibussowitsch   PetscCall(PetscLogStagePush(adjoint_stage));
14577f59fb53SHong Zhang #endif
14589566063dSJacob Faibussowitsch   PetscCall(TSAdjointSetUp(ts));
1459814e85d6SHong Zhang 
1460814e85d6SHong Zhang   /* reset time step and iteration counters */
1461814e85d6SHong Zhang   ts->adjoint_steps     = 0;
1462814e85d6SHong Zhang   ts->ksp_its           = 0;
1463814e85d6SHong Zhang   ts->snes_its          = 0;
1464814e85d6SHong Zhang   ts->num_snes_failures = 0;
1465814e85d6SHong Zhang   ts->reject            = 0;
1466814e85d6SHong Zhang   ts->reason            = TS_CONVERGED_ITERATING;
1467814e85d6SHong Zhang 
1468814e85d6SHong Zhang   if (!ts->adjoint_max_steps) ts->adjoint_max_steps = ts->steps;
1469814e85d6SHong Zhang   if (ts->adjoint_steps >= ts->adjoint_max_steps) ts->reason = TS_CONVERGED_ITS;
1470814e85d6SHong Zhang 
1471814e85d6SHong Zhang   while (!ts->reason) {
14729566063dSJacob Faibussowitsch     PetscCall(TSTrajectoryGet(ts->trajectory,ts,ts->steps,&ts->ptime));
14739566063dSJacob Faibussowitsch     PetscCall(TSAdjointMonitor(ts,ts->steps,ts->ptime,ts->vec_sol,ts->numcost,ts->vecs_sensi,ts->vecs_sensip));
14749566063dSJacob Faibussowitsch     PetscCall(TSAdjointEventHandler(ts));
14759566063dSJacob Faibussowitsch     PetscCall(TSAdjointStep(ts));
1476cd4cee2dSHong Zhang     if ((ts->vec_costintegral || ts->quadraturets) && !ts->costintegralfwd) {
14779566063dSJacob Faibussowitsch       PetscCall(TSAdjointCostIntegral(ts));
1478814e85d6SHong Zhang     }
1479814e85d6SHong Zhang   }
1480bdbff044SHong Zhang   if (!ts->steps) {
14819566063dSJacob Faibussowitsch     PetscCall(TSTrajectoryGet(ts->trajectory,ts,ts->steps,&ts->ptime));
14829566063dSJacob Faibussowitsch     PetscCall(TSAdjointMonitor(ts,ts->steps,ts->ptime,ts->vec_sol,ts->numcost,ts->vecs_sensi,ts->vecs_sensip));
1483bdbff044SHong Zhang   }
1484814e85d6SHong Zhang   ts->solvetime = ts->ptime;
14859566063dSJacob Faibussowitsch   PetscCall(TSTrajectoryViewFromOptions(ts->trajectory,NULL,"-ts_trajectory_view"));
14869566063dSJacob Faibussowitsch   PetscCall(VecViewFromOptions(ts->vecs_sensi[0],(PetscObject) ts, "-ts_adjoint_view_solution"));
1487814e85d6SHong Zhang   ts->adjoint_max_steps = 0;
14887f59fb53SHong Zhang #if defined(TSADJOINT_STAGE)
14899566063dSJacob Faibussowitsch   PetscCall(PetscLogStagePop());
14907f59fb53SHong Zhang #endif
1491814e85d6SHong Zhang   PetscFunctionReturn(0);
1492814e85d6SHong Zhang }
1493814e85d6SHong Zhang 
1494814e85d6SHong Zhang /*@C
1495814e85d6SHong Zhang    TSAdjointMonitor - Runs all user-provided adjoint monitor routines set using TSAdjointMonitorSet()
1496814e85d6SHong Zhang 
1497814e85d6SHong Zhang    Collective on TS
1498814e85d6SHong Zhang 
1499814e85d6SHong Zhang    Input Parameters:
1500814e85d6SHong Zhang +  ts - time stepping context obtained from TSCreate()
1501814e85d6SHong Zhang .  step - step number that has just completed
1502814e85d6SHong Zhang .  ptime - model time of the state
1503814e85d6SHong Zhang .  u - state at the current model time
1504814e85d6SHong Zhang .  numcost - number of cost functions (dimension of lambda  or mu)
1505814e85d6SHong Zhang .  lambda - vectors containing the gradients of the cost functions with respect to the ODE/DAE solution variables
1506814e85d6SHong Zhang -  mu - vectors containing the gradients of the cost functions with respect to the problem parameters
1507814e85d6SHong Zhang 
1508814e85d6SHong Zhang    Notes:
1509814e85d6SHong Zhang    TSAdjointMonitor() is typically used automatically within the time stepping implementations.
1510814e85d6SHong Zhang    Users would almost never call this routine directly.
1511814e85d6SHong Zhang 
1512814e85d6SHong Zhang    Level: developer
1513814e85d6SHong Zhang 
1514814e85d6SHong Zhang @*/
1515814e85d6SHong Zhang PetscErrorCode TSAdjointMonitor(TS ts,PetscInt step,PetscReal ptime,Vec u,PetscInt numcost,Vec *lambda, Vec *mu)
1516814e85d6SHong Zhang {
1517814e85d6SHong Zhang   PetscInt       i,n = ts->numberadjointmonitors;
1518814e85d6SHong Zhang 
1519814e85d6SHong Zhang   PetscFunctionBegin;
1520814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1521814e85d6SHong Zhang   PetscValidHeaderSpecific(u,VEC_CLASSID,4);
15229566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(u));
1523814e85d6SHong Zhang   for (i=0; i<n; i++) {
15249566063dSJacob Faibussowitsch     PetscCall((*ts->adjointmonitor[i])(ts,step,ptime,u,numcost,lambda,mu,ts->adjointmonitorcontext[i]));
1525814e85d6SHong Zhang   }
15269566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(u));
1527814e85d6SHong Zhang   PetscFunctionReturn(0);
1528814e85d6SHong Zhang }
1529814e85d6SHong Zhang 
1530814e85d6SHong Zhang /*@
1531814e85d6SHong Zhang  TSAdjointCostIntegral - Evaluate the cost integral in the adjoint run.
1532814e85d6SHong Zhang 
1533814e85d6SHong Zhang  Collective on TS
1534814e85d6SHong Zhang 
15354165533cSJose E. Roman  Input Parameter:
1536814e85d6SHong Zhang  .  ts - time stepping context
1537814e85d6SHong Zhang 
1538814e85d6SHong Zhang  Level: advanced
1539814e85d6SHong Zhang 
1540814e85d6SHong Zhang  Notes:
1541814e85d6SHong Zhang  This function cannot be called until TSAdjointStep() has been completed.
1542814e85d6SHong Zhang 
1543db781477SPatrick Sanan  .seealso: `TSAdjointSolve()`, `TSAdjointStep`
1544814e85d6SHong Zhang  @*/
1545814e85d6SHong Zhang PetscErrorCode TSAdjointCostIntegral(TS ts)
1546814e85d6SHong Zhang {
1547362febeeSStefano Zampini   PetscFunctionBegin;
1548814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1549*dbbe0bcdSBarry Smith   PetscUseTypeMethod(ts,adjointintegral);
1550814e85d6SHong Zhang   PetscFunctionReturn(0);
1551814e85d6SHong Zhang }
1552814e85d6SHong Zhang 
1553814e85d6SHong Zhang /* ------------------ Forward (tangent linear) sensitivity  ------------------*/
1554814e85d6SHong Zhang 
1555814e85d6SHong Zhang /*@
1556814e85d6SHong Zhang   TSForwardSetUp - Sets up the internal data structures for the later use
1557814e85d6SHong Zhang   of forward sensitivity analysis
1558814e85d6SHong Zhang 
1559814e85d6SHong Zhang   Collective on TS
1560814e85d6SHong Zhang 
1561814e85d6SHong Zhang   Input Parameter:
1562814e85d6SHong Zhang . ts - the TS context obtained from TSCreate()
1563814e85d6SHong Zhang 
1564814e85d6SHong Zhang   Level: advanced
1565814e85d6SHong Zhang 
1566db781477SPatrick Sanan .seealso: `TSCreate()`, `TSDestroy()`, `TSSetUp()`
1567814e85d6SHong Zhang @*/
1568814e85d6SHong Zhang PetscErrorCode TSForwardSetUp(TS ts)
1569814e85d6SHong Zhang {
1570814e85d6SHong Zhang   PetscFunctionBegin;
1571814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1572814e85d6SHong Zhang   if (ts->forwardsetupcalled) PetscFunctionReturn(0);
1573*dbbe0bcdSBarry Smith   PetscTryTypeMethod(ts,forwardsetup);
15749566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(ts->vec_sol,&ts->vec_sensip_col));
1575814e85d6SHong Zhang   ts->forwardsetupcalled = PETSC_TRUE;
1576814e85d6SHong Zhang   PetscFunctionReturn(0);
1577814e85d6SHong Zhang }
1578814e85d6SHong Zhang 
1579814e85d6SHong Zhang /*@
15807adebddeSHong Zhang   TSForwardReset - Reset the internal data structures used by forward sensitivity analysis
15817adebddeSHong Zhang 
15827adebddeSHong Zhang   Collective on TS
15837adebddeSHong Zhang 
15847adebddeSHong Zhang   Input Parameter:
15857adebddeSHong Zhang . ts - the TS context obtained from TSCreate()
15867adebddeSHong Zhang 
15877adebddeSHong Zhang   Level: advanced
15887adebddeSHong Zhang 
1589db781477SPatrick Sanan .seealso: `TSCreate()`, `TSDestroy()`, `TSForwardSetUp()`
15907adebddeSHong Zhang @*/
15917adebddeSHong Zhang PetscErrorCode TSForwardReset(TS ts)
15927adebddeSHong Zhang {
15937207e0fdSHong Zhang   TS             quadts = ts->quadraturets;
15947adebddeSHong Zhang 
15957adebddeSHong Zhang   PetscFunctionBegin;
15967adebddeSHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1597*dbbe0bcdSBarry Smith   PetscTryTypeMethod(ts,forwardreset);
15989566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&ts->mat_sensip));
15997207e0fdSHong Zhang   if (quadts) {
16009566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&quadts->mat_sensip));
16017207e0fdSHong Zhang   }
16029566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&ts->vec_sensip_col));
16037adebddeSHong Zhang   ts->forward_solve      = PETSC_FALSE;
16047adebddeSHong Zhang   ts->forwardsetupcalled = PETSC_FALSE;
16057adebddeSHong Zhang   PetscFunctionReturn(0);
16067adebddeSHong Zhang }
16077adebddeSHong Zhang 
16087adebddeSHong Zhang /*@
1609814e85d6SHong Zhang   TSForwardSetIntegralGradients - Set the vectors holding forward sensitivities of the integral term.
1610814e85d6SHong Zhang 
1611d8d19677SJose E. Roman   Input Parameters:
1612a2b725a8SWilliam Gropp + ts - the TS context obtained from TSCreate()
1613814e85d6SHong Zhang . numfwdint - number of integrals
161467b8a455SSatish Balay - vp - the vectors containing the gradients for each integral w.r.t. parameters
1615814e85d6SHong Zhang 
16167207e0fdSHong Zhang   Level: deprecated
1617814e85d6SHong Zhang 
1618db781477SPatrick Sanan .seealso: `TSForwardGetSensitivities()`, `TSForwardSetIntegralGradients()`, `TSForwardGetIntegralGradients()`, `TSForwardStep()`
1619814e85d6SHong Zhang @*/
1620814e85d6SHong Zhang PetscErrorCode TSForwardSetIntegralGradients(TS ts,PetscInt numfwdint,Vec *vp)
1621814e85d6SHong Zhang {
1622814e85d6SHong Zhang   PetscFunctionBegin;
1623814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
16243c633725SBarry Smith   PetscCheck(!ts->numcost || ts->numcost == numfwdint,PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"The number of cost functions (2nd parameter of TSSetCostIntegrand()) is inconsistent with the one set by TSSetCostIntegrand()");
1625814e85d6SHong Zhang   if (!ts->numcost) ts->numcost = numfwdint;
1626814e85d6SHong Zhang 
1627814e85d6SHong Zhang   ts->vecs_integral_sensip = vp;
1628814e85d6SHong Zhang   PetscFunctionReturn(0);
1629814e85d6SHong Zhang }
1630814e85d6SHong Zhang 
1631814e85d6SHong Zhang /*@
1632814e85d6SHong Zhang   TSForwardGetIntegralGradients - Returns the forward sensitivities ofthe integral term.
1633814e85d6SHong Zhang 
1634814e85d6SHong Zhang   Input Parameter:
1635814e85d6SHong Zhang . ts - the TS context obtained from TSCreate()
1636814e85d6SHong Zhang 
1637814e85d6SHong Zhang   Output Parameter:
163867b8a455SSatish Balay . vp - the vectors containing the gradients for each integral w.r.t. parameters
1639814e85d6SHong Zhang 
16407207e0fdSHong Zhang   Level: deprecated
1641814e85d6SHong Zhang 
1642db781477SPatrick Sanan .seealso: `TSForwardSetSensitivities()`, `TSForwardSetIntegralGradients()`, `TSForwardGetIntegralGradients()`, `TSForwardStep()`
1643814e85d6SHong Zhang @*/
1644814e85d6SHong Zhang PetscErrorCode TSForwardGetIntegralGradients(TS ts,PetscInt *numfwdint,Vec **vp)
1645814e85d6SHong Zhang {
1646814e85d6SHong Zhang   PetscFunctionBegin;
1647814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1648814e85d6SHong Zhang   PetscValidPointer(vp,3);
1649814e85d6SHong Zhang   if (numfwdint) *numfwdint = ts->numcost;
1650814e85d6SHong Zhang   if (vp) *vp = ts->vecs_integral_sensip;
1651814e85d6SHong Zhang   PetscFunctionReturn(0);
1652814e85d6SHong Zhang }
1653814e85d6SHong Zhang 
1654814e85d6SHong Zhang /*@
1655814e85d6SHong Zhang   TSForwardStep - Compute the forward sensitivity for one time step.
1656814e85d6SHong Zhang 
1657814e85d6SHong Zhang   Collective on TS
1658814e85d6SHong Zhang 
16594165533cSJose E. Roman   Input Parameter:
1660814e85d6SHong Zhang . ts - time stepping context
1661814e85d6SHong Zhang 
1662814e85d6SHong Zhang   Level: advanced
1663814e85d6SHong Zhang 
1664814e85d6SHong Zhang   Notes:
1665814e85d6SHong Zhang   This function cannot be called until TSStep() has been completed.
1666814e85d6SHong Zhang 
1667db781477SPatrick Sanan .seealso: `TSForwardSetSensitivities()`, `TSForwardGetSensitivities()`, `TSForwardSetIntegralGradients()`, `TSForwardGetIntegralGradients()`, `TSForwardSetUp()`
1668814e85d6SHong Zhang @*/
1669814e85d6SHong Zhang PetscErrorCode TSForwardStep(TS ts)
1670814e85d6SHong Zhang {
1671362febeeSStefano Zampini   PetscFunctionBegin;
1672814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
16739566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(TS_ForwardStep,ts,0,0,0));
1674*dbbe0bcdSBarry Smith   PetscUseTypeMethod(ts,forwardstep);
16759566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(TS_ForwardStep,ts,0,0,0));
16763c633725SBarry Smith   PetscCheck(ts->reason >= 0 || !ts->errorifstepfailed,PetscObjectComm((PetscObject)ts),PETSC_ERR_NOT_CONVERGED,"TSFowardStep has failed due to %s",TSConvergedReasons[ts->reason]);
1677814e85d6SHong Zhang   PetscFunctionReturn(0);
1678814e85d6SHong Zhang }
1679814e85d6SHong Zhang 
1680814e85d6SHong Zhang /*@
1681814e85d6SHong Zhang   TSForwardSetSensitivities - Sets the initial value of the trajectory sensitivities of solution  w.r.t. the problem parameters and initial values.
1682814e85d6SHong Zhang 
1683d083f849SBarry Smith   Logically Collective on TS
1684814e85d6SHong Zhang 
1685814e85d6SHong Zhang   Input Parameters:
1686814e85d6SHong Zhang + ts - the TS context obtained from TSCreate()
1687814e85d6SHong Zhang . nump - number of parameters
1688814e85d6SHong Zhang - Smat - sensitivities with respect to the parameters, the number of entries in these vectors is the same as the number of parameters
1689814e85d6SHong Zhang 
1690814e85d6SHong Zhang   Level: beginner
1691814e85d6SHong Zhang 
1692814e85d6SHong Zhang   Notes:
1693814e85d6SHong Zhang   Forward sensitivity is also called 'trajectory sensitivity' in some fields such as power systems.
1694814e85d6SHong Zhang   This function turns on a flag to trigger TSSolve() to compute forward sensitivities automatically.
1695814e85d6SHong Zhang   You must call this function before TSSolve().
1696814e85d6SHong Zhang   The entries in the sensitivity matrix must be correctly initialized with the values S = dy/dp|startingtime.
1697814e85d6SHong Zhang 
1698db781477SPatrick Sanan .seealso: `TSForwardGetSensitivities()`, `TSForwardSetIntegralGradients()`, `TSForwardGetIntegralGradients()`, `TSForwardStep()`
1699814e85d6SHong Zhang @*/
1700814e85d6SHong Zhang PetscErrorCode TSForwardSetSensitivities(TS ts,PetscInt nump,Mat Smat)
1701814e85d6SHong Zhang {
1702814e85d6SHong Zhang   PetscFunctionBegin;
1703814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1704814e85d6SHong Zhang   PetscValidHeaderSpecific(Smat,MAT_CLASSID,3);
1705814e85d6SHong Zhang   ts->forward_solve  = PETSC_TRUE;
1706b5b4017aSHong Zhang   if (nump == PETSC_DEFAULT) {
17079566063dSJacob Faibussowitsch     PetscCall(MatGetSize(Smat,NULL,&ts->num_parameters));
1708b5b4017aSHong Zhang   } else ts->num_parameters = nump;
17099566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)Smat));
17109566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&ts->mat_sensip));
1711814e85d6SHong Zhang   ts->mat_sensip = Smat;
1712814e85d6SHong Zhang   PetscFunctionReturn(0);
1713814e85d6SHong Zhang }
1714814e85d6SHong Zhang 
1715814e85d6SHong Zhang /*@
1716814e85d6SHong Zhang   TSForwardGetSensitivities - Returns the trajectory sensitivities
1717814e85d6SHong Zhang 
1718814e85d6SHong Zhang   Not Collective, but Vec returned is parallel if TS is parallel
1719814e85d6SHong Zhang 
1720d8d19677SJose E. Roman   Output Parameters:
1721814e85d6SHong Zhang + ts - the TS context obtained from TSCreate()
1722814e85d6SHong Zhang . nump - number of parameters
1723814e85d6SHong Zhang - Smat - sensitivities with respect to the parameters, the number of entries in these vectors is the same as the number of parameters
1724814e85d6SHong Zhang 
1725814e85d6SHong Zhang   Level: intermediate
1726814e85d6SHong Zhang 
1727db781477SPatrick Sanan .seealso: `TSForwardSetSensitivities()`, `TSForwardSetIntegralGradients()`, `TSForwardGetIntegralGradients()`, `TSForwardStep()`
1728814e85d6SHong Zhang @*/
1729814e85d6SHong Zhang PetscErrorCode TSForwardGetSensitivities(TS ts,PetscInt *nump,Mat *Smat)
1730814e85d6SHong Zhang {
1731814e85d6SHong Zhang   PetscFunctionBegin;
1732814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1733814e85d6SHong Zhang   if (nump) *nump = ts->num_parameters;
1734814e85d6SHong Zhang   if (Smat) *Smat = ts->mat_sensip;
1735814e85d6SHong Zhang   PetscFunctionReturn(0);
1736814e85d6SHong Zhang }
1737814e85d6SHong Zhang 
1738814e85d6SHong Zhang /*@
1739814e85d6SHong Zhang    TSForwardCostIntegral - Evaluate the cost integral in the forward run.
1740814e85d6SHong Zhang 
1741814e85d6SHong Zhang    Collective on TS
1742814e85d6SHong Zhang 
17434165533cSJose E. Roman    Input Parameter:
1744814e85d6SHong Zhang .  ts - time stepping context
1745814e85d6SHong Zhang 
1746814e85d6SHong Zhang    Level: advanced
1747814e85d6SHong Zhang 
1748814e85d6SHong Zhang    Notes:
1749814e85d6SHong Zhang    This function cannot be called until TSStep() has been completed.
1750814e85d6SHong Zhang 
1751db781477SPatrick Sanan .seealso: `TSSolve()`, `TSAdjointCostIntegral()`
1752814e85d6SHong Zhang @*/
1753814e85d6SHong Zhang PetscErrorCode TSForwardCostIntegral(TS ts)
1754814e85d6SHong Zhang {
1755362febeeSStefano Zampini   PetscFunctionBegin;
1756814e85d6SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1757*dbbe0bcdSBarry Smith   PetscUseTypeMethod(ts,forwardintegral);
1758814e85d6SHong Zhang   PetscFunctionReturn(0);
1759814e85d6SHong Zhang }
1760b5b4017aSHong Zhang 
1761b5b4017aSHong Zhang /*@
1762b5b4017aSHong Zhang   TSForwardSetInitialSensitivities - Set initial values for tangent linear sensitivities
1763b5b4017aSHong Zhang 
1764d083f849SBarry Smith   Collective on TS
1765b5b4017aSHong Zhang 
1766d8d19677SJose E. Roman   Input Parameters:
1767b5b4017aSHong Zhang + ts - the TS context obtained from TSCreate()
1768b5b4017aSHong Zhang - didp - parametric sensitivities of the initial condition
1769b5b4017aSHong Zhang 
1770b5b4017aSHong Zhang   Level: intermediate
1771b5b4017aSHong Zhang 
1772b5b4017aSHong 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.
1773b5b4017aSHong Zhang 
1774db781477SPatrick Sanan .seealso: `TSForwardSetSensitivities()`
1775b5b4017aSHong Zhang @*/
1776b5b4017aSHong Zhang PetscErrorCode TSForwardSetInitialSensitivities(TS ts,Mat didp)
1777b5b4017aSHong Zhang {
1778362febeeSStefano Zampini   PetscFunctionBegin;
1779b5b4017aSHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1780b5b4017aSHong Zhang   PetscValidHeaderSpecific(didp,MAT_CLASSID,2);
1781b5b4017aSHong Zhang   if (!ts->mat_sensip) {
17829566063dSJacob Faibussowitsch     PetscCall(TSForwardSetSensitivities(ts,PETSC_DEFAULT,didp));
1783b5b4017aSHong Zhang   }
1784b5b4017aSHong Zhang   PetscFunctionReturn(0);
1785b5b4017aSHong Zhang }
17866affb6f8SHong Zhang 
17876affb6f8SHong Zhang /*@
17886affb6f8SHong Zhang    TSForwardGetStages - Get the number of stages and the tangent linear sensitivities at the intermediate stages
17896affb6f8SHong Zhang 
17906affb6f8SHong Zhang    Input Parameter:
17916affb6f8SHong Zhang .  ts - the TS context obtained from TSCreate()
17926affb6f8SHong Zhang 
17936affb6f8SHong Zhang    Output Parameters:
1794cd4cee2dSHong Zhang +  ns - number of stages
17956affb6f8SHong Zhang -  S - tangent linear sensitivities at the intermediate stages
17966affb6f8SHong Zhang 
17976affb6f8SHong Zhang    Level: advanced
17986affb6f8SHong Zhang 
17996affb6f8SHong Zhang @*/
18006affb6f8SHong Zhang PetscErrorCode TSForwardGetStages(TS ts,PetscInt *ns,Mat **S)
18016affb6f8SHong Zhang {
18026affb6f8SHong Zhang   PetscFunctionBegin;
18036affb6f8SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
18046affb6f8SHong Zhang 
18056affb6f8SHong Zhang   if (!ts->ops->getstages) *S=NULL;
1806*dbbe0bcdSBarry Smith   else PetscUseTypeMethod(ts,forwardgetstages ,ns,S);
18076affb6f8SHong Zhang   PetscFunctionReturn(0);
18086affb6f8SHong Zhang }
1809cd4cee2dSHong Zhang 
1810cd4cee2dSHong Zhang /*@
1811cd4cee2dSHong Zhang    TSCreateQuadratureTS - Create a sub-TS that evaluates integrals over time
1812cd4cee2dSHong Zhang 
1813d8d19677SJose E. Roman    Input Parameters:
1814cd4cee2dSHong Zhang +  ts - the TS context obtained from TSCreate()
1815cd4cee2dSHong Zhang -  fwd - flag indicating whether to evaluate cost integral in the forward run or the adjoint run
1816cd4cee2dSHong Zhang 
1817cd4cee2dSHong Zhang    Output Parameters:
1818cd4cee2dSHong Zhang .  quadts - the child TS context
1819cd4cee2dSHong Zhang 
1820cd4cee2dSHong Zhang    Level: intermediate
1821cd4cee2dSHong Zhang 
1822db781477SPatrick Sanan .seealso: `TSGetQuadratureTS()`
1823cd4cee2dSHong Zhang @*/
1824cd4cee2dSHong Zhang PetscErrorCode TSCreateQuadratureTS(TS ts,PetscBool fwd,TS *quadts)
1825cd4cee2dSHong Zhang {
1826cd4cee2dSHong Zhang   char prefix[128];
1827cd4cee2dSHong Zhang 
1828cd4cee2dSHong Zhang   PetscFunctionBegin;
1829cd4cee2dSHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1830064a246eSJacob Faibussowitsch   PetscValidPointer(quadts,3);
18319566063dSJacob Faibussowitsch   PetscCall(TSDestroy(&ts->quadraturets));
18329566063dSJacob Faibussowitsch   PetscCall(TSCreate(PetscObjectComm((PetscObject)ts),&ts->quadraturets));
18339566063dSJacob Faibussowitsch   PetscCall(PetscObjectIncrementTabLevel((PetscObject)ts->quadraturets,(PetscObject)ts,1));
18349566063dSJacob Faibussowitsch   PetscCall(PetscLogObjectParent((PetscObject)ts,(PetscObject)ts->quadraturets));
18359566063dSJacob Faibussowitsch   PetscCall(PetscSNPrintf(prefix,sizeof(prefix),"%squad_",((PetscObject)ts)->prefix ? ((PetscObject)ts)->prefix : ""));
18369566063dSJacob Faibussowitsch   PetscCall(TSSetOptionsPrefix(ts->quadraturets,prefix));
1837cd4cee2dSHong Zhang   *quadts = ts->quadraturets;
1838cd4cee2dSHong Zhang 
1839cd4cee2dSHong Zhang   if (ts->numcost) {
18409566063dSJacob Faibussowitsch     PetscCall(VecCreateSeq(PETSC_COMM_SELF,ts->numcost,&(*quadts)->vec_sol));
1841cd4cee2dSHong Zhang   } else {
18429566063dSJacob Faibussowitsch     PetscCall(VecCreateSeq(PETSC_COMM_SELF,1,&(*quadts)->vec_sol));
1843cd4cee2dSHong Zhang   }
1844cd4cee2dSHong Zhang   ts->costintegralfwd = fwd;
1845cd4cee2dSHong Zhang   PetscFunctionReturn(0);
1846cd4cee2dSHong Zhang }
1847cd4cee2dSHong Zhang 
1848cd4cee2dSHong Zhang /*@
1849cd4cee2dSHong Zhang    TSGetQuadratureTS - Return the sub-TS that evaluates integrals over time
1850cd4cee2dSHong Zhang 
1851cd4cee2dSHong Zhang    Input Parameter:
1852cd4cee2dSHong Zhang .  ts - the TS context obtained from TSCreate()
1853cd4cee2dSHong Zhang 
1854cd4cee2dSHong Zhang    Output Parameters:
1855cd4cee2dSHong Zhang +  fwd - flag indicating whether to evaluate cost integral in the forward run or the adjoint run
1856cd4cee2dSHong Zhang -  quadts - the child TS context
1857cd4cee2dSHong Zhang 
1858cd4cee2dSHong Zhang    Level: intermediate
1859cd4cee2dSHong Zhang 
1860db781477SPatrick Sanan .seealso: `TSCreateQuadratureTS()`
1861cd4cee2dSHong Zhang @*/
1862cd4cee2dSHong Zhang PetscErrorCode TSGetQuadratureTS(TS ts,PetscBool *fwd,TS *quadts)
1863cd4cee2dSHong Zhang {
1864cd4cee2dSHong Zhang   PetscFunctionBegin;
1865cd4cee2dSHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1866cd4cee2dSHong Zhang   if (fwd) *fwd = ts->costintegralfwd;
1867cd4cee2dSHong Zhang   if (quadts) *quadts = ts->quadraturets;
1868cd4cee2dSHong Zhang   PetscFunctionReturn(0);
1869cd4cee2dSHong Zhang }
1870ba0675f6SHong Zhang 
1871ba0675f6SHong Zhang /*@
1872ba0675f6SHong Zhang    TSComputeSNESJacobian - Compute the SNESJacobian
1873ba0675f6SHong Zhang 
1874ba0675f6SHong Zhang    Input Parameters:
1875ba0675f6SHong Zhang +  ts - the TS context obtained from TSCreate()
1876ba0675f6SHong Zhang -  x - state vector
1877ba0675f6SHong Zhang 
1878ba0675f6SHong Zhang    Output Parameters:
1879ba0675f6SHong Zhang +  J - Jacobian matrix
1880ba0675f6SHong Zhang -  Jpre - preconditioning matrix for J (may be same as J)
1881ba0675f6SHong Zhang 
1882ba0675f6SHong Zhang    Level: developer
1883ba0675f6SHong Zhang 
1884ba0675f6SHong Zhang    Notes:
1885ba0675f6SHong Zhang    Using SNES to compute the Jacobian enables finite differencing when TS Jacobian is not available.
1886ba0675f6SHong Zhang @*/
1887ba0675f6SHong Zhang PetscErrorCode TSComputeSNESJacobian(TS ts,Vec x,Mat J,Mat Jpre)
1888ba0675f6SHong Zhang {
1889ba0675f6SHong Zhang   SNES           snes = ts->snes;
1890ba0675f6SHong Zhang   PetscErrorCode (*jac)(SNES,Vec,Mat,Mat,void*) = NULL;
1891ba0675f6SHong Zhang 
1892ba0675f6SHong Zhang   PetscFunctionBegin;
1893ba0675f6SHong Zhang   /*
1894ba0675f6SHong Zhang     Unlike implicit methods, explicit methods do not have SNESMatFDColoring in the snes object
1895ba0675f6SHong Zhang     because SNESSolve() has not been called yet; so querying SNESMatFDColoring does not work for
1896ba0675f6SHong Zhang     explicit methods. Instead, we check the Jacobian compute function directly to determin if FD
1897ba0675f6SHong Zhang     coloring is used.
1898ba0675f6SHong Zhang   */
18999566063dSJacob Faibussowitsch   PetscCall(SNESGetJacobian(snes,NULL,NULL,&jac,NULL));
1900ba0675f6SHong Zhang   if (jac == SNESComputeJacobianDefaultColor) {
1901ba0675f6SHong Zhang     Vec f;
19029566063dSJacob Faibussowitsch     PetscCall(SNESSetSolution(snes,x));
19039566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes,&f,NULL,NULL));
1904ba0675f6SHong Zhang     /* Force MatFDColoringApply to evaluate the SNES residual function for the base vector */
19059566063dSJacob Faibussowitsch     PetscCall(SNESComputeFunction(snes,x,f));
1906ba0675f6SHong Zhang   }
19079566063dSJacob Faibussowitsch   PetscCall(SNESComputeJacobian(snes,x,J,Jpre));
1908ba0675f6SHong Zhang   PetscFunctionReturn(0);
1909ba0675f6SHong Zhang }
1910