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 Note: 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 - input vector to be left-multiplied with the Hessian 467 . Vr - input vector to be right-multiplied with the Hessian 468 . VHV - output vector for vector-Hessian-vector product 469 - ctx - [optional] user-defined function context 470 471 Level: intermediate 472 473 Note: The first Hessian function and the working array are required. 474 475 .keywords: TS, sensitivity 476 477 .seealso: 478 @*/ 479 PetscErrorCode TSSetIHessianProduct(TS ts,Vec *ihp1,PetscErrorCode (*ihessianproductfunc1)(TS,PetscReal,Vec,Vec*,Vec,Vec*,void*), 480 Vec *ihp2,PetscErrorCode (*ihessianproductfunc2)(TS,PetscReal,Vec,Vec*,Vec,Vec*,void*), 481 Vec *ihp3,PetscErrorCode (*ihessianproductfunc3)(TS,PetscReal,Vec,Vec*,Vec,Vec*,void*), 482 Vec *ihp4,PetscErrorCode (*ihessianproductfunc4)(TS,PetscReal,Vec,Vec*,Vec,Vec*,void*), 483 void *ctx) 484 { 485 PetscFunctionBegin; 486 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 487 PetscValidPointer(ihp1,2); 488 489 ts->ihessianproductctx = ctx; 490 if (ihp1) ts->vecs_fuu = ihp1; 491 if (ihp2) ts->vecs_fup = ihp2; 492 if (ihp3) ts->vecs_fpu = ihp3; 493 if (ihp4) ts->vecs_fpp = ihp4; 494 ts->ihessianproduct_fuu = ihessianproductfunc1; 495 ts->ihessianproduct_fup = ihessianproductfunc2; 496 ts->ihessianproduct_fpu = ihessianproductfunc3; 497 ts->ihessianproduct_fpp = ihessianproductfunc4; 498 PetscFunctionReturn(0); 499 } 500 501 /*@C 502 TSComputeIHessianProductFunction1 - Runs the user-defined vector-Hessian-vector product function for Fuu. 503 504 Collective on TS 505 506 Input Parameters: 507 . ts - The TS context obtained from TSCreate() 508 509 Notes: 510 TSComputeIHessianProductFunction1() is typically used for sensitivity implementation, 511 so most users would not generally call this routine themselves. 512 513 Level: developer 514 515 .keywords: TS, sensitivity 516 517 .seealso: TSSetIHessianProduct() 518 @*/ 519 PetscErrorCode TSComputeIHessianProductFunction1(TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV) 520 { 521 PetscErrorCode ierr; 522 523 PetscFunctionBegin; 524 if (!VHV) PetscFunctionReturn(0); 525 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 526 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 527 528 if (ts->ihessianproduct_fuu) { 529 PetscStackPush("TS user IHessianProduct function 1 for sensitivity analysis"); 530 ierr = (*ts->ihessianproduct_fuu)(ts,t,U,Vl,Vr,VHV,ts->ihessianproductctx);CHKERRQ(ierr); 531 PetscStackPop; 532 } 533 /* does not consider IMEX for now, so either IHessian or RHSHessian will be calculated, using the same output VHV */ 534 if (ts->rhshessianproduct_guu) { 535 PetscInt nadj; 536 ierr = TSComputeRHSHessianProductFunction1(ts,t,U,Vl,Vr,VHV);CHKERRQ(ierr); 537 for (nadj=0; nadj<ts->numcost; nadj++) { 538 ierr = VecScale(VHV[nadj],-1);CHKERRQ(ierr); 539 } 540 } 541 PetscFunctionReturn(0); 542 } 543 544 /*@C 545 TSComputeIHessianProductFunction2 - Runs the user-defined vector-Hessian-vector product function for Fup. 546 547 Collective on TS 548 549 Input Parameters: 550 . ts - The TS context obtained from TSCreate() 551 552 Notes: 553 TSComputeIHessianProductFunction2() is typically used for sensitivity implementation, 554 so most users would not generally call this routine themselves. 555 556 Level: developer 557 558 .keywords: TS, sensitivity 559 560 .seealso: TSSetIHessianProduct() 561 @*/ 562 PetscErrorCode TSComputeIHessianProductFunction2(TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV) 563 { 564 PetscErrorCode ierr; 565 566 PetscFunctionBegin; 567 if (!VHV) PetscFunctionReturn(0); 568 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 569 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 570 571 if (ts->ihessianproduct_fup) { 572 PetscStackPush("TS user IHessianProduct function 2 for sensitivity analysis"); 573 ierr = (*ts->ihessianproduct_fup)(ts,t,U,Vl,Vr,VHV,ts->ihessianproductctx);CHKERRQ(ierr); 574 PetscStackPop; 575 } 576 /* does not consider IMEX for now, so either IHessian or RHSHessian will be calculated, using the same output VHV */ 577 if (ts->rhshessianproduct_gup) { 578 PetscInt nadj; 579 ierr = TSComputeRHSHessianProductFunction2(ts,t,U,Vl,Vr,VHV);CHKERRQ(ierr); 580 for (nadj=0; nadj<ts->numcost; nadj++) { 581 ierr = VecScale(VHV[nadj],-1);CHKERRQ(ierr); 582 } 583 } 584 PetscFunctionReturn(0); 585 } 586 587 /*@C 588 TSComputeIHessianProductFunction3 - Runs the user-defined vector-Hessian-vector product function for Fpu. 589 590 Collective on TS 591 592 Input Parameters: 593 . ts - The TS context obtained from TSCreate() 594 595 Notes: 596 TSComputeIHessianProductFunction3() is typically used for sensitivity implementation, 597 so most users would not generally call this routine themselves. 598 599 Level: developer 600 601 .keywords: TS, sensitivity 602 603 .seealso: TSSetIHessianProduct() 604 @*/ 605 PetscErrorCode TSComputeIHessianProductFunction3(TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV) 606 { 607 PetscErrorCode ierr; 608 609 PetscFunctionBegin; 610 if (!VHV) PetscFunctionReturn(0); 611 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 612 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 613 614 if (ts->ihessianproduct_fpu) { 615 PetscStackPush("TS user IHessianProduct function 3 for sensitivity analysis"); 616 ierr = (*ts->ihessianproduct_fpu)(ts,t,U,Vl,Vr,VHV,ts->ihessianproductctx);CHKERRQ(ierr); 617 PetscStackPop; 618 } 619 /* does not consider IMEX for now, so either IHessian or RHSHessian will be calculated, using the same output VHV */ 620 if (ts->rhshessianproduct_gpu) { 621 PetscInt nadj; 622 ierr = TSComputeRHSHessianProductFunction3(ts,t,U,Vl,Vr,VHV);CHKERRQ(ierr); 623 for (nadj=0; nadj<ts->numcost; nadj++) { 624 ierr = VecScale(VHV[nadj],-1);CHKERRQ(ierr); 625 } 626 } 627 PetscFunctionReturn(0); 628 } 629 630 /*@C 631 TSComputeIHessianProductFunction4 - Runs the user-defined vector-Hessian-vector product function for Fpp. 632 633 Collective on TS 634 635 Input Parameters: 636 . ts - The TS context obtained from TSCreate() 637 638 Notes: 639 TSComputeIHessianProductFunction4() is typically used for sensitivity implementation, 640 so most users would not generally call this routine themselves. 641 642 Level: developer 643 644 .keywords: TS, sensitivity 645 646 .seealso: TSSetIHessianProduct() 647 @*/ 648 PetscErrorCode TSComputeIHessianProductFunction4(TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV) 649 { 650 PetscErrorCode ierr; 651 652 PetscFunctionBegin; 653 if (!VHV) PetscFunctionReturn(0); 654 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 655 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 656 657 if (ts->ihessianproduct_fpp) { 658 PetscStackPush("TS user IHessianProduct function 3 for sensitivity analysis"); 659 ierr = (*ts->ihessianproduct_fpp)(ts,t,U,Vl,Vr,VHV,ts->ihessianproductctx);CHKERRQ(ierr); 660 PetscStackPop; 661 } 662 /* does not consider IMEX for now, so either IHessian or RHSHessian will be calculated, using the same output VHV */ 663 if (ts->rhshessianproduct_gpp) { 664 PetscInt nadj; 665 ierr = TSComputeRHSHessianProductFunction4(ts,t,U,Vl,Vr,VHV);CHKERRQ(ierr); 666 for (nadj=0; nadj<ts->numcost; nadj++) { 667 ierr = VecScale(VHV[nadj],-1);CHKERRQ(ierr); 668 } 669 } 670 PetscFunctionReturn(0); 671 } 672 673 /*@C 674 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. 675 676 Logically Collective on TS 677 678 Input Parameters: 679 + ts - TS context obtained from TSCreate() 680 . rhshp1 - an array of vectors storing the result of vector-Hessian-vector product for G_UU 681 . hessianproductfunc1 - vector-Hessian-vector product function for G_UU 682 . rhshp2 - an array of vectors storing the result of vector-Hessian-vector product for G_UP 683 . hessianproductfunc2 - vector-Hessian-vector product function for G_UP 684 . rhshp3 - an array of vectors storing the result of vector-Hessian-vector product for G_PU 685 . hessianproductfunc3 - vector-Hessian-vector product function for G_PU 686 . rhshp4 - an array of vectors storing the result of vector-Hessian-vector product for G_PP 687 . hessianproductfunc4 - vector-Hessian-vector product function for G_PP 688 689 Calling sequence of ihessianproductfunc: 690 $ rhshessianproductfunc (TS ts,PetscReal t,Vec U,Vec Vl,Vec Vr,Vec VHV,void *ctx); 691 + t - current timestep 692 . U - input vector (current ODE solution) 693 . Vl - input vector to be left-multiplied with the Hessian 694 . Vr - input vector to be right-multiplied with the Hessian 695 . VHV - output vector for vector-Hessian-vector product 696 - ctx - [optional] user-defined function context 697 698 Level: intermediate 699 700 Note: The first Hessian function and the working array are required. 701 702 .keywords: TS, sensitivity 703 704 .seealso: 705 @*/ 706 PetscErrorCode TSSetRHSHessianProduct(TS ts,Vec *rhshp1,PetscErrorCode (*rhshessianproductfunc1)(TS,PetscReal,Vec,Vec*,Vec,Vec*,void*), 707 Vec *rhshp2,PetscErrorCode (*rhshessianproductfunc2)(TS,PetscReal,Vec,Vec*,Vec,Vec*,void*), 708 Vec *rhshp3,PetscErrorCode (*rhshessianproductfunc3)(TS,PetscReal,Vec,Vec*,Vec,Vec*,void*), 709 Vec *rhshp4,PetscErrorCode (*rhshessianproductfunc4)(TS,PetscReal,Vec,Vec*,Vec,Vec*,void*), 710 void *ctx) 711 { 712 PetscFunctionBegin; 713 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 714 PetscValidPointer(rhshp1,2); 715 716 ts->rhshessianproductctx = ctx; 717 if (rhshp1) ts->vecs_guu = rhshp1; 718 if (rhshp2) ts->vecs_gup = rhshp2; 719 if (rhshp3) ts->vecs_gpu = rhshp3; 720 if (rhshp4) ts->vecs_gpp = rhshp4; 721 ts->rhshessianproduct_guu = rhshessianproductfunc1; 722 ts->rhshessianproduct_gup = rhshessianproductfunc2; 723 ts->rhshessianproduct_gpu = rhshessianproductfunc3; 724 ts->rhshessianproduct_gpp = rhshessianproductfunc4; 725 PetscFunctionReturn(0); 726 } 727 728 /*@C 729 TSComputeRHSHessianProductFunction1 - Runs the user-defined vector-Hessian-vector product function for Guu. 730 731 Collective on TS 732 733 Input Parameters: 734 . ts - The TS context obtained from TSCreate() 735 736 Notes: 737 TSComputeRHSHessianProductFunction1() is typically used for sensitivity implementation, 738 so most users would not generally call this routine themselves. 739 740 Level: developer 741 742 .keywords: TS, sensitivity 743 744 .seealso: TSSetRHSHessianProduct() 745 @*/ 746 PetscErrorCode TSComputeRHSHessianProductFunction1(TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV) 747 { 748 PetscErrorCode ierr; 749 750 PetscFunctionBegin; 751 if (!VHV) PetscFunctionReturn(0); 752 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 753 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 754 755 PetscStackPush("TS user RHSHessianProduct function 1 for sensitivity analysis"); 756 ierr = (*ts->rhshessianproduct_guu)(ts,t,U,Vl,Vr,VHV,ts->rhshessianproductctx);CHKERRQ(ierr); 757 PetscStackPop; 758 PetscFunctionReturn(0); 759 } 760 761 /*@C 762 TSComputeRHSHessianProductFunction2 - Runs the user-defined vector-Hessian-vector product function for Gup. 763 764 Collective on TS 765 766 Input Parameters: 767 . ts - The TS context obtained from TSCreate() 768 769 Notes: 770 TSComputeRHSHessianProductFunction2() is typically used for sensitivity implementation, 771 so most users would not generally call this routine themselves. 772 773 Level: developer 774 775 .keywords: TS, sensitivity 776 777 .seealso: TSSetRHSHessianProduct() 778 @*/ 779 PetscErrorCode TSComputeRHSHessianProductFunction2(TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV) 780 { 781 PetscErrorCode ierr; 782 783 PetscFunctionBegin; 784 if (!VHV) PetscFunctionReturn(0); 785 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 786 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 787 788 PetscStackPush("TS user RHSHessianProduct function 2 for sensitivity analysis"); 789 ierr = (*ts->rhshessianproduct_gup)(ts,t,U,Vl,Vr,VHV,ts->rhshessianproductctx);CHKERRQ(ierr); 790 PetscStackPop; 791 PetscFunctionReturn(0); 792 } 793 794 /*@C 795 TSComputeRHSHessianProductFunction3 - Runs the user-defined vector-Hessian-vector product function for Gpu. 796 797 Collective on TS 798 799 Input Parameters: 800 . ts - The TS context obtained from TSCreate() 801 802 Notes: 803 TSComputeRHSHessianProductFunction3() is typically used for sensitivity implementation, 804 so most users would not generally call this routine themselves. 805 806 Level: developer 807 808 .keywords: TS, sensitivity 809 810 .seealso: TSSetRHSHessianProduct() 811 @*/ 812 PetscErrorCode TSComputeRHSHessianProductFunction3(TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV) 813 { 814 PetscErrorCode ierr; 815 816 PetscFunctionBegin; 817 if (!VHV) PetscFunctionReturn(0); 818 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 819 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 820 821 PetscStackPush("TS user RHSHessianProduct function 3 for sensitivity analysis"); 822 ierr = (*ts->rhshessianproduct_gpu)(ts,t,U,Vl,Vr,VHV,ts->rhshessianproductctx);CHKERRQ(ierr); 823 PetscStackPop; 824 PetscFunctionReturn(0); 825 } 826 827 /*@C 828 TSComputeRHSHessianProductFunction4 - Runs the user-defined vector-Hessian-vector product function for Gpp. 829 830 Collective on TS 831 832 Input Parameters: 833 . ts - The TS context obtained from TSCreate() 834 835 Notes: 836 TSComputeRHSHessianProductFunction4() is typically used for sensitivity implementation, 837 so most users would not generally call this routine themselves. 838 839 Level: developer 840 841 .keywords: TS, sensitivity 842 843 .seealso: TSSetRHSHessianProduct() 844 @*/ 845 PetscErrorCode TSComputeRHSHessianProductFunction4(TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV) 846 { 847 PetscErrorCode ierr; 848 849 PetscFunctionBegin; 850 if (!VHV) PetscFunctionReturn(0); 851 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 852 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 853 854 PetscStackPush("TS user RHSHessianProduct function 3 for sensitivity analysis"); 855 ierr = (*ts->rhshessianproduct_gpp)(ts,t,U,Vl,Vr,VHV,ts->rhshessianproductctx);CHKERRQ(ierr); 856 PetscStackPop; 857 PetscFunctionReturn(0); 858 } 859 860 /* --------------------------- Adjoint sensitivity ---------------------------*/ 861 862 /*@ 863 TSSetCostGradients - Sets the initial value of the gradients of the cost function w.r.t. initial values and w.r.t. the problem parameters 864 for use by the TSAdjoint routines. 865 866 Logically Collective on TS and Vec 867 868 Input Parameters: 869 + ts - the TS context obtained from TSCreate() 870 . 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 871 - mu - gradients with respect to the parameters, the number of entries in these vectors is the same as the number of parameters 872 873 Level: beginner 874 875 Notes: 876 the entries in these vectors must be correctly initialized with the values lamda_i = df/dy|finaltime mu_i = df/dp|finaltime 877 878 After TSAdjointSolve() is called the lamba and the mu contain the computed sensitivities 879 880 .keywords: TS, timestep, set, sensitivity, initial values 881 882 .seealso TSGetCostGradients() 883 @*/ 884 PetscErrorCode TSSetCostGradients(TS ts,PetscInt numcost,Vec *lambda,Vec *mu) 885 { 886 PetscFunctionBegin; 887 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 888 PetscValidPointer(lambda,2); 889 ts->vecs_sensi = lambda; 890 ts->vecs_sensip = mu; 891 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"); 892 ts->numcost = numcost; 893 PetscFunctionReturn(0); 894 } 895 896 /*@ 897 TSGetCostGradients - Returns the gradients from the TSAdjointSolve() 898 899 Not Collective, but Vec returned is parallel if TS is parallel 900 901 Input Parameter: 902 . ts - the TS context obtained from TSCreate() 903 904 Output Parameter: 905 + lambda - vectors containing the gradients of the cost functions with respect to the ODE/DAE solution variables 906 - mu - vectors containing the gradients of the cost functions with respect to the problem parameters 907 908 Level: intermediate 909 910 .keywords: TS, timestep, get, sensitivity 911 912 .seealso: TSSetCostGradients() 913 @*/ 914 PetscErrorCode TSGetCostGradients(TS ts,PetscInt *numcost,Vec **lambda,Vec **mu) 915 { 916 PetscFunctionBegin; 917 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 918 if (numcost) *numcost = ts->numcost; 919 if (lambda) *lambda = ts->vecs_sensi; 920 if (mu) *mu = ts->vecs_sensip; 921 PetscFunctionReturn(0); 922 } 923 924 /*@ 925 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 926 for use by the TSAdjoint routines. 927 928 Logically Collective on TS and Vec 929 930 Input Parameters: 931 + ts - the TS context obtained from TSCreate() 932 . numcost - number of cost functions 933 . 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 934 . mu2 - Hessian-vector product with respect to the parameters, the number of entries in these vectors is the same as the number of parameters 935 - dir - the direction vector that are multiplied with the Hessian of the cost functions 936 937 Level: beginner 938 939 Notes: Hessian of the cost function is completely different from Hessian of the ODE/DAE system 940 941 For second-order adjoint, one needs to call this function and then TSAdjointInitializeForward() before TSSolve(). 942 943 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. 944 945 Passing NULL for lambda2 disables the second-order calculation. 946 .keywords: TS, sensitivity, second-order adjoint 947 948 .seealso: TSAdjointInitializeForward() 949 @*/ 950 PetscErrorCode TSSetCostHessianProducts(TS ts,PetscInt numcost,Vec *lambda2,Vec *mu2,Vec dir) 951 { 952 PetscFunctionBegin; 953 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 954 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"); 955 ts->numcost = numcost; 956 ts->vecs_sensi2 = lambda2; 957 ts->vecs_sensi2p = mu2; 958 ts->vec_dir = dir; 959 PetscFunctionReturn(0); 960 } 961 962 /*@ 963 TSGetCostHessianProducts - Returns the gradients from the TSAdjointSolve() 964 965 Not Collective, but Vec returned is parallel if TS is parallel 966 967 Input Parameter: 968 . ts - the TS context obtained from TSCreate() 969 970 Output Parameter: 971 + numcost - number of cost functions 972 . 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 973 . mu2 - Hessian-vector product with respect to the parameters, the number of entries in these vectors is the same as the number of parameters 974 - dir - the direction vector that are multiplied with the Hessian of the cost functions 975 976 Level: intermediate 977 978 .keywords: TS, sensitivity, second-order adjoint 979 980 .seealso: TSSetCostHessianProducts() 981 @*/ 982 PetscErrorCode TSGetCostHessianProducts(TS ts,PetscInt *numcost,Vec **lambda2,Vec **mu2, Vec *dir) 983 { 984 PetscFunctionBegin; 985 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 986 if (numcost) *numcost = ts->numcost; 987 if (lambda2) *lambda2 = ts->vecs_sensi2; 988 if (mu2) *mu2 = ts->vecs_sensi2p; 989 if (dir) *dir = ts->vec_dir; 990 PetscFunctionReturn(0); 991 } 992 993 /*@ 994 TSAdjointInitializeForward - Trigger the tangent linear solver and initialize the forward sensitivities 995 996 Logically Collective on TS and Mat 997 998 Input Parameters: 999 + ts - the TS context obtained from TSCreate() 1000 - didp - the derivative of initial values w.r.t. parameters 1001 1002 Level: intermediate 1003 1004 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. 1005 1006 .keywords: TS, sensitivity, second-order adjoint 1007 1008 .seealso: TSSetCostHessianProducts() 1009 @*/ 1010 PetscErrorCode TSAdjointInitializeForward(TS ts,Mat didp) 1011 { 1012 Mat A; 1013 Vec sp; 1014 PetscScalar *xarr; 1015 PetscInt lsize; 1016 PetscErrorCode ierr; 1017 1018 PetscFunctionBegin; 1019 ts->forward_solve = PETSC_TRUE; /* turn on tangent linear mode */ 1020 if (!ts->vecs_sensi2) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Must call TSSetCostHessianProducts() first"); 1021 if (!ts->vec_dir) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Directional vector is missing. Call TSSetCostHessianProducts() to set it."); 1022 /* create a single-column dense matrix */ 1023 ierr = VecGetLocalSize(ts->vec_sol,&lsize);CHKERRQ(ierr); 1024 ierr = MatCreateDense(PETSC_COMM_WORLD,lsize,PETSC_DECIDE,PETSC_DECIDE,1,NULL,&A);CHKERRQ(ierr); 1025 1026 ierr = VecDuplicate(ts->vec_sol,&sp);CHKERRQ(ierr); 1027 ierr = MatDenseGetColumn(A,0,&xarr);CHKERRQ(ierr); 1028 ierr = VecPlaceArray(sp,xarr);CHKERRQ(ierr); 1029 if (ts->vecs_sensi2p) { /* TLM variable initialized as 2*dIdP*dir */ 1030 if (didp) { 1031 ierr = MatMult(didp,ts->vec_dir,sp);CHKERRQ(ierr); 1032 ierr = VecScale(sp,2.);CHKERRQ(ierr); 1033 } else { 1034 ierr = VecZeroEntries(sp);CHKERRQ(ierr); 1035 } 1036 } else { /* TLM variable initialized as dir */ 1037 ierr = VecCopy(ts->vec_dir,sp);CHKERRQ(ierr); 1038 } 1039 ierr = VecResetArray(sp);CHKERRQ(ierr); 1040 ierr = MatDenseRestoreColumn(A,&xarr);CHKERRQ(ierr); 1041 ierr = VecDestroy(&sp);CHKERRQ(ierr); 1042 1043 ierr = TSForwardSetInitialSensitivities(ts,A);CHKERRQ(ierr); /* if didp is NULL, identity matrix is assumed */ 1044 1045 ierr = MatDestroy(&A);CHKERRQ(ierr); 1046 PetscFunctionReturn(0); 1047 } 1048 1049 /*@ 1050 TSAdjointSetUp - Sets up the internal data structures for the later use 1051 of an adjoint solver 1052 1053 Collective on TS 1054 1055 Input Parameter: 1056 . ts - the TS context obtained from TSCreate() 1057 1058 Level: advanced 1059 1060 .keywords: TS, timestep, setup 1061 1062 .seealso: TSCreate(), TSAdjointStep(), TSSetCostGradients() 1063 @*/ 1064 PetscErrorCode TSAdjointSetUp(TS ts) 1065 { 1066 PetscErrorCode ierr; 1067 1068 PetscFunctionBegin; 1069 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1070 if (ts->adjointsetupcalled) PetscFunctionReturn(0); 1071 if (!ts->vecs_sensi) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONGSTATE,"Must call TSSetCostGradients() first"); 1072 if (ts->vecs_sensip && !ts->Jacp && !ts->Jacprhs) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONGSTATE,"Must call TSSetRHSJacobianP() or TSSetIJacobianP() first"); 1073 1074 if (!ts->Jacp && ts->Jacprhs) ts->Jacp = ts->Jacprhs; 1075 1076 if (ts->quadraturets) { /* if there is integral in the cost function */ 1077 ierr = VecDuplicate(ts->vecs_sensi[0],&ts->vec_drdu_col);CHKERRQ(ierr); 1078 if (ts->vecs_sensip){ 1079 ierr = VecDuplicate(ts->vecs_sensip[0],&ts->vec_drdp_col);CHKERRQ(ierr); 1080 } 1081 } 1082 1083 if (ts->ops->adjointsetup) { 1084 ierr = (*ts->ops->adjointsetup)(ts);CHKERRQ(ierr); 1085 } 1086 ts->adjointsetupcalled = PETSC_TRUE; 1087 PetscFunctionReturn(0); 1088 } 1089 1090 /*@ 1091 TSAdjointReset - Resets a TSAdjoint context and removes any allocated Vecs and Mats. 1092 1093 Collective on TS 1094 1095 Input Parameter: 1096 . ts - the TS context obtained from TSCreate() 1097 1098 Level: beginner 1099 1100 .keywords: TS, timestep, reset 1101 1102 .seealso: TSCreate(), TSAdjointSetup(), TSADestroy() 1103 @*/ 1104 PetscErrorCode TSAdjointReset(TS ts) 1105 { 1106 PetscErrorCode ierr; 1107 1108 PetscFunctionBegin; 1109 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1110 if (ts->ops->adjointreset) { 1111 ierr = (*ts->ops->adjointreset)(ts);CHKERRQ(ierr); 1112 } 1113 if (ts->quadraturets) { /* if there is integral in the cost function */ 1114 ierr = VecDestroy(&ts->vec_drdu_col);CHKERRQ(ierr); 1115 if (ts->vecs_sensip){ 1116 ierr = VecDestroy(&ts->vec_drdp_col);CHKERRQ(ierr); 1117 } 1118 } 1119 if (ts->vec_dir) { /* second-order adjoint */ 1120 ierr = TSForwardReset(ts);CHKERRQ(ierr); 1121 } 1122 ts->vecs_sensi = NULL; 1123 ts->vecs_sensip = NULL; 1124 ts->vecs_sensi2 = NULL; 1125 ts->vecs_sensi2p = NULL; 1126 ts->vec_dir = NULL; 1127 ts->adjointsetupcalled = PETSC_FALSE; 1128 PetscFunctionReturn(0); 1129 } 1130 1131 /*@ 1132 TSAdjointSetSteps - Sets the number of steps the adjoint solver should take backward in time 1133 1134 Logically Collective on TS 1135 1136 Input Parameters: 1137 + ts - the TS context obtained from TSCreate() 1138 . steps - number of steps to use 1139 1140 Level: intermediate 1141 1142 Notes: 1143 Normally one does not call this and TSAdjointSolve() integrates back to the original timestep. One can call this 1144 so as to integrate back to less than the original timestep 1145 1146 .keywords: TS, timestep, set, maximum, iterations 1147 1148 .seealso: TSSetExactFinalTime() 1149 @*/ 1150 PetscErrorCode TSAdjointSetSteps(TS ts,PetscInt steps) 1151 { 1152 PetscFunctionBegin; 1153 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1154 PetscValidLogicalCollectiveInt(ts,steps,2); 1155 if (steps < 0) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Cannot step back a negative number of steps"); 1156 if (steps > ts->steps) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Cannot step back more than the total number of forward steps"); 1157 ts->adjoint_max_steps = steps; 1158 PetscFunctionReturn(0); 1159 } 1160 1161 /*@C 1162 TSAdjointSetRHSJacobian - Deprecated, use TSSetRHSJacobianP() 1163 1164 Level: deprecated 1165 1166 @*/ 1167 PetscErrorCode TSAdjointSetRHSJacobian(TS ts,Mat Amat,PetscErrorCode (*func)(TS,PetscReal,Vec,Mat,void*),void *ctx) 1168 { 1169 PetscErrorCode ierr; 1170 1171 PetscFunctionBegin; 1172 PetscValidHeaderSpecific(ts, TS_CLASSID,1); 1173 PetscValidHeaderSpecific(Amat,MAT_CLASSID,2); 1174 1175 ts->rhsjacobianp = func; 1176 ts->rhsjacobianpctx = ctx; 1177 if(Amat) { 1178 ierr = PetscObjectReference((PetscObject)Amat);CHKERRQ(ierr); 1179 ierr = MatDestroy(&ts->Jacp);CHKERRQ(ierr); 1180 ts->Jacp = Amat; 1181 } 1182 PetscFunctionReturn(0); 1183 } 1184 1185 /*@C 1186 TSAdjointComputeRHSJacobian - Deprecated, use TSComputeRHSJacobianP() 1187 1188 Level: deprecated 1189 1190 @*/ 1191 PetscErrorCode TSAdjointComputeRHSJacobian(TS ts,PetscReal t,Vec U,Mat Amat) 1192 { 1193 PetscErrorCode ierr; 1194 1195 PetscFunctionBegin; 1196 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1197 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 1198 PetscValidPointer(Amat,4); 1199 1200 PetscStackPush("TS user JacobianP function for sensitivity analysis"); 1201 ierr = (*ts->rhsjacobianp)(ts,t,U,Amat,ts->rhsjacobianpctx); CHKERRQ(ierr); 1202 PetscStackPop; 1203 PetscFunctionReturn(0); 1204 } 1205 1206 /*@ 1207 TSAdjointComputeDRDYFunction - Deprecated, use TSComputeDRDUFunction() 1208 1209 Level: deprecated 1210 1211 @*/ 1212 PetscErrorCode TSAdjointComputeDRDYFunction(TS ts,PetscReal t,Vec U,Vec *DRDU) 1213 { 1214 PetscErrorCode ierr; 1215 1216 PetscFunctionBegin; 1217 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1218 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 1219 1220 PetscStackPush("TS user DRDY function for sensitivity analysis"); 1221 ierr = (*ts->drdufunction)(ts,t,U,DRDU,ts->costintegrandctx); CHKERRQ(ierr); 1222 PetscStackPop; 1223 PetscFunctionReturn(0); 1224 } 1225 1226 /*@ 1227 TSAdjointComputeDRDPFunction - Deprecated, use TSComputeDRDPFunction() 1228 1229 Level: deprecated 1230 1231 @*/ 1232 PetscErrorCode TSAdjointComputeDRDPFunction(TS ts,PetscReal t,Vec U,Vec *DRDP) 1233 { 1234 PetscErrorCode ierr; 1235 1236 PetscFunctionBegin; 1237 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1238 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 1239 1240 PetscStackPush("TS user DRDP function for sensitivity analysis"); 1241 ierr = (*ts->drdpfunction)(ts,t,U,DRDP,ts->costintegrandctx); CHKERRQ(ierr); 1242 PetscStackPop; 1243 PetscFunctionReturn(0); 1244 } 1245 1246 /*@C 1247 TSAdjointMonitorSensi - monitors the first lambda sensitivity 1248 1249 Level: intermediate 1250 1251 .keywords: TS, set, monitor 1252 1253 .seealso: TSAdjointMonitorSet() 1254 @*/ 1255 PetscErrorCode TSAdjointMonitorSensi(TS ts,PetscInt step,PetscReal ptime,Vec v,PetscInt numcost,Vec *lambda,Vec *mu,PetscViewerAndFormat *vf) 1256 { 1257 PetscErrorCode ierr; 1258 PetscViewer viewer = vf->viewer; 1259 1260 PetscFunctionBegin; 1261 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,4); 1262 ierr = PetscViewerPushFormat(viewer,vf->format);CHKERRQ(ierr); 1263 ierr = VecView(lambda[0],viewer);CHKERRQ(ierr); 1264 ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 1265 PetscFunctionReturn(0); 1266 } 1267 1268 /*@C 1269 TSAdjointMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user 1270 1271 Collective on TS 1272 1273 Input Parameters: 1274 + ts - TS object you wish to monitor 1275 . name - the monitor type one is seeking 1276 . help - message indicating what monitoring is done 1277 . manual - manual page for the monitor 1278 . monitor - the monitor function 1279 - 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 1280 1281 Level: developer 1282 1283 .seealso: PetscOptionsGetViewer(), PetscOptionsGetReal(), PetscOptionsHasName(), PetscOptionsGetString(), 1284 PetscOptionsGetIntArray(), PetscOptionsGetRealArray(), PetscOptionsBool() 1285 PetscOptionsInt(), PetscOptionsString(), PetscOptionsReal(), PetscOptionsBool(), 1286 PetscOptionsName(), PetscOptionsBegin(), PetscOptionsEnd(), PetscOptionsHead(), 1287 PetscOptionsStringArray(),PetscOptionsRealArray(), PetscOptionsScalar(), 1288 PetscOptionsBoolGroupBegin(), PetscOptionsBoolGroup(), PetscOptionsBoolGroupEnd(), 1289 PetscOptionsFList(), PetscOptionsEList() 1290 @*/ 1291 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*)) 1292 { 1293 PetscErrorCode ierr; 1294 PetscViewer viewer; 1295 PetscViewerFormat format; 1296 PetscBool flg; 1297 1298 PetscFunctionBegin; 1299 ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject)ts),((PetscObject) ts)->options,((PetscObject)ts)->prefix,name,&viewer,&format,&flg);CHKERRQ(ierr); 1300 if (flg) { 1301 PetscViewerAndFormat *vf; 1302 ierr = PetscViewerAndFormatCreate(viewer,format,&vf);CHKERRQ(ierr); 1303 ierr = PetscObjectDereference((PetscObject)viewer);CHKERRQ(ierr); 1304 if (monitorsetup) { 1305 ierr = (*monitorsetup)(ts,vf);CHKERRQ(ierr); 1306 } 1307 ierr = TSAdjointMonitorSet(ts,(PetscErrorCode (*)(TS,PetscInt,PetscReal,Vec,PetscInt,Vec*,Vec*,void*))monitor,vf,(PetscErrorCode (*)(void**))PetscViewerAndFormatDestroy);CHKERRQ(ierr); 1308 } 1309 PetscFunctionReturn(0); 1310 } 1311 1312 /*@C 1313 TSAdjointMonitorSet - Sets an ADDITIONAL function that is to be used at every 1314 timestep to display the iteration's progress. 1315 1316 Logically Collective on TS 1317 1318 Input Parameters: 1319 + ts - the TS context obtained from TSCreate() 1320 . adjointmonitor - monitoring routine 1321 . adjointmctx - [optional] user-defined context for private data for the 1322 monitor routine (use NULL if no context is desired) 1323 - adjointmonitordestroy - [optional] routine that frees monitor context 1324 (may be NULL) 1325 1326 Calling sequence of monitor: 1327 $ int adjointmonitor(TS ts,PetscInt steps,PetscReal time,Vec u,PetscInt numcost,Vec *lambda, Vec *mu,void *adjointmctx) 1328 1329 + ts - the TS context 1330 . 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 1331 been interpolated to) 1332 . time - current time 1333 . u - current iterate 1334 . numcost - number of cost functionos 1335 . lambda - sensitivities to initial conditions 1336 . mu - sensitivities to parameters 1337 - adjointmctx - [optional] adjoint monitoring context 1338 1339 Notes: 1340 This routine adds an additional monitor to the list of monitors that 1341 already has been loaded. 1342 1343 Fortran Notes: 1344 Only a single monitor function can be set for each TS object 1345 1346 Level: intermediate 1347 1348 .keywords: TS, timestep, set, adjoint, monitor 1349 1350 .seealso: TSAdjointMonitorCancel() 1351 @*/ 1352 PetscErrorCode TSAdjointMonitorSet(TS ts,PetscErrorCode (*adjointmonitor)(TS,PetscInt,PetscReal,Vec,PetscInt,Vec*,Vec*,void*),void *adjointmctx,PetscErrorCode (*adjointmdestroy)(void**)) 1353 { 1354 PetscErrorCode ierr; 1355 PetscInt i; 1356 PetscBool identical; 1357 1358 PetscFunctionBegin; 1359 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1360 for (i=0; i<ts->numbermonitors;i++) { 1361 ierr = PetscMonitorCompare((PetscErrorCode (*)(void))adjointmonitor,adjointmctx,adjointmdestroy,(PetscErrorCode (*)(void))ts->adjointmonitor[i],ts->adjointmonitorcontext[i],ts->adjointmonitordestroy[i],&identical);CHKERRQ(ierr); 1362 if (identical) PetscFunctionReturn(0); 1363 } 1364 if (ts->numberadjointmonitors >= MAXTSMONITORS) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Too many adjoint monitors set"); 1365 ts->adjointmonitor[ts->numberadjointmonitors] = adjointmonitor; 1366 ts->adjointmonitordestroy[ts->numberadjointmonitors] = adjointmdestroy; 1367 ts->adjointmonitorcontext[ts->numberadjointmonitors++] = (void*)adjointmctx; 1368 PetscFunctionReturn(0); 1369 } 1370 1371 /*@C 1372 TSAdjointMonitorCancel - Clears all the adjoint monitors that have been set on a time-step object. 1373 1374 Logically Collective on TS 1375 1376 Input Parameters: 1377 . ts - the TS context obtained from TSCreate() 1378 1379 Notes: 1380 There is no way to remove a single, specific monitor. 1381 1382 Level: intermediate 1383 1384 .keywords: TS, timestep, set, adjoint, monitor 1385 1386 .seealso: TSAdjointMonitorSet() 1387 @*/ 1388 PetscErrorCode TSAdjointMonitorCancel(TS ts) 1389 { 1390 PetscErrorCode ierr; 1391 PetscInt i; 1392 1393 PetscFunctionBegin; 1394 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1395 for (i=0; i<ts->numberadjointmonitors; i++) { 1396 if (ts->adjointmonitordestroy[i]) { 1397 ierr = (*ts->adjointmonitordestroy[i])(&ts->adjointmonitorcontext[i]);CHKERRQ(ierr); 1398 } 1399 } 1400 ts->numberadjointmonitors = 0; 1401 PetscFunctionReturn(0); 1402 } 1403 1404 /*@C 1405 TSAdjointMonitorDefault - the default monitor of adjoint computations 1406 1407 Level: intermediate 1408 1409 .keywords: TS, set, monitor 1410 1411 .seealso: TSAdjointMonitorSet() 1412 @*/ 1413 PetscErrorCode TSAdjointMonitorDefault(TS ts,PetscInt step,PetscReal ptime,Vec v,PetscInt numcost,Vec *lambda,Vec *mu,PetscViewerAndFormat *vf) 1414 { 1415 PetscErrorCode ierr; 1416 PetscViewer viewer = vf->viewer; 1417 1418 PetscFunctionBegin; 1419 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,4); 1420 ierr = PetscViewerPushFormat(viewer,vf->format);CHKERRQ(ierr); 1421 ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)ts)->tablevel);CHKERRQ(ierr); 1422 ierr = PetscViewerASCIIPrintf(viewer,"%D TS dt %g time %g%s",step,(double)ts->time_step,(double)ptime,ts->steprollback ? " (r)\n" : "\n");CHKERRQ(ierr); 1423 ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)ts)->tablevel);CHKERRQ(ierr); 1424 ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 1425 PetscFunctionReturn(0); 1426 } 1427 1428 /*@C 1429 TSAdjointMonitorDrawSensi - Monitors progress of the adjoint TS solvers by calling 1430 VecView() for the sensitivities to initial states at each timestep 1431 1432 Collective on TS 1433 1434 Input Parameters: 1435 + ts - the TS context 1436 . step - current time-step 1437 . ptime - current time 1438 . u - current state 1439 . numcost - number of cost functions 1440 . lambda - sensitivities to initial conditions 1441 . mu - sensitivities to parameters 1442 - dummy - either a viewer or NULL 1443 1444 Level: intermediate 1445 1446 .keywords: TS, vector, adjoint, monitor, view 1447 1448 .seealso: TSAdjointMonitorSet(), TSAdjointMonitorDefault(), VecView() 1449 @*/ 1450 PetscErrorCode TSAdjointMonitorDrawSensi(TS ts,PetscInt step,PetscReal ptime,Vec u,PetscInt numcost,Vec *lambda,Vec *mu,void *dummy) 1451 { 1452 PetscErrorCode ierr; 1453 TSMonitorDrawCtx ictx = (TSMonitorDrawCtx)dummy; 1454 PetscDraw draw; 1455 PetscReal xl,yl,xr,yr,h; 1456 char time[32]; 1457 1458 PetscFunctionBegin; 1459 if (!(((ictx->howoften > 0) && (!(step % ictx->howoften))) || ((ictx->howoften == -1) && ts->reason))) PetscFunctionReturn(0); 1460 1461 ierr = VecView(lambda[0],ictx->viewer);CHKERRQ(ierr); 1462 ierr = PetscViewerDrawGetDraw(ictx->viewer,0,&draw);CHKERRQ(ierr); 1463 ierr = PetscSNPrintf(time,32,"Timestep %d Time %g",(int)step,(double)ptime);CHKERRQ(ierr); 1464 ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr); 1465 h = yl + .95*(yr - yl); 1466 ierr = PetscDrawStringCentered(draw,.5*(xl+xr),h,PETSC_DRAW_BLACK,time);CHKERRQ(ierr); 1467 ierr = PetscDrawFlush(draw);CHKERRQ(ierr); 1468 PetscFunctionReturn(0); 1469 } 1470 1471 /* 1472 TSAdjointSetFromOptions - Sets various TSAdjoint parameters from user options. 1473 1474 Collective on TSAdjoint 1475 1476 Input Parameter: 1477 . ts - the TS context 1478 1479 Options Database Keys: 1480 + -ts_adjoint_solve <yes,no> After solving the ODE/DAE solve the adjoint problem (requires -ts_save_trajectory) 1481 . -ts_adjoint_monitor - print information at each adjoint time step 1482 - -ts_adjoint_monitor_draw_sensi - monitor the sensitivity of the first cost function wrt initial conditions (lambda[0]) graphically 1483 1484 Level: developer 1485 1486 Notes: 1487 This is not normally called directly by users 1488 1489 .keywords: TS, trajectory, timestep, set, options, database 1490 1491 .seealso: TSSetSaveTrajectory(), TSTrajectorySetUp() 1492 */ 1493 PetscErrorCode TSAdjointSetFromOptions(PetscOptionItems *PetscOptionsObject,TS ts) 1494 { 1495 PetscBool tflg,opt; 1496 PetscErrorCode ierr; 1497 1498 PetscFunctionBegin; 1499 PetscValidHeaderSpecific(ts,TS_CLASSID,2); 1500 ierr = PetscOptionsHead(PetscOptionsObject,"TS Adjoint options");CHKERRQ(ierr); 1501 tflg = ts->adjoint_solve ? PETSC_TRUE : PETSC_FALSE; 1502 ierr = PetscOptionsBool("-ts_adjoint_solve","Solve the adjoint problem immediately after solving the forward problem","",tflg,&tflg,&opt);CHKERRQ(ierr); 1503 if (opt) { 1504 ierr = TSSetSaveTrajectory(ts);CHKERRQ(ierr); 1505 ts->adjoint_solve = tflg; 1506 } 1507 ierr = TSAdjointMonitorSetFromOptions(ts,"-ts_adjoint_monitor","Monitor adjoint timestep size","TSAdjointMonitorDefault",TSAdjointMonitorDefault,NULL);CHKERRQ(ierr); 1508 ierr = TSAdjointMonitorSetFromOptions(ts,"-ts_adjoint_monitor_sensi","Monitor sensitivity in the adjoint computation","TSAdjointMonitorSensi",TSAdjointMonitorSensi,NULL);CHKERRQ(ierr); 1509 opt = PETSC_FALSE; 1510 ierr = PetscOptionsName("-ts_adjoint_monitor_draw_sensi","Monitor adjoint sensitivities (lambda only) graphically","TSAdjointMonitorDrawSensi",&opt);CHKERRQ(ierr); 1511 if (opt) { 1512 TSMonitorDrawCtx ctx; 1513 PetscInt howoften = 1; 1514 1515 ierr = PetscOptionsInt("-ts_adjoint_monitor_draw_sensi","Monitor adjoint sensitivities (lambda only) graphically","TSAdjointMonitorDrawSensi",howoften,&howoften,NULL);CHKERRQ(ierr); 1516 ierr = TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts),0,0,PETSC_DECIDE,PETSC_DECIDE,300,300,howoften,&ctx);CHKERRQ(ierr); 1517 ierr = TSAdjointMonitorSet(ts,TSAdjointMonitorDrawSensi,ctx,(PetscErrorCode (*)(void**))TSMonitorDrawCtxDestroy);CHKERRQ(ierr); 1518 } 1519 PetscFunctionReturn(0); 1520 } 1521 1522 /*@ 1523 TSAdjointStep - Steps one time step backward in the adjoint run 1524 1525 Collective on TS 1526 1527 Input Parameter: 1528 . ts - the TS context obtained from TSCreate() 1529 1530 Level: intermediate 1531 1532 .keywords: TS, adjoint, step 1533 1534 .seealso: TSAdjointSetUp(), TSAdjointSolve() 1535 @*/ 1536 PetscErrorCode TSAdjointStep(TS ts) 1537 { 1538 DM dm; 1539 PetscErrorCode ierr; 1540 1541 PetscFunctionBegin; 1542 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1543 ierr = TSGetDM(ts,&dm);CHKERRQ(ierr); 1544 ierr = TSAdjointSetUp(ts);CHKERRQ(ierr); 1545 1546 ts->reason = TS_CONVERGED_ITERATING; 1547 ts->ptime_prev = ts->ptime; 1548 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); 1549 ierr = PetscLogEventBegin(TS_AdjointStep,ts,0,0,0);CHKERRQ(ierr); 1550 ierr = (*ts->ops->adjointstep)(ts);CHKERRQ(ierr); 1551 ierr = PetscLogEventEnd(TS_AdjointStep,ts,0,0,0);CHKERRQ(ierr); 1552 ts->adjoint_steps++; ts->steps--; 1553 1554 if (ts->reason < 0) { 1555 if (ts->errorifstepfailed) { 1556 if (ts->reason == TSADJOINT_DIVERGED_LINEAR_SOLVE) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_NOT_CONVERGED,"TSAdjointStep has failed due to %s",TSConvergedReasons[ts->reason]); 1557 else SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_NOT_CONVERGED,"TSAdjointStep has failed due to %s",TSConvergedReasons[ts->reason]); 1558 } 1559 } else if (!ts->reason) { 1560 if (ts->adjoint_steps >= ts->adjoint_max_steps) ts->reason = TS_CONVERGED_ITS; 1561 } 1562 PetscFunctionReturn(0); 1563 } 1564 1565 /*@ 1566 TSAdjointSolve - Solves the discrete ajoint problem for an ODE/DAE 1567 1568 Collective on TS 1569 1570 Input Parameter: 1571 . ts - the TS context obtained from TSCreate() 1572 1573 Options Database: 1574 . -ts_adjoint_view_solution <viewerinfo> - views the first gradient with respect to the initial values 1575 1576 Level: intermediate 1577 1578 Notes: 1579 This must be called after a call to TSSolve() that solves the forward problem 1580 1581 By default this will integrate back to the initial time, one can use TSAdjointSetSteps() to step back to a later time 1582 1583 .keywords: TS, timestep, solve 1584 1585 .seealso: TSCreate(), TSSetCostGradients(), TSSetSolution(), TSAdjointStep() 1586 @*/ 1587 PetscErrorCode TSAdjointSolve(TS ts) 1588 { 1589 PetscErrorCode ierr; 1590 1591 PetscFunctionBegin; 1592 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1593 ierr = TSAdjointSetUp(ts);CHKERRQ(ierr); 1594 1595 /* reset time step and iteration counters */ 1596 ts->adjoint_steps = 0; 1597 ts->ksp_its = 0; 1598 ts->snes_its = 0; 1599 ts->num_snes_failures = 0; 1600 ts->reject = 0; 1601 ts->reason = TS_CONVERGED_ITERATING; 1602 1603 if (!ts->adjoint_max_steps) ts->adjoint_max_steps = ts->steps; 1604 if (ts->adjoint_steps >= ts->adjoint_max_steps) ts->reason = TS_CONVERGED_ITS; 1605 1606 while (!ts->reason) { 1607 ierr = TSTrajectoryGet(ts->trajectory,ts,ts->steps,&ts->ptime);CHKERRQ(ierr); 1608 ierr = TSAdjointMonitor(ts,ts->steps,ts->ptime,ts->vec_sol,ts->numcost,ts->vecs_sensi,ts->vecs_sensip);CHKERRQ(ierr); 1609 ierr = TSAdjointEventHandler(ts);CHKERRQ(ierr); 1610 ierr = TSAdjointStep(ts);CHKERRQ(ierr); 1611 if ((ts->vec_costintegral || ts->quadraturets) && !ts->costintegralfwd) { 1612 ierr = TSAdjointCostIntegral(ts);CHKERRQ(ierr); 1613 } 1614 } 1615 ierr = TSTrajectoryGet(ts->trajectory,ts,ts->steps,&ts->ptime);CHKERRQ(ierr); 1616 ierr = TSAdjointMonitor(ts,ts->steps,ts->ptime,ts->vec_sol,ts->numcost,ts->vecs_sensi,ts->vecs_sensip);CHKERRQ(ierr); 1617 ts->solvetime = ts->ptime; 1618 ierr = TSTrajectoryViewFromOptions(ts->trajectory,NULL,"-ts_trajectory_view");CHKERRQ(ierr); 1619 ierr = VecViewFromOptions(ts->vecs_sensi[0],(PetscObject) ts, "-ts_adjoint_view_solution");CHKERRQ(ierr); 1620 ts->adjoint_max_steps = 0; 1621 PetscFunctionReturn(0); 1622 } 1623 1624 /*@C 1625 TSAdjointMonitor - Runs all user-provided adjoint monitor routines set using TSAdjointMonitorSet() 1626 1627 Collective on TS 1628 1629 Input Parameters: 1630 + ts - time stepping context obtained from TSCreate() 1631 . step - step number that has just completed 1632 . ptime - model time of the state 1633 . u - state at the current model time 1634 . numcost - number of cost functions (dimension of lambda or mu) 1635 . lambda - vectors containing the gradients of the cost functions with respect to the ODE/DAE solution variables 1636 - mu - vectors containing the gradients of the cost functions with respect to the problem parameters 1637 1638 Notes: 1639 TSAdjointMonitor() is typically used automatically within the time stepping implementations. 1640 Users would almost never call this routine directly. 1641 1642 Level: developer 1643 1644 .keywords: TS, timestep 1645 @*/ 1646 PetscErrorCode TSAdjointMonitor(TS ts,PetscInt step,PetscReal ptime,Vec u,PetscInt numcost,Vec *lambda, Vec *mu) 1647 { 1648 PetscErrorCode ierr; 1649 PetscInt i,n = ts->numberadjointmonitors; 1650 1651 PetscFunctionBegin; 1652 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1653 PetscValidHeaderSpecific(u,VEC_CLASSID,4); 1654 ierr = VecLockReadPush(u);CHKERRQ(ierr); 1655 for (i=0; i<n; i++) { 1656 ierr = (*ts->adjointmonitor[i])(ts,step,ptime,u,numcost,lambda,mu,ts->adjointmonitorcontext[i]);CHKERRQ(ierr); 1657 } 1658 ierr = VecLockReadPop(u);CHKERRQ(ierr); 1659 PetscFunctionReturn(0); 1660 } 1661 1662 /*@ 1663 TSAdjointCostIntegral - Evaluate the cost integral in the adjoint run. 1664 1665 Collective on TS 1666 1667 Input Arguments: 1668 . ts - time stepping context 1669 1670 Level: advanced 1671 1672 Notes: 1673 This function cannot be called until TSAdjointStep() has been completed. 1674 1675 .seealso: TSAdjointSolve(), TSAdjointStep 1676 @*/ 1677 PetscErrorCode TSAdjointCostIntegral(TS ts) 1678 { 1679 PetscErrorCode ierr; 1680 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1681 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); 1682 ierr = (*ts->ops->adjointintegral)(ts);CHKERRQ(ierr); 1683 PetscFunctionReturn(0); 1684 } 1685 1686 /* ------------------ Forward (tangent linear) sensitivity ------------------*/ 1687 1688 /*@ 1689 TSForwardSetUp - Sets up the internal data structures for the later use 1690 of forward sensitivity analysis 1691 1692 Collective on TS 1693 1694 Input Parameter: 1695 . ts - the TS context obtained from TSCreate() 1696 1697 Level: advanced 1698 1699 .keywords: TS, forward sensitivity, setup 1700 1701 .seealso: TSCreate(), TSDestroy(), TSSetUp() 1702 @*/ 1703 PetscErrorCode TSForwardSetUp(TS ts) 1704 { 1705 PetscErrorCode ierr; 1706 1707 PetscFunctionBegin; 1708 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1709 if (ts->forwardsetupcalled) PetscFunctionReturn(0); 1710 if (!ts->Jacp && ts->Jacprhs) ts->Jacp = ts->Jacprhs; 1711 1712 if (ts->ops->forwardsetup) { 1713 ierr = (*ts->ops->forwardsetup)(ts);CHKERRQ(ierr); 1714 } 1715 ierr = VecDuplicate(ts->vec_sol,&ts->vec_sensip_col);CHKERRQ(ierr); 1716 ts->forwardsetupcalled = PETSC_TRUE; 1717 PetscFunctionReturn(0); 1718 } 1719 1720 /*@ 1721 TSForwardReset - Reset the internal data structures used by forward sensitivity analysis 1722 1723 Collective on TS 1724 1725 Input Parameter: 1726 . ts - the TS context obtained from TSCreate() 1727 1728 Level: advanced 1729 1730 .keywords: TS, forward sensitivity, reset 1731 1732 .seealso: TSCreate(), TSDestroy(), TSForwardSetUp() 1733 @*/ 1734 PetscErrorCode TSForwardReset(TS ts) 1735 { 1736 TS quadts = ts->quadraturets; 1737 PetscErrorCode ierr; 1738 1739 PetscFunctionBegin; 1740 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1741 if (ts->ops->forwardreset) { 1742 ierr = (*ts->ops->forwardreset)(ts);CHKERRQ(ierr); 1743 } 1744 ierr = MatDestroy(&ts->mat_sensip);CHKERRQ(ierr); 1745 if (quadts) { 1746 ierr = MatDestroy(&quadts->mat_sensip);CHKERRQ(ierr); 1747 } 1748 ierr = VecDestroy(&ts->vec_sensip_col);CHKERRQ(ierr); 1749 ts->forward_solve = PETSC_FALSE; 1750 ts->forwardsetupcalled = PETSC_FALSE; 1751 PetscFunctionReturn(0); 1752 } 1753 1754 /*@ 1755 TSForwardSetIntegralGradients - Set the vectors holding forward sensitivities of the integral term. 1756 1757 Input Parameter: 1758 . ts- the TS context obtained from TSCreate() 1759 . numfwdint- number of integrals 1760 . vp = the vectors containing the gradients for each integral w.r.t. parameters 1761 1762 Level: deprecated 1763 1764 .keywords: TS, forward sensitivity 1765 1766 .seealso: TSForwardGetSensitivities(), TSForwardSetIntegralGradients(), TSForwardGetIntegralGradients(), TSForwardStep() 1767 @*/ 1768 PetscErrorCode TSForwardSetIntegralGradients(TS ts,PetscInt numfwdint,Vec *vp) 1769 { 1770 PetscFunctionBegin; 1771 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1772 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()"); 1773 if (!ts->numcost) ts->numcost = numfwdint; 1774 1775 ts->vecs_integral_sensip = vp; 1776 PetscFunctionReturn(0); 1777 } 1778 1779 /*@ 1780 TSForwardGetIntegralGradients - Returns the forward sensitivities ofthe integral term. 1781 1782 Input Parameter: 1783 . ts- the TS context obtained from TSCreate() 1784 1785 Output Parameter: 1786 . vp = the vectors containing the gradients for each integral w.r.t. parameters 1787 1788 Level: deprecated 1789 1790 .keywords: TS, forward sensitivity 1791 1792 .seealso: TSForwardSetSensitivities(), TSForwardSetIntegralGradients(), TSForwardGetIntegralGradients(), TSForwardStep() 1793 @*/ 1794 PetscErrorCode TSForwardGetIntegralGradients(TS ts,PetscInt *numfwdint,Vec **vp) 1795 { 1796 PetscFunctionBegin; 1797 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1798 PetscValidPointer(vp,3); 1799 if (numfwdint) *numfwdint = ts->numcost; 1800 if (vp) *vp = ts->vecs_integral_sensip; 1801 PetscFunctionReturn(0); 1802 } 1803 1804 /*@ 1805 TSForwardStep - Compute the forward sensitivity for one time step. 1806 1807 Collective on TS 1808 1809 Input Arguments: 1810 . ts - time stepping context 1811 1812 Level: advanced 1813 1814 Notes: 1815 This function cannot be called until TSStep() has been completed. 1816 1817 .keywords: TS, forward sensitivity 1818 1819 .seealso: TSForwardSetSensitivities(), TSForwardGetSensitivities(), TSForwardSetIntegralGradients(), TSForwardGetIntegralGradients(), TSForwardSetUp() 1820 @*/ 1821 PetscErrorCode TSForwardStep(TS ts) 1822 { 1823 PetscErrorCode ierr; 1824 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1825 if (!ts->ops->forwardstep) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"%s does not provide forward sensitivity analysis",((PetscObject)ts)->type_name); 1826 ierr = PetscLogEventBegin(TS_ForwardStep,ts,0,0,0);CHKERRQ(ierr); 1827 ierr = (*ts->ops->forwardstep)(ts);CHKERRQ(ierr); 1828 ierr = PetscLogEventEnd(TS_ForwardStep,ts,0,0,0);CHKERRQ(ierr); 1829 PetscFunctionReturn(0); 1830 } 1831 1832 /*@ 1833 TSForwardSetSensitivities - Sets the initial value of the trajectory sensitivities of solution w.r.t. the problem parameters and initial values. 1834 1835 Logically Collective on TS and Vec 1836 1837 Input Parameters: 1838 + ts - the TS context obtained from TSCreate() 1839 . nump - number of parameters 1840 - Smat - sensitivities with respect to the parameters, the number of entries in these vectors is the same as the number of parameters 1841 1842 Level: beginner 1843 1844 Notes: 1845 Forward sensitivity is also called 'trajectory sensitivity' in some fields such as power systems. 1846 This function turns on a flag to trigger TSSolve() to compute forward sensitivities automatically. 1847 You must call this function before TSSolve(). 1848 The entries in the sensitivity matrix must be correctly initialized with the values S = dy/dp|startingtime. 1849 1850 .keywords: TS, timestep, set, forward sensitivity, initial values 1851 1852 .seealso: TSForwardGetSensitivities(), TSForwardSetIntegralGradients(), TSForwardGetIntegralGradients(), TSForwardStep() 1853 @*/ 1854 PetscErrorCode TSForwardSetSensitivities(TS ts,PetscInt nump,Mat Smat) 1855 { 1856 PetscErrorCode ierr; 1857 1858 PetscFunctionBegin; 1859 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1860 PetscValidHeaderSpecific(Smat,MAT_CLASSID,3); 1861 ts->forward_solve = PETSC_TRUE; 1862 if (nump == PETSC_DEFAULT) { 1863 ierr = MatGetSize(Smat,NULL,&ts->num_parameters);CHKERRQ(ierr); 1864 } else ts->num_parameters = nump; 1865 ierr = PetscObjectReference((PetscObject)Smat);CHKERRQ(ierr); 1866 ierr = MatDestroy(&ts->mat_sensip);CHKERRQ(ierr); 1867 ts->mat_sensip = Smat; 1868 PetscFunctionReturn(0); 1869 } 1870 1871 /*@ 1872 TSForwardGetSensitivities - Returns the trajectory sensitivities 1873 1874 Not Collective, but Vec returned is parallel if TS is parallel 1875 1876 Output Parameter: 1877 + ts - the TS context obtained from TSCreate() 1878 . nump - number of parameters 1879 - Smat - sensitivities with respect to the parameters, the number of entries in these vectors is the same as the number of parameters 1880 1881 Level: intermediate 1882 1883 .keywords: TS, forward sensitivity 1884 1885 .seealso: TSForwardSetSensitivities(), TSForwardSetIntegralGradients(), TSForwardGetIntegralGradients(), TSForwardStep() 1886 @*/ 1887 PetscErrorCode TSForwardGetSensitivities(TS ts,PetscInt *nump,Mat *Smat) 1888 { 1889 PetscFunctionBegin; 1890 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1891 if (nump) *nump = ts->num_parameters; 1892 if (Smat) *Smat = ts->mat_sensip; 1893 PetscFunctionReturn(0); 1894 } 1895 1896 /*@ 1897 TSForwardCostIntegral - Evaluate the cost integral in the forward run. 1898 1899 Collective on TS 1900 1901 Input Arguments: 1902 . ts - time stepping context 1903 1904 Level: advanced 1905 1906 Notes: 1907 This function cannot be called until TSStep() has been completed. 1908 1909 .seealso: TSSolve(), TSAdjointCostIntegral() 1910 @*/ 1911 PetscErrorCode TSForwardCostIntegral(TS ts) 1912 { 1913 PetscErrorCode ierr; 1914 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1915 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); 1916 ierr = (*ts->ops->forwardintegral)(ts);CHKERRQ(ierr); 1917 PetscFunctionReturn(0); 1918 } 1919 1920 /*@ 1921 TSForwardSetInitialSensitivities - Set initial values for tangent linear sensitivities 1922 1923 Collective on TS and Mat 1924 1925 Input Parameter 1926 + ts - the TS context obtained from TSCreate() 1927 - didp - parametric sensitivities of the initial condition 1928 1929 Level: intermediate 1930 1931 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. 1932 1933 .seealso: TSForwardSetSensitivities() 1934 @*/ 1935 PetscErrorCode TSForwardSetInitialSensitivities(TS ts,Mat didp) 1936 { 1937 PetscErrorCode ierr; 1938 1939 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1940 PetscValidHeaderSpecific(didp,MAT_CLASSID,2); 1941 if (!ts->mat_sensip) { 1942 ierr = TSForwardSetSensitivities(ts,PETSC_DEFAULT,didp);CHKERRQ(ierr); 1943 } 1944 PetscFunctionReturn(0); 1945 } 1946 1947 /*@ 1948 TSForwardGetStages - Get the number of stages and the tangent linear sensitivities at the intermediate stages 1949 1950 Input Parameter: 1951 . ts - the TS context obtained from TSCreate() 1952 1953 Output Parameters: 1954 + ns - number of stages 1955 - S - tangent linear sensitivities at the intermediate stages 1956 1957 Level: advanced 1958 1959 .keywords: TS, second-order adjoint, forward sensitivity 1960 @*/ 1961 PetscErrorCode TSForwardGetStages(TS ts,PetscInt *ns,Mat **S) 1962 { 1963 PetscErrorCode ierr; 1964 1965 PetscFunctionBegin; 1966 PetscValidHeaderSpecific(ts, TS_CLASSID,1); 1967 1968 if (!ts->ops->getstages) *S=NULL; 1969 else { 1970 ierr = (*ts->ops->forwardgetstages)(ts,ns,S);CHKERRQ(ierr); 1971 } 1972 PetscFunctionReturn(0); 1973 } 1974 1975 /*@ 1976 TSCreateQuadratureTS - Create a sub-TS that evaluates integrals over time 1977 1978 Input Parameter: 1979 + ts - the TS context obtained from TSCreate() 1980 - fwd - flag indicating whether to evaluate cost integral in the forward run or the adjoint run 1981 1982 Output Parameters: 1983 . quadts - the child TS context 1984 1985 Level: intermediate 1986 1987 .keywords: TS, quadrature evaluation 1988 1989 .seealso: TSGetQuadratureTS() 1990 @*/ 1991 PetscErrorCode TSCreateQuadratureTS(TS ts,PetscBool fwd,TS *quadts) 1992 { 1993 char prefix[128]; 1994 PetscErrorCode ierr; 1995 1996 PetscFunctionBegin; 1997 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1998 PetscValidPointer(quadts,2); 1999 ierr = TSDestroy(&ts->quadraturets);CHKERRQ(ierr); 2000 ierr = TSCreate(PetscObjectComm((PetscObject)ts),&ts->quadraturets);CHKERRQ(ierr); 2001 ierr = PetscObjectIncrementTabLevel((PetscObject)ts->quadraturets,(PetscObject)ts,1);CHKERRQ(ierr); 2002 ierr = PetscLogObjectParent((PetscObject)ts,(PetscObject)ts->quadraturets);CHKERRQ(ierr); 2003 ierr = PetscSNPrintf(prefix,sizeof(prefix),"%squad_",((PetscObject)ts)->prefix ? ((PetscObject)ts)->prefix : "");CHKERRQ(ierr); 2004 ierr = TSSetOptionsPrefix(ts->quadraturets,prefix);CHKERRQ(ierr); 2005 *quadts = ts->quadraturets; 2006 2007 if (ts->numcost) { 2008 ierr = VecCreateSeq(PETSC_COMM_SELF,ts->numcost,&(*quadts)->vec_sol);CHKERRQ(ierr); 2009 } else { 2010 ierr = VecCreateSeq(PETSC_COMM_SELF,1,&(*quadts)->vec_sol);CHKERRQ(ierr); 2011 } 2012 ts->costintegralfwd = fwd; 2013 PetscFunctionReturn(0); 2014 } 2015 2016 /*@ 2017 TSGetQuadratureTS - Return the sub-TS that evaluates integrals over time 2018 2019 Input Parameter: 2020 . ts - the TS context obtained from TSCreate() 2021 2022 Output Parameters: 2023 + fwd - flag indicating whether to evaluate cost integral in the forward run or the adjoint run 2024 - quadts - the child TS context 2025 2026 Level: intermediate 2027 2028 .keywords: TS, quadrature evaluation 2029 2030 .seealso: TSCreateQuadratureTS() 2031 @*/ 2032 PetscErrorCode TSGetQuadratureTS(TS ts,PetscBool *fwd,TS *quadts) 2033 { 2034 PetscFunctionBegin; 2035 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 2036 if (fwd) *fwd = ts->costintegralfwd; 2037 if (quadts) *quadts = ts->quadraturets; 2038 PetscFunctionReturn(0); 2039 } 2040