1814e85d6SHong Zhang #include <petsc/private/tsimpl.h> /*I "petscts.h" I*/ 2814e85d6SHong Zhang #include <petscdraw.h> 3814e85d6SHong Zhang 433f72c5dSHong Zhang PetscLogEvent TS_AdjointStep, TS_ForwardStep, TS_JacobianPEval; 5814e85d6SHong Zhang 67f59fb53SHong Zhang /* #define TSADJOINT_STAGE */ 77f59fb53SHong Zhang 8814e85d6SHong Zhang /* ------------------------ Sensitivity Context ---------------------------*/ 9814e85d6SHong Zhang 10814e85d6SHong Zhang /*@C 11b5b4017aSHong Zhang TSSetRHSJacobianP - Sets the function that computes the Jacobian of G w.r.t. the parameters P where U_t = G(U,P,t), as well as the location to store the matrix. 12814e85d6SHong Zhang 13*bcf0153eSBarry Smith Logically Collective on ts 14814e85d6SHong Zhang 15814e85d6SHong Zhang Input Parameters: 16*bcf0153eSBarry 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 Calling sequence of func: 22814e85d6SHong Zhang $ func (TS ts,PetscReal t,Vec y,Mat A,void *ctx); 23814e85d6SHong Zhang + t - current timestep 24c9ad9de0SHong Zhang . U - input vector (current ODE solution) 25814e85d6SHong Zhang . A - output matrix 26814e85d6SHong Zhang - ctx - [optional] user-defined function context 27814e85d6SHong Zhang 28814e85d6SHong Zhang Level: intermediate 29814e85d6SHong Zhang 30*bcf0153eSBarry Smith Note: 31814e85d6SHong Zhang Amat has the same number of rows and the same row parallel layout as u, Amat has the same number of columns and parallel layout as p 32814e85d6SHong Zhang 33*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TS`, `TSGetRHSJacobianP()` 34814e85d6SHong Zhang @*/ 35d71ae5a4SJacob Faibussowitsch PetscErrorCode TSSetRHSJacobianP(TS ts, Mat Amat, PetscErrorCode (*func)(TS, PetscReal, Vec, Mat, void *), void *ctx) 36d71ae5a4SJacob Faibussowitsch { 37814e85d6SHong Zhang PetscFunctionBegin; 38814e85d6SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 39814e85d6SHong Zhang PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2); 40814e85d6SHong Zhang 41814e85d6SHong Zhang ts->rhsjacobianp = func; 42814e85d6SHong Zhang ts->rhsjacobianpctx = ctx; 43814e85d6SHong Zhang if (Amat) { 449566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)Amat)); 459566063dSJacob Faibussowitsch PetscCall(MatDestroy(&ts->Jacprhs)); 4633f72c5dSHong Zhang ts->Jacprhs = Amat; 47814e85d6SHong Zhang } 48814e85d6SHong Zhang PetscFunctionReturn(0); 49814e85d6SHong Zhang } 50814e85d6SHong Zhang 51814e85d6SHong Zhang /*@C 52cd4cee2dSHong Zhang TSGetRHSJacobianP - Gets the function that computes the Jacobian of G w.r.t. the parameters P where U_t = G(U,P,t), as well as the location to store the matrix. 53cd4cee2dSHong Zhang 54*bcf0153eSBarry Smith Logically Collective on ts 55cd4cee2dSHong Zhang 56f899ff85SJose E. Roman Input Parameter: 57*bcf0153eSBarry Smith . ts - `TS` context obtained from `TSCreate()` 58cd4cee2dSHong Zhang 59cd4cee2dSHong Zhang Output Parameters: 60cd4cee2dSHong Zhang + Amat - JacobianP matrix 61cd4cee2dSHong Zhang . func - function 62cd4cee2dSHong Zhang - ctx - [optional] user-defined function context 63cd4cee2dSHong Zhang 64cd4cee2dSHong Zhang Calling sequence of func: 65cd4cee2dSHong Zhang $ func (TS ts,PetscReal t,Vec y,Mat A,void *ctx); 66cd4cee2dSHong Zhang + t - current timestep 67cd4cee2dSHong Zhang . U - input vector (current ODE solution) 68cd4cee2dSHong Zhang . A - output matrix 69cd4cee2dSHong Zhang - ctx - [optional] user-defined function context 70cd4cee2dSHong Zhang 71cd4cee2dSHong Zhang Level: intermediate 72cd4cee2dSHong Zhang 73*bcf0153eSBarry Smith Note: 74cd4cee2dSHong Zhang Amat has the same number of rows and the same row parallel layout as u, Amat has the same number of columns and parallel layout as p 75cd4cee2dSHong Zhang 76*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TSSetRHSJacobianP()`, `TS`, `TSGetRHSJacobianP()` 77cd4cee2dSHong Zhang @*/ 78d71ae5a4SJacob Faibussowitsch PetscErrorCode TSGetRHSJacobianP(TS ts, Mat *Amat, PetscErrorCode (**func)(TS, PetscReal, Vec, Mat, void *), void **ctx) 79d71ae5a4SJacob Faibussowitsch { 80cd4cee2dSHong Zhang PetscFunctionBegin; 81cd4cee2dSHong Zhang if (func) *func = ts->rhsjacobianp; 82cd4cee2dSHong Zhang if (ctx) *ctx = ts->rhsjacobianpctx; 83cd4cee2dSHong Zhang if (Amat) *Amat = ts->Jacprhs; 84cd4cee2dSHong Zhang PetscFunctionReturn(0); 85cd4cee2dSHong Zhang } 86cd4cee2dSHong Zhang 87cd4cee2dSHong Zhang /*@C 88814e85d6SHong Zhang TSComputeRHSJacobianP - Runs the user-defined JacobianP function. 89814e85d6SHong Zhang 90*bcf0153eSBarry Smith Collective on ts 91814e85d6SHong Zhang 92814e85d6SHong Zhang Input Parameters: 93*bcf0153eSBarry Smith . ts - The `TS` context obtained from `TSCreate()` 94814e85d6SHong Zhang 95814e85d6SHong Zhang Level: developer 96814e85d6SHong Zhang 97*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TSSetRHSJacobianP()`, `TS` 98814e85d6SHong Zhang @*/ 99d71ae5a4SJacob Faibussowitsch PetscErrorCode TSComputeRHSJacobianP(TS ts, PetscReal t, Vec U, Mat Amat) 100d71ae5a4SJacob Faibussowitsch { 101814e85d6SHong Zhang PetscFunctionBegin; 10233f72c5dSHong Zhang if (!Amat) PetscFunctionReturn(0); 103814e85d6SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 104c9ad9de0SHong Zhang PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 105814e85d6SHong Zhang 106792fecdfSBarry Smith PetscCallBack("TS callback JacobianP for sensitivity analysis", (*ts->rhsjacobianp)(ts, t, U, Amat, ts->rhsjacobianpctx)); 107814e85d6SHong Zhang PetscFunctionReturn(0); 108814e85d6SHong Zhang } 109814e85d6SHong Zhang 110814e85d6SHong Zhang /*@C 11133f72c5dSHong Zhang TSSetIJacobianP - Sets the function that computes the Jacobian of F w.r.t. the parameters P where F(Udot,U,t) = G(U,P,t), as well as the location to store the matrix. 11233f72c5dSHong Zhang 113*bcf0153eSBarry Smith Logically Collective on ts 11433f72c5dSHong Zhang 11533f72c5dSHong Zhang Input Parameters: 116*bcf0153eSBarry 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 12133f72c5dSHong Zhang Calling sequence of func: 12233f72c5dSHong Zhang $ func (TS ts,PetscReal t,Vec y,Mat A,void *ctx); 12333f72c5dSHong Zhang + t - current timestep 12433f72c5dSHong Zhang . U - input vector (current ODE solution) 12533f72c5dSHong Zhang . Udot - time derivative of state vector 12633f72c5dSHong Zhang . shift - shift to apply, see note below 12733f72c5dSHong Zhang . A - output matrix 12833f72c5dSHong Zhang - ctx - [optional] user-defined function context 12933f72c5dSHong Zhang 13033f72c5dSHong Zhang Level: intermediate 13133f72c5dSHong Zhang 132*bcf0153eSBarry Smith Note: 13333f72c5dSHong Zhang Amat has the same number of rows and the same row parallel layout as u, Amat has the same number of columns and parallel layout as p 13433f72c5dSHong Zhang 135*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TSSetRHSJacobianP()`, `TS` 13633f72c5dSHong Zhang @*/ 137d71ae5a4SJacob Faibussowitsch PetscErrorCode TSSetIJacobianP(TS ts, Mat Amat, PetscErrorCode (*func)(TS, PetscReal, Vec, Vec, PetscReal, Mat, void *), 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 } 15033f72c5dSHong Zhang PetscFunctionReturn(0); 15133f72c5dSHong Zhang } 15233f72c5dSHong Zhang 15333f72c5dSHong Zhang /*@C 15433f72c5dSHong Zhang TSComputeIJacobianP - Runs the user-defined IJacobianP function. 15533f72c5dSHong Zhang 156*bcf0153eSBarry Smith Collective on ts 15733f72c5dSHong Zhang 15833f72c5dSHong Zhang Input Parameters: 159*bcf0153eSBarry Smith + ts - the `TS` context 16033f72c5dSHong Zhang . t - current timestep 16133f72c5dSHong Zhang . U - state vector 16233f72c5dSHong Zhang . Udot - time derivative of state vector 16333f72c5dSHong Zhang . shift - shift to apply, see note below 16433f72c5dSHong Zhang - imex - flag indicates if the method is IMEX so that the RHSJacobian should be kept separate 16533f72c5dSHong Zhang 16633f72c5dSHong Zhang Output Parameters: 16733f72c5dSHong Zhang . A - Jacobian matrix 16833f72c5dSHong Zhang 16933f72c5dSHong Zhang Level: developer 17033f72c5dSHong Zhang 171*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TS`, `TSSetIJacobianP()` 17233f72c5dSHong Zhang @*/ 173d71ae5a4SJacob Faibussowitsch PetscErrorCode TSComputeIJacobianP(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal shift, Mat Amat, PetscBool imex) 174d71ae5a4SJacob Faibussowitsch { 17533f72c5dSHong Zhang PetscFunctionBegin; 17633f72c5dSHong Zhang if (!Amat) PetscFunctionReturn(0); 17733f72c5dSHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 17833f72c5dSHong Zhang PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 17933f72c5dSHong Zhang PetscValidHeaderSpecific(Udot, VEC_CLASSID, 4); 18033f72c5dSHong Zhang 1819566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(TS_JacobianPEval, ts, U, Amat, 0)); 18248a46eb9SPierre Jolivet if (ts->ijacobianp) PetscCallBack("TS callback JacobianP for sensitivity analysis", (*ts->ijacobianp)(ts, t, U, Udot, shift, Amat, ts->ijacobianpctx)); 18333f72c5dSHong Zhang if (imex) { 18433f72c5dSHong Zhang if (!ts->ijacobianp) { /* system was written as Udot = G(t,U) */ 18533f72c5dSHong Zhang PetscBool assembled; 1869566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(Amat)); 1879566063dSJacob Faibussowitsch PetscCall(MatAssembled(Amat, &assembled)); 18833f72c5dSHong Zhang if (!assembled) { 1899566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(Amat, MAT_FINAL_ASSEMBLY)); 1909566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(Amat, MAT_FINAL_ASSEMBLY)); 19133f72c5dSHong Zhang } 19233f72c5dSHong Zhang } 19333f72c5dSHong Zhang } else { 1941baa6e33SBarry Smith if (ts->rhsjacobianp) PetscCall(TSComputeRHSJacobianP(ts, t, U, ts->Jacprhs)); 19533f72c5dSHong Zhang if (ts->Jacprhs == Amat) { /* No IJacobian, so we only have the RHS matrix */ 1969566063dSJacob Faibussowitsch PetscCall(MatScale(Amat, -1)); 19733f72c5dSHong Zhang } else if (ts->Jacprhs) { /* Both IJacobian and RHSJacobian */ 19833f72c5dSHong Zhang MatStructure axpy = DIFFERENT_NONZERO_PATTERN; 19933f72c5dSHong Zhang if (!ts->ijacobianp) { /* No IJacobianp provided, but we have a separate RHS matrix */ 2009566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(Amat)); 20133f72c5dSHong Zhang } 2029566063dSJacob Faibussowitsch PetscCall(MatAXPY(Amat, -1, ts->Jacprhs, axpy)); 20333f72c5dSHong Zhang } 20433f72c5dSHong Zhang } 2059566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(TS_JacobianPEval, ts, U, Amat, 0)); 20633f72c5dSHong Zhang PetscFunctionReturn(0); 20733f72c5dSHong Zhang } 20833f72c5dSHong Zhang 20933f72c5dSHong Zhang /*@C 210814e85d6SHong Zhang TSSetCostIntegrand - Sets the routine for evaluating the integral term in one or more cost functions 211814e85d6SHong Zhang 212*bcf0153eSBarry Smith Logically Collective on ts 213814e85d6SHong Zhang 214814e85d6SHong Zhang Input Parameters: 215*bcf0153eSBarry Smith + ts - the `TS` context obtained from `TSCreate()` 216814e85d6SHong Zhang . numcost - number of gradients to be computed, this is the number of cost functions 217814e85d6SHong Zhang . costintegral - vector that stores the integral values 218814e85d6SHong Zhang . rf - routine for evaluating the integrand function 219c9ad9de0SHong Zhang . drduf - function that computes the gradients of the r's with respect to u 220814e85d6SHong Zhang . drdpf - function that computes the gradients of the r's with respect to p, can be NULL if parametric sensitivity is not desired (mu=NULL) 221814e85d6SHong Zhang . fwd - flag indicating whether to evaluate cost integral in the forward run or the adjoint run 222814e85d6SHong Zhang - ctx - [optional] user-defined context for private data for the function evaluation routine (may be NULL) 223814e85d6SHong Zhang 224814e85d6SHong Zhang Calling sequence of rf: 225c9ad9de0SHong Zhang $ PetscErrorCode rf(TS ts,PetscReal t,Vec U,Vec F,void *ctx); 226814e85d6SHong Zhang 227c9ad9de0SHong Zhang Calling sequence of drduf: 228c9ad9de0SHong Zhang $ PetscErroCode drduf(TS ts,PetscReal t,Vec U,Vec *dRdU,void *ctx); 229814e85d6SHong Zhang 230814e85d6SHong Zhang Calling sequence of drdpf: 231c9ad9de0SHong Zhang $ PetscErroCode drdpf(TS ts,PetscReal t,Vec U,Vec *dRdP,void *ctx); 232814e85d6SHong Zhang 233cd4cee2dSHong Zhang Level: deprecated 234814e85d6SHong Zhang 235*bcf0153eSBarry Smith Note: 236814e85d6SHong Zhang For optimization there is usually a single cost function (numcost = 1). For sensitivities there may be multiple cost functions 237814e85d6SHong Zhang 238*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TS`, `TSSetRHSJacobianP()`, `TSGetCostGradients()`, `TSSetCostGradients()` 239814e85d6SHong Zhang @*/ 240d71ae5a4SJacob Faibussowitsch PetscErrorCode TSSetCostIntegrand(TS ts, PetscInt numcost, Vec costintegral, PetscErrorCode (*rf)(TS, PetscReal, Vec, Vec, void *), PetscErrorCode (*drduf)(TS, PetscReal, Vec, Vec *, void *), PetscErrorCode (*drdpf)(TS, PetscReal, Vec, Vec *, void *), PetscBool fwd, void *ctx) 241d71ae5a4SJacob Faibussowitsch { 242814e85d6SHong Zhang PetscFunctionBegin; 243814e85d6SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 244814e85d6SHong Zhang if (costintegral) PetscValidHeaderSpecific(costintegral, VEC_CLASSID, 3); 2453c633725SBarry 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()"); 246814e85d6SHong Zhang if (!ts->numcost) ts->numcost = numcost; 247814e85d6SHong Zhang 248814e85d6SHong Zhang if (costintegral) { 2499566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)costintegral)); 2509566063dSJacob Faibussowitsch PetscCall(VecDestroy(&ts->vec_costintegral)); 251814e85d6SHong Zhang ts->vec_costintegral = costintegral; 252814e85d6SHong Zhang } else { 253814e85d6SHong Zhang if (!ts->vec_costintegral) { /* Create a seq vec if user does not provide one */ 2549566063dSJacob Faibussowitsch PetscCall(VecCreateSeq(PETSC_COMM_SELF, numcost, &ts->vec_costintegral)); 255814e85d6SHong Zhang } else { 2569566063dSJacob Faibussowitsch PetscCall(VecSet(ts->vec_costintegral, 0.0)); 257814e85d6SHong Zhang } 258814e85d6SHong Zhang } 259814e85d6SHong Zhang if (!ts->vec_costintegrand) { 2609566063dSJacob Faibussowitsch PetscCall(VecDuplicate(ts->vec_costintegral, &ts->vec_costintegrand)); 261814e85d6SHong Zhang } else { 2629566063dSJacob Faibussowitsch PetscCall(VecSet(ts->vec_costintegrand, 0.0)); 263814e85d6SHong Zhang } 264814e85d6SHong Zhang ts->costintegralfwd = fwd; /* Evaluate the cost integral in forward run if fwd is true */ 265814e85d6SHong Zhang ts->costintegrand = rf; 266814e85d6SHong Zhang ts->costintegrandctx = ctx; 267c9ad9de0SHong Zhang ts->drdufunction = drduf; 268814e85d6SHong Zhang ts->drdpfunction = drdpf; 269814e85d6SHong Zhang PetscFunctionReturn(0); 270814e85d6SHong Zhang } 271814e85d6SHong Zhang 272b5b4017aSHong Zhang /*@C 273814e85d6SHong Zhang TSGetCostIntegral - Returns the values of the integral term in the cost functions. 274814e85d6SHong Zhang It is valid to call the routine after a backward run. 275814e85d6SHong Zhang 276814e85d6SHong Zhang Not Collective 277814e85d6SHong Zhang 278814e85d6SHong Zhang Input Parameter: 279*bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()` 280814e85d6SHong Zhang 281814e85d6SHong Zhang Output Parameter: 282814e85d6SHong Zhang . v - the vector containing the integrals for each cost function 283814e85d6SHong Zhang 284814e85d6SHong Zhang Level: intermediate 285814e85d6SHong Zhang 286*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TS`, `TSAdjointSolve()`, ``TSSetCostIntegrand()` 287814e85d6SHong Zhang @*/ 288d71ae5a4SJacob Faibussowitsch PetscErrorCode TSGetCostIntegral(TS ts, Vec *v) 289d71ae5a4SJacob Faibussowitsch { 290cd4cee2dSHong Zhang TS quadts; 291cd4cee2dSHong Zhang 292814e85d6SHong Zhang PetscFunctionBegin; 293814e85d6SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 294814e85d6SHong Zhang PetscValidPointer(v, 2); 2959566063dSJacob Faibussowitsch PetscCall(TSGetQuadratureTS(ts, NULL, &quadts)); 296cd4cee2dSHong Zhang *v = quadts->vec_sol; 297814e85d6SHong Zhang PetscFunctionReturn(0); 298814e85d6SHong Zhang } 299814e85d6SHong Zhang 300b5b4017aSHong Zhang /*@C 301814e85d6SHong Zhang TSComputeCostIntegrand - Evaluates the integral function in the cost functions. 302814e85d6SHong Zhang 303814e85d6SHong Zhang Input Parameters: 304*bcf0153eSBarry Smith + ts - the `TS` context 305814e85d6SHong Zhang . t - current time 306c9ad9de0SHong Zhang - U - state vector, i.e. current solution 307814e85d6SHong Zhang 308814e85d6SHong Zhang Output Parameter: 309c9ad9de0SHong Zhang . Q - vector of size numcost to hold the outputs 310814e85d6SHong Zhang 311*bcf0153eSBarry Smith Level: deprecated 312*bcf0153eSBarry Smith 313*bcf0153eSBarry Smith Note: 314814e85d6SHong Zhang Most users should not need to explicitly call this routine, as it 315814e85d6SHong Zhang is used internally within the sensitivity analysis context. 316814e85d6SHong Zhang 317*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TS`, `TSAdjointSolve()`, `TSSetCostIntegrand()` 318814e85d6SHong Zhang @*/ 319d71ae5a4SJacob Faibussowitsch PetscErrorCode TSComputeCostIntegrand(TS ts, PetscReal t, Vec U, Vec Q) 320d71ae5a4SJacob Faibussowitsch { 321814e85d6SHong Zhang PetscFunctionBegin; 322814e85d6SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 323c9ad9de0SHong Zhang PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 324c9ad9de0SHong Zhang PetscValidHeaderSpecific(Q, VEC_CLASSID, 4); 325814e85d6SHong Zhang 3269566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(TS_FunctionEval, ts, U, Q, 0)); 327792fecdfSBarry Smith if (ts->costintegrand) PetscCallBack("TS callback integrand in the cost function", (*ts->costintegrand)(ts, t, U, Q, ts->costintegrandctx)); 328ef1023bdSBarry Smith else PetscCall(VecZeroEntries(Q)); 3299566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(TS_FunctionEval, ts, U, Q, 0)); 330814e85d6SHong Zhang PetscFunctionReturn(0); 331814e85d6SHong Zhang } 332814e85d6SHong Zhang 333b5b4017aSHong Zhang /*@C 334*bcf0153eSBarry Smith TSComputeDRDUFunction - Deprecated, use `TSGetQuadratureTS()` then `TSComputeRHSJacobian()` 335814e85d6SHong Zhang 336d76be551SHong Zhang Level: deprecated 337814e85d6SHong Zhang 338814e85d6SHong Zhang @*/ 339d71ae5a4SJacob Faibussowitsch PetscErrorCode TSComputeDRDUFunction(TS ts, PetscReal t, Vec U, Vec *DRDU) 340d71ae5a4SJacob Faibussowitsch { 341814e85d6SHong Zhang PetscFunctionBegin; 34233f72c5dSHong Zhang if (!DRDU) PetscFunctionReturn(0); 343814e85d6SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 344c9ad9de0SHong Zhang PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 345814e85d6SHong Zhang 346792fecdfSBarry Smith PetscCallBack("TS callback DRDU for sensitivity analysis", (*ts->drdufunction)(ts, t, U, DRDU, ts->costintegrandctx)); 347814e85d6SHong Zhang PetscFunctionReturn(0); 348814e85d6SHong Zhang } 349814e85d6SHong Zhang 350b5b4017aSHong Zhang /*@C 351*bcf0153eSBarry Smith TSComputeDRDPFunction - Deprecated, use `TSGetQuadratureTS()` then `TSComputeRHSJacobianP()` 352814e85d6SHong Zhang 353d76be551SHong Zhang Level: deprecated 354814e85d6SHong Zhang 355814e85d6SHong Zhang @*/ 356d71ae5a4SJacob Faibussowitsch PetscErrorCode TSComputeDRDPFunction(TS ts, PetscReal t, Vec U, Vec *DRDP) 357d71ae5a4SJacob Faibussowitsch { 358814e85d6SHong Zhang PetscFunctionBegin; 35933f72c5dSHong Zhang if (!DRDP) PetscFunctionReturn(0); 360814e85d6SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 361c9ad9de0SHong Zhang PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 362814e85d6SHong Zhang 363792fecdfSBarry Smith PetscCallBack("TS callback DRDP for sensitivity analysis", (*ts->drdpfunction)(ts, t, U, DRDP, ts->costintegrandctx)); 364814e85d6SHong Zhang PetscFunctionReturn(0); 365814e85d6SHong Zhang } 366814e85d6SHong Zhang 367b5b4017aSHong Zhang /*@C 368b5b4017aSHong 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. 369b5b4017aSHong Zhang 370*bcf0153eSBarry Smith Logically Collective on ts 371b5b4017aSHong Zhang 372b5b4017aSHong Zhang Input Parameters: 373*bcf0153eSBarry Smith + ts - `TS` context obtained from `TSCreate()` 374b5b4017aSHong Zhang . ihp1 - an array of vectors storing the result of vector-Hessian-vector product for F_UU 375b5b4017aSHong Zhang . hessianproductfunc1 - vector-Hessian-vector product function for F_UU 376b5b4017aSHong Zhang . ihp2 - an array of vectors storing the result of vector-Hessian-vector product for F_UP 377b5b4017aSHong Zhang . hessianproductfunc2 - vector-Hessian-vector product function for F_UP 378b5b4017aSHong Zhang . ihp3 - an array of vectors storing the result of vector-Hessian-vector product for F_PU 379b5b4017aSHong Zhang . hessianproductfunc3 - vector-Hessian-vector product function for F_PU 380b5b4017aSHong Zhang . ihp4 - an array of vectors storing the result of vector-Hessian-vector product for F_PP 381f0fc11ceSJed Brown - hessianproductfunc4 - vector-Hessian-vector product function for F_PP 382b5b4017aSHong Zhang 383b5b4017aSHong Zhang Calling sequence of ihessianproductfunc: 384369cf35fSHong Zhang $ ihessianproductfunc (TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV,void *ctx); 385b5b4017aSHong Zhang + t - current timestep 386b5b4017aSHong Zhang . U - input vector (current ODE solution) 387369cf35fSHong Zhang . Vl - an array of input vectors to be left-multiplied with the Hessian 388b5b4017aSHong Zhang . Vr - input vector to be right-multiplied with the Hessian 389369cf35fSHong Zhang . VHV - an array of output vectors for vector-Hessian-vector product 390b5b4017aSHong Zhang - ctx - [optional] user-defined function context 391b5b4017aSHong Zhang 392b5b4017aSHong Zhang Level: intermediate 393b5b4017aSHong Zhang 394369cf35fSHong Zhang Notes: 395369cf35fSHong Zhang The first Hessian function and the working array are required. 396369cf35fSHong Zhang As an example to implement the callback functions, the second callback function calculates the vector-Hessian-vector product 397369cf35fSHong Zhang $ Vl_n^T*F_UP*Vr 398369cf35fSHong 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. 399369cf35fSHong Zhang Each entry of F_UP corresponds to the derivative 400369cf35fSHong Zhang $ F_UP[i][j][k] = \frac{\partial^2 F[i]}{\partial U[j] \partial P[k]}. 401369cf35fSHong 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 402369cf35fSHong Zhang $ VHV_n[j] = \sum_i \sum_k {Vl_n[i] * F_UP[i][j][k] * Vr[k]} 403369cf35fSHong Zhang If the cost function is a scalar, there will be only one vector in Vl and VHV. 404b5b4017aSHong Zhang 405*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TS` 406b5b4017aSHong Zhang @*/ 407d71ae5a4SJacob Faibussowitsch PetscErrorCode TSSetIHessianProduct(TS ts, Vec *ihp1, PetscErrorCode (*ihessianproductfunc1)(TS, PetscReal, Vec, Vec *, Vec, Vec *, void *), 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) 408d71ae5a4SJacob Faibussowitsch { 409b5b4017aSHong Zhang PetscFunctionBegin; 410b5b4017aSHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 411b5b4017aSHong Zhang PetscValidPointer(ihp1, 2); 412b5b4017aSHong Zhang 413b5b4017aSHong Zhang ts->ihessianproductctx = ctx; 414b5b4017aSHong Zhang if (ihp1) ts->vecs_fuu = ihp1; 415b5b4017aSHong Zhang if (ihp2) ts->vecs_fup = ihp2; 416b5b4017aSHong Zhang if (ihp3) ts->vecs_fpu = ihp3; 417b5b4017aSHong Zhang if (ihp4) ts->vecs_fpp = ihp4; 418b5b4017aSHong Zhang ts->ihessianproduct_fuu = ihessianproductfunc1; 419b5b4017aSHong Zhang ts->ihessianproduct_fup = ihessianproductfunc2; 420b5b4017aSHong Zhang ts->ihessianproduct_fpu = ihessianproductfunc3; 421b5b4017aSHong Zhang ts->ihessianproduct_fpp = ihessianproductfunc4; 422b5b4017aSHong Zhang PetscFunctionReturn(0); 423b5b4017aSHong Zhang } 424b5b4017aSHong Zhang 425b5b4017aSHong Zhang /*@C 426b1e111ebSHong Zhang TSComputeIHessianProductFunctionUU - Runs the user-defined vector-Hessian-vector product function for Fuu. 427b5b4017aSHong Zhang 428*bcf0153eSBarry Smith Collective on ts 429b5b4017aSHong Zhang 430b5b4017aSHong Zhang Input Parameters: 431*bcf0153eSBarry Smith . ts - The `TS` context obtained from `TSCreate()` 432b5b4017aSHong Zhang 433b5b4017aSHong Zhang Level: developer 434b5b4017aSHong Zhang 435*bcf0153eSBarry Smith Note: 436*bcf0153eSBarry Smith `TSComputeIHessianProductFunctionUU()` is typically used for sensitivity implementation, 437*bcf0153eSBarry Smith so most users would not generally call this routine themselves. 438*bcf0153eSBarry Smith 439*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TSSetIHessianProduct()` 440b5b4017aSHong Zhang @*/ 441d71ae5a4SJacob Faibussowitsch PetscErrorCode TSComputeIHessianProductFunctionUU(TS ts, PetscReal t, Vec U, Vec *Vl, Vec Vr, Vec *VHV) 442d71ae5a4SJacob Faibussowitsch { 443b5b4017aSHong Zhang PetscFunctionBegin; 44433f72c5dSHong Zhang if (!VHV) PetscFunctionReturn(0); 445b5b4017aSHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 446b5b4017aSHong Zhang PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 447b5b4017aSHong Zhang 448792fecdfSBarry Smith if (ts->ihessianproduct_fuu) PetscCallBack("TS callback IHessianProduct 1 for sensitivity analysis", (*ts->ihessianproduct_fuu)(ts, t, U, Vl, Vr, VHV, ts->ihessianproductctx)); 449ef1023bdSBarry Smith 45067633408SHong Zhang /* does not consider IMEX for now, so either IHessian or RHSHessian will be calculated, using the same output VHV */ 45167633408SHong Zhang if (ts->rhshessianproduct_guu) { 45267633408SHong Zhang PetscInt nadj; 4539566063dSJacob Faibussowitsch PetscCall(TSComputeRHSHessianProductFunctionUU(ts, t, U, Vl, Vr, VHV)); 45448a46eb9SPierre Jolivet for (nadj = 0; nadj < ts->numcost; nadj++) PetscCall(VecScale(VHV[nadj], -1)); 45567633408SHong Zhang } 456b5b4017aSHong Zhang PetscFunctionReturn(0); 457b5b4017aSHong Zhang } 458b5b4017aSHong Zhang 459b5b4017aSHong Zhang /*@C 460b1e111ebSHong Zhang TSComputeIHessianProductFunctionUP - Runs the user-defined vector-Hessian-vector product function for Fup. 461b5b4017aSHong Zhang 462*bcf0153eSBarry Smith Collective on ts 463b5b4017aSHong Zhang 464b5b4017aSHong Zhang Input Parameters: 465*bcf0153eSBarry Smith . ts - The `TS` context obtained from `TSCreate()` 466b5b4017aSHong Zhang 467b5b4017aSHong Zhang Level: developer 468b5b4017aSHong Zhang 469*bcf0153eSBarry Smith Note: 470*bcf0153eSBarry Smith `TSComputeIHessianProductFunctionUP()` is typically used for sensitivity implementation, 471*bcf0153eSBarry Smith so most users would not generally call this routine themselves. 472*bcf0153eSBarry Smith 473*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TSSetIHessianProduct()` 474b5b4017aSHong Zhang @*/ 475d71ae5a4SJacob Faibussowitsch PetscErrorCode TSComputeIHessianProductFunctionUP(TS ts, PetscReal t, Vec U, Vec *Vl, Vec Vr, Vec *VHV) 476d71ae5a4SJacob Faibussowitsch { 477b5b4017aSHong Zhang PetscFunctionBegin; 47833f72c5dSHong Zhang if (!VHV) PetscFunctionReturn(0); 479b5b4017aSHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 480b5b4017aSHong Zhang PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 481b5b4017aSHong Zhang 482792fecdfSBarry Smith if (ts->ihessianproduct_fup) PetscCallBack("TS callback IHessianProduct 2 for sensitivity analysis", (*ts->ihessianproduct_fup)(ts, t, U, Vl, Vr, VHV, ts->ihessianproductctx)); 483ef1023bdSBarry Smith 48467633408SHong Zhang /* does not consider IMEX for now, so either IHessian or RHSHessian will be calculated, using the same output VHV */ 48567633408SHong Zhang if (ts->rhshessianproduct_gup) { 48667633408SHong Zhang PetscInt nadj; 4879566063dSJacob Faibussowitsch PetscCall(TSComputeRHSHessianProductFunctionUP(ts, t, U, Vl, Vr, VHV)); 48848a46eb9SPierre Jolivet for (nadj = 0; nadj < ts->numcost; nadj++) PetscCall(VecScale(VHV[nadj], -1)); 48967633408SHong Zhang } 490b5b4017aSHong Zhang PetscFunctionReturn(0); 491b5b4017aSHong Zhang } 492b5b4017aSHong Zhang 493b5b4017aSHong Zhang /*@C 494b1e111ebSHong Zhang TSComputeIHessianProductFunctionPU - Runs the user-defined vector-Hessian-vector product function for Fpu. 495b5b4017aSHong Zhang 496*bcf0153eSBarry Smith Collective on ts 497b5b4017aSHong Zhang 498b5b4017aSHong Zhang Input Parameters: 499*bcf0153eSBarry Smith . ts - The `TS` context obtained from `TSCreate()` 500b5b4017aSHong Zhang 501b5b4017aSHong Zhang Level: developer 502b5b4017aSHong Zhang 503*bcf0153eSBarry Smith Note: 504*bcf0153eSBarry Smith `TSComputeIHessianProductFunctionPU()` is typically used for sensitivity implementation, 505*bcf0153eSBarry Smith so most users would not generally call this routine themselves. 506*bcf0153eSBarry Smith 507*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TSSetIHessianProduct()` 508b5b4017aSHong Zhang @*/ 509d71ae5a4SJacob Faibussowitsch PetscErrorCode TSComputeIHessianProductFunctionPU(TS ts, PetscReal t, Vec U, Vec *Vl, Vec Vr, Vec *VHV) 510d71ae5a4SJacob Faibussowitsch { 511b5b4017aSHong Zhang PetscFunctionBegin; 51233f72c5dSHong Zhang if (!VHV) PetscFunctionReturn(0); 513b5b4017aSHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 514b5b4017aSHong Zhang PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 515b5b4017aSHong Zhang 516792fecdfSBarry Smith if (ts->ihessianproduct_fpu) PetscCallBack("TS callback IHessianProduct 3 for sensitivity analysis", (*ts->ihessianproduct_fpu)(ts, t, U, Vl, Vr, VHV, ts->ihessianproductctx)); 517ef1023bdSBarry Smith 51867633408SHong Zhang /* does not consider IMEX for now, so either IHessian or RHSHessian will be calculated, using the same output VHV */ 51967633408SHong Zhang if (ts->rhshessianproduct_gpu) { 52067633408SHong Zhang PetscInt nadj; 5219566063dSJacob Faibussowitsch PetscCall(TSComputeRHSHessianProductFunctionPU(ts, t, U, Vl, Vr, VHV)); 52248a46eb9SPierre Jolivet for (nadj = 0; nadj < ts->numcost; nadj++) PetscCall(VecScale(VHV[nadj], -1)); 52367633408SHong Zhang } 524b5b4017aSHong Zhang PetscFunctionReturn(0); 525b5b4017aSHong Zhang } 526b5b4017aSHong Zhang 527b5b4017aSHong Zhang /*@C 528b1e111ebSHong Zhang TSComputeIHessianProductFunctionPP - Runs the user-defined vector-Hessian-vector product function for Fpp. 529b5b4017aSHong Zhang 530*bcf0153eSBarry Smith Collective on ts 531b5b4017aSHong Zhang 532b5b4017aSHong Zhang Input Parameters: 533*bcf0153eSBarry Smith . ts - The `TS` context obtained from `TSCreate()` 534b5b4017aSHong Zhang 535b5b4017aSHong Zhang Level: developer 536b5b4017aSHong Zhang 537*bcf0153eSBarry Smith Note: 538*bcf0153eSBarry Smith `TSComputeIHessianProductFunctionPP()` is typically used for sensitivity implementation, 539*bcf0153eSBarry Smith so most users would not generally call this routine themselves. 540*bcf0153eSBarry Smith 541*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TSSetIHessianProduct()` 542b5b4017aSHong Zhang @*/ 543d71ae5a4SJacob Faibussowitsch PetscErrorCode TSComputeIHessianProductFunctionPP(TS ts, PetscReal t, Vec U, Vec *Vl, Vec Vr, Vec *VHV) 544d71ae5a4SJacob Faibussowitsch { 545b5b4017aSHong Zhang PetscFunctionBegin; 54633f72c5dSHong Zhang if (!VHV) PetscFunctionReturn(0); 547b5b4017aSHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 548b5b4017aSHong Zhang PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 549b5b4017aSHong Zhang 550792fecdfSBarry Smith if (ts->ihessianproduct_fpp) PetscCallBack("TS callback IHessianProduct 3 for sensitivity analysis", (*ts->ihessianproduct_fpp)(ts, t, U, Vl, Vr, VHV, ts->ihessianproductctx)); 551ef1023bdSBarry Smith 55267633408SHong Zhang /* does not consider IMEX for now, so either IHessian or RHSHessian will be calculated, using the same output VHV */ 55367633408SHong Zhang if (ts->rhshessianproduct_gpp) { 55467633408SHong Zhang PetscInt nadj; 5559566063dSJacob Faibussowitsch PetscCall(TSComputeRHSHessianProductFunctionPP(ts, t, U, Vl, Vr, VHV)); 55648a46eb9SPierre Jolivet for (nadj = 0; nadj < ts->numcost; nadj++) PetscCall(VecScale(VHV[nadj], -1)); 55767633408SHong Zhang } 558b5b4017aSHong Zhang PetscFunctionReturn(0); 559b5b4017aSHong Zhang } 560b5b4017aSHong Zhang 56113af1a74SHong Zhang /*@C 5624c500f23SPierre Jolivet TSSetRHSHessianProduct - Sets the function that computes the vector-Hessian-vector product. The Hessian is the second-order derivative of G (RHSFunction) w.r.t. the state variable. 56313af1a74SHong Zhang 564*bcf0153eSBarry Smith Logically Collective on ts 56513af1a74SHong Zhang 56613af1a74SHong Zhang Input Parameters: 567*bcf0153eSBarry Smith + ts - `TS` context obtained from `TSCreate()` 56813af1a74SHong Zhang . rhshp1 - an array of vectors storing the result of vector-Hessian-vector product for G_UU 56913af1a74SHong Zhang . hessianproductfunc1 - vector-Hessian-vector product function for G_UU 57013af1a74SHong Zhang . rhshp2 - an array of vectors storing the result of vector-Hessian-vector product for G_UP 57113af1a74SHong Zhang . hessianproductfunc2 - vector-Hessian-vector product function for G_UP 57213af1a74SHong Zhang . rhshp3 - an array of vectors storing the result of vector-Hessian-vector product for G_PU 57313af1a74SHong Zhang . hessianproductfunc3 - vector-Hessian-vector product function for G_PU 57413af1a74SHong Zhang . rhshp4 - an array of vectors storing the result of vector-Hessian-vector product for G_PP 575f0fc11ceSJed Brown - hessianproductfunc4 - vector-Hessian-vector product function for G_PP 57613af1a74SHong Zhang 57713af1a74SHong Zhang Calling sequence of ihessianproductfunc: 578369cf35fSHong Zhang $ rhshessianproductfunc (TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV,void *ctx); 57913af1a74SHong Zhang + t - current timestep 58013af1a74SHong Zhang . U - input vector (current ODE solution) 581369cf35fSHong Zhang . Vl - an array of input vectors to be left-multiplied with the Hessian 58213af1a74SHong Zhang . Vr - input vector to be right-multiplied with the Hessian 583369cf35fSHong Zhang . VHV - an array of output vectors for vector-Hessian-vector product 58413af1a74SHong Zhang - ctx - [optional] user-defined function context 58513af1a74SHong Zhang 58613af1a74SHong Zhang Level: intermediate 58713af1a74SHong Zhang 588369cf35fSHong Zhang Notes: 589369cf35fSHong Zhang The first Hessian function and the working array are required. 590369cf35fSHong Zhang As an example to implement the callback functions, the second callback function calculates the vector-Hessian-vector product 591369cf35fSHong Zhang $ Vl_n^T*G_UP*Vr 592369cf35fSHong 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. 593369cf35fSHong Zhang Each entry of G_UP corresponds to the derivative 594369cf35fSHong Zhang $ G_UP[i][j][k] = \frac{\partial^2 G[i]}{\partial U[j] \partial P[k]}. 595369cf35fSHong 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 596369cf35fSHong Zhang $ VHV_n[j] = \sum_i \sum_k {Vl_n[i] * G_UP[i][j][k] * Vr[k]} 597369cf35fSHong Zhang If the cost function is a scalar, there will be only one vector in Vl and VHV. 59813af1a74SHong Zhang 599*bcf0153eSBarry Smith .seealso: `TS` 60013af1a74SHong Zhang @*/ 601d71ae5a4SJacob Faibussowitsch PetscErrorCode TSSetRHSHessianProduct(TS ts, Vec *rhshp1, PetscErrorCode (*rhshessianproductfunc1)(TS, PetscReal, Vec, Vec *, Vec, Vec *, void *), 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) 602d71ae5a4SJacob Faibussowitsch { 60313af1a74SHong Zhang PetscFunctionBegin; 60413af1a74SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 60513af1a74SHong Zhang PetscValidPointer(rhshp1, 2); 60613af1a74SHong Zhang 60713af1a74SHong Zhang ts->rhshessianproductctx = ctx; 60813af1a74SHong Zhang if (rhshp1) ts->vecs_guu = rhshp1; 60913af1a74SHong Zhang if (rhshp2) ts->vecs_gup = rhshp2; 61013af1a74SHong Zhang if (rhshp3) ts->vecs_gpu = rhshp3; 61113af1a74SHong Zhang if (rhshp4) ts->vecs_gpp = rhshp4; 61213af1a74SHong Zhang ts->rhshessianproduct_guu = rhshessianproductfunc1; 61313af1a74SHong Zhang ts->rhshessianproduct_gup = rhshessianproductfunc2; 61413af1a74SHong Zhang ts->rhshessianproduct_gpu = rhshessianproductfunc3; 61513af1a74SHong Zhang ts->rhshessianproduct_gpp = rhshessianproductfunc4; 61613af1a74SHong Zhang PetscFunctionReturn(0); 61713af1a74SHong Zhang } 61813af1a74SHong Zhang 61913af1a74SHong Zhang /*@C 620b1e111ebSHong Zhang TSComputeRHSHessianProductFunctionUU - Runs the user-defined vector-Hessian-vector product function for Guu. 62113af1a74SHong Zhang 622*bcf0153eSBarry Smith Collective on ts 62313af1a74SHong Zhang 62413af1a74SHong Zhang Input Parameters: 625*bcf0153eSBarry Smith . ts - The `TS` context obtained from `TSCreate()` 62613af1a74SHong Zhang 62713af1a74SHong Zhang Level: developer 62813af1a74SHong Zhang 629*bcf0153eSBarry Smith Note: 630*bcf0153eSBarry Smith `TSComputeRHSHessianProductFunctionUU()` is typically used for sensitivity implementation, 631*bcf0153eSBarry Smith so most users would not generally call this routine themselves. 632*bcf0153eSBarry Smith 633*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TS`, `TSSetRHSHessianProduct()` 63413af1a74SHong Zhang @*/ 635d71ae5a4SJacob Faibussowitsch PetscErrorCode TSComputeRHSHessianProductFunctionUU(TS ts, PetscReal t, Vec U, Vec *Vl, Vec Vr, Vec *VHV) 636d71ae5a4SJacob Faibussowitsch { 63713af1a74SHong Zhang PetscFunctionBegin; 63813af1a74SHong Zhang if (!VHV) PetscFunctionReturn(0); 63913af1a74SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 64013af1a74SHong Zhang PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 64113af1a74SHong Zhang 642792fecdfSBarry Smith PetscCallBack("TS callback RHSHessianProduct 1 for sensitivity analysis", (*ts->rhshessianproduct_guu)(ts, t, U, Vl, Vr, VHV, ts->rhshessianproductctx)); 64313af1a74SHong Zhang PetscFunctionReturn(0); 64413af1a74SHong Zhang } 64513af1a74SHong Zhang 64613af1a74SHong Zhang /*@C 647b1e111ebSHong Zhang TSComputeRHSHessianProductFunctionUP - Runs the user-defined vector-Hessian-vector product function for Gup. 64813af1a74SHong Zhang 649*bcf0153eSBarry Smith Collective on ts 65013af1a74SHong Zhang 65113af1a74SHong Zhang Input Parameters: 652*bcf0153eSBarry Smith . ts - The `TS` context obtained from `TSCreate()` 65313af1a74SHong Zhang 65413af1a74SHong Zhang Level: developer 65513af1a74SHong Zhang 656*bcf0153eSBarry Smith Note: 657*bcf0153eSBarry Smith `TSComputeRHSHessianProductFunctionUP()` is typically used for sensitivity implementation, 658*bcf0153eSBarry Smith so most users would not generally call this routine themselves. 659*bcf0153eSBarry Smith 660*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TS`, `TSSetRHSHessianProduct()` 66113af1a74SHong Zhang @*/ 662d71ae5a4SJacob Faibussowitsch PetscErrorCode TSComputeRHSHessianProductFunctionUP(TS ts, PetscReal t, Vec U, Vec *Vl, Vec Vr, Vec *VHV) 663d71ae5a4SJacob Faibussowitsch { 66413af1a74SHong Zhang PetscFunctionBegin; 66513af1a74SHong Zhang if (!VHV) PetscFunctionReturn(0); 66613af1a74SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 66713af1a74SHong Zhang PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 66813af1a74SHong Zhang 669792fecdfSBarry Smith PetscCallBack("TS callback RHSHessianProduct 2 for sensitivity analysis", (*ts->rhshessianproduct_gup)(ts, t, U, Vl, Vr, VHV, ts->rhshessianproductctx)); 67013af1a74SHong Zhang PetscFunctionReturn(0); 67113af1a74SHong Zhang } 67213af1a74SHong Zhang 67313af1a74SHong Zhang /*@C 674b1e111ebSHong Zhang TSComputeRHSHessianProductFunctionPU - Runs the user-defined vector-Hessian-vector product function for Gpu. 67513af1a74SHong Zhang 676*bcf0153eSBarry Smith Collective on ts 67713af1a74SHong Zhang 67813af1a74SHong Zhang Input Parameters: 679*bcf0153eSBarry Smith . ts - The `TS` context obtained from `TSCreate()` 68013af1a74SHong Zhang 68113af1a74SHong Zhang Level: developer 68213af1a74SHong Zhang 683*bcf0153eSBarry Smith Note: 684*bcf0153eSBarry Smith `TSComputeRHSHessianProductFunctionPU()` is typically used for sensitivity implementation, 685*bcf0153eSBarry Smith so most users would not generally call this routine themselves. 686*bcf0153eSBarry Smith 687*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TSSetRHSHessianProduct()` 68813af1a74SHong Zhang @*/ 689d71ae5a4SJacob Faibussowitsch PetscErrorCode TSComputeRHSHessianProductFunctionPU(TS ts, PetscReal t, Vec U, Vec *Vl, Vec Vr, Vec *VHV) 690d71ae5a4SJacob Faibussowitsch { 69113af1a74SHong Zhang PetscFunctionBegin; 69213af1a74SHong Zhang if (!VHV) PetscFunctionReturn(0); 69313af1a74SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 69413af1a74SHong Zhang PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 69513af1a74SHong Zhang 696792fecdfSBarry Smith PetscCallBack("TS callback RHSHessianProduct 3 for sensitivity analysis", (*ts->rhshessianproduct_gpu)(ts, t, U, Vl, Vr, VHV, ts->rhshessianproductctx)); 69713af1a74SHong Zhang PetscFunctionReturn(0); 69813af1a74SHong Zhang } 69913af1a74SHong Zhang 70013af1a74SHong Zhang /*@C 701b1e111ebSHong Zhang TSComputeRHSHessianProductFunctionPP - Runs the user-defined vector-Hessian-vector product function for Gpp. 70213af1a74SHong Zhang 703*bcf0153eSBarry Smith Collective on ts 70413af1a74SHong Zhang 70513af1a74SHong Zhang Input Parameters: 706*bcf0153eSBarry Smith . ts - The `TS` context obtained from `TSCreate()` 70713af1a74SHong Zhang 70813af1a74SHong Zhang Level: developer 70913af1a74SHong Zhang 710*bcf0153eSBarry Smith Note: 711*bcf0153eSBarry Smith `TSComputeRHSHessianProductFunctionPP()` is typically used for sensitivity implementation, 712*bcf0153eSBarry Smith so most users would not generally call this routine themselves. 713*bcf0153eSBarry Smith 714*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TSSetRHSHessianProduct()` 71513af1a74SHong Zhang @*/ 716d71ae5a4SJacob Faibussowitsch PetscErrorCode TSComputeRHSHessianProductFunctionPP(TS ts, PetscReal t, Vec U, Vec *Vl, Vec Vr, Vec *VHV) 717d71ae5a4SJacob Faibussowitsch { 71813af1a74SHong Zhang PetscFunctionBegin; 71913af1a74SHong Zhang if (!VHV) PetscFunctionReturn(0); 72013af1a74SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 72113af1a74SHong Zhang PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 72213af1a74SHong Zhang 723792fecdfSBarry Smith PetscCallBack("TS callback RHSHessianProduct 3 for sensitivity analysis", (*ts->rhshessianproduct_gpp)(ts, t, U, Vl, Vr, VHV, ts->rhshessianproductctx)); 72413af1a74SHong Zhang PetscFunctionReturn(0); 72513af1a74SHong Zhang } 72613af1a74SHong Zhang 727814e85d6SHong Zhang /* --------------------------- Adjoint sensitivity ---------------------------*/ 728814e85d6SHong Zhang 729814e85d6SHong Zhang /*@ 730814e85d6SHong 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 731*bcf0153eSBarry Smith for use by the `TS` adjoint routines. 732814e85d6SHong Zhang 733*bcf0153eSBarry Smith Logically Collective on ts 734814e85d6SHong Zhang 735814e85d6SHong Zhang Input Parameters: 736*bcf0153eSBarry Smith + ts - the `TS` context obtained from `TSCreate()` 737d2fd7bfcSHong Zhang . numcost - number of gradients to be computed, this is the number of cost functions 738814e85d6SHong 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 739814e85d6SHong Zhang - mu - gradients with respect to the parameters, the number of entries in these vectors is the same as the number of parameters 740814e85d6SHong Zhang 741814e85d6SHong Zhang Level: beginner 742814e85d6SHong Zhang 743814e85d6SHong Zhang Notes: 744814e85d6SHong Zhang the entries in these vectors must be correctly initialized with the values lamda_i = df/dy|finaltime mu_i = df/dp|finaltime 745814e85d6SHong Zhang 746*bcf0153eSBarry Smith After `TSAdjointSolve()` is called the lamba and the mu contain the computed sensitivities 747814e85d6SHong Zhang 748*bcf0153eSBarry Smith .seealso: `TS`, `TSAdjointSolve()`, `TSGetCostGradients()` 749814e85d6SHong Zhang @*/ 750d71ae5a4SJacob Faibussowitsch PetscErrorCode TSSetCostGradients(TS ts, PetscInt numcost, Vec *lambda, Vec *mu) 751d71ae5a4SJacob Faibussowitsch { 752814e85d6SHong Zhang PetscFunctionBegin; 753814e85d6SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 754064a246eSJacob Faibussowitsch PetscValidPointer(lambda, 3); 755814e85d6SHong Zhang ts->vecs_sensi = lambda; 756814e85d6SHong Zhang ts->vecs_sensip = mu; 7573c633725SBarry 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"); 758814e85d6SHong Zhang ts->numcost = numcost; 759814e85d6SHong Zhang PetscFunctionReturn(0); 760814e85d6SHong Zhang } 761814e85d6SHong Zhang 762814e85d6SHong Zhang /*@ 763*bcf0153eSBarry Smith TSGetCostGradients - Returns the gradients from the `TSAdjointSolve()` 764814e85d6SHong Zhang 765*bcf0153eSBarry Smith Not Collective, but the vectors returned are parallel if `TS` is parallel 766814e85d6SHong Zhang 767814e85d6SHong Zhang Input Parameter: 768*bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()` 769814e85d6SHong Zhang 770d8d19677SJose E. Roman Output Parameters: 7716b867d5aSJose E. Roman + numcost - size of returned arrays 7726b867d5aSJose E. Roman . lambda - vectors containing the gradients of the cost functions with respect to the ODE/DAE solution variables 773814e85d6SHong Zhang - mu - vectors containing the gradients of the cost functions with respect to the problem parameters 774814e85d6SHong Zhang 775814e85d6SHong Zhang Level: intermediate 776814e85d6SHong Zhang 777*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TS`, `TSAdjointSolve()`, `TSSetCostGradients()` 778814e85d6SHong Zhang @*/ 779d71ae5a4SJacob Faibussowitsch PetscErrorCode TSGetCostGradients(TS ts, PetscInt *numcost, Vec **lambda, Vec **mu) 780d71ae5a4SJacob Faibussowitsch { 781814e85d6SHong Zhang PetscFunctionBegin; 782814e85d6SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 783814e85d6SHong Zhang if (numcost) *numcost = ts->numcost; 784814e85d6SHong Zhang if (lambda) *lambda = ts->vecs_sensi; 785814e85d6SHong Zhang if (mu) *mu = ts->vecs_sensip; 786814e85d6SHong Zhang PetscFunctionReturn(0); 787814e85d6SHong Zhang } 788814e85d6SHong Zhang 789814e85d6SHong Zhang /*@ 790b5b4017aSHong 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 791*bcf0153eSBarry Smith for use by the `TS` adjoint routines. 792b5b4017aSHong Zhang 793*bcf0153eSBarry Smith Logically Collective on ts 794b5b4017aSHong Zhang 795b5b4017aSHong Zhang Input Parameters: 796*bcf0153eSBarry Smith + ts - the `TS` context obtained from `TSCreate()` 797b5b4017aSHong Zhang . numcost - number of cost functions 798b5b4017aSHong 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 799b5b4017aSHong 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 800b5b4017aSHong Zhang - dir - the direction vector that are multiplied with the Hessian of the cost functions 801b5b4017aSHong Zhang 802b5b4017aSHong Zhang Level: beginner 803b5b4017aSHong Zhang 804*bcf0153eSBarry Smith Notes: 805*bcf0153eSBarry Smith Hessian of the cost function is completely different from Hessian of the ODE/DAE system 806b5b4017aSHong Zhang 807*bcf0153eSBarry Smith For second-order adjoint, one needs to call this function and then `TSAdjointSetForward()` before `TSSolve()`. 808b5b4017aSHong Zhang 809*bcf0153eSBarry Smith After `TSAdjointSolve()` is called, the lamba2 and the mu2 will contain the computed second-order adjoint sensitivities, and can be used to produce Hessian-vector product (not the full Hessian matrix). Users must provide a direction vector; it is usually generated by an optimization solver. 810b5b4017aSHong Zhang 8113fca9621SHong Zhang Passing NULL for lambda2 disables the second-order calculation. 812*bcf0153eSBarry Smith 813*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TS`, `TSAdjointSolve()`, `TSAdjointSetForward()` 814b5b4017aSHong Zhang @*/ 815d71ae5a4SJacob Faibussowitsch PetscErrorCode TSSetCostHessianProducts(TS ts, PetscInt numcost, Vec *lambda2, Vec *mu2, Vec dir) 816d71ae5a4SJacob Faibussowitsch { 817b5b4017aSHong Zhang PetscFunctionBegin; 818b5b4017aSHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 8193c633725SBarry 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"); 820b5b4017aSHong Zhang ts->numcost = numcost; 821b5b4017aSHong Zhang ts->vecs_sensi2 = lambda2; 82233f72c5dSHong Zhang ts->vecs_sensi2p = mu2; 823b5b4017aSHong Zhang ts->vec_dir = dir; 824b5b4017aSHong Zhang PetscFunctionReturn(0); 825b5b4017aSHong Zhang } 826b5b4017aSHong Zhang 827b5b4017aSHong Zhang /*@ 828*bcf0153eSBarry Smith TSGetCostHessianProducts - Returns the gradients from the `TSAdjointSolve()` 829b5b4017aSHong Zhang 830*bcf0153eSBarry Smith Not Collective, but vectors returned are parallel if `TS` is parallel 831b5b4017aSHong Zhang 832b5b4017aSHong Zhang Input Parameter: 833*bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()` 834b5b4017aSHong Zhang 835d8d19677SJose E. Roman Output Parameters: 836b5b4017aSHong Zhang + numcost - number of cost functions 837b5b4017aSHong 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 838b5b4017aSHong 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 839b5b4017aSHong Zhang - dir - the direction vector that are multiplied with the Hessian of the cost functions 840b5b4017aSHong Zhang 841b5b4017aSHong Zhang Level: intermediate 842b5b4017aSHong Zhang 843*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TSAdjointSolve()`, `TSSetCostHessianProducts()` 844b5b4017aSHong Zhang @*/ 845d71ae5a4SJacob Faibussowitsch PetscErrorCode TSGetCostHessianProducts(TS ts, PetscInt *numcost, Vec **lambda2, Vec **mu2, Vec *dir) 846d71ae5a4SJacob Faibussowitsch { 847b5b4017aSHong Zhang PetscFunctionBegin; 848b5b4017aSHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 849b5b4017aSHong Zhang if (numcost) *numcost = ts->numcost; 850b5b4017aSHong Zhang if (lambda2) *lambda2 = ts->vecs_sensi2; 85133f72c5dSHong Zhang if (mu2) *mu2 = ts->vecs_sensi2p; 852b5b4017aSHong Zhang if (dir) *dir = ts->vec_dir; 853b5b4017aSHong Zhang PetscFunctionReturn(0); 854b5b4017aSHong Zhang } 855b5b4017aSHong Zhang 856b5b4017aSHong Zhang /*@ 857ecf68647SHong Zhang TSAdjointSetForward - Trigger the tangent linear solver and initialize the forward sensitivities 858b5b4017aSHong Zhang 859*bcf0153eSBarry Smith Logically Collective on ts 860b5b4017aSHong Zhang 861b5b4017aSHong Zhang Input Parameters: 862*bcf0153eSBarry Smith + ts - the `TS` context obtained from `TSCreate()` 863b5b4017aSHong Zhang - didp - the derivative of initial values w.r.t. parameters 864b5b4017aSHong Zhang 865b5b4017aSHong Zhang Level: intermediate 866b5b4017aSHong Zhang 867*bcf0153eSBarry Smith Notes: 868*bcf0153eSBarry Smith When computing sensitivies w.r.t. initial condition, set didp to NULL so that the solver will take it as an identity matrix mathematically. 869*bcf0153eSBarry Smith `TS` adjoint does not reset the tangent linear solver automatically, `TSAdjointResetForward()` should be called to reset the tangent linear solver. 870b5b4017aSHong Zhang 871*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TSAdjointSolve()`, `TSSetCostHessianProducts()`, `TSAdjointResetForward()` 872b5b4017aSHong Zhang @*/ 873d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointSetForward(TS ts, Mat didp) 874d71ae5a4SJacob Faibussowitsch { 87533f72c5dSHong Zhang Mat A; 87633f72c5dSHong Zhang Vec sp; 87733f72c5dSHong Zhang PetscScalar *xarr; 87833f72c5dSHong Zhang PetscInt lsize; 879b5b4017aSHong Zhang 880b5b4017aSHong Zhang PetscFunctionBegin; 881b5b4017aSHong Zhang ts->forward_solve = PETSC_TRUE; /* turn on tangent linear mode */ 8823c633725SBarry Smith PetscCheck(ts->vecs_sensi2, PetscObjectComm((PetscObject)ts), PETSC_ERR_USER, "Must call TSSetCostHessianProducts() first"); 8833c633725SBarry Smith PetscCheck(ts->vec_dir, PetscObjectComm((PetscObject)ts), PETSC_ERR_USER, "Directional vector is missing. Call TSSetCostHessianProducts() to set it."); 88433f72c5dSHong Zhang /* create a single-column dense matrix */ 8859566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(ts->vec_sol, &lsize)); 8869566063dSJacob Faibussowitsch PetscCall(MatCreateDense(PetscObjectComm((PetscObject)ts), lsize, PETSC_DECIDE, PETSC_DECIDE, 1, NULL, &A)); 88733f72c5dSHong Zhang 8889566063dSJacob Faibussowitsch PetscCall(VecDuplicate(ts->vec_sol, &sp)); 8899566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumn(A, 0, &xarr)); 8909566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(sp, xarr)); 891ecf68647SHong Zhang if (ts->vecs_sensi2p) { /* tangent linear variable initialized as 2*dIdP*dir */ 89233f72c5dSHong Zhang if (didp) { 8939566063dSJacob Faibussowitsch PetscCall(MatMult(didp, ts->vec_dir, sp)); 8949566063dSJacob Faibussowitsch PetscCall(VecScale(sp, 2.)); 89533f72c5dSHong Zhang } else { 8969566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(sp)); 89733f72c5dSHong Zhang } 898ecf68647SHong Zhang } else { /* tangent linear variable initialized as dir */ 8999566063dSJacob Faibussowitsch PetscCall(VecCopy(ts->vec_dir, sp)); 90033f72c5dSHong Zhang } 9019566063dSJacob Faibussowitsch PetscCall(VecResetArray(sp)); 9029566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumn(A, &xarr)); 9039566063dSJacob Faibussowitsch PetscCall(VecDestroy(&sp)); 90433f72c5dSHong Zhang 9059566063dSJacob Faibussowitsch PetscCall(TSForwardSetInitialSensitivities(ts, A)); /* if didp is NULL, identity matrix is assumed */ 90633f72c5dSHong Zhang 9079566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A)); 908b5b4017aSHong Zhang PetscFunctionReturn(0); 909b5b4017aSHong Zhang } 910b5b4017aSHong Zhang 911b5b4017aSHong Zhang /*@ 912ecf68647SHong Zhang TSAdjointResetForward - Reset the tangent linear solver and destroy the tangent linear context 913ecf68647SHong Zhang 914*bcf0153eSBarry Smith Logically Collective on ts 915ecf68647SHong Zhang 916ecf68647SHong Zhang Input Parameters: 917*bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()` 918ecf68647SHong Zhang 919ecf68647SHong Zhang Level: intermediate 920ecf68647SHong Zhang 921*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TSAdjointSetForward()` 922ecf68647SHong Zhang @*/ 923d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointResetForward(TS ts) 924d71ae5a4SJacob Faibussowitsch { 925ecf68647SHong Zhang PetscFunctionBegin; 926ecf68647SHong Zhang ts->forward_solve = PETSC_FALSE; /* turn off tangent linear mode */ 9279566063dSJacob Faibussowitsch PetscCall(TSForwardReset(ts)); 928ecf68647SHong Zhang PetscFunctionReturn(0); 929ecf68647SHong Zhang } 930ecf68647SHong Zhang 931ecf68647SHong Zhang /*@ 932814e85d6SHong Zhang TSAdjointSetUp - Sets up the internal data structures for the later use 933814e85d6SHong Zhang of an adjoint solver 934814e85d6SHong Zhang 935*bcf0153eSBarry Smith Collective on ts 936814e85d6SHong Zhang 937814e85d6SHong Zhang Input Parameter: 938*bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()` 939814e85d6SHong Zhang 940814e85d6SHong Zhang Level: advanced 941814e85d6SHong Zhang 942*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TSCreate()`, `TSAdjointStep()`, `TSSetCostGradients()` 943814e85d6SHong Zhang @*/ 944d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointSetUp(TS ts) 945d71ae5a4SJacob Faibussowitsch { 946881c1a9bSHong Zhang TSTrajectory tj; 947881c1a9bSHong Zhang PetscBool match; 948814e85d6SHong Zhang 949814e85d6SHong Zhang PetscFunctionBegin; 950814e85d6SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 951814e85d6SHong Zhang if (ts->adjointsetupcalled) PetscFunctionReturn(0); 9523c633725SBarry Smith PetscCheck(ts->vecs_sensi, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONGSTATE, "Must call TSSetCostGradients() first"); 9533c633725SBarry Smith PetscCheck(!ts->vecs_sensip || ts->Jacp || ts->Jacprhs, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONGSTATE, "Must call TSSetRHSJacobianP() or TSSetIJacobianP() first"); 9549566063dSJacob Faibussowitsch PetscCall(TSGetTrajectory(ts, &tj)); 9559566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)tj, TSTRAJECTORYBASIC, &match)); 956881c1a9bSHong Zhang if (match) { 957881c1a9bSHong Zhang PetscBool solution_only; 9589566063dSJacob Faibussowitsch PetscCall(TSTrajectoryGetSolutionOnly(tj, &solution_only)); 9593c633725SBarry 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"); 960881c1a9bSHong Zhang } 9619566063dSJacob Faibussowitsch PetscCall(TSTrajectorySetUseHistory(tj, PETSC_FALSE)); /* not use TSHistory */ 96233f72c5dSHong Zhang 963cd4cee2dSHong Zhang if (ts->quadraturets) { /* if there is integral in the cost function */ 9649566063dSJacob Faibussowitsch PetscCall(VecDuplicate(ts->vecs_sensi[0], &ts->vec_drdu_col)); 96548a46eb9SPierre Jolivet if (ts->vecs_sensip) PetscCall(VecDuplicate(ts->vecs_sensip[0], &ts->vec_drdp_col)); 966814e85d6SHong Zhang } 967814e85d6SHong Zhang 968dbbe0bcdSBarry Smith PetscTryTypeMethod(ts, adjointsetup); 969814e85d6SHong Zhang ts->adjointsetupcalled = PETSC_TRUE; 970814e85d6SHong Zhang PetscFunctionReturn(0); 971814e85d6SHong Zhang } 972814e85d6SHong Zhang 973814e85d6SHong Zhang /*@ 974*bcf0153eSBarry Smith TSAdjointReset - Resets a `TS` adjoint context and removes any allocated `Vec`s and `Mat`s. 975ece46509SHong Zhang 976*bcf0153eSBarry Smith Collective on ts 977ece46509SHong Zhang 978ece46509SHong Zhang Input Parameter: 979*bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()` 980ece46509SHong Zhang 981ece46509SHong Zhang Level: beginner 982ece46509SHong Zhang 983*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TSCreate()`, `TSAdjointSetUp()`, `TSADestroy()` 984ece46509SHong Zhang @*/ 985d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointReset(TS ts) 986d71ae5a4SJacob Faibussowitsch { 987ece46509SHong Zhang PetscFunctionBegin; 988ece46509SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 989dbbe0bcdSBarry Smith PetscTryTypeMethod(ts, adjointreset); 9907207e0fdSHong Zhang if (ts->quadraturets) { /* if there is integral in the cost function */ 9919566063dSJacob Faibussowitsch PetscCall(VecDestroy(&ts->vec_drdu_col)); 99248a46eb9SPierre Jolivet if (ts->vecs_sensip) PetscCall(VecDestroy(&ts->vec_drdp_col)); 9937207e0fdSHong Zhang } 994ece46509SHong Zhang ts->vecs_sensi = NULL; 995ece46509SHong Zhang ts->vecs_sensip = NULL; 996ece46509SHong Zhang ts->vecs_sensi2 = NULL; 99733f72c5dSHong Zhang ts->vecs_sensi2p = NULL; 998ece46509SHong Zhang ts->vec_dir = NULL; 999ece46509SHong Zhang ts->adjointsetupcalled = PETSC_FALSE; 1000ece46509SHong Zhang PetscFunctionReturn(0); 1001ece46509SHong Zhang } 1002ece46509SHong Zhang 1003ece46509SHong Zhang /*@ 1004814e85d6SHong Zhang TSAdjointSetSteps - Sets the number of steps the adjoint solver should take backward in time 1005814e85d6SHong Zhang 1006*bcf0153eSBarry Smith Logically Collective on ts 1007814e85d6SHong Zhang 1008814e85d6SHong Zhang Input Parameters: 1009*bcf0153eSBarry Smith + ts - the `TS` context obtained from `TSCreate()` 1010a2b725a8SWilliam Gropp - steps - number of steps to use 1011814e85d6SHong Zhang 1012814e85d6SHong Zhang Level: intermediate 1013814e85d6SHong Zhang 1014814e85d6SHong Zhang Notes: 1015*bcf0153eSBarry Smith Normally one does not call this and `TSAdjointSolve()` integrates back to the original timestep. One can call this 1016814e85d6SHong Zhang so as to integrate back to less than the original timestep 1017814e85d6SHong Zhang 1018*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TSAdjointSolve()`, `TS`, `TSSetExactFinalTime()` 1019814e85d6SHong Zhang @*/ 1020d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointSetSteps(TS ts, PetscInt steps) 1021d71ae5a4SJacob Faibussowitsch { 1022814e85d6SHong Zhang PetscFunctionBegin; 1023814e85d6SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1024814e85d6SHong Zhang PetscValidLogicalCollectiveInt(ts, steps, 2); 10253c633725SBarry Smith PetscCheck(steps >= 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Cannot step back a negative number of steps"); 10263c633725SBarry Smith PetscCheck(steps <= ts->steps, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Cannot step back more than the total number of forward steps"); 1027814e85d6SHong Zhang ts->adjoint_max_steps = steps; 1028814e85d6SHong Zhang PetscFunctionReturn(0); 1029814e85d6SHong Zhang } 1030814e85d6SHong Zhang 1031814e85d6SHong Zhang /*@C 1032*bcf0153eSBarry Smith TSAdjointSetRHSJacobian - Deprecated, use `TSSetRHSJacobianP()` 1033814e85d6SHong Zhang 1034814e85d6SHong Zhang Level: deprecated 1035814e85d6SHong Zhang 1036814e85d6SHong Zhang @*/ 1037d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointSetRHSJacobian(TS ts, Mat Amat, PetscErrorCode (*func)(TS, PetscReal, Vec, Mat, void *), void *ctx) 1038d71ae5a4SJacob Faibussowitsch { 1039814e85d6SHong Zhang PetscFunctionBegin; 1040814e85d6SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1041814e85d6SHong Zhang PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2); 1042814e85d6SHong Zhang 1043814e85d6SHong Zhang ts->rhsjacobianp = func; 1044814e85d6SHong Zhang ts->rhsjacobianpctx = ctx; 1045814e85d6SHong Zhang if (Amat) { 10469566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)Amat)); 10479566063dSJacob Faibussowitsch PetscCall(MatDestroy(&ts->Jacp)); 1048814e85d6SHong Zhang ts->Jacp = Amat; 1049814e85d6SHong Zhang } 1050814e85d6SHong Zhang PetscFunctionReturn(0); 1051814e85d6SHong Zhang } 1052814e85d6SHong Zhang 1053814e85d6SHong Zhang /*@C 1054*bcf0153eSBarry Smith TSAdjointComputeRHSJacobian - Deprecated, use `TSComputeRHSJacobianP()` 1055814e85d6SHong Zhang 1056814e85d6SHong Zhang Level: deprecated 1057814e85d6SHong Zhang 1058814e85d6SHong Zhang @*/ 1059d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointComputeRHSJacobian(TS ts, PetscReal t, Vec U, Mat Amat) 1060d71ae5a4SJacob Faibussowitsch { 1061814e85d6SHong Zhang PetscFunctionBegin; 1062814e85d6SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1063c9ad9de0SHong Zhang PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 1064814e85d6SHong Zhang PetscValidPointer(Amat, 4); 1065814e85d6SHong Zhang 1066792fecdfSBarry Smith PetscCallBack("TS callback JacobianP for sensitivity analysis", (*ts->rhsjacobianp)(ts, t, U, Amat, ts->rhsjacobianpctx)); 1067814e85d6SHong Zhang PetscFunctionReturn(0); 1068814e85d6SHong Zhang } 1069814e85d6SHong Zhang 1070814e85d6SHong Zhang /*@ 1071*bcf0153eSBarry Smith TSAdjointComputeDRDYFunction - Deprecated, use `TSGetQuadratureTS()` then `TSComputeRHSJacobian()` 1072814e85d6SHong Zhang 1073814e85d6SHong Zhang Level: deprecated 1074814e85d6SHong Zhang 1075814e85d6SHong Zhang @*/ 1076d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointComputeDRDYFunction(TS ts, PetscReal t, Vec U, Vec *DRDU) 1077d71ae5a4SJacob Faibussowitsch { 1078814e85d6SHong Zhang PetscFunctionBegin; 1079814e85d6SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1080c9ad9de0SHong Zhang PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 1081814e85d6SHong Zhang 1082792fecdfSBarry Smith PetscCallBack("TS callback DRDY for sensitivity analysis", (*ts->drdufunction)(ts, t, U, DRDU, ts->costintegrandctx)); 1083814e85d6SHong Zhang PetscFunctionReturn(0); 1084814e85d6SHong Zhang } 1085814e85d6SHong Zhang 1086814e85d6SHong Zhang /*@ 1087*bcf0153eSBarry Smith TSAdjointComputeDRDPFunction - Deprecated, use `TSGetQuadratureTS()` then `TSComputeRHSJacobianP()` 1088814e85d6SHong Zhang 1089814e85d6SHong Zhang Level: deprecated 1090814e85d6SHong Zhang 1091814e85d6SHong Zhang @*/ 1092d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointComputeDRDPFunction(TS ts, PetscReal t, Vec U, Vec *DRDP) 1093d71ae5a4SJacob Faibussowitsch { 1094814e85d6SHong Zhang PetscFunctionBegin; 1095814e85d6SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1096c9ad9de0SHong Zhang PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 1097814e85d6SHong Zhang 1098792fecdfSBarry Smith PetscCallBack("TS callback DRDP for sensitivity analysis", (*ts->drdpfunction)(ts, t, U, DRDP, ts->costintegrandctx)); 1099814e85d6SHong Zhang PetscFunctionReturn(0); 1100814e85d6SHong Zhang } 1101814e85d6SHong Zhang 1102814e85d6SHong Zhang /*@C 1103814e85d6SHong Zhang TSAdjointMonitorSensi - monitors the first lambda sensitivity 1104814e85d6SHong Zhang 1105814e85d6SHong Zhang Level: intermediate 1106814e85d6SHong Zhang 1107*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TSAdjointMonitorSet()` 1108814e85d6SHong Zhang @*/ 1109d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointMonitorSensi(TS ts, PetscInt step, PetscReal ptime, Vec v, PetscInt numcost, Vec *lambda, Vec *mu, PetscViewerAndFormat *vf) 1110d71ae5a4SJacob Faibussowitsch { 1111814e85d6SHong Zhang PetscViewer viewer = vf->viewer; 1112814e85d6SHong Zhang 1113814e85d6SHong Zhang PetscFunctionBegin; 1114064a246eSJacob Faibussowitsch PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 8); 11159566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(viewer, vf->format)); 11169566063dSJacob Faibussowitsch PetscCall(VecView(lambda[0], viewer)); 11179566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(viewer)); 1118814e85d6SHong Zhang PetscFunctionReturn(0); 1119814e85d6SHong Zhang } 1120814e85d6SHong Zhang 1121814e85d6SHong Zhang /*@C 1122814e85d6SHong Zhang TSAdjointMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user 1123814e85d6SHong Zhang 1124*bcf0153eSBarry Smith Collective on ts 1125814e85d6SHong Zhang 1126814e85d6SHong Zhang Input Parameters: 1127*bcf0153eSBarry Smith + ts - `TS` object you wish to monitor 1128814e85d6SHong Zhang . name - the monitor type one is seeking 1129814e85d6SHong Zhang . help - message indicating what monitoring is done 1130814e85d6SHong Zhang . manual - manual page for the monitor 1131814e85d6SHong Zhang . monitor - the monitor function 1132*bcf0153eSBarry 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 1133814e85d6SHong Zhang 1134814e85d6SHong Zhang Level: developer 1135814e85d6SHong Zhang 1136*bcf0153eSBarry Smith .seealso: [](chapter_ts), `PetscOptionsGetViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, 1137db781477SPatrick Sanan `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()` 1138db781477SPatrick Sanan `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, `PetscOptionsBool()`, 1139db781477SPatrick Sanan `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`, 1140c2e3fba1SPatrick Sanan `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`, 1141db781477SPatrick Sanan `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`, 1142db781477SPatrick Sanan `PetscOptionsFList()`, `PetscOptionsEList()` 1143814e85d6SHong Zhang @*/ 1144d71ae5a4SJacob 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 *)) 1145d71ae5a4SJacob Faibussowitsch { 1146814e85d6SHong Zhang PetscViewer viewer; 1147814e85d6SHong Zhang PetscViewerFormat format; 1148814e85d6SHong Zhang PetscBool flg; 1149814e85d6SHong Zhang 1150814e85d6SHong Zhang PetscFunctionBegin; 11519566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)ts), ((PetscObject)ts)->options, ((PetscObject)ts)->prefix, name, &viewer, &format, &flg)); 1152814e85d6SHong Zhang if (flg) { 1153814e85d6SHong Zhang PetscViewerAndFormat *vf; 11549566063dSJacob Faibussowitsch PetscCall(PetscViewerAndFormatCreate(viewer, format, &vf)); 11559566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)viewer)); 11561baa6e33SBarry Smith if (monitorsetup) PetscCall((*monitorsetup)(ts, vf)); 11579566063dSJacob Faibussowitsch PetscCall(TSAdjointMonitorSet(ts, (PetscErrorCode(*)(TS, PetscInt, PetscReal, Vec, PetscInt, Vec *, Vec *, void *))monitor, vf, (PetscErrorCode(*)(void **))PetscViewerAndFormatDestroy)); 1158814e85d6SHong Zhang } 1159814e85d6SHong Zhang PetscFunctionReturn(0); 1160814e85d6SHong Zhang } 1161814e85d6SHong Zhang 1162814e85d6SHong Zhang /*@C 1163814e85d6SHong Zhang TSAdjointMonitorSet - Sets an ADDITIONAL function that is to be used at every 1164814e85d6SHong Zhang timestep to display the iteration's progress. 1165814e85d6SHong Zhang 1166*bcf0153eSBarry Smith Logically Collective on ts 1167814e85d6SHong Zhang 1168814e85d6SHong Zhang Input Parameters: 1169*bcf0153eSBarry Smith + ts - the `TS` context obtained from `TSCreate()` 1170814e85d6SHong Zhang . adjointmonitor - monitoring routine 1171814e85d6SHong Zhang . adjointmctx - [optional] user-defined context for private data for the 1172814e85d6SHong Zhang monitor routine (use NULL if no context is desired) 1173814e85d6SHong Zhang - adjointmonitordestroy - [optional] routine that frees monitor context 1174814e85d6SHong Zhang (may be NULL) 1175814e85d6SHong Zhang 1176814e85d6SHong Zhang Calling sequence of monitor: 1177814e85d6SHong Zhang $ int adjointmonitor(TS ts,PetscInt steps,PetscReal time,Vec u,PetscInt numcost,Vec *lambda, Vec *mu,void *adjointmctx) 1178814e85d6SHong Zhang 1179*bcf0153eSBarry Smith + ts - the `TS` context 1180814e85d6SHong Zhang . steps - iteration number (after the final time step the monitor routine is called with a step of -1, this is at the final time which may have 1181814e85d6SHong Zhang been interpolated to) 1182814e85d6SHong Zhang . time - current time 1183814e85d6SHong Zhang . u - current iterate 1184814e85d6SHong Zhang . numcost - number of cost functionos 1185814e85d6SHong Zhang . lambda - sensitivities to initial conditions 1186814e85d6SHong Zhang . mu - sensitivities to parameters 1187814e85d6SHong Zhang - adjointmctx - [optional] adjoint monitoring context 1188814e85d6SHong Zhang 1189*bcf0153eSBarry Smith Level: intermediate 1190*bcf0153eSBarry Smith 1191*bcf0153eSBarry Smith Note: 1192814e85d6SHong Zhang This routine adds an additional monitor to the list of monitors that 1193814e85d6SHong Zhang already has been loaded. 1194814e85d6SHong Zhang 1195*bcf0153eSBarry Smith Fortran Note: 1196814e85d6SHong Zhang Only a single monitor function can be set for each TS object 1197814e85d6SHong Zhang 1198*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TS`, `TSAdjointSolve()`, `TSAdjointMonitorCancel()` 1199814e85d6SHong Zhang @*/ 1200d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointMonitorSet(TS ts, PetscErrorCode (*adjointmonitor)(TS, PetscInt, PetscReal, Vec, PetscInt, Vec *, Vec *, void *), void *adjointmctx, PetscErrorCode (*adjointmdestroy)(void **)) 1201d71ae5a4SJacob Faibussowitsch { 1202814e85d6SHong Zhang PetscInt i; 1203814e85d6SHong Zhang PetscBool identical; 1204814e85d6SHong Zhang 1205814e85d6SHong Zhang PetscFunctionBegin; 1206814e85d6SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1207814e85d6SHong Zhang for (i = 0; i < ts->numbermonitors; i++) { 12089566063dSJacob Faibussowitsch PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))adjointmonitor, adjointmctx, adjointmdestroy, (PetscErrorCode(*)(void))ts->adjointmonitor[i], ts->adjointmonitorcontext[i], ts->adjointmonitordestroy[i], &identical)); 1209814e85d6SHong Zhang if (identical) PetscFunctionReturn(0); 1210814e85d6SHong Zhang } 12113c633725SBarry Smith PetscCheck(ts->numberadjointmonitors < MAXTSMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many adjoint monitors set"); 1212814e85d6SHong Zhang ts->adjointmonitor[ts->numberadjointmonitors] = adjointmonitor; 1213814e85d6SHong Zhang ts->adjointmonitordestroy[ts->numberadjointmonitors] = adjointmdestroy; 1214814e85d6SHong Zhang ts->adjointmonitorcontext[ts->numberadjointmonitors++] = (void *)adjointmctx; 1215814e85d6SHong Zhang PetscFunctionReturn(0); 1216814e85d6SHong Zhang } 1217814e85d6SHong Zhang 1218814e85d6SHong Zhang /*@C 1219814e85d6SHong Zhang TSAdjointMonitorCancel - Clears all the adjoint monitors that have been set on a time-step object. 1220814e85d6SHong Zhang 1221*bcf0153eSBarry Smith Logically Collective on ts 1222814e85d6SHong Zhang 1223814e85d6SHong Zhang Input Parameters: 1224*bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()` 1225814e85d6SHong Zhang 1226814e85d6SHong Zhang Notes: 1227814e85d6SHong Zhang There is no way to remove a single, specific monitor. 1228814e85d6SHong Zhang 1229814e85d6SHong Zhang Level: intermediate 1230814e85d6SHong Zhang 1231*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TS`, `TSAdjointSolve()`, `TSAdjointMonitorSet()` 1232814e85d6SHong Zhang @*/ 1233d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointMonitorCancel(TS ts) 1234d71ae5a4SJacob Faibussowitsch { 1235814e85d6SHong Zhang PetscInt i; 1236814e85d6SHong Zhang 1237814e85d6SHong Zhang PetscFunctionBegin; 1238814e85d6SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1239814e85d6SHong Zhang for (i = 0; i < ts->numberadjointmonitors; i++) { 124048a46eb9SPierre Jolivet if (ts->adjointmonitordestroy[i]) PetscCall((*ts->adjointmonitordestroy[i])(&ts->adjointmonitorcontext[i])); 1241814e85d6SHong Zhang } 1242814e85d6SHong Zhang ts->numberadjointmonitors = 0; 1243814e85d6SHong Zhang PetscFunctionReturn(0); 1244814e85d6SHong Zhang } 1245814e85d6SHong Zhang 1246814e85d6SHong Zhang /*@C 1247814e85d6SHong Zhang TSAdjointMonitorDefault - the default monitor of adjoint computations 1248814e85d6SHong Zhang 1249814e85d6SHong Zhang Level: intermediate 1250814e85d6SHong Zhang 1251*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TS`, `TSAdjointSolve()`, `TSAdjointMonitorSet()` 1252814e85d6SHong Zhang @*/ 1253d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointMonitorDefault(TS ts, PetscInt step, PetscReal ptime, Vec v, PetscInt numcost, Vec *lambda, Vec *mu, PetscViewerAndFormat *vf) 1254d71ae5a4SJacob Faibussowitsch { 1255814e85d6SHong Zhang PetscViewer viewer = vf->viewer; 1256814e85d6SHong Zhang 1257814e85d6SHong Zhang PetscFunctionBegin; 1258064a246eSJacob Faibussowitsch PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 8); 12599566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(viewer, vf->format)); 12609566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)ts)->tablevel)); 126163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " TS dt %g time %g%s", step, (double)ts->time_step, (double)ptime, ts->steprollback ? " (r)\n" : "\n")); 12629566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)ts)->tablevel)); 12639566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(viewer)); 1264814e85d6SHong Zhang PetscFunctionReturn(0); 1265814e85d6SHong Zhang } 1266814e85d6SHong Zhang 1267814e85d6SHong Zhang /*@C 1268*bcf0153eSBarry Smith TSAdjointMonitorDrawSensi - Monitors progress of the adjoint `TS` solvers by calling 1269*bcf0153eSBarry Smith `VecView()` for the sensitivities to initial states at each timestep 1270814e85d6SHong Zhang 1271*bcf0153eSBarry Smith Collective on ts 1272814e85d6SHong Zhang 1273814e85d6SHong Zhang Input Parameters: 1274*bcf0153eSBarry Smith + ts - the `TS` context 1275814e85d6SHong Zhang . step - current time-step 1276814e85d6SHong Zhang . ptime - current time 1277814e85d6SHong Zhang . u - current state 1278814e85d6SHong Zhang . numcost - number of cost functions 1279814e85d6SHong Zhang . lambda - sensitivities to initial conditions 1280814e85d6SHong Zhang . mu - sensitivities to parameters 1281814e85d6SHong Zhang - dummy - either a viewer or NULL 1282814e85d6SHong Zhang 1283814e85d6SHong Zhang Level: intermediate 1284814e85d6SHong Zhang 1285*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TSAdjointSolve()`, `TSAdjointMonitorSet()`, `TSAdjointMonitorDefault()`, `VecView()` 1286814e85d6SHong Zhang @*/ 1287d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointMonitorDrawSensi(TS ts, PetscInt step, PetscReal ptime, Vec u, PetscInt numcost, Vec *lambda, Vec *mu, void *dummy) 1288d71ae5a4SJacob Faibussowitsch { 1289814e85d6SHong Zhang TSMonitorDrawCtx ictx = (TSMonitorDrawCtx)dummy; 1290814e85d6SHong Zhang PetscDraw draw; 1291814e85d6SHong Zhang PetscReal xl, yl, xr, yr, h; 1292814e85d6SHong Zhang char time[32]; 1293814e85d6SHong Zhang 1294814e85d6SHong Zhang PetscFunctionBegin; 1295814e85d6SHong Zhang if (!(((ictx->howoften > 0) && (!(step % ictx->howoften))) || ((ictx->howoften == -1) && ts->reason))) PetscFunctionReturn(0); 1296814e85d6SHong Zhang 12979566063dSJacob Faibussowitsch PetscCall(VecView(lambda[0], ictx->viewer)); 12989566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(ictx->viewer, 0, &draw)); 12999566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(time, 32, "Timestep %d Time %g", (int)step, (double)ptime)); 13009566063dSJacob Faibussowitsch PetscCall(PetscDrawGetCoordinates(draw, &xl, &yl, &xr, &yr)); 1301814e85d6SHong Zhang h = yl + .95 * (yr - yl); 13029566063dSJacob Faibussowitsch PetscCall(PetscDrawStringCentered(draw, .5 * (xl + xr), h, PETSC_DRAW_BLACK, time)); 13039566063dSJacob Faibussowitsch PetscCall(PetscDrawFlush(draw)); 1304814e85d6SHong Zhang PetscFunctionReturn(0); 1305814e85d6SHong Zhang } 1306814e85d6SHong Zhang 1307814e85d6SHong Zhang /* 1308*bcf0153eSBarry Smith TSAdjointSetFromOptions - Sets various `TS` adjoint parameters from user options. 1309814e85d6SHong Zhang 1310*bcf0153eSBarry Smith Collective on ts 1311814e85d6SHong Zhang 1312814e85d6SHong Zhang Input Parameter: 1313*bcf0153eSBarry Smith . ts - the `TS` context 1314814e85d6SHong Zhang 1315814e85d6SHong Zhang Options Database Keys: 1316814e85d6SHong Zhang + -ts_adjoint_solve <yes,no> After solving the ODE/DAE solve the adjoint problem (requires -ts_save_trajectory) 1317814e85d6SHong Zhang . -ts_adjoint_monitor - print information at each adjoint time step 1318814e85d6SHong Zhang - -ts_adjoint_monitor_draw_sensi - monitor the sensitivity of the first cost function wrt initial conditions (lambda[0]) graphically 1319814e85d6SHong Zhang 1320814e85d6SHong Zhang Level: developer 1321814e85d6SHong Zhang 1322*bcf0153eSBarry Smith Note: 1323814e85d6SHong Zhang This is not normally called directly by users 1324814e85d6SHong Zhang 1325*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TSSetSaveTrajectory()`, `TSTrajectorySetUp()` 1326814e85d6SHong Zhang */ 1327d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointSetFromOptions(TS ts, PetscOptionItems *PetscOptionsObject) 1328d71ae5a4SJacob Faibussowitsch { 1329814e85d6SHong Zhang PetscBool tflg, opt; 1330814e85d6SHong Zhang 1331814e85d6SHong Zhang PetscFunctionBegin; 1332dbbe0bcdSBarry Smith PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1333d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "TS Adjoint options"); 1334814e85d6SHong Zhang tflg = ts->adjoint_solve ? PETSC_TRUE : PETSC_FALSE; 13359566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-ts_adjoint_solve", "Solve the adjoint problem immediately after solving the forward problem", "", tflg, &tflg, &opt)); 1336814e85d6SHong Zhang if (opt) { 13379566063dSJacob Faibussowitsch PetscCall(TSSetSaveTrajectory(ts)); 1338814e85d6SHong Zhang ts->adjoint_solve = tflg; 1339814e85d6SHong Zhang } 13409566063dSJacob Faibussowitsch PetscCall(TSAdjointMonitorSetFromOptions(ts, "-ts_adjoint_monitor", "Monitor adjoint timestep size", "TSAdjointMonitorDefault", TSAdjointMonitorDefault, NULL)); 13419566063dSJacob Faibussowitsch PetscCall(TSAdjointMonitorSetFromOptions(ts, "-ts_adjoint_monitor_sensi", "Monitor sensitivity in the adjoint computation", "TSAdjointMonitorSensi", TSAdjointMonitorSensi, NULL)); 1342814e85d6SHong Zhang opt = PETSC_FALSE; 13439566063dSJacob Faibussowitsch PetscCall(PetscOptionsName("-ts_adjoint_monitor_draw_sensi", "Monitor adjoint sensitivities (lambda only) graphically", "TSAdjointMonitorDrawSensi", &opt)); 1344814e85d6SHong Zhang if (opt) { 1345814e85d6SHong Zhang TSMonitorDrawCtx ctx; 1346814e85d6SHong Zhang PetscInt howoften = 1; 1347814e85d6SHong Zhang 13489566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-ts_adjoint_monitor_draw_sensi", "Monitor adjoint sensitivities (lambda only) graphically", "TSAdjointMonitorDrawSensi", howoften, &howoften, NULL)); 13499566063dSJacob Faibussowitsch PetscCall(TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, &ctx)); 13509566063dSJacob Faibussowitsch PetscCall(TSAdjointMonitorSet(ts, TSAdjointMonitorDrawSensi, ctx, (PetscErrorCode(*)(void **))TSMonitorDrawCtxDestroy)); 1351814e85d6SHong Zhang } 1352814e85d6SHong Zhang PetscFunctionReturn(0); 1353814e85d6SHong Zhang } 1354814e85d6SHong Zhang 1355814e85d6SHong Zhang /*@ 1356814e85d6SHong Zhang TSAdjointStep - Steps one time step backward in the adjoint run 1357814e85d6SHong Zhang 1358*bcf0153eSBarry Smith Collective on ts 1359814e85d6SHong Zhang 1360814e85d6SHong Zhang Input Parameter: 1361*bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()` 1362814e85d6SHong Zhang 1363814e85d6SHong Zhang Level: intermediate 1364814e85d6SHong Zhang 1365*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TSAdjointSetUp()`, `TSAdjointSolve()` 1366814e85d6SHong Zhang @*/ 1367d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointStep(TS ts) 1368d71ae5a4SJacob Faibussowitsch { 1369814e85d6SHong Zhang DM dm; 1370814e85d6SHong Zhang 1371814e85d6SHong Zhang PetscFunctionBegin; 1372814e85d6SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 13739566063dSJacob Faibussowitsch PetscCall(TSGetDM(ts, &dm)); 13749566063dSJacob Faibussowitsch PetscCall(TSAdjointSetUp(ts)); 13757b0e2f17SHong Zhang ts->steps--; /* must decrease the step index before the adjoint step is taken. */ 1376814e85d6SHong Zhang 1377814e85d6SHong Zhang ts->reason = TS_CONVERGED_ITERATING; 1378814e85d6SHong Zhang ts->ptime_prev = ts->ptime; 13799566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(TS_AdjointStep, ts, 0, 0, 0)); 1380dbbe0bcdSBarry Smith PetscUseTypeMethod(ts, adjointstep); 13819566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(TS_AdjointStep, ts, 0, 0, 0)); 13827b0e2f17SHong Zhang ts->adjoint_steps++; 1383814e85d6SHong Zhang 1384814e85d6SHong Zhang if (ts->reason < 0) { 13853c633725SBarry Smith PetscCheck(!ts->errorifstepfailed, PetscObjectComm((PetscObject)ts), PETSC_ERR_NOT_CONVERGED, "TSAdjointStep has failed due to %s", TSConvergedReasons[ts->reason]); 1386814e85d6SHong Zhang } else if (!ts->reason) { 1387814e85d6SHong Zhang if (ts->adjoint_steps >= ts->adjoint_max_steps) ts->reason = TS_CONVERGED_ITS; 1388814e85d6SHong Zhang } 1389814e85d6SHong Zhang PetscFunctionReturn(0); 1390814e85d6SHong Zhang } 1391814e85d6SHong Zhang 1392814e85d6SHong Zhang /*@ 1393814e85d6SHong Zhang TSAdjointSolve - Solves the discrete ajoint problem for an ODE/DAE 1394814e85d6SHong Zhang 1395*bcf0153eSBarry Smith Collective on ts 1396*bcf0153eSBarry Smith ` 1397814e85d6SHong Zhang Input Parameter: 1398*bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()` 1399814e85d6SHong Zhang 1400*bcf0153eSBarry Smith Options Database Key: 1401814e85d6SHong Zhang . -ts_adjoint_view_solution <viewerinfo> - views the first gradient with respect to the initial values 1402814e85d6SHong Zhang 1403814e85d6SHong Zhang Level: intermediate 1404814e85d6SHong Zhang 1405814e85d6SHong Zhang Notes: 1406*bcf0153eSBarry Smith This must be called after a call to `TSSolve()` that solves the forward problem 1407814e85d6SHong Zhang 1408*bcf0153eSBarry Smith By default this will integrate back to the initial time, one can use `TSAdjointSetSteps()` to step back to a later time 1409814e85d6SHong Zhang 1410*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TSAdjointSolve()`, `TSCreate()`, `TSSetCostGradients()`, `TSSetSolution()`, `TSAdjointStep()` 1411814e85d6SHong Zhang @*/ 1412d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointSolve(TS ts) 1413d71ae5a4SJacob Faibussowitsch { 1414f1d62c27SHong Zhang static PetscBool cite = PETSC_FALSE; 14157f59fb53SHong Zhang #if defined(TSADJOINT_STAGE) 14167f59fb53SHong Zhang PetscLogStage adjoint_stage; 14177f59fb53SHong Zhang #endif 1418814e85d6SHong Zhang 1419814e85d6SHong Zhang PetscFunctionBegin; 1420814e85d6SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1421421b783aSHong Zhang PetscCall(PetscCitationsRegister("@article{Zhang2022tsadjoint,\n" 1422421b783aSHong Zhang " title = {{PETSc TSAdjoint: A Discrete Adjoint ODE Solver for First-Order and Second-Order Sensitivity Analysis}},\n" 1423f1d62c27SHong Zhang " author = {Zhang, Hong and Constantinescu, Emil M. and Smith, Barry F.},\n" 1424421b783aSHong Zhang " journal = {SIAM Journal on Scientific Computing},\n" 1425421b783aSHong Zhang " volume = {44},\n" 1426421b783aSHong Zhang " number = {1},\n" 1427421b783aSHong Zhang " pages = {C1-C24},\n" 1428421b783aSHong Zhang " doi = {10.1137/21M140078X},\n" 14299371c9d4SSatish Balay " year = {2022}\n}\n", 14309371c9d4SSatish Balay &cite)); 14317f59fb53SHong Zhang #if defined(TSADJOINT_STAGE) 14329566063dSJacob Faibussowitsch PetscCall(PetscLogStageRegister("TSAdjoint", &adjoint_stage)); 14339566063dSJacob Faibussowitsch PetscCall(PetscLogStagePush(adjoint_stage)); 14347f59fb53SHong Zhang #endif 14359566063dSJacob Faibussowitsch PetscCall(TSAdjointSetUp(ts)); 1436814e85d6SHong Zhang 1437814e85d6SHong Zhang /* reset time step and iteration counters */ 1438814e85d6SHong Zhang ts->adjoint_steps = 0; 1439814e85d6SHong Zhang ts->ksp_its = 0; 1440814e85d6SHong Zhang ts->snes_its = 0; 1441814e85d6SHong Zhang ts->num_snes_failures = 0; 1442814e85d6SHong Zhang ts->reject = 0; 1443814e85d6SHong Zhang ts->reason = TS_CONVERGED_ITERATING; 1444814e85d6SHong Zhang 1445814e85d6SHong Zhang if (!ts->adjoint_max_steps) ts->adjoint_max_steps = ts->steps; 1446814e85d6SHong Zhang if (ts->adjoint_steps >= ts->adjoint_max_steps) ts->reason = TS_CONVERGED_ITS; 1447814e85d6SHong Zhang 1448814e85d6SHong Zhang while (!ts->reason) { 14499566063dSJacob Faibussowitsch PetscCall(TSTrajectoryGet(ts->trajectory, ts, ts->steps, &ts->ptime)); 14509566063dSJacob Faibussowitsch PetscCall(TSAdjointMonitor(ts, ts->steps, ts->ptime, ts->vec_sol, ts->numcost, ts->vecs_sensi, ts->vecs_sensip)); 14519566063dSJacob Faibussowitsch PetscCall(TSAdjointEventHandler(ts)); 14529566063dSJacob Faibussowitsch PetscCall(TSAdjointStep(ts)); 145348a46eb9SPierre Jolivet if ((ts->vec_costintegral || ts->quadraturets) && !ts->costintegralfwd) PetscCall(TSAdjointCostIntegral(ts)); 1454814e85d6SHong Zhang } 1455bdbff044SHong Zhang if (!ts->steps) { 14569566063dSJacob Faibussowitsch PetscCall(TSTrajectoryGet(ts->trajectory, ts, ts->steps, &ts->ptime)); 14579566063dSJacob Faibussowitsch PetscCall(TSAdjointMonitor(ts, ts->steps, ts->ptime, ts->vec_sol, ts->numcost, ts->vecs_sensi, ts->vecs_sensip)); 1458bdbff044SHong Zhang } 1459814e85d6SHong Zhang ts->solvetime = ts->ptime; 14609566063dSJacob Faibussowitsch PetscCall(TSTrajectoryViewFromOptions(ts->trajectory, NULL, "-ts_trajectory_view")); 14619566063dSJacob Faibussowitsch PetscCall(VecViewFromOptions(ts->vecs_sensi[0], (PetscObject)ts, "-ts_adjoint_view_solution")); 1462814e85d6SHong Zhang ts->adjoint_max_steps = 0; 14637f59fb53SHong Zhang #if defined(TSADJOINT_STAGE) 14649566063dSJacob Faibussowitsch PetscCall(PetscLogStagePop()); 14657f59fb53SHong Zhang #endif 1466814e85d6SHong Zhang PetscFunctionReturn(0); 1467814e85d6SHong Zhang } 1468814e85d6SHong Zhang 1469814e85d6SHong Zhang /*@C 1470*bcf0153eSBarry Smith TSAdjointMonitor - Runs all user-provided adjoint monitor routines set using `TSAdjointMonitorSet()` 1471814e85d6SHong Zhang 1472*bcf0153eSBarry Smith Collective on ts 1473814e85d6SHong Zhang 1474814e85d6SHong Zhang Input Parameters: 1475*bcf0153eSBarry Smith + ts - time stepping context obtained from `TSCreate()` 1476814e85d6SHong Zhang . step - step number that has just completed 1477814e85d6SHong Zhang . ptime - model time of the state 1478814e85d6SHong Zhang . u - state at the current model time 1479814e85d6SHong Zhang . numcost - number of cost functions (dimension of lambda or mu) 1480814e85d6SHong Zhang . lambda - vectors containing the gradients of the cost functions with respect to the ODE/DAE solution variables 1481814e85d6SHong Zhang - mu - vectors containing the gradients of the cost functions with respect to the problem parameters 1482814e85d6SHong Zhang 1483814e85d6SHong Zhang Level: developer 1484814e85d6SHong Zhang 1485*bcf0153eSBarry Smith Note: 1486*bcf0153eSBarry Smith `TSAdjointMonitor()` is typically used automatically within the time stepping implementations. 1487*bcf0153eSBarry Smith Users would almost never call this routine directly. 1488*bcf0153eSBarry Smith 1489*bcf0153eSBarry Smith .seealso: `TSAdjointMonitorSet()`, `TSAdjointSolve()` 1490814e85d6SHong Zhang @*/ 1491d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointMonitor(TS ts, PetscInt step, PetscReal ptime, Vec u, PetscInt numcost, Vec *lambda, Vec *mu) 1492d71ae5a4SJacob Faibussowitsch { 1493814e85d6SHong Zhang PetscInt i, n = ts->numberadjointmonitors; 1494814e85d6SHong Zhang 1495814e85d6SHong Zhang PetscFunctionBegin; 1496814e85d6SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1497814e85d6SHong Zhang PetscValidHeaderSpecific(u, VEC_CLASSID, 4); 14989566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(u)); 149948a46eb9SPierre Jolivet for (i = 0; i < n; i++) PetscCall((*ts->adjointmonitor[i])(ts, step, ptime, u, numcost, lambda, mu, ts->adjointmonitorcontext[i])); 15009566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(u)); 1501814e85d6SHong Zhang PetscFunctionReturn(0); 1502814e85d6SHong Zhang } 1503814e85d6SHong Zhang 1504814e85d6SHong Zhang /*@ 1505814e85d6SHong Zhang TSAdjointCostIntegral - Evaluate the cost integral in the adjoint run. 1506814e85d6SHong Zhang 1507*bcf0153eSBarry Smith Collective on ts 1508814e85d6SHong Zhang 15094165533cSJose E. Roman Input Parameter: 1510814e85d6SHong Zhang . ts - time stepping context 1511814e85d6SHong Zhang 1512814e85d6SHong Zhang Level: advanced 1513814e85d6SHong Zhang 1514814e85d6SHong Zhang Notes: 1515*bcf0153eSBarry Smith This function cannot be called until `TSAdjointStep()` has been completed. 1516814e85d6SHong Zhang 1517*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TSAdjointSolve()`, `TSAdjointStep()` 1518814e85d6SHong Zhang @*/ 1519d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAdjointCostIntegral(TS ts) 1520d71ae5a4SJacob Faibussowitsch { 1521362febeeSStefano Zampini PetscFunctionBegin; 1522814e85d6SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1523dbbe0bcdSBarry Smith PetscUseTypeMethod(ts, adjointintegral); 1524814e85d6SHong Zhang PetscFunctionReturn(0); 1525814e85d6SHong Zhang } 1526814e85d6SHong Zhang 1527814e85d6SHong Zhang /* ------------------ Forward (tangent linear) sensitivity ------------------*/ 1528814e85d6SHong Zhang 1529814e85d6SHong Zhang /*@ 1530814e85d6SHong Zhang TSForwardSetUp - Sets up the internal data structures for the later use 1531814e85d6SHong Zhang of forward sensitivity analysis 1532814e85d6SHong Zhang 1533*bcf0153eSBarry Smith Collective on ts 1534814e85d6SHong Zhang 1535814e85d6SHong Zhang Input Parameter: 1536*bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()` 1537814e85d6SHong Zhang 1538814e85d6SHong Zhang Level: advanced 1539814e85d6SHong Zhang 1540*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TS`, `TSCreate()`, `TSDestroy()`, `TSSetUp()` 1541814e85d6SHong Zhang @*/ 1542d71ae5a4SJacob Faibussowitsch PetscErrorCode TSForwardSetUp(TS ts) 1543d71ae5a4SJacob Faibussowitsch { 1544814e85d6SHong Zhang PetscFunctionBegin; 1545814e85d6SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1546814e85d6SHong Zhang if (ts->forwardsetupcalled) PetscFunctionReturn(0); 1547dbbe0bcdSBarry Smith PetscTryTypeMethod(ts, forwardsetup); 15489566063dSJacob Faibussowitsch PetscCall(VecDuplicate(ts->vec_sol, &ts->vec_sensip_col)); 1549814e85d6SHong Zhang ts->forwardsetupcalled = PETSC_TRUE; 1550814e85d6SHong Zhang PetscFunctionReturn(0); 1551814e85d6SHong Zhang } 1552814e85d6SHong Zhang 1553814e85d6SHong Zhang /*@ 15547adebddeSHong Zhang TSForwardReset - Reset the internal data structures used by forward sensitivity analysis 15557adebddeSHong Zhang 1556*bcf0153eSBarry Smith Collective on ts 15577adebddeSHong Zhang 15587adebddeSHong Zhang Input Parameter: 1559*bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()` 15607adebddeSHong Zhang 15617adebddeSHong Zhang Level: advanced 15627adebddeSHong Zhang 1563*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TSCreate()`, `TSDestroy()`, `TSForwardSetUp()` 15647adebddeSHong Zhang @*/ 1565d71ae5a4SJacob Faibussowitsch PetscErrorCode TSForwardReset(TS ts) 1566d71ae5a4SJacob Faibussowitsch { 15677207e0fdSHong Zhang TS quadts = ts->quadraturets; 15687adebddeSHong Zhang 15697adebddeSHong Zhang PetscFunctionBegin; 15707adebddeSHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1571dbbe0bcdSBarry Smith PetscTryTypeMethod(ts, forwardreset); 15729566063dSJacob Faibussowitsch PetscCall(MatDestroy(&ts->mat_sensip)); 157348a46eb9SPierre Jolivet if (quadts) PetscCall(MatDestroy(&quadts->mat_sensip)); 15749566063dSJacob Faibussowitsch PetscCall(VecDestroy(&ts->vec_sensip_col)); 15757adebddeSHong Zhang ts->forward_solve = PETSC_FALSE; 15767adebddeSHong Zhang ts->forwardsetupcalled = PETSC_FALSE; 15777adebddeSHong Zhang PetscFunctionReturn(0); 15787adebddeSHong Zhang } 15797adebddeSHong Zhang 15807adebddeSHong Zhang /*@ 1581814e85d6SHong Zhang TSForwardSetIntegralGradients - Set the vectors holding forward sensitivities of the integral term. 1582814e85d6SHong Zhang 1583d8d19677SJose E. Roman Input Parameters: 1584*bcf0153eSBarry Smith + ts - the `TS` context obtained from `TSCreate()` 1585814e85d6SHong Zhang . numfwdint - number of integrals 158667b8a455SSatish Balay - vp - the vectors containing the gradients for each integral w.r.t. parameters 1587814e85d6SHong Zhang 15887207e0fdSHong Zhang Level: deprecated 1589814e85d6SHong Zhang 1590*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TSForwardGetSensitivities()`, `TSForwardSetIntegralGradients()`, `TSForwardGetIntegralGradients()`, `TSForwardStep()` 1591814e85d6SHong Zhang @*/ 1592d71ae5a4SJacob Faibussowitsch PetscErrorCode TSForwardSetIntegralGradients(TS ts, PetscInt numfwdint, Vec *vp) 1593d71ae5a4SJacob Faibussowitsch { 1594814e85d6SHong Zhang PetscFunctionBegin; 1595814e85d6SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 15963c633725SBarry 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()"); 1597814e85d6SHong Zhang if (!ts->numcost) ts->numcost = numfwdint; 1598814e85d6SHong Zhang 1599814e85d6SHong Zhang ts->vecs_integral_sensip = vp; 1600814e85d6SHong Zhang PetscFunctionReturn(0); 1601814e85d6SHong Zhang } 1602814e85d6SHong Zhang 1603814e85d6SHong Zhang /*@ 1604814e85d6SHong Zhang TSForwardGetIntegralGradients - Returns the forward sensitivities ofthe integral term. 1605814e85d6SHong Zhang 1606814e85d6SHong Zhang Input Parameter: 1607*bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()` 1608814e85d6SHong Zhang 1609814e85d6SHong Zhang Output Parameter: 161067b8a455SSatish Balay . vp - the vectors containing the gradients for each integral w.r.t. parameters 1611814e85d6SHong Zhang 16127207e0fdSHong Zhang Level: deprecated 1613814e85d6SHong Zhang 1614*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TSForwardSetSensitivities()`, `TSForwardSetIntegralGradients()`, `TSForwardGetIntegralGradients()`, `TSForwardStep()` 1615814e85d6SHong Zhang @*/ 1616d71ae5a4SJacob Faibussowitsch PetscErrorCode TSForwardGetIntegralGradients(TS ts, PetscInt *numfwdint, Vec **vp) 1617d71ae5a4SJacob Faibussowitsch { 1618814e85d6SHong Zhang PetscFunctionBegin; 1619814e85d6SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1620814e85d6SHong Zhang PetscValidPointer(vp, 3); 1621814e85d6SHong Zhang if (numfwdint) *numfwdint = ts->numcost; 1622814e85d6SHong Zhang if (vp) *vp = ts->vecs_integral_sensip; 1623814e85d6SHong Zhang PetscFunctionReturn(0); 1624814e85d6SHong Zhang } 1625814e85d6SHong Zhang 1626814e85d6SHong Zhang /*@ 1627814e85d6SHong Zhang TSForwardStep - Compute the forward sensitivity for one time step. 1628814e85d6SHong Zhang 1629*bcf0153eSBarry Smith Collective on ts 1630814e85d6SHong Zhang 16314165533cSJose E. Roman Input Parameter: 1632814e85d6SHong Zhang . ts - time stepping context 1633814e85d6SHong Zhang 1634814e85d6SHong Zhang Level: advanced 1635814e85d6SHong Zhang 1636814e85d6SHong Zhang Notes: 1637*bcf0153eSBarry Smith This function cannot be called until `TSStep()` has been completed. 1638814e85d6SHong Zhang 1639*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TSForwardSetSensitivities()`, `TSForwardGetSensitivities()`, `TSForwardSetIntegralGradients()`, `TSForwardGetIntegralGradients()`, `TSForwardSetUp()` 1640814e85d6SHong Zhang @*/ 1641d71ae5a4SJacob Faibussowitsch PetscErrorCode TSForwardStep(TS ts) 1642d71ae5a4SJacob Faibussowitsch { 1643362febeeSStefano Zampini PetscFunctionBegin; 1644814e85d6SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 16459566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(TS_ForwardStep, ts, 0, 0, 0)); 1646dbbe0bcdSBarry Smith PetscUseTypeMethod(ts, forwardstep); 16479566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(TS_ForwardStep, ts, 0, 0, 0)); 16483c633725SBarry Smith PetscCheck(ts->reason >= 0 || !ts->errorifstepfailed, PetscObjectComm((PetscObject)ts), PETSC_ERR_NOT_CONVERGED, "TSFowardStep has failed due to %s", TSConvergedReasons[ts->reason]); 1649814e85d6SHong Zhang PetscFunctionReturn(0); 1650814e85d6SHong Zhang } 1651814e85d6SHong Zhang 1652814e85d6SHong Zhang /*@ 1653814e85d6SHong Zhang TSForwardSetSensitivities - Sets the initial value of the trajectory sensitivities of solution w.r.t. the problem parameters and initial values. 1654814e85d6SHong Zhang 1655*bcf0153eSBarry Smith Logically Collective on ts 1656814e85d6SHong Zhang 1657814e85d6SHong Zhang Input Parameters: 1658*bcf0153eSBarry Smith + ts - the `TS` context obtained from `TSCreate()` 1659814e85d6SHong Zhang . nump - number of parameters 1660814e85d6SHong Zhang - Smat - sensitivities with respect to the parameters, the number of entries in these vectors is the same as the number of parameters 1661814e85d6SHong Zhang 1662814e85d6SHong Zhang Level: beginner 1663814e85d6SHong Zhang 1664814e85d6SHong Zhang Notes: 1665814e85d6SHong Zhang Forward sensitivity is also called 'trajectory sensitivity' in some fields such as power systems. 1666*bcf0153eSBarry Smith This function turns on a flag to trigger `TSSolve()` to compute forward sensitivities automatically. 1667*bcf0153eSBarry Smith You must call this function before `TSSolve()`. 1668814e85d6SHong Zhang The entries in the sensitivity matrix must be correctly initialized with the values S = dy/dp|startingtime. 1669814e85d6SHong Zhang 1670*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TSForwardGetSensitivities()`, `TSForwardSetIntegralGradients()`, `TSForwardGetIntegralGradients()`, `TSForwardStep()` 1671814e85d6SHong Zhang @*/ 1672d71ae5a4SJacob Faibussowitsch PetscErrorCode TSForwardSetSensitivities(TS ts, PetscInt nump, Mat Smat) 1673d71ae5a4SJacob Faibussowitsch { 1674814e85d6SHong Zhang PetscFunctionBegin; 1675814e85d6SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1676814e85d6SHong Zhang PetscValidHeaderSpecific(Smat, MAT_CLASSID, 3); 1677814e85d6SHong Zhang ts->forward_solve = PETSC_TRUE; 1678b5b4017aSHong Zhang if (nump == PETSC_DEFAULT) { 16799566063dSJacob Faibussowitsch PetscCall(MatGetSize(Smat, NULL, &ts->num_parameters)); 1680b5b4017aSHong Zhang } else ts->num_parameters = nump; 16819566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)Smat)); 16829566063dSJacob Faibussowitsch PetscCall(MatDestroy(&ts->mat_sensip)); 1683814e85d6SHong Zhang ts->mat_sensip = Smat; 1684814e85d6SHong Zhang PetscFunctionReturn(0); 1685814e85d6SHong Zhang } 1686814e85d6SHong Zhang 1687814e85d6SHong Zhang /*@ 1688814e85d6SHong Zhang TSForwardGetSensitivities - Returns the trajectory sensitivities 1689814e85d6SHong Zhang 1690*bcf0153eSBarry Smith Not Collective, but Smat returned is parallel if ts is parallel 1691814e85d6SHong Zhang 1692d8d19677SJose E. Roman Output Parameters: 1693*bcf0153eSBarry Smith + ts - the `TS` context obtained from `TSCreate()` 1694814e85d6SHong Zhang . nump - number of parameters 1695814e85d6SHong Zhang - Smat - sensitivities with respect to the parameters, the number of entries in these vectors is the same as the number of parameters 1696814e85d6SHong Zhang 1697814e85d6SHong Zhang Level: intermediate 1698814e85d6SHong Zhang 1699*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TSForwardSetSensitivities()`, `TSForwardSetIntegralGradients()`, `TSForwardGetIntegralGradients()`, `TSForwardStep()` 1700814e85d6SHong Zhang @*/ 1701d71ae5a4SJacob Faibussowitsch PetscErrorCode TSForwardGetSensitivities(TS ts, PetscInt *nump, Mat *Smat) 1702d71ae5a4SJacob Faibussowitsch { 1703814e85d6SHong Zhang PetscFunctionBegin; 1704814e85d6SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1705814e85d6SHong Zhang if (nump) *nump = ts->num_parameters; 1706814e85d6SHong Zhang if (Smat) *Smat = ts->mat_sensip; 1707814e85d6SHong Zhang PetscFunctionReturn(0); 1708814e85d6SHong Zhang } 1709814e85d6SHong Zhang 1710814e85d6SHong Zhang /*@ 1711814e85d6SHong Zhang TSForwardCostIntegral - Evaluate the cost integral in the forward run. 1712814e85d6SHong Zhang 1713*bcf0153eSBarry Smith Collective on ts 1714814e85d6SHong Zhang 17154165533cSJose E. Roman Input Parameter: 1716814e85d6SHong Zhang . ts - time stepping context 1717814e85d6SHong Zhang 1718814e85d6SHong Zhang Level: advanced 1719814e85d6SHong Zhang 1720*bcf0153eSBarry Smith Note: 1721*bcf0153eSBarry Smith This function cannot be called until `TSStep()` has been completed. 1722814e85d6SHong Zhang 1723*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TS`, `TSSolve()`, `TSAdjointCostIntegral()` 1724814e85d6SHong Zhang @*/ 1725d71ae5a4SJacob Faibussowitsch PetscErrorCode TSForwardCostIntegral(TS ts) 1726d71ae5a4SJacob Faibussowitsch { 1727362febeeSStefano Zampini PetscFunctionBegin; 1728814e85d6SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1729dbbe0bcdSBarry Smith PetscUseTypeMethod(ts, forwardintegral); 1730814e85d6SHong Zhang PetscFunctionReturn(0); 1731814e85d6SHong Zhang } 1732b5b4017aSHong Zhang 1733b5b4017aSHong Zhang /*@ 1734b5b4017aSHong Zhang TSForwardSetInitialSensitivities - Set initial values for tangent linear sensitivities 1735b5b4017aSHong Zhang 1736*bcf0153eSBarry Smith Collective on ts 1737b5b4017aSHong Zhang 1738d8d19677SJose E. Roman Input Parameters: 1739*bcf0153eSBarry Smith + ts - the `TS` context obtained from `TSCreate()` 1740b5b4017aSHong Zhang - didp - parametric sensitivities of the initial condition 1741b5b4017aSHong Zhang 1742b5b4017aSHong Zhang Level: intermediate 1743b5b4017aSHong Zhang 1744*bcf0153eSBarry Smith Notes: 1745*bcf0153eSBarry Smith `TSSolve()` allows users to pass the initial solution directly to `TS`. But the tangent linear variables cannot be initialized in this way. 1746*bcf0153eSBarry Smith This function is used to set initial values for tangent linear variables. 1747b5b4017aSHong Zhang 1748*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TS`, `TSForwardSetSensitivities()` 1749b5b4017aSHong Zhang @*/ 1750d71ae5a4SJacob Faibussowitsch PetscErrorCode TSForwardSetInitialSensitivities(TS ts, Mat didp) 1751d71ae5a4SJacob Faibussowitsch { 1752362febeeSStefano Zampini PetscFunctionBegin; 1753b5b4017aSHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1754b5b4017aSHong Zhang PetscValidHeaderSpecific(didp, MAT_CLASSID, 2); 175548a46eb9SPierre Jolivet if (!ts->mat_sensip) PetscCall(TSForwardSetSensitivities(ts, PETSC_DEFAULT, didp)); 1756b5b4017aSHong Zhang PetscFunctionReturn(0); 1757b5b4017aSHong Zhang } 17586affb6f8SHong Zhang 17596affb6f8SHong Zhang /*@ 17606affb6f8SHong Zhang TSForwardGetStages - Get the number of stages and the tangent linear sensitivities at the intermediate stages 17616affb6f8SHong Zhang 17626affb6f8SHong Zhang Input Parameter: 1763*bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()` 17646affb6f8SHong Zhang 17656affb6f8SHong Zhang Output Parameters: 1766cd4cee2dSHong Zhang + ns - number of stages 17676affb6f8SHong Zhang - S - tangent linear sensitivities at the intermediate stages 17686affb6f8SHong Zhang 17696affb6f8SHong Zhang Level: advanced 17706affb6f8SHong Zhang 1771*bcf0153eSBarry Smith .seealso: `TS` 17726affb6f8SHong Zhang @*/ 1773d71ae5a4SJacob Faibussowitsch PetscErrorCode TSForwardGetStages(TS ts, PetscInt *ns, Mat **S) 1774d71ae5a4SJacob Faibussowitsch { 17756affb6f8SHong Zhang PetscFunctionBegin; 17766affb6f8SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 17776affb6f8SHong Zhang 17786affb6f8SHong Zhang if (!ts->ops->getstages) *S = NULL; 1779dbbe0bcdSBarry Smith else PetscUseTypeMethod(ts, forwardgetstages, ns, S); 17806affb6f8SHong Zhang PetscFunctionReturn(0); 17816affb6f8SHong Zhang } 1782cd4cee2dSHong Zhang 1783cd4cee2dSHong Zhang /*@ 1784*bcf0153eSBarry Smith TSCreateQuadratureTS - Create a sub-`TS` that evaluates integrals over time 1785cd4cee2dSHong Zhang 1786d8d19677SJose E. Roman Input Parameters: 1787*bcf0153eSBarry Smith + ts - the `TS` context obtained from `TSCreate()` 1788cd4cee2dSHong Zhang - fwd - flag indicating whether to evaluate cost integral in the forward run or the adjoint run 1789cd4cee2dSHong Zhang 1790cd4cee2dSHong Zhang Output Parameters: 1791*bcf0153eSBarry Smith . quadts - the child `TS` context 1792cd4cee2dSHong Zhang 1793cd4cee2dSHong Zhang Level: intermediate 1794cd4cee2dSHong Zhang 1795*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TSGetQuadratureTS()` 1796cd4cee2dSHong Zhang @*/ 1797d71ae5a4SJacob Faibussowitsch PetscErrorCode TSCreateQuadratureTS(TS ts, PetscBool fwd, TS *quadts) 1798d71ae5a4SJacob Faibussowitsch { 1799cd4cee2dSHong Zhang char prefix[128]; 1800cd4cee2dSHong Zhang 1801cd4cee2dSHong Zhang PetscFunctionBegin; 1802cd4cee2dSHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1803064a246eSJacob Faibussowitsch PetscValidPointer(quadts, 3); 18049566063dSJacob Faibussowitsch PetscCall(TSDestroy(&ts->quadraturets)); 18059566063dSJacob Faibussowitsch PetscCall(TSCreate(PetscObjectComm((PetscObject)ts), &ts->quadraturets)); 18069566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)ts->quadraturets, (PetscObject)ts, 1)); 18079566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(prefix, sizeof(prefix), "%squad_", ((PetscObject)ts)->prefix ? ((PetscObject)ts)->prefix : "")); 18089566063dSJacob Faibussowitsch PetscCall(TSSetOptionsPrefix(ts->quadraturets, prefix)); 1809cd4cee2dSHong Zhang *quadts = ts->quadraturets; 1810cd4cee2dSHong Zhang 1811cd4cee2dSHong Zhang if (ts->numcost) { 18129566063dSJacob Faibussowitsch PetscCall(VecCreateSeq(PETSC_COMM_SELF, ts->numcost, &(*quadts)->vec_sol)); 1813cd4cee2dSHong Zhang } else { 18149566063dSJacob Faibussowitsch PetscCall(VecCreateSeq(PETSC_COMM_SELF, 1, &(*quadts)->vec_sol)); 1815cd4cee2dSHong Zhang } 1816cd4cee2dSHong Zhang ts->costintegralfwd = fwd; 1817cd4cee2dSHong Zhang PetscFunctionReturn(0); 1818cd4cee2dSHong Zhang } 1819cd4cee2dSHong Zhang 1820cd4cee2dSHong Zhang /*@ 1821*bcf0153eSBarry Smith TSGetQuadratureTS - Return the sub-`TS` that evaluates integrals over time 1822cd4cee2dSHong Zhang 1823cd4cee2dSHong Zhang Input Parameter: 1824*bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()` 1825cd4cee2dSHong Zhang 1826cd4cee2dSHong Zhang Output Parameters: 1827cd4cee2dSHong Zhang + fwd - flag indicating whether to evaluate cost integral in the forward run or the adjoint run 1828*bcf0153eSBarry Smith - quadts - the child `TS` context 1829cd4cee2dSHong Zhang 1830cd4cee2dSHong Zhang Level: intermediate 1831cd4cee2dSHong Zhang 1832*bcf0153eSBarry Smith .seealso: [](chapter_ts), `TSCreateQuadratureTS()` 1833cd4cee2dSHong Zhang @*/ 1834d71ae5a4SJacob Faibussowitsch PetscErrorCode TSGetQuadratureTS(TS ts, PetscBool *fwd, TS *quadts) 1835d71ae5a4SJacob Faibussowitsch { 1836cd4cee2dSHong Zhang PetscFunctionBegin; 1837cd4cee2dSHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1838cd4cee2dSHong Zhang if (fwd) *fwd = ts->costintegralfwd; 1839cd4cee2dSHong Zhang if (quadts) *quadts = ts->quadraturets; 1840cd4cee2dSHong Zhang PetscFunctionReturn(0); 1841cd4cee2dSHong Zhang } 1842ba0675f6SHong Zhang 1843ba0675f6SHong Zhang /*@ 1844*bcf0153eSBarry Smith TSComputeSNESJacobian - Compute the Jacobian needed for the `SNESSolve()` in `TS` 1845*bcf0153eSBarry Smith 1846*bcf0153eSBarry Smith Collective on ts 1847ba0675f6SHong Zhang 1848ba0675f6SHong Zhang Input Parameters: 1849*bcf0153eSBarry Smith + ts - the `TS` context obtained from `TSCreate()` 1850ba0675f6SHong Zhang - x - state vector 1851ba0675f6SHong Zhang 1852ba0675f6SHong Zhang Output Parameters: 1853ba0675f6SHong Zhang + J - Jacobian matrix 1854ba0675f6SHong Zhang - Jpre - preconditioning matrix for J (may be same as J) 1855ba0675f6SHong Zhang 1856ba0675f6SHong Zhang Level: developer 1857ba0675f6SHong Zhang 1858*bcf0153eSBarry Smith Note: 1859*bcf0153eSBarry Smith Uses finite differencing when `TS` Jacobian is not available. 1860*bcf0153eSBarry Smith 1861*bcf0153eSBarry Smith .seealso: `SNES`, `TS`, `SNESSetJacobian()`, TSSetRHSJacobian()`, `TSSetIJacobian()` 1862ba0675f6SHong Zhang @*/ 1863d71ae5a4SJacob Faibussowitsch PetscErrorCode TSComputeSNESJacobian(TS ts, Vec x, Mat J, Mat Jpre) 1864d71ae5a4SJacob Faibussowitsch { 1865ba0675f6SHong Zhang SNES snes = ts->snes; 1866ba0675f6SHong Zhang PetscErrorCode (*jac)(SNES, Vec, Mat, Mat, void *) = NULL; 1867ba0675f6SHong Zhang 1868ba0675f6SHong Zhang PetscFunctionBegin; 1869ba0675f6SHong Zhang /* 1870ba0675f6SHong Zhang Unlike implicit methods, explicit methods do not have SNESMatFDColoring in the snes object 1871ba0675f6SHong Zhang because SNESSolve() has not been called yet; so querying SNESMatFDColoring does not work for 1872ba0675f6SHong Zhang explicit methods. Instead, we check the Jacobian compute function directly to determin if FD 1873ba0675f6SHong Zhang coloring is used. 1874ba0675f6SHong Zhang */ 18759566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes, NULL, NULL, &jac, NULL)); 1876ba0675f6SHong Zhang if (jac == SNESComputeJacobianDefaultColor) { 1877ba0675f6SHong Zhang Vec f; 18789566063dSJacob Faibussowitsch PetscCall(SNESSetSolution(snes, x)); 18799566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, &f, NULL, NULL)); 1880ba0675f6SHong Zhang /* Force MatFDColoringApply to evaluate the SNES residual function for the base vector */ 18819566063dSJacob Faibussowitsch PetscCall(SNESComputeFunction(snes, x, f)); 1882ba0675f6SHong Zhang } 18839566063dSJacob Faibussowitsch PetscCall(SNESComputeJacobian(snes, x, J, Jpre)); 1884ba0675f6SHong Zhang PetscFunctionReturn(0); 1885ba0675f6SHong Zhang } 1886