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 1125 if (!ts->Jacp && ts->Jacprhs) ts->Jacp = ts->Jacprhs; 1126 1127 if (ts->quadraturets) { /* if there is integral in the cost function */ 1128 ierr = VecDuplicate(ts->vecs_sensi[0],&ts->vec_drdu_col);CHKERRQ(ierr); 1129 if (ts->vecs_sensip){ 1130 ierr = VecDuplicate(ts->vecs_sensip[0],&ts->vec_drdp_col);CHKERRQ(ierr); 1131 } 1132 } 1133 1134 if (ts->ops->adjointsetup) { 1135 ierr = (*ts->ops->adjointsetup)(ts);CHKERRQ(ierr); 1136 } 1137 ts->adjointsetupcalled = PETSC_TRUE; 1138 PetscFunctionReturn(0); 1139 } 1140 1141 /*@ 1142 TSAdjointReset - Resets a TSAdjoint context and removes any allocated Vecs and Mats. 1143 1144 Collective on TS 1145 1146 Input Parameter: 1147 . ts - the TS context obtained from TSCreate() 1148 1149 Level: beginner 1150 1151 .keywords: TS, timestep, reset 1152 1153 .seealso: TSCreate(), TSAdjointSetup(), TSADestroy() 1154 @*/ 1155 PetscErrorCode TSAdjointReset(TS ts) 1156 { 1157 PetscErrorCode ierr; 1158 1159 PetscFunctionBegin; 1160 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1161 if (ts->ops->adjointreset) { 1162 ierr = (*ts->ops->adjointreset)(ts);CHKERRQ(ierr); 1163 } 1164 if (ts->quadraturets) { /* if there is integral in the cost function */ 1165 ierr = VecDestroy(&ts->vec_drdu_col);CHKERRQ(ierr); 1166 if (ts->vecs_sensip){ 1167 ierr = VecDestroy(&ts->vec_drdp_col);CHKERRQ(ierr); 1168 } 1169 } 1170 ts->vecs_sensi = NULL; 1171 ts->vecs_sensip = NULL; 1172 ts->vecs_sensi2 = NULL; 1173 ts->vecs_sensi2p = NULL; 1174 ts->vec_dir = NULL; 1175 ts->adjointsetupcalled = PETSC_FALSE; 1176 PetscFunctionReturn(0); 1177 } 1178 1179 /*@ 1180 TSAdjointSetSteps - Sets the number of steps the adjoint solver should take backward in time 1181 1182 Logically Collective on TS 1183 1184 Input Parameters: 1185 + ts - the TS context obtained from TSCreate() 1186 . steps - number of steps to use 1187 1188 Level: intermediate 1189 1190 Notes: 1191 Normally one does not call this and TSAdjointSolve() integrates back to the original timestep. One can call this 1192 so as to integrate back to less than the original timestep 1193 1194 .keywords: TS, timestep, set, maximum, iterations 1195 1196 .seealso: TSSetExactFinalTime() 1197 @*/ 1198 PetscErrorCode TSAdjointSetSteps(TS ts,PetscInt steps) 1199 { 1200 PetscFunctionBegin; 1201 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1202 PetscValidLogicalCollectiveInt(ts,steps,2); 1203 if (steps < 0) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Cannot step back a negative number of steps"); 1204 if (steps > ts->steps) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Cannot step back more than the total number of forward steps"); 1205 ts->adjoint_max_steps = steps; 1206 PetscFunctionReturn(0); 1207 } 1208 1209 /*@C 1210 TSAdjointSetRHSJacobian - Deprecated, use TSSetRHSJacobianP() 1211 1212 Level: deprecated 1213 1214 @*/ 1215 PetscErrorCode TSAdjointSetRHSJacobian(TS ts,Mat Amat,PetscErrorCode (*func)(TS,PetscReal,Vec,Mat,void*),void *ctx) 1216 { 1217 PetscErrorCode ierr; 1218 1219 PetscFunctionBegin; 1220 PetscValidHeaderSpecific(ts, TS_CLASSID,1); 1221 PetscValidHeaderSpecific(Amat,MAT_CLASSID,2); 1222 1223 ts->rhsjacobianp = func; 1224 ts->rhsjacobianpctx = ctx; 1225 if(Amat) { 1226 ierr = PetscObjectReference((PetscObject)Amat);CHKERRQ(ierr); 1227 ierr = MatDestroy(&ts->Jacp);CHKERRQ(ierr); 1228 ts->Jacp = Amat; 1229 } 1230 PetscFunctionReturn(0); 1231 } 1232 1233 /*@C 1234 TSAdjointComputeRHSJacobian - Deprecated, use TSComputeRHSJacobianP() 1235 1236 Level: deprecated 1237 1238 @*/ 1239 PetscErrorCode TSAdjointComputeRHSJacobian(TS ts,PetscReal t,Vec U,Mat Amat) 1240 { 1241 PetscErrorCode ierr; 1242 1243 PetscFunctionBegin; 1244 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1245 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 1246 PetscValidPointer(Amat,4); 1247 1248 PetscStackPush("TS user JacobianP function for sensitivity analysis"); 1249 ierr = (*ts->rhsjacobianp)(ts,t,U,Amat,ts->rhsjacobianpctx); CHKERRQ(ierr); 1250 PetscStackPop; 1251 PetscFunctionReturn(0); 1252 } 1253 1254 /*@ 1255 TSAdjointComputeDRDYFunction - Deprecated, use TSComputeDRDUFunction() 1256 1257 Level: deprecated 1258 1259 @*/ 1260 PetscErrorCode TSAdjointComputeDRDYFunction(TS ts,PetscReal t,Vec U,Vec *DRDU) 1261 { 1262 PetscErrorCode ierr; 1263 1264 PetscFunctionBegin; 1265 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1266 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 1267 1268 PetscStackPush("TS user DRDY function for sensitivity analysis"); 1269 ierr = (*ts->drdufunction)(ts,t,U,DRDU,ts->costintegrandctx); CHKERRQ(ierr); 1270 PetscStackPop; 1271 PetscFunctionReturn(0); 1272 } 1273 1274 /*@ 1275 TSAdjointComputeDRDPFunction - Deprecated, use TSComputeDRDPFunction() 1276 1277 Level: deprecated 1278 1279 @*/ 1280 PetscErrorCode TSAdjointComputeDRDPFunction(TS ts,PetscReal t,Vec U,Vec *DRDP) 1281 { 1282 PetscErrorCode ierr; 1283 1284 PetscFunctionBegin; 1285 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1286 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 1287 1288 PetscStackPush("TS user DRDP function for sensitivity analysis"); 1289 ierr = (*ts->drdpfunction)(ts,t,U,DRDP,ts->costintegrandctx); CHKERRQ(ierr); 1290 PetscStackPop; 1291 PetscFunctionReturn(0); 1292 } 1293 1294 /*@C 1295 TSAdjointMonitorSensi - monitors the first lambda sensitivity 1296 1297 Level: intermediate 1298 1299 .keywords: TS, set, monitor 1300 1301 .seealso: TSAdjointMonitorSet() 1302 @*/ 1303 PetscErrorCode TSAdjointMonitorSensi(TS ts,PetscInt step,PetscReal ptime,Vec v,PetscInt numcost,Vec *lambda,Vec *mu,PetscViewerAndFormat *vf) 1304 { 1305 PetscErrorCode ierr; 1306 PetscViewer viewer = vf->viewer; 1307 1308 PetscFunctionBegin; 1309 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,4); 1310 ierr = PetscViewerPushFormat(viewer,vf->format);CHKERRQ(ierr); 1311 ierr = VecView(lambda[0],viewer);CHKERRQ(ierr); 1312 ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 1313 PetscFunctionReturn(0); 1314 } 1315 1316 /*@C 1317 TSAdjointMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user 1318 1319 Collective on TS 1320 1321 Input Parameters: 1322 + ts - TS object you wish to monitor 1323 . name - the monitor type one is seeking 1324 . help - message indicating what monitoring is done 1325 . manual - manual page for the monitor 1326 . monitor - the monitor function 1327 - 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 1328 1329 Level: developer 1330 1331 .seealso: PetscOptionsGetViewer(), PetscOptionsGetReal(), PetscOptionsHasName(), PetscOptionsGetString(), 1332 PetscOptionsGetIntArray(), PetscOptionsGetRealArray(), PetscOptionsBool() 1333 PetscOptionsInt(), PetscOptionsString(), PetscOptionsReal(), PetscOptionsBool(), 1334 PetscOptionsName(), PetscOptionsBegin(), PetscOptionsEnd(), PetscOptionsHead(), 1335 PetscOptionsStringArray(),PetscOptionsRealArray(), PetscOptionsScalar(), 1336 PetscOptionsBoolGroupBegin(), PetscOptionsBoolGroup(), PetscOptionsBoolGroupEnd(), 1337 PetscOptionsFList(), PetscOptionsEList() 1338 @*/ 1339 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*)) 1340 { 1341 PetscErrorCode ierr; 1342 PetscViewer viewer; 1343 PetscViewerFormat format; 1344 PetscBool flg; 1345 1346 PetscFunctionBegin; 1347 ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject)ts),((PetscObject) ts)->options,((PetscObject)ts)->prefix,name,&viewer,&format,&flg);CHKERRQ(ierr); 1348 if (flg) { 1349 PetscViewerAndFormat *vf; 1350 ierr = PetscViewerAndFormatCreate(viewer,format,&vf);CHKERRQ(ierr); 1351 ierr = PetscObjectDereference((PetscObject)viewer);CHKERRQ(ierr); 1352 if (monitorsetup) { 1353 ierr = (*monitorsetup)(ts,vf);CHKERRQ(ierr); 1354 } 1355 ierr = TSAdjointMonitorSet(ts,(PetscErrorCode (*)(TS,PetscInt,PetscReal,Vec,PetscInt,Vec*,Vec*,void*))monitor,vf,(PetscErrorCode (*)(void**))PetscViewerAndFormatDestroy);CHKERRQ(ierr); 1356 } 1357 PetscFunctionReturn(0); 1358 } 1359 1360 /*@C 1361 TSAdjointMonitorSet - Sets an ADDITIONAL function that is to be used at every 1362 timestep to display the iteration's progress. 1363 1364 Logically Collective on TS 1365 1366 Input Parameters: 1367 + ts - the TS context obtained from TSCreate() 1368 . adjointmonitor - monitoring routine 1369 . adjointmctx - [optional] user-defined context for private data for the 1370 monitor routine (use NULL if no context is desired) 1371 - adjointmonitordestroy - [optional] routine that frees monitor context 1372 (may be NULL) 1373 1374 Calling sequence of monitor: 1375 $ int adjointmonitor(TS ts,PetscInt steps,PetscReal time,Vec u,PetscInt numcost,Vec *lambda, Vec *mu,void *adjointmctx) 1376 1377 + ts - the TS context 1378 . 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 1379 been interpolated to) 1380 . time - current time 1381 . u - current iterate 1382 . numcost - number of cost functionos 1383 . lambda - sensitivities to initial conditions 1384 . mu - sensitivities to parameters 1385 - adjointmctx - [optional] adjoint monitoring context 1386 1387 Notes: 1388 This routine adds an additional monitor to the list of monitors that 1389 already has been loaded. 1390 1391 Fortran Notes: 1392 Only a single monitor function can be set for each TS object 1393 1394 Level: intermediate 1395 1396 .keywords: TS, timestep, set, adjoint, monitor 1397 1398 .seealso: TSAdjointMonitorCancel() 1399 @*/ 1400 PetscErrorCode TSAdjointMonitorSet(TS ts,PetscErrorCode (*adjointmonitor)(TS,PetscInt,PetscReal,Vec,PetscInt,Vec*,Vec*,void*),void *adjointmctx,PetscErrorCode (*adjointmdestroy)(void**)) 1401 { 1402 PetscErrorCode ierr; 1403 PetscInt i; 1404 PetscBool identical; 1405 1406 PetscFunctionBegin; 1407 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1408 for (i=0; i<ts->numbermonitors;i++) { 1409 ierr = PetscMonitorCompare((PetscErrorCode (*)(void))adjointmonitor,adjointmctx,adjointmdestroy,(PetscErrorCode (*)(void))ts->adjointmonitor[i],ts->adjointmonitorcontext[i],ts->adjointmonitordestroy[i],&identical);CHKERRQ(ierr); 1410 if (identical) PetscFunctionReturn(0); 1411 } 1412 if (ts->numberadjointmonitors >= MAXTSMONITORS) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Too many adjoint monitors set"); 1413 ts->adjointmonitor[ts->numberadjointmonitors] = adjointmonitor; 1414 ts->adjointmonitordestroy[ts->numberadjointmonitors] = adjointmdestroy; 1415 ts->adjointmonitorcontext[ts->numberadjointmonitors++] = (void*)adjointmctx; 1416 PetscFunctionReturn(0); 1417 } 1418 1419 /*@C 1420 TSAdjointMonitorCancel - Clears all the adjoint monitors that have been set on a time-step object. 1421 1422 Logically Collective on TS 1423 1424 Input Parameters: 1425 . ts - the TS context obtained from TSCreate() 1426 1427 Notes: 1428 There is no way to remove a single, specific monitor. 1429 1430 Level: intermediate 1431 1432 .keywords: TS, timestep, set, adjoint, monitor 1433 1434 .seealso: TSAdjointMonitorSet() 1435 @*/ 1436 PetscErrorCode TSAdjointMonitorCancel(TS ts) 1437 { 1438 PetscErrorCode ierr; 1439 PetscInt i; 1440 1441 PetscFunctionBegin; 1442 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1443 for (i=0; i<ts->numberadjointmonitors; i++) { 1444 if (ts->adjointmonitordestroy[i]) { 1445 ierr = (*ts->adjointmonitordestroy[i])(&ts->adjointmonitorcontext[i]);CHKERRQ(ierr); 1446 } 1447 } 1448 ts->numberadjointmonitors = 0; 1449 PetscFunctionReturn(0); 1450 } 1451 1452 /*@C 1453 TSAdjointMonitorDefault - the default monitor of adjoint computations 1454 1455 Level: intermediate 1456 1457 .keywords: TS, set, monitor 1458 1459 .seealso: TSAdjointMonitorSet() 1460 @*/ 1461 PetscErrorCode TSAdjointMonitorDefault(TS ts,PetscInt step,PetscReal ptime,Vec v,PetscInt numcost,Vec *lambda,Vec *mu,PetscViewerAndFormat *vf) 1462 { 1463 PetscErrorCode ierr; 1464 PetscViewer viewer = vf->viewer; 1465 1466 PetscFunctionBegin; 1467 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,4); 1468 ierr = PetscViewerPushFormat(viewer,vf->format);CHKERRQ(ierr); 1469 ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)ts)->tablevel);CHKERRQ(ierr); 1470 ierr = PetscViewerASCIIPrintf(viewer,"%D TS dt %g time %g%s",step,(double)ts->time_step,(double)ptime,ts->steprollback ? " (r)\n" : "\n");CHKERRQ(ierr); 1471 ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)ts)->tablevel);CHKERRQ(ierr); 1472 ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 1473 PetscFunctionReturn(0); 1474 } 1475 1476 /*@C 1477 TSAdjointMonitorDrawSensi - Monitors progress of the adjoint TS solvers by calling 1478 VecView() for the sensitivities to initial states at each timestep 1479 1480 Collective on TS 1481 1482 Input Parameters: 1483 + ts - the TS context 1484 . step - current time-step 1485 . ptime - current time 1486 . u - current state 1487 . numcost - number of cost functions 1488 . lambda - sensitivities to initial conditions 1489 . mu - sensitivities to parameters 1490 - dummy - either a viewer or NULL 1491 1492 Level: intermediate 1493 1494 .keywords: TS, vector, adjoint, monitor, view 1495 1496 .seealso: TSAdjointMonitorSet(), TSAdjointMonitorDefault(), VecView() 1497 @*/ 1498 PetscErrorCode TSAdjointMonitorDrawSensi(TS ts,PetscInt step,PetscReal ptime,Vec u,PetscInt numcost,Vec *lambda,Vec *mu,void *dummy) 1499 { 1500 PetscErrorCode ierr; 1501 TSMonitorDrawCtx ictx = (TSMonitorDrawCtx)dummy; 1502 PetscDraw draw; 1503 PetscReal xl,yl,xr,yr,h; 1504 char time[32]; 1505 1506 PetscFunctionBegin; 1507 if (!(((ictx->howoften > 0) && (!(step % ictx->howoften))) || ((ictx->howoften == -1) && ts->reason))) PetscFunctionReturn(0); 1508 1509 ierr = VecView(lambda[0],ictx->viewer);CHKERRQ(ierr); 1510 ierr = PetscViewerDrawGetDraw(ictx->viewer,0,&draw);CHKERRQ(ierr); 1511 ierr = PetscSNPrintf(time,32,"Timestep %d Time %g",(int)step,(double)ptime);CHKERRQ(ierr); 1512 ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr); 1513 h = yl + .95*(yr - yl); 1514 ierr = PetscDrawStringCentered(draw,.5*(xl+xr),h,PETSC_DRAW_BLACK,time);CHKERRQ(ierr); 1515 ierr = PetscDrawFlush(draw);CHKERRQ(ierr); 1516 PetscFunctionReturn(0); 1517 } 1518 1519 /* 1520 TSAdjointSetFromOptions - Sets various TSAdjoint parameters from user options. 1521 1522 Collective on TSAdjoint 1523 1524 Input Parameter: 1525 . ts - the TS context 1526 1527 Options Database Keys: 1528 + -ts_adjoint_solve <yes,no> After solving the ODE/DAE solve the adjoint problem (requires -ts_save_trajectory) 1529 . -ts_adjoint_monitor - print information at each adjoint time step 1530 - -ts_adjoint_monitor_draw_sensi - monitor the sensitivity of the first cost function wrt initial conditions (lambda[0]) graphically 1531 1532 Level: developer 1533 1534 Notes: 1535 This is not normally called directly by users 1536 1537 .keywords: TS, trajectory, timestep, set, options, database 1538 1539 .seealso: TSSetSaveTrajectory(), TSTrajectorySetUp() 1540 */ 1541 PetscErrorCode TSAdjointSetFromOptions(PetscOptionItems *PetscOptionsObject,TS ts) 1542 { 1543 PetscBool tflg,opt; 1544 PetscErrorCode ierr; 1545 1546 PetscFunctionBegin; 1547 PetscValidHeaderSpecific(ts,TS_CLASSID,2); 1548 ierr = PetscOptionsHead(PetscOptionsObject,"TS Adjoint options");CHKERRQ(ierr); 1549 tflg = ts->adjoint_solve ? PETSC_TRUE : PETSC_FALSE; 1550 ierr = PetscOptionsBool("-ts_adjoint_solve","Solve the adjoint problem immediately after solving the forward problem","",tflg,&tflg,&opt);CHKERRQ(ierr); 1551 if (opt) { 1552 ierr = TSSetSaveTrajectory(ts);CHKERRQ(ierr); 1553 ts->adjoint_solve = tflg; 1554 } 1555 ierr = TSAdjointMonitorSetFromOptions(ts,"-ts_adjoint_monitor","Monitor adjoint timestep size","TSAdjointMonitorDefault",TSAdjointMonitorDefault,NULL);CHKERRQ(ierr); 1556 ierr = TSAdjointMonitorSetFromOptions(ts,"-ts_adjoint_monitor_sensi","Monitor sensitivity in the adjoint computation","TSAdjointMonitorSensi",TSAdjointMonitorSensi,NULL);CHKERRQ(ierr); 1557 opt = PETSC_FALSE; 1558 ierr = PetscOptionsName("-ts_adjoint_monitor_draw_sensi","Monitor adjoint sensitivities (lambda only) graphically","TSAdjointMonitorDrawSensi",&opt);CHKERRQ(ierr); 1559 if (opt) { 1560 TSMonitorDrawCtx ctx; 1561 PetscInt howoften = 1; 1562 1563 ierr = PetscOptionsInt("-ts_adjoint_monitor_draw_sensi","Monitor adjoint sensitivities (lambda only) graphically","TSAdjointMonitorDrawSensi",howoften,&howoften,NULL);CHKERRQ(ierr); 1564 ierr = TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts),0,0,PETSC_DECIDE,PETSC_DECIDE,300,300,howoften,&ctx);CHKERRQ(ierr); 1565 ierr = TSAdjointMonitorSet(ts,TSAdjointMonitorDrawSensi,ctx,(PetscErrorCode (*)(void**))TSMonitorDrawCtxDestroy);CHKERRQ(ierr); 1566 } 1567 PetscFunctionReturn(0); 1568 } 1569 1570 /*@ 1571 TSAdjointStep - Steps one time step backward in the adjoint run 1572 1573 Collective on TS 1574 1575 Input Parameter: 1576 . ts - the TS context obtained from TSCreate() 1577 1578 Level: intermediate 1579 1580 .keywords: TS, adjoint, step 1581 1582 .seealso: TSAdjointSetUp(), TSAdjointSolve() 1583 @*/ 1584 PetscErrorCode TSAdjointStep(TS ts) 1585 { 1586 DM dm; 1587 PetscErrorCode ierr; 1588 1589 PetscFunctionBegin; 1590 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1591 ierr = TSGetDM(ts,&dm);CHKERRQ(ierr); 1592 ierr = TSAdjointSetUp(ts);CHKERRQ(ierr); 1593 1594 ts->reason = TS_CONVERGED_ITERATING; 1595 ts->ptime_prev = ts->ptime; 1596 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); 1597 ierr = PetscLogEventBegin(TS_AdjointStep,ts,0,0,0);CHKERRQ(ierr); 1598 ierr = (*ts->ops->adjointstep)(ts);CHKERRQ(ierr); 1599 ierr = PetscLogEventEnd(TS_AdjointStep,ts,0,0,0);CHKERRQ(ierr); 1600 ts->adjoint_steps++; ts->steps--; 1601 1602 if (ts->reason < 0) { 1603 if (ts->errorifstepfailed) { 1604 if (ts->reason == TSADJOINT_DIVERGED_LINEAR_SOLVE) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_NOT_CONVERGED,"TSAdjointStep has failed due to %s",TSConvergedReasons[ts->reason]); 1605 else SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_NOT_CONVERGED,"TSAdjointStep has failed due to %s",TSConvergedReasons[ts->reason]); 1606 } 1607 } else if (!ts->reason) { 1608 if (ts->adjoint_steps >= ts->adjoint_max_steps) ts->reason = TS_CONVERGED_ITS; 1609 } 1610 PetscFunctionReturn(0); 1611 } 1612 1613 /*@ 1614 TSAdjointSolve - Solves the discrete ajoint problem for an ODE/DAE 1615 1616 Collective on TS 1617 1618 Input Parameter: 1619 . ts - the TS context obtained from TSCreate() 1620 1621 Options Database: 1622 . -ts_adjoint_view_solution <viewerinfo> - views the first gradient with respect to the initial values 1623 1624 Level: intermediate 1625 1626 Notes: 1627 This must be called after a call to TSSolve() that solves the forward problem 1628 1629 By default this will integrate back to the initial time, one can use TSAdjointSetSteps() to step back to a later time 1630 1631 .keywords: TS, timestep, solve 1632 1633 .seealso: TSCreate(), TSSetCostGradients(), TSSetSolution(), TSAdjointStep() 1634 @*/ 1635 PetscErrorCode TSAdjointSolve(TS ts) 1636 { 1637 PetscErrorCode ierr; 1638 1639 PetscFunctionBegin; 1640 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1641 ierr = TSAdjointSetUp(ts);CHKERRQ(ierr); 1642 1643 /* reset time step and iteration counters */ 1644 ts->adjoint_steps = 0; 1645 ts->ksp_its = 0; 1646 ts->snes_its = 0; 1647 ts->num_snes_failures = 0; 1648 ts->reject = 0; 1649 ts->reason = TS_CONVERGED_ITERATING; 1650 1651 if (!ts->adjoint_max_steps) ts->adjoint_max_steps = ts->steps; 1652 if (ts->adjoint_steps >= ts->adjoint_max_steps) ts->reason = TS_CONVERGED_ITS; 1653 1654 while (!ts->reason) { 1655 ierr = TSTrajectoryGet(ts->trajectory,ts,ts->steps,&ts->ptime);CHKERRQ(ierr); 1656 ierr = TSAdjointMonitor(ts,ts->steps,ts->ptime,ts->vec_sol,ts->numcost,ts->vecs_sensi,ts->vecs_sensip);CHKERRQ(ierr); 1657 ierr = TSAdjointEventHandler(ts);CHKERRQ(ierr); 1658 ierr = TSAdjointStep(ts);CHKERRQ(ierr); 1659 if ((ts->vec_costintegral || ts->quadraturets) && !ts->costintegralfwd) { 1660 ierr = TSAdjointCostIntegral(ts);CHKERRQ(ierr); 1661 } 1662 } 1663 ierr = TSTrajectoryGet(ts->trajectory,ts,ts->steps,&ts->ptime);CHKERRQ(ierr); 1664 ierr = TSAdjointMonitor(ts,ts->steps,ts->ptime,ts->vec_sol,ts->numcost,ts->vecs_sensi,ts->vecs_sensip);CHKERRQ(ierr); 1665 ts->solvetime = ts->ptime; 1666 ierr = TSTrajectoryViewFromOptions(ts->trajectory,NULL,"-ts_trajectory_view");CHKERRQ(ierr); 1667 ierr = VecViewFromOptions(ts->vecs_sensi[0],(PetscObject) ts, "-ts_adjoint_view_solution");CHKERRQ(ierr); 1668 ts->adjoint_max_steps = 0; 1669 PetscFunctionReturn(0); 1670 } 1671 1672 /*@C 1673 TSAdjointMonitor - Runs all user-provided adjoint monitor routines set using TSAdjointMonitorSet() 1674 1675 Collective on TS 1676 1677 Input Parameters: 1678 + ts - time stepping context obtained from TSCreate() 1679 . step - step number that has just completed 1680 . ptime - model time of the state 1681 . u - state at the current model time 1682 . numcost - number of cost functions (dimension of lambda or mu) 1683 . lambda - vectors containing the gradients of the cost functions with respect to the ODE/DAE solution variables 1684 - mu - vectors containing the gradients of the cost functions with respect to the problem parameters 1685 1686 Notes: 1687 TSAdjointMonitor() is typically used automatically within the time stepping implementations. 1688 Users would almost never call this routine directly. 1689 1690 Level: developer 1691 1692 .keywords: TS, timestep 1693 @*/ 1694 PetscErrorCode TSAdjointMonitor(TS ts,PetscInt step,PetscReal ptime,Vec u,PetscInt numcost,Vec *lambda, Vec *mu) 1695 { 1696 PetscErrorCode ierr; 1697 PetscInt i,n = ts->numberadjointmonitors; 1698 1699 PetscFunctionBegin; 1700 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1701 PetscValidHeaderSpecific(u,VEC_CLASSID,4); 1702 ierr = VecLockReadPush(u);CHKERRQ(ierr); 1703 for (i=0; i<n; i++) { 1704 ierr = (*ts->adjointmonitor[i])(ts,step,ptime,u,numcost,lambda,mu,ts->adjointmonitorcontext[i]);CHKERRQ(ierr); 1705 } 1706 ierr = VecLockReadPop(u);CHKERRQ(ierr); 1707 PetscFunctionReturn(0); 1708 } 1709 1710 /*@ 1711 TSAdjointCostIntegral - Evaluate the cost integral in the adjoint run. 1712 1713 Collective on TS 1714 1715 Input Arguments: 1716 . ts - time stepping context 1717 1718 Level: advanced 1719 1720 Notes: 1721 This function cannot be called until TSAdjointStep() has been completed. 1722 1723 .seealso: TSAdjointSolve(), TSAdjointStep 1724 @*/ 1725 PetscErrorCode TSAdjointCostIntegral(TS ts) 1726 { 1727 PetscErrorCode ierr; 1728 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1729 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); 1730 ierr = (*ts->ops->adjointintegral)(ts);CHKERRQ(ierr); 1731 PetscFunctionReturn(0); 1732 } 1733 1734 /* ------------------ Forward (tangent linear) sensitivity ------------------*/ 1735 1736 /*@ 1737 TSForwardSetUp - Sets up the internal data structures for the later use 1738 of forward sensitivity analysis 1739 1740 Collective on TS 1741 1742 Input Parameter: 1743 . ts - the TS context obtained from TSCreate() 1744 1745 Level: advanced 1746 1747 .keywords: TS, forward sensitivity, setup 1748 1749 .seealso: TSCreate(), TSDestroy(), TSSetUp() 1750 @*/ 1751 PetscErrorCode TSForwardSetUp(TS ts) 1752 { 1753 PetscErrorCode ierr; 1754 1755 PetscFunctionBegin; 1756 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1757 if (ts->forwardsetupcalled) PetscFunctionReturn(0); 1758 if (!ts->Jacp && ts->Jacprhs) ts->Jacp = ts->Jacprhs; 1759 1760 if (ts->ops->forwardsetup) { 1761 ierr = (*ts->ops->forwardsetup)(ts);CHKERRQ(ierr); 1762 } 1763 ierr = VecDuplicate(ts->vec_sol,&ts->vec_sensip_col);CHKERRQ(ierr); 1764 ts->forwardsetupcalled = PETSC_TRUE; 1765 PetscFunctionReturn(0); 1766 } 1767 1768 /*@ 1769 TSForwardReset - Reset the internal data structures used by forward sensitivity analysis 1770 1771 Collective on TS 1772 1773 Input Parameter: 1774 . ts - the TS context obtained from TSCreate() 1775 1776 Level: advanced 1777 1778 .keywords: TS, forward sensitivity, reset 1779 1780 .seealso: TSCreate(), TSDestroy(), TSForwardSetUp() 1781 @*/ 1782 PetscErrorCode TSForwardReset(TS ts) 1783 { 1784 TS quadts = ts->quadraturets; 1785 PetscErrorCode ierr; 1786 1787 PetscFunctionBegin; 1788 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1789 if (ts->ops->forwardreset) { 1790 ierr = (*ts->ops->forwardreset)(ts);CHKERRQ(ierr); 1791 } 1792 ierr = MatDestroy(&ts->mat_sensip);CHKERRQ(ierr); 1793 if (quadts) { 1794 ierr = MatDestroy(&quadts->mat_sensip);CHKERRQ(ierr); 1795 } 1796 ierr = VecDestroy(&ts->vec_sensip_col);CHKERRQ(ierr); 1797 ts->forward_solve = PETSC_FALSE; 1798 ts->forwardsetupcalled = PETSC_FALSE; 1799 PetscFunctionReturn(0); 1800 } 1801 1802 /*@ 1803 TSForwardSetIntegralGradients - Set the vectors holding forward sensitivities of the integral term. 1804 1805 Input Parameter: 1806 . ts- the TS context obtained from TSCreate() 1807 . numfwdint- number of integrals 1808 . vp = the vectors containing the gradients for each integral w.r.t. parameters 1809 1810 Level: deprecated 1811 1812 .keywords: TS, forward sensitivity 1813 1814 .seealso: TSForwardGetSensitivities(), TSForwardSetIntegralGradients(), TSForwardGetIntegralGradients(), TSForwardStep() 1815 @*/ 1816 PetscErrorCode TSForwardSetIntegralGradients(TS ts,PetscInt numfwdint,Vec *vp) 1817 { 1818 PetscFunctionBegin; 1819 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1820 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()"); 1821 if (!ts->numcost) ts->numcost = numfwdint; 1822 1823 ts->vecs_integral_sensip = vp; 1824 PetscFunctionReturn(0); 1825 } 1826 1827 /*@ 1828 TSForwardGetIntegralGradients - Returns the forward sensitivities ofthe integral term. 1829 1830 Input Parameter: 1831 . ts- the TS context obtained from TSCreate() 1832 1833 Output Parameter: 1834 . vp = the vectors containing the gradients for each integral w.r.t. parameters 1835 1836 Level: deprecated 1837 1838 .keywords: TS, forward sensitivity 1839 1840 .seealso: TSForwardSetSensitivities(), TSForwardSetIntegralGradients(), TSForwardGetIntegralGradients(), TSForwardStep() 1841 @*/ 1842 PetscErrorCode TSForwardGetIntegralGradients(TS ts,PetscInt *numfwdint,Vec **vp) 1843 { 1844 PetscFunctionBegin; 1845 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1846 PetscValidPointer(vp,3); 1847 if (numfwdint) *numfwdint = ts->numcost; 1848 if (vp) *vp = ts->vecs_integral_sensip; 1849 PetscFunctionReturn(0); 1850 } 1851 1852 /*@ 1853 TSForwardStep - Compute the forward sensitivity for one time step. 1854 1855 Collective on TS 1856 1857 Input Arguments: 1858 . ts - time stepping context 1859 1860 Level: advanced 1861 1862 Notes: 1863 This function cannot be called until TSStep() has been completed. 1864 1865 .keywords: TS, forward sensitivity 1866 1867 .seealso: TSForwardSetSensitivities(), TSForwardGetSensitivities(), TSForwardSetIntegralGradients(), TSForwardGetIntegralGradients(), TSForwardSetUp() 1868 @*/ 1869 PetscErrorCode TSForwardStep(TS ts) 1870 { 1871 PetscErrorCode ierr; 1872 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1873 if (!ts->ops->forwardstep) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"%s does not provide forward sensitivity analysis",((PetscObject)ts)->type_name); 1874 ierr = PetscLogEventBegin(TS_ForwardStep,ts,0,0,0);CHKERRQ(ierr); 1875 ierr = (*ts->ops->forwardstep)(ts);CHKERRQ(ierr); 1876 ierr = PetscLogEventEnd(TS_ForwardStep,ts,0,0,0);CHKERRQ(ierr); 1877 PetscFunctionReturn(0); 1878 } 1879 1880 /*@ 1881 TSForwardSetSensitivities - Sets the initial value of the trajectory sensitivities of solution w.r.t. the problem parameters and initial values. 1882 1883 Logically Collective on TS and Vec 1884 1885 Input Parameters: 1886 + ts - the TS context obtained from TSCreate() 1887 . nump - number of parameters 1888 - Smat - sensitivities with respect to the parameters, the number of entries in these vectors is the same as the number of parameters 1889 1890 Level: beginner 1891 1892 Notes: 1893 Forward sensitivity is also called 'trajectory sensitivity' in some fields such as power systems. 1894 This function turns on a flag to trigger TSSolve() to compute forward sensitivities automatically. 1895 You must call this function before TSSolve(). 1896 The entries in the sensitivity matrix must be correctly initialized with the values S = dy/dp|startingtime. 1897 1898 .keywords: TS, timestep, set, forward sensitivity, initial values 1899 1900 .seealso: TSForwardGetSensitivities(), TSForwardSetIntegralGradients(), TSForwardGetIntegralGradients(), TSForwardStep() 1901 @*/ 1902 PetscErrorCode TSForwardSetSensitivities(TS ts,PetscInt nump,Mat Smat) 1903 { 1904 PetscErrorCode ierr; 1905 1906 PetscFunctionBegin; 1907 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1908 PetscValidHeaderSpecific(Smat,MAT_CLASSID,3); 1909 ts->forward_solve = PETSC_TRUE; 1910 if (nump == PETSC_DEFAULT) { 1911 ierr = MatGetSize(Smat,NULL,&ts->num_parameters);CHKERRQ(ierr); 1912 } else ts->num_parameters = nump; 1913 ierr = PetscObjectReference((PetscObject)Smat);CHKERRQ(ierr); 1914 ierr = MatDestroy(&ts->mat_sensip);CHKERRQ(ierr); 1915 ts->mat_sensip = Smat; 1916 PetscFunctionReturn(0); 1917 } 1918 1919 /*@ 1920 TSForwardGetSensitivities - Returns the trajectory sensitivities 1921 1922 Not Collective, but Vec returned is parallel if TS is parallel 1923 1924 Output Parameter: 1925 + ts - the TS context obtained from TSCreate() 1926 . nump - number of parameters 1927 - Smat - sensitivities with respect to the parameters, the number of entries in these vectors is the same as the number of parameters 1928 1929 Level: intermediate 1930 1931 .keywords: TS, forward sensitivity 1932 1933 .seealso: TSForwardSetSensitivities(), TSForwardSetIntegralGradients(), TSForwardGetIntegralGradients(), TSForwardStep() 1934 @*/ 1935 PetscErrorCode TSForwardGetSensitivities(TS ts,PetscInt *nump,Mat *Smat) 1936 { 1937 PetscFunctionBegin; 1938 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1939 if (nump) *nump = ts->num_parameters; 1940 if (Smat) *Smat = ts->mat_sensip; 1941 PetscFunctionReturn(0); 1942 } 1943 1944 /*@ 1945 TSForwardCostIntegral - Evaluate the cost integral in the forward run. 1946 1947 Collective on TS 1948 1949 Input Arguments: 1950 . ts - time stepping context 1951 1952 Level: advanced 1953 1954 Notes: 1955 This function cannot be called until TSStep() has been completed. 1956 1957 .seealso: TSSolve(), TSAdjointCostIntegral() 1958 @*/ 1959 PetscErrorCode TSForwardCostIntegral(TS ts) 1960 { 1961 PetscErrorCode ierr; 1962 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1963 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); 1964 ierr = (*ts->ops->forwardintegral)(ts);CHKERRQ(ierr); 1965 PetscFunctionReturn(0); 1966 } 1967 1968 /*@ 1969 TSForwardSetInitialSensitivities - Set initial values for tangent linear sensitivities 1970 1971 Collective on TS and Mat 1972 1973 Input Parameter 1974 + ts - the TS context obtained from TSCreate() 1975 - didp - parametric sensitivities of the initial condition 1976 1977 Level: intermediate 1978 1979 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. 1980 1981 .seealso: TSForwardSetSensitivities() 1982 @*/ 1983 PetscErrorCode TSForwardSetInitialSensitivities(TS ts,Mat didp) 1984 { 1985 PetscErrorCode ierr; 1986 1987 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1988 PetscValidHeaderSpecific(didp,MAT_CLASSID,2); 1989 if (!ts->mat_sensip) { 1990 ierr = TSForwardSetSensitivities(ts,PETSC_DEFAULT,didp);CHKERRQ(ierr); 1991 } 1992 PetscFunctionReturn(0); 1993 } 1994 1995 /*@ 1996 TSForwardGetStages - Get the number of stages and the tangent linear sensitivities at the intermediate stages 1997 1998 Input Parameter: 1999 . ts - the TS context obtained from TSCreate() 2000 2001 Output Parameters: 2002 + ns - number of stages 2003 - S - tangent linear sensitivities at the intermediate stages 2004 2005 Level: advanced 2006 2007 .keywords: TS, second-order adjoint, forward sensitivity 2008 @*/ 2009 PetscErrorCode TSForwardGetStages(TS ts,PetscInt *ns,Mat **S) 2010 { 2011 PetscErrorCode ierr; 2012 2013 PetscFunctionBegin; 2014 PetscValidHeaderSpecific(ts, TS_CLASSID,1); 2015 2016 if (!ts->ops->getstages) *S=NULL; 2017 else { 2018 ierr = (*ts->ops->forwardgetstages)(ts,ns,S);CHKERRQ(ierr); 2019 } 2020 PetscFunctionReturn(0); 2021 } 2022 2023 /*@ 2024 TSCreateQuadratureTS - Create a sub-TS that evaluates integrals over time 2025 2026 Input Parameter: 2027 + ts - the TS context obtained from TSCreate() 2028 - fwd - flag indicating whether to evaluate cost integral in the forward run or the adjoint run 2029 2030 Output Parameters: 2031 . quadts - the child TS context 2032 2033 Level: intermediate 2034 2035 .keywords: TS, quadrature evaluation 2036 2037 .seealso: TSGetQuadratureTS() 2038 @*/ 2039 PetscErrorCode TSCreateQuadratureTS(TS ts,PetscBool fwd,TS *quadts) 2040 { 2041 char prefix[128]; 2042 PetscErrorCode ierr; 2043 2044 PetscFunctionBegin; 2045 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 2046 PetscValidPointer(quadts,2); 2047 ierr = TSDestroy(&ts->quadraturets);CHKERRQ(ierr); 2048 ierr = TSCreate(PetscObjectComm((PetscObject)ts),&ts->quadraturets);CHKERRQ(ierr); 2049 ierr = PetscObjectIncrementTabLevel((PetscObject)ts->quadraturets,(PetscObject)ts,1);CHKERRQ(ierr); 2050 ierr = PetscLogObjectParent((PetscObject)ts,(PetscObject)ts->quadraturets);CHKERRQ(ierr); 2051 ierr = PetscSNPrintf(prefix,sizeof(prefix),"%squad_",((PetscObject)ts)->prefix ? ((PetscObject)ts)->prefix : "");CHKERRQ(ierr); 2052 ierr = TSSetOptionsPrefix(ts->quadraturets,prefix);CHKERRQ(ierr); 2053 *quadts = ts->quadraturets; 2054 2055 if (ts->numcost) { 2056 ierr = VecCreateSeq(PETSC_COMM_SELF,ts->numcost,&(*quadts)->vec_sol);CHKERRQ(ierr); 2057 } else { 2058 ierr = VecCreateSeq(PETSC_COMM_SELF,1,&(*quadts)->vec_sol);CHKERRQ(ierr); 2059 } 2060 ts->costintegralfwd = fwd; 2061 PetscFunctionReturn(0); 2062 } 2063 2064 /*@ 2065 TSGetQuadratureTS - Return the sub-TS that evaluates integrals over time 2066 2067 Input Parameter: 2068 . ts - the TS context obtained from TSCreate() 2069 2070 Output Parameters: 2071 + fwd - flag indicating whether to evaluate cost integral in the forward run or the adjoint run 2072 - quadts - the child TS context 2073 2074 Level: intermediate 2075 2076 .keywords: TS, quadrature evaluation 2077 2078 .seealso: TSCreateQuadratureTS() 2079 @*/ 2080 PetscErrorCode TSGetQuadratureTS(TS ts,PetscBool *fwd,TS *quadts) 2081 { 2082 PetscFunctionBegin; 2083 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 2084 if (fwd) *fwd = ts->costintegralfwd; 2085 if (quadts) *quadts = ts->quadraturets; 2086 PetscFunctionReturn(0); 2087 } 2088