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