1 #include <petsc/private/tsimpl.h> /*I "petscts.h" I*/ 2 #include <petscdraw.h> 3 4 PetscLogEvent TS_AdjointStep,TS_ForwardStep,TS_JacobianPEval; 5 6 /* ------------------------ Sensitivity Context ---------------------------*/ 7 8 /*@C 9 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. 10 11 Logically Collective on TS 12 13 Input Parameters: 14 + ts - TS context obtained from TSCreate() 15 . Amat - JacobianP matrix 16 . func - function 17 - ctx - [optional] user-defined function context 18 19 Calling sequence of func: 20 $ func (TS ts,PetscReal t,Vec y,Mat A,void *ctx); 21 + t - current timestep 22 . U - input vector (current ODE solution) 23 . A - output matrix 24 - ctx - [optional] user-defined function context 25 26 Level: intermediate 27 28 Notes: 29 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 30 31 .keywords: TS, sensitivity 32 .seealso: TSGetRHSJacobianP() 33 @*/ 34 PetscErrorCode TSSetRHSJacobianP(TS ts,Mat Amat,PetscErrorCode (*func)(TS,PetscReal,Vec,Mat,void*),void *ctx) 35 { 36 PetscErrorCode ierr; 37 38 PetscFunctionBegin; 39 PetscValidHeaderSpecific(ts, TS_CLASSID,1); 40 PetscValidHeaderSpecific(Amat,MAT_CLASSID,2); 41 42 ts->rhsjacobianp = func; 43 ts->rhsjacobianpctx = ctx; 44 if(Amat) { 45 ierr = PetscObjectReference((PetscObject)Amat);CHKERRQ(ierr); 46 ierr = MatDestroy(&ts->Jacprhs);CHKERRQ(ierr); 47 ts->Jacprhs = Amat; 48 } 49 PetscFunctionReturn(0); 50 } 51 52 /*@C 53 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. 54 55 Logically Collective on TS 56 57 Input Parameters: 58 . ts - TS context obtained from TSCreate() 59 60 Output Parameters: 61 + Amat - JacobianP matrix 62 . func - function 63 - ctx - [optional] user-defined function context 64 65 Calling sequence of func: 66 $ func (TS ts,PetscReal t,Vec y,Mat A,void *ctx); 67 + t - current timestep 68 . U - input vector (current ODE solution) 69 . A - output matrix 70 - ctx - [optional] user-defined function context 71 72 Level: intermediate 73 74 Notes: 75 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 76 77 .keywords: TS, sensitivity 78 .seealso: TSSetRHSJacobianP() 79 @*/ 80 PetscErrorCode TSGetRHSJacobianP(TS ts,Mat *Amat,PetscErrorCode (**func)(TS,PetscReal,Vec,Mat,void*),void **ctx) 81 { 82 PetscFunctionBegin; 83 if (func) *func = ts->rhsjacobianp; 84 if (ctx) *ctx = ts->rhsjacobianpctx; 85 if (Amat) *Amat = ts->Jacprhs; 86 PetscFunctionReturn(0); 87 } 88 89 /*@C 90 TSComputeRHSJacobianP - Runs the user-defined JacobianP function. 91 92 Collective on TS 93 94 Input Parameters: 95 . ts - The TS context obtained from TSCreate() 96 97 Level: developer 98 99 .keywords: TS, sensitivity 100 .seealso: TSSetRHSJacobianP() 101 @*/ 102 PetscErrorCode TSComputeRHSJacobianP(TS ts,PetscReal t,Vec U,Mat Amat) 103 { 104 PetscErrorCode ierr; 105 106 PetscFunctionBegin; 107 if (!Amat) PetscFunctionReturn(0); 108 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 109 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 110 111 PetscStackPush("TS user JacobianP function for sensitivity analysis"); 112 ierr = (*ts->rhsjacobianp)(ts,t,U,Amat,ts->rhsjacobianpctx);CHKERRQ(ierr); 113 PetscStackPop; 114 PetscFunctionReturn(0); 115 } 116 117 /*@C 118 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. 119 120 Logically Collective on TS 121 122 Input Parameters: 123 + ts - TS context obtained from TSCreate() 124 . Amat - JacobianP matrix 125 . func - function 126 - ctx - [optional] user-defined function context 127 128 Calling sequence of func: 129 $ func (TS ts,PetscReal t,Vec y,Mat A,void *ctx); 130 + t - current timestep 131 . U - input vector (current ODE solution) 132 . Udot - time derivative of state vector 133 . shift - shift to apply, see note below 134 . A - output matrix 135 - ctx - [optional] user-defined function context 136 137 Level: intermediate 138 139 Notes: 140 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 141 142 .keywords: TS, sensitivity 143 .seealso: 144 @*/ 145 PetscErrorCode TSSetIJacobianP(TS ts,Mat Amat,PetscErrorCode (*func)(TS,PetscReal,Vec,Vec,PetscReal,Mat,void*),void *ctx) 146 { 147 PetscErrorCode ierr; 148 149 PetscFunctionBegin; 150 PetscValidHeaderSpecific(ts, TS_CLASSID,1); 151 PetscValidHeaderSpecific(Amat,MAT_CLASSID,2); 152 153 ts->ijacobianp = func; 154 ts->ijacobianpctx = ctx; 155 if(Amat) { 156 ierr = PetscObjectReference((PetscObject)Amat);CHKERRQ(ierr); 157 ierr = MatDestroy(&ts->Jacp);CHKERRQ(ierr); 158 ts->Jacp = Amat; 159 } 160 PetscFunctionReturn(0); 161 } 162 163 /*@C 164 TSComputeIJacobianP - Runs the user-defined IJacobianP function. 165 166 Collective on TS 167 168 Input Parameters: 169 + ts - the TS context 170 . t - current timestep 171 . U - state vector 172 . Udot - time derivative of state vector 173 . shift - shift to apply, see note below 174 - imex - flag indicates if the method is IMEX so that the RHSJacobian should be kept separate 175 176 Output Parameters: 177 . A - Jacobian matrix 178 179 Level: developer 180 181 .keywords: TS, sensitivity 182 .seealso: TSSetIJacobianP() 183 @*/ 184 PetscErrorCode TSComputeIJacobianP(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal shift,Mat Amat,PetscBool imex) 185 { 186 PetscErrorCode ierr; 187 188 PetscFunctionBegin; 189 if (!Amat) PetscFunctionReturn(0); 190 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 191 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 192 PetscValidHeaderSpecific(Udot,VEC_CLASSID,4); 193 194 ierr = PetscLogEventBegin(TS_JacobianPEval,ts,U,Amat,0);CHKERRQ(ierr); 195 if (ts->ijacobianp) { 196 PetscStackPush("TS user JacobianP function for sensitivity analysis"); 197 ierr = (*ts->ijacobianp)(ts,t,U,Udot,shift,Amat,ts->ijacobianpctx);CHKERRQ(ierr); 198 PetscStackPop; 199 } 200 if (imex) { 201 if (!ts->ijacobianp) { /* system was written as Udot = G(t,U) */ 202 PetscBool assembled; 203 ierr = MatZeroEntries(Amat);CHKERRQ(ierr); 204 ierr = MatAssembled(Amat,&assembled);CHKERRQ(ierr); 205 if (!assembled) { 206 ierr = MatAssemblyBegin(Amat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 207 ierr = MatAssemblyEnd(Amat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 208 } 209 } 210 } else { 211 if (ts->rhsjacobianp) { 212 ierr = TSComputeRHSJacobianP(ts,t,U,ts->Jacprhs);CHKERRQ(ierr); 213 } 214 if (ts->Jacprhs == Amat) { /* No IJacobian, so we only have the RHS matrix */ 215 ierr = MatScale(Amat,-1);CHKERRQ(ierr); 216 } else if (ts->Jacprhs) { /* Both IJacobian and RHSJacobian */ 217 MatStructure axpy = DIFFERENT_NONZERO_PATTERN; 218 if (!ts->ijacobianp) { /* No IJacobianp provided, but we have a separate RHS matrix */ 219 ierr = MatZeroEntries(Amat);CHKERRQ(ierr); 220 } 221 ierr = MatAXPY(Amat,-1,ts->Jacprhs,axpy);CHKERRQ(ierr); 222 } 223 } 224 ierr = PetscLogEventEnd(TS_JacobianPEval,ts,U,Amat,0);CHKERRQ(ierr); 225 PetscFunctionReturn(0); 226 } 227 228 /*@C 229 TSSetCostIntegrand - Sets the routine for evaluating the integral term in one or more cost functions 230 231 Logically Collective on TS 232 233 Input Parameters: 234 + ts - the TS context obtained from TSCreate() 235 . numcost - number of gradients to be computed, this is the number of cost functions 236 . costintegral - vector that stores the integral values 237 . rf - routine for evaluating the integrand function 238 . drduf - function that computes the gradients of the r's with respect to u 239 . 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) 240 . fwd - flag indicating whether to evaluate cost integral in the forward run or the adjoint run 241 - ctx - [optional] user-defined context for private data for the function evaluation routine (may be NULL) 242 243 Calling sequence of rf: 244 $ PetscErrorCode rf(TS ts,PetscReal t,Vec U,Vec F,void *ctx); 245 246 Calling sequence of drduf: 247 $ PetscErroCode drduf(TS ts,PetscReal t,Vec U,Vec *dRdU,void *ctx); 248 249 Calling sequence of drdpf: 250 $ PetscErroCode drdpf(TS ts,PetscReal t,Vec U,Vec *dRdP,void *ctx); 251 252 Level: deprecated 253 254 Notes: 255 For optimization there is usually a single cost function (numcost = 1). For sensitivities there may be multiple cost functions 256 257 .keywords: TS, sensitivity analysis, timestep, set, quadrature, function 258 259 .seealso: TSSetRHSJacobianP(), TSGetCostGradients(), TSSetCostGradients() 260 @*/ 261 PetscErrorCode TSSetCostIntegrand(TS ts,PetscInt numcost,Vec costintegral,PetscErrorCode (*rf)(TS,PetscReal,Vec,Vec,void*), 262 PetscErrorCode (*drduf)(TS,PetscReal,Vec,Vec*,void*), 263 PetscErrorCode (*drdpf)(TS,PetscReal,Vec,Vec*,void*), 264 PetscBool fwd,void *ctx) 265 { 266 PetscErrorCode ierr; 267 268 PetscFunctionBegin; 269 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 270 if (costintegral) PetscValidHeaderSpecific(costintegral,VEC_CLASSID,3); 271 if (ts->numcost && ts->numcost!=numcost) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"The number of cost functions (2rd parameter of TSSetCostIntegrand()) is inconsistent with the one set by TSSetCostGradients() or TSForwardSetIntegralGradients()"); 272 if (!ts->numcost) ts->numcost=numcost; 273 274 if (costintegral) { 275 ierr = PetscObjectReference((PetscObject)costintegral);CHKERRQ(ierr); 276 ierr = VecDestroy(&ts->vec_costintegral);CHKERRQ(ierr); 277 ts->vec_costintegral = costintegral; 278 } else { 279 if (!ts->vec_costintegral) { /* Create a seq vec if user does not provide one */ 280 ierr = VecCreateSeq(PETSC_COMM_SELF,numcost,&ts->vec_costintegral);CHKERRQ(ierr); 281 } else { 282 ierr = VecSet(ts->vec_costintegral,0.0);CHKERRQ(ierr); 283 } 284 } 285 if (!ts->vec_costintegrand) { 286 ierr = VecDuplicate(ts->vec_costintegral,&ts->vec_costintegrand);CHKERRQ(ierr); 287 } else { 288 ierr = VecSet(ts->vec_costintegrand,0.0);CHKERRQ(ierr); 289 } 290 ts->costintegralfwd = fwd; /* Evaluate the cost integral in forward run if fwd is true */ 291 ts->costintegrand = rf; 292 ts->costintegrandctx = ctx; 293 ts->drdufunction = drduf; 294 ts->drdpfunction = drdpf; 295 PetscFunctionReturn(0); 296 } 297 298 /*@C 299 TSGetCostIntegral - Returns the values of the integral term in the cost functions. 300 It is valid to call the routine after a backward run. 301 302 Not Collective 303 304 Input Parameter: 305 . ts - the TS context obtained from TSCreate() 306 307 Output Parameter: 308 . v - the vector containing the integrals for each cost function 309 310 Level: intermediate 311 312 .seealso: TSSetCostIntegrand() 313 314 .keywords: TS, sensitivity analysis 315 @*/ 316 PetscErrorCode TSGetCostIntegral(TS ts,Vec *v) 317 { 318 TS quadts; 319 PetscErrorCode ierr; 320 321 PetscFunctionBegin; 322 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 323 PetscValidPointer(v,2); 324 ierr = TSGetQuadratureTS(ts,NULL,&quadts);CHKERRQ(ierr); 325 *v = quadts->vec_sol; 326 PetscFunctionReturn(0); 327 } 328 329 /*@C 330 TSComputeCostIntegrand - Evaluates the integral function in the cost functions. 331 332 Input Parameters: 333 + ts - the TS context 334 . t - current time 335 - U - state vector, i.e. current solution 336 337 Output Parameter: 338 . Q - vector of size numcost to hold the outputs 339 340 Notes: 341 Most users should not need to explicitly call this routine, as it 342 is used internally within the sensitivity analysis context. 343 344 Level: deprecated 345 346 .keywords: TS, compute 347 348 .seealso: TSSetCostIntegrand() 349 @*/ 350 PetscErrorCode TSComputeCostIntegrand(TS ts,PetscReal t,Vec U,Vec Q) 351 { 352 PetscErrorCode ierr; 353 354 PetscFunctionBegin; 355 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 356 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 357 PetscValidHeaderSpecific(Q,VEC_CLASSID,4); 358 359 ierr = PetscLogEventBegin(TS_FunctionEval,ts,U,Q,0);CHKERRQ(ierr); 360 if (ts->costintegrand) { 361 PetscStackPush("TS user integrand in the cost function"); 362 ierr = (*ts->costintegrand)(ts,t,U,Q,ts->costintegrandctx);CHKERRQ(ierr); 363 PetscStackPop; 364 } else { 365 ierr = VecZeroEntries(Q);CHKERRQ(ierr); 366 } 367 368 ierr = PetscLogEventEnd(TS_FunctionEval,ts,U,Q,0);CHKERRQ(ierr); 369 PetscFunctionReturn(0); 370 } 371 372 /*@C 373 TSComputeDRDUFunction - Runs the user-defined DRDU function. 374 375 Collective on TS 376 377 Input Parameters: 378 + ts - the TS context obtained from TSCreate() 379 . t - current time 380 - U - stata vector 381 382 Output Parameters: 383 . DRDU - vector array to hold the outputs 384 385 Notes: 386 TSComputeDRDUFunction() is typically used for sensitivity implementation, 387 so most users would not generally call this routine themselves. 388 389 Level: developer 390 391 .keywords: TS, sensitivity 392 .seealso: TSSetCostIntegrand() 393 @*/ 394 PetscErrorCode TSComputeDRDUFunction(TS ts,PetscReal t,Vec U,Vec *DRDU) 395 { 396 PetscErrorCode ierr; 397 398 PetscFunctionBegin; 399 if (!DRDU) PetscFunctionReturn(0); 400 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 401 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 402 403 PetscStackPush("TS user DRDU function for sensitivity analysis"); 404 ierr = (*ts->drdufunction)(ts,t,U,DRDU,ts->costintegrandctx); CHKERRQ(ierr); 405 PetscStackPop; 406 PetscFunctionReturn(0); 407 } 408 409 /*@C 410 TSComputeDRDPFunction - Runs the user-defined DRDP function. 411 412 Collective on TS 413 414 Input Parameters: 415 + ts - the TS context obtained from TSCreate() 416 . t - current time 417 - U - stata vector 418 419 Output Parameters: 420 . DRDP - vector array to hold the outputs 421 422 Notes: 423 TSComputeDRDPFunction() is typically used for sensitivity implementation, 424 so most users would not generally call this routine themselves. 425 426 Level: developer 427 428 .keywords: TS, sensitivity 429 .seealso: TSSetCostIntegrand() 430 @*/ 431 PetscErrorCode TSComputeDRDPFunction(TS ts,PetscReal t,Vec U,Vec *DRDP) 432 { 433 PetscErrorCode ierr; 434 435 PetscFunctionBegin; 436 if (!DRDP) PetscFunctionReturn(0); 437 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 438 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 439 440 PetscStackPush("TS user DRDP function for sensitivity analysis"); 441 ierr = (*ts->drdpfunction)(ts,t,U,DRDP,ts->costintegrandctx); CHKERRQ(ierr); 442 PetscStackPop; 443 PetscFunctionReturn(0); 444 } 445 446 /*@C 447 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. 448 449 Logically Collective on TS 450 451 Input Parameters: 452 + ts - TS context obtained from TSCreate() 453 . ihp1 - an array of vectors storing the result of vector-Hessian-vector product for F_UU 454 . hessianproductfunc1 - vector-Hessian-vector product function for F_UU 455 . ihp2 - an array of vectors storing the result of vector-Hessian-vector product for F_UP 456 . hessianproductfunc2 - vector-Hessian-vector product function for F_UP 457 . ihp3 - an array of vectors storing the result of vector-Hessian-vector product for F_PU 458 . hessianproductfunc3 - vector-Hessian-vector product function for F_PU 459 . ihp4 - an array of vectors storing the result of vector-Hessian-vector product for F_PP 460 . hessianproductfunc4 - vector-Hessian-vector product function for F_PP 461 462 Calling sequence of ihessianproductfunc: 463 $ ihessianproductfunc (TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV,void *ctx); 464 + t - current timestep 465 . U - input vector (current ODE solution) 466 . Vl - an array of input vectors to be left-multiplied with the Hessian 467 . Vr - input vector to be right-multiplied with the Hessian 468 . VHV - an array of output vectors for vector-Hessian-vector product 469 - ctx - [optional] user-defined function context 470 471 Level: intermediate 472 473 Notes: 474 The first Hessian function and the working array are required. 475 As an example to implement the callback functions, the second callback function calculates the vector-Hessian-vector product 476 $ Vl_n^T*F_UP*Vr 477 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. 478 Each entry of F_UP corresponds to the derivative 479 $ F_UP[i][j][k] = \frac{\partial^2 F[i]}{\partial U[j] \partial P[k]}. 480 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 481 $ VHV_n[j] = \sum_i \sum_k {Vl_n[i] * F_UP[i][j][k] * Vr[k]} 482 If the cost function is a scalar, there will be only one vector in Vl and VHV. 483 484 .keywords: TS, sensitivity 485 486 .seealso: 487 @*/ 488 PetscErrorCode TSSetIHessianProduct(TS ts,Vec *ihp1,PetscErrorCode (*ihessianproductfunc1)(TS,PetscReal,Vec,Vec*,Vec,Vec*,void*), 489 Vec *ihp2,PetscErrorCode (*ihessianproductfunc2)(TS,PetscReal,Vec,Vec*,Vec,Vec*,void*), 490 Vec *ihp3,PetscErrorCode (*ihessianproductfunc3)(TS,PetscReal,Vec,Vec*,Vec,Vec*,void*), 491 Vec *ihp4,PetscErrorCode (*ihessianproductfunc4)(TS,PetscReal,Vec,Vec*,Vec,Vec*,void*), 492 void *ctx) 493 { 494 PetscFunctionBegin; 495 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 496 PetscValidPointer(ihp1,2); 497 498 ts->ihessianproductctx = ctx; 499 if (ihp1) ts->vecs_fuu = ihp1; 500 if (ihp2) ts->vecs_fup = ihp2; 501 if (ihp3) ts->vecs_fpu = ihp3; 502 if (ihp4) ts->vecs_fpp = ihp4; 503 ts->ihessianproduct_fuu = ihessianproductfunc1; 504 ts->ihessianproduct_fup = ihessianproductfunc2; 505 ts->ihessianproduct_fpu = ihessianproductfunc3; 506 ts->ihessianproduct_fpp = ihessianproductfunc4; 507 PetscFunctionReturn(0); 508 } 509 510 /*@C 511 TSComputeIHessianProductFunctionUU - Runs the user-defined vector-Hessian-vector product function for Fuu. 512 513 Collective on TS 514 515 Input Parameters: 516 . ts - The TS context obtained from TSCreate() 517 518 Notes: 519 TSComputeIHessianProductFunctionUU() is typically used for sensitivity implementation, 520 so most users would not generally call this routine themselves. 521 522 Level: developer 523 524 .keywords: TS, sensitivity 525 526 .seealso: TSSetIHessianProduct() 527 @*/ 528 PetscErrorCode TSComputeIHessianProductFunctionUU(TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV) 529 { 530 PetscErrorCode ierr; 531 532 PetscFunctionBegin; 533 if (!VHV) PetscFunctionReturn(0); 534 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 535 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 536 537 if (ts->ihessianproduct_fuu) { 538 PetscStackPush("TS user IHessianProduct function 1 for sensitivity analysis"); 539 ierr = (*ts->ihessianproduct_fuu)(ts,t,U,Vl,Vr,VHV,ts->ihessianproductctx);CHKERRQ(ierr); 540 PetscStackPop; 541 } 542 /* does not consider IMEX for now, so either IHessian or RHSHessian will be calculated, using the same output VHV */ 543 if (ts->rhshessianproduct_guu) { 544 PetscInt nadj; 545 ierr = TSComputeRHSHessianProductFunctionUU(ts,t,U,Vl,Vr,VHV);CHKERRQ(ierr); 546 for (nadj=0; nadj<ts->numcost; nadj++) { 547 ierr = VecScale(VHV[nadj],-1);CHKERRQ(ierr); 548 } 549 } 550 PetscFunctionReturn(0); 551 } 552 553 /*@C 554 TSComputeIHessianProductFunctionUP - Runs the user-defined vector-Hessian-vector product function for Fup. 555 556 Collective on TS 557 558 Input Parameters: 559 . ts - The TS context obtained from TSCreate() 560 561 Notes: 562 TSComputeIHessianProductFunctionUP() is typically used for sensitivity implementation, 563 so most users would not generally call this routine themselves. 564 565 Level: developer 566 567 .keywords: TS, sensitivity 568 569 .seealso: TSSetIHessianProduct() 570 @*/ 571 PetscErrorCode TSComputeIHessianProductFunctionUP(TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV) 572 { 573 PetscErrorCode ierr; 574 575 PetscFunctionBegin; 576 if (!VHV) PetscFunctionReturn(0); 577 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 578 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 579 580 if (ts->ihessianproduct_fup) { 581 PetscStackPush("TS user IHessianProduct function 2 for sensitivity analysis"); 582 ierr = (*ts->ihessianproduct_fup)(ts,t,U,Vl,Vr,VHV,ts->ihessianproductctx);CHKERRQ(ierr); 583 PetscStackPop; 584 } 585 /* does not consider IMEX for now, so either IHessian or RHSHessian will be calculated, using the same output VHV */ 586 if (ts->rhshessianproduct_gup) { 587 PetscInt nadj; 588 ierr = TSComputeRHSHessianProductFunctionUP(ts,t,U,Vl,Vr,VHV);CHKERRQ(ierr); 589 for (nadj=0; nadj<ts->numcost; nadj++) { 590 ierr = VecScale(VHV[nadj],-1);CHKERRQ(ierr); 591 } 592 } 593 PetscFunctionReturn(0); 594 } 595 596 /*@C 597 TSComputeIHessianProductFunctionPU - Runs the user-defined vector-Hessian-vector product function for Fpu. 598 599 Collective on TS 600 601 Input Parameters: 602 . ts - The TS context obtained from TSCreate() 603 604 Notes: 605 TSComputeIHessianProductFunctionPU() is typically used for sensitivity implementation, 606 so most users would not generally call this routine themselves. 607 608 Level: developer 609 610 .keywords: TS, sensitivity 611 612 .seealso: TSSetIHessianProduct() 613 @*/ 614 PetscErrorCode TSComputeIHessianProductFunctionPU(TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV) 615 { 616 PetscErrorCode ierr; 617 618 PetscFunctionBegin; 619 if (!VHV) PetscFunctionReturn(0); 620 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 621 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 622 623 if (ts->ihessianproduct_fpu) { 624 PetscStackPush("TS user IHessianProduct function 3 for sensitivity analysis"); 625 ierr = (*ts->ihessianproduct_fpu)(ts,t,U,Vl,Vr,VHV,ts->ihessianproductctx);CHKERRQ(ierr); 626 PetscStackPop; 627 } 628 /* does not consider IMEX for now, so either IHessian or RHSHessian will be calculated, using the same output VHV */ 629 if (ts->rhshessianproduct_gpu) { 630 PetscInt nadj; 631 ierr = TSComputeRHSHessianProductFunctionPU(ts,t,U,Vl,Vr,VHV);CHKERRQ(ierr); 632 for (nadj=0; nadj<ts->numcost; nadj++) { 633 ierr = VecScale(VHV[nadj],-1);CHKERRQ(ierr); 634 } 635 } 636 PetscFunctionReturn(0); 637 } 638 639 /*@C 640 TSComputeIHessianProductFunctionPP - Runs the user-defined vector-Hessian-vector product function for Fpp. 641 642 Collective on TS 643 644 Input Parameters: 645 . ts - The TS context obtained from TSCreate() 646 647 Notes: 648 TSComputeIHessianProductFunctionPP() is typically used for sensitivity implementation, 649 so most users would not generally call this routine themselves. 650 651 Level: developer 652 653 .keywords: TS, sensitivity 654 655 .seealso: TSSetIHessianProduct() 656 @*/ 657 PetscErrorCode TSComputeIHessianProductFunctionPP(TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV) 658 { 659 PetscErrorCode ierr; 660 661 PetscFunctionBegin; 662 if (!VHV) PetscFunctionReturn(0); 663 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 664 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 665 666 if (ts->ihessianproduct_fpp) { 667 PetscStackPush("TS user IHessianProduct function 3 for sensitivity analysis"); 668 ierr = (*ts->ihessianproduct_fpp)(ts,t,U,Vl,Vr,VHV,ts->ihessianproductctx);CHKERRQ(ierr); 669 PetscStackPop; 670 } 671 /* does not consider IMEX for now, so either IHessian or RHSHessian will be calculated, using the same output VHV */ 672 if (ts->rhshessianproduct_gpp) { 673 PetscInt nadj; 674 ierr = TSComputeRHSHessianProductFunctionPP(ts,t,U,Vl,Vr,VHV);CHKERRQ(ierr); 675 for (nadj=0; nadj<ts->numcost; nadj++) { 676 ierr = VecScale(VHV[nadj],-1);CHKERRQ(ierr); 677 } 678 } 679 PetscFunctionReturn(0); 680 } 681 682 /*@C 683 TSSetRHSHessianProduct - Sets the function that computes the vecotr-Hessian-vector product. The Hessian is the second-order derivative of G (RHSFunction) w.r.t. the state variable. 684 685 Logically Collective on TS 686 687 Input Parameters: 688 + ts - TS context obtained from TSCreate() 689 . rhshp1 - an array of vectors storing the result of vector-Hessian-vector product for G_UU 690 . hessianproductfunc1 - vector-Hessian-vector product function for G_UU 691 . rhshp2 - an array of vectors storing the result of vector-Hessian-vector product for G_UP 692 . hessianproductfunc2 - vector-Hessian-vector product function for G_UP 693 . rhshp3 - an array of vectors storing the result of vector-Hessian-vector product for G_PU 694 . hessianproductfunc3 - vector-Hessian-vector product function for G_PU 695 . rhshp4 - an array of vectors storing the result of vector-Hessian-vector product for G_PP 696 . hessianproductfunc4 - vector-Hessian-vector product function for G_PP 697 698 Calling sequence of ihessianproductfunc: 699 $ rhshessianproductfunc (TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV,void *ctx); 700 + t - current timestep 701 . U - input vector (current ODE solution) 702 . Vl - an array of input vectors to be left-multiplied with the Hessian 703 . Vr - input vector to be right-multiplied with the Hessian 704 . VHV - an array of output vectors for vector-Hessian-vector product 705 - ctx - [optional] user-defined function context 706 707 Level: intermediate 708 709 Notes: 710 The first Hessian function and the working array are required. 711 As an example to implement the callback functions, the second callback function calculates the vector-Hessian-vector product 712 $ Vl_n^T*G_UP*Vr 713 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. 714 Each entry of G_UP corresponds to the derivative 715 $ G_UP[i][j][k] = \frac{\partial^2 G[i]}{\partial U[j] \partial P[k]}. 716 The result of the vector-Hessian-vector product for Vl_n needs to be stored in vector VHV_n with j-th entry being 717 $ VHV_n[j] = \sum_i \sum_k {Vl_n[i] * G_UP[i][j][k] * Vr[k]} 718 If the cost function is a scalar, there will be only one vector in Vl and VHV. 719 720 .keywords: TS, sensitivity 721 722 .seealso: 723 @*/ 724 PetscErrorCode TSSetRHSHessianProduct(TS ts,Vec *rhshp1,PetscErrorCode (*rhshessianproductfunc1)(TS,PetscReal,Vec,Vec*,Vec,Vec*,void*), 725 Vec *rhshp2,PetscErrorCode (*rhshessianproductfunc2)(TS,PetscReal,Vec,Vec*,Vec,Vec*,void*), 726 Vec *rhshp3,PetscErrorCode (*rhshessianproductfunc3)(TS,PetscReal,Vec,Vec*,Vec,Vec*,void*), 727 Vec *rhshp4,PetscErrorCode (*rhshessianproductfunc4)(TS,PetscReal,Vec,Vec*,Vec,Vec*,void*), 728 void *ctx) 729 { 730 PetscFunctionBegin; 731 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 732 PetscValidPointer(rhshp1,2); 733 734 ts->rhshessianproductctx = ctx; 735 if (rhshp1) ts->vecs_guu = rhshp1; 736 if (rhshp2) ts->vecs_gup = rhshp2; 737 if (rhshp3) ts->vecs_gpu = rhshp3; 738 if (rhshp4) ts->vecs_gpp = rhshp4; 739 ts->rhshessianproduct_guu = rhshessianproductfunc1; 740 ts->rhshessianproduct_gup = rhshessianproductfunc2; 741 ts->rhshessianproduct_gpu = rhshessianproductfunc3; 742 ts->rhshessianproduct_gpp = rhshessianproductfunc4; 743 PetscFunctionReturn(0); 744 } 745 746 /*@C 747 TSComputeRHSHessianProductFunctionUU - Runs the user-defined vector-Hessian-vector product function for Guu. 748 749 Collective on TS 750 751 Input Parameters: 752 . ts - The TS context obtained from TSCreate() 753 754 Notes: 755 TSComputeRHSHessianProductFunctionUU() is typically used for sensitivity implementation, 756 so most users would not generally call this routine themselves. 757 758 Level: developer 759 760 .keywords: TS, sensitivity 761 762 .seealso: TSSetRHSHessianProduct() 763 @*/ 764 PetscErrorCode TSComputeRHSHessianProductFunctionUU(TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV) 765 { 766 PetscErrorCode ierr; 767 768 PetscFunctionBegin; 769 if (!VHV) PetscFunctionReturn(0); 770 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 771 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 772 773 PetscStackPush("TS user RHSHessianProduct function 1 for sensitivity analysis"); 774 ierr = (*ts->rhshessianproduct_guu)(ts,t,U,Vl,Vr,VHV,ts->rhshessianproductctx);CHKERRQ(ierr); 775 PetscStackPop; 776 PetscFunctionReturn(0); 777 } 778 779 /*@C 780 TSComputeRHSHessianProductFunctionUP - Runs the user-defined vector-Hessian-vector product function for Gup. 781 782 Collective on TS 783 784 Input Parameters: 785 . ts - The TS context obtained from TSCreate() 786 787 Notes: 788 TSComputeRHSHessianProductFunctionUP() is typically used for sensitivity implementation, 789 so most users would not generally call this routine themselves. 790 791 Level: developer 792 793 .keywords: TS, sensitivity 794 795 .seealso: TSSetRHSHessianProduct() 796 @*/ 797 PetscErrorCode TSComputeRHSHessianProductFunctionUP(TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV) 798 { 799 PetscErrorCode ierr; 800 801 PetscFunctionBegin; 802 if (!VHV) PetscFunctionReturn(0); 803 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 804 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 805 806 PetscStackPush("TS user RHSHessianProduct function 2 for sensitivity analysis"); 807 ierr = (*ts->rhshessianproduct_gup)(ts,t,U,Vl,Vr,VHV,ts->rhshessianproductctx);CHKERRQ(ierr); 808 PetscStackPop; 809 PetscFunctionReturn(0); 810 } 811 812 /*@C 813 TSComputeRHSHessianProductFunctionPU - Runs the user-defined vector-Hessian-vector product function for Gpu. 814 815 Collective on TS 816 817 Input Parameters: 818 . ts - The TS context obtained from TSCreate() 819 820 Notes: 821 TSComputeRHSHessianProductFunctionPU() is typically used for sensitivity implementation, 822 so most users would not generally call this routine themselves. 823 824 Level: developer 825 826 .keywords: TS, sensitivity 827 828 .seealso: TSSetRHSHessianProduct() 829 @*/ 830 PetscErrorCode TSComputeRHSHessianProductFunctionPU(TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV) 831 { 832 PetscErrorCode ierr; 833 834 PetscFunctionBegin; 835 if (!VHV) PetscFunctionReturn(0); 836 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 837 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 838 839 PetscStackPush("TS user RHSHessianProduct function 3 for sensitivity analysis"); 840 ierr = (*ts->rhshessianproduct_gpu)(ts,t,U,Vl,Vr,VHV,ts->rhshessianproductctx);CHKERRQ(ierr); 841 PetscStackPop; 842 PetscFunctionReturn(0); 843 } 844 845 /*@C 846 TSComputeRHSHessianProductFunctionPP - Runs the user-defined vector-Hessian-vector product function for Gpp. 847 848 Collective on TS 849 850 Input Parameters: 851 . ts - The TS context obtained from TSCreate() 852 853 Notes: 854 TSComputeRHSHessianProductFunctionPP() is typically used for sensitivity implementation, 855 so most users would not generally call this routine themselves. 856 857 Level: developer 858 859 .keywords: TS, sensitivity 860 861 .seealso: TSSetRHSHessianProduct() 862 @*/ 863 PetscErrorCode TSComputeRHSHessianProductFunctionPP(TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV) 864 { 865 PetscErrorCode ierr; 866 867 PetscFunctionBegin; 868 if (!VHV) PetscFunctionReturn(0); 869 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 870 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 871 872 PetscStackPush("TS user RHSHessianProduct function 3 for sensitivity analysis"); 873 ierr = (*ts->rhshessianproduct_gpp)(ts,t,U,Vl,Vr,VHV,ts->rhshessianproductctx);CHKERRQ(ierr); 874 PetscStackPop; 875 PetscFunctionReturn(0); 876 } 877 878 /* --------------------------- Adjoint sensitivity ---------------------------*/ 879 880 /*@ 881 TSSetCostGradients - Sets the initial value of the gradients of the cost function w.r.t. initial values and w.r.t. the problem parameters 882 for use by the TSAdjoint routines. 883 884 Logically Collective on TS and Vec 885 886 Input Parameters: 887 + ts - the TS context obtained from TSCreate() 888 . 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 889 - mu - gradients with respect to the parameters, the number of entries in these vectors is the same as the number of parameters 890 891 Level: beginner 892 893 Notes: 894 the entries in these vectors must be correctly initialized with the values lamda_i = df/dy|finaltime mu_i = df/dp|finaltime 895 896 After TSAdjointSolve() is called the lamba and the mu contain the computed sensitivities 897 898 .keywords: TS, timestep, set, sensitivity, initial values 899 900 .seealso TSGetCostGradients() 901 @*/ 902 PetscErrorCode TSSetCostGradients(TS ts,PetscInt numcost,Vec *lambda,Vec *mu) 903 { 904 PetscFunctionBegin; 905 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 906 PetscValidPointer(lambda,2); 907 ts->vecs_sensi = lambda; 908 ts->vecs_sensip = mu; 909 if (ts->numcost && ts->numcost!=numcost) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"The number of cost functions (2rd parameter of TSSetCostIntegrand()) is inconsistent with the one set by TSSetCostIntegrand"); 910 ts->numcost = numcost; 911 PetscFunctionReturn(0); 912 } 913 914 /*@ 915 TSGetCostGradients - Returns the gradients from the TSAdjointSolve() 916 917 Not Collective, but Vec returned is parallel if TS is parallel 918 919 Input Parameter: 920 . ts - the TS context obtained from TSCreate() 921 922 Output Parameter: 923 + lambda - vectors containing the gradients of the cost functions with respect to the ODE/DAE solution variables 924 - mu - vectors containing the gradients of the cost functions with respect to the problem parameters 925 926 Level: intermediate 927 928 .keywords: TS, timestep, get, sensitivity 929 930 .seealso: TSSetCostGradients() 931 @*/ 932 PetscErrorCode TSGetCostGradients(TS ts,PetscInt *numcost,Vec **lambda,Vec **mu) 933 { 934 PetscFunctionBegin; 935 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 936 if (numcost) *numcost = ts->numcost; 937 if (lambda) *lambda = ts->vecs_sensi; 938 if (mu) *mu = ts->vecs_sensip; 939 PetscFunctionReturn(0); 940 } 941 942 /*@ 943 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 944 for use by the TSAdjoint routines. 945 946 Logically Collective on TS and Vec 947 948 Input Parameters: 949 + ts - the TS context obtained from TSCreate() 950 . numcost - number of cost functions 951 . 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 952 . mu2 - Hessian-vector product with respect to the parameters, the number of entries in these vectors is the same as the number of parameters 953 - dir - the direction vector that are multiplied with the Hessian of the cost functions 954 955 Level: beginner 956 957 Notes: Hessian of the cost function is completely different from Hessian of the ODE/DAE system 958 959 For second-order adjoint, one needs to call this function and then TSAdjointSetForward() before TSSolve(). 960 961 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. 962 963 Passing NULL for lambda2 disables the second-order calculation. 964 .keywords: TS, sensitivity, second-order adjoint 965 966 .seealso: TSAdjointSetForward() 967 @*/ 968 PetscErrorCode TSSetCostHessianProducts(TS ts,PetscInt numcost,Vec *lambda2,Vec *mu2,Vec dir) 969 { 970 PetscFunctionBegin; 971 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 972 if (ts->numcost && ts->numcost!=numcost) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"The number of cost functions (2rd parameter of TSSetCostIntegrand()) is inconsistent with the one set by TSSetCostIntegrand"); 973 ts->numcost = numcost; 974 ts->vecs_sensi2 = lambda2; 975 ts->vecs_sensi2p = mu2; 976 ts->vec_dir = dir; 977 PetscFunctionReturn(0); 978 } 979 980 /*@ 981 TSGetCostHessianProducts - Returns the gradients from the TSAdjointSolve() 982 983 Not Collective, but Vec returned is parallel if TS is parallel 984 985 Input Parameter: 986 . ts - the TS context obtained from TSCreate() 987 988 Output Parameter: 989 + numcost - number of cost functions 990 . 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 991 . mu2 - Hessian-vector product with respect to the parameters, the number of entries in these vectors is the same as the number of parameters 992 - dir - the direction vector that are multiplied with the Hessian of the cost functions 993 994 Level: intermediate 995 996 .keywords: TS, sensitivity, second-order adjoint 997 998 .seealso: TSSetCostHessianProducts() 999 @*/ 1000 PetscErrorCode TSGetCostHessianProducts(TS ts,PetscInt *numcost,Vec **lambda2,Vec **mu2, Vec *dir) 1001 { 1002 PetscFunctionBegin; 1003 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1004 if (numcost) *numcost = ts->numcost; 1005 if (lambda2) *lambda2 = ts->vecs_sensi2; 1006 if (mu2) *mu2 = ts->vecs_sensi2p; 1007 if (dir) *dir = ts->vec_dir; 1008 PetscFunctionReturn(0); 1009 } 1010 1011 /*@ 1012 TSAdjointSetForward - Trigger the tangent linear solver and initialize the forward sensitivities 1013 1014 Logically Collective on TS and Mat 1015 1016 Input Parameters: 1017 + ts - the TS context obtained from TSCreate() 1018 - didp - the derivative of initial values w.r.t. parameters 1019 1020 Level: intermediate 1021 1022 Notes: When computing sensitivies w.r.t. initial condition, set didp to NULL so that the solver will take it as an identity matrix mathematically. TSAdjoint does not reset the tangent linear solver automatically, TSAdjointResetForward() should be called to reset the tangent linear solver. 1023 1024 .keywords: TS, sensitivity, second-order adjoint 1025 1026 .seealso: TSSetCostHessianProducts(), TSAdjointResetForward() 1027 @*/ 1028 PetscErrorCode TSAdjointSetForward(TS ts,Mat didp) 1029 { 1030 Mat A; 1031 Vec sp; 1032 PetscScalar *xarr; 1033 PetscInt lsize; 1034 PetscErrorCode ierr; 1035 1036 PetscFunctionBegin; 1037 ts->forward_solve = PETSC_TRUE; /* turn on tangent linear mode */ 1038 if (!ts->vecs_sensi2) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Must call TSSetCostHessianProducts() first"); 1039 if (!ts->vec_dir) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Directional vector is missing. Call TSSetCostHessianProducts() to set it."); 1040 /* create a single-column dense matrix */ 1041 ierr = VecGetLocalSize(ts->vec_sol,&lsize);CHKERRQ(ierr); 1042 ierr = MatCreateDense(PetscObjectComm((PetscObject)ts),lsize,PETSC_DECIDE,PETSC_DECIDE,1,NULL,&A);CHKERRQ(ierr); 1043 1044 ierr = VecDuplicate(ts->vec_sol,&sp);CHKERRQ(ierr); 1045 ierr = MatDenseGetColumn(A,0,&xarr);CHKERRQ(ierr); 1046 ierr = VecPlaceArray(sp,xarr);CHKERRQ(ierr); 1047 if (ts->vecs_sensi2p) { /* tangent linear variable initialized as 2*dIdP*dir */ 1048 if (didp) { 1049 ierr = MatMult(didp,ts->vec_dir,sp);CHKERRQ(ierr); 1050 ierr = VecScale(sp,2.);CHKERRQ(ierr); 1051 } else { 1052 ierr = VecZeroEntries(sp);CHKERRQ(ierr); 1053 } 1054 } else { /* tangent linear variable initialized as dir */ 1055 ierr = VecCopy(ts->vec_dir,sp);CHKERRQ(ierr); 1056 } 1057 ierr = VecResetArray(sp);CHKERRQ(ierr); 1058 ierr = MatDenseRestoreColumn(A,&xarr);CHKERRQ(ierr); 1059 ierr = VecDestroy(&sp);CHKERRQ(ierr); 1060 1061 ierr = TSForwardSetInitialSensitivities(ts,A);CHKERRQ(ierr); /* if didp is NULL, identity matrix is assumed */ 1062 1063 ierr = MatDestroy(&A);CHKERRQ(ierr); 1064 PetscFunctionReturn(0); 1065 } 1066 1067 /*@ 1068 TSAdjointResetForward - Reset the tangent linear solver and destroy the tangent linear context 1069 1070 Logically Collective on TS and Mat 1071 1072 Input Parameters: 1073 . ts - the TS context obtained from TSCreate() 1074 1075 Level: intermediate 1076 1077 .keywords: TS, sensitivity, second-order adjoint 1078 1079 .seealso: TSAdjointSetForward() 1080 @*/ 1081 PetscErrorCode TSAdjointResetForward(TS ts) 1082 { 1083 PetscErrorCode ierr; 1084 1085 PetscFunctionBegin; 1086 ts->forward_solve = PETSC_FALSE; /* turn off tangent linear mode */ 1087 ierr = TSForwardReset(ts);CHKERRQ(ierr); 1088 PetscFunctionReturn(0); 1089 } 1090 1091 /*@ 1092 TSAdjointSetUp - Sets up the internal data structures for the later use 1093 of an adjoint solver 1094 1095 Collective on TS 1096 1097 Input Parameter: 1098 . ts - the TS context obtained from TSCreate() 1099 1100 Level: advanced 1101 1102 .keywords: TS, timestep, setup 1103 1104 .seealso: TSCreate(), TSAdjointStep(), TSSetCostGradients() 1105 @*/ 1106 PetscErrorCode TSAdjointSetUp(TS ts) 1107 { 1108 TSTrajectory tj; 1109 PetscBool match; 1110 PetscErrorCode ierr; 1111 1112 PetscFunctionBegin; 1113 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1114 if (ts->adjointsetupcalled) PetscFunctionReturn(0); 1115 if (!ts->vecs_sensi) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONGSTATE,"Must call TSSetCostGradients() first"); 1116 if (ts->vecs_sensip && !ts->Jacp && !ts->Jacprhs) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONGSTATE,"Must call TSSetRHSJacobianP() or TSSetIJacobianP() first"); 1117 ierr = TSGetTrajectory(ts,&tj);CHKERRQ(ierr); 1118 ierr = PetscObjectTypeCompare((PetscObject)tj,TSTRAJECTORYBASIC,&match);CHKERRQ(ierr); 1119 if (match) { 1120 PetscBool solution_only; 1121 ierr = TSTrajectoryGetSolutionOnly(tj,&solution_only);CHKERRQ(ierr); 1122 if (solution_only) SETERRQ(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"); 1123 } 1124 ierr = TSTrajectorySetUseHistory(tj,PETSC_FALSE);CHKERRQ(ierr); /* not use TSHistory */ 1125 1126 if (ts->quadraturets) { /* if there is integral in the cost function */ 1127 ierr = VecDuplicate(ts->vecs_sensi[0],&ts->vec_drdu_col);CHKERRQ(ierr); 1128 if (ts->vecs_sensip){ 1129 ierr = VecDuplicate(ts->vecs_sensip[0],&ts->vec_drdp_col);CHKERRQ(ierr); 1130 } 1131 } 1132 1133 if (ts->ops->adjointsetup) { 1134 ierr = (*ts->ops->adjointsetup)(ts);CHKERRQ(ierr); 1135 } 1136 ts->adjointsetupcalled = PETSC_TRUE; 1137 PetscFunctionReturn(0); 1138 } 1139 1140 /*@ 1141 TSAdjointReset - Resets a TSAdjoint context and removes any allocated Vecs and Mats. 1142 1143 Collective on TS 1144 1145 Input Parameter: 1146 . ts - the TS context obtained from TSCreate() 1147 1148 Level: beginner 1149 1150 .keywords: TS, timestep, reset 1151 1152 .seealso: TSCreate(), TSAdjointSetUp(), TSADestroy() 1153 @*/ 1154 PetscErrorCode TSAdjointReset(TS ts) 1155 { 1156 PetscErrorCode ierr; 1157 1158 PetscFunctionBegin; 1159 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1160 if (ts->ops->adjointreset) { 1161 ierr = (*ts->ops->adjointreset)(ts);CHKERRQ(ierr); 1162 } 1163 if (ts->quadraturets) { /* if there is integral in the cost function */ 1164 ierr = VecDestroy(&ts->vec_drdu_col);CHKERRQ(ierr); 1165 if (ts->vecs_sensip){ 1166 ierr = VecDestroy(&ts->vec_drdp_col);CHKERRQ(ierr); 1167 } 1168 } 1169 ts->vecs_sensi = NULL; 1170 ts->vecs_sensip = NULL; 1171 ts->vecs_sensi2 = NULL; 1172 ts->vecs_sensi2p = NULL; 1173 ts->vec_dir = NULL; 1174 ts->adjointsetupcalled = PETSC_FALSE; 1175 PetscFunctionReturn(0); 1176 } 1177 1178 /*@ 1179 TSAdjointSetSteps - Sets the number of steps the adjoint solver should take backward in time 1180 1181 Logically Collective on TS 1182 1183 Input Parameters: 1184 + ts - the TS context obtained from TSCreate() 1185 . steps - number of steps to use 1186 1187 Level: intermediate 1188 1189 Notes: 1190 Normally one does not call this and TSAdjointSolve() integrates back to the original timestep. One can call this 1191 so as to integrate back to less than the original timestep 1192 1193 .keywords: TS, timestep, set, maximum, iterations 1194 1195 .seealso: TSSetExactFinalTime() 1196 @*/ 1197 PetscErrorCode TSAdjointSetSteps(TS ts,PetscInt steps) 1198 { 1199 PetscFunctionBegin; 1200 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1201 PetscValidLogicalCollectiveInt(ts,steps,2); 1202 if (steps < 0) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Cannot step back a negative number of steps"); 1203 if (steps > ts->steps) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Cannot step back more than the total number of forward steps"); 1204 ts->adjoint_max_steps = steps; 1205 PetscFunctionReturn(0); 1206 } 1207 1208 /*@C 1209 TSAdjointSetRHSJacobian - Deprecated, use TSSetRHSJacobianP() 1210 1211 Level: deprecated 1212 1213 @*/ 1214 PetscErrorCode TSAdjointSetRHSJacobian(TS ts,Mat Amat,PetscErrorCode (*func)(TS,PetscReal,Vec,Mat,void*),void *ctx) 1215 { 1216 PetscErrorCode ierr; 1217 1218 PetscFunctionBegin; 1219 PetscValidHeaderSpecific(ts, TS_CLASSID,1); 1220 PetscValidHeaderSpecific(Amat,MAT_CLASSID,2); 1221 1222 ts->rhsjacobianp = func; 1223 ts->rhsjacobianpctx = ctx; 1224 if(Amat) { 1225 ierr = PetscObjectReference((PetscObject)Amat);CHKERRQ(ierr); 1226 ierr = MatDestroy(&ts->Jacp);CHKERRQ(ierr); 1227 ts->Jacp = Amat; 1228 } 1229 PetscFunctionReturn(0); 1230 } 1231 1232 /*@C 1233 TSAdjointComputeRHSJacobian - Deprecated, use TSComputeRHSJacobianP() 1234 1235 Level: deprecated 1236 1237 @*/ 1238 PetscErrorCode TSAdjointComputeRHSJacobian(TS ts,PetscReal t,Vec U,Mat Amat) 1239 { 1240 PetscErrorCode ierr; 1241 1242 PetscFunctionBegin; 1243 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1244 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 1245 PetscValidPointer(Amat,4); 1246 1247 PetscStackPush("TS user JacobianP function for sensitivity analysis"); 1248 ierr = (*ts->rhsjacobianp)(ts,t,U,Amat,ts->rhsjacobianpctx); CHKERRQ(ierr); 1249 PetscStackPop; 1250 PetscFunctionReturn(0); 1251 } 1252 1253 /*@ 1254 TSAdjointComputeDRDYFunction - Deprecated, use TSComputeDRDUFunction() 1255 1256 Level: deprecated 1257 1258 @*/ 1259 PetscErrorCode TSAdjointComputeDRDYFunction(TS ts,PetscReal t,Vec U,Vec *DRDU) 1260 { 1261 PetscErrorCode ierr; 1262 1263 PetscFunctionBegin; 1264 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1265 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 1266 1267 PetscStackPush("TS user DRDY function for sensitivity analysis"); 1268 ierr = (*ts->drdufunction)(ts,t,U,DRDU,ts->costintegrandctx); CHKERRQ(ierr); 1269 PetscStackPop; 1270 PetscFunctionReturn(0); 1271 } 1272 1273 /*@ 1274 TSAdjointComputeDRDPFunction - Deprecated, use TSComputeDRDPFunction() 1275 1276 Level: deprecated 1277 1278 @*/ 1279 PetscErrorCode TSAdjointComputeDRDPFunction(TS ts,PetscReal t,Vec U,Vec *DRDP) 1280 { 1281 PetscErrorCode ierr; 1282 1283 PetscFunctionBegin; 1284 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1285 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 1286 1287 PetscStackPush("TS user DRDP function for sensitivity analysis"); 1288 ierr = (*ts->drdpfunction)(ts,t,U,DRDP,ts->costintegrandctx); CHKERRQ(ierr); 1289 PetscStackPop; 1290 PetscFunctionReturn(0); 1291 } 1292 1293 /*@C 1294 TSAdjointMonitorSensi - monitors the first lambda sensitivity 1295 1296 Level: intermediate 1297 1298 .keywords: TS, set, monitor 1299 1300 .seealso: TSAdjointMonitorSet() 1301 @*/ 1302 PetscErrorCode TSAdjointMonitorSensi(TS ts,PetscInt step,PetscReal ptime,Vec v,PetscInt numcost,Vec *lambda,Vec *mu,PetscViewerAndFormat *vf) 1303 { 1304 PetscErrorCode ierr; 1305 PetscViewer viewer = vf->viewer; 1306 1307 PetscFunctionBegin; 1308 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,4); 1309 ierr = PetscViewerPushFormat(viewer,vf->format);CHKERRQ(ierr); 1310 ierr = VecView(lambda[0],viewer);CHKERRQ(ierr); 1311 ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 1312 PetscFunctionReturn(0); 1313 } 1314 1315 /*@C 1316 TSAdjointMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user 1317 1318 Collective on TS 1319 1320 Input Parameters: 1321 + ts - TS object you wish to monitor 1322 . name - the monitor type one is seeking 1323 . help - message indicating what monitoring is done 1324 . manual - manual page for the monitor 1325 . monitor - the monitor function 1326 - 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 1327 1328 Level: developer 1329 1330 .seealso: PetscOptionsGetViewer(), PetscOptionsGetReal(), PetscOptionsHasName(), PetscOptionsGetString(), 1331 PetscOptionsGetIntArray(), PetscOptionsGetRealArray(), PetscOptionsBool() 1332 PetscOptionsInt(), PetscOptionsString(), PetscOptionsReal(), PetscOptionsBool(), 1333 PetscOptionsName(), PetscOptionsBegin(), PetscOptionsEnd(), PetscOptionsHead(), 1334 PetscOptionsStringArray(),PetscOptionsRealArray(), PetscOptionsScalar(), 1335 PetscOptionsBoolGroupBegin(), PetscOptionsBoolGroup(), PetscOptionsBoolGroupEnd(), 1336 PetscOptionsFList(), PetscOptionsEList() 1337 @*/ 1338 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*)) 1339 { 1340 PetscErrorCode ierr; 1341 PetscViewer viewer; 1342 PetscViewerFormat format; 1343 PetscBool flg; 1344 1345 PetscFunctionBegin; 1346 ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject)ts),((PetscObject) ts)->options,((PetscObject)ts)->prefix,name,&viewer,&format,&flg);CHKERRQ(ierr); 1347 if (flg) { 1348 PetscViewerAndFormat *vf; 1349 ierr = PetscViewerAndFormatCreate(viewer,format,&vf);CHKERRQ(ierr); 1350 ierr = PetscObjectDereference((PetscObject)viewer);CHKERRQ(ierr); 1351 if (monitorsetup) { 1352 ierr = (*monitorsetup)(ts,vf);CHKERRQ(ierr); 1353 } 1354 ierr = TSAdjointMonitorSet(ts,(PetscErrorCode (*)(TS,PetscInt,PetscReal,Vec,PetscInt,Vec*,Vec*,void*))monitor,vf,(PetscErrorCode (*)(void**))PetscViewerAndFormatDestroy);CHKERRQ(ierr); 1355 } 1356 PetscFunctionReturn(0); 1357 } 1358 1359 /*@C 1360 TSAdjointMonitorSet - Sets an ADDITIONAL function that is to be used at every 1361 timestep to display the iteration's progress. 1362 1363 Logically Collective on TS 1364 1365 Input Parameters: 1366 + ts - the TS context obtained from TSCreate() 1367 . adjointmonitor - monitoring routine 1368 . adjointmctx - [optional] user-defined context for private data for the 1369 monitor routine (use NULL if no context is desired) 1370 - adjointmonitordestroy - [optional] routine that frees monitor context 1371 (may be NULL) 1372 1373 Calling sequence of monitor: 1374 $ int adjointmonitor(TS ts,PetscInt steps,PetscReal time,Vec u,PetscInt numcost,Vec *lambda, Vec *mu,void *adjointmctx) 1375 1376 + ts - the TS context 1377 . 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 1378 been interpolated to) 1379 . time - current time 1380 . u - current iterate 1381 . numcost - number of cost functionos 1382 . lambda - sensitivities to initial conditions 1383 . mu - sensitivities to parameters 1384 - adjointmctx - [optional] adjoint monitoring context 1385 1386 Notes: 1387 This routine adds an additional monitor to the list of monitors that 1388 already has been loaded. 1389 1390 Fortran Notes: 1391 Only a single monitor function can be set for each TS object 1392 1393 Level: intermediate 1394 1395 .keywords: TS, timestep, set, adjoint, monitor 1396 1397 .seealso: TSAdjointMonitorCancel() 1398 @*/ 1399 PetscErrorCode TSAdjointMonitorSet(TS ts,PetscErrorCode (*adjointmonitor)(TS,PetscInt,PetscReal,Vec,PetscInt,Vec*,Vec*,void*),void *adjointmctx,PetscErrorCode (*adjointmdestroy)(void**)) 1400 { 1401 PetscErrorCode ierr; 1402 PetscInt i; 1403 PetscBool identical; 1404 1405 PetscFunctionBegin; 1406 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1407 for (i=0; i<ts->numbermonitors;i++) { 1408 ierr = PetscMonitorCompare((PetscErrorCode (*)(void))adjointmonitor,adjointmctx,adjointmdestroy,(PetscErrorCode (*)(void))ts->adjointmonitor[i],ts->adjointmonitorcontext[i],ts->adjointmonitordestroy[i],&identical);CHKERRQ(ierr); 1409 if (identical) PetscFunctionReturn(0); 1410 } 1411 if (ts->numberadjointmonitors >= MAXTSMONITORS) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Too many adjoint monitors set"); 1412 ts->adjointmonitor[ts->numberadjointmonitors] = adjointmonitor; 1413 ts->adjointmonitordestroy[ts->numberadjointmonitors] = adjointmdestroy; 1414 ts->adjointmonitorcontext[ts->numberadjointmonitors++] = (void*)adjointmctx; 1415 PetscFunctionReturn(0); 1416 } 1417 1418 /*@C 1419 TSAdjointMonitorCancel - Clears all the adjoint monitors that have been set on a time-step object. 1420 1421 Logically Collective on TS 1422 1423 Input Parameters: 1424 . ts - the TS context obtained from TSCreate() 1425 1426 Notes: 1427 There is no way to remove a single, specific monitor. 1428 1429 Level: intermediate 1430 1431 .keywords: TS, timestep, set, adjoint, monitor 1432 1433 .seealso: TSAdjointMonitorSet() 1434 @*/ 1435 PetscErrorCode TSAdjointMonitorCancel(TS ts) 1436 { 1437 PetscErrorCode ierr; 1438 PetscInt i; 1439 1440 PetscFunctionBegin; 1441 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1442 for (i=0; i<ts->numberadjointmonitors; i++) { 1443 if (ts->adjointmonitordestroy[i]) { 1444 ierr = (*ts->adjointmonitordestroy[i])(&ts->adjointmonitorcontext[i]);CHKERRQ(ierr); 1445 } 1446 } 1447 ts->numberadjointmonitors = 0; 1448 PetscFunctionReturn(0); 1449 } 1450 1451 /*@C 1452 TSAdjointMonitorDefault - the default monitor of adjoint computations 1453 1454 Level: intermediate 1455 1456 .keywords: TS, set, monitor 1457 1458 .seealso: TSAdjointMonitorSet() 1459 @*/ 1460 PetscErrorCode TSAdjointMonitorDefault(TS ts,PetscInt step,PetscReal ptime,Vec v,PetscInt numcost,Vec *lambda,Vec *mu,PetscViewerAndFormat *vf) 1461 { 1462 PetscErrorCode ierr; 1463 PetscViewer viewer = vf->viewer; 1464 1465 PetscFunctionBegin; 1466 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,4); 1467 ierr = PetscViewerPushFormat(viewer,vf->format);CHKERRQ(ierr); 1468 ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)ts)->tablevel);CHKERRQ(ierr); 1469 ierr = PetscViewerASCIIPrintf(viewer,"%D TS dt %g time %g%s",step,(double)ts->time_step,(double)ptime,ts->steprollback ? " (r)\n" : "\n");CHKERRQ(ierr); 1470 ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)ts)->tablevel);CHKERRQ(ierr); 1471 ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 1472 PetscFunctionReturn(0); 1473 } 1474 1475 /*@C 1476 TSAdjointMonitorDrawSensi - Monitors progress of the adjoint TS solvers by calling 1477 VecView() for the sensitivities to initial states at each timestep 1478 1479 Collective on TS 1480 1481 Input Parameters: 1482 + ts - the TS context 1483 . step - current time-step 1484 . ptime - current time 1485 . u - current state 1486 . numcost - number of cost functions 1487 . lambda - sensitivities to initial conditions 1488 . mu - sensitivities to parameters 1489 - dummy - either a viewer or NULL 1490 1491 Level: intermediate 1492 1493 .keywords: TS, vector, adjoint, monitor, view 1494 1495 .seealso: TSAdjointMonitorSet(), TSAdjointMonitorDefault(), VecView() 1496 @*/ 1497 PetscErrorCode TSAdjointMonitorDrawSensi(TS ts,PetscInt step,PetscReal ptime,Vec u,PetscInt numcost,Vec *lambda,Vec *mu,void *dummy) 1498 { 1499 PetscErrorCode ierr; 1500 TSMonitorDrawCtx ictx = (TSMonitorDrawCtx)dummy; 1501 PetscDraw draw; 1502 PetscReal xl,yl,xr,yr,h; 1503 char time[32]; 1504 1505 PetscFunctionBegin; 1506 if (!(((ictx->howoften > 0) && (!(step % ictx->howoften))) || ((ictx->howoften == -1) && ts->reason))) PetscFunctionReturn(0); 1507 1508 ierr = VecView(lambda[0],ictx->viewer);CHKERRQ(ierr); 1509 ierr = PetscViewerDrawGetDraw(ictx->viewer,0,&draw);CHKERRQ(ierr); 1510 ierr = PetscSNPrintf(time,32,"Timestep %d Time %g",(int)step,(double)ptime);CHKERRQ(ierr); 1511 ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr); 1512 h = yl + .95*(yr - yl); 1513 ierr = PetscDrawStringCentered(draw,.5*(xl+xr),h,PETSC_DRAW_BLACK,time);CHKERRQ(ierr); 1514 ierr = PetscDrawFlush(draw);CHKERRQ(ierr); 1515 PetscFunctionReturn(0); 1516 } 1517 1518 /* 1519 TSAdjointSetFromOptions - Sets various TSAdjoint parameters from user options. 1520 1521 Collective on TSAdjoint 1522 1523 Input Parameter: 1524 . ts - the TS context 1525 1526 Options Database Keys: 1527 + -ts_adjoint_solve <yes,no> After solving the ODE/DAE solve the adjoint problem (requires -ts_save_trajectory) 1528 . -ts_adjoint_monitor - print information at each adjoint time step 1529 - -ts_adjoint_monitor_draw_sensi - monitor the sensitivity of the first cost function wrt initial conditions (lambda[0]) graphically 1530 1531 Level: developer 1532 1533 Notes: 1534 This is not normally called directly by users 1535 1536 .keywords: TS, trajectory, timestep, set, options, database 1537 1538 .seealso: TSSetSaveTrajectory(), TSTrajectorySetUp() 1539 */ 1540 PetscErrorCode TSAdjointSetFromOptions(PetscOptionItems *PetscOptionsObject,TS ts) 1541 { 1542 PetscBool tflg,opt; 1543 PetscErrorCode ierr; 1544 1545 PetscFunctionBegin; 1546 PetscValidHeaderSpecific(ts,TS_CLASSID,2); 1547 ierr = PetscOptionsHead(PetscOptionsObject,"TS Adjoint options");CHKERRQ(ierr); 1548 tflg = ts->adjoint_solve ? PETSC_TRUE : PETSC_FALSE; 1549 ierr = PetscOptionsBool("-ts_adjoint_solve","Solve the adjoint problem immediately after solving the forward problem","",tflg,&tflg,&opt);CHKERRQ(ierr); 1550 if (opt) { 1551 ierr = TSSetSaveTrajectory(ts);CHKERRQ(ierr); 1552 ts->adjoint_solve = tflg; 1553 } 1554 ierr = TSAdjointMonitorSetFromOptions(ts,"-ts_adjoint_monitor","Monitor adjoint timestep size","TSAdjointMonitorDefault",TSAdjointMonitorDefault,NULL);CHKERRQ(ierr); 1555 ierr = TSAdjointMonitorSetFromOptions(ts,"-ts_adjoint_monitor_sensi","Monitor sensitivity in the adjoint computation","TSAdjointMonitorSensi",TSAdjointMonitorSensi,NULL);CHKERRQ(ierr); 1556 opt = PETSC_FALSE; 1557 ierr = PetscOptionsName("-ts_adjoint_monitor_draw_sensi","Monitor adjoint sensitivities (lambda only) graphically","TSAdjointMonitorDrawSensi",&opt);CHKERRQ(ierr); 1558 if (opt) { 1559 TSMonitorDrawCtx ctx; 1560 PetscInt howoften = 1; 1561 1562 ierr = PetscOptionsInt("-ts_adjoint_monitor_draw_sensi","Monitor adjoint sensitivities (lambda only) graphically","TSAdjointMonitorDrawSensi",howoften,&howoften,NULL);CHKERRQ(ierr); 1563 ierr = TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts),0,0,PETSC_DECIDE,PETSC_DECIDE,300,300,howoften,&ctx);CHKERRQ(ierr); 1564 ierr = TSAdjointMonitorSet(ts,TSAdjointMonitorDrawSensi,ctx,(PetscErrorCode (*)(void**))TSMonitorDrawCtxDestroy);CHKERRQ(ierr); 1565 } 1566 PetscFunctionReturn(0); 1567 } 1568 1569 /*@ 1570 TSAdjointStep - Steps one time step backward in the adjoint run 1571 1572 Collective on TS 1573 1574 Input Parameter: 1575 . ts - the TS context obtained from TSCreate() 1576 1577 Level: intermediate 1578 1579 .keywords: TS, adjoint, step 1580 1581 .seealso: TSAdjointSetUp(), TSAdjointSolve() 1582 @*/ 1583 PetscErrorCode TSAdjointStep(TS ts) 1584 { 1585 DM dm; 1586 PetscErrorCode ierr; 1587 1588 PetscFunctionBegin; 1589 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1590 ierr = TSGetDM(ts,&dm);CHKERRQ(ierr); 1591 ierr = TSAdjointSetUp(ts);CHKERRQ(ierr); 1592 1593 ts->reason = TS_CONVERGED_ITERATING; 1594 ts->ptime_prev = ts->ptime; 1595 if (!ts->ops->adjointstep) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_NOT_CONVERGED,"TSStep has failed because the adjoint of %s has not been implemented, try other time stepping methods for adjoint sensitivity analysis",((PetscObject)ts)->type_name); 1596 ierr = PetscLogEventBegin(TS_AdjointStep,ts,0,0,0);CHKERRQ(ierr); 1597 ierr = (*ts->ops->adjointstep)(ts);CHKERRQ(ierr); 1598 ierr = PetscLogEventEnd(TS_AdjointStep,ts,0,0,0);CHKERRQ(ierr); 1599 ts->adjoint_steps++; ts->steps--; 1600 1601 if (ts->reason < 0) { 1602 if (ts->errorifstepfailed) { 1603 if (ts->reason == TSADJOINT_DIVERGED_LINEAR_SOLVE) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_NOT_CONVERGED,"TSAdjointStep has failed due to %s",TSConvergedReasons[ts->reason]); 1604 else SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_NOT_CONVERGED,"TSAdjointStep has failed due to %s",TSConvergedReasons[ts->reason]); 1605 } 1606 } else if (!ts->reason) { 1607 if (ts->adjoint_steps >= ts->adjoint_max_steps) ts->reason = TS_CONVERGED_ITS; 1608 } 1609 PetscFunctionReturn(0); 1610 } 1611 1612 /*@ 1613 TSAdjointSolve - Solves the discrete ajoint problem for an ODE/DAE 1614 1615 Collective on TS 1616 1617 Input Parameter: 1618 . ts - the TS context obtained from TSCreate() 1619 1620 Options Database: 1621 . -ts_adjoint_view_solution <viewerinfo> - views the first gradient with respect to the initial values 1622 1623 Level: intermediate 1624 1625 Notes: 1626 This must be called after a call to TSSolve() that solves the forward problem 1627 1628 By default this will integrate back to the initial time, one can use TSAdjointSetSteps() to step back to a later time 1629 1630 .keywords: TS, timestep, solve 1631 1632 .seealso: TSCreate(), TSSetCostGradients(), TSSetSolution(), TSAdjointStep() 1633 @*/ 1634 PetscErrorCode TSAdjointSolve(TS ts) 1635 { 1636 PetscErrorCode ierr; 1637 1638 PetscFunctionBegin; 1639 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1640 ierr = TSAdjointSetUp(ts);CHKERRQ(ierr); 1641 1642 /* reset time step and iteration counters */ 1643 ts->adjoint_steps = 0; 1644 ts->ksp_its = 0; 1645 ts->snes_its = 0; 1646 ts->num_snes_failures = 0; 1647 ts->reject = 0; 1648 ts->reason = TS_CONVERGED_ITERATING; 1649 1650 if (!ts->adjoint_max_steps) ts->adjoint_max_steps = ts->steps; 1651 if (ts->adjoint_steps >= ts->adjoint_max_steps) ts->reason = TS_CONVERGED_ITS; 1652 1653 while (!ts->reason) { 1654 ierr = TSTrajectoryGet(ts->trajectory,ts,ts->steps,&ts->ptime);CHKERRQ(ierr); 1655 ierr = TSAdjointMonitor(ts,ts->steps,ts->ptime,ts->vec_sol,ts->numcost,ts->vecs_sensi,ts->vecs_sensip);CHKERRQ(ierr); 1656 ierr = TSAdjointEventHandler(ts);CHKERRQ(ierr); 1657 ierr = TSAdjointStep(ts);CHKERRQ(ierr); 1658 if ((ts->vec_costintegral || ts->quadraturets) && !ts->costintegralfwd) { 1659 ierr = TSAdjointCostIntegral(ts);CHKERRQ(ierr); 1660 } 1661 } 1662 ierr = TSTrajectoryGet(ts->trajectory,ts,ts->steps,&ts->ptime);CHKERRQ(ierr); 1663 ierr = TSAdjointMonitor(ts,ts->steps,ts->ptime,ts->vec_sol,ts->numcost,ts->vecs_sensi,ts->vecs_sensip);CHKERRQ(ierr); 1664 ts->solvetime = ts->ptime; 1665 ierr = TSTrajectoryViewFromOptions(ts->trajectory,NULL,"-ts_trajectory_view");CHKERRQ(ierr); 1666 ierr = VecViewFromOptions(ts->vecs_sensi[0],(PetscObject) ts, "-ts_adjoint_view_solution");CHKERRQ(ierr); 1667 ts->adjoint_max_steps = 0; 1668 PetscFunctionReturn(0); 1669 } 1670 1671 /*@C 1672 TSAdjointMonitor - Runs all user-provided adjoint monitor routines set using TSAdjointMonitorSet() 1673 1674 Collective on TS 1675 1676 Input Parameters: 1677 + ts - time stepping context obtained from TSCreate() 1678 . step - step number that has just completed 1679 . ptime - model time of the state 1680 . u - state at the current model time 1681 . numcost - number of cost functions (dimension of lambda or mu) 1682 . lambda - vectors containing the gradients of the cost functions with respect to the ODE/DAE solution variables 1683 - mu - vectors containing the gradients of the cost functions with respect to the problem parameters 1684 1685 Notes: 1686 TSAdjointMonitor() is typically used automatically within the time stepping implementations. 1687 Users would almost never call this routine directly. 1688 1689 Level: developer 1690 1691 .keywords: TS, timestep 1692 @*/ 1693 PetscErrorCode TSAdjointMonitor(TS ts,PetscInt step,PetscReal ptime,Vec u,PetscInt numcost,Vec *lambda, Vec *mu) 1694 { 1695 PetscErrorCode ierr; 1696 PetscInt i,n = ts->numberadjointmonitors; 1697 1698 PetscFunctionBegin; 1699 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1700 PetscValidHeaderSpecific(u,VEC_CLASSID,4); 1701 ierr = VecLockReadPush(u);CHKERRQ(ierr); 1702 for (i=0; i<n; i++) { 1703 ierr = (*ts->adjointmonitor[i])(ts,step,ptime,u,numcost,lambda,mu,ts->adjointmonitorcontext[i]);CHKERRQ(ierr); 1704 } 1705 ierr = VecLockReadPop(u);CHKERRQ(ierr); 1706 PetscFunctionReturn(0); 1707 } 1708 1709 /*@ 1710 TSAdjointCostIntegral - Evaluate the cost integral in the adjoint run. 1711 1712 Collective on TS 1713 1714 Input Arguments: 1715 . ts - time stepping context 1716 1717 Level: advanced 1718 1719 Notes: 1720 This function cannot be called until TSAdjointStep() has been completed. 1721 1722 .seealso: TSAdjointSolve(), TSAdjointStep 1723 @*/ 1724 PetscErrorCode TSAdjointCostIntegral(TS ts) 1725 { 1726 PetscErrorCode ierr; 1727 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1728 if (!ts->ops->adjointintegral) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"%s does not provide integral evaluation in the adjoint run",((PetscObject)ts)->type_name); 1729 ierr = (*ts->ops->adjointintegral)(ts);CHKERRQ(ierr); 1730 PetscFunctionReturn(0); 1731 } 1732 1733 /* ------------------ Forward (tangent linear) sensitivity ------------------*/ 1734 1735 /*@ 1736 TSForwardSetUp - Sets up the internal data structures for the later use 1737 of forward sensitivity analysis 1738 1739 Collective on TS 1740 1741 Input Parameter: 1742 . ts - the TS context obtained from TSCreate() 1743 1744 Level: advanced 1745 1746 .keywords: TS, forward sensitivity, setup 1747 1748 .seealso: TSCreate(), TSDestroy(), TSSetUp() 1749 @*/ 1750 PetscErrorCode TSForwardSetUp(TS ts) 1751 { 1752 PetscErrorCode ierr; 1753 1754 PetscFunctionBegin; 1755 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1756 if (ts->forwardsetupcalled) PetscFunctionReturn(0); 1757 if (ts->ops->forwardsetup) { 1758 ierr = (*ts->ops->forwardsetup)(ts);CHKERRQ(ierr); 1759 } 1760 ierr = VecDuplicate(ts->vec_sol,&ts->vec_sensip_col);CHKERRQ(ierr); 1761 ts->forwardsetupcalled = PETSC_TRUE; 1762 PetscFunctionReturn(0); 1763 } 1764 1765 /*@ 1766 TSForwardReset - Reset the internal data structures used by forward sensitivity analysis 1767 1768 Collective on TS 1769 1770 Input Parameter: 1771 . ts - the TS context obtained from TSCreate() 1772 1773 Level: advanced 1774 1775 .keywords: TS, forward sensitivity, reset 1776 1777 .seealso: TSCreate(), TSDestroy(), TSForwardSetUp() 1778 @*/ 1779 PetscErrorCode TSForwardReset(TS ts) 1780 { 1781 TS quadts = ts->quadraturets; 1782 PetscErrorCode ierr; 1783 1784 PetscFunctionBegin; 1785 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1786 if (ts->ops->forwardreset) { 1787 ierr = (*ts->ops->forwardreset)(ts);CHKERRQ(ierr); 1788 } 1789 ierr = MatDestroy(&ts->mat_sensip);CHKERRQ(ierr); 1790 if (quadts) { 1791 ierr = MatDestroy(&quadts->mat_sensip);CHKERRQ(ierr); 1792 } 1793 ierr = VecDestroy(&ts->vec_sensip_col);CHKERRQ(ierr); 1794 ts->forward_solve = PETSC_FALSE; 1795 ts->forwardsetupcalled = PETSC_FALSE; 1796 PetscFunctionReturn(0); 1797 } 1798 1799 /*@ 1800 TSForwardSetIntegralGradients - Set the vectors holding forward sensitivities of the integral term. 1801 1802 Input Parameter: 1803 . ts- the TS context obtained from TSCreate() 1804 . numfwdint- number of integrals 1805 . vp = the vectors containing the gradients for each integral w.r.t. parameters 1806 1807 Level: deprecated 1808 1809 .keywords: TS, forward sensitivity 1810 1811 .seealso: TSForwardGetSensitivities(), TSForwardSetIntegralGradients(), TSForwardGetIntegralGradients(), TSForwardStep() 1812 @*/ 1813 PetscErrorCode TSForwardSetIntegralGradients(TS ts,PetscInt numfwdint,Vec *vp) 1814 { 1815 PetscFunctionBegin; 1816 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1817 if (ts->numcost && ts->numcost!=numfwdint) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"The number of cost functions (2rd parameter of TSSetCostIntegrand()) is inconsistent with the one set by TSSetCostIntegrand()"); 1818 if (!ts->numcost) ts->numcost = numfwdint; 1819 1820 ts->vecs_integral_sensip = vp; 1821 PetscFunctionReturn(0); 1822 } 1823 1824 /*@ 1825 TSForwardGetIntegralGradients - Returns the forward sensitivities ofthe integral term. 1826 1827 Input Parameter: 1828 . ts- the TS context obtained from TSCreate() 1829 1830 Output Parameter: 1831 . vp = the vectors containing the gradients for each integral w.r.t. parameters 1832 1833 Level: deprecated 1834 1835 .keywords: TS, forward sensitivity 1836 1837 .seealso: TSForwardSetSensitivities(), TSForwardSetIntegralGradients(), TSForwardGetIntegralGradients(), TSForwardStep() 1838 @*/ 1839 PetscErrorCode TSForwardGetIntegralGradients(TS ts,PetscInt *numfwdint,Vec **vp) 1840 { 1841 PetscFunctionBegin; 1842 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1843 PetscValidPointer(vp,3); 1844 if (numfwdint) *numfwdint = ts->numcost; 1845 if (vp) *vp = ts->vecs_integral_sensip; 1846 PetscFunctionReturn(0); 1847 } 1848 1849 /*@ 1850 TSForwardStep - Compute the forward sensitivity for one time step. 1851 1852 Collective on TS 1853 1854 Input Arguments: 1855 . ts - time stepping context 1856 1857 Level: advanced 1858 1859 Notes: 1860 This function cannot be called until TSStep() has been completed. 1861 1862 .keywords: TS, forward sensitivity 1863 1864 .seealso: TSForwardSetSensitivities(), TSForwardGetSensitivities(), TSForwardSetIntegralGradients(), TSForwardGetIntegralGradients(), TSForwardSetUp() 1865 @*/ 1866 PetscErrorCode TSForwardStep(TS ts) 1867 { 1868 PetscErrorCode ierr; 1869 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1870 if (!ts->ops->forwardstep) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"%s does not provide forward sensitivity analysis",((PetscObject)ts)->type_name); 1871 ierr = PetscLogEventBegin(TS_ForwardStep,ts,0,0,0);CHKERRQ(ierr); 1872 ierr = (*ts->ops->forwardstep)(ts);CHKERRQ(ierr); 1873 ierr = PetscLogEventEnd(TS_ForwardStep,ts,0,0,0);CHKERRQ(ierr); 1874 PetscFunctionReturn(0); 1875 } 1876 1877 /*@ 1878 TSForwardSetSensitivities - Sets the initial value of the trajectory sensitivities of solution w.r.t. the problem parameters and initial values. 1879 1880 Logically Collective on TS and Vec 1881 1882 Input Parameters: 1883 + ts - the TS context obtained from TSCreate() 1884 . nump - number of parameters 1885 - Smat - sensitivities with respect to the parameters, the number of entries in these vectors is the same as the number of parameters 1886 1887 Level: beginner 1888 1889 Notes: 1890 Forward sensitivity is also called 'trajectory sensitivity' in some fields such as power systems. 1891 This function turns on a flag to trigger TSSolve() to compute forward sensitivities automatically. 1892 You must call this function before TSSolve(). 1893 The entries in the sensitivity matrix must be correctly initialized with the values S = dy/dp|startingtime. 1894 1895 .keywords: TS, timestep, set, forward sensitivity, initial values 1896 1897 .seealso: TSForwardGetSensitivities(), TSForwardSetIntegralGradients(), TSForwardGetIntegralGradients(), TSForwardStep() 1898 @*/ 1899 PetscErrorCode TSForwardSetSensitivities(TS ts,PetscInt nump,Mat Smat) 1900 { 1901 PetscErrorCode ierr; 1902 1903 PetscFunctionBegin; 1904 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1905 PetscValidHeaderSpecific(Smat,MAT_CLASSID,3); 1906 ts->forward_solve = PETSC_TRUE; 1907 if (nump == PETSC_DEFAULT) { 1908 ierr = MatGetSize(Smat,NULL,&ts->num_parameters);CHKERRQ(ierr); 1909 } else ts->num_parameters = nump; 1910 ierr = PetscObjectReference((PetscObject)Smat);CHKERRQ(ierr); 1911 ierr = MatDestroy(&ts->mat_sensip);CHKERRQ(ierr); 1912 ts->mat_sensip = Smat; 1913 PetscFunctionReturn(0); 1914 } 1915 1916 /*@ 1917 TSForwardGetSensitivities - Returns the trajectory sensitivities 1918 1919 Not Collective, but Vec returned is parallel if TS is parallel 1920 1921 Output Parameter: 1922 + ts - the TS context obtained from TSCreate() 1923 . nump - number of parameters 1924 - Smat - sensitivities with respect to the parameters, the number of entries in these vectors is the same as the number of parameters 1925 1926 Level: intermediate 1927 1928 .keywords: TS, forward sensitivity 1929 1930 .seealso: TSForwardSetSensitivities(), TSForwardSetIntegralGradients(), TSForwardGetIntegralGradients(), TSForwardStep() 1931 @*/ 1932 PetscErrorCode TSForwardGetSensitivities(TS ts,PetscInt *nump,Mat *Smat) 1933 { 1934 PetscFunctionBegin; 1935 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1936 if (nump) *nump = ts->num_parameters; 1937 if (Smat) *Smat = ts->mat_sensip; 1938 PetscFunctionReturn(0); 1939 } 1940 1941 /*@ 1942 TSForwardCostIntegral - Evaluate the cost integral in the forward run. 1943 1944 Collective on TS 1945 1946 Input Arguments: 1947 . ts - time stepping context 1948 1949 Level: advanced 1950 1951 Notes: 1952 This function cannot be called until TSStep() has been completed. 1953 1954 .seealso: TSSolve(), TSAdjointCostIntegral() 1955 @*/ 1956 PetscErrorCode TSForwardCostIntegral(TS ts) 1957 { 1958 PetscErrorCode ierr; 1959 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1960 if (!ts->ops->forwardintegral) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"%s does not provide integral evaluation in the forward run",((PetscObject)ts)->type_name); 1961 ierr = (*ts->ops->forwardintegral)(ts);CHKERRQ(ierr); 1962 PetscFunctionReturn(0); 1963 } 1964 1965 /*@ 1966 TSForwardSetInitialSensitivities - Set initial values for tangent linear sensitivities 1967 1968 Collective on TS and Mat 1969 1970 Input Parameter 1971 + ts - the TS context obtained from TSCreate() 1972 - didp - parametric sensitivities of the initial condition 1973 1974 Level: intermediate 1975 1976 Notes: TSSolve() allows users to pass the initial solution directly to TS. But the tangent linear variables cannot be initialized in this way. This function is used to set initial values for tangent linear variables. 1977 1978 .seealso: TSForwardSetSensitivities() 1979 @*/ 1980 PetscErrorCode TSForwardSetInitialSensitivities(TS ts,Mat didp) 1981 { 1982 PetscErrorCode ierr; 1983 1984 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1985 PetscValidHeaderSpecific(didp,MAT_CLASSID,2); 1986 if (!ts->mat_sensip) { 1987 ierr = TSForwardSetSensitivities(ts,PETSC_DEFAULT,didp);CHKERRQ(ierr); 1988 } 1989 PetscFunctionReturn(0); 1990 } 1991 1992 /*@ 1993 TSForwardGetStages - Get the number of stages and the tangent linear sensitivities at the intermediate stages 1994 1995 Input Parameter: 1996 . ts - the TS context obtained from TSCreate() 1997 1998 Output Parameters: 1999 + ns - number of stages 2000 - S - tangent linear sensitivities at the intermediate stages 2001 2002 Level: advanced 2003 2004 .keywords: TS, second-order adjoint, forward sensitivity 2005 @*/ 2006 PetscErrorCode TSForwardGetStages(TS ts,PetscInt *ns,Mat **S) 2007 { 2008 PetscErrorCode ierr; 2009 2010 PetscFunctionBegin; 2011 PetscValidHeaderSpecific(ts, TS_CLASSID,1); 2012 2013 if (!ts->ops->getstages) *S=NULL; 2014 else { 2015 ierr = (*ts->ops->forwardgetstages)(ts,ns,S);CHKERRQ(ierr); 2016 } 2017 PetscFunctionReturn(0); 2018 } 2019 2020 /*@ 2021 TSCreateQuadratureTS - Create a sub-TS that evaluates integrals over time 2022 2023 Input Parameter: 2024 + ts - the TS context obtained from TSCreate() 2025 - fwd - flag indicating whether to evaluate cost integral in the forward run or the adjoint run 2026 2027 Output Parameters: 2028 . quadts - the child TS context 2029 2030 Level: intermediate 2031 2032 .keywords: TS, quadrature evaluation 2033 2034 .seealso: TSGetQuadratureTS() 2035 @*/ 2036 PetscErrorCode TSCreateQuadratureTS(TS ts,PetscBool fwd,TS *quadts) 2037 { 2038 char prefix[128]; 2039 PetscErrorCode ierr; 2040 2041 PetscFunctionBegin; 2042 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 2043 PetscValidPointer(quadts,2); 2044 ierr = TSDestroy(&ts->quadraturets);CHKERRQ(ierr); 2045 ierr = TSCreate(PetscObjectComm((PetscObject)ts),&ts->quadraturets);CHKERRQ(ierr); 2046 ierr = PetscObjectIncrementTabLevel((PetscObject)ts->quadraturets,(PetscObject)ts,1);CHKERRQ(ierr); 2047 ierr = PetscLogObjectParent((PetscObject)ts,(PetscObject)ts->quadraturets);CHKERRQ(ierr); 2048 ierr = PetscSNPrintf(prefix,sizeof(prefix),"%squad_",((PetscObject)ts)->prefix ? ((PetscObject)ts)->prefix : "");CHKERRQ(ierr); 2049 ierr = TSSetOptionsPrefix(ts->quadraturets,prefix);CHKERRQ(ierr); 2050 *quadts = ts->quadraturets; 2051 2052 if (ts->numcost) { 2053 ierr = VecCreateSeq(PETSC_COMM_SELF,ts->numcost,&(*quadts)->vec_sol);CHKERRQ(ierr); 2054 } else { 2055 ierr = VecCreateSeq(PETSC_COMM_SELF,1,&(*quadts)->vec_sol);CHKERRQ(ierr); 2056 } 2057 ts->costintegralfwd = fwd; 2058 PetscFunctionReturn(0); 2059 } 2060 2061 /*@ 2062 TSGetQuadratureTS - Return the sub-TS that evaluates integrals over time 2063 2064 Input Parameter: 2065 . ts - the TS context obtained from TSCreate() 2066 2067 Output Parameters: 2068 + fwd - flag indicating whether to evaluate cost integral in the forward run or the adjoint run 2069 - quadts - the child TS context 2070 2071 Level: intermediate 2072 2073 .keywords: TS, quadrature evaluation 2074 2075 .seealso: TSCreateQuadratureTS() 2076 @*/ 2077 PetscErrorCode TSGetQuadratureTS(TS ts,PetscBool *fwd,TS *quadts) 2078 { 2079 PetscFunctionBegin; 2080 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 2081 if (fwd) *fwd = ts->costintegralfwd; 2082 if (quadts) *quadts = ts->quadraturets; 2083 PetscFunctionReturn(0); 2084 } 2085