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