xref: /petsc/src/ts/interface/sensitivity/tssen.c (revision 4e8208cbcbc709572b8abe32f33c78b69c819375)
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
1190907b5bSBarry Smith   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 @*/
TSSetRHSJacobianP(TS ts,Mat Amat,TSRHSJacobianPFn * func,PetscCtx ctx)28*2a8381b2SBarry Smith PetscErrorCode TSSetRHSJacobianP(TS ts, Mat Amat, TSRHSJacobianPFn *func, PetscCtx 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
4590907b5bSBarry Smith   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 @*/
TSGetRHSJacobianP(TS ts,Mat * Amat,TSRHSJacobianPFn ** func,PetscCtxRt ctx)64*2a8381b2SBarry Smith PetscErrorCode TSGetRHSJacobianP(TS ts, Mat *Amat, TSRHSJacobianPFn **func, PetscCtxRt ctx)
65d71ae5a4SJacob Faibussowitsch {
66cd4cee2dSHong Zhang   PetscFunctionBegin;
67cd4cee2dSHong Zhang   if (func) *func = ts->rhsjacobianp;
68*2a8381b2SBarry Smith   if (ctx) *(void **)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 @*/
TSComputeRHSJacobianP(TS ts,PetscReal t,Vec U,Mat Amat)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
11190907b5bSBarry Smith   TSSetIJacobianP - Sets the function that computes the Jacobian of $F$ w.r.t. the parameters $p$ where $F(Udot,U,p,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
12690907b5bSBarry Smith . shift - shift to apply, see the note in `TSSetIJacobian()`
12733f72c5dSHong Zhang . A     - output matrix
12833f72c5dSHong Zhang - ctx   - [optional] user-defined function context
12933f72c5dSHong Zhang 
13033f72c5dSHong Zhang   Level: intermediate
13133f72c5dSHong Zhang 
132bcf0153eSBarry Smith   Note:
13390907b5bSBarry Smith   `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 @*/
TSSetIJacobianP(TS ts,Mat Amat,PetscErrorCode (* func)(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal shift,Mat A,PetscCtx ctx),PetscCtx ctx)137*2a8381b2SBarry Smith PetscErrorCode TSSetIJacobianP(TS ts, Mat Amat, PetscErrorCode (*func)(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal shift, Mat A, PetscCtx ctx), PetscCtx 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 
1533beb8511SBarry Smith /*@C
1543beb8511SBarry Smith   TSGetIJacobianP - Gets the function that computes the Jacobian of $ F$ w.r.t. the parameters $p$ where $F(Udot,U,p,t) = G(U,p,t) $, as well as the location to store the matrix.
1553beb8511SBarry Smith 
1563beb8511SBarry Smith   Logically Collective
1573beb8511SBarry Smith 
1583beb8511SBarry Smith   Input Parameter:
1593beb8511SBarry Smith . ts - `TS` context obtained from `TSCreate()`
1603beb8511SBarry Smith 
1613beb8511SBarry Smith   Output Parameters:
1623beb8511SBarry Smith + Amat - JacobianP matrix
1633beb8511SBarry Smith . func - the function that computes the JacobianP
1643beb8511SBarry Smith - ctx  - [optional] user-defined function context
1653beb8511SBarry Smith 
1663beb8511SBarry Smith   Calling sequence of `func`:
1673beb8511SBarry Smith + ts    - the `TS` context
1683beb8511SBarry Smith . t     - current timestep
1693beb8511SBarry Smith . U     - input vector (current ODE solution)
1703beb8511SBarry Smith . Udot  - time derivative of state vector
1713beb8511SBarry Smith . shift - shift to apply, see the note in `TSSetIJacobian()`
1723beb8511SBarry Smith . A     - output matrix
1733beb8511SBarry Smith - ctx   - [optional] user-defined function context
1743beb8511SBarry Smith 
1753beb8511SBarry Smith   Level: intermediate
1763beb8511SBarry Smith 
1773beb8511SBarry Smith   Note:
1783beb8511SBarry Smith   `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`
1793beb8511SBarry Smith 
1803beb8511SBarry Smith .seealso: [](ch_ts), `TSSetRHSJacobianP()`, `TS`, `TSSetIJacobianP()`, `TSGetRHSJacobianP()`
1813beb8511SBarry Smith @*/
TSGetIJacobianP(TS ts,Mat * Amat,PetscErrorCode (** func)(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal shift,Mat A,PetscCtx ctx),PetscCtxRt ctx)182*2a8381b2SBarry Smith PetscErrorCode TSGetIJacobianP(TS ts, Mat *Amat, PetscErrorCode (**func)(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal shift, Mat A, PetscCtx ctx), PetscCtxRt ctx)
1833beb8511SBarry Smith {
1843beb8511SBarry Smith   PetscFunctionBegin;
1853beb8511SBarry Smith   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
1863beb8511SBarry Smith 
1873beb8511SBarry Smith   if (func) *func = ts->ijacobianp;
188*2a8381b2SBarry Smith   if (ctx) *(void **)ctx = ts->ijacobianpctx;
1893beb8511SBarry Smith   if (Amat) *Amat = ts->Jacp;
1903beb8511SBarry Smith   PetscFunctionReturn(PETSC_SUCCESS);
1913beb8511SBarry Smith }
1923beb8511SBarry Smith 
193cc4c1da9SBarry Smith /*@
19433f72c5dSHong Zhang   TSComputeIJacobianP - Runs the user-defined IJacobianP function.
19533f72c5dSHong Zhang 
196c3339decSBarry Smith   Collective
19733f72c5dSHong Zhang 
19833f72c5dSHong Zhang   Input Parameters:
199bcf0153eSBarry Smith + ts    - the `TS` context
20033f72c5dSHong Zhang . t     - current timestep
20133f72c5dSHong Zhang . U     - state vector
20233f72c5dSHong Zhang . Udot  - time derivative of state vector
20333f72c5dSHong Zhang . shift - shift to apply, see note below
20490907b5bSBarry Smith - imex  - flag indicates if the method is IMEX so that the `RHSJacobianP` should be kept separate
20533f72c5dSHong Zhang 
2062fe279fdSBarry Smith   Output Parameter:
207b43aa488SJacob Faibussowitsch . Amat - Jacobian matrix
20833f72c5dSHong Zhang 
20933f72c5dSHong Zhang   Level: developer
21033f72c5dSHong Zhang 
2111cc06b55SBarry Smith .seealso: [](ch_ts), `TS`, `TSSetIJacobianP()`
21233f72c5dSHong Zhang @*/
TSComputeIJacobianP(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal shift,Mat Amat,PetscBool imex)213d71ae5a4SJacob Faibussowitsch PetscErrorCode TSComputeIJacobianP(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal shift, Mat Amat, PetscBool imex)
214d71ae5a4SJacob Faibussowitsch {
21533f72c5dSHong Zhang   PetscFunctionBegin;
2163ba16761SJacob Faibussowitsch   if (!Amat) PetscFunctionReturn(PETSC_SUCCESS);
21733f72c5dSHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
21833f72c5dSHong Zhang   PetscValidHeaderSpecific(U, VEC_CLASSID, 3);
21933f72c5dSHong Zhang   PetscValidHeaderSpecific(Udot, VEC_CLASSID, 4);
22033f72c5dSHong Zhang 
2219566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(TS_JacobianPEval, ts, U, Amat, 0));
22248a46eb9SPierre Jolivet   if (ts->ijacobianp) PetscCallBack("TS callback JacobianP for sensitivity analysis", (*ts->ijacobianp)(ts, t, U, Udot, shift, Amat, ts->ijacobianpctx));
22333f72c5dSHong Zhang   if (imex) {
22433f72c5dSHong Zhang     if (!ts->ijacobianp) { /* system was written as Udot = G(t,U) */
22533f72c5dSHong Zhang       PetscBool assembled;
2269566063dSJacob Faibussowitsch       PetscCall(MatZeroEntries(Amat));
2279566063dSJacob Faibussowitsch       PetscCall(MatAssembled(Amat, &assembled));
22833f72c5dSHong Zhang       if (!assembled) {
2299566063dSJacob Faibussowitsch         PetscCall(MatAssemblyBegin(Amat, MAT_FINAL_ASSEMBLY));
2309566063dSJacob Faibussowitsch         PetscCall(MatAssemblyEnd(Amat, MAT_FINAL_ASSEMBLY));
23133f72c5dSHong Zhang       }
23233f72c5dSHong Zhang     }
23333f72c5dSHong Zhang   } else {
2341baa6e33SBarry Smith     if (ts->rhsjacobianp) PetscCall(TSComputeRHSJacobianP(ts, t, U, ts->Jacprhs));
23533f72c5dSHong Zhang     if (ts->Jacprhs == Amat) { /* No IJacobian, so we only have the RHS matrix */
2369566063dSJacob Faibussowitsch       PetscCall(MatScale(Amat, -1));
23733f72c5dSHong Zhang     } else if (ts->Jacprhs) { /* Both IJacobian and RHSJacobian */
23833f72c5dSHong Zhang       MatStructure axpy = DIFFERENT_NONZERO_PATTERN;
23933f72c5dSHong Zhang       if (!ts->ijacobianp) { /* No IJacobianp provided, but we have a separate RHS matrix */
2409566063dSJacob Faibussowitsch         PetscCall(MatZeroEntries(Amat));
24133f72c5dSHong Zhang       }
2429566063dSJacob Faibussowitsch       PetscCall(MatAXPY(Amat, -1, ts->Jacprhs, axpy));
24333f72c5dSHong Zhang     }
24433f72c5dSHong Zhang   }
2459566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(TS_JacobianPEval, ts, U, Amat, 0));
2463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24733f72c5dSHong Zhang }
24833f72c5dSHong Zhang 
24933f72c5dSHong Zhang /*@C
250814e85d6SHong Zhang   TSSetCostIntegrand - Sets the routine for evaluating the integral term in one or more cost functions
251814e85d6SHong Zhang 
252c3339decSBarry Smith   Logically Collective
253814e85d6SHong Zhang 
254814e85d6SHong Zhang   Input Parameters:
255bcf0153eSBarry Smith + ts           - the `TS` context obtained from `TSCreate()`
256814e85d6SHong Zhang . numcost      - number of gradients to be computed, this is the number of cost functions
257814e85d6SHong Zhang . costintegral - vector that stores the integral values
258814e85d6SHong Zhang . rf           - routine for evaluating the integrand function
2598847d985SBarry Smith . drduf        - function that computes the gradients of the r with respect to u
2608847d985SBarry 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`)
261814e85d6SHong Zhang . fwd          - flag indicating whether to evaluate cost integral in the forward run or the adjoint run
2622fe279fdSBarry Smith - ctx          - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`)
263814e85d6SHong Zhang 
26420f4b53cSBarry Smith   Calling sequence of `rf`:
2658847d985SBarry Smith + ts  - the integrator
2668847d985SBarry Smith . t   - the time
2678847d985SBarry Smith . U   - the solution
2688847d985SBarry Smith . F   - the computed value of the function
2698847d985SBarry Smith - ctx - the user context
270814e85d6SHong Zhang 
27120f4b53cSBarry Smith   Calling sequence of `drduf`:
2728847d985SBarry Smith + ts   - the integrator
2738847d985SBarry Smith . t    - the time
2748847d985SBarry Smith . U    - the solution
2758847d985SBarry Smith . dRdU - the computed gradients of the r with respect to u
2768847d985SBarry Smith - ctx  - the user context
277814e85d6SHong Zhang 
27820f4b53cSBarry Smith   Calling sequence of `drdpf`:
2798847d985SBarry Smith + ts   - the integrator
2808847d985SBarry Smith . t    - the time
2818847d985SBarry Smith . U    - the solution
2828847d985SBarry Smith . dRdP - the computed gradients of the r with respect to p
2838847d985SBarry Smith - ctx  - the user context
284814e85d6SHong Zhang 
285cd4cee2dSHong Zhang   Level: deprecated
286814e85d6SHong Zhang 
2878847d985SBarry Smith   Notes:
288814e85d6SHong Zhang   For optimization there is usually a single cost function (numcost = 1). For sensitivities there may be multiple cost functions
289814e85d6SHong Zhang 
2908847d985SBarry Smith   Use `TSCreateQuadratureTS()` and `TSForwardSetSensitivities()` instead
2918847d985SBarry Smith 
2928847d985SBarry Smith .seealso: [](ch_ts), `TS`, `TSSetRHSJacobianP()`, `TSGetCostGradients()`, `TSSetCostGradients()`,
2938847d985SBarry Smith           `TSCreateQuadratureTS()`, `TSForwardSetSensitivities()`
294814e85d6SHong Zhang @*/
TSSetCostIntegrand(TS ts,PetscInt numcost,Vec costintegral,PetscErrorCode (* rf)(TS ts,PetscReal t,Vec U,Vec F,PetscCtx ctx),PetscErrorCode (* drduf)(TS ts,PetscReal t,Vec U,Vec * dRdU,PetscCtx ctx),PetscErrorCode (* drdpf)(TS ts,PetscReal t,Vec U,Vec * dRdP,PetscCtx ctx),PetscBool fwd,PetscCtx ctx)295*2a8381b2SBarry Smith PetscErrorCode TSSetCostIntegrand(TS ts, PetscInt numcost, Vec costintegral, PetscErrorCode (*rf)(TS ts, PetscReal t, Vec U, Vec F, PetscCtx ctx), PetscErrorCode (*drduf)(TS ts, PetscReal t, Vec U, Vec *dRdU, PetscCtx ctx), PetscErrorCode (*drdpf)(TS ts, PetscReal t, Vec U, Vec *dRdP, PetscCtx ctx), PetscBool fwd, PetscCtx ctx)
296d71ae5a4SJacob Faibussowitsch {
297814e85d6SHong Zhang   PetscFunctionBegin;
298814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
299814e85d6SHong Zhang   if (costintegral) PetscValidHeaderSpecific(costintegral, VEC_CLASSID, 3);
3003c633725SBarry 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()");
301814e85d6SHong Zhang   if (!ts->numcost) ts->numcost = numcost;
302814e85d6SHong Zhang 
303814e85d6SHong Zhang   if (costintegral) {
3049566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)costintegral));
3059566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&ts->vec_costintegral));
306814e85d6SHong Zhang     ts->vec_costintegral = costintegral;
307814e85d6SHong Zhang   } else {
308814e85d6SHong Zhang     if (!ts->vec_costintegral) { /* Create a seq vec if user does not provide one */
3099566063dSJacob Faibussowitsch       PetscCall(VecCreateSeq(PETSC_COMM_SELF, numcost, &ts->vec_costintegral));
310814e85d6SHong Zhang     } else {
3119566063dSJacob Faibussowitsch       PetscCall(VecSet(ts->vec_costintegral, 0.0));
312814e85d6SHong Zhang     }
313814e85d6SHong Zhang   }
314814e85d6SHong Zhang   if (!ts->vec_costintegrand) {
3159566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(ts->vec_costintegral, &ts->vec_costintegrand));
316814e85d6SHong Zhang   } else {
3179566063dSJacob Faibussowitsch     PetscCall(VecSet(ts->vec_costintegrand, 0.0));
318814e85d6SHong Zhang   }
319814e85d6SHong Zhang   ts->costintegralfwd  = fwd; /* Evaluate the cost integral in forward run if fwd is true */
320814e85d6SHong Zhang   ts->costintegrand    = rf;
321814e85d6SHong Zhang   ts->costintegrandctx = ctx;
322c9ad9de0SHong Zhang   ts->drdufunction     = drduf;
323814e85d6SHong Zhang   ts->drdpfunction     = drdpf;
3243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
325814e85d6SHong Zhang }
326814e85d6SHong Zhang 
327cc4c1da9SBarry Smith /*@
328814e85d6SHong Zhang   TSGetCostIntegral - Returns the values of the integral term in the cost functions.
329814e85d6SHong Zhang   It is valid to call the routine after a backward run.
330814e85d6SHong Zhang 
331814e85d6SHong Zhang   Not Collective
332814e85d6SHong Zhang 
333814e85d6SHong Zhang   Input Parameter:
334bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()`
335814e85d6SHong Zhang 
336814e85d6SHong Zhang   Output Parameter:
337814e85d6SHong Zhang . v - the vector containing the integrals for each cost function
338814e85d6SHong Zhang 
339814e85d6SHong Zhang   Level: intermediate
340814e85d6SHong Zhang 
341a94f484eSPierre Jolivet .seealso: [](ch_ts), `TS`, `TSAdjointSolve()`, `TSSetCostIntegrand()`
342814e85d6SHong Zhang @*/
TSGetCostIntegral(TS ts,Vec * v)343d71ae5a4SJacob Faibussowitsch PetscErrorCode TSGetCostIntegral(TS ts, Vec *v)
344d71ae5a4SJacob Faibussowitsch {
345cd4cee2dSHong Zhang   TS quadts;
346cd4cee2dSHong Zhang 
347814e85d6SHong Zhang   PetscFunctionBegin;
348814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3494f572ea9SToby Isaac   PetscAssertPointer(v, 2);
3509566063dSJacob Faibussowitsch   PetscCall(TSGetQuadratureTS(ts, NULL, &quadts));
351cd4cee2dSHong Zhang   *v = quadts->vec_sol;
3523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
353814e85d6SHong Zhang }
354814e85d6SHong Zhang 
355cc4c1da9SBarry Smith /*@
356814e85d6SHong Zhang   TSComputeCostIntegrand - Evaluates the integral function in the cost functions.
357814e85d6SHong Zhang 
358814e85d6SHong Zhang   Input Parameters:
359bcf0153eSBarry Smith + ts - the `TS` context
360814e85d6SHong Zhang . t  - current time
361c9ad9de0SHong Zhang - U  - state vector, i.e. current solution
362814e85d6SHong Zhang 
363814e85d6SHong Zhang   Output Parameter:
364c9ad9de0SHong Zhang . Q - vector of size numcost to hold the outputs
365814e85d6SHong Zhang 
366bcf0153eSBarry Smith   Level: deprecated
367bcf0153eSBarry Smith 
368bcf0153eSBarry Smith   Note:
369814e85d6SHong Zhang   Most users should not need to explicitly call this routine, as it
370814e85d6SHong Zhang   is used internally within the sensitivity analysis context.
371814e85d6SHong Zhang 
3721cc06b55SBarry Smith .seealso: [](ch_ts), `TS`, `TSAdjointSolve()`, `TSSetCostIntegrand()`
373814e85d6SHong Zhang @*/
TSComputeCostIntegrand(TS ts,PetscReal t,Vec U,Vec Q)374d71ae5a4SJacob Faibussowitsch PetscErrorCode TSComputeCostIntegrand(TS ts, PetscReal t, Vec U, Vec Q)
375d71ae5a4SJacob Faibussowitsch {
376814e85d6SHong Zhang   PetscFunctionBegin;
377814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
378c9ad9de0SHong Zhang   PetscValidHeaderSpecific(U, VEC_CLASSID, 3);
379c9ad9de0SHong Zhang   PetscValidHeaderSpecific(Q, VEC_CLASSID, 4);
380814e85d6SHong Zhang 
3819566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(TS_FunctionEval, ts, U, Q, 0));
382792fecdfSBarry Smith   if (ts->costintegrand) PetscCallBack("TS callback integrand in the cost function", (*ts->costintegrand)(ts, t, U, Q, ts->costintegrandctx));
383ef1023bdSBarry Smith   else PetscCall(VecZeroEntries(Q));
3849566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(TS_FunctionEval, ts, U, Q, 0));
3853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
386814e85d6SHong Zhang }
387814e85d6SHong Zhang 
38814d0ab18SJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-*
389cc4c1da9SBarry Smith /*@
390bcf0153eSBarry Smith   TSComputeDRDUFunction - Deprecated, use `TSGetQuadratureTS()` then `TSComputeRHSJacobian()`
391814e85d6SHong Zhang 
392d76be551SHong Zhang   Level: deprecated
393814e85d6SHong Zhang 
394814e85d6SHong Zhang @*/
TSComputeDRDUFunction(TS ts,PetscReal t,Vec U,Vec * DRDU)395d71ae5a4SJacob Faibussowitsch PetscErrorCode TSComputeDRDUFunction(TS ts, PetscReal t, Vec U, Vec *DRDU)
396d71ae5a4SJacob Faibussowitsch {
397814e85d6SHong Zhang   PetscFunctionBegin;
3983ba16761SJacob Faibussowitsch   if (!DRDU) PetscFunctionReturn(PETSC_SUCCESS);
399814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
400c9ad9de0SHong Zhang   PetscValidHeaderSpecific(U, VEC_CLASSID, 3);
401814e85d6SHong Zhang 
402792fecdfSBarry Smith   PetscCallBack("TS callback DRDU for sensitivity analysis", (*ts->drdufunction)(ts, t, U, DRDU, ts->costintegrandctx));
4033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
404814e85d6SHong Zhang }
405814e85d6SHong Zhang 
40614d0ab18SJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-*
407cc4c1da9SBarry Smith /*@
408bcf0153eSBarry Smith   TSComputeDRDPFunction - Deprecated, use `TSGetQuadratureTS()` then `TSComputeRHSJacobianP()`
409814e85d6SHong Zhang 
410d76be551SHong Zhang   Level: deprecated
411814e85d6SHong Zhang 
412814e85d6SHong Zhang @*/
TSComputeDRDPFunction(TS ts,PetscReal t,Vec U,Vec * DRDP)413d71ae5a4SJacob Faibussowitsch PetscErrorCode TSComputeDRDPFunction(TS ts, PetscReal t, Vec U, Vec *DRDP)
414d71ae5a4SJacob Faibussowitsch {
415814e85d6SHong Zhang   PetscFunctionBegin;
4163ba16761SJacob Faibussowitsch   if (!DRDP) PetscFunctionReturn(PETSC_SUCCESS);
417814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
418c9ad9de0SHong Zhang   PetscValidHeaderSpecific(U, VEC_CLASSID, 3);
419814e85d6SHong Zhang 
420792fecdfSBarry Smith   PetscCallBack("TS callback DRDP for sensitivity analysis", (*ts->drdpfunction)(ts, t, U, DRDP, ts->costintegrandctx));
4213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
422814e85d6SHong Zhang }
423814e85d6SHong Zhang 
42414d0ab18SJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-param-list-func-parameter-documentation
42514d0ab18SJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-section-header-unknown
426b5b4017aSHong Zhang /*@C
427b5b4017aSHong 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.
428b5b4017aSHong Zhang 
429c3339decSBarry Smith   Logically Collective
430b5b4017aSHong Zhang 
431b5b4017aSHong Zhang   Input Parameters:
432bcf0153eSBarry Smith + ts   - `TS` context obtained from `TSCreate()`
433b5b4017aSHong Zhang . ihp1 - an array of vectors storing the result of vector-Hessian-vector product for F_UU
434b5b4017aSHong Zhang . hessianproductfunc1 - vector-Hessian-vector product function for F_UU
435b5b4017aSHong Zhang . ihp2 - an array of vectors storing the result of vector-Hessian-vector product for F_UP
436b5b4017aSHong Zhang . hessianproductfunc2 - vector-Hessian-vector product function for F_UP
437b5b4017aSHong Zhang . ihp3 - an array of vectors storing the result of vector-Hessian-vector product for F_PU
438b5b4017aSHong Zhang . hessianproductfunc3 - vector-Hessian-vector product function for F_PU
439b5b4017aSHong Zhang . ihp4 - an array of vectors storing the result of vector-Hessian-vector product for F_PP
440f0fc11ceSJed Brown - hessianproductfunc4 - vector-Hessian-vector product function for F_PP
441b5b4017aSHong Zhang 
44214d0ab18SJacob Faibussowitsch   Calling sequence of `ihessianproductfunc1`:
44314d0ab18SJacob Faibussowitsch + ts  - the `TS` context
444b5b4017aSHong Zhang + t   - current timestep
445b5b4017aSHong Zhang . U   - input vector (current ODE solution)
446369cf35fSHong Zhang . Vl  - an array of input vectors to be left-multiplied with the Hessian
447b5b4017aSHong Zhang . Vr  - input vector to be right-multiplied with the Hessian
448369cf35fSHong Zhang . VHV - an array of output vectors for vector-Hessian-vector product
449b5b4017aSHong Zhang - ctx - [optional] user-defined function context
450b5b4017aSHong Zhang 
451b5b4017aSHong Zhang   Level: intermediate
452b5b4017aSHong Zhang 
453369cf35fSHong Zhang   Notes:
45414d0ab18SJacob Faibussowitsch   All other functions have the same calling sequence as `rhhessianproductfunc1`, so their
45514d0ab18SJacob Faibussowitsch   descriptions are omitted for brevity.
45614d0ab18SJacob Faibussowitsch 
457369cf35fSHong Zhang   The first Hessian function and the working array are required.
458369cf35fSHong Zhang   As an example to implement the callback functions, the second callback function calculates the vector-Hessian-vector product
459369cf35fSHong Zhang   $ Vl_n^T*F_UP*Vr
460369cf35fSHong 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.
461369cf35fSHong Zhang   Each entry of F_UP corresponds to the derivative
462369cf35fSHong Zhang   $ F_UP[i][j][k] = \frac{\partial^2 F[i]}{\partial U[j] \partial P[k]}.
463369cf35fSHong 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
464369cf35fSHong Zhang   $ VHV_n[j] = \sum_i \sum_k {Vl_n[i] * F_UP[i][j][k] * Vr[k]}
465369cf35fSHong Zhang   If the cost function is a scalar, there will be only one vector in Vl and VHV.
466b5b4017aSHong Zhang 
4671cc06b55SBarry Smith .seealso: [](ch_ts), `TS`
468b5b4017aSHong Zhang @*/
TSSetIHessianProduct(TS ts,Vec * ihp1,PetscErrorCode (* ihessianproductfunc1)(TS ts,PetscReal t,Vec U,Vec * Vl,Vec Vr,Vec * VHV,PetscCtx 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 *),PetscCtx ctx)469*2a8381b2SBarry Smith PetscErrorCode TSSetIHessianProduct(TS ts, Vec *ihp1, PetscErrorCode (*ihessianproductfunc1)(TS ts, PetscReal t, Vec U, Vec *Vl, Vec Vr, Vec *VHV, PetscCtx 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 *), PetscCtx ctx)
470d71ae5a4SJacob Faibussowitsch {
471b5b4017aSHong Zhang   PetscFunctionBegin;
472b5b4017aSHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4734f572ea9SToby Isaac   PetscAssertPointer(ihp1, 2);
474b5b4017aSHong Zhang 
475b5b4017aSHong Zhang   ts->ihessianproductctx = ctx;
476b5b4017aSHong Zhang   if (ihp1) ts->vecs_fuu = ihp1;
477b5b4017aSHong Zhang   if (ihp2) ts->vecs_fup = ihp2;
478b5b4017aSHong Zhang   if (ihp3) ts->vecs_fpu = ihp3;
479b5b4017aSHong Zhang   if (ihp4) ts->vecs_fpp = ihp4;
480b5b4017aSHong Zhang   ts->ihessianproduct_fuu = ihessianproductfunc1;
481b5b4017aSHong Zhang   ts->ihessianproduct_fup = ihessianproductfunc2;
482b5b4017aSHong Zhang   ts->ihessianproduct_fpu = ihessianproductfunc3;
483b5b4017aSHong Zhang   ts->ihessianproduct_fpp = ihessianproductfunc4;
4843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
485b5b4017aSHong Zhang }
486b5b4017aSHong Zhang 
487cc4c1da9SBarry Smith /*@
488b1e111ebSHong Zhang   TSComputeIHessianProductFunctionUU - Runs the user-defined vector-Hessian-vector product function for Fuu.
489b5b4017aSHong Zhang 
490c3339decSBarry Smith   Collective
491b5b4017aSHong Zhang 
492b5b4017aSHong Zhang   Input Parameters:
4932fe279fdSBarry Smith + ts - The `TS` context obtained from `TSCreate()`
4942fe279fdSBarry Smith . t  - the time
4952fe279fdSBarry Smith . U  - the solution at which to compute the Hessian product
4962fe279fdSBarry Smith . Vl - the array of input vectors to be multiplied with the Hessian from the left
4972fe279fdSBarry Smith - Vr - the input vector to be multiplied with the Hessian from the right
4982fe279fdSBarry Smith 
4992fe279fdSBarry Smith   Output Parameter:
500b43aa488SJacob Faibussowitsch . VHV - the array of output vectors that store the Hessian product
501b5b4017aSHong Zhang 
502b5b4017aSHong Zhang   Level: developer
503b5b4017aSHong Zhang 
504bcf0153eSBarry Smith   Note:
505bcf0153eSBarry Smith   `TSComputeIHessianProductFunctionUU()` is typically used for sensitivity implementation,
506bcf0153eSBarry Smith   so most users would not generally call this routine themselves.
507bcf0153eSBarry Smith 
5081cc06b55SBarry Smith .seealso: [](ch_ts), `TSSetIHessianProduct()`
509b5b4017aSHong Zhang @*/
TSComputeIHessianProductFunctionUU(TS ts,PetscReal t,Vec U,Vec Vl[],Vec Vr,Vec VHV[])510cc4c1da9SBarry Smith PetscErrorCode TSComputeIHessianProductFunctionUU(TS ts, PetscReal t, Vec U, Vec Vl[], Vec Vr, Vec VHV[])
511d71ae5a4SJacob Faibussowitsch {
512b5b4017aSHong Zhang   PetscFunctionBegin;
5133ba16761SJacob Faibussowitsch   if (!VHV) PetscFunctionReturn(PETSC_SUCCESS);
514b5b4017aSHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
515b5b4017aSHong Zhang   PetscValidHeaderSpecific(U, VEC_CLASSID, 3);
516b5b4017aSHong Zhang 
517792fecdfSBarry Smith   if (ts->ihessianproduct_fuu) PetscCallBack("TS callback IHessianProduct 1 for sensitivity analysis", (*ts->ihessianproduct_fuu)(ts, t, U, Vl, Vr, VHV, ts->ihessianproductctx));
518ef1023bdSBarry Smith 
51967633408SHong Zhang   /* does not consider IMEX for now, so either IHessian or RHSHessian will be calculated, using the same output VHV */
52067633408SHong Zhang   if (ts->rhshessianproduct_guu) {
52167633408SHong Zhang     PetscInt nadj;
5229566063dSJacob Faibussowitsch     PetscCall(TSComputeRHSHessianProductFunctionUU(ts, t, U, Vl, Vr, VHV));
52348a46eb9SPierre Jolivet     for (nadj = 0; nadj < ts->numcost; nadj++) PetscCall(VecScale(VHV[nadj], -1));
52467633408SHong Zhang   }
5253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
526b5b4017aSHong Zhang }
527b5b4017aSHong Zhang 
528cc4c1da9SBarry Smith /*@
529b1e111ebSHong Zhang   TSComputeIHessianProductFunctionUP - Runs the user-defined vector-Hessian-vector product function for Fup.
530b5b4017aSHong Zhang 
531c3339decSBarry Smith   Collective
532b5b4017aSHong Zhang 
533b5b4017aSHong Zhang   Input Parameters:
5342fe279fdSBarry Smith + ts - The `TS` context obtained from `TSCreate()`
5352fe279fdSBarry Smith . t  - the time
5362fe279fdSBarry Smith . U  - the solution at which to compute the Hessian product
5372fe279fdSBarry Smith . Vl - the array of input vectors to be multiplied with the Hessian from the left
5382fe279fdSBarry Smith - Vr - the input vector to be multiplied with the Hessian from the right
5392fe279fdSBarry Smith 
5402fe279fdSBarry Smith   Output Parameter:
541b43aa488SJacob Faibussowitsch . VHV - the array of output vectors that store the Hessian product
542b5b4017aSHong Zhang 
543b5b4017aSHong Zhang   Level: developer
544b5b4017aSHong Zhang 
545bcf0153eSBarry Smith   Note:
546bcf0153eSBarry Smith   `TSComputeIHessianProductFunctionUP()` is typically used for sensitivity implementation,
547bcf0153eSBarry Smith   so most users would not generally call this routine themselves.
548bcf0153eSBarry Smith 
5491cc06b55SBarry Smith .seealso: [](ch_ts), `TSSetIHessianProduct()`
550b5b4017aSHong Zhang @*/
TSComputeIHessianProductFunctionUP(TS ts,PetscReal t,Vec U,Vec Vl[],Vec Vr,Vec VHV[])551cc4c1da9SBarry Smith PetscErrorCode TSComputeIHessianProductFunctionUP(TS ts, PetscReal t, Vec U, Vec Vl[], Vec Vr, Vec VHV[])
552d71ae5a4SJacob Faibussowitsch {
553b5b4017aSHong Zhang   PetscFunctionBegin;
5543ba16761SJacob Faibussowitsch   if (!VHV) PetscFunctionReturn(PETSC_SUCCESS);
555b5b4017aSHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
556b5b4017aSHong Zhang   PetscValidHeaderSpecific(U, VEC_CLASSID, 3);
557b5b4017aSHong Zhang 
558792fecdfSBarry Smith   if (ts->ihessianproduct_fup) PetscCallBack("TS callback IHessianProduct 2 for sensitivity analysis", (*ts->ihessianproduct_fup)(ts, t, U, Vl, Vr, VHV, ts->ihessianproductctx));
559ef1023bdSBarry Smith 
56067633408SHong Zhang   /* does not consider IMEX for now, so either IHessian or RHSHessian will be calculated, using the same output VHV */
56167633408SHong Zhang   if (ts->rhshessianproduct_gup) {
56267633408SHong Zhang     PetscInt nadj;
5639566063dSJacob Faibussowitsch     PetscCall(TSComputeRHSHessianProductFunctionUP(ts, t, U, Vl, Vr, VHV));
56448a46eb9SPierre Jolivet     for (nadj = 0; nadj < ts->numcost; nadj++) PetscCall(VecScale(VHV[nadj], -1));
56567633408SHong Zhang   }
5663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
567b5b4017aSHong Zhang }
568b5b4017aSHong Zhang 
569cc4c1da9SBarry Smith /*@
570b1e111ebSHong Zhang   TSComputeIHessianProductFunctionPU - Runs the user-defined vector-Hessian-vector product function for Fpu.
571b5b4017aSHong Zhang 
572c3339decSBarry Smith   Collective
573b5b4017aSHong Zhang 
574b5b4017aSHong Zhang   Input Parameters:
5752fe279fdSBarry Smith + ts - The `TS` context obtained from `TSCreate()`
5762fe279fdSBarry Smith . t  - the time
5772fe279fdSBarry Smith . U  - the solution at which to compute the Hessian product
5782fe279fdSBarry Smith . Vl - the array of input vectors to be multiplied with the Hessian from the left
5792fe279fdSBarry Smith - Vr - the input vector to be multiplied with the Hessian from the right
5802fe279fdSBarry Smith 
5812fe279fdSBarry Smith   Output Parameter:
582b43aa488SJacob Faibussowitsch . VHV - the array of output vectors that store the Hessian product
583b5b4017aSHong Zhang 
584b5b4017aSHong Zhang   Level: developer
585b5b4017aSHong Zhang 
586bcf0153eSBarry Smith   Note:
587bcf0153eSBarry Smith   `TSComputeIHessianProductFunctionPU()` is typically used for sensitivity implementation,
588bcf0153eSBarry Smith   so most users would not generally call this routine themselves.
589bcf0153eSBarry Smith 
5901cc06b55SBarry Smith .seealso: [](ch_ts), `TSSetIHessianProduct()`
591b5b4017aSHong Zhang @*/
TSComputeIHessianProductFunctionPU(TS ts,PetscReal t,Vec U,Vec Vl[],Vec Vr,Vec VHV[])592cc4c1da9SBarry Smith PetscErrorCode TSComputeIHessianProductFunctionPU(TS ts, PetscReal t, Vec U, Vec Vl[], Vec Vr, Vec VHV[])
593d71ae5a4SJacob Faibussowitsch {
594b5b4017aSHong Zhang   PetscFunctionBegin;
5953ba16761SJacob Faibussowitsch   if (!VHV) PetscFunctionReturn(PETSC_SUCCESS);
596b5b4017aSHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
597b5b4017aSHong Zhang   PetscValidHeaderSpecific(U, VEC_CLASSID, 3);
598b5b4017aSHong Zhang 
599792fecdfSBarry Smith   if (ts->ihessianproduct_fpu) PetscCallBack("TS callback IHessianProduct 3 for sensitivity analysis", (*ts->ihessianproduct_fpu)(ts, t, U, Vl, Vr, VHV, ts->ihessianproductctx));
600ef1023bdSBarry Smith 
60167633408SHong Zhang   /* does not consider IMEX for now, so either IHessian or RHSHessian will be calculated, using the same output VHV */
60267633408SHong Zhang   if (ts->rhshessianproduct_gpu) {
60367633408SHong Zhang     PetscInt nadj;
6049566063dSJacob Faibussowitsch     PetscCall(TSComputeRHSHessianProductFunctionPU(ts, t, U, Vl, Vr, VHV));
60548a46eb9SPierre Jolivet     for (nadj = 0; nadj < ts->numcost; nadj++) PetscCall(VecScale(VHV[nadj], -1));
60667633408SHong Zhang   }
6073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
608b5b4017aSHong Zhang }
609b5b4017aSHong Zhang 
610b5b4017aSHong Zhang /*@C
611b1e111ebSHong Zhang   TSComputeIHessianProductFunctionPP - Runs the user-defined vector-Hessian-vector product function for Fpp.
612b5b4017aSHong Zhang 
613c3339decSBarry Smith   Collective
614b5b4017aSHong Zhang 
615b5b4017aSHong Zhang   Input Parameters:
6162fe279fdSBarry Smith + ts - The `TS` context obtained from `TSCreate()`
6172fe279fdSBarry Smith . t  - the time
6182fe279fdSBarry Smith . U  - the solution at which to compute the Hessian product
6192fe279fdSBarry Smith . Vl - the array of input vectors to be multiplied with the Hessian from the left
6202fe279fdSBarry Smith - Vr - the input vector to be multiplied with the Hessian from the right
6212fe279fdSBarry Smith 
6222fe279fdSBarry Smith   Output Parameter:
623b43aa488SJacob Faibussowitsch . VHV - the array of output vectors that store the Hessian product
624b5b4017aSHong Zhang 
625b5b4017aSHong Zhang   Level: developer
626b5b4017aSHong Zhang 
627bcf0153eSBarry Smith   Note:
628bcf0153eSBarry Smith   `TSComputeIHessianProductFunctionPP()` is typically used for sensitivity implementation,
629bcf0153eSBarry Smith   so most users would not generally call this routine themselves.
630bcf0153eSBarry Smith 
6311cc06b55SBarry Smith .seealso: [](ch_ts), `TSSetIHessianProduct()`
632b5b4017aSHong Zhang @*/
TSComputeIHessianProductFunctionPP(TS ts,PetscReal t,Vec U,Vec Vl[],Vec Vr,Vec VHV[])633cc4c1da9SBarry Smith PetscErrorCode TSComputeIHessianProductFunctionPP(TS ts, PetscReal t, Vec U, Vec Vl[], Vec Vr, Vec VHV[])
634d71ae5a4SJacob Faibussowitsch {
635b5b4017aSHong Zhang   PetscFunctionBegin;
6363ba16761SJacob Faibussowitsch   if (!VHV) PetscFunctionReturn(PETSC_SUCCESS);
637b5b4017aSHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
638b5b4017aSHong Zhang   PetscValidHeaderSpecific(U, VEC_CLASSID, 3);
639b5b4017aSHong Zhang 
640792fecdfSBarry Smith   if (ts->ihessianproduct_fpp) PetscCallBack("TS callback IHessianProduct 3 for sensitivity analysis", (*ts->ihessianproduct_fpp)(ts, t, U, Vl, Vr, VHV, ts->ihessianproductctx));
641ef1023bdSBarry Smith 
64267633408SHong Zhang   /* does not consider IMEX for now, so either IHessian or RHSHessian will be calculated, using the same output VHV */
64367633408SHong Zhang   if (ts->rhshessianproduct_gpp) {
64467633408SHong Zhang     PetscInt nadj;
6459566063dSJacob Faibussowitsch     PetscCall(TSComputeRHSHessianProductFunctionPP(ts, t, U, Vl, Vr, VHV));
64648a46eb9SPierre Jolivet     for (nadj = 0; nadj < ts->numcost; nadj++) PetscCall(VecScale(VHV[nadj], -1));
64767633408SHong Zhang   }
6483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
649b5b4017aSHong Zhang }
650b5b4017aSHong Zhang 
65114d0ab18SJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-param-list-func-parameter-documentation
65214d0ab18SJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-section-header-unknown
65313af1a74SHong Zhang /*@C
65414d0ab18SJacob Faibussowitsch   TSSetRHSHessianProduct - Sets the function that computes the vector-Hessian-vector
65514d0ab18SJacob Faibussowitsch   product. The Hessian is the second-order derivative of G (RHSFunction) w.r.t. the state
65614d0ab18SJacob Faibussowitsch   variable.
65713af1a74SHong Zhang 
658c3339decSBarry Smith   Logically Collective
65913af1a74SHong Zhang 
66013af1a74SHong Zhang   Input Parameters:
661bcf0153eSBarry Smith + ts     - `TS` context obtained from `TSCreate()`
66213af1a74SHong Zhang . rhshp1 - an array of vectors storing the result of vector-Hessian-vector product for G_UU
66313af1a74SHong Zhang . hessianproductfunc1 - vector-Hessian-vector product function for G_UU
66413af1a74SHong Zhang . rhshp2 - an array of vectors storing the result of vector-Hessian-vector product for G_UP
66513af1a74SHong Zhang . hessianproductfunc2 - vector-Hessian-vector product function for G_UP
66613af1a74SHong Zhang . rhshp3 - an array of vectors storing the result of vector-Hessian-vector product for G_PU
66713af1a74SHong Zhang . hessianproductfunc3 - vector-Hessian-vector product function for G_PU
66813af1a74SHong Zhang . rhshp4 - an array of vectors storing the result of vector-Hessian-vector product for G_PP
66914d0ab18SJacob Faibussowitsch . hessianproductfunc4 - vector-Hessian-vector product function for G_PP
67014d0ab18SJacob Faibussowitsch - ctx    - [optional] user-defined function context
67113af1a74SHong Zhang 
67214d0ab18SJacob Faibussowitsch   Calling sequence of `rhshessianproductfunc1`:
67314d0ab18SJacob Faibussowitsch + ts  - the `TS` context
67414d0ab18SJacob Faibussowitsch . t   - current timestep
67513af1a74SHong Zhang . U   - input vector (current ODE solution)
676369cf35fSHong Zhang . Vl  - an array of input vectors to be left-multiplied with the Hessian
67713af1a74SHong Zhang . Vr  - input vector to be right-multiplied with the Hessian
678369cf35fSHong Zhang . VHV - an array of output vectors for vector-Hessian-vector product
67913af1a74SHong Zhang - ctx - [optional] user-defined function context
68013af1a74SHong Zhang 
68113af1a74SHong Zhang   Level: intermediate
68213af1a74SHong Zhang 
683369cf35fSHong Zhang   Notes:
68414d0ab18SJacob Faibussowitsch   All other functions have the same calling sequence as `rhhessianproductfunc1`, so their
68514d0ab18SJacob Faibussowitsch   descriptions are omitted for brevity.
68614d0ab18SJacob Faibussowitsch 
687369cf35fSHong Zhang   The first Hessian function and the working array are required.
68814d0ab18SJacob Faibussowitsch 
689369cf35fSHong Zhang   As an example to implement the callback functions, the second callback function calculates the vector-Hessian-vector product
690369cf35fSHong Zhang   $ Vl_n^T*G_UP*Vr
691369cf35fSHong 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.
692369cf35fSHong Zhang   Each entry of G_UP corresponds to the derivative
693369cf35fSHong Zhang   $ G_UP[i][j][k] = \frac{\partial^2 G[i]}{\partial U[j] \partial P[k]}.
694369cf35fSHong 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
695369cf35fSHong Zhang   $ VHV_n[j] = \sum_i \sum_k {Vl_n[i] * G_UP[i][j][k] * Vr[k]}
696369cf35fSHong Zhang   If the cost function is a scalar, there will be only one vector in Vl and VHV.
69713af1a74SHong Zhang 
6982fe279fdSBarry Smith .seealso: `TS`, `TSAdjoint`
69913af1a74SHong Zhang @*/
TSSetRHSHessianProduct(TS ts,Vec rhshp1[],PetscErrorCode (* rhshessianproductfunc1)(TS ts,PetscReal t,Vec U,Vec * Vl,Vec Vr,Vec * VHV,PetscCtx 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 *),PetscCtx ctx)700*2a8381b2SBarry Smith PetscErrorCode TSSetRHSHessianProduct(TS ts, Vec rhshp1[], PetscErrorCode (*rhshessianproductfunc1)(TS ts, PetscReal t, Vec U, Vec *Vl, Vec Vr, Vec *VHV, PetscCtx 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 *), PetscCtx ctx)
701d71ae5a4SJacob Faibussowitsch {
70213af1a74SHong Zhang   PetscFunctionBegin;
70313af1a74SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
7044f572ea9SToby Isaac   PetscAssertPointer(rhshp1, 2);
70513af1a74SHong Zhang 
70613af1a74SHong Zhang   ts->rhshessianproductctx = ctx;
70713af1a74SHong Zhang   if (rhshp1) ts->vecs_guu = rhshp1;
70813af1a74SHong Zhang   if (rhshp2) ts->vecs_gup = rhshp2;
70913af1a74SHong Zhang   if (rhshp3) ts->vecs_gpu = rhshp3;
71013af1a74SHong Zhang   if (rhshp4) ts->vecs_gpp = rhshp4;
71113af1a74SHong Zhang   ts->rhshessianproduct_guu = rhshessianproductfunc1;
71213af1a74SHong Zhang   ts->rhshessianproduct_gup = rhshessianproductfunc2;
71313af1a74SHong Zhang   ts->rhshessianproduct_gpu = rhshessianproductfunc3;
71413af1a74SHong Zhang   ts->rhshessianproduct_gpp = rhshessianproductfunc4;
7153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
71613af1a74SHong Zhang }
71713af1a74SHong Zhang 
718cc4c1da9SBarry Smith /*@
719b1e111ebSHong Zhang   TSComputeRHSHessianProductFunctionUU - Runs the user-defined vector-Hessian-vector product function for Guu.
72013af1a74SHong Zhang 
721c3339decSBarry Smith   Collective
72213af1a74SHong Zhang 
72313af1a74SHong Zhang   Input Parameters:
7242fe279fdSBarry Smith + ts - The `TS` context obtained from `TSCreate()`
7252fe279fdSBarry Smith . t  - the time
7262fe279fdSBarry Smith . U  - the solution at which to compute the Hessian product
7272fe279fdSBarry Smith . Vl - the array of input vectors to be multiplied with the Hessian from the left
7282fe279fdSBarry Smith - Vr - the input vector to be multiplied with the Hessian from the right
7292fe279fdSBarry Smith 
7302fe279fdSBarry Smith   Output Parameter:
731b43aa488SJacob Faibussowitsch . VHV - the array of output vectors that store the Hessian product
73213af1a74SHong Zhang 
73313af1a74SHong Zhang   Level: developer
73413af1a74SHong Zhang 
735bcf0153eSBarry Smith   Note:
736bcf0153eSBarry Smith   `TSComputeRHSHessianProductFunctionUU()` is typically used for sensitivity implementation,
737bcf0153eSBarry Smith   so most users would not generally call this routine themselves.
738bcf0153eSBarry Smith 
7391cc06b55SBarry Smith .seealso: [](ch_ts), `TS`, `TSSetRHSHessianProduct()`
74013af1a74SHong Zhang @*/
TSComputeRHSHessianProductFunctionUU(TS ts,PetscReal t,Vec U,Vec Vl[],Vec Vr,Vec VHV[])741cc4c1da9SBarry Smith PetscErrorCode TSComputeRHSHessianProductFunctionUU(TS ts, PetscReal t, Vec U, Vec Vl[], Vec Vr, Vec VHV[])
742d71ae5a4SJacob Faibussowitsch {
74313af1a74SHong Zhang   PetscFunctionBegin;
7443ba16761SJacob Faibussowitsch   if (!VHV) PetscFunctionReturn(PETSC_SUCCESS);
74513af1a74SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
74613af1a74SHong Zhang   PetscValidHeaderSpecific(U, VEC_CLASSID, 3);
74713af1a74SHong Zhang 
748792fecdfSBarry Smith   PetscCallBack("TS callback RHSHessianProduct 1 for sensitivity analysis", (*ts->rhshessianproduct_guu)(ts, t, U, Vl, Vr, VHV, ts->rhshessianproductctx));
7493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
75013af1a74SHong Zhang }
75113af1a74SHong Zhang 
752cc4c1da9SBarry Smith /*@
753b1e111ebSHong Zhang   TSComputeRHSHessianProductFunctionUP - Runs the user-defined vector-Hessian-vector product function for Gup.
75413af1a74SHong Zhang 
755c3339decSBarry Smith   Collective
75613af1a74SHong Zhang 
75713af1a74SHong Zhang   Input Parameters:
7582fe279fdSBarry Smith + ts - The `TS` context obtained from `TSCreate()`
7592fe279fdSBarry Smith . t  - the time
7602fe279fdSBarry Smith . U  - the solution at which to compute the Hessian product
7612fe279fdSBarry Smith . Vl - the array of input vectors to be multiplied with the Hessian from the left
7622fe279fdSBarry Smith - Vr - the input vector to be multiplied with the Hessian from the right
7632fe279fdSBarry Smith 
7642fe279fdSBarry Smith   Output Parameter:
765b43aa488SJacob Faibussowitsch . VHV - the array of output vectors that store the Hessian product
76613af1a74SHong Zhang 
76713af1a74SHong Zhang   Level: developer
76813af1a74SHong Zhang 
769bcf0153eSBarry Smith   Note:
770bcf0153eSBarry Smith   `TSComputeRHSHessianProductFunctionUP()` is typically used for sensitivity implementation,
771bcf0153eSBarry Smith   so most users would not generally call this routine themselves.
772bcf0153eSBarry Smith 
7731cc06b55SBarry Smith .seealso: [](ch_ts), `TS`, `TSSetRHSHessianProduct()`
77413af1a74SHong Zhang @*/
TSComputeRHSHessianProductFunctionUP(TS ts,PetscReal t,Vec U,Vec Vl[],Vec Vr,Vec VHV[])775cc4c1da9SBarry Smith PetscErrorCode TSComputeRHSHessianProductFunctionUP(TS ts, PetscReal t, Vec U, Vec Vl[], Vec Vr, Vec VHV[])
776d71ae5a4SJacob Faibussowitsch {
77713af1a74SHong Zhang   PetscFunctionBegin;
7783ba16761SJacob Faibussowitsch   if (!VHV) PetscFunctionReturn(PETSC_SUCCESS);
77913af1a74SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
78013af1a74SHong Zhang   PetscValidHeaderSpecific(U, VEC_CLASSID, 3);
78113af1a74SHong Zhang 
782792fecdfSBarry Smith   PetscCallBack("TS callback RHSHessianProduct 2 for sensitivity analysis", (*ts->rhshessianproduct_gup)(ts, t, U, Vl, Vr, VHV, ts->rhshessianproductctx));
7833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
78413af1a74SHong Zhang }
78513af1a74SHong Zhang 
786cc4c1da9SBarry Smith /*@
787b1e111ebSHong Zhang   TSComputeRHSHessianProductFunctionPU - Runs the user-defined vector-Hessian-vector product function for Gpu.
78813af1a74SHong Zhang 
789c3339decSBarry Smith   Collective
79013af1a74SHong Zhang 
79113af1a74SHong Zhang   Input Parameters:
7922fe279fdSBarry Smith + ts - The `TS` context obtained from `TSCreate()`
7932fe279fdSBarry Smith . t  - the time
7942fe279fdSBarry Smith . U  - the solution at which to compute the Hessian product
7952fe279fdSBarry Smith . Vl - the array of input vectors to be multiplied with the Hessian from the left
7962fe279fdSBarry Smith - Vr - the input vector to be multiplied with the Hessian from the right
7972fe279fdSBarry Smith 
7982fe279fdSBarry Smith   Output Parameter:
799b43aa488SJacob Faibussowitsch . VHV - the array of output vectors that store the Hessian product
80013af1a74SHong Zhang 
80113af1a74SHong Zhang   Level: developer
80213af1a74SHong Zhang 
803bcf0153eSBarry Smith   Note:
804bcf0153eSBarry Smith   `TSComputeRHSHessianProductFunctionPU()` is typically used for sensitivity implementation,
805bcf0153eSBarry Smith   so most users would not generally call this routine themselves.
806bcf0153eSBarry Smith 
8071cc06b55SBarry Smith .seealso: [](ch_ts), `TSSetRHSHessianProduct()`
80813af1a74SHong Zhang @*/
TSComputeRHSHessianProductFunctionPU(TS ts,PetscReal t,Vec U,Vec Vl[],Vec Vr,Vec VHV[])809cc4c1da9SBarry Smith PetscErrorCode TSComputeRHSHessianProductFunctionPU(TS ts, PetscReal t, Vec U, Vec Vl[], Vec Vr, Vec VHV[])
810d71ae5a4SJacob Faibussowitsch {
81113af1a74SHong Zhang   PetscFunctionBegin;
8123ba16761SJacob Faibussowitsch   if (!VHV) PetscFunctionReturn(PETSC_SUCCESS);
81313af1a74SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
81413af1a74SHong Zhang   PetscValidHeaderSpecific(U, VEC_CLASSID, 3);
81513af1a74SHong Zhang 
816792fecdfSBarry Smith   PetscCallBack("TS callback RHSHessianProduct 3 for sensitivity analysis", (*ts->rhshessianproduct_gpu)(ts, t, U, Vl, Vr, VHV, ts->rhshessianproductctx));
8173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
81813af1a74SHong Zhang }
81913af1a74SHong Zhang 
820cc4c1da9SBarry Smith /*@
821b1e111ebSHong Zhang   TSComputeRHSHessianProductFunctionPP - Runs the user-defined vector-Hessian-vector product function for Gpp.
82213af1a74SHong Zhang 
823c3339decSBarry Smith   Collective
82413af1a74SHong Zhang 
82513af1a74SHong Zhang   Input Parameters:
8262fe279fdSBarry Smith + ts - The `TS` context obtained from `TSCreate()`
8272fe279fdSBarry Smith . t  - the time
8282fe279fdSBarry Smith . U  - the solution at which to compute the Hessian product
8292fe279fdSBarry Smith . Vl - the array of input vectors to be multiplied with the Hessian from the left
8302fe279fdSBarry Smith - Vr - the input vector to be multiplied with the Hessian from the right
8312fe279fdSBarry Smith 
8322fe279fdSBarry Smith   Output Parameter:
833b43aa488SJacob Faibussowitsch . VHV - the array of output vectors that store the Hessian product
83413af1a74SHong Zhang 
83513af1a74SHong Zhang   Level: developer
83613af1a74SHong Zhang 
837bcf0153eSBarry Smith   Note:
838bcf0153eSBarry Smith   `TSComputeRHSHessianProductFunctionPP()` is typically used for sensitivity implementation,
839bcf0153eSBarry Smith   so most users would not generally call this routine themselves.
840bcf0153eSBarry Smith 
8411cc06b55SBarry Smith .seealso: [](ch_ts), `TSSetRHSHessianProduct()`
84213af1a74SHong Zhang @*/
TSComputeRHSHessianProductFunctionPP(TS ts,PetscReal t,Vec U,Vec Vl[],Vec Vr,Vec VHV[])843cc4c1da9SBarry Smith PetscErrorCode TSComputeRHSHessianProductFunctionPP(TS ts, PetscReal t, Vec U, Vec Vl[], Vec Vr, Vec VHV[])
844d71ae5a4SJacob Faibussowitsch {
84513af1a74SHong Zhang   PetscFunctionBegin;
8463ba16761SJacob Faibussowitsch   if (!VHV) PetscFunctionReturn(PETSC_SUCCESS);
84713af1a74SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
84813af1a74SHong Zhang   PetscValidHeaderSpecific(U, VEC_CLASSID, 3);
84913af1a74SHong Zhang 
850792fecdfSBarry Smith   PetscCallBack("TS callback RHSHessianProduct 3 for sensitivity analysis", (*ts->rhshessianproduct_gpp)(ts, t, U, Vl, Vr, VHV, ts->rhshessianproductctx));
8513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
85213af1a74SHong Zhang }
85313af1a74SHong Zhang 
854814e85d6SHong Zhang /* --------------------------- Adjoint sensitivity ---------------------------*/
855814e85d6SHong Zhang 
856814e85d6SHong Zhang /*@
857814e85d6SHong 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
858bcf0153eSBarry Smith   for use by the `TS` adjoint routines.
859814e85d6SHong Zhang 
860c3339decSBarry Smith   Logically Collective
861814e85d6SHong Zhang 
862814e85d6SHong Zhang   Input Parameters:
863bcf0153eSBarry Smith + ts      - the `TS` context obtained from `TSCreate()`
864d2fd7bfcSHong Zhang . numcost - number of gradients to be computed, this is the number of cost functions
865814e85d6SHong 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
866814e85d6SHong Zhang - mu      - gradients with respect to the parameters, the number of entries in these vectors is the same as the number of parameters
867814e85d6SHong Zhang 
868814e85d6SHong Zhang   Level: beginner
869814e85d6SHong Zhang 
870814e85d6SHong Zhang   Notes:
87135cb6cd3SPierre Jolivet   the entries in these vectors must be correctly initialized with the values lambda_i = df/dy|finaltime  mu_i = df/dp|finaltime
872814e85d6SHong Zhang 
87335cb6cd3SPierre Jolivet   After `TSAdjointSolve()` is called the lambda and the mu contain the computed sensitivities
874814e85d6SHong Zhang 
875bcf0153eSBarry Smith .seealso: `TS`, `TSAdjointSolve()`, `TSGetCostGradients()`
876814e85d6SHong Zhang @*/
TSSetCostGradients(TS ts,PetscInt numcost,Vec lambda[],Vec mu[])8770fc7ecceSBarry Smith PetscErrorCode TSSetCostGradients(TS ts, PetscInt numcost, Vec lambda[], Vec mu[])
878d71ae5a4SJacob Faibussowitsch {
879814e85d6SHong Zhang   PetscFunctionBegin;
880814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
8814f572ea9SToby Isaac   PetscAssertPointer(lambda, 3);
882814e85d6SHong Zhang   ts->vecs_sensi  = lambda;
883814e85d6SHong Zhang   ts->vecs_sensip = mu;
8843c633725SBarry 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");
885814e85d6SHong Zhang   ts->numcost = numcost;
8863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
887814e85d6SHong Zhang }
888814e85d6SHong Zhang 
889814e85d6SHong Zhang /*@
890bcf0153eSBarry Smith   TSGetCostGradients - Returns the gradients from the `TSAdjointSolve()`
891814e85d6SHong Zhang 
892bcf0153eSBarry Smith   Not Collective, but the vectors returned are parallel if `TS` is parallel
893814e85d6SHong Zhang 
894814e85d6SHong Zhang   Input Parameter:
895bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()`
896814e85d6SHong Zhang 
897d8d19677SJose E. Roman   Output Parameters:
8986b867d5aSJose E. Roman + numcost - size of returned arrays
8996b867d5aSJose E. Roman . lambda  - vectors containing the gradients of the cost functions with respect to the ODE/DAE solution variables
900814e85d6SHong Zhang - mu      - vectors containing the gradients of the cost functions with respect to the problem parameters
901814e85d6SHong Zhang 
902814e85d6SHong Zhang   Level: intermediate
903814e85d6SHong Zhang 
9041cc06b55SBarry Smith .seealso: [](ch_ts), `TS`, `TSAdjointSolve()`, `TSSetCostGradients()`
905814e85d6SHong Zhang @*/
TSGetCostGradients(TS ts,PetscInt * numcost,Vec * lambda[],Vec * mu[])9060fc7ecceSBarry Smith PetscErrorCode TSGetCostGradients(TS ts, PetscInt *numcost, Vec *lambda[], Vec *mu[])
907d71ae5a4SJacob Faibussowitsch {
908814e85d6SHong Zhang   PetscFunctionBegin;
909814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
910814e85d6SHong Zhang   if (numcost) *numcost = ts->numcost;
911814e85d6SHong Zhang   if (lambda) *lambda = ts->vecs_sensi;
912814e85d6SHong Zhang   if (mu) *mu = ts->vecs_sensip;
9133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
914814e85d6SHong Zhang }
915814e85d6SHong Zhang 
916814e85d6SHong Zhang /*@
917b5b4017aSHong 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
918bcf0153eSBarry Smith   for use by the `TS` adjoint routines.
919b5b4017aSHong Zhang 
920c3339decSBarry Smith   Logically Collective
921b5b4017aSHong Zhang 
922b5b4017aSHong Zhang   Input Parameters:
923bcf0153eSBarry Smith + ts      - the `TS` context obtained from `TSCreate()`
924b5b4017aSHong Zhang . numcost - number of cost functions
925b5b4017aSHong 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
926b5b4017aSHong 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
927b5b4017aSHong Zhang - dir     - the direction vector that are multiplied with the Hessian of the cost functions
928b5b4017aSHong Zhang 
929b5b4017aSHong Zhang   Level: beginner
930b5b4017aSHong Zhang 
931bcf0153eSBarry Smith   Notes:
932bcf0153eSBarry Smith   Hessian of the cost function is completely different from Hessian of the ODE/DAE system
933b5b4017aSHong Zhang 
934bcf0153eSBarry Smith   For second-order adjoint, one needs to call this function and then `TSAdjointSetForward()` before `TSSolve()`.
935b5b4017aSHong Zhang 
93635cb6cd3SPierre 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.
937b5b4017aSHong Zhang 
9382fe279fdSBarry Smith   Passing `NULL` for `lambda2` disables the second-order calculation.
939bcf0153eSBarry Smith 
9401cc06b55SBarry Smith .seealso: [](ch_ts), `TS`, `TSAdjointSolve()`, `TSAdjointSetForward()`
941b5b4017aSHong Zhang @*/
TSSetCostHessianProducts(TS ts,PetscInt numcost,Vec lambda2[],Vec mu2[],Vec dir)9420fc7ecceSBarry Smith PetscErrorCode TSSetCostHessianProducts(TS ts, PetscInt numcost, Vec lambda2[], Vec mu2[], Vec dir)
943d71ae5a4SJacob Faibussowitsch {
944b5b4017aSHong Zhang   PetscFunctionBegin;
945b5b4017aSHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
9463c633725SBarry 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");
947b5b4017aSHong Zhang   ts->numcost      = numcost;
948b5b4017aSHong Zhang   ts->vecs_sensi2  = lambda2;
94933f72c5dSHong Zhang   ts->vecs_sensi2p = mu2;
950b5b4017aSHong Zhang   ts->vec_dir      = dir;
9513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
952b5b4017aSHong Zhang }
953b5b4017aSHong Zhang 
954b5b4017aSHong Zhang /*@
955bcf0153eSBarry Smith   TSGetCostHessianProducts - Returns the gradients from the `TSAdjointSolve()`
956b5b4017aSHong Zhang 
957bcf0153eSBarry Smith   Not Collective, but vectors returned are parallel if `TS` is parallel
958b5b4017aSHong Zhang 
959b5b4017aSHong Zhang   Input Parameter:
960bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()`
961b5b4017aSHong Zhang 
962d8d19677SJose E. Roman   Output Parameters:
963b5b4017aSHong Zhang + numcost - number of cost functions
964b5b4017aSHong 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
965b5b4017aSHong 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
966b5b4017aSHong Zhang - dir     - the direction vector that are multiplied with the Hessian of the cost functions
967b5b4017aSHong Zhang 
968b5b4017aSHong Zhang   Level: intermediate
969b5b4017aSHong Zhang 
9701cc06b55SBarry Smith .seealso: [](ch_ts), `TSAdjointSolve()`, `TSSetCostHessianProducts()`
971b5b4017aSHong Zhang @*/
TSGetCostHessianProducts(TS ts,PetscInt * numcost,Vec * lambda2[],Vec * mu2[],Vec * dir)9720fc7ecceSBarry Smith PetscErrorCode TSGetCostHessianProducts(TS ts, PetscInt *numcost, Vec *lambda2[], Vec *mu2[], Vec *dir)
973d71ae5a4SJacob Faibussowitsch {
974b5b4017aSHong Zhang   PetscFunctionBegin;
975b5b4017aSHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
976b5b4017aSHong Zhang   if (numcost) *numcost = ts->numcost;
977b5b4017aSHong Zhang   if (lambda2) *lambda2 = ts->vecs_sensi2;
97833f72c5dSHong Zhang   if (mu2) *mu2 = ts->vecs_sensi2p;
979b5b4017aSHong Zhang   if (dir) *dir = ts->vec_dir;
9803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
981b5b4017aSHong Zhang }
982b5b4017aSHong Zhang 
983b5b4017aSHong Zhang /*@
984ecf68647SHong Zhang   TSAdjointSetForward - Trigger the tangent linear solver and initialize the forward sensitivities
985b5b4017aSHong Zhang 
986c3339decSBarry Smith   Logically Collective
987b5b4017aSHong Zhang 
988b5b4017aSHong Zhang   Input Parameters:
989bcf0153eSBarry Smith + ts   - the `TS` context obtained from `TSCreate()`
990b5b4017aSHong Zhang - didp - the derivative of initial values w.r.t. parameters
991b5b4017aSHong Zhang 
992b5b4017aSHong Zhang   Level: intermediate
993b5b4017aSHong Zhang 
994bcf0153eSBarry Smith   Notes:
995baca6076SPierre 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.
9962fe279fdSBarry Smith   `TSAdjoint` does not reset the tangent linear solver automatically, `TSAdjointResetForward()` should be called to reset the tangent linear solver.
997b5b4017aSHong Zhang 
9981cc06b55SBarry Smith .seealso: [](ch_ts), `TSAdjointSolve()`, `TSSetCostHessianProducts()`, `TSAdjointResetForward()`
999b5b4017aSHong Zhang @*/
TSAdjointSetForward(TS ts,Mat didp)1000d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointSetForward(TS ts, Mat didp)
1001d71ae5a4SJacob Faibussowitsch {
100233f72c5dSHong Zhang   Mat          A;
100333f72c5dSHong Zhang   Vec          sp;
100433f72c5dSHong Zhang   PetscScalar *xarr;
100533f72c5dSHong Zhang   PetscInt     lsize;
1006b5b4017aSHong Zhang 
1007b5b4017aSHong Zhang   PetscFunctionBegin;
1008b5b4017aSHong Zhang   ts->forward_solve = PETSC_TRUE; /* turn on tangent linear mode */
10093c633725SBarry Smith   PetscCheck(ts->vecs_sensi2, PetscObjectComm((PetscObject)ts), PETSC_ERR_USER, "Must call TSSetCostHessianProducts() first");
10103c633725SBarry Smith   PetscCheck(ts->vec_dir, PetscObjectComm((PetscObject)ts), PETSC_ERR_USER, "Directional vector is missing. Call TSSetCostHessianProducts() to set it.");
101133f72c5dSHong Zhang   /* create a single-column dense matrix */
10129566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(ts->vec_sol, &lsize));
10139566063dSJacob Faibussowitsch   PetscCall(MatCreateDense(PetscObjectComm((PetscObject)ts), lsize, PETSC_DECIDE, PETSC_DECIDE, 1, NULL, &A));
101433f72c5dSHong Zhang 
10159566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(ts->vec_sol, &sp));
10169566063dSJacob Faibussowitsch   PetscCall(MatDenseGetColumn(A, 0, &xarr));
10179566063dSJacob Faibussowitsch   PetscCall(VecPlaceArray(sp, xarr));
1018ecf68647SHong Zhang   if (ts->vecs_sensi2p) { /* tangent linear variable initialized as 2*dIdP*dir */
101933f72c5dSHong Zhang     if (didp) {
10209566063dSJacob Faibussowitsch       PetscCall(MatMult(didp, ts->vec_dir, sp));
10219566063dSJacob Faibussowitsch       PetscCall(VecScale(sp, 2.));
102233f72c5dSHong Zhang     } else {
10239566063dSJacob Faibussowitsch       PetscCall(VecZeroEntries(sp));
102433f72c5dSHong Zhang     }
1025ecf68647SHong Zhang   } else { /* tangent linear variable initialized as dir */
10269566063dSJacob Faibussowitsch     PetscCall(VecCopy(ts->vec_dir, sp));
102733f72c5dSHong Zhang   }
10289566063dSJacob Faibussowitsch   PetscCall(VecResetArray(sp));
10299566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreColumn(A, &xarr));
10309566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&sp));
103133f72c5dSHong Zhang 
10329566063dSJacob Faibussowitsch   PetscCall(TSForwardSetInitialSensitivities(ts, A)); /* if didp is NULL, identity matrix is assumed */
103333f72c5dSHong Zhang 
10349566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&A));
10353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1036b5b4017aSHong Zhang }
1037b5b4017aSHong Zhang 
1038b5b4017aSHong Zhang /*@
1039ecf68647SHong Zhang   TSAdjointResetForward - Reset the tangent linear solver and destroy the tangent linear context
1040ecf68647SHong Zhang 
1041c3339decSBarry Smith   Logically Collective
1042ecf68647SHong Zhang 
10432fe279fdSBarry Smith   Input Parameter:
1044bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()`
1045ecf68647SHong Zhang 
1046ecf68647SHong Zhang   Level: intermediate
1047ecf68647SHong Zhang 
10481cc06b55SBarry Smith .seealso: [](ch_ts), `TSAdjointSetForward()`
1049ecf68647SHong Zhang @*/
TSAdjointResetForward(TS ts)1050d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointResetForward(TS ts)
1051d71ae5a4SJacob Faibussowitsch {
1052ecf68647SHong Zhang   PetscFunctionBegin;
1053ecf68647SHong Zhang   ts->forward_solve = PETSC_FALSE; /* turn off tangent linear mode */
10549566063dSJacob Faibussowitsch   PetscCall(TSForwardReset(ts));
10553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1056ecf68647SHong Zhang }
1057ecf68647SHong Zhang 
1058ecf68647SHong Zhang /*@
1059814e85d6SHong Zhang   TSAdjointSetUp - Sets up the internal data structures for the later use
1060814e85d6SHong Zhang   of an adjoint solver
1061814e85d6SHong Zhang 
1062c3339decSBarry Smith   Collective
1063814e85d6SHong Zhang 
1064814e85d6SHong Zhang   Input Parameter:
1065bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()`
1066814e85d6SHong Zhang 
1067814e85d6SHong Zhang   Level: advanced
1068814e85d6SHong Zhang 
10691cc06b55SBarry Smith .seealso: [](ch_ts), `TSCreate()`, `TSAdjointStep()`, `TSSetCostGradients()`
1070814e85d6SHong Zhang @*/
TSAdjointSetUp(TS ts)1071d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointSetUp(TS ts)
1072d71ae5a4SJacob Faibussowitsch {
1073881c1a9bSHong Zhang   TSTrajectory tj;
1074881c1a9bSHong Zhang   PetscBool    match;
1075814e85d6SHong Zhang 
1076814e85d6SHong Zhang   PetscFunctionBegin;
1077814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
10783ba16761SJacob Faibussowitsch   if (ts->adjointsetupcalled) PetscFunctionReturn(PETSC_SUCCESS);
10793c633725SBarry Smith   PetscCheck(ts->vecs_sensi, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONGSTATE, "Must call TSSetCostGradients() first");
10803c633725SBarry Smith   PetscCheck(!ts->vecs_sensip || ts->Jacp || ts->Jacprhs, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONGSTATE, "Must call TSSetRHSJacobianP() or TSSetIJacobianP() first");
10819566063dSJacob Faibussowitsch   PetscCall(TSGetTrajectory(ts, &tj));
10829566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)tj, TSTRAJECTORYBASIC, &match));
1083881c1a9bSHong Zhang   if (match) {
1084881c1a9bSHong Zhang     PetscBool solution_only;
10859566063dSJacob Faibussowitsch     PetscCall(TSTrajectoryGetSolutionOnly(tj, &solution_only));
10863c633725SBarry 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");
1087881c1a9bSHong Zhang   }
10889566063dSJacob Faibussowitsch   PetscCall(TSTrajectorySetUseHistory(tj, PETSC_FALSE)); /* not use TSHistory */
108933f72c5dSHong Zhang 
1090cd4cee2dSHong Zhang   if (ts->quadraturets) { /* if there is integral in the cost function */
10919566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(ts->vecs_sensi[0], &ts->vec_drdu_col));
109248a46eb9SPierre Jolivet     if (ts->vecs_sensip) PetscCall(VecDuplicate(ts->vecs_sensip[0], &ts->vec_drdp_col));
1093814e85d6SHong Zhang   }
1094814e85d6SHong Zhang 
1095dbbe0bcdSBarry Smith   PetscTryTypeMethod(ts, adjointsetup);
1096814e85d6SHong Zhang   ts->adjointsetupcalled = PETSC_TRUE;
10973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1098814e85d6SHong Zhang }
1099814e85d6SHong Zhang 
1100814e85d6SHong Zhang /*@
1101bcf0153eSBarry Smith   TSAdjointReset - Resets a `TS` adjoint context and removes any allocated `Vec`s and `Mat`s.
1102ece46509SHong Zhang 
1103c3339decSBarry Smith   Collective
1104ece46509SHong Zhang 
1105ece46509SHong Zhang   Input Parameter:
1106bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()`
1107ece46509SHong Zhang 
1108ece46509SHong Zhang   Level: beginner
1109ece46509SHong Zhang 
1110bfe80ac4SPierre Jolivet .seealso: [](ch_ts), `TSCreate()`, `TSAdjointSetUp()`, `TSDestroy()`
1111ece46509SHong Zhang @*/
TSAdjointReset(TS ts)1112d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointReset(TS ts)
1113d71ae5a4SJacob Faibussowitsch {
1114ece46509SHong Zhang   PetscFunctionBegin;
1115ece46509SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
1116dbbe0bcdSBarry Smith   PetscTryTypeMethod(ts, adjointreset);
11177207e0fdSHong Zhang   if (ts->quadraturets) { /* if there is integral in the cost function */
11189566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&ts->vec_drdu_col));
111948a46eb9SPierre Jolivet     if (ts->vecs_sensip) PetscCall(VecDestroy(&ts->vec_drdp_col));
11207207e0fdSHong Zhang   }
1121ece46509SHong Zhang   ts->vecs_sensi         = NULL;
1122ece46509SHong Zhang   ts->vecs_sensip        = NULL;
1123ece46509SHong Zhang   ts->vecs_sensi2        = NULL;
112433f72c5dSHong Zhang   ts->vecs_sensi2p       = NULL;
1125ece46509SHong Zhang   ts->vec_dir            = NULL;
1126ece46509SHong Zhang   ts->adjointsetupcalled = PETSC_FALSE;
11273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1128ece46509SHong Zhang }
1129ece46509SHong Zhang 
1130ece46509SHong Zhang /*@
1131814e85d6SHong Zhang   TSAdjointSetSteps - Sets the number of steps the adjoint solver should take backward in time
1132814e85d6SHong Zhang 
1133c3339decSBarry Smith   Logically Collective
1134814e85d6SHong Zhang 
1135814e85d6SHong Zhang   Input Parameters:
1136bcf0153eSBarry Smith + ts    - the `TS` context obtained from `TSCreate()`
1137a2b725a8SWilliam Gropp - steps - number of steps to use
1138814e85d6SHong Zhang 
1139814e85d6SHong Zhang   Level: intermediate
1140814e85d6SHong Zhang 
1141814e85d6SHong Zhang   Notes:
1142bcf0153eSBarry Smith   Normally one does not call this and `TSAdjointSolve()` integrates back to the original timestep. One can call this
1143814e85d6SHong Zhang   so as to integrate back to less than the original timestep
1144814e85d6SHong Zhang 
11451cc06b55SBarry Smith .seealso: [](ch_ts), `TSAdjointSolve()`, `TS`, `TSSetExactFinalTime()`
1146814e85d6SHong Zhang @*/
TSAdjointSetSteps(TS ts,PetscInt steps)1147d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointSetSteps(TS ts, PetscInt steps)
1148d71ae5a4SJacob Faibussowitsch {
1149814e85d6SHong Zhang   PetscFunctionBegin;
1150814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
1151814e85d6SHong Zhang   PetscValidLogicalCollectiveInt(ts, steps, 2);
11523c633725SBarry Smith   PetscCheck(steps >= 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Cannot step back a negative number of steps");
11533c633725SBarry Smith   PetscCheck(steps <= ts->steps, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Cannot step back more than the total number of forward steps");
1154814e85d6SHong Zhang   ts->adjoint_max_steps = steps;
11553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1156814e85d6SHong Zhang }
1157814e85d6SHong Zhang 
115814d0ab18SJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-*
1159814e85d6SHong Zhang /*@C
1160bcf0153eSBarry Smith   TSAdjointSetRHSJacobian - Deprecated, use `TSSetRHSJacobianP()`
1161814e85d6SHong Zhang 
1162814e85d6SHong Zhang   Level: deprecated
1163814e85d6SHong Zhang @*/
TSAdjointSetRHSJacobian(TS ts,Mat Amat,PetscErrorCode (* func)(TS,PetscReal,Vec,Mat,void *),PetscCtx ctx)1164*2a8381b2SBarry Smith PetscErrorCode TSAdjointSetRHSJacobian(TS ts, Mat Amat, PetscErrorCode (*func)(TS, PetscReal, Vec, Mat, void *), PetscCtx ctx)
1165d71ae5a4SJacob Faibussowitsch {
1166814e85d6SHong Zhang   PetscFunctionBegin;
1167814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
1168814e85d6SHong Zhang   PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2);
1169814e85d6SHong Zhang 
1170814e85d6SHong Zhang   ts->rhsjacobianp    = func;
1171814e85d6SHong Zhang   ts->rhsjacobianpctx = ctx;
1172814e85d6SHong Zhang   if (Amat) {
11739566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)Amat));
11749566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&ts->Jacp));
1175814e85d6SHong Zhang     ts->Jacp = Amat;
1176814e85d6SHong Zhang   }
11773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1178814e85d6SHong Zhang }
1179814e85d6SHong Zhang 
118014d0ab18SJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-*
1181814e85d6SHong Zhang /*@C
1182bcf0153eSBarry Smith   TSAdjointComputeRHSJacobian - Deprecated, use `TSComputeRHSJacobianP()`
1183814e85d6SHong Zhang 
1184814e85d6SHong Zhang   Level: deprecated
1185814e85d6SHong Zhang @*/
TSAdjointComputeRHSJacobian(TS ts,PetscReal t,Vec U,Mat Amat)1186d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointComputeRHSJacobian(TS ts, PetscReal t, Vec U, Mat Amat)
1187d71ae5a4SJacob Faibussowitsch {
1188814e85d6SHong Zhang   PetscFunctionBegin;
1189814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
1190c9ad9de0SHong Zhang   PetscValidHeaderSpecific(U, VEC_CLASSID, 3);
1191292bffcbSToby Isaac   PetscValidHeaderSpecific(Amat, MAT_CLASSID, 4);
1192814e85d6SHong Zhang 
1193792fecdfSBarry Smith   PetscCallBack("TS callback JacobianP for sensitivity analysis", (*ts->rhsjacobianp)(ts, t, U, Amat, ts->rhsjacobianpctx));
11943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1195814e85d6SHong Zhang }
1196814e85d6SHong Zhang 
119714d0ab18SJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-*
1198814e85d6SHong Zhang /*@
1199bcf0153eSBarry Smith   TSAdjointComputeDRDYFunction - Deprecated, use `TSGetQuadratureTS()` then `TSComputeRHSJacobian()`
1200814e85d6SHong Zhang 
1201814e85d6SHong Zhang   Level: deprecated
1202814e85d6SHong Zhang @*/
TSAdjointComputeDRDYFunction(TS ts,PetscReal t,Vec U,Vec * DRDU)1203d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointComputeDRDYFunction(TS ts, PetscReal t, Vec U, Vec *DRDU)
1204d71ae5a4SJacob Faibussowitsch {
1205814e85d6SHong Zhang   PetscFunctionBegin;
1206814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
1207c9ad9de0SHong Zhang   PetscValidHeaderSpecific(U, VEC_CLASSID, 3);
1208814e85d6SHong Zhang 
1209792fecdfSBarry Smith   PetscCallBack("TS callback DRDY for sensitivity analysis", (*ts->drdufunction)(ts, t, U, DRDU, ts->costintegrandctx));
12103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1211814e85d6SHong Zhang }
1212814e85d6SHong Zhang 
121314d0ab18SJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-*
1214814e85d6SHong Zhang /*@
1215bcf0153eSBarry Smith   TSAdjointComputeDRDPFunction - Deprecated, use `TSGetQuadratureTS()` then `TSComputeRHSJacobianP()`
1216814e85d6SHong Zhang 
1217814e85d6SHong Zhang   Level: deprecated
1218814e85d6SHong Zhang @*/
TSAdjointComputeDRDPFunction(TS ts,PetscReal t,Vec U,Vec * DRDP)1219d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointComputeDRDPFunction(TS ts, PetscReal t, Vec U, Vec *DRDP)
1220d71ae5a4SJacob Faibussowitsch {
1221814e85d6SHong Zhang   PetscFunctionBegin;
1222814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
1223c9ad9de0SHong Zhang   PetscValidHeaderSpecific(U, VEC_CLASSID, 3);
1224814e85d6SHong Zhang 
1225792fecdfSBarry Smith   PetscCallBack("TS callback DRDP for sensitivity analysis", (*ts->drdpfunction)(ts, t, U, DRDP, ts->costintegrandctx));
12263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1227814e85d6SHong Zhang }
1228814e85d6SHong Zhang 
122914d0ab18SJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-param-list-func-parameter-documentation
1230814e85d6SHong Zhang /*@C
1231814e85d6SHong Zhang   TSAdjointMonitorSensi - monitors the first lambda sensitivity
1232814e85d6SHong Zhang 
1233814e85d6SHong Zhang   Level: intermediate
1234814e85d6SHong Zhang 
12351cc06b55SBarry Smith .seealso: [](ch_ts), `TSAdjointMonitorSet()`
1236814e85d6SHong Zhang @*/
TSAdjointMonitorSensi(TS ts,PetscInt step,PetscReal ptime,Vec v,PetscInt numcost,Vec * lambda,Vec * mu,PetscViewerAndFormat * vf)1237ba38deedSJacob Faibussowitsch static PetscErrorCode TSAdjointMonitorSensi(TS ts, PetscInt step, PetscReal ptime, Vec v, PetscInt numcost, Vec *lambda, Vec *mu, PetscViewerAndFormat *vf)
1238d71ae5a4SJacob Faibussowitsch {
1239814e85d6SHong Zhang   PetscViewer viewer = vf->viewer;
1240814e85d6SHong Zhang 
1241814e85d6SHong Zhang   PetscFunctionBegin;
1242064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 8);
12439566063dSJacob Faibussowitsch   PetscCall(PetscViewerPushFormat(viewer, vf->format));
12449566063dSJacob Faibussowitsch   PetscCall(VecView(lambda[0], viewer));
12459566063dSJacob Faibussowitsch   PetscCall(PetscViewerPopFormat(viewer));
12463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1247814e85d6SHong Zhang }
1248814e85d6SHong Zhang 
1249814e85d6SHong Zhang /*@C
1250814e85d6SHong Zhang   TSAdjointMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user
1251814e85d6SHong Zhang 
1252c3339decSBarry Smith   Collective
1253814e85d6SHong Zhang 
1254814e85d6SHong Zhang   Input Parameters:
1255bcf0153eSBarry Smith + ts           - `TS` object you wish to monitor
1256814e85d6SHong Zhang . name         - the monitor type one is seeking
1257814e85d6SHong Zhang . help         - message indicating what monitoring is done
1258814e85d6SHong Zhang . manual       - manual page for the monitor
125949abdd8aSBarry Smith . monitor      - the monitor function, its context must be a `PetscViewerAndFormat`
1260bcf0153eSBarry 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
1261814e85d6SHong Zhang 
1262814e85d6SHong Zhang   Level: developer
1263814e85d6SHong Zhang 
1264648c30bcSBarry Smith .seealso: [](ch_ts), `PetscOptionsCreateViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
1265db781477SPatrick Sanan           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
1266b43aa488SJacob Faibussowitsch           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
1267db781477SPatrick Sanan           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1268c2e3fba1SPatrick Sanan           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1269db781477SPatrick Sanan           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
127049abdd8aSBarry Smith           `PetscOptionsFList()`, `PetscOptionsEList()`, `PetscViewerAndFormat`
1271814e85d6SHong Zhang @*/
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 *))1272d71ae5a4SJacob 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 *))
1273d71ae5a4SJacob Faibussowitsch {
1274814e85d6SHong Zhang   PetscViewer       viewer;
1275814e85d6SHong Zhang   PetscViewerFormat format;
1276814e85d6SHong Zhang   PetscBool         flg;
1277814e85d6SHong Zhang 
1278814e85d6SHong Zhang   PetscFunctionBegin;
1279648c30bcSBarry Smith   PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)ts), ((PetscObject)ts)->options, ((PetscObject)ts)->prefix, name, &viewer, &format, &flg));
1280814e85d6SHong Zhang   if (flg) {
1281814e85d6SHong Zhang     PetscViewerAndFormat *vf;
12829566063dSJacob Faibussowitsch     PetscCall(PetscViewerAndFormatCreate(viewer, format, &vf));
1283648c30bcSBarry Smith     PetscCall(PetscViewerDestroy(&viewer));
12841baa6e33SBarry Smith     if (monitorsetup) PetscCall((*monitorsetup)(ts, vf));
1285*2a8381b2SBarry Smith     PetscCall(TSAdjointMonitorSet(ts, (PetscErrorCode (*)(TS, PetscInt, PetscReal, Vec, PetscInt, Vec *, Vec *, PetscCtx))monitor, vf, (PetscCtxDestroyFn *)PetscViewerAndFormatDestroy));
1286814e85d6SHong Zhang   }
12873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1288814e85d6SHong Zhang }
1289814e85d6SHong Zhang 
1290814e85d6SHong Zhang /*@C
1291814e85d6SHong Zhang   TSAdjointMonitorSet - Sets an ADDITIONAL function that is to be used at every
1292814e85d6SHong Zhang   timestep to display the iteration's  progress.
1293814e85d6SHong Zhang 
1294c3339decSBarry Smith   Logically Collective
1295814e85d6SHong Zhang 
1296814e85d6SHong Zhang   Input Parameters:
1297bcf0153eSBarry Smith + ts              - the `TS` context obtained from `TSCreate()`
1298814e85d6SHong Zhang . adjointmonitor  - monitoring routine
129914d0ab18SJacob Faibussowitsch . adjointmctx     - [optional] user-defined context for private data for the monitor routine
130014d0ab18SJacob Faibussowitsch                     (use `NULL` if no context is desired)
130149abdd8aSBarry Smith - adjointmdestroy - [optional] routine that frees monitor context (may be `NULL`), see `PetscCtxDestroyFn` for its calling sequence
1302814e85d6SHong Zhang 
130320f4b53cSBarry Smith   Calling sequence of `adjointmonitor`:
1304bcf0153eSBarry Smith + ts          - the `TS` context
130514d0ab18SJacob Faibussowitsch . steps       - iteration number (after the final time step the monitor routine is called with
130614d0ab18SJacob Faibussowitsch                 a step of -1, this is at the final time which may have been interpolated to)
1307814e85d6SHong Zhang . time        - current time
1308814e85d6SHong Zhang . u           - current iterate
1309814e85d6SHong Zhang . numcost     - number of cost functionos
1310814e85d6SHong Zhang . lambda      - sensitivities to initial conditions
1311814e85d6SHong Zhang . mu          - sensitivities to parameters
1312814e85d6SHong Zhang - adjointmctx - [optional] adjoint monitoring context
1313814e85d6SHong Zhang 
1314bcf0153eSBarry Smith   Level: intermediate
1315bcf0153eSBarry Smith 
1316bcf0153eSBarry Smith   Note:
1317814e85d6SHong Zhang   This routine adds an additional monitor to the list of monitors that
1318814e85d6SHong Zhang   already has been loaded.
1319814e85d6SHong Zhang 
1320b43aa488SJacob Faibussowitsch   Fortran Notes:
132120f4b53cSBarry Smith   Only a single monitor function can be set for each `TS` object
1322814e85d6SHong Zhang 
132349abdd8aSBarry Smith .seealso: [](ch_ts), `TS`, `TSAdjointSolve()`, `TSAdjointMonitorCancel()`, `PetscCtxDestroyFn`
1324814e85d6SHong Zhang @*/
TSAdjointMonitorSet(TS ts,PetscErrorCode (* adjointmonitor)(TS ts,PetscInt steps,PetscReal time,Vec u,PetscInt numcost,Vec * lambda,Vec * mu,PetscCtx adjointmctx),PetscCtx adjointmctx,PetscCtxDestroyFn * adjointmdestroy)1325*2a8381b2SBarry Smith PetscErrorCode TSAdjointMonitorSet(TS ts, PetscErrorCode (*adjointmonitor)(TS ts, PetscInt steps, PetscReal time, Vec u, PetscInt numcost, Vec *lambda, Vec *mu, PetscCtx adjointmctx), PetscCtx adjointmctx, PetscCtxDestroyFn *adjointmdestroy)
1326d71ae5a4SJacob Faibussowitsch {
1327814e85d6SHong Zhang   PetscFunctionBegin;
1328814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
1329453a69bbSBarry Smith   for (PetscInt i = 0; i < ts->numbermonitors; i++) {
1330453a69bbSBarry Smith     PetscBool identical;
1331453a69bbSBarry Smith 
1332453a69bbSBarry Smith     PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))(PetscVoidFn *)adjointmonitor, adjointmctx, adjointmdestroy, (PetscErrorCode (*)(void))(PetscVoidFn *)ts->adjointmonitor[i], ts->adjointmonitorcontext[i], ts->adjointmonitordestroy[i], &identical));
13333ba16761SJacob Faibussowitsch     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
1334814e85d6SHong Zhang   }
13353c633725SBarry Smith   PetscCheck(ts->numberadjointmonitors < MAXTSMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many adjoint monitors set");
1336814e85d6SHong Zhang   ts->adjointmonitor[ts->numberadjointmonitors]          = adjointmonitor;
1337814e85d6SHong Zhang   ts->adjointmonitordestroy[ts->numberadjointmonitors]   = adjointmdestroy;
1338835f2295SStefano Zampini   ts->adjointmonitorcontext[ts->numberadjointmonitors++] = adjointmctx;
13393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1340814e85d6SHong Zhang }
1341814e85d6SHong Zhang 
1342814e85d6SHong Zhang /*@C
1343814e85d6SHong Zhang   TSAdjointMonitorCancel - Clears all the adjoint monitors that have been set on a time-step object.
1344814e85d6SHong Zhang 
1345c3339decSBarry Smith   Logically Collective
1346814e85d6SHong Zhang 
13472fe279fdSBarry Smith   Input Parameter:
1348bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()`
1349814e85d6SHong Zhang 
1350814e85d6SHong Zhang   Notes:
1351814e85d6SHong Zhang   There is no way to remove a single, specific monitor.
1352814e85d6SHong Zhang 
1353814e85d6SHong Zhang   Level: intermediate
1354814e85d6SHong Zhang 
13551cc06b55SBarry Smith .seealso: [](ch_ts), `TS`, `TSAdjointSolve()`, `TSAdjointMonitorSet()`
1356814e85d6SHong Zhang @*/
TSAdjointMonitorCancel(TS ts)1357d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointMonitorCancel(TS ts)
1358d71ae5a4SJacob Faibussowitsch {
1359814e85d6SHong Zhang   PetscInt i;
1360814e85d6SHong Zhang 
1361814e85d6SHong Zhang   PetscFunctionBegin;
1362814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
1363814e85d6SHong Zhang   for (i = 0; i < ts->numberadjointmonitors; i++) {
136448a46eb9SPierre Jolivet     if (ts->adjointmonitordestroy[i]) PetscCall((*ts->adjointmonitordestroy[i])(&ts->adjointmonitorcontext[i]));
1365814e85d6SHong Zhang   }
1366814e85d6SHong Zhang   ts->numberadjointmonitors = 0;
13673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1368814e85d6SHong Zhang }
1369814e85d6SHong Zhang 
1370814e85d6SHong Zhang /*@C
1371814e85d6SHong Zhang   TSAdjointMonitorDefault - the default monitor of adjoint computations
1372814e85d6SHong Zhang 
137314d0ab18SJacob Faibussowitsch   Input Parameters:
137414d0ab18SJacob Faibussowitsch + ts      - the `TS` context
137514d0ab18SJacob Faibussowitsch . step    - iteration number (after the final time step the monitor routine is called with a
137614d0ab18SJacob Faibussowitsch step of -1, this is at the final time which may have been interpolated to)
137714d0ab18SJacob Faibussowitsch . time    - current time
137814d0ab18SJacob Faibussowitsch . v       - current iterate
137914d0ab18SJacob Faibussowitsch . numcost - number of cost functionos
138014d0ab18SJacob Faibussowitsch . lambda  - sensitivities to initial conditions
138114d0ab18SJacob Faibussowitsch . mu      - sensitivities to parameters
138214d0ab18SJacob Faibussowitsch - vf      - the viewer and format
138314d0ab18SJacob Faibussowitsch 
1384814e85d6SHong Zhang   Level: intermediate
1385814e85d6SHong Zhang 
13861cc06b55SBarry Smith .seealso: [](ch_ts), `TS`, `TSAdjointSolve()`, `TSAdjointMonitorSet()`
1387814e85d6SHong Zhang @*/
TSAdjointMonitorDefault(TS ts,PetscInt step,PetscReal time,Vec v,PetscInt numcost,Vec lambda[],Vec mu[],PetscViewerAndFormat * vf)13880fc7ecceSBarry Smith PetscErrorCode TSAdjointMonitorDefault(TS ts, PetscInt step, PetscReal time, Vec v, PetscInt numcost, Vec lambda[], Vec mu[], PetscViewerAndFormat *vf)
1389d71ae5a4SJacob Faibussowitsch {
1390814e85d6SHong Zhang   PetscViewer viewer = vf->viewer;
1391814e85d6SHong Zhang 
1392814e85d6SHong Zhang   PetscFunctionBegin;
139314d0ab18SJacob Faibussowitsch   (void)v;
139414d0ab18SJacob Faibussowitsch   (void)numcost;
139514d0ab18SJacob Faibussowitsch   (void)lambda;
139614d0ab18SJacob Faibussowitsch   (void)mu;
1397064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 8);
13989566063dSJacob Faibussowitsch   PetscCall(PetscViewerPushFormat(viewer, vf->format));
13999566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)ts)->tablevel));
140014d0ab18SJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " TS dt %g time %g%s", step, (double)ts->time_step, (double)time, ts->steprollback ? " (r)\n" : "\n"));
14019566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)ts)->tablevel));
14029566063dSJacob Faibussowitsch   PetscCall(PetscViewerPopFormat(viewer));
14033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1404814e85d6SHong Zhang }
1405814e85d6SHong Zhang 
1406814e85d6SHong Zhang /*@C
1407bcf0153eSBarry Smith   TSAdjointMonitorDrawSensi - Monitors progress of the adjoint `TS` solvers by calling
1408bcf0153eSBarry Smith   `VecView()` for the sensitivities to initial states at each timestep
1409814e85d6SHong Zhang 
1410c3339decSBarry Smith   Collective
1411814e85d6SHong Zhang 
1412814e85d6SHong Zhang   Input Parameters:
1413bcf0153eSBarry Smith + ts      - the `TS` context
1414814e85d6SHong Zhang . step    - current time-step
1415814e85d6SHong Zhang . ptime   - current time
1416814e85d6SHong Zhang . u       - current state
1417814e85d6SHong Zhang . numcost - number of cost functions
1418814e85d6SHong Zhang . lambda  - sensitivities to initial conditions
1419814e85d6SHong Zhang . mu      - sensitivities to parameters
14202fe279fdSBarry Smith - dummy   - either a viewer or `NULL`
1421814e85d6SHong Zhang 
1422814e85d6SHong Zhang   Level: intermediate
1423814e85d6SHong Zhang 
14241cc06b55SBarry Smith .seealso: [](ch_ts), `TSAdjointSolve()`, `TSAdjointMonitorSet()`, `TSAdjointMonitorDefault()`, `VecView()`
1425814e85d6SHong Zhang @*/
TSAdjointMonitorDrawSensi(TS ts,PetscInt step,PetscReal ptime,Vec u,PetscInt numcost,Vec lambda[],Vec mu[],void * dummy)14260fc7ecceSBarry Smith PetscErrorCode TSAdjointMonitorDrawSensi(TS ts, PetscInt step, PetscReal ptime, Vec u, PetscInt numcost, Vec lambda[], Vec mu[], void *dummy)
1427d71ae5a4SJacob Faibussowitsch {
1428814e85d6SHong Zhang   TSMonitorDrawCtx ictx = (TSMonitorDrawCtx)dummy;
1429814e85d6SHong Zhang   PetscDraw        draw;
1430814e85d6SHong Zhang   PetscReal        xl, yl, xr, yr, h;
1431814e85d6SHong Zhang   char             time[32];
1432814e85d6SHong Zhang 
1433814e85d6SHong Zhang   PetscFunctionBegin;
14343ba16761SJacob Faibussowitsch   if (!(((ictx->howoften > 0) && (!(step % ictx->howoften))) || ((ictx->howoften == -1) && ts->reason))) PetscFunctionReturn(PETSC_SUCCESS);
1435814e85d6SHong Zhang 
14369566063dSJacob Faibussowitsch   PetscCall(VecView(lambda[0], ictx->viewer));
14379566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(ictx->viewer, 0, &draw));
1438835f2295SStefano Zampini   PetscCall(PetscSNPrintf(time, 32, "Timestep %" PetscInt_FMT " Time %g", step, (double)ptime));
14399566063dSJacob Faibussowitsch   PetscCall(PetscDrawGetCoordinates(draw, &xl, &yl, &xr, &yr));
1440814e85d6SHong Zhang   h = yl + .95 * (yr - yl);
14419566063dSJacob Faibussowitsch   PetscCall(PetscDrawStringCentered(draw, .5 * (xl + xr), h, PETSC_DRAW_BLACK, time));
14429566063dSJacob Faibussowitsch   PetscCall(PetscDrawFlush(draw));
14433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1444814e85d6SHong Zhang }
1445814e85d6SHong Zhang 
144614d0ab18SJacob Faibussowitsch /*@C
144714d0ab18SJacob Faibussowitsch   TSAdjointSetFromOptions - Sets various `TS` adjoint parameters from options database.
1448814e85d6SHong Zhang 
1449c3339decSBarry Smith   Collective
1450814e85d6SHong Zhang 
145114d0ab18SJacob Faibussowitsch   Input Parameters:
145214d0ab18SJacob Faibussowitsch + ts                 - the `TS` context
145314d0ab18SJacob Faibussowitsch - PetscOptionsObject - the options context
1454814e85d6SHong Zhang 
1455814e85d6SHong Zhang   Options Database Keys:
145614d0ab18SJacob Faibussowitsch + -ts_adjoint_solve <yes,no>     - After solving the ODE/DAE solve the adjoint problem (requires `-ts_save_trajectory`)
1457814e85d6SHong Zhang . -ts_adjoint_monitor            - print information at each adjoint time step
1458814e85d6SHong Zhang - -ts_adjoint_monitor_draw_sensi - monitor the sensitivity of the first cost function wrt initial conditions (lambda[0]) graphically
1459814e85d6SHong Zhang 
1460814e85d6SHong Zhang   Level: developer
1461814e85d6SHong Zhang 
1462bcf0153eSBarry Smith   Note:
1463814e85d6SHong Zhang   This is not normally called directly by users
1464814e85d6SHong Zhang 
14651cc06b55SBarry Smith .seealso: [](ch_ts), `TSSetSaveTrajectory()`, `TSTrajectorySetUp()`
146614d0ab18SJacob Faibussowitsch @*/
TSAdjointSetFromOptions(TS ts,PetscOptionItems PetscOptionsObject)1467ce78bad3SBarry Smith PetscErrorCode TSAdjointSetFromOptions(TS ts, PetscOptionItems PetscOptionsObject)
1468d71ae5a4SJacob Faibussowitsch {
1469814e85d6SHong Zhang   PetscBool tflg, opt;
1470814e85d6SHong Zhang 
1471814e85d6SHong Zhang   PetscFunctionBegin;
1472dbbe0bcdSBarry Smith   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
1473d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "TS Adjoint options");
1474814e85d6SHong Zhang   tflg = ts->adjoint_solve ? PETSC_TRUE : PETSC_FALSE;
14759566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-ts_adjoint_solve", "Solve the adjoint problem immediately after solving the forward problem", "", tflg, &tflg, &opt));
1476814e85d6SHong Zhang   if (opt) {
14779566063dSJacob Faibussowitsch     PetscCall(TSSetSaveTrajectory(ts));
1478814e85d6SHong Zhang     ts->adjoint_solve = tflg;
1479814e85d6SHong Zhang   }
14809566063dSJacob Faibussowitsch   PetscCall(TSAdjointMonitorSetFromOptions(ts, "-ts_adjoint_monitor", "Monitor adjoint timestep size", "TSAdjointMonitorDefault", TSAdjointMonitorDefault, NULL));
14819566063dSJacob Faibussowitsch   PetscCall(TSAdjointMonitorSetFromOptions(ts, "-ts_adjoint_monitor_sensi", "Monitor sensitivity in the adjoint computation", "TSAdjointMonitorSensi", TSAdjointMonitorSensi, NULL));
1482814e85d6SHong Zhang   opt = PETSC_FALSE;
14839566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-ts_adjoint_monitor_draw_sensi", "Monitor adjoint sensitivities (lambda only) graphically", "TSAdjointMonitorDrawSensi", &opt));
1484814e85d6SHong Zhang   if (opt) {
1485814e85d6SHong Zhang     TSMonitorDrawCtx ctx;
1486814e85d6SHong Zhang     PetscInt         howoften = 1;
1487814e85d6SHong Zhang 
14889566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-ts_adjoint_monitor_draw_sensi", "Monitor adjoint sensitivities (lambda only) graphically", "TSAdjointMonitorDrawSensi", howoften, &howoften, NULL));
14899566063dSJacob Faibussowitsch     PetscCall(TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, &ctx));
149049abdd8aSBarry Smith     PetscCall(TSAdjointMonitorSet(ts, TSAdjointMonitorDrawSensi, ctx, (PetscCtxDestroyFn *)TSMonitorDrawCtxDestroy));
1491814e85d6SHong Zhang   }
14923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1493814e85d6SHong Zhang }
1494814e85d6SHong Zhang 
1495814e85d6SHong Zhang /*@
1496814e85d6SHong Zhang   TSAdjointStep - Steps one time step backward in the adjoint run
1497814e85d6SHong Zhang 
1498c3339decSBarry Smith   Collective
1499814e85d6SHong Zhang 
1500814e85d6SHong Zhang   Input Parameter:
1501bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()`
1502814e85d6SHong Zhang 
1503814e85d6SHong Zhang   Level: intermediate
1504814e85d6SHong Zhang 
15051cc06b55SBarry Smith .seealso: [](ch_ts), `TSAdjointSetUp()`, `TSAdjointSolve()`
1506814e85d6SHong Zhang @*/
TSAdjointStep(TS ts)1507d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointStep(TS ts)
1508d71ae5a4SJacob Faibussowitsch {
1509814e85d6SHong Zhang   DM dm;
1510814e85d6SHong Zhang 
1511814e85d6SHong Zhang   PetscFunctionBegin;
1512814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
15139566063dSJacob Faibussowitsch   PetscCall(TSGetDM(ts, &dm));
15149566063dSJacob Faibussowitsch   PetscCall(TSAdjointSetUp(ts));
15157b0e2f17SHong Zhang   ts->steps--; /* must decrease the step index before the adjoint step is taken. */
1516814e85d6SHong Zhang 
1517814e85d6SHong Zhang   ts->reason     = TS_CONVERGED_ITERATING;
1518814e85d6SHong Zhang   ts->ptime_prev = ts->ptime;
15199566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(TS_AdjointStep, ts, 0, 0, 0));
1520dbbe0bcdSBarry Smith   PetscUseTypeMethod(ts, adjointstep);
15219566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(TS_AdjointStep, ts, 0, 0, 0));
15227b0e2f17SHong Zhang   ts->adjoint_steps++;
1523814e85d6SHong Zhang 
1524814e85d6SHong Zhang   if (ts->reason < 0) {
15253c633725SBarry Smith     PetscCheck(!ts->errorifstepfailed, PetscObjectComm((PetscObject)ts), PETSC_ERR_NOT_CONVERGED, "TSAdjointStep has failed due to %s", TSConvergedReasons[ts->reason]);
1526814e85d6SHong Zhang   } else if (!ts->reason) {
1527814e85d6SHong Zhang     if (ts->adjoint_steps >= ts->adjoint_max_steps) ts->reason = TS_CONVERGED_ITS;
1528814e85d6SHong Zhang   }
15293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1530814e85d6SHong Zhang }
1531814e85d6SHong Zhang 
1532814e85d6SHong Zhang /*@
1533814e85d6SHong Zhang   TSAdjointSolve - Solves the discrete ajoint problem for an ODE/DAE
1534814e85d6SHong Zhang 
1535c3339decSBarry Smith   Collective
1536bcf0153eSBarry Smith   `
1537b43aa488SJacob Faibussowitsch 
1538814e85d6SHong Zhang   Input Parameter:
1539bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()`
1540814e85d6SHong Zhang 
1541bcf0153eSBarry Smith   Options Database Key:
1542814e85d6SHong Zhang . -ts_adjoint_view_solution <viewerinfo> - views the first gradient with respect to the initial values
1543814e85d6SHong Zhang 
1544814e85d6SHong Zhang   Level: intermediate
1545814e85d6SHong Zhang 
1546814e85d6SHong Zhang   Notes:
1547bcf0153eSBarry Smith   This must be called after a call to `TSSolve()` that solves the forward problem
1548814e85d6SHong Zhang 
1549bcf0153eSBarry Smith   By default this will integrate back to the initial time, one can use `TSAdjointSetSteps()` to step back to a later time
1550814e85d6SHong Zhang 
155142747ad1SJacob Faibussowitsch .seealso: [](ch_ts), `TSCreate()`, `TSSetCostGradients()`, `TSSetSolution()`, `TSAdjointStep()`
1552814e85d6SHong Zhang @*/
TSAdjointSolve(TS ts)1553d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointSolve(TS ts)
1554d71ae5a4SJacob Faibussowitsch {
1555f1d62c27SHong Zhang   static PetscBool cite = PETSC_FALSE;
15567f59fb53SHong Zhang #if defined(TSADJOINT_STAGE)
15577f59fb53SHong Zhang   PetscLogStage adjoint_stage;
15587f59fb53SHong Zhang #endif
1559814e85d6SHong Zhang 
1560814e85d6SHong Zhang   PetscFunctionBegin;
1561814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
1562421b783aSHong Zhang   PetscCall(PetscCitationsRegister("@article{Zhang2022tsadjoint,\n"
1563421b783aSHong Zhang                                    "  title         = {{PETSc TSAdjoint: A Discrete Adjoint ODE Solver for First-Order and Second-Order Sensitivity Analysis}},\n"
1564f1d62c27SHong Zhang                                    "  author        = {Zhang, Hong and Constantinescu, Emil M.  and Smith, Barry F.},\n"
1565421b783aSHong Zhang                                    "  journal       = {SIAM Journal on Scientific Computing},\n"
1566421b783aSHong Zhang                                    "  volume        = {44},\n"
1567421b783aSHong Zhang                                    "  number        = {1},\n"
1568421b783aSHong Zhang                                    "  pages         = {C1-C24},\n"
1569421b783aSHong Zhang                                    "  doi           = {10.1137/21M140078X},\n"
15709371c9d4SSatish Balay                                    "  year          = {2022}\n}\n",
15719371c9d4SSatish Balay                                    &cite));
15727f59fb53SHong Zhang #if defined(TSADJOINT_STAGE)
15739566063dSJacob Faibussowitsch   PetscCall(PetscLogStageRegister("TSAdjoint", &adjoint_stage));
15749566063dSJacob Faibussowitsch   PetscCall(PetscLogStagePush(adjoint_stage));
15757f59fb53SHong Zhang #endif
15769566063dSJacob Faibussowitsch   PetscCall(TSAdjointSetUp(ts));
1577814e85d6SHong Zhang 
1578814e85d6SHong Zhang   /* reset time step and iteration counters */
1579814e85d6SHong Zhang   ts->adjoint_steps     = 0;
1580814e85d6SHong Zhang   ts->ksp_its           = 0;
1581814e85d6SHong Zhang   ts->snes_its          = 0;
1582814e85d6SHong Zhang   ts->num_snes_failures = 0;
1583814e85d6SHong Zhang   ts->reject            = 0;
1584814e85d6SHong Zhang   ts->reason            = TS_CONVERGED_ITERATING;
1585814e85d6SHong Zhang 
1586814e85d6SHong Zhang   if (!ts->adjoint_max_steps) ts->adjoint_max_steps = ts->steps;
1587814e85d6SHong Zhang   if (ts->adjoint_steps >= ts->adjoint_max_steps) ts->reason = TS_CONVERGED_ITS;
1588814e85d6SHong Zhang 
1589814e85d6SHong Zhang   while (!ts->reason) {
15909566063dSJacob Faibussowitsch     PetscCall(TSTrajectoryGet(ts->trajectory, ts, ts->steps, &ts->ptime));
15919566063dSJacob Faibussowitsch     PetscCall(TSAdjointMonitor(ts, ts->steps, ts->ptime, ts->vec_sol, ts->numcost, ts->vecs_sensi, ts->vecs_sensip));
15929566063dSJacob Faibussowitsch     PetscCall(TSAdjointEventHandler(ts));
15939566063dSJacob Faibussowitsch     PetscCall(TSAdjointStep(ts));
159448a46eb9SPierre Jolivet     if ((ts->vec_costintegral || ts->quadraturets) && !ts->costintegralfwd) PetscCall(TSAdjointCostIntegral(ts));
1595814e85d6SHong Zhang   }
1596bdbff044SHong Zhang   if (!ts->steps) {
15979566063dSJacob Faibussowitsch     PetscCall(TSTrajectoryGet(ts->trajectory, ts, ts->steps, &ts->ptime));
15989566063dSJacob Faibussowitsch     PetscCall(TSAdjointMonitor(ts, ts->steps, ts->ptime, ts->vec_sol, ts->numcost, ts->vecs_sensi, ts->vecs_sensip));
1599bdbff044SHong Zhang   }
1600814e85d6SHong Zhang   ts->solvetime = ts->ptime;
16019566063dSJacob Faibussowitsch   PetscCall(TSTrajectoryViewFromOptions(ts->trajectory, NULL, "-ts_trajectory_view"));
16029566063dSJacob Faibussowitsch   PetscCall(VecViewFromOptions(ts->vecs_sensi[0], (PetscObject)ts, "-ts_adjoint_view_solution"));
1603814e85d6SHong Zhang   ts->adjoint_max_steps = 0;
16047f59fb53SHong Zhang #if defined(TSADJOINT_STAGE)
16059566063dSJacob Faibussowitsch   PetscCall(PetscLogStagePop());
16067f59fb53SHong Zhang #endif
16073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1608814e85d6SHong Zhang }
1609814e85d6SHong Zhang 
1610814e85d6SHong Zhang /*@C
1611bcf0153eSBarry Smith   TSAdjointMonitor - Runs all user-provided adjoint monitor routines set using `TSAdjointMonitorSet()`
1612814e85d6SHong Zhang 
1613c3339decSBarry Smith   Collective
1614814e85d6SHong Zhang 
1615814e85d6SHong Zhang   Input Parameters:
1616bcf0153eSBarry Smith + ts      - time stepping context obtained from `TSCreate()`
1617814e85d6SHong Zhang . step    - step number that has just completed
1618814e85d6SHong Zhang . ptime   - model time of the state
1619814e85d6SHong Zhang . u       - state at the current model time
1620814e85d6SHong Zhang . numcost - number of cost functions (dimension of lambda  or mu)
1621814e85d6SHong Zhang . lambda  - vectors containing the gradients of the cost functions with respect to the ODE/DAE solution variables
1622814e85d6SHong Zhang - mu      - vectors containing the gradients of the cost functions with respect to the problem parameters
1623814e85d6SHong Zhang 
1624814e85d6SHong Zhang   Level: developer
1625814e85d6SHong Zhang 
1626bcf0153eSBarry Smith   Note:
1627bcf0153eSBarry Smith   `TSAdjointMonitor()` is typically used automatically within the time stepping implementations.
1628bcf0153eSBarry Smith   Users would almost never call this routine directly.
1629bcf0153eSBarry Smith 
1630bcf0153eSBarry Smith .seealso: `TSAdjointMonitorSet()`, `TSAdjointSolve()`
1631814e85d6SHong Zhang @*/
TSAdjointMonitor(TS ts,PetscInt step,PetscReal ptime,Vec u,PetscInt numcost,Vec lambda[],Vec mu[])16320fc7ecceSBarry Smith PetscErrorCode TSAdjointMonitor(TS ts, PetscInt step, PetscReal ptime, Vec u, PetscInt numcost, Vec lambda[], Vec mu[])
1633d71ae5a4SJacob Faibussowitsch {
1634814e85d6SHong Zhang   PetscInt i, n = ts->numberadjointmonitors;
1635814e85d6SHong Zhang 
1636814e85d6SHong Zhang   PetscFunctionBegin;
1637814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
1638814e85d6SHong Zhang   PetscValidHeaderSpecific(u, VEC_CLASSID, 4);
16399566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(u));
164048a46eb9SPierre Jolivet   for (i = 0; i < n; i++) PetscCall((*ts->adjointmonitor[i])(ts, step, ptime, u, numcost, lambda, mu, ts->adjointmonitorcontext[i]));
16419566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(u));
16423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1643814e85d6SHong Zhang }
1644814e85d6SHong Zhang 
1645814e85d6SHong Zhang /*@
1646814e85d6SHong Zhang   TSAdjointCostIntegral - Evaluate the cost integral in the adjoint run.
1647814e85d6SHong Zhang 
1648c3339decSBarry Smith   Collective
1649814e85d6SHong Zhang 
16504165533cSJose E. Roman   Input Parameter:
1651814e85d6SHong Zhang . ts - time stepping context
1652814e85d6SHong Zhang 
1653814e85d6SHong Zhang   Level: advanced
1654814e85d6SHong Zhang 
1655814e85d6SHong Zhang   Notes:
1656bcf0153eSBarry Smith   This function cannot be called until `TSAdjointStep()` has been completed.
1657814e85d6SHong Zhang 
16581cc06b55SBarry Smith .seealso: [](ch_ts), `TSAdjointSolve()`, `TSAdjointStep()`
1659814e85d6SHong Zhang  @*/
TSAdjointCostIntegral(TS ts)1660d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointCostIntegral(TS ts)
1661d71ae5a4SJacob Faibussowitsch {
1662362febeeSStefano Zampini   PetscFunctionBegin;
1663814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
1664dbbe0bcdSBarry Smith   PetscUseTypeMethod(ts, adjointintegral);
16653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1666814e85d6SHong Zhang }
1667814e85d6SHong Zhang 
1668814e85d6SHong Zhang /* ------------------ Forward (tangent linear) sensitivity  ------------------*/
1669814e85d6SHong Zhang 
1670814e85d6SHong Zhang /*@
1671814e85d6SHong Zhang   TSForwardSetUp - Sets up the internal data structures for the later use
1672814e85d6SHong Zhang   of forward sensitivity analysis
1673814e85d6SHong Zhang 
1674c3339decSBarry Smith   Collective
1675814e85d6SHong Zhang 
1676814e85d6SHong Zhang   Input Parameter:
1677bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()`
1678814e85d6SHong Zhang 
1679814e85d6SHong Zhang   Level: advanced
1680814e85d6SHong Zhang 
16811cc06b55SBarry Smith .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSDestroy()`, `TSSetUp()`
1682814e85d6SHong Zhang @*/
TSForwardSetUp(TS ts)1683d71ae5a4SJacob Faibussowitsch PetscErrorCode TSForwardSetUp(TS ts)
1684d71ae5a4SJacob Faibussowitsch {
1685814e85d6SHong Zhang   PetscFunctionBegin;
1686814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
16873ba16761SJacob Faibussowitsch   if (ts->forwardsetupcalled) PetscFunctionReturn(PETSC_SUCCESS);
1688dbbe0bcdSBarry Smith   PetscTryTypeMethod(ts, forwardsetup);
16899566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(ts->vec_sol, &ts->vec_sensip_col));
1690814e85d6SHong Zhang   ts->forwardsetupcalled = PETSC_TRUE;
16913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1692814e85d6SHong Zhang }
1693814e85d6SHong Zhang 
1694814e85d6SHong Zhang /*@
16957adebddeSHong Zhang   TSForwardReset - Reset the internal data structures used by forward sensitivity analysis
16967adebddeSHong Zhang 
1697c3339decSBarry Smith   Collective
16987adebddeSHong Zhang 
16997adebddeSHong Zhang   Input Parameter:
1700bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()`
17017adebddeSHong Zhang 
17027adebddeSHong Zhang   Level: advanced
17037adebddeSHong Zhang 
17041cc06b55SBarry Smith .seealso: [](ch_ts), `TSCreate()`, `TSDestroy()`, `TSForwardSetUp()`
17057adebddeSHong Zhang @*/
TSForwardReset(TS ts)1706d71ae5a4SJacob Faibussowitsch PetscErrorCode TSForwardReset(TS ts)
1707d71ae5a4SJacob Faibussowitsch {
17087207e0fdSHong Zhang   TS quadts = ts->quadraturets;
17097adebddeSHong Zhang 
17107adebddeSHong Zhang   PetscFunctionBegin;
17117adebddeSHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
1712dbbe0bcdSBarry Smith   PetscTryTypeMethod(ts, forwardreset);
17139566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&ts->mat_sensip));
171448a46eb9SPierre Jolivet   if (quadts) PetscCall(MatDestroy(&quadts->mat_sensip));
17159566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&ts->vec_sensip_col));
17167adebddeSHong Zhang   ts->forward_solve      = PETSC_FALSE;
17177adebddeSHong Zhang   ts->forwardsetupcalled = PETSC_FALSE;
17183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17197adebddeSHong Zhang }
17207adebddeSHong Zhang 
17217adebddeSHong Zhang /*@
1722814e85d6SHong Zhang   TSForwardSetIntegralGradients - Set the vectors holding forward sensitivities of the integral term.
1723814e85d6SHong Zhang 
1724d8d19677SJose E. Roman   Input Parameters:
1725bcf0153eSBarry Smith + ts        - the `TS` context obtained from `TSCreate()`
1726814e85d6SHong Zhang . numfwdint - number of integrals
172767b8a455SSatish Balay - vp        - the vectors containing the gradients for each integral w.r.t. parameters
1728814e85d6SHong Zhang 
17297207e0fdSHong Zhang   Level: deprecated
1730814e85d6SHong Zhang 
173142747ad1SJacob Faibussowitsch .seealso: [](ch_ts), `TSForwardGetSensitivities()`, `TSForwardGetIntegralGradients()`, `TSForwardStep()`
1732814e85d6SHong Zhang @*/
TSForwardSetIntegralGradients(TS ts,PetscInt numfwdint,Vec vp[])17330fc7ecceSBarry Smith PetscErrorCode TSForwardSetIntegralGradients(TS ts, PetscInt numfwdint, Vec vp[])
1734d71ae5a4SJacob Faibussowitsch {
1735814e85d6SHong Zhang   PetscFunctionBegin;
1736814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
17373c633725SBarry 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()");
1738814e85d6SHong Zhang   if (!ts->numcost) ts->numcost = numfwdint;
1739814e85d6SHong Zhang 
1740814e85d6SHong Zhang   ts->vecs_integral_sensip = vp;
17413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1742814e85d6SHong Zhang }
1743814e85d6SHong Zhang 
1744814e85d6SHong Zhang /*@
1745814e85d6SHong Zhang   TSForwardGetIntegralGradients - Returns the forward sensitivities of the integral term.
1746814e85d6SHong Zhang 
1747814e85d6SHong Zhang   Input Parameter:
1748bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()`
1749814e85d6SHong Zhang 
175014d0ab18SJacob Faibussowitsch   Output Parameters:
175114d0ab18SJacob Faibussowitsch + numfwdint - number of integrals
175214d0ab18SJacob Faibussowitsch - vp        - the vectors containing the gradients for each integral w.r.t. parameters
1753814e85d6SHong Zhang 
17547207e0fdSHong Zhang   Level: deprecated
1755814e85d6SHong Zhang 
175642747ad1SJacob Faibussowitsch .seealso: [](ch_ts), `TSForwardSetSensitivities()`, `TSForwardSetIntegralGradients()`, `TSForwardStep()`
1757814e85d6SHong Zhang @*/
TSForwardGetIntegralGradients(TS ts,PetscInt * numfwdint,Vec * vp[])17580fc7ecceSBarry Smith PetscErrorCode TSForwardGetIntegralGradients(TS ts, PetscInt *numfwdint, Vec *vp[])
1759d71ae5a4SJacob Faibussowitsch {
1760814e85d6SHong Zhang   PetscFunctionBegin;
1761814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
17624f572ea9SToby Isaac   PetscAssertPointer(vp, 3);
1763814e85d6SHong Zhang   if (numfwdint) *numfwdint = ts->numcost;
1764814e85d6SHong Zhang   if (vp) *vp = ts->vecs_integral_sensip;
17653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1766814e85d6SHong Zhang }
1767814e85d6SHong Zhang 
1768814e85d6SHong Zhang /*@
1769814e85d6SHong Zhang   TSForwardStep - Compute the forward sensitivity for one time step.
1770814e85d6SHong Zhang 
1771c3339decSBarry Smith   Collective
1772814e85d6SHong Zhang 
17734165533cSJose E. Roman   Input Parameter:
1774814e85d6SHong Zhang . ts - time stepping context
1775814e85d6SHong Zhang 
1776814e85d6SHong Zhang   Level: advanced
1777814e85d6SHong Zhang 
1778814e85d6SHong Zhang   Notes:
1779bcf0153eSBarry Smith   This function cannot be called until `TSStep()` has been completed.
1780814e85d6SHong Zhang 
17811cc06b55SBarry Smith .seealso: [](ch_ts), `TSForwardSetSensitivities()`, `TSForwardGetSensitivities()`, `TSForwardSetIntegralGradients()`, `TSForwardGetIntegralGradients()`, `TSForwardSetUp()`
1782814e85d6SHong Zhang @*/
TSForwardStep(TS ts)1783d71ae5a4SJacob Faibussowitsch PetscErrorCode TSForwardStep(TS ts)
1784d71ae5a4SJacob Faibussowitsch {
1785362febeeSStefano Zampini   PetscFunctionBegin;
1786814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
17879566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(TS_ForwardStep, ts, 0, 0, 0));
1788dbbe0bcdSBarry Smith   PetscUseTypeMethod(ts, forwardstep);
17899566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(TS_ForwardStep, ts, 0, 0, 0));
17903c633725SBarry Smith   PetscCheck(ts->reason >= 0 || !ts->errorifstepfailed, PetscObjectComm((PetscObject)ts), PETSC_ERR_NOT_CONVERGED, "TSFowardStep has failed due to %s", TSConvergedReasons[ts->reason]);
17913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1792814e85d6SHong Zhang }
1793814e85d6SHong Zhang 
1794814e85d6SHong Zhang /*@
1795814e85d6SHong Zhang   TSForwardSetSensitivities - Sets the initial value of the trajectory sensitivities of solution  w.r.t. the problem parameters and initial values.
1796814e85d6SHong Zhang 
1797c3339decSBarry Smith   Logically Collective
1798814e85d6SHong Zhang 
1799814e85d6SHong Zhang   Input Parameters:
1800bcf0153eSBarry Smith + ts   - the `TS` context obtained from `TSCreate()`
1801814e85d6SHong Zhang . nump - number of parameters
1802814e85d6SHong Zhang - Smat - sensitivities with respect to the parameters, the number of entries in these vectors is the same as the number of parameters
1803814e85d6SHong Zhang 
1804814e85d6SHong Zhang   Level: beginner
1805814e85d6SHong Zhang 
1806814e85d6SHong Zhang   Notes:
180709cb0f53SBarry Smith   Use `PETSC_DETERMINE` to use the number of columns of `Smat` for `nump`
180809cb0f53SBarry Smith 
1809814e85d6SHong Zhang   Forward sensitivity is also called 'trajectory sensitivity' in some fields such as power systems.
1810bcf0153eSBarry Smith   This function turns on a flag to trigger `TSSolve()` to compute forward sensitivities automatically.
1811bcf0153eSBarry Smith   You must call this function before `TSSolve()`.
1812814e85d6SHong Zhang   The entries in the sensitivity matrix must be correctly initialized with the values S = dy/dp|startingtime.
1813814e85d6SHong Zhang 
18141cc06b55SBarry Smith .seealso: [](ch_ts), `TSForwardGetSensitivities()`, `TSForwardSetIntegralGradients()`, `TSForwardGetIntegralGradients()`, `TSForwardStep()`
1815814e85d6SHong Zhang @*/
TSForwardSetSensitivities(TS ts,PetscInt nump,Mat Smat)1816d71ae5a4SJacob Faibussowitsch PetscErrorCode TSForwardSetSensitivities(TS ts, PetscInt nump, Mat Smat)
1817d71ae5a4SJacob Faibussowitsch {
1818814e85d6SHong Zhang   PetscFunctionBegin;
1819814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
1820814e85d6SHong Zhang   PetscValidHeaderSpecific(Smat, MAT_CLASSID, 3);
1821814e85d6SHong Zhang   ts->forward_solve = PETSC_TRUE;
1822ac530a7eSPierre Jolivet   if (nump == PETSC_DEFAULT || nump == PETSC_DETERMINE) PetscCall(MatGetSize(Smat, NULL, &ts->num_parameters));
1823ac530a7eSPierre Jolivet   else ts->num_parameters = nump;
18249566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)Smat));
18259566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&ts->mat_sensip));
1826814e85d6SHong Zhang   ts->mat_sensip = Smat;
18273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1828814e85d6SHong Zhang }
1829814e85d6SHong Zhang 
1830814e85d6SHong Zhang /*@
1831814e85d6SHong Zhang   TSForwardGetSensitivities - Returns the trajectory sensitivities
1832814e85d6SHong Zhang 
1833bcf0153eSBarry Smith   Not Collective, but Smat returned is parallel if ts is parallel
1834814e85d6SHong Zhang 
1835d8d19677SJose E. Roman   Output Parameters:
1836bcf0153eSBarry Smith + ts   - the `TS` context obtained from `TSCreate()`
1837814e85d6SHong Zhang . nump - number of parameters
1838814e85d6SHong Zhang - Smat - sensitivities with respect to the parameters, the number of entries in these vectors is the same as the number of parameters
1839814e85d6SHong Zhang 
1840814e85d6SHong Zhang   Level: intermediate
1841814e85d6SHong Zhang 
18421cc06b55SBarry Smith .seealso: [](ch_ts), `TSForwardSetSensitivities()`, `TSForwardSetIntegralGradients()`, `TSForwardGetIntegralGradients()`, `TSForwardStep()`
1843814e85d6SHong Zhang @*/
TSForwardGetSensitivities(TS ts,PetscInt * nump,Mat * Smat)1844d71ae5a4SJacob Faibussowitsch PetscErrorCode TSForwardGetSensitivities(TS ts, PetscInt *nump, Mat *Smat)
1845d71ae5a4SJacob Faibussowitsch {
1846814e85d6SHong Zhang   PetscFunctionBegin;
1847814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
1848814e85d6SHong Zhang   if (nump) *nump = ts->num_parameters;
1849814e85d6SHong Zhang   if (Smat) *Smat = ts->mat_sensip;
18503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1851814e85d6SHong Zhang }
1852814e85d6SHong Zhang 
1853814e85d6SHong Zhang /*@
1854814e85d6SHong Zhang   TSForwardCostIntegral - Evaluate the cost integral in the forward run.
1855814e85d6SHong Zhang 
1856c3339decSBarry Smith   Collective
1857814e85d6SHong Zhang 
18584165533cSJose E. Roman   Input Parameter:
1859814e85d6SHong Zhang . ts - time stepping context
1860814e85d6SHong Zhang 
1861814e85d6SHong Zhang   Level: advanced
1862814e85d6SHong Zhang 
1863bcf0153eSBarry Smith   Note:
1864bcf0153eSBarry Smith   This function cannot be called until `TSStep()` has been completed.
1865814e85d6SHong Zhang 
18661cc06b55SBarry Smith .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSAdjointCostIntegral()`
1867814e85d6SHong Zhang @*/
TSForwardCostIntegral(TS ts)1868d71ae5a4SJacob Faibussowitsch PetscErrorCode TSForwardCostIntegral(TS ts)
1869d71ae5a4SJacob Faibussowitsch {
1870362febeeSStefano Zampini   PetscFunctionBegin;
1871814e85d6SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
1872dbbe0bcdSBarry Smith   PetscUseTypeMethod(ts, forwardintegral);
18733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1874814e85d6SHong Zhang }
1875b5b4017aSHong Zhang 
1876b5b4017aSHong Zhang /*@
1877b5b4017aSHong Zhang   TSForwardSetInitialSensitivities - Set initial values for tangent linear sensitivities
1878b5b4017aSHong Zhang 
1879c3339decSBarry Smith   Collective
1880b5b4017aSHong Zhang 
1881d8d19677SJose E. Roman   Input Parameters:
1882bcf0153eSBarry Smith + ts   - the `TS` context obtained from `TSCreate()`
1883b5b4017aSHong Zhang - didp - parametric sensitivities of the initial condition
1884b5b4017aSHong Zhang 
1885b5b4017aSHong Zhang   Level: intermediate
1886b5b4017aSHong Zhang 
1887bcf0153eSBarry Smith   Notes:
1888bcf0153eSBarry Smith   `TSSolve()` allows users to pass the initial solution directly to `TS`. But the tangent linear variables cannot be initialized in this way.
1889bcf0153eSBarry Smith   This function is used to set initial values for tangent linear variables.
1890b5b4017aSHong Zhang 
18911cc06b55SBarry Smith .seealso: [](ch_ts), `TS`, `TSForwardSetSensitivities()`
1892b5b4017aSHong Zhang @*/
TSForwardSetInitialSensitivities(TS ts,Mat didp)1893d71ae5a4SJacob Faibussowitsch PetscErrorCode TSForwardSetInitialSensitivities(TS ts, Mat didp)
1894d71ae5a4SJacob Faibussowitsch {
1895362febeeSStefano Zampini   PetscFunctionBegin;
1896b5b4017aSHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
1897b5b4017aSHong Zhang   PetscValidHeaderSpecific(didp, MAT_CLASSID, 2);
189809cb0f53SBarry Smith   if (!ts->mat_sensip) PetscCall(TSForwardSetSensitivities(ts, PETSC_DETERMINE, didp));
18993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1900b5b4017aSHong Zhang }
19016affb6f8SHong Zhang 
19026affb6f8SHong Zhang /*@
19036affb6f8SHong Zhang   TSForwardGetStages - Get the number of stages and the tangent linear sensitivities at the intermediate stages
19046affb6f8SHong Zhang 
19056affb6f8SHong Zhang   Input Parameter:
1906bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()`
19076affb6f8SHong Zhang 
19086affb6f8SHong Zhang   Output Parameters:
1909cd4cee2dSHong Zhang + ns - number of stages
19106affb6f8SHong Zhang - S  - tangent linear sensitivities at the intermediate stages
19116affb6f8SHong Zhang 
19126affb6f8SHong Zhang   Level: advanced
19136affb6f8SHong Zhang 
1914bcf0153eSBarry Smith .seealso: `TS`
19156affb6f8SHong Zhang @*/
TSForwardGetStages(TS ts,PetscInt * ns,Mat ** S)1916d71ae5a4SJacob Faibussowitsch PetscErrorCode TSForwardGetStages(TS ts, PetscInt *ns, Mat **S)
1917d71ae5a4SJacob Faibussowitsch {
19186affb6f8SHong Zhang   PetscFunctionBegin;
19196affb6f8SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
19206affb6f8SHong Zhang 
19216affb6f8SHong Zhang   if (!ts->ops->getstages) *S = NULL;
1922dbbe0bcdSBarry Smith   else PetscUseTypeMethod(ts, forwardgetstages, ns, S);
19233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19246affb6f8SHong Zhang }
1925cd4cee2dSHong Zhang 
1926cd4cee2dSHong Zhang /*@
1927bcf0153eSBarry Smith   TSCreateQuadratureTS - Create a sub-`TS` that evaluates integrals over time
1928cd4cee2dSHong Zhang 
1929d8d19677SJose E. Roman   Input Parameters:
1930bcf0153eSBarry Smith + ts  - the `TS` context obtained from `TSCreate()`
1931cd4cee2dSHong Zhang - fwd - flag indicating whether to evaluate cost integral in the forward run or the adjoint run
1932cd4cee2dSHong Zhang 
19332fe279fdSBarry Smith   Output Parameter:
1934bcf0153eSBarry Smith . quadts - the child `TS` context
1935cd4cee2dSHong Zhang 
1936cd4cee2dSHong Zhang   Level: intermediate
1937cd4cee2dSHong Zhang 
19381cc06b55SBarry Smith .seealso: [](ch_ts), `TSGetQuadratureTS()`
1939cd4cee2dSHong Zhang @*/
TSCreateQuadratureTS(TS ts,PetscBool fwd,TS * quadts)1940d71ae5a4SJacob Faibussowitsch PetscErrorCode TSCreateQuadratureTS(TS ts, PetscBool fwd, TS *quadts)
1941d71ae5a4SJacob Faibussowitsch {
1942cd4cee2dSHong Zhang   char prefix[128];
1943cd4cee2dSHong Zhang 
1944cd4cee2dSHong Zhang   PetscFunctionBegin;
1945cd4cee2dSHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
19464f572ea9SToby Isaac   PetscAssertPointer(quadts, 3);
19479566063dSJacob Faibussowitsch   PetscCall(TSDestroy(&ts->quadraturets));
19489566063dSJacob Faibussowitsch   PetscCall(TSCreate(PetscObjectComm((PetscObject)ts), &ts->quadraturets));
19499566063dSJacob Faibussowitsch   PetscCall(PetscObjectIncrementTabLevel((PetscObject)ts->quadraturets, (PetscObject)ts, 1));
19509566063dSJacob Faibussowitsch   PetscCall(PetscSNPrintf(prefix, sizeof(prefix), "%squad_", ((PetscObject)ts)->prefix ? ((PetscObject)ts)->prefix : ""));
19519566063dSJacob Faibussowitsch   PetscCall(TSSetOptionsPrefix(ts->quadraturets, prefix));
1952cd4cee2dSHong Zhang   *quadts = ts->quadraturets;
1953cd4cee2dSHong Zhang 
1954cd4cee2dSHong Zhang   if (ts->numcost) {
19559566063dSJacob Faibussowitsch     PetscCall(VecCreateSeq(PETSC_COMM_SELF, ts->numcost, &(*quadts)->vec_sol));
1956cd4cee2dSHong Zhang   } else {
19579566063dSJacob Faibussowitsch     PetscCall(VecCreateSeq(PETSC_COMM_SELF, 1, &(*quadts)->vec_sol));
1958cd4cee2dSHong Zhang   }
1959cd4cee2dSHong Zhang   ts->costintegralfwd = fwd;
19603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1961cd4cee2dSHong Zhang }
1962cd4cee2dSHong Zhang 
1963cd4cee2dSHong Zhang /*@
1964bcf0153eSBarry Smith   TSGetQuadratureTS - Return the sub-`TS` that evaluates integrals over time
1965cd4cee2dSHong Zhang 
1966cd4cee2dSHong Zhang   Input Parameter:
1967bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()`
1968cd4cee2dSHong Zhang 
1969cd4cee2dSHong Zhang   Output Parameters:
1970cd4cee2dSHong Zhang + fwd    - flag indicating whether to evaluate cost integral in the forward run or the adjoint run
1971bcf0153eSBarry Smith - quadts - the child `TS` context
1972cd4cee2dSHong Zhang 
1973cd4cee2dSHong Zhang   Level: intermediate
1974cd4cee2dSHong Zhang 
19751cc06b55SBarry Smith .seealso: [](ch_ts), `TSCreateQuadratureTS()`
1976cd4cee2dSHong Zhang @*/
TSGetQuadratureTS(TS ts,PetscBool * fwd,TS * quadts)1977d71ae5a4SJacob Faibussowitsch PetscErrorCode TSGetQuadratureTS(TS ts, PetscBool *fwd, TS *quadts)
1978d71ae5a4SJacob Faibussowitsch {
1979cd4cee2dSHong Zhang   PetscFunctionBegin;
1980cd4cee2dSHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
1981cd4cee2dSHong Zhang   if (fwd) *fwd = ts->costintegralfwd;
1982cd4cee2dSHong Zhang   if (quadts) *quadts = ts->quadraturets;
19833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1984cd4cee2dSHong Zhang }
1985ba0675f6SHong Zhang 
1986ba0675f6SHong Zhang /*@
1987bcf0153eSBarry Smith   TSComputeSNESJacobian - Compute the Jacobian needed for the `SNESSolve()` in `TS`
1988bcf0153eSBarry Smith 
1989c3339decSBarry Smith   Collective
1990ba0675f6SHong Zhang 
1991ba0675f6SHong Zhang   Input Parameters:
1992bcf0153eSBarry Smith + ts - the `TS` context obtained from `TSCreate()`
1993ba0675f6SHong Zhang - x  - state vector
1994ba0675f6SHong Zhang 
1995ba0675f6SHong Zhang   Output Parameters:
1996ba0675f6SHong Zhang + J    - Jacobian matrix
19977addb90fSBarry Smith - Jpre - matrix used to compute the preconditioner for `J` (may be same as `J`)
1998ba0675f6SHong Zhang 
1999ba0675f6SHong Zhang   Level: developer
2000ba0675f6SHong Zhang 
2001bcf0153eSBarry Smith   Note:
2002bcf0153eSBarry Smith   Uses finite differencing when `TS` Jacobian is not available.
2003bcf0153eSBarry Smith 
2004b43aa488SJacob Faibussowitsch .seealso: `SNES`, `TS`, `SNESSetJacobian()`, `TSSetRHSJacobian()`, `TSSetIJacobian()`
2005ba0675f6SHong Zhang @*/
TSComputeSNESJacobian(TS ts,Vec x,Mat J,Mat Jpre)2006d71ae5a4SJacob Faibussowitsch PetscErrorCode TSComputeSNESJacobian(TS ts, Vec x, Mat J, Mat Jpre)
2007d71ae5a4SJacob Faibussowitsch {
2008ba0675f6SHong Zhang   SNES snes                                          = ts->snes;
2009ba0675f6SHong Zhang   PetscErrorCode (*jac)(SNES, Vec, Mat, Mat, void *) = NULL;
2010ba0675f6SHong Zhang 
2011ba0675f6SHong Zhang   PetscFunctionBegin;
2012ba0675f6SHong Zhang   /*
2013ba0675f6SHong Zhang     Unlike implicit methods, explicit methods do not have SNESMatFDColoring in the snes object
2014ba0675f6SHong Zhang     because SNESSolve() has not been called yet; so querying SNESMatFDColoring does not work for
2015da81f932SPierre Jolivet     explicit methods. Instead, we check the Jacobian compute function directly to determine if FD
2016ba0675f6SHong Zhang     coloring is used.
2017ba0675f6SHong Zhang   */
20189566063dSJacob Faibussowitsch   PetscCall(SNESGetJacobian(snes, NULL, NULL, &jac, NULL));
2019ba0675f6SHong Zhang   if (jac == SNESComputeJacobianDefaultColor) {
2020ba0675f6SHong Zhang     Vec f;
20219566063dSJacob Faibussowitsch     PetscCall(SNESSetSolution(snes, x));
20229566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, &f, NULL, NULL));
2023ba0675f6SHong Zhang     /* Force MatFDColoringApply to evaluate the SNES residual function for the base vector */
20249566063dSJacob Faibussowitsch     PetscCall(SNESComputeFunction(snes, x, f));
2025ba0675f6SHong Zhang   }
20269566063dSJacob Faibussowitsch   PetscCall(SNESComputeJacobian(snes, x, J, Jpre));
20273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2028ba0675f6SHong Zhang }
2029