xref: /petsc/src/ts/interface/sensitivity/tssen.c (revision a94f484e013b4585682eb702a2adcd35b3f289ab)
114d0ab18SJacob Faibussowitsch #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 
13c3339decSBarry Smith   Logically Collective
14814e85d6SHong Zhang 
15814e85d6SHong Zhang   Input Parameters:
16bcf0153eSBarry Smith + 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   Level: intermediate
22814e85d6SHong Zhang 
23bcf0153eSBarry Smith   Note:
2414d0ab18SJacob Faibussowitsch   `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`
25814e85d6SHong Zhang 
268434afd1SBarry Smith .seealso: [](ch_ts), `TS`, `TSRHSJacobianPFn`, `TSGetRHSJacobianP()`
27814e85d6SHong Zhang @*/
288434afd1SBarry Smith PetscErrorCode TSSetRHSJacobianP(TS ts, Mat Amat, TSRHSJacobianPFn *func, void *ctx)
29d71ae5a4SJacob Faibussowitsch {
30814e85d6SHong Zhang   PetscFunctionBegin;
31814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
32814e85d6SHong Zhang   PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2);
33814e85d6SHong Zhang 
34814e85d6SHong Zhang   ts->rhsjacobianp    = func;
35814e85d6SHong Zhang   ts->rhsjacobianpctx = ctx;
36814e85d6SHong Zhang   if (Amat) {
379566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)Amat));
389566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&ts->Jacprhs));
3933f72c5dSHong Zhang     ts->Jacprhs = Amat;
40814e85d6SHong Zhang   }
413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
42814e85d6SHong Zhang }
43814e85d6SHong Zhang 
44814e85d6SHong Zhang /*@C
45cd4cee2dSHong 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.
46cd4cee2dSHong Zhang 
47c3339decSBarry Smith   Logically Collective
48cd4cee2dSHong Zhang 
49f899ff85SJose E. Roman   Input Parameter:
50bcf0153eSBarry Smith . ts - `TS` context obtained from `TSCreate()`
51cd4cee2dSHong Zhang 
52cd4cee2dSHong Zhang   Output Parameters:
53cd4cee2dSHong Zhang + Amat - JacobianP matrix
54cd4cee2dSHong Zhang . func - function
55cd4cee2dSHong Zhang - ctx  - [optional] user-defined function context
56cd4cee2dSHong Zhang 
57cd4cee2dSHong Zhang   Level: intermediate
58cd4cee2dSHong Zhang 
59bcf0153eSBarry Smith   Note:
6014d0ab18SJacob Faibussowitsch   `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`
61cd4cee2dSHong Zhang 
628434afd1SBarry Smith .seealso: [](ch_ts), `TSSetRHSJacobianP()`, `TS`, `TSRHSJacobianPFn`
63cd4cee2dSHong Zhang @*/
648434afd1SBarry Smith PetscErrorCode TSGetRHSJacobianP(TS ts, Mat *Amat, TSRHSJacobianPFn **func, void **ctx)
65d71ae5a4SJacob Faibussowitsch {
66cd4cee2dSHong Zhang   PetscFunctionBegin;
67cd4cee2dSHong Zhang   if (func) *func = ts->rhsjacobianp;
68cd4cee2dSHong Zhang   if (ctx) *ctx = ts->rhsjacobianpctx;
69cd4cee2dSHong Zhang   if (Amat) *Amat = ts->Jacprhs;
703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
71cd4cee2dSHong Zhang }
72cd4cee2dSHong Zhang 
73cd4cee2dSHong Zhang /*@C
74814e85d6SHong Zhang   TSComputeRHSJacobianP - Runs the user-defined JacobianP function.
75814e85d6SHong Zhang 
76c3339decSBarry Smith   Collective
77814e85d6SHong Zhang 
78814e85d6SHong Zhang   Input Parameters:
792fe279fdSBarry Smith + ts - The `TS` context obtained from `TSCreate()`
802fe279fdSBarry Smith . t  - the time
812fe279fdSBarry Smith - U  - the solution at which to compute the Jacobian
822fe279fdSBarry Smith 
832fe279fdSBarry Smith   Output Parameter:
842fe279fdSBarry Smith . Amat - the computed Jacobian
85814e85d6SHong Zhang 
86814e85d6SHong Zhang   Level: developer
87814e85d6SHong Zhang 
881cc06b55SBarry Smith .seealso: [](ch_ts), `TSSetRHSJacobianP()`, `TS`
89814e85d6SHong Zhang @*/
90d71ae5a4SJacob Faibussowitsch PetscErrorCode TSComputeRHSJacobianP(TS ts, PetscReal t, Vec U, Mat Amat)
91d71ae5a4SJacob Faibussowitsch {
92814e85d6SHong Zhang   PetscFunctionBegin;
933ba16761SJacob Faibussowitsch   if (!Amat) PetscFunctionReturn(PETSC_SUCCESS);
94814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
95c9ad9de0SHong Zhang   PetscValidHeaderSpecific(U, VEC_CLASSID, 3);
96814e85d6SHong Zhang 
9780ab5e31SHong Zhang   if (ts->rhsjacobianp) PetscCallBack("TS callback JacobianP for sensitivity analysis", (*ts->rhsjacobianp)(ts, t, U, Amat, ts->rhsjacobianpctx));
9880ab5e31SHong Zhang   else {
9980ab5e31SHong Zhang     PetscBool assembled;
10080ab5e31SHong Zhang     PetscCall(MatZeroEntries(Amat));
10180ab5e31SHong Zhang     PetscCall(MatAssembled(Amat, &assembled));
10280ab5e31SHong Zhang     if (!assembled) {
10380ab5e31SHong Zhang       PetscCall(MatAssemblyBegin(Amat, MAT_FINAL_ASSEMBLY));
10480ab5e31SHong Zhang       PetscCall(MatAssemblyEnd(Amat, MAT_FINAL_ASSEMBLY));
10580ab5e31SHong Zhang     }
10680ab5e31SHong Zhang   }
1073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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 
113c3339decSBarry Smith   Logically Collective
11433f72c5dSHong Zhang 
11533f72c5dSHong Zhang   Input Parameters:
116bcf0153eSBarry Smith + 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 
12120f4b53cSBarry Smith   Calling sequence of `func`:
12214d0ab18SJacob Faibussowitsch + ts    - the `TS` context
12314d0ab18SJacob Faibussowitsch . 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 
132bcf0153eSBarry Smith   Note:
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 
1351cc06b55SBarry Smith .seealso: [](ch_ts), `TSSetRHSJacobianP()`, `TS`
13633f72c5dSHong Zhang @*/
13714d0ab18SJacob Faibussowitsch PetscErrorCode TSSetIJacobianP(TS ts, Mat Amat, PetscErrorCode (*func)(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal shift, Mat A, void *ctx), void *ctx)
138d71ae5a4SJacob Faibussowitsch {
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   }
1503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15133f72c5dSHong Zhang }
15233f72c5dSHong Zhang 
15333f72c5dSHong Zhang /*@C
15433f72c5dSHong Zhang   TSComputeIJacobianP - Runs the user-defined IJacobianP function.
15533f72c5dSHong Zhang 
156c3339decSBarry Smith   Collective
15733f72c5dSHong Zhang 
15833f72c5dSHong Zhang   Input Parameters:
159bcf0153eSBarry Smith + 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
16480ab5e31SHong Zhang - imex  - flag indicates if the method is IMEX so that the RHSJacobianP should be kept separate
16533f72c5dSHong Zhang 
1662fe279fdSBarry Smith   Output Parameter:
167b43aa488SJacob Faibussowitsch . Amat - Jacobian matrix
16833f72c5dSHong Zhang 
16933f72c5dSHong Zhang   Level: developer
17033f72c5dSHong Zhang 
1711cc06b55SBarry Smith .seealso: [](ch_ts), `TS`, `TSSetIJacobianP()`
17233f72c5dSHong Zhang @*/
173d71ae5a4SJacob Faibussowitsch PetscErrorCode TSComputeIJacobianP(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal shift, Mat Amat, PetscBool imex)
174d71ae5a4SJacob Faibussowitsch {
17533f72c5dSHong Zhang   PetscFunctionBegin;
1763ba16761SJacob Faibussowitsch   if (!Amat) PetscFunctionReturn(PETSC_SUCCESS);
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));
18248a46eb9SPierre Jolivet   if (ts->ijacobianp) PetscCallBack("TS callback JacobianP for sensitivity analysis", (*ts->ijacobianp)(ts, t, U, Udot, shift, Amat, ts->ijacobianpctx));
18333f72c5dSHong Zhang   if (imex) {
18433f72c5dSHong Zhang     if (!ts->ijacobianp) { /* system was written as Udot = G(t,U) */
18533f72c5dSHong Zhang       PetscBool assembled;
1869566063dSJacob Faibussowitsch       PetscCall(MatZeroEntries(Amat));
1879566063dSJacob Faibussowitsch       PetscCall(MatAssembled(Amat, &assembled));
18833f72c5dSHong Zhang       if (!assembled) {
1899566063dSJacob Faibussowitsch         PetscCall(MatAssemblyBegin(Amat, MAT_FINAL_ASSEMBLY));
1909566063dSJacob Faibussowitsch         PetscCall(MatAssemblyEnd(Amat, MAT_FINAL_ASSEMBLY));
19133f72c5dSHong Zhang       }
19233f72c5dSHong Zhang     }
19333f72c5dSHong Zhang   } else {
1941baa6e33SBarry Smith     if (ts->rhsjacobianp) PetscCall(TSComputeRHSJacobianP(ts, t, U, ts->Jacprhs));
19533f72c5dSHong Zhang     if (ts->Jacprhs == Amat) { /* No IJacobian, so we only have the RHS matrix */
1969566063dSJacob Faibussowitsch       PetscCall(MatScale(Amat, -1));
19733f72c5dSHong Zhang     } else if (ts->Jacprhs) { /* Both IJacobian and RHSJacobian */
19833f72c5dSHong Zhang       MatStructure axpy = DIFFERENT_NONZERO_PATTERN;
19933f72c5dSHong Zhang       if (!ts->ijacobianp) { /* No IJacobianp provided, but we have a separate RHS matrix */
2009566063dSJacob Faibussowitsch         PetscCall(MatZeroEntries(Amat));
20133f72c5dSHong Zhang       }
2029566063dSJacob Faibussowitsch       PetscCall(MatAXPY(Amat, -1, ts->Jacprhs, axpy));
20333f72c5dSHong Zhang     }
20433f72c5dSHong Zhang   }
2059566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(TS_JacobianPEval, ts, U, Amat, 0));
2063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20733f72c5dSHong Zhang }
20833f72c5dSHong Zhang 
20933f72c5dSHong Zhang /*@C
210814e85d6SHong Zhang   TSSetCostIntegrand - Sets the routine for evaluating the integral term in one or more cost functions
211814e85d6SHong Zhang 
212c3339decSBarry Smith   Logically Collective
213814e85d6SHong Zhang 
214814e85d6SHong Zhang   Input Parameters:
215bcf0153eSBarry Smith + ts           - the `TS` context obtained from `TSCreate()`
216814e85d6SHong Zhang . numcost      - number of gradients to be computed, this is the number of cost functions
217814e85d6SHong Zhang . costintegral - vector that stores the integral values
218814e85d6SHong Zhang . rf           - routine for evaluating the integrand function
2198847d985SBarry Smith . drduf        - function that computes the gradients of the r with respect to u
2208847d985SBarry Smith . drdpf        - function that computes the gradients of the r with respect to p, can be `NULL` if parametric sensitivity is not desired (`mu` = `NULL`)
221814e85d6SHong Zhang . fwd          - flag indicating whether to evaluate cost integral in the forward run or the adjoint run
2222fe279fdSBarry Smith - ctx          - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`)
223814e85d6SHong Zhang 
22420f4b53cSBarry Smith   Calling sequence of `rf`:
2258847d985SBarry Smith + ts  - the integrator
2268847d985SBarry Smith . t   - the time
2278847d985SBarry Smith . U   - the solution
2288847d985SBarry Smith . F   - the computed value of the function
2298847d985SBarry Smith - ctx - the user context
230814e85d6SHong Zhang 
23120f4b53cSBarry Smith   Calling sequence of `drduf`:
2328847d985SBarry Smith + ts   - the integrator
2338847d985SBarry Smith . t    - the time
2348847d985SBarry Smith . U    - the solution
2358847d985SBarry Smith . dRdU - the computed gradients of the r with respect to u
2368847d985SBarry Smith - ctx  - the user context
237814e85d6SHong Zhang 
23820f4b53cSBarry Smith   Calling sequence of `drdpf`:
2398847d985SBarry Smith + ts   - the integrator
2408847d985SBarry Smith . t    - the time
2418847d985SBarry Smith . U    - the solution
2428847d985SBarry Smith . dRdP - the computed gradients of the r with respect to p
2438847d985SBarry Smith - ctx  - the user context
244814e85d6SHong Zhang 
245cd4cee2dSHong Zhang   Level: deprecated
246814e85d6SHong Zhang 
2478847d985SBarry Smith   Notes:
248814e85d6SHong Zhang   For optimization there is usually a single cost function (numcost = 1). For sensitivities there may be multiple cost functions
249814e85d6SHong Zhang 
2508847d985SBarry Smith   Use `TSCreateQuadratureTS()` and `TSForwardSetSensitivities()` instead
2518847d985SBarry Smith 
2528847d985SBarry Smith .seealso: [](ch_ts), `TS`, `TSSetRHSJacobianP()`, `TSGetCostGradients()`, `TSSetCostGradients()`,
2538847d985SBarry Smith           `TSCreateQuadratureTS()`, `TSForwardSetSensitivities()`
254814e85d6SHong Zhang @*/
2558847d985SBarry Smith PetscErrorCode TSSetCostIntegrand(TS ts, PetscInt numcost, Vec costintegral, PetscErrorCode (*rf)(TS ts, PetscReal t, Vec U, Vec F, void *ctx), PetscErrorCode (*drduf)(TS ts, PetscReal t, Vec U, Vec *dRdU, void *ctx), PetscErrorCode (*drdpf)(TS ts, PetscReal t, Vec U, Vec *dRdP, void *ctx), PetscBool fwd, void *ctx)
256d71ae5a4SJacob Faibussowitsch {
257814e85d6SHong Zhang   PetscFunctionBegin;
258814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
259814e85d6SHong Zhang   if (costintegral) PetscValidHeaderSpecific(costintegral, VEC_CLASSID, 3);
2603c633725SBarry 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()");
261814e85d6SHong Zhang   if (!ts->numcost) ts->numcost = numcost;
262814e85d6SHong Zhang 
263814e85d6SHong Zhang   if (costintegral) {
2649566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)costintegral));
2659566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&ts->vec_costintegral));
266814e85d6SHong Zhang     ts->vec_costintegral = costintegral;
267814e85d6SHong Zhang   } else {
268814e85d6SHong Zhang     if (!ts->vec_costintegral) { /* Create a seq vec if user does not provide one */
2699566063dSJacob Faibussowitsch       PetscCall(VecCreateSeq(PETSC_COMM_SELF, numcost, &ts->vec_costintegral));
270814e85d6SHong Zhang     } else {
2719566063dSJacob Faibussowitsch       PetscCall(VecSet(ts->vec_costintegral, 0.0));
272814e85d6SHong Zhang     }
273814e85d6SHong Zhang   }
274814e85d6SHong Zhang   if (!ts->vec_costintegrand) {
2759566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(ts->vec_costintegral, &ts->vec_costintegrand));
276814e85d6SHong Zhang   } else {
2779566063dSJacob Faibussowitsch     PetscCall(VecSet(ts->vec_costintegrand, 0.0));
278814e85d6SHong Zhang   }
279814e85d6SHong Zhang   ts->costintegralfwd  = fwd; /* Evaluate the cost integral in forward run if fwd is true */
280814e85d6SHong Zhang   ts->costintegrand    = rf;
281814e85d6SHong Zhang   ts->costintegrandctx = ctx;
282c9ad9de0SHong Zhang   ts->drdufunction     = drduf;
283814e85d6SHong Zhang   ts->drdpfunction     = drdpf;
2843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
285814e85d6SHong Zhang }
286814e85d6SHong Zhang 
287b5b4017aSHong Zhang /*@C
288814e85d6SHong Zhang   TSGetCostIntegral - Returns the values of the integral term in the cost functions.
289814e85d6SHong Zhang   It is valid to call the routine after a backward run.
290814e85d6SHong Zhang 
291814e85d6SHong Zhang   Not Collective
292814e85d6SHong Zhang 
293814e85d6SHong Zhang   Input Parameter:
294bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()`
295814e85d6SHong Zhang 
296814e85d6SHong Zhang   Output Parameter:
297814e85d6SHong Zhang . v - the vector containing the integrals for each cost function
298814e85d6SHong Zhang 
299814e85d6SHong Zhang   Level: intermediate
300814e85d6SHong Zhang 
301*a94f484eSPierre Jolivet .seealso: [](ch_ts), `TS`, `TSAdjointSolve()`, `TSSetCostIntegrand()`
302814e85d6SHong Zhang @*/
303d71ae5a4SJacob Faibussowitsch PetscErrorCode TSGetCostIntegral(TS ts, Vec *v)
304d71ae5a4SJacob Faibussowitsch {
305cd4cee2dSHong Zhang   TS quadts;
306cd4cee2dSHong Zhang 
307814e85d6SHong Zhang   PetscFunctionBegin;
308814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3094f572ea9SToby Isaac   PetscAssertPointer(v, 2);
3109566063dSJacob Faibussowitsch   PetscCall(TSGetQuadratureTS(ts, NULL, &quadts));
311cd4cee2dSHong Zhang   *v = quadts->vec_sol;
3123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
313814e85d6SHong Zhang }
314814e85d6SHong Zhang 
315b5b4017aSHong Zhang /*@C
316814e85d6SHong Zhang   TSComputeCostIntegrand - Evaluates the integral function in the cost functions.
317814e85d6SHong Zhang 
318814e85d6SHong Zhang   Input Parameters:
319bcf0153eSBarry Smith + ts - the `TS` context
320814e85d6SHong Zhang . t  - current time
321c9ad9de0SHong Zhang - U  - state vector, i.e. current solution
322814e85d6SHong Zhang 
323814e85d6SHong Zhang   Output Parameter:
324c9ad9de0SHong Zhang . Q - vector of size numcost to hold the outputs
325814e85d6SHong Zhang 
326bcf0153eSBarry Smith   Level: deprecated
327bcf0153eSBarry Smith 
328bcf0153eSBarry Smith   Note:
329814e85d6SHong Zhang   Most users should not need to explicitly call this routine, as it
330814e85d6SHong Zhang   is used internally within the sensitivity analysis context.
331814e85d6SHong Zhang 
3321cc06b55SBarry Smith .seealso: [](ch_ts), `TS`, `TSAdjointSolve()`, `TSSetCostIntegrand()`
333814e85d6SHong Zhang @*/
334d71ae5a4SJacob Faibussowitsch PetscErrorCode TSComputeCostIntegrand(TS ts, PetscReal t, Vec U, Vec Q)
335d71ae5a4SJacob Faibussowitsch {
336814e85d6SHong Zhang   PetscFunctionBegin;
337814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
338c9ad9de0SHong Zhang   PetscValidHeaderSpecific(U, VEC_CLASSID, 3);
339c9ad9de0SHong Zhang   PetscValidHeaderSpecific(Q, VEC_CLASSID, 4);
340814e85d6SHong Zhang 
3419566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(TS_FunctionEval, ts, U, Q, 0));
342792fecdfSBarry Smith   if (ts->costintegrand) PetscCallBack("TS callback integrand in the cost function", (*ts->costintegrand)(ts, t, U, Q, ts->costintegrandctx));
343ef1023bdSBarry Smith   else PetscCall(VecZeroEntries(Q));
3449566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(TS_FunctionEval, ts, U, Q, 0));
3453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
346814e85d6SHong Zhang }
347814e85d6SHong Zhang 
34814d0ab18SJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-*
349b5b4017aSHong Zhang /*@C
350bcf0153eSBarry Smith   TSComputeDRDUFunction - Deprecated, use `TSGetQuadratureTS()` then `TSComputeRHSJacobian()`
351814e85d6SHong Zhang 
352d76be551SHong Zhang   Level: deprecated
353814e85d6SHong Zhang 
354814e85d6SHong Zhang @*/
355d71ae5a4SJacob Faibussowitsch PetscErrorCode TSComputeDRDUFunction(TS ts, PetscReal t, Vec U, Vec *DRDU)
356d71ae5a4SJacob Faibussowitsch {
357814e85d6SHong Zhang   PetscFunctionBegin;
3583ba16761SJacob Faibussowitsch   if (!DRDU) PetscFunctionReturn(PETSC_SUCCESS);
359814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
360c9ad9de0SHong Zhang   PetscValidHeaderSpecific(U, VEC_CLASSID, 3);
361814e85d6SHong Zhang 
362792fecdfSBarry Smith   PetscCallBack("TS callback DRDU for sensitivity analysis", (*ts->drdufunction)(ts, t, U, DRDU, ts->costintegrandctx));
3633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
364814e85d6SHong Zhang }
365814e85d6SHong Zhang 
36614d0ab18SJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-*
367b5b4017aSHong Zhang /*@C
368bcf0153eSBarry Smith   TSComputeDRDPFunction - Deprecated, use `TSGetQuadratureTS()` then `TSComputeRHSJacobianP()`
369814e85d6SHong Zhang 
370d76be551SHong Zhang   Level: deprecated
371814e85d6SHong Zhang 
372814e85d6SHong Zhang @*/
373d71ae5a4SJacob Faibussowitsch PetscErrorCode TSComputeDRDPFunction(TS ts, PetscReal t, Vec U, Vec *DRDP)
374d71ae5a4SJacob Faibussowitsch {
375814e85d6SHong Zhang   PetscFunctionBegin;
3763ba16761SJacob Faibussowitsch   if (!DRDP) PetscFunctionReturn(PETSC_SUCCESS);
377814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
378c9ad9de0SHong Zhang   PetscValidHeaderSpecific(U, VEC_CLASSID, 3);
379814e85d6SHong Zhang 
380792fecdfSBarry Smith   PetscCallBack("TS callback DRDP for sensitivity analysis", (*ts->drdpfunction)(ts, t, U, DRDP, ts->costintegrandctx));
3813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
382814e85d6SHong Zhang }
383814e85d6SHong Zhang 
38414d0ab18SJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-param-list-func-parameter-documentation
38514d0ab18SJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-section-header-unknown
386b5b4017aSHong Zhang /*@C
387b5b4017aSHong 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.
388b5b4017aSHong Zhang 
389c3339decSBarry Smith   Logically Collective
390b5b4017aSHong Zhang 
391b5b4017aSHong Zhang   Input Parameters:
392bcf0153eSBarry Smith + ts   - `TS` context obtained from `TSCreate()`
393b5b4017aSHong Zhang . ihp1 - an array of vectors storing the result of vector-Hessian-vector product for F_UU
394b5b4017aSHong Zhang . hessianproductfunc1 - vector-Hessian-vector product function for F_UU
395b5b4017aSHong Zhang . ihp2 - an array of vectors storing the result of vector-Hessian-vector product for F_UP
396b5b4017aSHong Zhang . hessianproductfunc2 - vector-Hessian-vector product function for F_UP
397b5b4017aSHong Zhang . ihp3 - an array of vectors storing the result of vector-Hessian-vector product for F_PU
398b5b4017aSHong Zhang . hessianproductfunc3 - vector-Hessian-vector product function for F_PU
399b5b4017aSHong Zhang . ihp4 - an array of vectors storing the result of vector-Hessian-vector product for F_PP
400f0fc11ceSJed Brown - hessianproductfunc4 - vector-Hessian-vector product function for F_PP
401b5b4017aSHong Zhang 
40214d0ab18SJacob Faibussowitsch   Calling sequence of `ihessianproductfunc1`:
40314d0ab18SJacob Faibussowitsch + ts  - the `TS` context
404b5b4017aSHong Zhang + t   - current timestep
405b5b4017aSHong Zhang . U   - input vector (current ODE solution)
406369cf35fSHong Zhang . Vl  - an array of input vectors to be left-multiplied with the Hessian
407b5b4017aSHong Zhang . Vr  - input vector to be right-multiplied with the Hessian
408369cf35fSHong Zhang . VHV - an array of output vectors for vector-Hessian-vector product
409b5b4017aSHong Zhang - ctx - [optional] user-defined function context
410b5b4017aSHong Zhang 
411b5b4017aSHong Zhang   Level: intermediate
412b5b4017aSHong Zhang 
413369cf35fSHong Zhang   Notes:
41414d0ab18SJacob Faibussowitsch   All other functions have the same calling sequence as `rhhessianproductfunc1`, so their
41514d0ab18SJacob Faibussowitsch   descriptions are omitted for brevity.
41614d0ab18SJacob Faibussowitsch 
417369cf35fSHong Zhang   The first Hessian function and the working array are required.
418369cf35fSHong Zhang   As an example to implement the callback functions, the second callback function calculates the vector-Hessian-vector product
419369cf35fSHong Zhang   $ Vl_n^T*F_UP*Vr
420369cf35fSHong 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.
421369cf35fSHong Zhang   Each entry of F_UP corresponds to the derivative
422369cf35fSHong Zhang   $ F_UP[i][j][k] = \frac{\partial^2 F[i]}{\partial U[j] \partial P[k]}.
423369cf35fSHong 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
424369cf35fSHong Zhang   $ VHV_n[j] = \sum_i \sum_k {Vl_n[i] * F_UP[i][j][k] * Vr[k]}
425369cf35fSHong Zhang   If the cost function is a scalar, there will be only one vector in Vl and VHV.
426b5b4017aSHong Zhang 
4271cc06b55SBarry Smith .seealso: [](ch_ts), `TS`
428b5b4017aSHong Zhang @*/
42914d0ab18SJacob Faibussowitsch PetscErrorCode TSSetIHessianProduct(TS ts, Vec *ihp1, PetscErrorCode (*ihessianproductfunc1)(TS ts, PetscReal t, Vec U, Vec *Vl, Vec Vr, Vec *VHV, void *ctx), Vec *ihp2, PetscErrorCode (*ihessianproductfunc2)(TS, PetscReal, Vec, Vec *, Vec, Vec *, void *), Vec *ihp3, PetscErrorCode (*ihessianproductfunc3)(TS, PetscReal, Vec, Vec *, Vec, Vec *, void *), Vec *ihp4, PetscErrorCode (*ihessianproductfunc4)(TS, PetscReal, Vec, Vec *, Vec, Vec *, void *), void *ctx)
430d71ae5a4SJacob Faibussowitsch {
431b5b4017aSHong Zhang   PetscFunctionBegin;
432b5b4017aSHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4334f572ea9SToby Isaac   PetscAssertPointer(ihp1, 2);
434b5b4017aSHong Zhang 
435b5b4017aSHong Zhang   ts->ihessianproductctx = ctx;
436b5b4017aSHong Zhang   if (ihp1) ts->vecs_fuu = ihp1;
437b5b4017aSHong Zhang   if (ihp2) ts->vecs_fup = ihp2;
438b5b4017aSHong Zhang   if (ihp3) ts->vecs_fpu = ihp3;
439b5b4017aSHong Zhang   if (ihp4) ts->vecs_fpp = ihp4;
440b5b4017aSHong Zhang   ts->ihessianproduct_fuu = ihessianproductfunc1;
441b5b4017aSHong Zhang   ts->ihessianproduct_fup = ihessianproductfunc2;
442b5b4017aSHong Zhang   ts->ihessianproduct_fpu = ihessianproductfunc3;
443b5b4017aSHong Zhang   ts->ihessianproduct_fpp = ihessianproductfunc4;
4443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
445b5b4017aSHong Zhang }
446b5b4017aSHong Zhang 
447b5b4017aSHong Zhang /*@C
448b1e111ebSHong Zhang   TSComputeIHessianProductFunctionUU - Runs the user-defined vector-Hessian-vector product function for Fuu.
449b5b4017aSHong Zhang 
450c3339decSBarry Smith   Collective
451b5b4017aSHong Zhang 
452b5b4017aSHong Zhang   Input Parameters:
4532fe279fdSBarry Smith + ts - The `TS` context obtained from `TSCreate()`
4542fe279fdSBarry Smith . t  - the time
4552fe279fdSBarry Smith . U  - the solution at which to compute the Hessian product
4562fe279fdSBarry Smith . Vl - the array of input vectors to be multiplied with the Hessian from the left
4572fe279fdSBarry Smith - Vr - the input vector to be multiplied with the Hessian from the right
4582fe279fdSBarry Smith 
4592fe279fdSBarry Smith   Output Parameter:
460b43aa488SJacob Faibussowitsch . VHV - the array of output vectors that store the Hessian product
461b5b4017aSHong Zhang 
462b5b4017aSHong Zhang   Level: developer
463b5b4017aSHong Zhang 
464bcf0153eSBarry Smith   Note:
465bcf0153eSBarry Smith   `TSComputeIHessianProductFunctionUU()` is typically used for sensitivity implementation,
466bcf0153eSBarry Smith   so most users would not generally call this routine themselves.
467bcf0153eSBarry Smith 
4681cc06b55SBarry Smith .seealso: [](ch_ts), `TSSetIHessianProduct()`
469b5b4017aSHong Zhang @*/
470d71ae5a4SJacob Faibussowitsch PetscErrorCode TSComputeIHessianProductFunctionUU(TS ts, PetscReal t, Vec U, Vec *Vl, Vec Vr, Vec *VHV)
471d71ae5a4SJacob Faibussowitsch {
472b5b4017aSHong Zhang   PetscFunctionBegin;
4733ba16761SJacob Faibussowitsch   if (!VHV) PetscFunctionReturn(PETSC_SUCCESS);
474b5b4017aSHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
475b5b4017aSHong Zhang   PetscValidHeaderSpecific(U, VEC_CLASSID, 3);
476b5b4017aSHong Zhang 
477792fecdfSBarry Smith   if (ts->ihessianproduct_fuu) PetscCallBack("TS callback IHessianProduct 1 for sensitivity analysis", (*ts->ihessianproduct_fuu)(ts, t, U, Vl, Vr, VHV, ts->ihessianproductctx));
478ef1023bdSBarry Smith 
47967633408SHong Zhang   /* does not consider IMEX for now, so either IHessian or RHSHessian will be calculated, using the same output VHV */
48067633408SHong Zhang   if (ts->rhshessianproduct_guu) {
48167633408SHong Zhang     PetscInt nadj;
4829566063dSJacob Faibussowitsch     PetscCall(TSComputeRHSHessianProductFunctionUU(ts, t, U, Vl, Vr, VHV));
48348a46eb9SPierre Jolivet     for (nadj = 0; nadj < ts->numcost; nadj++) PetscCall(VecScale(VHV[nadj], -1));
48467633408SHong Zhang   }
4853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
486b5b4017aSHong Zhang }
487b5b4017aSHong Zhang 
488b5b4017aSHong Zhang /*@C
489b1e111ebSHong Zhang   TSComputeIHessianProductFunctionUP - Runs the user-defined vector-Hessian-vector product function for Fup.
490b5b4017aSHong Zhang 
491c3339decSBarry Smith   Collective
492b5b4017aSHong Zhang 
493b5b4017aSHong Zhang   Input Parameters:
4942fe279fdSBarry Smith + ts - The `TS` context obtained from `TSCreate()`
4952fe279fdSBarry Smith . t  - the time
4962fe279fdSBarry Smith . U  - the solution at which to compute the Hessian product
4972fe279fdSBarry Smith . Vl - the array of input vectors to be multiplied with the Hessian from the left
4982fe279fdSBarry Smith - Vr - the input vector to be multiplied with the Hessian from the right
4992fe279fdSBarry Smith 
5002fe279fdSBarry Smith   Output Parameter:
501b43aa488SJacob Faibussowitsch . VHV - the array of output vectors that store the Hessian product
502b5b4017aSHong Zhang 
503b5b4017aSHong Zhang   Level: developer
504b5b4017aSHong Zhang 
505bcf0153eSBarry Smith   Note:
506bcf0153eSBarry Smith   `TSComputeIHessianProductFunctionUP()` is typically used for sensitivity implementation,
507bcf0153eSBarry Smith   so most users would not generally call this routine themselves.
508bcf0153eSBarry Smith 
5091cc06b55SBarry Smith .seealso: [](ch_ts), `TSSetIHessianProduct()`
510b5b4017aSHong Zhang @*/
511d71ae5a4SJacob Faibussowitsch PetscErrorCode TSComputeIHessianProductFunctionUP(TS ts, PetscReal t, Vec U, Vec *Vl, Vec Vr, Vec *VHV)
512d71ae5a4SJacob Faibussowitsch {
513b5b4017aSHong Zhang   PetscFunctionBegin;
5143ba16761SJacob Faibussowitsch   if (!VHV) PetscFunctionReturn(PETSC_SUCCESS);
515b5b4017aSHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
516b5b4017aSHong Zhang   PetscValidHeaderSpecific(U, VEC_CLASSID, 3);
517b5b4017aSHong Zhang 
518792fecdfSBarry Smith   if (ts->ihessianproduct_fup) PetscCallBack("TS callback IHessianProduct 2 for sensitivity analysis", (*ts->ihessianproduct_fup)(ts, t, U, Vl, Vr, VHV, ts->ihessianproductctx));
519ef1023bdSBarry Smith 
52067633408SHong Zhang   /* does not consider IMEX for now, so either IHessian or RHSHessian will be calculated, using the same output VHV */
52167633408SHong Zhang   if (ts->rhshessianproduct_gup) {
52267633408SHong Zhang     PetscInt nadj;
5239566063dSJacob Faibussowitsch     PetscCall(TSComputeRHSHessianProductFunctionUP(ts, t, U, Vl, Vr, VHV));
52448a46eb9SPierre Jolivet     for (nadj = 0; nadj < ts->numcost; nadj++) PetscCall(VecScale(VHV[nadj], -1));
52567633408SHong Zhang   }
5263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
527b5b4017aSHong Zhang }
528b5b4017aSHong Zhang 
529b5b4017aSHong Zhang /*@C
530b1e111ebSHong Zhang   TSComputeIHessianProductFunctionPU - Runs the user-defined vector-Hessian-vector product function for Fpu.
531b5b4017aSHong Zhang 
532c3339decSBarry Smith   Collective
533b5b4017aSHong Zhang 
534b5b4017aSHong Zhang   Input Parameters:
5352fe279fdSBarry Smith + ts - The `TS` context obtained from `TSCreate()`
5362fe279fdSBarry Smith . t  - the time
5372fe279fdSBarry Smith . U  - the solution at which to compute the Hessian product
5382fe279fdSBarry Smith . Vl - the array of input vectors to be multiplied with the Hessian from the left
5392fe279fdSBarry Smith - Vr - the input vector to be multiplied with the Hessian from the right
5402fe279fdSBarry Smith 
5412fe279fdSBarry Smith   Output Parameter:
542b43aa488SJacob Faibussowitsch . VHV - the array of output vectors that store the Hessian product
543b5b4017aSHong Zhang 
544b5b4017aSHong Zhang   Level: developer
545b5b4017aSHong Zhang 
546bcf0153eSBarry Smith   Note:
547bcf0153eSBarry Smith   `TSComputeIHessianProductFunctionPU()` is typically used for sensitivity implementation,
548bcf0153eSBarry Smith   so most users would not generally call this routine themselves.
549bcf0153eSBarry Smith 
5501cc06b55SBarry Smith .seealso: [](ch_ts), `TSSetIHessianProduct()`
551b5b4017aSHong Zhang @*/
552d71ae5a4SJacob Faibussowitsch PetscErrorCode TSComputeIHessianProductFunctionPU(TS ts, PetscReal t, Vec U, Vec *Vl, Vec Vr, Vec *VHV)
553d71ae5a4SJacob Faibussowitsch {
554b5b4017aSHong Zhang   PetscFunctionBegin;
5553ba16761SJacob Faibussowitsch   if (!VHV) PetscFunctionReturn(PETSC_SUCCESS);
556b5b4017aSHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
557b5b4017aSHong Zhang   PetscValidHeaderSpecific(U, VEC_CLASSID, 3);
558b5b4017aSHong Zhang 
559792fecdfSBarry Smith   if (ts->ihessianproduct_fpu) PetscCallBack("TS callback IHessianProduct 3 for sensitivity analysis", (*ts->ihessianproduct_fpu)(ts, t, U, Vl, Vr, VHV, ts->ihessianproductctx));
560ef1023bdSBarry Smith 
56167633408SHong Zhang   /* does not consider IMEX for now, so either IHessian or RHSHessian will be calculated, using the same output VHV */
56267633408SHong Zhang   if (ts->rhshessianproduct_gpu) {
56367633408SHong Zhang     PetscInt nadj;
5649566063dSJacob Faibussowitsch     PetscCall(TSComputeRHSHessianProductFunctionPU(ts, t, U, Vl, Vr, VHV));
56548a46eb9SPierre Jolivet     for (nadj = 0; nadj < ts->numcost; nadj++) PetscCall(VecScale(VHV[nadj], -1));
56667633408SHong Zhang   }
5673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
568b5b4017aSHong Zhang }
569b5b4017aSHong Zhang 
570b5b4017aSHong Zhang /*@C
571b1e111ebSHong Zhang   TSComputeIHessianProductFunctionPP - Runs the user-defined vector-Hessian-vector product function for Fpp.
572b5b4017aSHong Zhang 
573c3339decSBarry Smith   Collective
574b5b4017aSHong Zhang 
575b5b4017aSHong Zhang   Input Parameters:
5762fe279fdSBarry Smith + ts - The `TS` context obtained from `TSCreate()`
5772fe279fdSBarry Smith . t  - the time
5782fe279fdSBarry Smith . U  - the solution at which to compute the Hessian product
5792fe279fdSBarry Smith . Vl - the array of input vectors to be multiplied with the Hessian from the left
5802fe279fdSBarry Smith - Vr - the input vector to be multiplied with the Hessian from the right
5812fe279fdSBarry Smith 
5822fe279fdSBarry Smith   Output Parameter:
583b43aa488SJacob Faibussowitsch . VHV - the array of output vectors that store the Hessian product
584b5b4017aSHong Zhang 
585b5b4017aSHong Zhang   Level: developer
586b5b4017aSHong Zhang 
587bcf0153eSBarry Smith   Note:
588bcf0153eSBarry Smith   `TSComputeIHessianProductFunctionPP()` is typically used for sensitivity implementation,
589bcf0153eSBarry Smith   so most users would not generally call this routine themselves.
590bcf0153eSBarry Smith 
5911cc06b55SBarry Smith .seealso: [](ch_ts), `TSSetIHessianProduct()`
592b5b4017aSHong Zhang @*/
593d71ae5a4SJacob Faibussowitsch PetscErrorCode TSComputeIHessianProductFunctionPP(TS ts, PetscReal t, Vec U, Vec *Vl, Vec Vr, Vec *VHV)
594d71ae5a4SJacob Faibussowitsch {
595b5b4017aSHong Zhang   PetscFunctionBegin;
5963ba16761SJacob Faibussowitsch   if (!VHV) PetscFunctionReturn(PETSC_SUCCESS);
597b5b4017aSHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
598b5b4017aSHong Zhang   PetscValidHeaderSpecific(U, VEC_CLASSID, 3);
599b5b4017aSHong Zhang 
600792fecdfSBarry Smith   if (ts->ihessianproduct_fpp) PetscCallBack("TS callback IHessianProduct 3 for sensitivity analysis", (*ts->ihessianproduct_fpp)(ts, t, U, Vl, Vr, VHV, ts->ihessianproductctx));
601ef1023bdSBarry Smith 
60267633408SHong Zhang   /* does not consider IMEX for now, so either IHessian or RHSHessian will be calculated, using the same output VHV */
60367633408SHong Zhang   if (ts->rhshessianproduct_gpp) {
60467633408SHong Zhang     PetscInt nadj;
6059566063dSJacob Faibussowitsch     PetscCall(TSComputeRHSHessianProductFunctionPP(ts, t, U, Vl, Vr, VHV));
60648a46eb9SPierre Jolivet     for (nadj = 0; nadj < ts->numcost; nadj++) PetscCall(VecScale(VHV[nadj], -1));
60767633408SHong Zhang   }
6083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
609b5b4017aSHong Zhang }
610b5b4017aSHong Zhang 
61114d0ab18SJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-param-list-func-parameter-documentation
61214d0ab18SJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-section-header-unknown
61313af1a74SHong Zhang /*@C
61414d0ab18SJacob Faibussowitsch   TSSetRHSHessianProduct - Sets the function that computes the vector-Hessian-vector
61514d0ab18SJacob Faibussowitsch   product. The Hessian is the second-order derivative of G (RHSFunction) w.r.t. the state
61614d0ab18SJacob Faibussowitsch   variable.
61713af1a74SHong Zhang 
618c3339decSBarry Smith   Logically Collective
61913af1a74SHong Zhang 
62013af1a74SHong Zhang   Input Parameters:
621bcf0153eSBarry Smith + ts     - `TS` context obtained from `TSCreate()`
62213af1a74SHong Zhang . rhshp1 - an array of vectors storing the result of vector-Hessian-vector product for G_UU
62313af1a74SHong Zhang . hessianproductfunc1 - vector-Hessian-vector product function for G_UU
62413af1a74SHong Zhang . rhshp2 - an array of vectors storing the result of vector-Hessian-vector product for G_UP
62513af1a74SHong Zhang . hessianproductfunc2 - vector-Hessian-vector product function for G_UP
62613af1a74SHong Zhang . rhshp3 - an array of vectors storing the result of vector-Hessian-vector product for G_PU
62713af1a74SHong Zhang . hessianproductfunc3 - vector-Hessian-vector product function for G_PU
62813af1a74SHong Zhang . rhshp4 - an array of vectors storing the result of vector-Hessian-vector product for G_PP
62914d0ab18SJacob Faibussowitsch . hessianproductfunc4 - vector-Hessian-vector product function for G_PP
63014d0ab18SJacob Faibussowitsch - ctx    - [optional] user-defined function context
63113af1a74SHong Zhang 
63214d0ab18SJacob Faibussowitsch   Calling sequence of `rhshessianproductfunc1`:
63314d0ab18SJacob Faibussowitsch + ts  - the `TS` context
63414d0ab18SJacob Faibussowitsch . t   - current timestep
63513af1a74SHong Zhang . U   - input vector (current ODE solution)
636369cf35fSHong Zhang . Vl  - an array of input vectors to be left-multiplied with the Hessian
63713af1a74SHong Zhang . Vr  - input vector to be right-multiplied with the Hessian
638369cf35fSHong Zhang . VHV - an array of output vectors for vector-Hessian-vector product
63913af1a74SHong Zhang - ctx - [optional] user-defined function context
64013af1a74SHong Zhang 
64113af1a74SHong Zhang   Level: intermediate
64213af1a74SHong Zhang 
643369cf35fSHong Zhang   Notes:
64414d0ab18SJacob Faibussowitsch   All other functions have the same calling sequence as `rhhessianproductfunc1`, so their
64514d0ab18SJacob Faibussowitsch   descriptions are omitted for brevity.
64614d0ab18SJacob Faibussowitsch 
647369cf35fSHong Zhang   The first Hessian function and the working array are required.
64814d0ab18SJacob Faibussowitsch 
649369cf35fSHong Zhang   As an example to implement the callback functions, the second callback function calculates the vector-Hessian-vector product
650369cf35fSHong Zhang   $ Vl_n^T*G_UP*Vr
651369cf35fSHong 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.
652369cf35fSHong Zhang   Each entry of G_UP corresponds to the derivative
653369cf35fSHong Zhang   $ G_UP[i][j][k] = \frac{\partial^2 G[i]}{\partial U[j] \partial P[k]}.
654369cf35fSHong 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
655369cf35fSHong Zhang   $ VHV_n[j] = \sum_i \sum_k {Vl_n[i] * G_UP[i][j][k] * Vr[k]}
656369cf35fSHong Zhang   If the cost function is a scalar, there will be only one vector in Vl and VHV.
65713af1a74SHong Zhang 
6582fe279fdSBarry Smith .seealso: `TS`, `TSAdjoint`
65913af1a74SHong Zhang @*/
66014d0ab18SJacob Faibussowitsch PetscErrorCode TSSetRHSHessianProduct(TS ts, Vec *rhshp1, PetscErrorCode (*rhshessianproductfunc1)(TS ts, PetscReal t, Vec U, Vec *Vl, Vec Vr, Vec *VHV, void *ctx), Vec *rhshp2, PetscErrorCode (*rhshessianproductfunc2)(TS, PetscReal, Vec, Vec *, Vec, Vec *, void *), Vec *rhshp3, PetscErrorCode (*rhshessianproductfunc3)(TS, PetscReal, Vec, Vec *, Vec, Vec *, void *), Vec *rhshp4, PetscErrorCode (*rhshessianproductfunc4)(TS, PetscReal, Vec, Vec *, Vec, Vec *, void *), void *ctx)
661d71ae5a4SJacob Faibussowitsch {
66213af1a74SHong Zhang   PetscFunctionBegin;
66313af1a74SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
6644f572ea9SToby Isaac   PetscAssertPointer(rhshp1, 2);
66513af1a74SHong Zhang 
66613af1a74SHong Zhang   ts->rhshessianproductctx = ctx;
66713af1a74SHong Zhang   if (rhshp1) ts->vecs_guu = rhshp1;
66813af1a74SHong Zhang   if (rhshp2) ts->vecs_gup = rhshp2;
66913af1a74SHong Zhang   if (rhshp3) ts->vecs_gpu = rhshp3;
67013af1a74SHong Zhang   if (rhshp4) ts->vecs_gpp = rhshp4;
67113af1a74SHong Zhang   ts->rhshessianproduct_guu = rhshessianproductfunc1;
67213af1a74SHong Zhang   ts->rhshessianproduct_gup = rhshessianproductfunc2;
67313af1a74SHong Zhang   ts->rhshessianproduct_gpu = rhshessianproductfunc3;
67413af1a74SHong Zhang   ts->rhshessianproduct_gpp = rhshessianproductfunc4;
6753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
67613af1a74SHong Zhang }
67713af1a74SHong Zhang 
67813af1a74SHong Zhang /*@C
679b1e111ebSHong Zhang   TSComputeRHSHessianProductFunctionUU - Runs the user-defined vector-Hessian-vector product function for Guu.
68013af1a74SHong Zhang 
681c3339decSBarry Smith   Collective
68213af1a74SHong Zhang 
68313af1a74SHong Zhang   Input Parameters:
6842fe279fdSBarry Smith + ts - The `TS` context obtained from `TSCreate()`
6852fe279fdSBarry Smith . t  - the time
6862fe279fdSBarry Smith . U  - the solution at which to compute the Hessian product
6872fe279fdSBarry Smith . Vl - the array of input vectors to be multiplied with the Hessian from the left
6882fe279fdSBarry Smith - Vr - the input vector to be multiplied with the Hessian from the right
6892fe279fdSBarry Smith 
6902fe279fdSBarry Smith   Output Parameter:
691b43aa488SJacob Faibussowitsch . VHV - the array of output vectors that store the Hessian product
69213af1a74SHong Zhang 
69313af1a74SHong Zhang   Level: developer
69413af1a74SHong Zhang 
695bcf0153eSBarry Smith   Note:
696bcf0153eSBarry Smith   `TSComputeRHSHessianProductFunctionUU()` is typically used for sensitivity implementation,
697bcf0153eSBarry Smith   so most users would not generally call this routine themselves.
698bcf0153eSBarry Smith 
6991cc06b55SBarry Smith .seealso: [](ch_ts), `TS`, `TSSetRHSHessianProduct()`
70013af1a74SHong Zhang @*/
701d71ae5a4SJacob Faibussowitsch PetscErrorCode TSComputeRHSHessianProductFunctionUU(TS ts, PetscReal t, Vec U, Vec *Vl, Vec Vr, Vec *VHV)
702d71ae5a4SJacob Faibussowitsch {
70313af1a74SHong Zhang   PetscFunctionBegin;
7043ba16761SJacob Faibussowitsch   if (!VHV) PetscFunctionReturn(PETSC_SUCCESS);
70513af1a74SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
70613af1a74SHong Zhang   PetscValidHeaderSpecific(U, VEC_CLASSID, 3);
70713af1a74SHong Zhang 
708792fecdfSBarry Smith   PetscCallBack("TS callback RHSHessianProduct 1 for sensitivity analysis", (*ts->rhshessianproduct_guu)(ts, t, U, Vl, Vr, VHV, ts->rhshessianproductctx));
7093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
71013af1a74SHong Zhang }
71113af1a74SHong Zhang 
71213af1a74SHong Zhang /*@C
713b1e111ebSHong Zhang   TSComputeRHSHessianProductFunctionUP - Runs the user-defined vector-Hessian-vector product function for Gup.
71413af1a74SHong Zhang 
715c3339decSBarry Smith   Collective
71613af1a74SHong Zhang 
71713af1a74SHong Zhang   Input Parameters:
7182fe279fdSBarry Smith + ts - The `TS` context obtained from `TSCreate()`
7192fe279fdSBarry Smith . t  - the time
7202fe279fdSBarry Smith . U  - the solution at which to compute the Hessian product
7212fe279fdSBarry Smith . Vl - the array of input vectors to be multiplied with the Hessian from the left
7222fe279fdSBarry Smith - Vr - the input vector to be multiplied with the Hessian from the right
7232fe279fdSBarry Smith 
7242fe279fdSBarry Smith   Output Parameter:
725b43aa488SJacob Faibussowitsch . VHV - the array of output vectors that store the Hessian product
72613af1a74SHong Zhang 
72713af1a74SHong Zhang   Level: developer
72813af1a74SHong Zhang 
729bcf0153eSBarry Smith   Note:
730bcf0153eSBarry Smith   `TSComputeRHSHessianProductFunctionUP()` is typically used for sensitivity implementation,
731bcf0153eSBarry Smith   so most users would not generally call this routine themselves.
732bcf0153eSBarry Smith 
7331cc06b55SBarry Smith .seealso: [](ch_ts), `TS`, `TSSetRHSHessianProduct()`
73413af1a74SHong Zhang @*/
735d71ae5a4SJacob Faibussowitsch PetscErrorCode TSComputeRHSHessianProductFunctionUP(TS ts, PetscReal t, Vec U, Vec *Vl, Vec Vr, Vec *VHV)
736d71ae5a4SJacob Faibussowitsch {
73713af1a74SHong Zhang   PetscFunctionBegin;
7383ba16761SJacob Faibussowitsch   if (!VHV) PetscFunctionReturn(PETSC_SUCCESS);
73913af1a74SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
74013af1a74SHong Zhang   PetscValidHeaderSpecific(U, VEC_CLASSID, 3);
74113af1a74SHong Zhang 
742792fecdfSBarry Smith   PetscCallBack("TS callback RHSHessianProduct 2 for sensitivity analysis", (*ts->rhshessianproduct_gup)(ts, t, U, Vl, Vr, VHV, ts->rhshessianproductctx));
7433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
74413af1a74SHong Zhang }
74513af1a74SHong Zhang 
74613af1a74SHong Zhang /*@C
747b1e111ebSHong Zhang   TSComputeRHSHessianProductFunctionPU - Runs the user-defined vector-Hessian-vector product function for Gpu.
74813af1a74SHong Zhang 
749c3339decSBarry Smith   Collective
75013af1a74SHong Zhang 
75113af1a74SHong Zhang   Input Parameters:
7522fe279fdSBarry Smith + ts - The `TS` context obtained from `TSCreate()`
7532fe279fdSBarry Smith . t  - the time
7542fe279fdSBarry Smith . U  - the solution at which to compute the Hessian product
7552fe279fdSBarry Smith . Vl - the array of input vectors to be multiplied with the Hessian from the left
7562fe279fdSBarry Smith - Vr - the input vector to be multiplied with the Hessian from the right
7572fe279fdSBarry Smith 
7582fe279fdSBarry Smith   Output Parameter:
759b43aa488SJacob Faibussowitsch . VHV - the array of output vectors that store the Hessian product
76013af1a74SHong Zhang 
76113af1a74SHong Zhang   Level: developer
76213af1a74SHong Zhang 
763bcf0153eSBarry Smith   Note:
764bcf0153eSBarry Smith   `TSComputeRHSHessianProductFunctionPU()` is typically used for sensitivity implementation,
765bcf0153eSBarry Smith   so most users would not generally call this routine themselves.
766bcf0153eSBarry Smith 
7671cc06b55SBarry Smith .seealso: [](ch_ts), `TSSetRHSHessianProduct()`
76813af1a74SHong Zhang @*/
769d71ae5a4SJacob Faibussowitsch PetscErrorCode TSComputeRHSHessianProductFunctionPU(TS ts, PetscReal t, Vec U, Vec *Vl, Vec Vr, Vec *VHV)
770d71ae5a4SJacob Faibussowitsch {
77113af1a74SHong Zhang   PetscFunctionBegin;
7723ba16761SJacob Faibussowitsch   if (!VHV) PetscFunctionReturn(PETSC_SUCCESS);
77313af1a74SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
77413af1a74SHong Zhang   PetscValidHeaderSpecific(U, VEC_CLASSID, 3);
77513af1a74SHong Zhang 
776792fecdfSBarry Smith   PetscCallBack("TS callback RHSHessianProduct 3 for sensitivity analysis", (*ts->rhshessianproduct_gpu)(ts, t, U, Vl, Vr, VHV, ts->rhshessianproductctx));
7773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
77813af1a74SHong Zhang }
77913af1a74SHong Zhang 
78013af1a74SHong Zhang /*@C
781b1e111ebSHong Zhang   TSComputeRHSHessianProductFunctionPP - Runs the user-defined vector-Hessian-vector product function for Gpp.
78213af1a74SHong Zhang 
783c3339decSBarry Smith   Collective
78413af1a74SHong Zhang 
78513af1a74SHong Zhang   Input Parameters:
7862fe279fdSBarry Smith + ts - The `TS` context obtained from `TSCreate()`
7872fe279fdSBarry Smith . t  - the time
7882fe279fdSBarry Smith . U  - the solution at which to compute the Hessian product
7892fe279fdSBarry Smith . Vl - the array of input vectors to be multiplied with the Hessian from the left
7902fe279fdSBarry Smith - Vr - the input vector to be multiplied with the Hessian from the right
7912fe279fdSBarry Smith 
7922fe279fdSBarry Smith   Output Parameter:
793b43aa488SJacob Faibussowitsch . VHV - the array of output vectors that store the Hessian product
79413af1a74SHong Zhang 
79513af1a74SHong Zhang   Level: developer
79613af1a74SHong Zhang 
797bcf0153eSBarry Smith   Note:
798bcf0153eSBarry Smith   `TSComputeRHSHessianProductFunctionPP()` is typically used for sensitivity implementation,
799bcf0153eSBarry Smith   so most users would not generally call this routine themselves.
800bcf0153eSBarry Smith 
8011cc06b55SBarry Smith .seealso: [](ch_ts), `TSSetRHSHessianProduct()`
80213af1a74SHong Zhang @*/
803d71ae5a4SJacob Faibussowitsch PetscErrorCode TSComputeRHSHessianProductFunctionPP(TS ts, PetscReal t, Vec U, Vec *Vl, Vec Vr, Vec *VHV)
804d71ae5a4SJacob Faibussowitsch {
80513af1a74SHong Zhang   PetscFunctionBegin;
8063ba16761SJacob Faibussowitsch   if (!VHV) PetscFunctionReturn(PETSC_SUCCESS);
80713af1a74SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
80813af1a74SHong Zhang   PetscValidHeaderSpecific(U, VEC_CLASSID, 3);
80913af1a74SHong Zhang 
810792fecdfSBarry Smith   PetscCallBack("TS callback RHSHessianProduct 3 for sensitivity analysis", (*ts->rhshessianproduct_gpp)(ts, t, U, Vl, Vr, VHV, ts->rhshessianproductctx));
8113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
81213af1a74SHong Zhang }
81313af1a74SHong Zhang 
814814e85d6SHong Zhang /* --------------------------- Adjoint sensitivity ---------------------------*/
815814e85d6SHong Zhang 
816814e85d6SHong Zhang /*@
817814e85d6SHong 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
818bcf0153eSBarry Smith   for use by the `TS` adjoint routines.
819814e85d6SHong Zhang 
820c3339decSBarry Smith   Logically Collective
821814e85d6SHong Zhang 
822814e85d6SHong Zhang   Input Parameters:
823bcf0153eSBarry Smith + ts      - the `TS` context obtained from `TSCreate()`
824d2fd7bfcSHong Zhang . numcost - number of gradients to be computed, this is the number of cost functions
825814e85d6SHong 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
826814e85d6SHong Zhang - mu      - gradients with respect to the parameters, the number of entries in these vectors is the same as the number of parameters
827814e85d6SHong Zhang 
828814e85d6SHong Zhang   Level: beginner
829814e85d6SHong Zhang 
830814e85d6SHong Zhang   Notes:
83135cb6cd3SPierre Jolivet   the entries in these vectors must be correctly initialized with the values lambda_i = df/dy|finaltime  mu_i = df/dp|finaltime
832814e85d6SHong Zhang 
83335cb6cd3SPierre Jolivet   After `TSAdjointSolve()` is called the lambda and the mu contain the computed sensitivities
834814e85d6SHong Zhang 
835bcf0153eSBarry Smith .seealso: `TS`, `TSAdjointSolve()`, `TSGetCostGradients()`
836814e85d6SHong Zhang @*/
837d71ae5a4SJacob Faibussowitsch PetscErrorCode TSSetCostGradients(TS ts, PetscInt numcost, Vec *lambda, Vec *mu)
838d71ae5a4SJacob Faibussowitsch {
839814e85d6SHong Zhang   PetscFunctionBegin;
840814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
8414f572ea9SToby Isaac   PetscAssertPointer(lambda, 3);
842814e85d6SHong Zhang   ts->vecs_sensi  = lambda;
843814e85d6SHong Zhang   ts->vecs_sensip = mu;
8443c633725SBarry 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");
845814e85d6SHong Zhang   ts->numcost = numcost;
8463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
847814e85d6SHong Zhang }
848814e85d6SHong Zhang 
849814e85d6SHong Zhang /*@
850bcf0153eSBarry Smith   TSGetCostGradients - Returns the gradients from the `TSAdjointSolve()`
851814e85d6SHong Zhang 
852bcf0153eSBarry Smith   Not Collective, but the vectors returned are parallel if `TS` is parallel
853814e85d6SHong Zhang 
854814e85d6SHong Zhang   Input Parameter:
855bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()`
856814e85d6SHong Zhang 
857d8d19677SJose E. Roman   Output Parameters:
8586b867d5aSJose E. Roman + numcost - size of returned arrays
8596b867d5aSJose E. Roman . lambda  - vectors containing the gradients of the cost functions with respect to the ODE/DAE solution variables
860814e85d6SHong Zhang - mu      - vectors containing the gradients of the cost functions with respect to the problem parameters
861814e85d6SHong Zhang 
862814e85d6SHong Zhang   Level: intermediate
863814e85d6SHong Zhang 
8641cc06b55SBarry Smith .seealso: [](ch_ts), `TS`, `TSAdjointSolve()`, `TSSetCostGradients()`
865814e85d6SHong Zhang @*/
866d71ae5a4SJacob Faibussowitsch PetscErrorCode TSGetCostGradients(TS ts, PetscInt *numcost, Vec **lambda, Vec **mu)
867d71ae5a4SJacob Faibussowitsch {
868814e85d6SHong Zhang   PetscFunctionBegin;
869814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
870814e85d6SHong Zhang   if (numcost) *numcost = ts->numcost;
871814e85d6SHong Zhang   if (lambda) *lambda = ts->vecs_sensi;
872814e85d6SHong Zhang   if (mu) *mu = ts->vecs_sensip;
8733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
874814e85d6SHong Zhang }
875814e85d6SHong Zhang 
876814e85d6SHong Zhang /*@
877b5b4017aSHong 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
878bcf0153eSBarry Smith   for use by the `TS` adjoint routines.
879b5b4017aSHong Zhang 
880c3339decSBarry Smith   Logically Collective
881b5b4017aSHong Zhang 
882b5b4017aSHong Zhang   Input Parameters:
883bcf0153eSBarry Smith + ts      - the `TS` context obtained from `TSCreate()`
884b5b4017aSHong Zhang . numcost - number of cost functions
885b5b4017aSHong 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
886b5b4017aSHong 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
887b5b4017aSHong Zhang - dir     - the direction vector that are multiplied with the Hessian of the cost functions
888b5b4017aSHong Zhang 
889b5b4017aSHong Zhang   Level: beginner
890b5b4017aSHong Zhang 
891bcf0153eSBarry Smith   Notes:
892bcf0153eSBarry Smith   Hessian of the cost function is completely different from Hessian of the ODE/DAE system
893b5b4017aSHong Zhang 
894bcf0153eSBarry Smith   For second-order adjoint, one needs to call this function and then `TSAdjointSetForward()` before `TSSolve()`.
895b5b4017aSHong Zhang 
89635cb6cd3SPierre Jolivet   After `TSAdjointSolve()` is called, the lambda2 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.
897b5b4017aSHong Zhang 
8982fe279fdSBarry Smith   Passing `NULL` for `lambda2` disables the second-order calculation.
899bcf0153eSBarry Smith 
9001cc06b55SBarry Smith .seealso: [](ch_ts), `TS`, `TSAdjointSolve()`, `TSAdjointSetForward()`
901b5b4017aSHong Zhang @*/
902d71ae5a4SJacob Faibussowitsch PetscErrorCode TSSetCostHessianProducts(TS ts, PetscInt numcost, Vec *lambda2, Vec *mu2, Vec dir)
903d71ae5a4SJacob Faibussowitsch {
904b5b4017aSHong Zhang   PetscFunctionBegin;
905b5b4017aSHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
9063c633725SBarry 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");
907b5b4017aSHong Zhang   ts->numcost      = numcost;
908b5b4017aSHong Zhang   ts->vecs_sensi2  = lambda2;
90933f72c5dSHong Zhang   ts->vecs_sensi2p = mu2;
910b5b4017aSHong Zhang   ts->vec_dir      = dir;
9113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
912b5b4017aSHong Zhang }
913b5b4017aSHong Zhang 
914b5b4017aSHong Zhang /*@
915bcf0153eSBarry Smith   TSGetCostHessianProducts - Returns the gradients from the `TSAdjointSolve()`
916b5b4017aSHong Zhang 
917bcf0153eSBarry Smith   Not Collective, but vectors returned are parallel if `TS` is parallel
918b5b4017aSHong Zhang 
919b5b4017aSHong Zhang   Input Parameter:
920bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()`
921b5b4017aSHong Zhang 
922d8d19677SJose E. Roman   Output Parameters:
923b5b4017aSHong Zhang + numcost - number of cost functions
924b5b4017aSHong 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
925b5b4017aSHong 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
926b5b4017aSHong Zhang - dir     - the direction vector that are multiplied with the Hessian of the cost functions
927b5b4017aSHong Zhang 
928b5b4017aSHong Zhang   Level: intermediate
929b5b4017aSHong Zhang 
9301cc06b55SBarry Smith .seealso: [](ch_ts), `TSAdjointSolve()`, `TSSetCostHessianProducts()`
931b5b4017aSHong Zhang @*/
932d71ae5a4SJacob Faibussowitsch PetscErrorCode TSGetCostHessianProducts(TS ts, PetscInt *numcost, Vec **lambda2, Vec **mu2, Vec *dir)
933d71ae5a4SJacob Faibussowitsch {
934b5b4017aSHong Zhang   PetscFunctionBegin;
935b5b4017aSHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
936b5b4017aSHong Zhang   if (numcost) *numcost = ts->numcost;
937b5b4017aSHong Zhang   if (lambda2) *lambda2 = ts->vecs_sensi2;
93833f72c5dSHong Zhang   if (mu2) *mu2 = ts->vecs_sensi2p;
939b5b4017aSHong Zhang   if (dir) *dir = ts->vec_dir;
9403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
941b5b4017aSHong Zhang }
942b5b4017aSHong Zhang 
943b5b4017aSHong Zhang /*@
944ecf68647SHong Zhang   TSAdjointSetForward - Trigger the tangent linear solver and initialize the forward sensitivities
945b5b4017aSHong Zhang 
946c3339decSBarry Smith   Logically Collective
947b5b4017aSHong Zhang 
948b5b4017aSHong Zhang   Input Parameters:
949bcf0153eSBarry Smith + ts   - the `TS` context obtained from `TSCreate()`
950b5b4017aSHong Zhang - didp - the derivative of initial values w.r.t. parameters
951b5b4017aSHong Zhang 
952b5b4017aSHong Zhang   Level: intermediate
953b5b4017aSHong Zhang 
954bcf0153eSBarry Smith   Notes:
955baca6076SPierre Jolivet   When computing sensitivities w.r.t. initial condition, set didp to `NULL` so that the solver will take it as an identity matrix mathematically.
9562fe279fdSBarry Smith   `TSAdjoint` does not reset the tangent linear solver automatically, `TSAdjointResetForward()` should be called to reset the tangent linear solver.
957b5b4017aSHong Zhang 
9581cc06b55SBarry Smith .seealso: [](ch_ts), `TSAdjointSolve()`, `TSSetCostHessianProducts()`, `TSAdjointResetForward()`
959b5b4017aSHong Zhang @*/
960d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointSetForward(TS ts, Mat didp)
961d71ae5a4SJacob Faibussowitsch {
96233f72c5dSHong Zhang   Mat          A;
96333f72c5dSHong Zhang   Vec          sp;
96433f72c5dSHong Zhang   PetscScalar *xarr;
96533f72c5dSHong Zhang   PetscInt     lsize;
966b5b4017aSHong Zhang 
967b5b4017aSHong Zhang   PetscFunctionBegin;
968b5b4017aSHong Zhang   ts->forward_solve = PETSC_TRUE; /* turn on tangent linear mode */
9693c633725SBarry Smith   PetscCheck(ts->vecs_sensi2, PetscObjectComm((PetscObject)ts), PETSC_ERR_USER, "Must call TSSetCostHessianProducts() first");
9703c633725SBarry Smith   PetscCheck(ts->vec_dir, PetscObjectComm((PetscObject)ts), PETSC_ERR_USER, "Directional vector is missing. Call TSSetCostHessianProducts() to set it.");
97133f72c5dSHong Zhang   /* create a single-column dense matrix */
9729566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(ts->vec_sol, &lsize));
9739566063dSJacob Faibussowitsch   PetscCall(MatCreateDense(PetscObjectComm((PetscObject)ts), lsize, PETSC_DECIDE, PETSC_DECIDE, 1, NULL, &A));
97433f72c5dSHong Zhang 
9759566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(ts->vec_sol, &sp));
9769566063dSJacob Faibussowitsch   PetscCall(MatDenseGetColumn(A, 0, &xarr));
9779566063dSJacob Faibussowitsch   PetscCall(VecPlaceArray(sp, xarr));
978ecf68647SHong Zhang   if (ts->vecs_sensi2p) { /* tangent linear variable initialized as 2*dIdP*dir */
97933f72c5dSHong Zhang     if (didp) {
9809566063dSJacob Faibussowitsch       PetscCall(MatMult(didp, ts->vec_dir, sp));
9819566063dSJacob Faibussowitsch       PetscCall(VecScale(sp, 2.));
98233f72c5dSHong Zhang     } else {
9839566063dSJacob Faibussowitsch       PetscCall(VecZeroEntries(sp));
98433f72c5dSHong Zhang     }
985ecf68647SHong Zhang   } else { /* tangent linear variable initialized as dir */
9869566063dSJacob Faibussowitsch     PetscCall(VecCopy(ts->vec_dir, sp));
98733f72c5dSHong Zhang   }
9889566063dSJacob Faibussowitsch   PetscCall(VecResetArray(sp));
9899566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreColumn(A, &xarr));
9909566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&sp));
99133f72c5dSHong Zhang 
9929566063dSJacob Faibussowitsch   PetscCall(TSForwardSetInitialSensitivities(ts, A)); /* if didp is NULL, identity matrix is assumed */
99333f72c5dSHong Zhang 
9949566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&A));
9953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
996b5b4017aSHong Zhang }
997b5b4017aSHong Zhang 
998b5b4017aSHong Zhang /*@
999ecf68647SHong Zhang   TSAdjointResetForward - Reset the tangent linear solver and destroy the tangent linear context
1000ecf68647SHong Zhang 
1001c3339decSBarry Smith   Logically Collective
1002ecf68647SHong Zhang 
10032fe279fdSBarry Smith   Input Parameter:
1004bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()`
1005ecf68647SHong Zhang 
1006ecf68647SHong Zhang   Level: intermediate
1007ecf68647SHong Zhang 
10081cc06b55SBarry Smith .seealso: [](ch_ts), `TSAdjointSetForward()`
1009ecf68647SHong Zhang @*/
1010d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointResetForward(TS ts)
1011d71ae5a4SJacob Faibussowitsch {
1012ecf68647SHong Zhang   PetscFunctionBegin;
1013ecf68647SHong Zhang   ts->forward_solve = PETSC_FALSE; /* turn off tangent linear mode */
10149566063dSJacob Faibussowitsch   PetscCall(TSForwardReset(ts));
10153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1016ecf68647SHong Zhang }
1017ecf68647SHong Zhang 
1018ecf68647SHong Zhang /*@
1019814e85d6SHong Zhang   TSAdjointSetUp - Sets up the internal data structures for the later use
1020814e85d6SHong Zhang   of an adjoint solver
1021814e85d6SHong Zhang 
1022c3339decSBarry Smith   Collective
1023814e85d6SHong Zhang 
1024814e85d6SHong Zhang   Input Parameter:
1025bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()`
1026814e85d6SHong Zhang 
1027814e85d6SHong Zhang   Level: advanced
1028814e85d6SHong Zhang 
10291cc06b55SBarry Smith .seealso: [](ch_ts), `TSCreate()`, `TSAdjointStep()`, `TSSetCostGradients()`
1030814e85d6SHong Zhang @*/
1031d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointSetUp(TS ts)
1032d71ae5a4SJacob Faibussowitsch {
1033881c1a9bSHong Zhang   TSTrajectory tj;
1034881c1a9bSHong Zhang   PetscBool    match;
1035814e85d6SHong Zhang 
1036814e85d6SHong Zhang   PetscFunctionBegin;
1037814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
10383ba16761SJacob Faibussowitsch   if (ts->adjointsetupcalled) PetscFunctionReturn(PETSC_SUCCESS);
10393c633725SBarry Smith   PetscCheck(ts->vecs_sensi, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONGSTATE, "Must call TSSetCostGradients() first");
10403c633725SBarry Smith   PetscCheck(!ts->vecs_sensip || ts->Jacp || ts->Jacprhs, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONGSTATE, "Must call TSSetRHSJacobianP() or TSSetIJacobianP() first");
10419566063dSJacob Faibussowitsch   PetscCall(TSGetTrajectory(ts, &tj));
10429566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)tj, TSTRAJECTORYBASIC, &match));
1043881c1a9bSHong Zhang   if (match) {
1044881c1a9bSHong Zhang     PetscBool solution_only;
10459566063dSJacob Faibussowitsch     PetscCall(TSTrajectoryGetSolutionOnly(tj, &solution_only));
10463c633725SBarry 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");
1047881c1a9bSHong Zhang   }
10489566063dSJacob Faibussowitsch   PetscCall(TSTrajectorySetUseHistory(tj, PETSC_FALSE)); /* not use TSHistory */
104933f72c5dSHong Zhang 
1050cd4cee2dSHong Zhang   if (ts->quadraturets) { /* if there is integral in the cost function */
10519566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(ts->vecs_sensi[0], &ts->vec_drdu_col));
105248a46eb9SPierre Jolivet     if (ts->vecs_sensip) PetscCall(VecDuplicate(ts->vecs_sensip[0], &ts->vec_drdp_col));
1053814e85d6SHong Zhang   }
1054814e85d6SHong Zhang 
1055dbbe0bcdSBarry Smith   PetscTryTypeMethod(ts, adjointsetup);
1056814e85d6SHong Zhang   ts->adjointsetupcalled = PETSC_TRUE;
10573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1058814e85d6SHong Zhang }
1059814e85d6SHong Zhang 
1060814e85d6SHong Zhang /*@
1061bcf0153eSBarry Smith   TSAdjointReset - Resets a `TS` adjoint context and removes any allocated `Vec`s and `Mat`s.
1062ece46509SHong Zhang 
1063c3339decSBarry Smith   Collective
1064ece46509SHong Zhang 
1065ece46509SHong Zhang   Input Parameter:
1066bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()`
1067ece46509SHong Zhang 
1068ece46509SHong Zhang   Level: beginner
1069ece46509SHong Zhang 
10701cc06b55SBarry Smith .seealso: [](ch_ts), `TSCreate()`, `TSAdjointSetUp()`, `TSADestroy()`
1071ece46509SHong Zhang @*/
1072d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointReset(TS ts)
1073d71ae5a4SJacob Faibussowitsch {
1074ece46509SHong Zhang   PetscFunctionBegin;
1075ece46509SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
1076dbbe0bcdSBarry Smith   PetscTryTypeMethod(ts, adjointreset);
10777207e0fdSHong Zhang   if (ts->quadraturets) { /* if there is integral in the cost function */
10789566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&ts->vec_drdu_col));
107948a46eb9SPierre Jolivet     if (ts->vecs_sensip) PetscCall(VecDestroy(&ts->vec_drdp_col));
10807207e0fdSHong Zhang   }
1081ece46509SHong Zhang   ts->vecs_sensi         = NULL;
1082ece46509SHong Zhang   ts->vecs_sensip        = NULL;
1083ece46509SHong Zhang   ts->vecs_sensi2        = NULL;
108433f72c5dSHong Zhang   ts->vecs_sensi2p       = NULL;
1085ece46509SHong Zhang   ts->vec_dir            = NULL;
1086ece46509SHong Zhang   ts->adjointsetupcalled = PETSC_FALSE;
10873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1088ece46509SHong Zhang }
1089ece46509SHong Zhang 
1090ece46509SHong Zhang /*@
1091814e85d6SHong Zhang   TSAdjointSetSteps - Sets the number of steps the adjoint solver should take backward in time
1092814e85d6SHong Zhang 
1093c3339decSBarry Smith   Logically Collective
1094814e85d6SHong Zhang 
1095814e85d6SHong Zhang   Input Parameters:
1096bcf0153eSBarry Smith + ts    - the `TS` context obtained from `TSCreate()`
1097a2b725a8SWilliam Gropp - steps - number of steps to use
1098814e85d6SHong Zhang 
1099814e85d6SHong Zhang   Level: intermediate
1100814e85d6SHong Zhang 
1101814e85d6SHong Zhang   Notes:
1102bcf0153eSBarry Smith   Normally one does not call this and `TSAdjointSolve()` integrates back to the original timestep. One can call this
1103814e85d6SHong Zhang   so as to integrate back to less than the original timestep
1104814e85d6SHong Zhang 
11051cc06b55SBarry Smith .seealso: [](ch_ts), `TSAdjointSolve()`, `TS`, `TSSetExactFinalTime()`
1106814e85d6SHong Zhang @*/
1107d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointSetSteps(TS ts, PetscInt steps)
1108d71ae5a4SJacob Faibussowitsch {
1109814e85d6SHong Zhang   PetscFunctionBegin;
1110814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
1111814e85d6SHong Zhang   PetscValidLogicalCollectiveInt(ts, steps, 2);
11123c633725SBarry Smith   PetscCheck(steps >= 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Cannot step back a negative number of steps");
11133c633725SBarry Smith   PetscCheck(steps <= ts->steps, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Cannot step back more than the total number of forward steps");
1114814e85d6SHong Zhang   ts->adjoint_max_steps = steps;
11153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1116814e85d6SHong Zhang }
1117814e85d6SHong Zhang 
111814d0ab18SJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-*
1119814e85d6SHong Zhang /*@C
1120bcf0153eSBarry Smith   TSAdjointSetRHSJacobian - Deprecated, use `TSSetRHSJacobianP()`
1121814e85d6SHong Zhang 
1122814e85d6SHong Zhang   Level: deprecated
1123814e85d6SHong Zhang @*/
1124d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointSetRHSJacobian(TS ts, Mat Amat, PetscErrorCode (*func)(TS, PetscReal, Vec, Mat, void *), void *ctx)
1125d71ae5a4SJacob Faibussowitsch {
1126814e85d6SHong Zhang   PetscFunctionBegin;
1127814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
1128814e85d6SHong Zhang   PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2);
1129814e85d6SHong Zhang 
1130814e85d6SHong Zhang   ts->rhsjacobianp    = func;
1131814e85d6SHong Zhang   ts->rhsjacobianpctx = ctx;
1132814e85d6SHong Zhang   if (Amat) {
11339566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)Amat));
11349566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&ts->Jacp));
1135814e85d6SHong Zhang     ts->Jacp = Amat;
1136814e85d6SHong Zhang   }
11373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1138814e85d6SHong Zhang }
1139814e85d6SHong Zhang 
114014d0ab18SJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-*
1141814e85d6SHong Zhang /*@C
1142bcf0153eSBarry Smith   TSAdjointComputeRHSJacobian - Deprecated, use `TSComputeRHSJacobianP()`
1143814e85d6SHong Zhang 
1144814e85d6SHong Zhang   Level: deprecated
1145814e85d6SHong Zhang @*/
1146d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointComputeRHSJacobian(TS ts, PetscReal t, Vec U, Mat Amat)
1147d71ae5a4SJacob Faibussowitsch {
1148814e85d6SHong Zhang   PetscFunctionBegin;
1149814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
1150c9ad9de0SHong Zhang   PetscValidHeaderSpecific(U, VEC_CLASSID, 3);
1151292bffcbSToby Isaac   PetscValidHeaderSpecific(Amat, MAT_CLASSID, 4);
1152814e85d6SHong Zhang 
1153792fecdfSBarry Smith   PetscCallBack("TS callback JacobianP for sensitivity analysis", (*ts->rhsjacobianp)(ts, t, U, Amat, ts->rhsjacobianpctx));
11543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1155814e85d6SHong Zhang }
1156814e85d6SHong Zhang 
115714d0ab18SJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-*
1158814e85d6SHong Zhang /*@
1159bcf0153eSBarry Smith   TSAdjointComputeDRDYFunction - Deprecated, use `TSGetQuadratureTS()` then `TSComputeRHSJacobian()`
1160814e85d6SHong Zhang 
1161814e85d6SHong Zhang   Level: deprecated
1162814e85d6SHong Zhang @*/
1163d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointComputeDRDYFunction(TS ts, PetscReal t, Vec U, Vec *DRDU)
1164d71ae5a4SJacob Faibussowitsch {
1165814e85d6SHong Zhang   PetscFunctionBegin;
1166814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
1167c9ad9de0SHong Zhang   PetscValidHeaderSpecific(U, VEC_CLASSID, 3);
1168814e85d6SHong Zhang 
1169792fecdfSBarry Smith   PetscCallBack("TS callback DRDY for sensitivity analysis", (*ts->drdufunction)(ts, t, U, DRDU, ts->costintegrandctx));
11703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1171814e85d6SHong Zhang }
1172814e85d6SHong Zhang 
117314d0ab18SJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-*
1174814e85d6SHong Zhang /*@
1175bcf0153eSBarry Smith   TSAdjointComputeDRDPFunction - Deprecated, use `TSGetQuadratureTS()` then `TSComputeRHSJacobianP()`
1176814e85d6SHong Zhang 
1177814e85d6SHong Zhang   Level: deprecated
1178814e85d6SHong Zhang @*/
1179d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointComputeDRDPFunction(TS ts, PetscReal t, Vec U, Vec *DRDP)
1180d71ae5a4SJacob Faibussowitsch {
1181814e85d6SHong Zhang   PetscFunctionBegin;
1182814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
1183c9ad9de0SHong Zhang   PetscValidHeaderSpecific(U, VEC_CLASSID, 3);
1184814e85d6SHong Zhang 
1185792fecdfSBarry Smith   PetscCallBack("TS callback DRDP for sensitivity analysis", (*ts->drdpfunction)(ts, t, U, DRDP, ts->costintegrandctx));
11863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1187814e85d6SHong Zhang }
1188814e85d6SHong Zhang 
118914d0ab18SJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-param-list-func-parameter-documentation
1190814e85d6SHong Zhang /*@C
1191814e85d6SHong Zhang   TSAdjointMonitorSensi - monitors the first lambda sensitivity
1192814e85d6SHong Zhang 
1193814e85d6SHong Zhang   Level: intermediate
1194814e85d6SHong Zhang 
11951cc06b55SBarry Smith .seealso: [](ch_ts), `TSAdjointMonitorSet()`
1196814e85d6SHong Zhang @*/
1197ba38deedSJacob Faibussowitsch static PetscErrorCode TSAdjointMonitorSensi(TS ts, PetscInt step, PetscReal ptime, Vec v, PetscInt numcost, Vec *lambda, Vec *mu, PetscViewerAndFormat *vf)
1198d71ae5a4SJacob Faibussowitsch {
1199814e85d6SHong Zhang   PetscViewer viewer = vf->viewer;
1200814e85d6SHong Zhang 
1201814e85d6SHong Zhang   PetscFunctionBegin;
1202064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 8);
12039566063dSJacob Faibussowitsch   PetscCall(PetscViewerPushFormat(viewer, vf->format));
12049566063dSJacob Faibussowitsch   PetscCall(VecView(lambda[0], viewer));
12059566063dSJacob Faibussowitsch   PetscCall(PetscViewerPopFormat(viewer));
12063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1207814e85d6SHong Zhang }
1208814e85d6SHong Zhang 
1209814e85d6SHong Zhang /*@C
1210814e85d6SHong Zhang   TSAdjointMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user
1211814e85d6SHong Zhang 
1212c3339decSBarry Smith   Collective
1213814e85d6SHong Zhang 
1214814e85d6SHong Zhang   Input Parameters:
1215bcf0153eSBarry Smith + ts           - `TS` object you wish to monitor
1216814e85d6SHong Zhang . name         - the monitor type one is seeking
1217814e85d6SHong Zhang . help         - message indicating what monitoring is done
1218814e85d6SHong Zhang . manual       - manual page for the monitor
1219814e85d6SHong Zhang . monitor      - the monitor function
1220bcf0153eSBarry Smith - 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
1221814e85d6SHong Zhang 
1222814e85d6SHong Zhang   Level: developer
1223814e85d6SHong Zhang 
12241cc06b55SBarry Smith .seealso: [](ch_ts), `PetscOptionsGetViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
1225db781477SPatrick Sanan           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
1226b43aa488SJacob Faibussowitsch           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
1227db781477SPatrick Sanan           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1228c2e3fba1SPatrick Sanan           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1229db781477SPatrick Sanan           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1230db781477SPatrick Sanan           `PetscOptionsFList()`, `PetscOptionsEList()`
1231814e85d6SHong Zhang @*/
1232d71ae5a4SJacob Faibussowitsch 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 *))
1233d71ae5a4SJacob Faibussowitsch {
1234814e85d6SHong Zhang   PetscViewer       viewer;
1235814e85d6SHong Zhang   PetscViewerFormat format;
1236814e85d6SHong Zhang   PetscBool         flg;
1237814e85d6SHong Zhang 
1238814e85d6SHong Zhang   PetscFunctionBegin;
12399566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)ts), ((PetscObject)ts)->options, ((PetscObject)ts)->prefix, name, &viewer, &format, &flg));
1240814e85d6SHong Zhang   if (flg) {
1241814e85d6SHong Zhang     PetscViewerAndFormat *vf;
12429566063dSJacob Faibussowitsch     PetscCall(PetscViewerAndFormatCreate(viewer, format, &vf));
1243cd791dc2SBarry Smith     PetscCall(PetscOptionsRestoreViewer(&viewer));
12441baa6e33SBarry Smith     if (monitorsetup) PetscCall((*monitorsetup)(ts, vf));
12459566063dSJacob Faibussowitsch     PetscCall(TSAdjointMonitorSet(ts, (PetscErrorCode(*)(TS, PetscInt, PetscReal, Vec, PetscInt, Vec *, Vec *, void *))monitor, vf, (PetscErrorCode(*)(void **))PetscViewerAndFormatDestroy));
1246814e85d6SHong Zhang   }
12473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1248814e85d6SHong Zhang }
1249814e85d6SHong Zhang 
1250814e85d6SHong Zhang /*@C
1251814e85d6SHong Zhang   TSAdjointMonitorSet - Sets an ADDITIONAL function that is to be used at every
1252814e85d6SHong Zhang   timestep to display the iteration's  progress.
1253814e85d6SHong Zhang 
1254c3339decSBarry Smith   Logically Collective
1255814e85d6SHong Zhang 
1256814e85d6SHong Zhang   Input Parameters:
1257bcf0153eSBarry Smith + ts              - the `TS` context obtained from `TSCreate()`
1258814e85d6SHong Zhang . adjointmonitor  - monitoring routine
125914d0ab18SJacob Faibussowitsch . adjointmctx     - [optional] user-defined context for private data for the monitor routine
126014d0ab18SJacob Faibussowitsch                     (use `NULL` if no context is desired)
126114d0ab18SJacob Faibussowitsch - adjointmdestroy - [optional] routine that frees monitor context (may be `NULL`)
1262814e85d6SHong Zhang 
126320f4b53cSBarry Smith   Calling sequence of `adjointmonitor`:
1264bcf0153eSBarry Smith + ts          - the `TS` context
126514d0ab18SJacob Faibussowitsch . steps       - iteration number (after the final time step the monitor routine is called with
126614d0ab18SJacob Faibussowitsch                 a step of -1, this is at the final time which may have been interpolated to)
1267814e85d6SHong Zhang . time        - current time
1268814e85d6SHong Zhang . u           - current iterate
1269814e85d6SHong Zhang . numcost     - number of cost functionos
1270814e85d6SHong Zhang . lambda      - sensitivities to initial conditions
1271814e85d6SHong Zhang . mu          - sensitivities to parameters
1272814e85d6SHong Zhang - adjointmctx - [optional] adjoint monitoring context
1273814e85d6SHong Zhang 
127414d0ab18SJacob Faibussowitsch   Calling sequence of `adjointmdestroy`:
127514d0ab18SJacob Faibussowitsch . mctx - the monitor context to destroy
127614d0ab18SJacob Faibussowitsch 
1277bcf0153eSBarry Smith   Level: intermediate
1278bcf0153eSBarry Smith 
1279bcf0153eSBarry Smith   Note:
1280814e85d6SHong Zhang   This routine adds an additional monitor to the list of monitors that
1281814e85d6SHong Zhang   already has been loaded.
1282814e85d6SHong Zhang 
1283b43aa488SJacob Faibussowitsch   Fortran Notes:
128420f4b53cSBarry Smith   Only a single monitor function can be set for each `TS` object
1285814e85d6SHong Zhang 
12861cc06b55SBarry Smith .seealso: [](ch_ts), `TS`, `TSAdjointSolve()`, `TSAdjointMonitorCancel()`
1287814e85d6SHong Zhang @*/
128814d0ab18SJacob Faibussowitsch PetscErrorCode TSAdjointMonitorSet(TS ts, PetscErrorCode (*adjointmonitor)(TS ts, PetscInt steps, PetscReal time, Vec u, PetscInt numcost, Vec *lambda, Vec *mu, void *adjointmctx), void *adjointmctx, PetscErrorCode (*adjointmdestroy)(void **mctx))
1289d71ae5a4SJacob Faibussowitsch {
1290814e85d6SHong Zhang   PetscInt  i;
1291814e85d6SHong Zhang   PetscBool identical;
1292814e85d6SHong Zhang 
1293814e85d6SHong Zhang   PetscFunctionBegin;
1294814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
1295814e85d6SHong Zhang   for (i = 0; i < ts->numbermonitors; i++) {
12969566063dSJacob Faibussowitsch     PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))adjointmonitor, adjointmctx, adjointmdestroy, (PetscErrorCode(*)(void))ts->adjointmonitor[i], ts->adjointmonitorcontext[i], ts->adjointmonitordestroy[i], &identical));
12973ba16761SJacob Faibussowitsch     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
1298814e85d6SHong Zhang   }
12993c633725SBarry Smith   PetscCheck(ts->numberadjointmonitors < MAXTSMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many adjoint monitors set");
1300814e85d6SHong Zhang   ts->adjointmonitor[ts->numberadjointmonitors]          = adjointmonitor;
1301814e85d6SHong Zhang   ts->adjointmonitordestroy[ts->numberadjointmonitors]   = adjointmdestroy;
1302814e85d6SHong Zhang   ts->adjointmonitorcontext[ts->numberadjointmonitors++] = (void *)adjointmctx;
13033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1304814e85d6SHong Zhang }
1305814e85d6SHong Zhang 
1306814e85d6SHong Zhang /*@C
1307814e85d6SHong Zhang   TSAdjointMonitorCancel - Clears all the adjoint monitors that have been set on a time-step object.
1308814e85d6SHong Zhang 
1309c3339decSBarry Smith   Logically Collective
1310814e85d6SHong Zhang 
13112fe279fdSBarry Smith   Input Parameter:
1312bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()`
1313814e85d6SHong Zhang 
1314814e85d6SHong Zhang   Notes:
1315814e85d6SHong Zhang   There is no way to remove a single, specific monitor.
1316814e85d6SHong Zhang 
1317814e85d6SHong Zhang   Level: intermediate
1318814e85d6SHong Zhang 
13191cc06b55SBarry Smith .seealso: [](ch_ts), `TS`, `TSAdjointSolve()`, `TSAdjointMonitorSet()`
1320814e85d6SHong Zhang @*/
1321d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointMonitorCancel(TS ts)
1322d71ae5a4SJacob Faibussowitsch {
1323814e85d6SHong Zhang   PetscInt i;
1324814e85d6SHong Zhang 
1325814e85d6SHong Zhang   PetscFunctionBegin;
1326814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
1327814e85d6SHong Zhang   for (i = 0; i < ts->numberadjointmonitors; i++) {
132848a46eb9SPierre Jolivet     if (ts->adjointmonitordestroy[i]) PetscCall((*ts->adjointmonitordestroy[i])(&ts->adjointmonitorcontext[i]));
1329814e85d6SHong Zhang   }
1330814e85d6SHong Zhang   ts->numberadjointmonitors = 0;
13313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1332814e85d6SHong Zhang }
1333814e85d6SHong Zhang 
1334814e85d6SHong Zhang /*@C
1335814e85d6SHong Zhang   TSAdjointMonitorDefault - the default monitor of adjoint computations
1336814e85d6SHong Zhang 
133714d0ab18SJacob Faibussowitsch   Input Parameters:
133814d0ab18SJacob Faibussowitsch + ts      - the `TS` context
133914d0ab18SJacob Faibussowitsch . step    - iteration number (after the final time step the monitor routine is called with a
134014d0ab18SJacob Faibussowitsch step of -1, this is at the final time which may have been interpolated to)
134114d0ab18SJacob Faibussowitsch . time    - current time
134214d0ab18SJacob Faibussowitsch . v       - current iterate
134314d0ab18SJacob Faibussowitsch . numcost - number of cost functionos
134414d0ab18SJacob Faibussowitsch . lambda  - sensitivities to initial conditions
134514d0ab18SJacob Faibussowitsch . mu      - sensitivities to parameters
134614d0ab18SJacob Faibussowitsch - vf      - the viewer and format
134714d0ab18SJacob Faibussowitsch 
1348814e85d6SHong Zhang   Level: intermediate
1349814e85d6SHong Zhang 
13501cc06b55SBarry Smith .seealso: [](ch_ts), `TS`, `TSAdjointSolve()`, `TSAdjointMonitorSet()`
1351814e85d6SHong Zhang @*/
135214d0ab18SJacob Faibussowitsch PetscErrorCode TSAdjointMonitorDefault(TS ts, PetscInt step, PetscReal time, Vec v, PetscInt numcost, Vec *lambda, Vec *mu, PetscViewerAndFormat *vf)
1353d71ae5a4SJacob Faibussowitsch {
1354814e85d6SHong Zhang   PetscViewer viewer = vf->viewer;
1355814e85d6SHong Zhang 
1356814e85d6SHong Zhang   PetscFunctionBegin;
135714d0ab18SJacob Faibussowitsch   (void)v;
135814d0ab18SJacob Faibussowitsch   (void)numcost;
135914d0ab18SJacob Faibussowitsch   (void)lambda;
136014d0ab18SJacob Faibussowitsch   (void)mu;
1361064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 8);
13629566063dSJacob Faibussowitsch   PetscCall(PetscViewerPushFormat(viewer, vf->format));
13639566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)ts)->tablevel));
136414d0ab18SJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " TS dt %g time %g%s", step, (double)ts->time_step, (double)time, ts->steprollback ? " (r)\n" : "\n"));
13659566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)ts)->tablevel));
13669566063dSJacob Faibussowitsch   PetscCall(PetscViewerPopFormat(viewer));
13673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1368814e85d6SHong Zhang }
1369814e85d6SHong Zhang 
1370814e85d6SHong Zhang /*@C
1371bcf0153eSBarry Smith   TSAdjointMonitorDrawSensi - Monitors progress of the adjoint `TS` solvers by calling
1372bcf0153eSBarry Smith   `VecView()` for the sensitivities to initial states at each timestep
1373814e85d6SHong Zhang 
1374c3339decSBarry Smith   Collective
1375814e85d6SHong Zhang 
1376814e85d6SHong Zhang   Input Parameters:
1377bcf0153eSBarry Smith + ts      - the `TS` context
1378814e85d6SHong Zhang . step    - current time-step
1379814e85d6SHong Zhang . ptime   - current time
1380814e85d6SHong Zhang . u       - current state
1381814e85d6SHong Zhang . numcost - number of cost functions
1382814e85d6SHong Zhang . lambda  - sensitivities to initial conditions
1383814e85d6SHong Zhang . mu      - sensitivities to parameters
13842fe279fdSBarry Smith - dummy   - either a viewer or `NULL`
1385814e85d6SHong Zhang 
1386814e85d6SHong Zhang   Level: intermediate
1387814e85d6SHong Zhang 
13881cc06b55SBarry Smith .seealso: [](ch_ts), `TSAdjointSolve()`, `TSAdjointMonitorSet()`, `TSAdjointMonitorDefault()`, `VecView()`
1389814e85d6SHong Zhang @*/
1390d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointMonitorDrawSensi(TS ts, PetscInt step, PetscReal ptime, Vec u, PetscInt numcost, Vec *lambda, Vec *mu, void *dummy)
1391d71ae5a4SJacob Faibussowitsch {
1392814e85d6SHong Zhang   TSMonitorDrawCtx ictx = (TSMonitorDrawCtx)dummy;
1393814e85d6SHong Zhang   PetscDraw        draw;
1394814e85d6SHong Zhang   PetscReal        xl, yl, xr, yr, h;
1395814e85d6SHong Zhang   char             time[32];
1396814e85d6SHong Zhang 
1397814e85d6SHong Zhang   PetscFunctionBegin;
13983ba16761SJacob Faibussowitsch   if (!(((ictx->howoften > 0) && (!(step % ictx->howoften))) || ((ictx->howoften == -1) && ts->reason))) PetscFunctionReturn(PETSC_SUCCESS);
1399814e85d6SHong Zhang 
14009566063dSJacob Faibussowitsch   PetscCall(VecView(lambda[0], ictx->viewer));
14019566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(ictx->viewer, 0, &draw));
14029566063dSJacob Faibussowitsch   PetscCall(PetscSNPrintf(time, 32, "Timestep %d Time %g", (int)step, (double)ptime));
14039566063dSJacob Faibussowitsch   PetscCall(PetscDrawGetCoordinates(draw, &xl, &yl, &xr, &yr));
1404814e85d6SHong Zhang   h = yl + .95 * (yr - yl);
14059566063dSJacob Faibussowitsch   PetscCall(PetscDrawStringCentered(draw, .5 * (xl + xr), h, PETSC_DRAW_BLACK, time));
14069566063dSJacob Faibussowitsch   PetscCall(PetscDrawFlush(draw));
14073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1408814e85d6SHong Zhang }
1409814e85d6SHong Zhang 
141014d0ab18SJacob Faibussowitsch /*@C
141114d0ab18SJacob Faibussowitsch   TSAdjointSetFromOptions - Sets various `TS` adjoint parameters from options database.
1412814e85d6SHong Zhang 
1413c3339decSBarry Smith   Collective
1414814e85d6SHong Zhang 
141514d0ab18SJacob Faibussowitsch   Input Parameters:
141614d0ab18SJacob Faibussowitsch + ts                 - the `TS` context
141714d0ab18SJacob Faibussowitsch - PetscOptionsObject - the options context
1418814e85d6SHong Zhang 
1419814e85d6SHong Zhang   Options Database Keys:
142014d0ab18SJacob Faibussowitsch + -ts_adjoint_solve <yes,no>     - After solving the ODE/DAE solve the adjoint problem (requires `-ts_save_trajectory`)
1421814e85d6SHong Zhang . -ts_adjoint_monitor            - print information at each adjoint time step
1422814e85d6SHong Zhang - -ts_adjoint_monitor_draw_sensi - monitor the sensitivity of the first cost function wrt initial conditions (lambda[0]) graphically
1423814e85d6SHong Zhang 
1424814e85d6SHong Zhang   Level: developer
1425814e85d6SHong Zhang 
1426bcf0153eSBarry Smith   Note:
1427814e85d6SHong Zhang   This is not normally called directly by users
1428814e85d6SHong Zhang 
14291cc06b55SBarry Smith .seealso: [](ch_ts), `TSSetSaveTrajectory()`, `TSTrajectorySetUp()`
143014d0ab18SJacob Faibussowitsch @*/
1431d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointSetFromOptions(TS ts, PetscOptionItems *PetscOptionsObject)
1432d71ae5a4SJacob Faibussowitsch {
1433814e85d6SHong Zhang   PetscBool tflg, opt;
1434814e85d6SHong Zhang 
1435814e85d6SHong Zhang   PetscFunctionBegin;
1436dbbe0bcdSBarry Smith   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
1437d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "TS Adjoint options");
1438814e85d6SHong Zhang   tflg = ts->adjoint_solve ? PETSC_TRUE : PETSC_FALSE;
14399566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-ts_adjoint_solve", "Solve the adjoint problem immediately after solving the forward problem", "", tflg, &tflg, &opt));
1440814e85d6SHong Zhang   if (opt) {
14419566063dSJacob Faibussowitsch     PetscCall(TSSetSaveTrajectory(ts));
1442814e85d6SHong Zhang     ts->adjoint_solve = tflg;
1443814e85d6SHong Zhang   }
14449566063dSJacob Faibussowitsch   PetscCall(TSAdjointMonitorSetFromOptions(ts, "-ts_adjoint_monitor", "Monitor adjoint timestep size", "TSAdjointMonitorDefault", TSAdjointMonitorDefault, NULL));
14459566063dSJacob Faibussowitsch   PetscCall(TSAdjointMonitorSetFromOptions(ts, "-ts_adjoint_monitor_sensi", "Monitor sensitivity in the adjoint computation", "TSAdjointMonitorSensi", TSAdjointMonitorSensi, NULL));
1446814e85d6SHong Zhang   opt = PETSC_FALSE;
14479566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-ts_adjoint_monitor_draw_sensi", "Monitor adjoint sensitivities (lambda only) graphically", "TSAdjointMonitorDrawSensi", &opt));
1448814e85d6SHong Zhang   if (opt) {
1449814e85d6SHong Zhang     TSMonitorDrawCtx ctx;
1450814e85d6SHong Zhang     PetscInt         howoften = 1;
1451814e85d6SHong Zhang 
14529566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-ts_adjoint_monitor_draw_sensi", "Monitor adjoint sensitivities (lambda only) graphically", "TSAdjointMonitorDrawSensi", howoften, &howoften, NULL));
14539566063dSJacob Faibussowitsch     PetscCall(TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, &ctx));
14549566063dSJacob Faibussowitsch     PetscCall(TSAdjointMonitorSet(ts, TSAdjointMonitorDrawSensi, ctx, (PetscErrorCode(*)(void **))TSMonitorDrawCtxDestroy));
1455814e85d6SHong Zhang   }
14563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1457814e85d6SHong Zhang }
1458814e85d6SHong Zhang 
1459814e85d6SHong Zhang /*@
1460814e85d6SHong Zhang   TSAdjointStep - Steps one time step backward in the adjoint run
1461814e85d6SHong Zhang 
1462c3339decSBarry Smith   Collective
1463814e85d6SHong Zhang 
1464814e85d6SHong Zhang   Input Parameter:
1465bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()`
1466814e85d6SHong Zhang 
1467814e85d6SHong Zhang   Level: intermediate
1468814e85d6SHong Zhang 
14691cc06b55SBarry Smith .seealso: [](ch_ts), `TSAdjointSetUp()`, `TSAdjointSolve()`
1470814e85d6SHong Zhang @*/
1471d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointStep(TS ts)
1472d71ae5a4SJacob Faibussowitsch {
1473814e85d6SHong Zhang   DM dm;
1474814e85d6SHong Zhang 
1475814e85d6SHong Zhang   PetscFunctionBegin;
1476814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
14779566063dSJacob Faibussowitsch   PetscCall(TSGetDM(ts, &dm));
14789566063dSJacob Faibussowitsch   PetscCall(TSAdjointSetUp(ts));
14797b0e2f17SHong Zhang   ts->steps--; /* must decrease the step index before the adjoint step is taken. */
1480814e85d6SHong Zhang 
1481814e85d6SHong Zhang   ts->reason     = TS_CONVERGED_ITERATING;
1482814e85d6SHong Zhang   ts->ptime_prev = ts->ptime;
14839566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(TS_AdjointStep, ts, 0, 0, 0));
1484dbbe0bcdSBarry Smith   PetscUseTypeMethod(ts, adjointstep);
14859566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(TS_AdjointStep, ts, 0, 0, 0));
14867b0e2f17SHong Zhang   ts->adjoint_steps++;
1487814e85d6SHong Zhang 
1488814e85d6SHong Zhang   if (ts->reason < 0) {
14893c633725SBarry Smith     PetscCheck(!ts->errorifstepfailed, PetscObjectComm((PetscObject)ts), PETSC_ERR_NOT_CONVERGED, "TSAdjointStep has failed due to %s", TSConvergedReasons[ts->reason]);
1490814e85d6SHong Zhang   } else if (!ts->reason) {
1491814e85d6SHong Zhang     if (ts->adjoint_steps >= ts->adjoint_max_steps) ts->reason = TS_CONVERGED_ITS;
1492814e85d6SHong Zhang   }
14933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1494814e85d6SHong Zhang }
1495814e85d6SHong Zhang 
1496814e85d6SHong Zhang /*@
1497814e85d6SHong Zhang   TSAdjointSolve - Solves the discrete ajoint problem for an ODE/DAE
1498814e85d6SHong Zhang 
1499c3339decSBarry Smith   Collective
1500bcf0153eSBarry Smith   `
1501b43aa488SJacob Faibussowitsch 
1502814e85d6SHong Zhang   Input Parameter:
1503bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()`
1504814e85d6SHong Zhang 
1505bcf0153eSBarry Smith   Options Database Key:
1506814e85d6SHong Zhang . -ts_adjoint_view_solution <viewerinfo> - views the first gradient with respect to the initial values
1507814e85d6SHong Zhang 
1508814e85d6SHong Zhang   Level: intermediate
1509814e85d6SHong Zhang 
1510814e85d6SHong Zhang   Notes:
1511bcf0153eSBarry Smith   This must be called after a call to `TSSolve()` that solves the forward problem
1512814e85d6SHong Zhang 
1513bcf0153eSBarry Smith   By default this will integrate back to the initial time, one can use `TSAdjointSetSteps()` to step back to a later time
1514814e85d6SHong Zhang 
151542747ad1SJacob Faibussowitsch .seealso: [](ch_ts), `TSCreate()`, `TSSetCostGradients()`, `TSSetSolution()`, `TSAdjointStep()`
1516814e85d6SHong Zhang @*/
1517d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointSolve(TS ts)
1518d71ae5a4SJacob Faibussowitsch {
1519f1d62c27SHong Zhang   static PetscBool cite = PETSC_FALSE;
15207f59fb53SHong Zhang #if defined(TSADJOINT_STAGE)
15217f59fb53SHong Zhang   PetscLogStage adjoint_stage;
15227f59fb53SHong Zhang #endif
1523814e85d6SHong Zhang 
1524814e85d6SHong Zhang   PetscFunctionBegin;
1525814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
1526421b783aSHong Zhang   PetscCall(PetscCitationsRegister("@article{Zhang2022tsadjoint,\n"
1527421b783aSHong Zhang                                    "  title         = {{PETSc TSAdjoint: A Discrete Adjoint ODE Solver for First-Order and Second-Order Sensitivity Analysis}},\n"
1528f1d62c27SHong Zhang                                    "  author        = {Zhang, Hong and Constantinescu, Emil M.  and Smith, Barry F.},\n"
1529421b783aSHong Zhang                                    "  journal       = {SIAM Journal on Scientific Computing},\n"
1530421b783aSHong Zhang                                    "  volume        = {44},\n"
1531421b783aSHong Zhang                                    "  number        = {1},\n"
1532421b783aSHong Zhang                                    "  pages         = {C1-C24},\n"
1533421b783aSHong Zhang                                    "  doi           = {10.1137/21M140078X},\n"
15349371c9d4SSatish Balay                                    "  year          = {2022}\n}\n",
15359371c9d4SSatish Balay                                    &cite));
15367f59fb53SHong Zhang #if defined(TSADJOINT_STAGE)
15379566063dSJacob Faibussowitsch   PetscCall(PetscLogStageRegister("TSAdjoint", &adjoint_stage));
15389566063dSJacob Faibussowitsch   PetscCall(PetscLogStagePush(adjoint_stage));
15397f59fb53SHong Zhang #endif
15409566063dSJacob Faibussowitsch   PetscCall(TSAdjointSetUp(ts));
1541814e85d6SHong Zhang 
1542814e85d6SHong Zhang   /* reset time step and iteration counters */
1543814e85d6SHong Zhang   ts->adjoint_steps     = 0;
1544814e85d6SHong Zhang   ts->ksp_its           = 0;
1545814e85d6SHong Zhang   ts->snes_its          = 0;
1546814e85d6SHong Zhang   ts->num_snes_failures = 0;
1547814e85d6SHong Zhang   ts->reject            = 0;
1548814e85d6SHong Zhang   ts->reason            = TS_CONVERGED_ITERATING;
1549814e85d6SHong Zhang 
1550814e85d6SHong Zhang   if (!ts->adjoint_max_steps) ts->adjoint_max_steps = ts->steps;
1551814e85d6SHong Zhang   if (ts->adjoint_steps >= ts->adjoint_max_steps) ts->reason = TS_CONVERGED_ITS;
1552814e85d6SHong Zhang 
1553814e85d6SHong Zhang   while (!ts->reason) {
15549566063dSJacob Faibussowitsch     PetscCall(TSTrajectoryGet(ts->trajectory, ts, ts->steps, &ts->ptime));
15559566063dSJacob Faibussowitsch     PetscCall(TSAdjointMonitor(ts, ts->steps, ts->ptime, ts->vec_sol, ts->numcost, ts->vecs_sensi, ts->vecs_sensip));
15569566063dSJacob Faibussowitsch     PetscCall(TSAdjointEventHandler(ts));
15579566063dSJacob Faibussowitsch     PetscCall(TSAdjointStep(ts));
155848a46eb9SPierre Jolivet     if ((ts->vec_costintegral || ts->quadraturets) && !ts->costintegralfwd) PetscCall(TSAdjointCostIntegral(ts));
1559814e85d6SHong Zhang   }
1560bdbff044SHong Zhang   if (!ts->steps) {
15619566063dSJacob Faibussowitsch     PetscCall(TSTrajectoryGet(ts->trajectory, ts, ts->steps, &ts->ptime));
15629566063dSJacob Faibussowitsch     PetscCall(TSAdjointMonitor(ts, ts->steps, ts->ptime, ts->vec_sol, ts->numcost, ts->vecs_sensi, ts->vecs_sensip));
1563bdbff044SHong Zhang   }
1564814e85d6SHong Zhang   ts->solvetime = ts->ptime;
15659566063dSJacob Faibussowitsch   PetscCall(TSTrajectoryViewFromOptions(ts->trajectory, NULL, "-ts_trajectory_view"));
15669566063dSJacob Faibussowitsch   PetscCall(VecViewFromOptions(ts->vecs_sensi[0], (PetscObject)ts, "-ts_adjoint_view_solution"));
1567814e85d6SHong Zhang   ts->adjoint_max_steps = 0;
15687f59fb53SHong Zhang #if defined(TSADJOINT_STAGE)
15699566063dSJacob Faibussowitsch   PetscCall(PetscLogStagePop());
15707f59fb53SHong Zhang #endif
15713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1572814e85d6SHong Zhang }
1573814e85d6SHong Zhang 
1574814e85d6SHong Zhang /*@C
1575bcf0153eSBarry Smith   TSAdjointMonitor - Runs all user-provided adjoint monitor routines set using `TSAdjointMonitorSet()`
1576814e85d6SHong Zhang 
1577c3339decSBarry Smith   Collective
1578814e85d6SHong Zhang 
1579814e85d6SHong Zhang   Input Parameters:
1580bcf0153eSBarry Smith + ts      - time stepping context obtained from `TSCreate()`
1581814e85d6SHong Zhang . step    - step number that has just completed
1582814e85d6SHong Zhang . ptime   - model time of the state
1583814e85d6SHong Zhang . u       - state at the current model time
1584814e85d6SHong Zhang . numcost - number of cost functions (dimension of lambda  or mu)
1585814e85d6SHong Zhang . lambda  - vectors containing the gradients of the cost functions with respect to the ODE/DAE solution variables
1586814e85d6SHong Zhang - mu      - vectors containing the gradients of the cost functions with respect to the problem parameters
1587814e85d6SHong Zhang 
1588814e85d6SHong Zhang   Level: developer
1589814e85d6SHong Zhang 
1590bcf0153eSBarry Smith   Note:
1591bcf0153eSBarry Smith   `TSAdjointMonitor()` is typically used automatically within the time stepping implementations.
1592bcf0153eSBarry Smith   Users would almost never call this routine directly.
1593bcf0153eSBarry Smith 
1594bcf0153eSBarry Smith .seealso: `TSAdjointMonitorSet()`, `TSAdjointSolve()`
1595814e85d6SHong Zhang @*/
1596d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointMonitor(TS ts, PetscInt step, PetscReal ptime, Vec u, PetscInt numcost, Vec *lambda, Vec *mu)
1597d71ae5a4SJacob Faibussowitsch {
1598814e85d6SHong Zhang   PetscInt i, n = ts->numberadjointmonitors;
1599814e85d6SHong Zhang 
1600814e85d6SHong Zhang   PetscFunctionBegin;
1601814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
1602814e85d6SHong Zhang   PetscValidHeaderSpecific(u, VEC_CLASSID, 4);
16039566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(u));
160448a46eb9SPierre Jolivet   for (i = 0; i < n; i++) PetscCall((*ts->adjointmonitor[i])(ts, step, ptime, u, numcost, lambda, mu, ts->adjointmonitorcontext[i]));
16059566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(u));
16063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1607814e85d6SHong Zhang }
1608814e85d6SHong Zhang 
1609814e85d6SHong Zhang /*@
1610814e85d6SHong Zhang   TSAdjointCostIntegral - Evaluate the cost integral in the adjoint run.
1611814e85d6SHong Zhang 
1612c3339decSBarry Smith   Collective
1613814e85d6SHong Zhang 
16144165533cSJose E. Roman   Input Parameter:
1615814e85d6SHong Zhang . ts - time stepping context
1616814e85d6SHong Zhang 
1617814e85d6SHong Zhang   Level: advanced
1618814e85d6SHong Zhang 
1619814e85d6SHong Zhang   Notes:
1620bcf0153eSBarry Smith   This function cannot be called until `TSAdjointStep()` has been completed.
1621814e85d6SHong Zhang 
16221cc06b55SBarry Smith .seealso: [](ch_ts), `TSAdjointSolve()`, `TSAdjointStep()`
1623814e85d6SHong Zhang  @*/
1624d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointCostIntegral(TS ts)
1625d71ae5a4SJacob Faibussowitsch {
1626362febeeSStefano Zampini   PetscFunctionBegin;
1627814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
1628dbbe0bcdSBarry Smith   PetscUseTypeMethod(ts, adjointintegral);
16293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1630814e85d6SHong Zhang }
1631814e85d6SHong Zhang 
1632814e85d6SHong Zhang /* ------------------ Forward (tangent linear) sensitivity  ------------------*/
1633814e85d6SHong Zhang 
1634814e85d6SHong Zhang /*@
1635814e85d6SHong Zhang   TSForwardSetUp - Sets up the internal data structures for the later use
1636814e85d6SHong Zhang   of forward sensitivity analysis
1637814e85d6SHong Zhang 
1638c3339decSBarry Smith   Collective
1639814e85d6SHong Zhang 
1640814e85d6SHong Zhang   Input Parameter:
1641bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()`
1642814e85d6SHong Zhang 
1643814e85d6SHong Zhang   Level: advanced
1644814e85d6SHong Zhang 
16451cc06b55SBarry Smith .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSDestroy()`, `TSSetUp()`
1646814e85d6SHong Zhang @*/
1647d71ae5a4SJacob Faibussowitsch PetscErrorCode TSForwardSetUp(TS ts)
1648d71ae5a4SJacob Faibussowitsch {
1649814e85d6SHong Zhang   PetscFunctionBegin;
1650814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
16513ba16761SJacob Faibussowitsch   if (ts->forwardsetupcalled) PetscFunctionReturn(PETSC_SUCCESS);
1652dbbe0bcdSBarry Smith   PetscTryTypeMethod(ts, forwardsetup);
16539566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(ts->vec_sol, &ts->vec_sensip_col));
1654814e85d6SHong Zhang   ts->forwardsetupcalled = PETSC_TRUE;
16553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1656814e85d6SHong Zhang }
1657814e85d6SHong Zhang 
1658814e85d6SHong Zhang /*@
16597adebddeSHong Zhang   TSForwardReset - Reset the internal data structures used by forward sensitivity analysis
16607adebddeSHong Zhang 
1661c3339decSBarry Smith   Collective
16627adebddeSHong Zhang 
16637adebddeSHong Zhang   Input Parameter:
1664bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()`
16657adebddeSHong Zhang 
16667adebddeSHong Zhang   Level: advanced
16677adebddeSHong Zhang 
16681cc06b55SBarry Smith .seealso: [](ch_ts), `TSCreate()`, `TSDestroy()`, `TSForwardSetUp()`
16697adebddeSHong Zhang @*/
1670d71ae5a4SJacob Faibussowitsch PetscErrorCode TSForwardReset(TS ts)
1671d71ae5a4SJacob Faibussowitsch {
16727207e0fdSHong Zhang   TS quadts = ts->quadraturets;
16737adebddeSHong Zhang 
16747adebddeSHong Zhang   PetscFunctionBegin;
16757adebddeSHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
1676dbbe0bcdSBarry Smith   PetscTryTypeMethod(ts, forwardreset);
16779566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&ts->mat_sensip));
167848a46eb9SPierre Jolivet   if (quadts) PetscCall(MatDestroy(&quadts->mat_sensip));
16799566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&ts->vec_sensip_col));
16807adebddeSHong Zhang   ts->forward_solve      = PETSC_FALSE;
16817adebddeSHong Zhang   ts->forwardsetupcalled = PETSC_FALSE;
16823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16837adebddeSHong Zhang }
16847adebddeSHong Zhang 
16857adebddeSHong Zhang /*@
1686814e85d6SHong Zhang   TSForwardSetIntegralGradients - Set the vectors holding forward sensitivities of the integral term.
1687814e85d6SHong Zhang 
1688d8d19677SJose E. Roman   Input Parameters:
1689bcf0153eSBarry Smith + ts        - the `TS` context obtained from `TSCreate()`
1690814e85d6SHong Zhang . numfwdint - number of integrals
169167b8a455SSatish Balay - vp        - the vectors containing the gradients for each integral w.r.t. parameters
1692814e85d6SHong Zhang 
16937207e0fdSHong Zhang   Level: deprecated
1694814e85d6SHong Zhang 
169542747ad1SJacob Faibussowitsch .seealso: [](ch_ts), `TSForwardGetSensitivities()`, `TSForwardGetIntegralGradients()`, `TSForwardStep()`
1696814e85d6SHong Zhang @*/
1697d71ae5a4SJacob Faibussowitsch PetscErrorCode TSForwardSetIntegralGradients(TS ts, PetscInt numfwdint, Vec *vp)
1698d71ae5a4SJacob Faibussowitsch {
1699814e85d6SHong Zhang   PetscFunctionBegin;
1700814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
17013c633725SBarry 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()");
1702814e85d6SHong Zhang   if (!ts->numcost) ts->numcost = numfwdint;
1703814e85d6SHong Zhang 
1704814e85d6SHong Zhang   ts->vecs_integral_sensip = vp;
17053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1706814e85d6SHong Zhang }
1707814e85d6SHong Zhang 
1708814e85d6SHong Zhang /*@
1709814e85d6SHong Zhang   TSForwardGetIntegralGradients - Returns the forward sensitivities of the integral term.
1710814e85d6SHong Zhang 
1711814e85d6SHong Zhang   Input Parameter:
1712bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()`
1713814e85d6SHong Zhang 
171414d0ab18SJacob Faibussowitsch   Output Parameters:
171514d0ab18SJacob Faibussowitsch + numfwdint - number of integrals
171614d0ab18SJacob Faibussowitsch - vp        - the vectors containing the gradients for each integral w.r.t. parameters
1717814e85d6SHong Zhang 
17187207e0fdSHong Zhang   Level: deprecated
1719814e85d6SHong Zhang 
172042747ad1SJacob Faibussowitsch .seealso: [](ch_ts), `TSForwardSetSensitivities()`, `TSForwardSetIntegralGradients()`, `TSForwardStep()`
1721814e85d6SHong Zhang @*/
1722d71ae5a4SJacob Faibussowitsch PetscErrorCode TSForwardGetIntegralGradients(TS ts, PetscInt *numfwdint, Vec **vp)
1723d71ae5a4SJacob Faibussowitsch {
1724814e85d6SHong Zhang   PetscFunctionBegin;
1725814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
17264f572ea9SToby Isaac   PetscAssertPointer(vp, 3);
1727814e85d6SHong Zhang   if (numfwdint) *numfwdint = ts->numcost;
1728814e85d6SHong Zhang   if (vp) *vp = ts->vecs_integral_sensip;
17293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1730814e85d6SHong Zhang }
1731814e85d6SHong Zhang 
1732814e85d6SHong Zhang /*@
1733814e85d6SHong Zhang   TSForwardStep - Compute the forward sensitivity for one time step.
1734814e85d6SHong Zhang 
1735c3339decSBarry Smith   Collective
1736814e85d6SHong Zhang 
17374165533cSJose E. Roman   Input Parameter:
1738814e85d6SHong Zhang . ts - time stepping context
1739814e85d6SHong Zhang 
1740814e85d6SHong Zhang   Level: advanced
1741814e85d6SHong Zhang 
1742814e85d6SHong Zhang   Notes:
1743bcf0153eSBarry Smith   This function cannot be called until `TSStep()` has been completed.
1744814e85d6SHong Zhang 
17451cc06b55SBarry Smith .seealso: [](ch_ts), `TSForwardSetSensitivities()`, `TSForwardGetSensitivities()`, `TSForwardSetIntegralGradients()`, `TSForwardGetIntegralGradients()`, `TSForwardSetUp()`
1746814e85d6SHong Zhang @*/
1747d71ae5a4SJacob Faibussowitsch PetscErrorCode TSForwardStep(TS ts)
1748d71ae5a4SJacob Faibussowitsch {
1749362febeeSStefano Zampini   PetscFunctionBegin;
1750814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
17519566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(TS_ForwardStep, ts, 0, 0, 0));
1752dbbe0bcdSBarry Smith   PetscUseTypeMethod(ts, forwardstep);
17539566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(TS_ForwardStep, ts, 0, 0, 0));
17543c633725SBarry Smith   PetscCheck(ts->reason >= 0 || !ts->errorifstepfailed, PetscObjectComm((PetscObject)ts), PETSC_ERR_NOT_CONVERGED, "TSFowardStep has failed due to %s", TSConvergedReasons[ts->reason]);
17553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1756814e85d6SHong Zhang }
1757814e85d6SHong Zhang 
1758814e85d6SHong Zhang /*@
1759814e85d6SHong Zhang   TSForwardSetSensitivities - Sets the initial value of the trajectory sensitivities of solution  w.r.t. the problem parameters and initial values.
1760814e85d6SHong Zhang 
1761c3339decSBarry Smith   Logically Collective
1762814e85d6SHong Zhang 
1763814e85d6SHong Zhang   Input Parameters:
1764bcf0153eSBarry Smith + ts   - the `TS` context obtained from `TSCreate()`
1765814e85d6SHong Zhang . nump - number of parameters
1766814e85d6SHong Zhang - Smat - sensitivities with respect to the parameters, the number of entries in these vectors is the same as the number of parameters
1767814e85d6SHong Zhang 
1768814e85d6SHong Zhang   Level: beginner
1769814e85d6SHong Zhang 
1770814e85d6SHong Zhang   Notes:
1771814e85d6SHong Zhang   Forward sensitivity is also called 'trajectory sensitivity' in some fields such as power systems.
1772bcf0153eSBarry Smith   This function turns on a flag to trigger `TSSolve()` to compute forward sensitivities automatically.
1773bcf0153eSBarry Smith   You must call this function before `TSSolve()`.
1774814e85d6SHong Zhang   The entries in the sensitivity matrix must be correctly initialized with the values S = dy/dp|startingtime.
1775814e85d6SHong Zhang 
17761cc06b55SBarry Smith .seealso: [](ch_ts), `TSForwardGetSensitivities()`, `TSForwardSetIntegralGradients()`, `TSForwardGetIntegralGradients()`, `TSForwardStep()`
1777814e85d6SHong Zhang @*/
1778d71ae5a4SJacob Faibussowitsch PetscErrorCode TSForwardSetSensitivities(TS ts, PetscInt nump, Mat Smat)
1779d71ae5a4SJacob Faibussowitsch {
1780814e85d6SHong Zhang   PetscFunctionBegin;
1781814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
1782814e85d6SHong Zhang   PetscValidHeaderSpecific(Smat, MAT_CLASSID, 3);
1783814e85d6SHong Zhang   ts->forward_solve = PETSC_TRUE;
1784b5b4017aSHong Zhang   if (nump == PETSC_DEFAULT) {
17859566063dSJacob Faibussowitsch     PetscCall(MatGetSize(Smat, NULL, &ts->num_parameters));
1786b5b4017aSHong Zhang   } else ts->num_parameters = nump;
17879566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)Smat));
17889566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&ts->mat_sensip));
1789814e85d6SHong Zhang   ts->mat_sensip = Smat;
17903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1791814e85d6SHong Zhang }
1792814e85d6SHong Zhang 
1793814e85d6SHong Zhang /*@
1794814e85d6SHong Zhang   TSForwardGetSensitivities - Returns the trajectory sensitivities
1795814e85d6SHong Zhang 
1796bcf0153eSBarry Smith   Not Collective, but Smat returned is parallel if ts is parallel
1797814e85d6SHong Zhang 
1798d8d19677SJose E. Roman   Output Parameters:
1799bcf0153eSBarry Smith + ts   - the `TS` context obtained from `TSCreate()`
1800814e85d6SHong Zhang . nump - number of parameters
1801814e85d6SHong Zhang - Smat - sensitivities with respect to the parameters, the number of entries in these vectors is the same as the number of parameters
1802814e85d6SHong Zhang 
1803814e85d6SHong Zhang   Level: intermediate
1804814e85d6SHong Zhang 
18051cc06b55SBarry Smith .seealso: [](ch_ts), `TSForwardSetSensitivities()`, `TSForwardSetIntegralGradients()`, `TSForwardGetIntegralGradients()`, `TSForwardStep()`
1806814e85d6SHong Zhang @*/
1807d71ae5a4SJacob Faibussowitsch PetscErrorCode TSForwardGetSensitivities(TS ts, PetscInt *nump, Mat *Smat)
1808d71ae5a4SJacob Faibussowitsch {
1809814e85d6SHong Zhang   PetscFunctionBegin;
1810814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
1811814e85d6SHong Zhang   if (nump) *nump = ts->num_parameters;
1812814e85d6SHong Zhang   if (Smat) *Smat = ts->mat_sensip;
18133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1814814e85d6SHong Zhang }
1815814e85d6SHong Zhang 
1816814e85d6SHong Zhang /*@
1817814e85d6SHong Zhang   TSForwardCostIntegral - Evaluate the cost integral in the forward run.
1818814e85d6SHong Zhang 
1819c3339decSBarry Smith   Collective
1820814e85d6SHong Zhang 
18214165533cSJose E. Roman   Input Parameter:
1822814e85d6SHong Zhang . ts - time stepping context
1823814e85d6SHong Zhang 
1824814e85d6SHong Zhang   Level: advanced
1825814e85d6SHong Zhang 
1826bcf0153eSBarry Smith   Note:
1827bcf0153eSBarry Smith   This function cannot be called until `TSStep()` has been completed.
1828814e85d6SHong Zhang 
18291cc06b55SBarry Smith .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSAdjointCostIntegral()`
1830814e85d6SHong Zhang @*/
1831d71ae5a4SJacob Faibussowitsch PetscErrorCode TSForwardCostIntegral(TS ts)
1832d71ae5a4SJacob Faibussowitsch {
1833362febeeSStefano Zampini   PetscFunctionBegin;
1834814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
1835dbbe0bcdSBarry Smith   PetscUseTypeMethod(ts, forwardintegral);
18363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1837814e85d6SHong Zhang }
1838b5b4017aSHong Zhang 
1839b5b4017aSHong Zhang /*@
1840b5b4017aSHong Zhang   TSForwardSetInitialSensitivities - Set initial values for tangent linear sensitivities
1841b5b4017aSHong Zhang 
1842c3339decSBarry Smith   Collective
1843b5b4017aSHong Zhang 
1844d8d19677SJose E. Roman   Input Parameters:
1845bcf0153eSBarry Smith + ts   - the `TS` context obtained from `TSCreate()`
1846b5b4017aSHong Zhang - didp - parametric sensitivities of the initial condition
1847b5b4017aSHong Zhang 
1848b5b4017aSHong Zhang   Level: intermediate
1849b5b4017aSHong Zhang 
1850bcf0153eSBarry Smith   Notes:
1851bcf0153eSBarry Smith   `TSSolve()` allows users to pass the initial solution directly to `TS`. But the tangent linear variables cannot be initialized in this way.
1852bcf0153eSBarry Smith   This function is used to set initial values for tangent linear variables.
1853b5b4017aSHong Zhang 
18541cc06b55SBarry Smith .seealso: [](ch_ts), `TS`, `TSForwardSetSensitivities()`
1855b5b4017aSHong Zhang @*/
1856d71ae5a4SJacob Faibussowitsch PetscErrorCode TSForwardSetInitialSensitivities(TS ts, Mat didp)
1857d71ae5a4SJacob Faibussowitsch {
1858362febeeSStefano Zampini   PetscFunctionBegin;
1859b5b4017aSHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
1860b5b4017aSHong Zhang   PetscValidHeaderSpecific(didp, MAT_CLASSID, 2);
186148a46eb9SPierre Jolivet   if (!ts->mat_sensip) PetscCall(TSForwardSetSensitivities(ts, PETSC_DEFAULT, didp));
18623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1863b5b4017aSHong Zhang }
18646affb6f8SHong Zhang 
18656affb6f8SHong Zhang /*@
18666affb6f8SHong Zhang   TSForwardGetStages - Get the number of stages and the tangent linear sensitivities at the intermediate stages
18676affb6f8SHong Zhang 
18686affb6f8SHong Zhang   Input Parameter:
1869bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()`
18706affb6f8SHong Zhang 
18716affb6f8SHong Zhang   Output Parameters:
1872cd4cee2dSHong Zhang + ns - number of stages
18736affb6f8SHong Zhang - S  - tangent linear sensitivities at the intermediate stages
18746affb6f8SHong Zhang 
18756affb6f8SHong Zhang   Level: advanced
18766affb6f8SHong Zhang 
1877bcf0153eSBarry Smith .seealso: `TS`
18786affb6f8SHong Zhang @*/
1879d71ae5a4SJacob Faibussowitsch PetscErrorCode TSForwardGetStages(TS ts, PetscInt *ns, Mat **S)
1880d71ae5a4SJacob Faibussowitsch {
18816affb6f8SHong Zhang   PetscFunctionBegin;
18826affb6f8SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
18836affb6f8SHong Zhang 
18846affb6f8SHong Zhang   if (!ts->ops->getstages) *S = NULL;
1885dbbe0bcdSBarry Smith   else PetscUseTypeMethod(ts, forwardgetstages, ns, S);
18863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18876affb6f8SHong Zhang }
1888cd4cee2dSHong Zhang 
1889cd4cee2dSHong Zhang /*@
1890bcf0153eSBarry Smith   TSCreateQuadratureTS - Create a sub-`TS` that evaluates integrals over time
1891cd4cee2dSHong Zhang 
1892d8d19677SJose E. Roman   Input Parameters:
1893bcf0153eSBarry Smith + ts  - the `TS` context obtained from `TSCreate()`
1894cd4cee2dSHong Zhang - fwd - flag indicating whether to evaluate cost integral in the forward run or the adjoint run
1895cd4cee2dSHong Zhang 
18962fe279fdSBarry Smith   Output Parameter:
1897bcf0153eSBarry Smith . quadts - the child `TS` context
1898cd4cee2dSHong Zhang 
1899cd4cee2dSHong Zhang   Level: intermediate
1900cd4cee2dSHong Zhang 
19011cc06b55SBarry Smith .seealso: [](ch_ts), `TSGetQuadratureTS()`
1902cd4cee2dSHong Zhang @*/
1903d71ae5a4SJacob Faibussowitsch PetscErrorCode TSCreateQuadratureTS(TS ts, PetscBool fwd, TS *quadts)
1904d71ae5a4SJacob Faibussowitsch {
1905cd4cee2dSHong Zhang   char prefix[128];
1906cd4cee2dSHong Zhang 
1907cd4cee2dSHong Zhang   PetscFunctionBegin;
1908cd4cee2dSHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
19094f572ea9SToby Isaac   PetscAssertPointer(quadts, 3);
19109566063dSJacob Faibussowitsch   PetscCall(TSDestroy(&ts->quadraturets));
19119566063dSJacob Faibussowitsch   PetscCall(TSCreate(PetscObjectComm((PetscObject)ts), &ts->quadraturets));
19129566063dSJacob Faibussowitsch   PetscCall(PetscObjectIncrementTabLevel((PetscObject)ts->quadraturets, (PetscObject)ts, 1));
19139566063dSJacob Faibussowitsch   PetscCall(PetscSNPrintf(prefix, sizeof(prefix), "%squad_", ((PetscObject)ts)->prefix ? ((PetscObject)ts)->prefix : ""));
19149566063dSJacob Faibussowitsch   PetscCall(TSSetOptionsPrefix(ts->quadraturets, prefix));
1915cd4cee2dSHong Zhang   *quadts = ts->quadraturets;
1916cd4cee2dSHong Zhang 
1917cd4cee2dSHong Zhang   if (ts->numcost) {
19189566063dSJacob Faibussowitsch     PetscCall(VecCreateSeq(PETSC_COMM_SELF, ts->numcost, &(*quadts)->vec_sol));
1919cd4cee2dSHong Zhang   } else {
19209566063dSJacob Faibussowitsch     PetscCall(VecCreateSeq(PETSC_COMM_SELF, 1, &(*quadts)->vec_sol));
1921cd4cee2dSHong Zhang   }
1922cd4cee2dSHong Zhang   ts->costintegralfwd = fwd;
19233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1924cd4cee2dSHong Zhang }
1925cd4cee2dSHong Zhang 
1926cd4cee2dSHong Zhang /*@
1927bcf0153eSBarry Smith   TSGetQuadratureTS - Return the sub-`TS` that evaluates integrals over time
1928cd4cee2dSHong Zhang 
1929cd4cee2dSHong Zhang   Input Parameter:
1930bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()`
1931cd4cee2dSHong Zhang 
1932cd4cee2dSHong Zhang   Output Parameters:
1933cd4cee2dSHong Zhang + fwd    - flag indicating whether to evaluate cost integral in the forward run or the adjoint run
1934bcf0153eSBarry Smith - quadts - the child `TS` context
1935cd4cee2dSHong Zhang 
1936cd4cee2dSHong Zhang   Level: intermediate
1937cd4cee2dSHong Zhang 
19381cc06b55SBarry Smith .seealso: [](ch_ts), `TSCreateQuadratureTS()`
1939cd4cee2dSHong Zhang @*/
1940d71ae5a4SJacob Faibussowitsch PetscErrorCode TSGetQuadratureTS(TS ts, PetscBool *fwd, TS *quadts)
1941d71ae5a4SJacob Faibussowitsch {
1942cd4cee2dSHong Zhang   PetscFunctionBegin;
1943cd4cee2dSHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
1944cd4cee2dSHong Zhang   if (fwd) *fwd = ts->costintegralfwd;
1945cd4cee2dSHong Zhang   if (quadts) *quadts = ts->quadraturets;
19463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1947cd4cee2dSHong Zhang }
1948ba0675f6SHong Zhang 
1949ba0675f6SHong Zhang /*@
1950bcf0153eSBarry Smith   TSComputeSNESJacobian - Compute the Jacobian needed for the `SNESSolve()` in `TS`
1951bcf0153eSBarry Smith 
1952c3339decSBarry Smith   Collective
1953ba0675f6SHong Zhang 
1954ba0675f6SHong Zhang   Input Parameters:
1955bcf0153eSBarry Smith + ts - the `TS` context obtained from `TSCreate()`
1956ba0675f6SHong Zhang - x  - state vector
1957ba0675f6SHong Zhang 
1958ba0675f6SHong Zhang   Output Parameters:
1959ba0675f6SHong Zhang + J    - Jacobian matrix
1960ba0675f6SHong Zhang - Jpre - preconditioning matrix for J (may be same as J)
1961ba0675f6SHong Zhang 
1962ba0675f6SHong Zhang   Level: developer
1963ba0675f6SHong Zhang 
1964bcf0153eSBarry Smith   Note:
1965bcf0153eSBarry Smith   Uses finite differencing when `TS` Jacobian is not available.
1966bcf0153eSBarry Smith 
1967b43aa488SJacob Faibussowitsch .seealso: `SNES`, `TS`, `SNESSetJacobian()`, `TSSetRHSJacobian()`, `TSSetIJacobian()`
1968ba0675f6SHong Zhang @*/
1969d71ae5a4SJacob Faibussowitsch PetscErrorCode TSComputeSNESJacobian(TS ts, Vec x, Mat J, Mat Jpre)
1970d71ae5a4SJacob Faibussowitsch {
1971ba0675f6SHong Zhang   SNES snes                                          = ts->snes;
1972ba0675f6SHong Zhang   PetscErrorCode (*jac)(SNES, Vec, Mat, Mat, void *) = NULL;
1973ba0675f6SHong Zhang 
1974ba0675f6SHong Zhang   PetscFunctionBegin;
1975ba0675f6SHong Zhang   /*
1976ba0675f6SHong Zhang     Unlike implicit methods, explicit methods do not have SNESMatFDColoring in the snes object
1977ba0675f6SHong Zhang     because SNESSolve() has not been called yet; so querying SNESMatFDColoring does not work for
1978da81f932SPierre Jolivet     explicit methods. Instead, we check the Jacobian compute function directly to determine if FD
1979ba0675f6SHong Zhang     coloring is used.
1980ba0675f6SHong Zhang   */
19819566063dSJacob Faibussowitsch   PetscCall(SNESGetJacobian(snes, NULL, NULL, &jac, NULL));
1982ba0675f6SHong Zhang   if (jac == SNESComputeJacobianDefaultColor) {
1983ba0675f6SHong Zhang     Vec f;
19849566063dSJacob Faibussowitsch     PetscCall(SNESSetSolution(snes, x));
19859566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, &f, NULL, NULL));
1986ba0675f6SHong Zhang     /* Force MatFDColoringApply to evaluate the SNES residual function for the base vector */
19879566063dSJacob Faibussowitsch     PetscCall(SNESComputeFunction(snes, x, f));
1988ba0675f6SHong Zhang   }
19899566063dSJacob Faibussowitsch   PetscCall(SNESComputeJacobian(snes, x, J, Jpre));
19903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1991ba0675f6SHong Zhang }
1992