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 @*/ 288434afd1SBarry Smith PetscErrorCode TSSetRHSJacobianP(TS ts, Mat Amat, TSRHSJacobianPFn *func, void *ctx) 29d71ae5a4SJacob Faibussowitsch { 30814e85d6SHong Zhang PetscFunctionBegin; 31814e85d6SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 32814e85d6SHong Zhang PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2); 33814e85d6SHong Zhang 34814e85d6SHong Zhang ts->rhsjacobianp = func; 35814e85d6SHong Zhang ts->rhsjacobianpctx = ctx; 36814e85d6SHong Zhang if (Amat) { 379566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)Amat)); 389566063dSJacob Faibussowitsch PetscCall(MatDestroy(&ts->Jacprhs)); 3933f72c5dSHong Zhang ts->Jacprhs = Amat; 40814e85d6SHong Zhang } 413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 42814e85d6SHong Zhang } 43814e85d6SHong Zhang 44814e85d6SHong Zhang /*@C 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 @*/ 648434afd1SBarry Smith PetscErrorCode TSGetRHSJacobianP(TS ts, Mat *Amat, TSRHSJacobianPFn **func, void **ctx) 65d71ae5a4SJacob Faibussowitsch { 66cd4cee2dSHong Zhang PetscFunctionBegin; 67cd4cee2dSHong Zhang if (func) *func = ts->rhsjacobianp; 68cd4cee2dSHong Zhang if (ctx) *ctx = ts->rhsjacobianpctx; 69cd4cee2dSHong Zhang if (Amat) *Amat = ts->Jacprhs; 703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 71cd4cee2dSHong Zhang } 72cd4cee2dSHong Zhang 73cd4cee2dSHong Zhang /*@C 74814e85d6SHong Zhang TSComputeRHSJacobianP - Runs the user-defined JacobianP function. 75814e85d6SHong Zhang 76c3339decSBarry Smith Collective 77814e85d6SHong Zhang 78814e85d6SHong Zhang Input Parameters: 792fe279fdSBarry Smith + ts - The `TS` context obtained from `TSCreate()` 802fe279fdSBarry Smith . t - the time 812fe279fdSBarry Smith - U - the solution at which to compute the Jacobian 822fe279fdSBarry Smith 832fe279fdSBarry Smith Output Parameter: 842fe279fdSBarry Smith . Amat - the computed Jacobian 85814e85d6SHong Zhang 86814e85d6SHong Zhang Level: developer 87814e85d6SHong Zhang 881cc06b55SBarry Smith .seealso: [](ch_ts), `TSSetRHSJacobianP()`, `TS` 89814e85d6SHong Zhang @*/ 90d71ae5a4SJacob Faibussowitsch PetscErrorCode TSComputeRHSJacobianP(TS ts, PetscReal t, Vec U, Mat Amat) 91d71ae5a4SJacob Faibussowitsch { 92814e85d6SHong Zhang PetscFunctionBegin; 933ba16761SJacob Faibussowitsch if (!Amat) PetscFunctionReturn(PETSC_SUCCESS); 94814e85d6SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 95c9ad9de0SHong Zhang PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 96814e85d6SHong Zhang 9780ab5e31SHong Zhang if (ts->rhsjacobianp) PetscCallBack("TS callback JacobianP for sensitivity analysis", (*ts->rhsjacobianp)(ts, t, U, Amat, ts->rhsjacobianpctx)); 9880ab5e31SHong Zhang else { 9980ab5e31SHong Zhang PetscBool assembled; 10080ab5e31SHong Zhang PetscCall(MatZeroEntries(Amat)); 10180ab5e31SHong Zhang PetscCall(MatAssembled(Amat, &assembled)); 10280ab5e31SHong Zhang if (!assembled) { 10380ab5e31SHong Zhang PetscCall(MatAssemblyBegin(Amat, MAT_FINAL_ASSEMBLY)); 10480ab5e31SHong Zhang PetscCall(MatAssemblyEnd(Amat, MAT_FINAL_ASSEMBLY)); 10580ab5e31SHong Zhang } 10680ab5e31SHong Zhang } 1073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 108814e85d6SHong Zhang } 109814e85d6SHong Zhang 110814e85d6SHong Zhang /*@C 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 @*/ 13714d0ab18SJacob Faibussowitsch PetscErrorCode TSSetIJacobianP(TS ts, Mat Amat, PetscErrorCode (*func)(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal shift, Mat A, void *ctx), void *ctx) 138d71ae5a4SJacob Faibussowitsch { 13933f72c5dSHong Zhang PetscFunctionBegin; 14033f72c5dSHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 14133f72c5dSHong Zhang PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2); 14233f72c5dSHong Zhang 14333f72c5dSHong Zhang ts->ijacobianp = func; 14433f72c5dSHong Zhang ts->ijacobianpctx = ctx; 14533f72c5dSHong Zhang if (Amat) { 1469566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)Amat)); 1479566063dSJacob Faibussowitsch PetscCall(MatDestroy(&ts->Jacp)); 14833f72c5dSHong Zhang ts->Jacp = Amat; 14933f72c5dSHong Zhang } 1503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15133f72c5dSHong Zhang } 15233f72c5dSHong Zhang 153*3beb8511SBarry Smith /*@C 154*3beb8511SBarry 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. 155*3beb8511SBarry Smith 156*3beb8511SBarry Smith Logically Collective 157*3beb8511SBarry Smith 158*3beb8511SBarry Smith Input Parameter: 159*3beb8511SBarry Smith . ts - `TS` context obtained from `TSCreate()` 160*3beb8511SBarry Smith 161*3beb8511SBarry Smith Output Parameters: 162*3beb8511SBarry Smith + Amat - JacobianP matrix 163*3beb8511SBarry Smith . func - the function that computes the JacobianP 164*3beb8511SBarry Smith - ctx - [optional] user-defined function context 165*3beb8511SBarry Smith 166*3beb8511SBarry Smith Calling sequence of `func`: 167*3beb8511SBarry Smith + ts - the `TS` context 168*3beb8511SBarry Smith . t - current timestep 169*3beb8511SBarry Smith . U - input vector (current ODE solution) 170*3beb8511SBarry Smith . Udot - time derivative of state vector 171*3beb8511SBarry Smith . shift - shift to apply, see the note in `TSSetIJacobian()` 172*3beb8511SBarry Smith . A - output matrix 173*3beb8511SBarry Smith - ctx - [optional] user-defined function context 174*3beb8511SBarry Smith 175*3beb8511SBarry Smith Level: intermediate 176*3beb8511SBarry Smith 177*3beb8511SBarry Smith Note: 178*3beb8511SBarry 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` 179*3beb8511SBarry Smith 180*3beb8511SBarry Smith .seealso: [](ch_ts), `TSSetRHSJacobianP()`, `TS`, `TSSetIJacobianP()`, `TSGetRHSJacobianP()` 181*3beb8511SBarry Smith @*/ 182*3beb8511SBarry Smith PetscErrorCode TSGetIJacobianP(TS ts, Mat *Amat, PetscErrorCode (**func)(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal shift, Mat A, void *ctx), void **ctx) 183*3beb8511SBarry Smith { 184*3beb8511SBarry Smith PetscFunctionBegin; 185*3beb8511SBarry Smith PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 186*3beb8511SBarry Smith 187*3beb8511SBarry Smith if (func) *func = ts->ijacobianp; 188*3beb8511SBarry Smith if (ctx) *ctx = ts->ijacobianpctx; 189*3beb8511SBarry Smith if (Amat) *Amat = ts->Jacp; 190*3beb8511SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 191*3beb8511SBarry Smith } 192*3beb8511SBarry 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 @*/ 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 @*/ 2958847d985SBarry Smith PetscErrorCode TSSetCostIntegrand(TS ts, PetscInt numcost, Vec costintegral, PetscErrorCode (*rf)(TS ts, PetscReal t, Vec U, Vec F, void *ctx), PetscErrorCode (*drduf)(TS ts, PetscReal t, Vec U, Vec *dRdU, void *ctx), PetscErrorCode (*drdpf)(TS ts, PetscReal t, Vec U, Vec *dRdP, void *ctx), PetscBool fwd, void *ctx) 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 46914d0ab18SJacob Faibussowitsch PetscErrorCode TSSetIHessianProduct(TS ts, Vec *ihp1, PetscErrorCode (*ihessianproductfunc1)(TS ts, PetscReal t, Vec U, Vec *Vl, Vec Vr, Vec *VHV, void *ctx), Vec *ihp2, PetscErrorCode (*ihessianproductfunc2)(TS, PetscReal, Vec, Vec *, Vec, Vec *, void *), Vec *ihp3, PetscErrorCode (*ihessianproductfunc3)(TS, PetscReal, Vec, Vec *, Vec, Vec *, void *), Vec *ihp4, PetscErrorCode (*ihessianproductfunc4)(TS, PetscReal, Vec, Vec *, Vec, Vec *, void *), void *ctx) 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 70014d0ab18SJacob Faibussowitsch PetscErrorCode TSSetRHSHessianProduct(TS ts, Vec *rhshp1, PetscErrorCode (*rhshessianproductfunc1)(TS ts, PetscReal t, Vec U, Vec *Vl, Vec Vr, Vec *VHV, void *ctx), Vec *rhshp2, PetscErrorCode (*rhshessianproductfunc2)(TS, PetscReal, Vec, Vec *, Vec, Vec *, void *), Vec *rhshp3, PetscErrorCode (*rhshessianproductfunc3)(TS, PetscReal, Vec, Vec *, Vec, Vec *, void *), Vec *rhshp4, PetscErrorCode (*rhshessianproductfunc4)(TS, PetscReal, Vec, Vec *, Vec, Vec *, void *), void *ctx) 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 877d71ae5a4SJacob Faibussowitsch 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 @*/ 906d71ae5a4SJacob Faibussowitsch 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 @*/ 942d71ae5a4SJacob Faibussowitsch 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 @*/ 972d71ae5a4SJacob Faibussowitsch 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 1164d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointSetRHSJacobian(TS ts, Mat Amat, PetscErrorCode (*func)(TS, PetscReal, Vec, Mat, void *), void *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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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)); 128549abdd8aSBarry Smith PetscCall(TSAdjointMonitorSet(ts, (PetscErrorCode (*)(TS, PetscInt, PetscReal, Vec, PetscInt, Vec *, Vec *, void *))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 @*/ 132549abdd8aSBarry Smith PetscErrorCode TSAdjointMonitorSet(TS ts, PetscErrorCode (*adjointmonitor)(TS ts, PetscInt steps, PetscReal time, Vec u, PetscInt numcost, Vec *lambda, Vec *mu, void *adjointmctx), void *adjointmctx, PetscCtxDestroyFn *adjointmdestroy) 1326d71ae5a4SJacob Faibussowitsch { 1327814e85d6SHong Zhang PetscInt i; 1328814e85d6SHong Zhang PetscBool identical; 1329814e85d6SHong Zhang 1330814e85d6SHong Zhang PetscFunctionBegin; 1331814e85d6SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1332814e85d6SHong Zhang for (i = 0; i < ts->numbermonitors; i++) { 13339566063dSJacob Faibussowitsch PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))adjointmonitor, adjointmctx, adjointmdestroy, (PetscErrorCode (*)(void))ts->adjointmonitor[i], ts->adjointmonitorcontext[i], ts->adjointmonitordestroy[i], &identical)); 13343ba16761SJacob Faibussowitsch if (identical) PetscFunctionReturn(PETSC_SUCCESS); 1335814e85d6SHong Zhang } 13363c633725SBarry Smith PetscCheck(ts->numberadjointmonitors < MAXTSMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many adjoint monitors set"); 1337814e85d6SHong Zhang ts->adjointmonitor[ts->numberadjointmonitors] = adjointmonitor; 1338814e85d6SHong Zhang ts->adjointmonitordestroy[ts->numberadjointmonitors] = adjointmdestroy; 1339835f2295SStefano Zampini ts->adjointmonitorcontext[ts->numberadjointmonitors++] = adjointmctx; 13403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1341814e85d6SHong Zhang } 1342814e85d6SHong Zhang 1343814e85d6SHong Zhang /*@C 1344814e85d6SHong Zhang TSAdjointMonitorCancel - Clears all the adjoint monitors that have been set on a time-step object. 1345814e85d6SHong Zhang 1346c3339decSBarry Smith Logically Collective 1347814e85d6SHong Zhang 13482fe279fdSBarry Smith Input Parameter: 1349bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()` 1350814e85d6SHong Zhang 1351814e85d6SHong Zhang Notes: 1352814e85d6SHong Zhang There is no way to remove a single, specific monitor. 1353814e85d6SHong Zhang 1354814e85d6SHong Zhang Level: intermediate 1355814e85d6SHong Zhang 13561cc06b55SBarry Smith .seealso: [](ch_ts), `TS`, `TSAdjointSolve()`, `TSAdjointMonitorSet()` 1357814e85d6SHong Zhang @*/ 1358d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointMonitorCancel(TS ts) 1359d71ae5a4SJacob Faibussowitsch { 1360814e85d6SHong Zhang PetscInt i; 1361814e85d6SHong Zhang 1362814e85d6SHong Zhang PetscFunctionBegin; 1363814e85d6SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1364814e85d6SHong Zhang for (i = 0; i < ts->numberadjointmonitors; i++) { 136548a46eb9SPierre Jolivet if (ts->adjointmonitordestroy[i]) PetscCall((*ts->adjointmonitordestroy[i])(&ts->adjointmonitorcontext[i])); 1366814e85d6SHong Zhang } 1367814e85d6SHong Zhang ts->numberadjointmonitors = 0; 13683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1369814e85d6SHong Zhang } 1370814e85d6SHong Zhang 1371814e85d6SHong Zhang /*@C 1372814e85d6SHong Zhang TSAdjointMonitorDefault - the default monitor of adjoint computations 1373814e85d6SHong Zhang 137414d0ab18SJacob Faibussowitsch Input Parameters: 137514d0ab18SJacob Faibussowitsch + ts - the `TS` context 137614d0ab18SJacob Faibussowitsch . step - iteration number (after the final time step the monitor routine is called with a 137714d0ab18SJacob Faibussowitsch step of -1, this is at the final time which may have been interpolated to) 137814d0ab18SJacob Faibussowitsch . time - current time 137914d0ab18SJacob Faibussowitsch . v - current iterate 138014d0ab18SJacob Faibussowitsch . numcost - number of cost functionos 138114d0ab18SJacob Faibussowitsch . lambda - sensitivities to initial conditions 138214d0ab18SJacob Faibussowitsch . mu - sensitivities to parameters 138314d0ab18SJacob Faibussowitsch - vf - the viewer and format 138414d0ab18SJacob Faibussowitsch 1385814e85d6SHong Zhang Level: intermediate 1386814e85d6SHong Zhang 13871cc06b55SBarry Smith .seealso: [](ch_ts), `TS`, `TSAdjointSolve()`, `TSAdjointMonitorSet()` 1388814e85d6SHong Zhang @*/ 138914d0ab18SJacob Faibussowitsch PetscErrorCode TSAdjointMonitorDefault(TS ts, PetscInt step, PetscReal time, Vec v, PetscInt numcost, Vec *lambda, Vec *mu, PetscViewerAndFormat *vf) 1390d71ae5a4SJacob Faibussowitsch { 1391814e85d6SHong Zhang PetscViewer viewer = vf->viewer; 1392814e85d6SHong Zhang 1393814e85d6SHong Zhang PetscFunctionBegin; 139414d0ab18SJacob Faibussowitsch (void)v; 139514d0ab18SJacob Faibussowitsch (void)numcost; 139614d0ab18SJacob Faibussowitsch (void)lambda; 139714d0ab18SJacob Faibussowitsch (void)mu; 1398064a246eSJacob Faibussowitsch PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 8); 13999566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(viewer, vf->format)); 14009566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)ts)->tablevel)); 140114d0ab18SJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " TS dt %g time %g%s", step, (double)ts->time_step, (double)time, ts->steprollback ? " (r)\n" : "\n")); 14029566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)ts)->tablevel)); 14039566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(viewer)); 14043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1405814e85d6SHong Zhang } 1406814e85d6SHong Zhang 1407814e85d6SHong Zhang /*@C 1408bcf0153eSBarry Smith TSAdjointMonitorDrawSensi - Monitors progress of the adjoint `TS` solvers by calling 1409bcf0153eSBarry Smith `VecView()` for the sensitivities to initial states at each timestep 1410814e85d6SHong Zhang 1411c3339decSBarry Smith Collective 1412814e85d6SHong Zhang 1413814e85d6SHong Zhang Input Parameters: 1414bcf0153eSBarry Smith + ts - the `TS` context 1415814e85d6SHong Zhang . step - current time-step 1416814e85d6SHong Zhang . ptime - current time 1417814e85d6SHong Zhang . u - current state 1418814e85d6SHong Zhang . numcost - number of cost functions 1419814e85d6SHong Zhang . lambda - sensitivities to initial conditions 1420814e85d6SHong Zhang . mu - sensitivities to parameters 14212fe279fdSBarry Smith - dummy - either a viewer or `NULL` 1422814e85d6SHong Zhang 1423814e85d6SHong Zhang Level: intermediate 1424814e85d6SHong Zhang 14251cc06b55SBarry Smith .seealso: [](ch_ts), `TSAdjointSolve()`, `TSAdjointMonitorSet()`, `TSAdjointMonitorDefault()`, `VecView()` 1426814e85d6SHong Zhang @*/ 1427d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointMonitorDrawSensi(TS ts, PetscInt step, PetscReal ptime, Vec u, PetscInt numcost, Vec *lambda, Vec *mu, void *dummy) 1428d71ae5a4SJacob Faibussowitsch { 1429814e85d6SHong Zhang TSMonitorDrawCtx ictx = (TSMonitorDrawCtx)dummy; 1430814e85d6SHong Zhang PetscDraw draw; 1431814e85d6SHong Zhang PetscReal xl, yl, xr, yr, h; 1432814e85d6SHong Zhang char time[32]; 1433814e85d6SHong Zhang 1434814e85d6SHong Zhang PetscFunctionBegin; 14353ba16761SJacob Faibussowitsch if (!(((ictx->howoften > 0) && (!(step % ictx->howoften))) || ((ictx->howoften == -1) && ts->reason))) PetscFunctionReturn(PETSC_SUCCESS); 1436814e85d6SHong Zhang 14379566063dSJacob Faibussowitsch PetscCall(VecView(lambda[0], ictx->viewer)); 14389566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(ictx->viewer, 0, &draw)); 1439835f2295SStefano Zampini PetscCall(PetscSNPrintf(time, 32, "Timestep %" PetscInt_FMT " Time %g", step, (double)ptime)); 14409566063dSJacob Faibussowitsch PetscCall(PetscDrawGetCoordinates(draw, &xl, &yl, &xr, &yr)); 1441814e85d6SHong Zhang h = yl + .95 * (yr - yl); 14429566063dSJacob Faibussowitsch PetscCall(PetscDrawStringCentered(draw, .5 * (xl + xr), h, PETSC_DRAW_BLACK, time)); 14439566063dSJacob Faibussowitsch PetscCall(PetscDrawFlush(draw)); 14443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1445814e85d6SHong Zhang } 1446814e85d6SHong Zhang 144714d0ab18SJacob Faibussowitsch /*@C 144814d0ab18SJacob Faibussowitsch TSAdjointSetFromOptions - Sets various `TS` adjoint parameters from options database. 1449814e85d6SHong Zhang 1450c3339decSBarry Smith Collective 1451814e85d6SHong Zhang 145214d0ab18SJacob Faibussowitsch Input Parameters: 145314d0ab18SJacob Faibussowitsch + ts - the `TS` context 145414d0ab18SJacob Faibussowitsch - PetscOptionsObject - the options context 1455814e85d6SHong Zhang 1456814e85d6SHong Zhang Options Database Keys: 145714d0ab18SJacob Faibussowitsch + -ts_adjoint_solve <yes,no> - After solving the ODE/DAE solve the adjoint problem (requires `-ts_save_trajectory`) 1458814e85d6SHong Zhang . -ts_adjoint_monitor - print information at each adjoint time step 1459814e85d6SHong Zhang - -ts_adjoint_monitor_draw_sensi - monitor the sensitivity of the first cost function wrt initial conditions (lambda[0]) graphically 1460814e85d6SHong Zhang 1461814e85d6SHong Zhang Level: developer 1462814e85d6SHong Zhang 1463bcf0153eSBarry Smith Note: 1464814e85d6SHong Zhang This is not normally called directly by users 1465814e85d6SHong Zhang 14661cc06b55SBarry Smith .seealso: [](ch_ts), `TSSetSaveTrajectory()`, `TSTrajectorySetUp()` 146714d0ab18SJacob Faibussowitsch @*/ 1468ce78bad3SBarry Smith PetscErrorCode TSAdjointSetFromOptions(TS ts, PetscOptionItems PetscOptionsObject) 1469d71ae5a4SJacob Faibussowitsch { 1470814e85d6SHong Zhang PetscBool tflg, opt; 1471814e85d6SHong Zhang 1472814e85d6SHong Zhang PetscFunctionBegin; 1473dbbe0bcdSBarry Smith PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1474d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "TS Adjoint options"); 1475814e85d6SHong Zhang tflg = ts->adjoint_solve ? PETSC_TRUE : PETSC_FALSE; 14769566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-ts_adjoint_solve", "Solve the adjoint problem immediately after solving the forward problem", "", tflg, &tflg, &opt)); 1477814e85d6SHong Zhang if (opt) { 14789566063dSJacob Faibussowitsch PetscCall(TSSetSaveTrajectory(ts)); 1479814e85d6SHong Zhang ts->adjoint_solve = tflg; 1480814e85d6SHong Zhang } 14819566063dSJacob Faibussowitsch PetscCall(TSAdjointMonitorSetFromOptions(ts, "-ts_adjoint_monitor", "Monitor adjoint timestep size", "TSAdjointMonitorDefault", TSAdjointMonitorDefault, NULL)); 14829566063dSJacob Faibussowitsch PetscCall(TSAdjointMonitorSetFromOptions(ts, "-ts_adjoint_monitor_sensi", "Monitor sensitivity in the adjoint computation", "TSAdjointMonitorSensi", TSAdjointMonitorSensi, NULL)); 1483814e85d6SHong Zhang opt = PETSC_FALSE; 14849566063dSJacob Faibussowitsch PetscCall(PetscOptionsName("-ts_adjoint_monitor_draw_sensi", "Monitor adjoint sensitivities (lambda only) graphically", "TSAdjointMonitorDrawSensi", &opt)); 1485814e85d6SHong Zhang if (opt) { 1486814e85d6SHong Zhang TSMonitorDrawCtx ctx; 1487814e85d6SHong Zhang PetscInt howoften = 1; 1488814e85d6SHong Zhang 14899566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-ts_adjoint_monitor_draw_sensi", "Monitor adjoint sensitivities (lambda only) graphically", "TSAdjointMonitorDrawSensi", howoften, &howoften, NULL)); 14909566063dSJacob Faibussowitsch PetscCall(TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, &ctx)); 149149abdd8aSBarry Smith PetscCall(TSAdjointMonitorSet(ts, TSAdjointMonitorDrawSensi, ctx, (PetscCtxDestroyFn *)TSMonitorDrawCtxDestroy)); 1492814e85d6SHong Zhang } 14933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1494814e85d6SHong Zhang } 1495814e85d6SHong Zhang 1496814e85d6SHong Zhang /*@ 1497814e85d6SHong Zhang TSAdjointStep - Steps one time step backward in the adjoint run 1498814e85d6SHong Zhang 1499c3339decSBarry Smith Collective 1500814e85d6SHong Zhang 1501814e85d6SHong Zhang Input Parameter: 1502bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()` 1503814e85d6SHong Zhang 1504814e85d6SHong Zhang Level: intermediate 1505814e85d6SHong Zhang 15061cc06b55SBarry Smith .seealso: [](ch_ts), `TSAdjointSetUp()`, `TSAdjointSolve()` 1507814e85d6SHong Zhang @*/ 1508d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointStep(TS ts) 1509d71ae5a4SJacob Faibussowitsch { 1510814e85d6SHong Zhang DM dm; 1511814e85d6SHong Zhang 1512814e85d6SHong Zhang PetscFunctionBegin; 1513814e85d6SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 15149566063dSJacob Faibussowitsch PetscCall(TSGetDM(ts, &dm)); 15159566063dSJacob Faibussowitsch PetscCall(TSAdjointSetUp(ts)); 15167b0e2f17SHong Zhang ts->steps--; /* must decrease the step index before the adjoint step is taken. */ 1517814e85d6SHong Zhang 1518814e85d6SHong Zhang ts->reason = TS_CONVERGED_ITERATING; 1519814e85d6SHong Zhang ts->ptime_prev = ts->ptime; 15209566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(TS_AdjointStep, ts, 0, 0, 0)); 1521dbbe0bcdSBarry Smith PetscUseTypeMethod(ts, adjointstep); 15229566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(TS_AdjointStep, ts, 0, 0, 0)); 15237b0e2f17SHong Zhang ts->adjoint_steps++; 1524814e85d6SHong Zhang 1525814e85d6SHong Zhang if (ts->reason < 0) { 15263c633725SBarry Smith PetscCheck(!ts->errorifstepfailed, PetscObjectComm((PetscObject)ts), PETSC_ERR_NOT_CONVERGED, "TSAdjointStep has failed due to %s", TSConvergedReasons[ts->reason]); 1527814e85d6SHong Zhang } else if (!ts->reason) { 1528814e85d6SHong Zhang if (ts->adjoint_steps >= ts->adjoint_max_steps) ts->reason = TS_CONVERGED_ITS; 1529814e85d6SHong Zhang } 15303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1531814e85d6SHong Zhang } 1532814e85d6SHong Zhang 1533814e85d6SHong Zhang /*@ 1534814e85d6SHong Zhang TSAdjointSolve - Solves the discrete ajoint problem for an ODE/DAE 1535814e85d6SHong Zhang 1536c3339decSBarry Smith Collective 1537bcf0153eSBarry Smith ` 1538b43aa488SJacob Faibussowitsch 1539814e85d6SHong Zhang Input Parameter: 1540bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()` 1541814e85d6SHong Zhang 1542bcf0153eSBarry Smith Options Database Key: 1543814e85d6SHong Zhang . -ts_adjoint_view_solution <viewerinfo> - views the first gradient with respect to the initial values 1544814e85d6SHong Zhang 1545814e85d6SHong Zhang Level: intermediate 1546814e85d6SHong Zhang 1547814e85d6SHong Zhang Notes: 1548bcf0153eSBarry Smith This must be called after a call to `TSSolve()` that solves the forward problem 1549814e85d6SHong Zhang 1550bcf0153eSBarry Smith By default this will integrate back to the initial time, one can use `TSAdjointSetSteps()` to step back to a later time 1551814e85d6SHong Zhang 155242747ad1SJacob Faibussowitsch .seealso: [](ch_ts), `TSCreate()`, `TSSetCostGradients()`, `TSSetSolution()`, `TSAdjointStep()` 1553814e85d6SHong Zhang @*/ 1554d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointSolve(TS ts) 1555d71ae5a4SJacob Faibussowitsch { 1556f1d62c27SHong Zhang static PetscBool cite = PETSC_FALSE; 15577f59fb53SHong Zhang #if defined(TSADJOINT_STAGE) 15587f59fb53SHong Zhang PetscLogStage adjoint_stage; 15597f59fb53SHong Zhang #endif 1560814e85d6SHong Zhang 1561814e85d6SHong Zhang PetscFunctionBegin; 1562814e85d6SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1563421b783aSHong Zhang PetscCall(PetscCitationsRegister("@article{Zhang2022tsadjoint,\n" 1564421b783aSHong Zhang " title = {{PETSc TSAdjoint: A Discrete Adjoint ODE Solver for First-Order and Second-Order Sensitivity Analysis}},\n" 1565f1d62c27SHong Zhang " author = {Zhang, Hong and Constantinescu, Emil M. and Smith, Barry F.},\n" 1566421b783aSHong Zhang " journal = {SIAM Journal on Scientific Computing},\n" 1567421b783aSHong Zhang " volume = {44},\n" 1568421b783aSHong Zhang " number = {1},\n" 1569421b783aSHong Zhang " pages = {C1-C24},\n" 1570421b783aSHong Zhang " doi = {10.1137/21M140078X},\n" 15719371c9d4SSatish Balay " year = {2022}\n}\n", 15729371c9d4SSatish Balay &cite)); 15737f59fb53SHong Zhang #if defined(TSADJOINT_STAGE) 15749566063dSJacob Faibussowitsch PetscCall(PetscLogStageRegister("TSAdjoint", &adjoint_stage)); 15759566063dSJacob Faibussowitsch PetscCall(PetscLogStagePush(adjoint_stage)); 15767f59fb53SHong Zhang #endif 15779566063dSJacob Faibussowitsch PetscCall(TSAdjointSetUp(ts)); 1578814e85d6SHong Zhang 1579814e85d6SHong Zhang /* reset time step and iteration counters */ 1580814e85d6SHong Zhang ts->adjoint_steps = 0; 1581814e85d6SHong Zhang ts->ksp_its = 0; 1582814e85d6SHong Zhang ts->snes_its = 0; 1583814e85d6SHong Zhang ts->num_snes_failures = 0; 1584814e85d6SHong Zhang ts->reject = 0; 1585814e85d6SHong Zhang ts->reason = TS_CONVERGED_ITERATING; 1586814e85d6SHong Zhang 1587814e85d6SHong Zhang if (!ts->adjoint_max_steps) ts->adjoint_max_steps = ts->steps; 1588814e85d6SHong Zhang if (ts->adjoint_steps >= ts->adjoint_max_steps) ts->reason = TS_CONVERGED_ITS; 1589814e85d6SHong Zhang 1590814e85d6SHong Zhang while (!ts->reason) { 15919566063dSJacob Faibussowitsch PetscCall(TSTrajectoryGet(ts->trajectory, ts, ts->steps, &ts->ptime)); 15929566063dSJacob Faibussowitsch PetscCall(TSAdjointMonitor(ts, ts->steps, ts->ptime, ts->vec_sol, ts->numcost, ts->vecs_sensi, ts->vecs_sensip)); 15939566063dSJacob Faibussowitsch PetscCall(TSAdjointEventHandler(ts)); 15949566063dSJacob Faibussowitsch PetscCall(TSAdjointStep(ts)); 159548a46eb9SPierre Jolivet if ((ts->vec_costintegral || ts->quadraturets) && !ts->costintegralfwd) PetscCall(TSAdjointCostIntegral(ts)); 1596814e85d6SHong Zhang } 1597bdbff044SHong Zhang if (!ts->steps) { 15989566063dSJacob Faibussowitsch PetscCall(TSTrajectoryGet(ts->trajectory, ts, ts->steps, &ts->ptime)); 15999566063dSJacob Faibussowitsch PetscCall(TSAdjointMonitor(ts, ts->steps, ts->ptime, ts->vec_sol, ts->numcost, ts->vecs_sensi, ts->vecs_sensip)); 1600bdbff044SHong Zhang } 1601814e85d6SHong Zhang ts->solvetime = ts->ptime; 16029566063dSJacob Faibussowitsch PetscCall(TSTrajectoryViewFromOptions(ts->trajectory, NULL, "-ts_trajectory_view")); 16039566063dSJacob Faibussowitsch PetscCall(VecViewFromOptions(ts->vecs_sensi[0], (PetscObject)ts, "-ts_adjoint_view_solution")); 1604814e85d6SHong Zhang ts->adjoint_max_steps = 0; 16057f59fb53SHong Zhang #if defined(TSADJOINT_STAGE) 16069566063dSJacob Faibussowitsch PetscCall(PetscLogStagePop()); 16077f59fb53SHong Zhang #endif 16083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1609814e85d6SHong Zhang } 1610814e85d6SHong Zhang 1611814e85d6SHong Zhang /*@C 1612bcf0153eSBarry Smith TSAdjointMonitor - Runs all user-provided adjoint monitor routines set using `TSAdjointMonitorSet()` 1613814e85d6SHong Zhang 1614c3339decSBarry Smith Collective 1615814e85d6SHong Zhang 1616814e85d6SHong Zhang Input Parameters: 1617bcf0153eSBarry Smith + ts - time stepping context obtained from `TSCreate()` 1618814e85d6SHong Zhang . step - step number that has just completed 1619814e85d6SHong Zhang . ptime - model time of the state 1620814e85d6SHong Zhang . u - state at the current model time 1621814e85d6SHong Zhang . numcost - number of cost functions (dimension of lambda or mu) 1622814e85d6SHong Zhang . lambda - vectors containing the gradients of the cost functions with respect to the ODE/DAE solution variables 1623814e85d6SHong Zhang - mu - vectors containing the gradients of the cost functions with respect to the problem parameters 1624814e85d6SHong Zhang 1625814e85d6SHong Zhang Level: developer 1626814e85d6SHong Zhang 1627bcf0153eSBarry Smith Note: 1628bcf0153eSBarry Smith `TSAdjointMonitor()` is typically used automatically within the time stepping implementations. 1629bcf0153eSBarry Smith Users would almost never call this routine directly. 1630bcf0153eSBarry Smith 1631bcf0153eSBarry Smith .seealso: `TSAdjointMonitorSet()`, `TSAdjointSolve()` 1632814e85d6SHong Zhang @*/ 1633d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointMonitor(TS ts, PetscInt step, PetscReal ptime, Vec u, PetscInt numcost, Vec *lambda, Vec *mu) 1634d71ae5a4SJacob Faibussowitsch { 1635814e85d6SHong Zhang PetscInt i, n = ts->numberadjointmonitors; 1636814e85d6SHong Zhang 1637814e85d6SHong Zhang PetscFunctionBegin; 1638814e85d6SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1639814e85d6SHong Zhang PetscValidHeaderSpecific(u, VEC_CLASSID, 4); 16409566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(u)); 164148a46eb9SPierre Jolivet for (i = 0; i < n; i++) PetscCall((*ts->adjointmonitor[i])(ts, step, ptime, u, numcost, lambda, mu, ts->adjointmonitorcontext[i])); 16429566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(u)); 16433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1644814e85d6SHong Zhang } 1645814e85d6SHong Zhang 1646814e85d6SHong Zhang /*@ 1647814e85d6SHong Zhang TSAdjointCostIntegral - Evaluate the cost integral in the adjoint run. 1648814e85d6SHong Zhang 1649c3339decSBarry Smith Collective 1650814e85d6SHong Zhang 16514165533cSJose E. Roman Input Parameter: 1652814e85d6SHong Zhang . ts - time stepping context 1653814e85d6SHong Zhang 1654814e85d6SHong Zhang Level: advanced 1655814e85d6SHong Zhang 1656814e85d6SHong Zhang Notes: 1657bcf0153eSBarry Smith This function cannot be called until `TSAdjointStep()` has been completed. 1658814e85d6SHong Zhang 16591cc06b55SBarry Smith .seealso: [](ch_ts), `TSAdjointSolve()`, `TSAdjointStep()` 1660814e85d6SHong Zhang @*/ 1661d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointCostIntegral(TS ts) 1662d71ae5a4SJacob Faibussowitsch { 1663362febeeSStefano Zampini PetscFunctionBegin; 1664814e85d6SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1665dbbe0bcdSBarry Smith PetscUseTypeMethod(ts, adjointintegral); 16663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1667814e85d6SHong Zhang } 1668814e85d6SHong Zhang 1669814e85d6SHong Zhang /* ------------------ Forward (tangent linear) sensitivity ------------------*/ 1670814e85d6SHong Zhang 1671814e85d6SHong Zhang /*@ 1672814e85d6SHong Zhang TSForwardSetUp - Sets up the internal data structures for the later use 1673814e85d6SHong Zhang of forward sensitivity analysis 1674814e85d6SHong Zhang 1675c3339decSBarry Smith Collective 1676814e85d6SHong Zhang 1677814e85d6SHong Zhang Input Parameter: 1678bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()` 1679814e85d6SHong Zhang 1680814e85d6SHong Zhang Level: advanced 1681814e85d6SHong Zhang 16821cc06b55SBarry Smith .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSDestroy()`, `TSSetUp()` 1683814e85d6SHong Zhang @*/ 1684d71ae5a4SJacob Faibussowitsch PetscErrorCode TSForwardSetUp(TS ts) 1685d71ae5a4SJacob Faibussowitsch { 1686814e85d6SHong Zhang PetscFunctionBegin; 1687814e85d6SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 16883ba16761SJacob Faibussowitsch if (ts->forwardsetupcalled) PetscFunctionReturn(PETSC_SUCCESS); 1689dbbe0bcdSBarry Smith PetscTryTypeMethod(ts, forwardsetup); 16909566063dSJacob Faibussowitsch PetscCall(VecDuplicate(ts->vec_sol, &ts->vec_sensip_col)); 1691814e85d6SHong Zhang ts->forwardsetupcalled = PETSC_TRUE; 16923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1693814e85d6SHong Zhang } 1694814e85d6SHong Zhang 1695814e85d6SHong Zhang /*@ 16967adebddeSHong Zhang TSForwardReset - Reset the internal data structures used by forward sensitivity analysis 16977adebddeSHong Zhang 1698c3339decSBarry Smith Collective 16997adebddeSHong Zhang 17007adebddeSHong Zhang Input Parameter: 1701bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()` 17027adebddeSHong Zhang 17037adebddeSHong Zhang Level: advanced 17047adebddeSHong Zhang 17051cc06b55SBarry Smith .seealso: [](ch_ts), `TSCreate()`, `TSDestroy()`, `TSForwardSetUp()` 17067adebddeSHong Zhang @*/ 1707d71ae5a4SJacob Faibussowitsch PetscErrorCode TSForwardReset(TS ts) 1708d71ae5a4SJacob Faibussowitsch { 17097207e0fdSHong Zhang TS quadts = ts->quadraturets; 17107adebddeSHong Zhang 17117adebddeSHong Zhang PetscFunctionBegin; 17127adebddeSHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1713dbbe0bcdSBarry Smith PetscTryTypeMethod(ts, forwardreset); 17149566063dSJacob Faibussowitsch PetscCall(MatDestroy(&ts->mat_sensip)); 171548a46eb9SPierre Jolivet if (quadts) PetscCall(MatDestroy(&quadts->mat_sensip)); 17169566063dSJacob Faibussowitsch PetscCall(VecDestroy(&ts->vec_sensip_col)); 17177adebddeSHong Zhang ts->forward_solve = PETSC_FALSE; 17187adebddeSHong Zhang ts->forwardsetupcalled = PETSC_FALSE; 17193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 17207adebddeSHong Zhang } 17217adebddeSHong Zhang 17227adebddeSHong Zhang /*@ 1723814e85d6SHong Zhang TSForwardSetIntegralGradients - Set the vectors holding forward sensitivities of the integral term. 1724814e85d6SHong Zhang 1725d8d19677SJose E. Roman Input Parameters: 1726bcf0153eSBarry Smith + ts - the `TS` context obtained from `TSCreate()` 1727814e85d6SHong Zhang . numfwdint - number of integrals 172867b8a455SSatish Balay - vp - the vectors containing the gradients for each integral w.r.t. parameters 1729814e85d6SHong Zhang 17307207e0fdSHong Zhang Level: deprecated 1731814e85d6SHong Zhang 173242747ad1SJacob Faibussowitsch .seealso: [](ch_ts), `TSForwardGetSensitivities()`, `TSForwardGetIntegralGradients()`, `TSForwardStep()` 1733814e85d6SHong Zhang @*/ 1734d71ae5a4SJacob Faibussowitsch PetscErrorCode TSForwardSetIntegralGradients(TS ts, PetscInt numfwdint, Vec *vp) 1735d71ae5a4SJacob Faibussowitsch { 1736814e85d6SHong Zhang PetscFunctionBegin; 1737814e85d6SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 17383c633725SBarry 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()"); 1739814e85d6SHong Zhang if (!ts->numcost) ts->numcost = numfwdint; 1740814e85d6SHong Zhang 1741814e85d6SHong Zhang ts->vecs_integral_sensip = vp; 17423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1743814e85d6SHong Zhang } 1744814e85d6SHong Zhang 1745814e85d6SHong Zhang /*@ 1746814e85d6SHong Zhang TSForwardGetIntegralGradients - Returns the forward sensitivities of the integral term. 1747814e85d6SHong Zhang 1748814e85d6SHong Zhang Input Parameter: 1749bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()` 1750814e85d6SHong Zhang 175114d0ab18SJacob Faibussowitsch Output Parameters: 175214d0ab18SJacob Faibussowitsch + numfwdint - number of integrals 175314d0ab18SJacob Faibussowitsch - vp - the vectors containing the gradients for each integral w.r.t. parameters 1754814e85d6SHong Zhang 17557207e0fdSHong Zhang Level: deprecated 1756814e85d6SHong Zhang 175742747ad1SJacob Faibussowitsch .seealso: [](ch_ts), `TSForwardSetSensitivities()`, `TSForwardSetIntegralGradients()`, `TSForwardStep()` 1758814e85d6SHong Zhang @*/ 1759d71ae5a4SJacob Faibussowitsch PetscErrorCode TSForwardGetIntegralGradients(TS ts, PetscInt *numfwdint, Vec **vp) 1760d71ae5a4SJacob Faibussowitsch { 1761814e85d6SHong Zhang PetscFunctionBegin; 1762814e85d6SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 17634f572ea9SToby Isaac PetscAssertPointer(vp, 3); 1764814e85d6SHong Zhang if (numfwdint) *numfwdint = ts->numcost; 1765814e85d6SHong Zhang if (vp) *vp = ts->vecs_integral_sensip; 17663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1767814e85d6SHong Zhang } 1768814e85d6SHong Zhang 1769814e85d6SHong Zhang /*@ 1770814e85d6SHong Zhang TSForwardStep - Compute the forward sensitivity for one time step. 1771814e85d6SHong Zhang 1772c3339decSBarry Smith Collective 1773814e85d6SHong Zhang 17744165533cSJose E. Roman Input Parameter: 1775814e85d6SHong Zhang . ts - time stepping context 1776814e85d6SHong Zhang 1777814e85d6SHong Zhang Level: advanced 1778814e85d6SHong Zhang 1779814e85d6SHong Zhang Notes: 1780bcf0153eSBarry Smith This function cannot be called until `TSStep()` has been completed. 1781814e85d6SHong Zhang 17821cc06b55SBarry Smith .seealso: [](ch_ts), `TSForwardSetSensitivities()`, `TSForwardGetSensitivities()`, `TSForwardSetIntegralGradients()`, `TSForwardGetIntegralGradients()`, `TSForwardSetUp()` 1783814e85d6SHong Zhang @*/ 1784d71ae5a4SJacob Faibussowitsch PetscErrorCode TSForwardStep(TS ts) 1785d71ae5a4SJacob Faibussowitsch { 1786362febeeSStefano Zampini PetscFunctionBegin; 1787814e85d6SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 17889566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(TS_ForwardStep, ts, 0, 0, 0)); 1789dbbe0bcdSBarry Smith PetscUseTypeMethod(ts, forwardstep); 17909566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(TS_ForwardStep, ts, 0, 0, 0)); 17913c633725SBarry Smith PetscCheck(ts->reason >= 0 || !ts->errorifstepfailed, PetscObjectComm((PetscObject)ts), PETSC_ERR_NOT_CONVERGED, "TSFowardStep has failed due to %s", TSConvergedReasons[ts->reason]); 17923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1793814e85d6SHong Zhang } 1794814e85d6SHong Zhang 1795814e85d6SHong Zhang /*@ 1796814e85d6SHong Zhang TSForwardSetSensitivities - Sets the initial value of the trajectory sensitivities of solution w.r.t. the problem parameters and initial values. 1797814e85d6SHong Zhang 1798c3339decSBarry Smith Logically Collective 1799814e85d6SHong Zhang 1800814e85d6SHong Zhang Input Parameters: 1801bcf0153eSBarry Smith + ts - the `TS` context obtained from `TSCreate()` 1802814e85d6SHong Zhang . nump - number of parameters 1803814e85d6SHong Zhang - Smat - sensitivities with respect to the parameters, the number of entries in these vectors is the same as the number of parameters 1804814e85d6SHong Zhang 1805814e85d6SHong Zhang Level: beginner 1806814e85d6SHong Zhang 1807814e85d6SHong Zhang Notes: 180809cb0f53SBarry Smith Use `PETSC_DETERMINE` to use the number of columns of `Smat` for `nump` 180909cb0f53SBarry Smith 1810814e85d6SHong Zhang Forward sensitivity is also called 'trajectory sensitivity' in some fields such as power systems. 1811bcf0153eSBarry Smith This function turns on a flag to trigger `TSSolve()` to compute forward sensitivities automatically. 1812bcf0153eSBarry Smith You must call this function before `TSSolve()`. 1813814e85d6SHong Zhang The entries in the sensitivity matrix must be correctly initialized with the values S = dy/dp|startingtime. 1814814e85d6SHong Zhang 18151cc06b55SBarry Smith .seealso: [](ch_ts), `TSForwardGetSensitivities()`, `TSForwardSetIntegralGradients()`, `TSForwardGetIntegralGradients()`, `TSForwardStep()` 1816814e85d6SHong Zhang @*/ 1817d71ae5a4SJacob Faibussowitsch PetscErrorCode TSForwardSetSensitivities(TS ts, PetscInt nump, Mat Smat) 1818d71ae5a4SJacob Faibussowitsch { 1819814e85d6SHong Zhang PetscFunctionBegin; 1820814e85d6SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1821814e85d6SHong Zhang PetscValidHeaderSpecific(Smat, MAT_CLASSID, 3); 1822814e85d6SHong Zhang ts->forward_solve = PETSC_TRUE; 182309cb0f53SBarry Smith if (nump == PETSC_DEFAULT || nump == PETSC_DETERMINE) { 18249566063dSJacob Faibussowitsch PetscCall(MatGetSize(Smat, NULL, &ts->num_parameters)); 1825b5b4017aSHong Zhang } else ts->num_parameters = nump; 18269566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)Smat)); 18279566063dSJacob Faibussowitsch PetscCall(MatDestroy(&ts->mat_sensip)); 1828814e85d6SHong Zhang ts->mat_sensip = Smat; 18293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1830814e85d6SHong Zhang } 1831814e85d6SHong Zhang 1832814e85d6SHong Zhang /*@ 1833814e85d6SHong Zhang TSForwardGetSensitivities - Returns the trajectory sensitivities 1834814e85d6SHong Zhang 1835bcf0153eSBarry Smith Not Collective, but Smat returned is parallel if ts is parallel 1836814e85d6SHong Zhang 1837d8d19677SJose E. Roman Output Parameters: 1838bcf0153eSBarry Smith + ts - the `TS` context obtained from `TSCreate()` 1839814e85d6SHong Zhang . nump - number of parameters 1840814e85d6SHong Zhang - Smat - sensitivities with respect to the parameters, the number of entries in these vectors is the same as the number of parameters 1841814e85d6SHong Zhang 1842814e85d6SHong Zhang Level: intermediate 1843814e85d6SHong Zhang 18441cc06b55SBarry Smith .seealso: [](ch_ts), `TSForwardSetSensitivities()`, `TSForwardSetIntegralGradients()`, `TSForwardGetIntegralGradients()`, `TSForwardStep()` 1845814e85d6SHong Zhang @*/ 1846d71ae5a4SJacob Faibussowitsch PetscErrorCode TSForwardGetSensitivities(TS ts, PetscInt *nump, Mat *Smat) 1847d71ae5a4SJacob Faibussowitsch { 1848814e85d6SHong Zhang PetscFunctionBegin; 1849814e85d6SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1850814e85d6SHong Zhang if (nump) *nump = ts->num_parameters; 1851814e85d6SHong Zhang if (Smat) *Smat = ts->mat_sensip; 18523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1853814e85d6SHong Zhang } 1854814e85d6SHong Zhang 1855814e85d6SHong Zhang /*@ 1856814e85d6SHong Zhang TSForwardCostIntegral - Evaluate the cost integral in the forward run. 1857814e85d6SHong Zhang 1858c3339decSBarry Smith Collective 1859814e85d6SHong Zhang 18604165533cSJose E. Roman Input Parameter: 1861814e85d6SHong Zhang . ts - time stepping context 1862814e85d6SHong Zhang 1863814e85d6SHong Zhang Level: advanced 1864814e85d6SHong Zhang 1865bcf0153eSBarry Smith Note: 1866bcf0153eSBarry Smith This function cannot be called until `TSStep()` has been completed. 1867814e85d6SHong Zhang 18681cc06b55SBarry Smith .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSAdjointCostIntegral()` 1869814e85d6SHong Zhang @*/ 1870d71ae5a4SJacob Faibussowitsch PetscErrorCode TSForwardCostIntegral(TS ts) 1871d71ae5a4SJacob Faibussowitsch { 1872362febeeSStefano Zampini PetscFunctionBegin; 1873814e85d6SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1874dbbe0bcdSBarry Smith PetscUseTypeMethod(ts, forwardintegral); 18753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1876814e85d6SHong Zhang } 1877b5b4017aSHong Zhang 1878b5b4017aSHong Zhang /*@ 1879b5b4017aSHong Zhang TSForwardSetInitialSensitivities - Set initial values for tangent linear sensitivities 1880b5b4017aSHong Zhang 1881c3339decSBarry Smith Collective 1882b5b4017aSHong Zhang 1883d8d19677SJose E. Roman Input Parameters: 1884bcf0153eSBarry Smith + ts - the `TS` context obtained from `TSCreate()` 1885b5b4017aSHong Zhang - didp - parametric sensitivities of the initial condition 1886b5b4017aSHong Zhang 1887b5b4017aSHong Zhang Level: intermediate 1888b5b4017aSHong Zhang 1889bcf0153eSBarry Smith Notes: 1890bcf0153eSBarry Smith `TSSolve()` allows users to pass the initial solution directly to `TS`. But the tangent linear variables cannot be initialized in this way. 1891bcf0153eSBarry Smith This function is used to set initial values for tangent linear variables. 1892b5b4017aSHong Zhang 18931cc06b55SBarry Smith .seealso: [](ch_ts), `TS`, `TSForwardSetSensitivities()` 1894b5b4017aSHong Zhang @*/ 1895d71ae5a4SJacob Faibussowitsch PetscErrorCode TSForwardSetInitialSensitivities(TS ts, Mat didp) 1896d71ae5a4SJacob Faibussowitsch { 1897362febeeSStefano Zampini PetscFunctionBegin; 1898b5b4017aSHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1899b5b4017aSHong Zhang PetscValidHeaderSpecific(didp, MAT_CLASSID, 2); 190009cb0f53SBarry Smith if (!ts->mat_sensip) PetscCall(TSForwardSetSensitivities(ts, PETSC_DETERMINE, didp)); 19013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1902b5b4017aSHong Zhang } 19036affb6f8SHong Zhang 19046affb6f8SHong Zhang /*@ 19056affb6f8SHong Zhang TSForwardGetStages - Get the number of stages and the tangent linear sensitivities at the intermediate stages 19066affb6f8SHong Zhang 19076affb6f8SHong Zhang Input Parameter: 1908bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()` 19096affb6f8SHong Zhang 19106affb6f8SHong Zhang Output Parameters: 1911cd4cee2dSHong Zhang + ns - number of stages 19126affb6f8SHong Zhang - S - tangent linear sensitivities at the intermediate stages 19136affb6f8SHong Zhang 19146affb6f8SHong Zhang Level: advanced 19156affb6f8SHong Zhang 1916bcf0153eSBarry Smith .seealso: `TS` 19176affb6f8SHong Zhang @*/ 1918d71ae5a4SJacob Faibussowitsch PetscErrorCode TSForwardGetStages(TS ts, PetscInt *ns, Mat **S) 1919d71ae5a4SJacob Faibussowitsch { 19206affb6f8SHong Zhang PetscFunctionBegin; 19216affb6f8SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 19226affb6f8SHong Zhang 19236affb6f8SHong Zhang if (!ts->ops->getstages) *S = NULL; 1924dbbe0bcdSBarry Smith else PetscUseTypeMethod(ts, forwardgetstages, ns, S); 19253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19266affb6f8SHong Zhang } 1927cd4cee2dSHong Zhang 1928cd4cee2dSHong Zhang /*@ 1929bcf0153eSBarry Smith TSCreateQuadratureTS - Create a sub-`TS` that evaluates integrals over time 1930cd4cee2dSHong Zhang 1931d8d19677SJose E. Roman Input Parameters: 1932bcf0153eSBarry Smith + ts - the `TS` context obtained from `TSCreate()` 1933cd4cee2dSHong Zhang - fwd - flag indicating whether to evaluate cost integral in the forward run or the adjoint run 1934cd4cee2dSHong Zhang 19352fe279fdSBarry Smith Output Parameter: 1936bcf0153eSBarry Smith . quadts - the child `TS` context 1937cd4cee2dSHong Zhang 1938cd4cee2dSHong Zhang Level: intermediate 1939cd4cee2dSHong Zhang 19401cc06b55SBarry Smith .seealso: [](ch_ts), `TSGetQuadratureTS()` 1941cd4cee2dSHong Zhang @*/ 1942d71ae5a4SJacob Faibussowitsch PetscErrorCode TSCreateQuadratureTS(TS ts, PetscBool fwd, TS *quadts) 1943d71ae5a4SJacob Faibussowitsch { 1944cd4cee2dSHong Zhang char prefix[128]; 1945cd4cee2dSHong Zhang 1946cd4cee2dSHong Zhang PetscFunctionBegin; 1947cd4cee2dSHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 19484f572ea9SToby Isaac PetscAssertPointer(quadts, 3); 19499566063dSJacob Faibussowitsch PetscCall(TSDestroy(&ts->quadraturets)); 19509566063dSJacob Faibussowitsch PetscCall(TSCreate(PetscObjectComm((PetscObject)ts), &ts->quadraturets)); 19519566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)ts->quadraturets, (PetscObject)ts, 1)); 19529566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(prefix, sizeof(prefix), "%squad_", ((PetscObject)ts)->prefix ? ((PetscObject)ts)->prefix : "")); 19539566063dSJacob Faibussowitsch PetscCall(TSSetOptionsPrefix(ts->quadraturets, prefix)); 1954cd4cee2dSHong Zhang *quadts = ts->quadraturets; 1955cd4cee2dSHong Zhang 1956cd4cee2dSHong Zhang if (ts->numcost) { 19579566063dSJacob Faibussowitsch PetscCall(VecCreateSeq(PETSC_COMM_SELF, ts->numcost, &(*quadts)->vec_sol)); 1958cd4cee2dSHong Zhang } else { 19599566063dSJacob Faibussowitsch PetscCall(VecCreateSeq(PETSC_COMM_SELF, 1, &(*quadts)->vec_sol)); 1960cd4cee2dSHong Zhang } 1961cd4cee2dSHong Zhang ts->costintegralfwd = fwd; 19623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1963cd4cee2dSHong Zhang } 1964cd4cee2dSHong Zhang 1965cd4cee2dSHong Zhang /*@ 1966bcf0153eSBarry Smith TSGetQuadratureTS - Return the sub-`TS` that evaluates integrals over time 1967cd4cee2dSHong Zhang 1968cd4cee2dSHong Zhang Input Parameter: 1969bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()` 1970cd4cee2dSHong Zhang 1971cd4cee2dSHong Zhang Output Parameters: 1972cd4cee2dSHong Zhang + fwd - flag indicating whether to evaluate cost integral in the forward run or the adjoint run 1973bcf0153eSBarry Smith - quadts - the child `TS` context 1974cd4cee2dSHong Zhang 1975cd4cee2dSHong Zhang Level: intermediate 1976cd4cee2dSHong Zhang 19771cc06b55SBarry Smith .seealso: [](ch_ts), `TSCreateQuadratureTS()` 1978cd4cee2dSHong Zhang @*/ 1979d71ae5a4SJacob Faibussowitsch PetscErrorCode TSGetQuadratureTS(TS ts, PetscBool *fwd, TS *quadts) 1980d71ae5a4SJacob Faibussowitsch { 1981cd4cee2dSHong Zhang PetscFunctionBegin; 1982cd4cee2dSHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1983cd4cee2dSHong Zhang if (fwd) *fwd = ts->costintegralfwd; 1984cd4cee2dSHong Zhang if (quadts) *quadts = ts->quadraturets; 19853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1986cd4cee2dSHong Zhang } 1987ba0675f6SHong Zhang 1988ba0675f6SHong Zhang /*@ 1989bcf0153eSBarry Smith TSComputeSNESJacobian - Compute the Jacobian needed for the `SNESSolve()` in `TS` 1990bcf0153eSBarry Smith 1991c3339decSBarry Smith Collective 1992ba0675f6SHong Zhang 1993ba0675f6SHong Zhang Input Parameters: 1994bcf0153eSBarry Smith + ts - the `TS` context obtained from `TSCreate()` 1995ba0675f6SHong Zhang - x - state vector 1996ba0675f6SHong Zhang 1997ba0675f6SHong Zhang Output Parameters: 1998ba0675f6SHong Zhang + J - Jacobian matrix 1999ba0675f6SHong Zhang - Jpre - preconditioning matrix for J (may be same as J) 2000ba0675f6SHong Zhang 2001ba0675f6SHong Zhang Level: developer 2002ba0675f6SHong Zhang 2003bcf0153eSBarry Smith Note: 2004bcf0153eSBarry Smith Uses finite differencing when `TS` Jacobian is not available. 2005bcf0153eSBarry Smith 2006b43aa488SJacob Faibussowitsch .seealso: `SNES`, `TS`, `SNESSetJacobian()`, `TSSetRHSJacobian()`, `TSSetIJacobian()` 2007ba0675f6SHong Zhang @*/ 2008d71ae5a4SJacob Faibussowitsch PetscErrorCode TSComputeSNESJacobian(TS ts, Vec x, Mat J, Mat Jpre) 2009d71ae5a4SJacob Faibussowitsch { 2010ba0675f6SHong Zhang SNES snes = ts->snes; 2011ba0675f6SHong Zhang PetscErrorCode (*jac)(SNES, Vec, Mat, Mat, void *) = NULL; 2012ba0675f6SHong Zhang 2013ba0675f6SHong Zhang PetscFunctionBegin; 2014ba0675f6SHong Zhang /* 2015ba0675f6SHong Zhang Unlike implicit methods, explicit methods do not have SNESMatFDColoring in the snes object 2016ba0675f6SHong Zhang because SNESSolve() has not been called yet; so querying SNESMatFDColoring does not work for 2017da81f932SPierre Jolivet explicit methods. Instead, we check the Jacobian compute function directly to determine if FD 2018ba0675f6SHong Zhang coloring is used. 2019ba0675f6SHong Zhang */ 20209566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes, NULL, NULL, &jac, NULL)); 2021ba0675f6SHong Zhang if (jac == SNESComputeJacobianDefaultColor) { 2022ba0675f6SHong Zhang Vec f; 20239566063dSJacob Faibussowitsch PetscCall(SNESSetSolution(snes, x)); 20249566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, &f, NULL, NULL)); 2025ba0675f6SHong Zhang /* Force MatFDColoringApply to evaluate the SNES residual function for the base vector */ 20269566063dSJacob Faibussowitsch PetscCall(SNESComputeFunction(snes, x, f)); 2027ba0675f6SHong Zhang } 20289566063dSJacob Faibussowitsch PetscCall(SNESComputeJacobian(snes, x, J, Jpre)); 20293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2030ba0675f6SHong Zhang } 2031