1 #include <petsc/private/tsimpl.h> /*I "petscts.h" I*/ 2 #include <petscdraw.h> 3 4 PetscLogEvent TS_AdjointStep, TS_ForwardStep; 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: 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->Jacp);CHKERRQ(ierr); 47 ts->Jacp = Amat; 48 } 49 PetscFunctionReturn(0); 50 } 51 52 /*@C 53 TSComputeRHSJacobianP - Runs the user-defined JacobianP function. 54 55 Collective on TS 56 57 Input Parameters: 58 . ts - The TS context obtained from TSCreate() 59 60 Level: developer 61 62 .keywords: TS, sensitivity 63 .seealso: TSSetRHSJacobianP() 64 @*/ 65 PetscErrorCode TSComputeRHSJacobianP(TS ts,PetscReal t,Vec U,Mat Amat) 66 { 67 PetscErrorCode ierr; 68 69 PetscFunctionBegin; 70 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 71 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 72 PetscValidPointer(Amat,4); 73 74 PetscStackPush("TS user JacobianP function for sensitivity analysis"); 75 ierr = (*ts->rhsjacobianp)(ts,t,U,Amat,ts->rhsjacobianpctx);CHKERRQ(ierr); 76 PetscStackPop; 77 PetscFunctionReturn(0); 78 } 79 80 /*@C 81 TSSetCostIntegrand - Sets the routine for evaluating the integral term in one or more cost functions 82 83 Logically Collective on TS 84 85 Input Parameters: 86 + ts - the TS context obtained from TSCreate() 87 . numcost - number of gradients to be computed, this is the number of cost functions 88 . costintegral - vector that stores the integral values 89 . rf - routine for evaluating the integrand function 90 . drduf - function that computes the gradients of the r's with respect to u 91 . 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) 92 . fwd - flag indicating whether to evaluate cost integral in the forward run or the adjoint run 93 - ctx - [optional] user-defined context for private data for the function evaluation routine (may be NULL) 94 95 Calling sequence of rf: 96 $ PetscErrorCode rf(TS ts,PetscReal t,Vec U,Vec F,void *ctx); 97 98 Calling sequence of drduf: 99 $ PetscErroCode drduf(TS ts,PetscReal t,Vec U,Vec *dRdU,void *ctx); 100 101 Calling sequence of drdpf: 102 $ PetscErroCode drdpf(TS ts,PetscReal t,Vec U,Vec *dRdP,void *ctx); 103 104 Level: intermediate 105 106 Notes: 107 For optimization there is usually a single cost function (numcost = 1). For sensitivities there may be multiple cost functions 108 109 .keywords: TS, sensitivity analysis, timestep, set, quadrature, function 110 111 .seealso: TSSetRHSJacobianP(), TSGetCostGradients(), TSSetCostGradients() 112 @*/ 113 PetscErrorCode TSSetCostIntegrand(TS ts,PetscInt numcost,Vec costintegral,PetscErrorCode (*rf)(TS,PetscReal,Vec,Vec,void*), 114 PetscErrorCode (*drduf)(TS,PetscReal,Vec,Vec*,void*), 115 PetscErrorCode (*drdpf)(TS,PetscReal,Vec,Vec*,void*), 116 PetscBool fwd,void *ctx) 117 { 118 PetscErrorCode ierr; 119 120 PetscFunctionBegin; 121 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 122 if (costintegral) PetscValidHeaderSpecific(costintegral,VEC_CLASSID,3); 123 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()"); 124 if (!ts->numcost) ts->numcost=numcost; 125 126 if (costintegral) { 127 ierr = PetscObjectReference((PetscObject)costintegral);CHKERRQ(ierr); 128 ierr = VecDestroy(&ts->vec_costintegral);CHKERRQ(ierr); 129 ts->vec_costintegral = costintegral; 130 } else { 131 if (!ts->vec_costintegral) { /* Create a seq vec if user does not provide one */ 132 ierr = VecCreateSeq(PETSC_COMM_SELF,numcost,&ts->vec_costintegral);CHKERRQ(ierr); 133 } else { 134 ierr = VecSet(ts->vec_costintegral,0.0);CHKERRQ(ierr); 135 } 136 } 137 if (!ts->vec_costintegrand) { 138 ierr = VecDuplicate(ts->vec_costintegral,&ts->vec_costintegrand);CHKERRQ(ierr); 139 } else { 140 ierr = VecSet(ts->vec_costintegrand,0.0);CHKERRQ(ierr); 141 } 142 ts->costintegralfwd = fwd; /* Evaluate the cost integral in forward run if fwd is true */ 143 ts->costintegrand = rf; 144 ts->costintegrandctx = ctx; 145 ts->drdufunction = drduf; 146 ts->drdpfunction = drdpf; 147 PetscFunctionReturn(0); 148 } 149 150 /*@C 151 TSGetCostIntegral - Returns the values of the integral term in the cost functions. 152 It is valid to call the routine after a backward run. 153 154 Not Collective 155 156 Input Parameter: 157 . ts - the TS context obtained from TSCreate() 158 159 Output Parameter: 160 . v - the vector containing the integrals for each cost function 161 162 Level: intermediate 163 164 .seealso: TSSetCostIntegrand() 165 166 .keywords: TS, sensitivity analysis 167 @*/ 168 PetscErrorCode TSGetCostIntegral(TS ts,Vec *v) 169 { 170 PetscFunctionBegin; 171 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 172 PetscValidPointer(v,2); 173 *v = ts->vec_costintegral; 174 PetscFunctionReturn(0); 175 } 176 177 /*@C 178 TSComputeCostIntegrand - Evaluates the integral function in the cost functions. 179 180 Input Parameters: 181 + ts - the TS context 182 . t - current time 183 - U - state vector, i.e. current solution 184 185 Output Parameter: 186 . Q - vector of size numcost to hold the outputs 187 188 Note: 189 Most users should not need to explicitly call this routine, as it 190 is used internally within the sensitivity analysis context. 191 192 Level: developer 193 194 .keywords: TS, compute 195 196 .seealso: TSSetCostIntegrand() 197 @*/ 198 PetscErrorCode TSComputeCostIntegrand(TS ts,PetscReal t,Vec U,Vec Q) 199 { 200 PetscErrorCode ierr; 201 202 PetscFunctionBegin; 203 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 204 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 205 PetscValidHeaderSpecific(Q,VEC_CLASSID,4); 206 207 ierr = PetscLogEventBegin(TS_FunctionEval,ts,U,Q,0);CHKERRQ(ierr); 208 if (ts->costintegrand) { 209 PetscStackPush("TS user integrand in the cost function"); 210 ierr = (*ts->costintegrand)(ts,t,U,Q,ts->costintegrandctx);CHKERRQ(ierr); 211 PetscStackPop; 212 } else { 213 ierr = VecZeroEntries(Q);CHKERRQ(ierr); 214 } 215 216 ierr = PetscLogEventEnd(TS_FunctionEval,ts,U,Q,0);CHKERRQ(ierr); 217 PetscFunctionReturn(0); 218 } 219 220 /*@C 221 TSComputeDRDUFunction - Runs the user-defined DRDU function. 222 223 Collective on TS 224 225 Input Parameters: 226 + ts - the TS context obtained from TSCreate() 227 . t - current time 228 - U - stata vector 229 230 Output Parameters: 231 . DRDU - vector array to hold the outputs 232 233 Notes: 234 TSComputeDRDUFunction() is typically used for sensitivity implementation, 235 so most users would not generally call this routine themselves. 236 237 Level: developer 238 239 .keywords: TS, sensitivity 240 .seealso: TSSetCostIntegrand() 241 @*/ 242 PetscErrorCode TSComputeDRDUFunction(TS ts,PetscReal t,Vec U,Vec *DRDU) 243 { 244 PetscErrorCode ierr; 245 246 PetscFunctionBegin; 247 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 248 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 249 250 PetscStackPush("TS user DRDU function for sensitivity analysis"); 251 ierr = (*ts->drdufunction)(ts,t,U,DRDU,ts->costintegrandctx); CHKERRQ(ierr); 252 PetscStackPop; 253 PetscFunctionReturn(0); 254 } 255 256 /*@C 257 TSComputeDRDPFunction - Runs the user-defined DRDP function. 258 259 Collective on TS 260 261 Input Parameters: 262 + ts - the TS context obtained from TSCreate() 263 . t - current time 264 - U - stata vector 265 266 Output Parameters: 267 . DRDP - vector array to hold the outputs 268 269 Notes: 270 TSComputeDRDPFunction() is typically used for sensitivity implementation, 271 so most users would not generally call this routine themselves. 272 273 Level: developer 274 275 .keywords: TS, sensitivity 276 .seealso: TSSetCostIntegrand() 277 @*/ 278 PetscErrorCode TSComputeDRDPFunction(TS ts,PetscReal t,Vec U,Vec *DRDP) 279 { 280 PetscErrorCode ierr; 281 282 PetscFunctionBegin; 283 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 284 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 285 286 PetscStackPush("TS user DRDP function for sensitivity analysis"); 287 ierr = (*ts->drdpfunction)(ts,t,U,DRDP,ts->costintegrandctx); CHKERRQ(ierr); 288 PetscStackPop; 289 PetscFunctionReturn(0); 290 } 291 292 /*@C 293 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. 294 295 Logically Collective on TS 296 297 Input Parameters: 298 + ts - TS context obtained from TSCreate() 299 . ihp1 - an array of vectors storing the result of vector-Hessian-vector product for F_UU 300 . hessianproductfunc1 - vector-Hessian-vector product function for F_UU 301 . ihp2 - an array of vectors storing the result of vector-Hessian-vector product for F_UP 302 . hessianproductfunc2 - vector-Hessian-vector product function for F_UP 303 . ihp3 - an array of vectors storing the result of vector-Hessian-vector product for F_PU 304 . hessianproductfunc3 - vector-Hessian-vector product function for F_PU 305 . ihp4 - an array of vectors storing the result of vector-Hessian-vector product for F_PP 306 . hessianproductfunc4 - vector-Hessian-vector product function for F_PP 307 308 Calling sequence of ihessianproductfunc: 309 $ ihessianproductfunc (TS ts,PetscReal t,Vec U,Vec Vl,Vec Vr,Vec VHV,void *ctx); 310 + t - current timestep 311 . U - input vector (current ODE solution) 312 . Vl - input vector to be left-multiplied with the Hessian 313 . Vr - input vector to be right-multiplied with the Hessian 314 . VHV - output vector for vector-Hessian-vector product 315 - ctx - [optional] user-defined function context 316 317 Level: intermediate 318 319 Note: The first Hessian function and the working array are required. 320 321 .keywords: TS, sensitivity 322 323 .seealso: 324 @*/ 325 PetscErrorCode TSSetIHessianProduct(TS ts,Vec *ihp1,PetscErrorCode (*ihessianproductfunc1)(TS,PetscReal,Vec,Vec*,Vec,Vec*,void*), 326 Vec *ihp2,PetscErrorCode (*ihessianproductfunc2)(TS,PetscReal,Vec,Vec*,Vec,Vec*,void*), 327 Vec *ihp3,PetscErrorCode (*ihessianproductfunc3)(TS,PetscReal,Vec,Vec*,Vec,Vec*,void*), 328 Vec *ihp4,PetscErrorCode (*ihessianproductfunc4)(TS,PetscReal,Vec,Vec*,Vec,Vec*,void*), 329 void *ctx) 330 { 331 PetscFunctionBegin; 332 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 333 PetscValidPointer(ihp1,2); 334 335 ts->ihessianproductctx = ctx; 336 if (ihp1) ts->vecs_fuu = ihp1; 337 if (ihp2) ts->vecs_fup = ihp2; 338 if (ihp3) ts->vecs_fpu = ihp3; 339 if (ihp4) ts->vecs_fpp = ihp4; 340 ts->ihessianproduct_fuu = ihessianproductfunc1; 341 ts->ihessianproduct_fup = ihessianproductfunc2; 342 ts->ihessianproduct_fpu = ihessianproductfunc3; 343 ts->ihessianproduct_fpp = ihessianproductfunc4; 344 PetscFunctionReturn(0); 345 } 346 347 /*@C 348 TSComputeIHessianProductFunction1 - Runs the user-defined vector-Hessian-vector product function for Fuu. 349 350 Collective on TS 351 352 Input Parameters: 353 . ts - The TS context obtained from TSCreate() 354 355 Notes: 356 TSComputeIHessianProductFunction1() is typically used for sensitivity implementation, 357 so most users would not generally call this routine themselves. 358 359 Level: developer 360 361 .keywords: TS, sensitivity 362 363 .seealso: TSSetIHessianProduct() 364 @*/ 365 PetscErrorCode TSComputeIHessianProductFunction1(TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV) 366 { 367 PetscErrorCode ierr; 368 369 PetscFunctionBegin; 370 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 371 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 372 373 PetscStackPush("TS user IHessianProduct function 1 for sensitivity analysis"); 374 ierr = (*ts->ihessianproduct_fuu)(ts,t,U,Vl,Vr,VHV,ts->ihessianproductctx);CHKERRQ(ierr); 375 PetscStackPop; 376 PetscFunctionReturn(0); 377 } 378 379 /*@C 380 TSComputeIHessianProductFunction2 - Runs the user-defined vector-Hessian-vector product function for Fup. 381 382 Collective on TS 383 384 Input Parameters: 385 . ts - The TS context obtained from TSCreate() 386 387 Notes: 388 TSComputeIHessianProductFunction2() is typically used for sensitivity implementation, 389 so most users would not generally call this routine themselves. 390 391 Level: developer 392 393 .keywords: TS, sensitivity 394 395 .seealso: TSSetIHessianProduct() 396 @*/ 397 PetscErrorCode TSComputeIHessianProductFunction2(TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV) 398 { 399 PetscErrorCode ierr; 400 401 PetscFunctionBegin; 402 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 403 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 404 405 PetscStackPush("TS user IHessianProduct function 2 for sensitivity analysis"); 406 ierr = (*ts->ihessianproduct_fup)(ts,t,U,Vl,Vr,VHV,ts->ihessianproductctx);CHKERRQ(ierr); 407 PetscStackPop; 408 PetscFunctionReturn(0); 409 } 410 411 /*@C 412 TSComputeIHessianProductFunction3 - Runs the user-defined vector-Hessian-vector product function for Fpu. 413 414 Collective on TS 415 416 Input Parameters: 417 . ts - The TS context obtained from TSCreate() 418 419 Notes: 420 TSComputeIHessianProductFunction3() is typically used for sensitivity implementation, 421 so most users would not generally call this routine themselves. 422 423 Level: developer 424 425 .keywords: TS, sensitivity 426 427 .seealso: TSSetIHessianProduct() 428 @*/ 429 PetscErrorCode TSComputeIHessianProductFunction3(TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV) 430 { 431 PetscErrorCode ierr; 432 433 PetscFunctionBegin; 434 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 435 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 436 437 PetscStackPush("TS user IHessianProduct function 3 for sensitivity analysis"); 438 ierr = (*ts->ihessianproduct_fpu)(ts,t,U,Vl,Vr,VHV,ts->ihessianproductctx);CHKERRQ(ierr); 439 PetscStackPop; 440 PetscFunctionReturn(0); 441 } 442 443 /*@C 444 TSComputeIHessianProductFunction4 - Runs the user-defined vector-Hessian-vector product function for Fpp. 445 446 Collective on TS 447 448 Input Parameters: 449 . ts - The TS context obtained from TSCreate() 450 451 Notes: 452 TSComputeIHessianProductFunction4() is typically used for sensitivity implementation, 453 so most users would not generally call this routine themselves. 454 455 Level: developer 456 457 .keywords: TS, sensitivity 458 459 .seealso: TSSetIHessianProduct() 460 @*/ 461 PetscErrorCode TSComputeIHessianProductFunction4(TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV) 462 { 463 PetscErrorCode ierr; 464 465 PetscFunctionBegin; 466 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 467 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 468 469 PetscStackPush("TS user IHessianProduct function 3 for sensitivity analysis"); 470 ierr = (*ts->ihessianproduct_fpp)(ts,t,U,Vl,Vr,VHV,ts->ihessianproductctx);CHKERRQ(ierr); 471 PetscStackPop; 472 PetscFunctionReturn(0); 473 } 474 475 /* --------------------------- Adjoint sensitivity ---------------------------*/ 476 477 /*@ 478 TSSetCostGradients - Sets the initial value of the gradients of the cost function w.r.t. initial values and w.r.t. the problem parameters 479 for use by the TSAdjoint routines. 480 481 Logically Collective on TS and Vec 482 483 Input Parameters: 484 + ts - the TS context obtained from TSCreate() 485 . 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 486 - mu - gradients with respect to the parameters, the number of entries in these vectors is the same as the number of parameters 487 488 Level: beginner 489 490 Notes: 491 the entries in these vectors must be correctly initialized with the values lamda_i = df/dy|finaltime mu_i = df/dp|finaltime 492 493 After TSAdjointSolve() is called the lamba and the mu contain the computed sensitivities 494 495 .keywords: TS, timestep, set, sensitivity, initial values 496 497 .seealso TSGetCostGradients() 498 @*/ 499 PetscErrorCode TSSetCostGradients(TS ts,PetscInt numcost,Vec *lambda,Vec *mu) 500 { 501 PetscFunctionBegin; 502 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 503 PetscValidPointer(lambda,2); 504 ts->vecs_sensi = lambda; 505 ts->vecs_sensip = mu; 506 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"); 507 ts->numcost = numcost; 508 PetscFunctionReturn(0); 509 } 510 511 /*@ 512 TSGetCostGradients - Returns the gradients from the TSAdjointSolve() 513 514 Not Collective, but Vec returned is parallel if TS is parallel 515 516 Input Parameter: 517 . ts - the TS context obtained from TSCreate() 518 519 Output Parameter: 520 + lambda - vectors containing the gradients of the cost functions with respect to the ODE/DAE solution variables 521 - mu - vectors containing the gradients of the cost functions with respect to the problem parameters 522 523 Level: intermediate 524 525 .keywords: TS, timestep, get, sensitivity 526 527 .seealso: TSSetCostGradients() 528 @*/ 529 PetscErrorCode TSGetCostGradients(TS ts,PetscInt *numcost,Vec **lambda,Vec **mu) 530 { 531 PetscFunctionBegin; 532 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 533 if (numcost) *numcost = ts->numcost; 534 if (lambda) *lambda = ts->vecs_sensi; 535 if (mu) *mu = ts->vecs_sensip; 536 PetscFunctionReturn(0); 537 } 538 539 /*@ 540 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 541 for use by the TSAdjoint routines. 542 543 Logically Collective on TS and Vec 544 545 Input Parameters: 546 + ts - the TS context obtained from TSCreate() 547 . numcost - number of cost functions 548 . 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 549 . mu2 - Hessian-vector product with respect to the parameters, the number of entries in these vectors is the same as the number of parameters 550 - dir - the direction vector that are multiplied with the Hessian of the cost functions 551 552 Level: beginner 553 554 Notes: Hessian of the cost function is completely different from Hessian of the ODE/DAE system 555 556 For second-order adjoint, one needs to call this function and then TSAdjointInitializeForward() before TSSolve(). 557 558 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. 559 560 Passing NULL for lambda2 disables the second-order calculation. 561 .keywords: TS, sensitivity, second-order adjoint 562 563 .seealso: TSAdjointInitializeForward() 564 @*/ 565 PetscErrorCode TSSetCostHessianProducts(TS ts,PetscInt numcost,Vec *lambda2,Vec *mu2,Vec dir) 566 { 567 PetscFunctionBegin; 568 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 569 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"); 570 ts->numcost = numcost; 571 ts->vecs_sensi2 = lambda2; 572 ts->vecs_sensip2 = mu2; 573 ts->vec_dir = dir; 574 PetscFunctionReturn(0); 575 } 576 577 /*@ 578 TSGetCostHessianProducts - Returns the gradients from the TSAdjointSolve() 579 580 Not Collective, but Vec returned is parallel if TS is parallel 581 582 Input Parameter: 583 . ts - the TS context obtained from TSCreate() 584 585 Output Parameter: 586 + numcost - number of cost functions 587 . 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 588 . mu2 - Hessian-vector product with respect to the parameters, the number of entries in these vectors is the same as the number of parameters 589 - dir - the direction vector that are multiplied with the Hessian of the cost functions 590 591 Level: intermediate 592 593 .keywords: TS, sensitivity, second-order adjoint 594 595 .seealso: TSSetCostHessianProducts() 596 @*/ 597 PetscErrorCode TSGetCostHessianProducts(TS ts,PetscInt *numcost,Vec **lambda2,Vec **mu2, Vec *dir) 598 { 599 PetscFunctionBegin; 600 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 601 if (numcost) *numcost = ts->numcost; 602 if (lambda2) *lambda2 = ts->vecs_sensi2; 603 if (mu2) *mu2 = ts->vecs_sensip2; 604 if (dir) *dir = ts->vec_dir; 605 PetscFunctionReturn(0); 606 } 607 608 /*@ 609 TSAdjointInitializeForward - Trigger the tangent linear solver and initialize the forward sensitivities 610 611 Logically Collective on TS and Mat 612 613 Input Parameters: 614 + ts - the TS context obtained from TSCreate() 615 - didp - the derivative of initial values w.r.t. parameters 616 617 Level: intermediate 618 619 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. 620 621 .keywords: TS, sensitivity, second-order adjoint 622 623 .seealso: TSSetCostHessianProducts() 624 @*/ 625 PetscErrorCode TSAdjointInitializeForward(TS ts,Mat didp) 626 { 627 PetscErrorCode ierr; 628 629 PetscFunctionBegin; 630 ts->forward_solve = PETSC_TRUE; /* turn on tangent linear mode */ 631 if (!ts->vecs_sensi2) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Must call TSSetCostHessianProducts() first"); 632 if (ts->vecs_sensip2 && !didp) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"The fourth argument is not NULL, indicating parametric sensitivities are desired, so the dIdP matrix must be provided"); /* check conflicted settings */ 633 ierr = TSForwardSetInitialSensitivities(ts,didp);CHKERRQ(ierr); /* if didp is NULL, identity matrix is assumed */ 634 PetscFunctionReturn(0); 635 } 636 637 /*@ 638 TSAdjointSetUp - Sets up the internal data structures for the later use 639 of an adjoint solver 640 641 Collective on TS 642 643 Input Parameter: 644 . ts - the TS context obtained from TSCreate() 645 646 Level: advanced 647 648 .keywords: TS, timestep, setup 649 650 .seealso: TSCreate(), TSAdjointStep(), TSSetCostGradients() 651 @*/ 652 PetscErrorCode TSAdjointSetUp(TS ts) 653 { 654 PetscErrorCode ierr; 655 656 PetscFunctionBegin; 657 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 658 if (ts->adjointsetupcalled) PetscFunctionReturn(0); 659 if (!ts->vecs_sensi) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONGSTATE,"Must call TSSetCostGradients() first"); 660 if (ts->vecs_sensip && !ts->Jacp) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONGSTATE,"Must call TSAdjointSetRHSJacobian() first"); 661 662 if (ts->vec_costintegral) { /* if there is integral in the cost function */ 663 ierr = VecDuplicateVecs(ts->vecs_sensi[0],ts->numcost,&ts->vecs_drdu);CHKERRQ(ierr); 664 if (ts->vecs_sensip){ 665 ierr = VecDuplicateVecs(ts->vecs_sensip[0],ts->numcost,&ts->vecs_drdp);CHKERRQ(ierr); 666 } 667 } 668 669 if (ts->ops->adjointsetup) { 670 ierr = (*ts->ops->adjointsetup)(ts);CHKERRQ(ierr); 671 } 672 ts->adjointsetupcalled = PETSC_TRUE; 673 PetscFunctionReturn(0); 674 } 675 676 /*@ 677 TSAdjointReset - Resets a TSAdjoint context and removes any allocated Vecs and Mats. 678 679 Collective on TS 680 681 Input Parameter: 682 . ts - the TS context obtained from TSCreate() 683 684 Level: beginner 685 686 .keywords: TS, timestep, reset 687 688 .seealso: TSCreate(), TSAdjointSetup(), TSADestroy() 689 @*/ 690 PetscErrorCode TSAdjointReset(TS ts) 691 { 692 PetscErrorCode ierr; 693 694 PetscFunctionBegin; 695 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 696 if (ts->ops->adjointreset) { 697 ierr = (*ts->ops->adjointreset)(ts);CHKERRQ(ierr); 698 } 699 if (ts->vec_dir) { /* second-order adjoint */ 700 ierr = TSForwardReset(ts);CHKERRQ(ierr); 701 } 702 ts->vecs_sensi = NULL; 703 ts->vecs_sensip = NULL; 704 ts->vecs_sensi2 = NULL; 705 ts->vecs_sensip2 = NULL; 706 ts->vec_dir = NULL; 707 ts->adjointsetupcalled = PETSC_FALSE; 708 PetscFunctionReturn(0); 709 } 710 711 /*@ 712 TSAdjointSetSteps - Sets the number of steps the adjoint solver should take backward in time 713 714 Logically Collective on TS 715 716 Input Parameters: 717 + ts - the TS context obtained from TSCreate() 718 . steps - number of steps to use 719 720 Level: intermediate 721 722 Notes: 723 Normally one does not call this and TSAdjointSolve() integrates back to the original timestep. One can call this 724 so as to integrate back to less than the original timestep 725 726 .keywords: TS, timestep, set, maximum, iterations 727 728 .seealso: TSSetExactFinalTime() 729 @*/ 730 PetscErrorCode TSAdjointSetSteps(TS ts,PetscInt steps) 731 { 732 PetscFunctionBegin; 733 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 734 PetscValidLogicalCollectiveInt(ts,steps,2); 735 if (steps < 0) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Cannot step back a negative number of steps"); 736 if (steps > ts->steps) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Cannot step back more than the total number of forward steps"); 737 ts->adjoint_max_steps = steps; 738 PetscFunctionReturn(0); 739 } 740 741 /*@C 742 TSAdjointSetRHSJacobian - Deprecated, use TSSetRHSJacobianP() 743 744 Level: deprecated 745 746 @*/ 747 PetscErrorCode TSAdjointSetRHSJacobian(TS ts,Mat Amat,PetscErrorCode (*func)(TS,PetscReal,Vec,Mat,void*),void *ctx) 748 { 749 PetscErrorCode ierr; 750 751 PetscFunctionBegin; 752 PetscValidHeaderSpecific(ts, TS_CLASSID,1); 753 PetscValidHeaderSpecific(Amat,MAT_CLASSID,2); 754 755 ts->rhsjacobianp = func; 756 ts->rhsjacobianpctx = ctx; 757 if(Amat) { 758 ierr = PetscObjectReference((PetscObject)Amat);CHKERRQ(ierr); 759 ierr = MatDestroy(&ts->Jacp);CHKERRQ(ierr); 760 ts->Jacp = Amat; 761 } 762 PetscFunctionReturn(0); 763 } 764 765 /*@C 766 TSAdjointComputeRHSJacobian - Deprecated, use TSComputeRHSJacobianP() 767 768 Level: deprecated 769 770 @*/ 771 PetscErrorCode TSAdjointComputeRHSJacobian(TS ts,PetscReal t,Vec U,Mat Amat) 772 { 773 PetscErrorCode ierr; 774 775 PetscFunctionBegin; 776 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 777 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 778 PetscValidPointer(Amat,4); 779 780 PetscStackPush("TS user JacobianP function for sensitivity analysis"); 781 ierr = (*ts->rhsjacobianp)(ts,t,U,Amat,ts->rhsjacobianpctx); CHKERRQ(ierr); 782 PetscStackPop; 783 PetscFunctionReturn(0); 784 } 785 786 /*@ 787 TSAdjointComputeDRDYFunction - Deprecated, use TSComputeDRDUFunction() 788 789 Level: deprecated 790 791 @*/ 792 PetscErrorCode TSAdjointComputeDRDYFunction(TS ts,PetscReal t,Vec U,Vec *DRDU) 793 { 794 PetscErrorCode ierr; 795 796 PetscFunctionBegin; 797 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 798 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 799 800 PetscStackPush("TS user DRDY function for sensitivity analysis"); 801 ierr = (*ts->drdufunction)(ts,t,U,DRDU,ts->costintegrandctx); CHKERRQ(ierr); 802 PetscStackPop; 803 PetscFunctionReturn(0); 804 } 805 806 /*@ 807 TSAdjointComputeDRDPFunction - Deprecated, use TSComputeDRDPFunction() 808 809 Level: deprecated 810 811 @*/ 812 PetscErrorCode TSAdjointComputeDRDPFunction(TS ts,PetscReal t,Vec U,Vec *DRDP) 813 { 814 PetscErrorCode ierr; 815 816 PetscFunctionBegin; 817 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 818 PetscValidHeaderSpecific(U,VEC_CLASSID,3); 819 820 PetscStackPush("TS user DRDP function for sensitivity analysis"); 821 ierr = (*ts->drdpfunction)(ts,t,U,DRDP,ts->costintegrandctx); CHKERRQ(ierr); 822 PetscStackPop; 823 PetscFunctionReturn(0); 824 } 825 826 /*@C 827 TSAdjointMonitorSensi - monitors the first lambda sensitivity 828 829 Level: intermediate 830 831 .keywords: TS, set, monitor 832 833 .seealso: TSAdjointMonitorSet() 834 @*/ 835 PetscErrorCode TSAdjointMonitorSensi(TS ts,PetscInt step,PetscReal ptime,Vec v,PetscInt numcost,Vec *lambda,Vec *mu,PetscViewerAndFormat *vf) 836 { 837 PetscErrorCode ierr; 838 PetscViewer viewer = vf->viewer; 839 840 PetscFunctionBegin; 841 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,4); 842 ierr = PetscViewerPushFormat(viewer,vf->format);CHKERRQ(ierr); 843 ierr = VecView(lambda[0],viewer);CHKERRQ(ierr); 844 ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 845 PetscFunctionReturn(0); 846 } 847 848 /*@C 849 TSAdjointMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user 850 851 Collective on TS 852 853 Input Parameters: 854 + ts - TS object you wish to monitor 855 . name - the monitor type one is seeking 856 . help - message indicating what monitoring is done 857 . manual - manual page for the monitor 858 . monitor - the monitor function 859 - 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 860 861 Level: developer 862 863 .seealso: PetscOptionsGetViewer(), PetscOptionsGetReal(), PetscOptionsHasName(), PetscOptionsGetString(), 864 PetscOptionsGetIntArray(), PetscOptionsGetRealArray(), PetscOptionsBool() 865 PetscOptionsInt(), PetscOptionsString(), PetscOptionsReal(), PetscOptionsBool(), 866 PetscOptionsName(), PetscOptionsBegin(), PetscOptionsEnd(), PetscOptionsHead(), 867 PetscOptionsStringArray(),PetscOptionsRealArray(), PetscOptionsScalar(), 868 PetscOptionsBoolGroupBegin(), PetscOptionsBoolGroup(), PetscOptionsBoolGroupEnd(), 869 PetscOptionsFList(), PetscOptionsEList() 870 @*/ 871 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*)) 872 { 873 PetscErrorCode ierr; 874 PetscViewer viewer; 875 PetscViewerFormat format; 876 PetscBool flg; 877 878 PetscFunctionBegin; 879 ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject)ts),((PetscObject) ts)->options,((PetscObject)ts)->prefix,name,&viewer,&format,&flg);CHKERRQ(ierr); 880 if (flg) { 881 PetscViewerAndFormat *vf; 882 ierr = PetscViewerAndFormatCreate(viewer,format,&vf);CHKERRQ(ierr); 883 ierr = PetscObjectDereference((PetscObject)viewer);CHKERRQ(ierr); 884 if (monitorsetup) { 885 ierr = (*monitorsetup)(ts,vf);CHKERRQ(ierr); 886 } 887 ierr = TSAdjointMonitorSet(ts,(PetscErrorCode (*)(TS,PetscInt,PetscReal,Vec,PetscInt,Vec*,Vec*,void*))monitor,vf,(PetscErrorCode (*)(void**))PetscViewerAndFormatDestroy);CHKERRQ(ierr); 888 } 889 PetscFunctionReturn(0); 890 } 891 892 /*@C 893 TSAdjointMonitorSet - Sets an ADDITIONAL function that is to be used at every 894 timestep to display the iteration's progress. 895 896 Logically Collective on TS 897 898 Input Parameters: 899 + ts - the TS context obtained from TSCreate() 900 . adjointmonitor - monitoring routine 901 . adjointmctx - [optional] user-defined context for private data for the 902 monitor routine (use NULL if no context is desired) 903 - adjointmonitordestroy - [optional] routine that frees monitor context 904 (may be NULL) 905 906 Calling sequence of monitor: 907 $ int adjointmonitor(TS ts,PetscInt steps,PetscReal time,Vec u,PetscInt numcost,Vec *lambda, Vec *mu,void *adjointmctx) 908 909 + ts - the TS context 910 . 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 911 been interpolated to) 912 . time - current time 913 . u - current iterate 914 . numcost - number of cost functionos 915 . lambda - sensitivities to initial conditions 916 . mu - sensitivities to parameters 917 - adjointmctx - [optional] adjoint monitoring context 918 919 Notes: 920 This routine adds an additional monitor to the list of monitors that 921 already has been loaded. 922 923 Fortran Notes: 924 Only a single monitor function can be set for each TS object 925 926 Level: intermediate 927 928 .keywords: TS, timestep, set, adjoint, monitor 929 930 .seealso: TSAdjointMonitorCancel() 931 @*/ 932 PetscErrorCode TSAdjointMonitorSet(TS ts,PetscErrorCode (*adjointmonitor)(TS,PetscInt,PetscReal,Vec,PetscInt,Vec*,Vec*,void*),void *adjointmctx,PetscErrorCode (*adjointmdestroy)(void**)) 933 { 934 PetscErrorCode ierr; 935 PetscInt i; 936 PetscBool identical; 937 938 PetscFunctionBegin; 939 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 940 for (i=0; i<ts->numbermonitors;i++) { 941 ierr = PetscMonitorCompare((PetscErrorCode (*)(void))adjointmonitor,adjointmctx,adjointmdestroy,(PetscErrorCode (*)(void))ts->adjointmonitor[i],ts->adjointmonitorcontext[i],ts->adjointmonitordestroy[i],&identical);CHKERRQ(ierr); 942 if (identical) PetscFunctionReturn(0); 943 } 944 if (ts->numberadjointmonitors >= MAXTSMONITORS) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Too many adjoint monitors set"); 945 ts->adjointmonitor[ts->numberadjointmonitors] = adjointmonitor; 946 ts->adjointmonitordestroy[ts->numberadjointmonitors] = adjointmdestroy; 947 ts->adjointmonitorcontext[ts->numberadjointmonitors++] = (void*)adjointmctx; 948 PetscFunctionReturn(0); 949 } 950 951 /*@C 952 TSAdjointMonitorCancel - Clears all the adjoint monitors that have been set on a time-step object. 953 954 Logically Collective on TS 955 956 Input Parameters: 957 . ts - the TS context obtained from TSCreate() 958 959 Notes: 960 There is no way to remove a single, specific monitor. 961 962 Level: intermediate 963 964 .keywords: TS, timestep, set, adjoint, monitor 965 966 .seealso: TSAdjointMonitorSet() 967 @*/ 968 PetscErrorCode TSAdjointMonitorCancel(TS ts) 969 { 970 PetscErrorCode ierr; 971 PetscInt i; 972 973 PetscFunctionBegin; 974 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 975 for (i=0; i<ts->numberadjointmonitors; i++) { 976 if (ts->adjointmonitordestroy[i]) { 977 ierr = (*ts->adjointmonitordestroy[i])(&ts->adjointmonitorcontext[i]);CHKERRQ(ierr); 978 } 979 } 980 ts->numberadjointmonitors = 0; 981 PetscFunctionReturn(0); 982 } 983 984 /*@C 985 TSAdjointMonitorDefault - the default monitor of adjoint computations 986 987 Level: intermediate 988 989 .keywords: TS, set, monitor 990 991 .seealso: TSAdjointMonitorSet() 992 @*/ 993 PetscErrorCode TSAdjointMonitorDefault(TS ts,PetscInt step,PetscReal ptime,Vec v,PetscInt numcost,Vec *lambda,Vec *mu,PetscViewerAndFormat *vf) 994 { 995 PetscErrorCode ierr; 996 PetscViewer viewer = vf->viewer; 997 998 PetscFunctionBegin; 999 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,4); 1000 ierr = PetscViewerPushFormat(viewer,vf->format);CHKERRQ(ierr); 1001 ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)ts)->tablevel);CHKERRQ(ierr); 1002 ierr = PetscViewerASCIIPrintf(viewer,"%D TS dt %g time %g%s",step,(double)ts->time_step,(double)ptime,ts->steprollback ? " (r)\n" : "\n");CHKERRQ(ierr); 1003 ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)ts)->tablevel);CHKERRQ(ierr); 1004 ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 1005 PetscFunctionReturn(0); 1006 } 1007 1008 /*@C 1009 TSAdjointMonitorDrawSensi - Monitors progress of the adjoint TS solvers by calling 1010 VecView() for the sensitivities to initial states at each timestep 1011 1012 Collective on TS 1013 1014 Input Parameters: 1015 + ts - the TS context 1016 . step - current time-step 1017 . ptime - current time 1018 . u - current state 1019 . numcost - number of cost functions 1020 . lambda - sensitivities to initial conditions 1021 . mu - sensitivities to parameters 1022 - dummy - either a viewer or NULL 1023 1024 Level: intermediate 1025 1026 .keywords: TS, vector, adjoint, monitor, view 1027 1028 .seealso: TSAdjointMonitorSet(), TSAdjointMonitorDefault(), VecView() 1029 @*/ 1030 PetscErrorCode TSAdjointMonitorDrawSensi(TS ts,PetscInt step,PetscReal ptime,Vec u,PetscInt numcost,Vec *lambda,Vec *mu,void *dummy) 1031 { 1032 PetscErrorCode ierr; 1033 TSMonitorDrawCtx ictx = (TSMonitorDrawCtx)dummy; 1034 PetscDraw draw; 1035 PetscReal xl,yl,xr,yr,h; 1036 char time[32]; 1037 1038 PetscFunctionBegin; 1039 if (!(((ictx->howoften > 0) && (!(step % ictx->howoften))) || ((ictx->howoften == -1) && ts->reason))) PetscFunctionReturn(0); 1040 1041 ierr = VecView(lambda[0],ictx->viewer);CHKERRQ(ierr); 1042 ierr = PetscViewerDrawGetDraw(ictx->viewer,0,&draw);CHKERRQ(ierr); 1043 ierr = PetscSNPrintf(time,32,"Timestep %d Time %g",(int)step,(double)ptime);CHKERRQ(ierr); 1044 ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr); 1045 h = yl + .95*(yr - yl); 1046 ierr = PetscDrawStringCentered(draw,.5*(xl+xr),h,PETSC_DRAW_BLACK,time);CHKERRQ(ierr); 1047 ierr = PetscDrawFlush(draw);CHKERRQ(ierr); 1048 PetscFunctionReturn(0); 1049 } 1050 1051 /* 1052 TSAdjointSetFromOptions - Sets various TSAdjoint parameters from user options. 1053 1054 Collective on TSAdjoint 1055 1056 Input Parameter: 1057 . ts - the TS context 1058 1059 Options Database Keys: 1060 + -ts_adjoint_solve <yes,no> After solving the ODE/DAE solve the adjoint problem (requires -ts_save_trajectory) 1061 . -ts_adjoint_monitor - print information at each adjoint time step 1062 - -ts_adjoint_monitor_draw_sensi - monitor the sensitivity of the first cost function wrt initial conditions (lambda[0]) graphically 1063 1064 Level: developer 1065 1066 Notes: 1067 This is not normally called directly by users 1068 1069 .keywords: TS, trajectory, timestep, set, options, database 1070 1071 .seealso: TSSetSaveTrajectory(), TSTrajectorySetUp() 1072 */ 1073 PetscErrorCode TSAdjointSetFromOptions(PetscOptionItems *PetscOptionsObject,TS ts) 1074 { 1075 PetscBool tflg,opt; 1076 PetscErrorCode ierr; 1077 1078 PetscFunctionBegin; 1079 PetscValidHeaderSpecific(ts,TS_CLASSID,2); 1080 ierr = PetscOptionsHead(PetscOptionsObject,"TS Adjoint options");CHKERRQ(ierr); 1081 tflg = ts->adjoint_solve ? PETSC_TRUE : PETSC_FALSE; 1082 ierr = PetscOptionsBool("-ts_adjoint_solve","Solve the adjoint problem immediately after solving the forward problem","",tflg,&tflg,&opt);CHKERRQ(ierr); 1083 if (opt) { 1084 ierr = TSSetSaveTrajectory(ts);CHKERRQ(ierr); 1085 ts->adjoint_solve = tflg; 1086 } 1087 ierr = TSAdjointMonitorSetFromOptions(ts,"-ts_adjoint_monitor","Monitor adjoint timestep size","TSAdjointMonitorDefault",TSAdjointMonitorDefault,NULL);CHKERRQ(ierr); 1088 ierr = TSAdjointMonitorSetFromOptions(ts,"-ts_adjoint_monitor_sensi","Monitor sensitivity in the adjoint computation","TSAdjointMonitorSensi",TSAdjointMonitorSensi,NULL);CHKERRQ(ierr); 1089 opt = PETSC_FALSE; 1090 ierr = PetscOptionsName("-ts_adjoint_monitor_draw_sensi","Monitor adjoint sensitivities (lambda only) graphically","TSAdjointMonitorDrawSensi",&opt);CHKERRQ(ierr); 1091 if (opt) { 1092 TSMonitorDrawCtx ctx; 1093 PetscInt howoften = 1; 1094 1095 ierr = PetscOptionsInt("-ts_adjoint_monitor_draw_sensi","Monitor adjoint sensitivities (lambda only) graphically","TSAdjointMonitorDrawSensi",howoften,&howoften,NULL);CHKERRQ(ierr); 1096 ierr = TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts),0,0,PETSC_DECIDE,PETSC_DECIDE,300,300,howoften,&ctx);CHKERRQ(ierr); 1097 ierr = TSAdjointMonitorSet(ts,TSAdjointMonitorDrawSensi,ctx,(PetscErrorCode (*)(void**))TSMonitorDrawCtxDestroy);CHKERRQ(ierr); 1098 } 1099 PetscFunctionReturn(0); 1100 } 1101 1102 /*@ 1103 TSAdjointStep - Steps one time step backward in the adjoint run 1104 1105 Collective on TS 1106 1107 Input Parameter: 1108 . ts - the TS context obtained from TSCreate() 1109 1110 Level: intermediate 1111 1112 .keywords: TS, adjoint, step 1113 1114 .seealso: TSAdjointSetUp(), TSAdjointSolve() 1115 @*/ 1116 PetscErrorCode TSAdjointStep(TS ts) 1117 { 1118 DM dm; 1119 PetscErrorCode ierr; 1120 1121 PetscFunctionBegin; 1122 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1123 ierr = TSGetDM(ts,&dm);CHKERRQ(ierr); 1124 ierr = TSAdjointSetUp(ts);CHKERRQ(ierr); 1125 1126 ts->reason = TS_CONVERGED_ITERATING; 1127 ts->ptime_prev = ts->ptime; 1128 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); 1129 ierr = PetscLogEventBegin(TS_AdjointStep,ts,0,0,0);CHKERRQ(ierr); 1130 ierr = (*ts->ops->adjointstep)(ts);CHKERRQ(ierr); 1131 ierr = PetscLogEventEnd(TS_AdjointStep,ts,0,0,0);CHKERRQ(ierr); 1132 ts->adjoint_steps++; ts->steps--; 1133 1134 if (ts->reason < 0) { 1135 if (ts->errorifstepfailed) { 1136 if (ts->reason == TSADJOINT_DIVERGED_LINEAR_SOLVE) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_NOT_CONVERGED,"TSAdjointStep has failed due to %s",TSConvergedReasons[ts->reason]); 1137 else SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_NOT_CONVERGED,"TSAdjointStep has failed due to %s",TSConvergedReasons[ts->reason]); 1138 } 1139 } else if (!ts->reason) { 1140 if (ts->adjoint_steps >= ts->adjoint_max_steps) ts->reason = TS_CONVERGED_ITS; 1141 } 1142 PetscFunctionReturn(0); 1143 } 1144 1145 /*@ 1146 TSAdjointSolve - Solves the discrete ajoint problem for an ODE/DAE 1147 1148 Collective on TS 1149 1150 Input Parameter: 1151 . ts - the TS context obtained from TSCreate() 1152 1153 Options Database: 1154 . -ts_adjoint_view_solution <viewerinfo> - views the first gradient with respect to the initial values 1155 1156 Level: intermediate 1157 1158 Notes: 1159 This must be called after a call to TSSolve() that solves the forward problem 1160 1161 By default this will integrate back to the initial time, one can use TSAdjointSetSteps() to step back to a later time 1162 1163 .keywords: TS, timestep, solve 1164 1165 .seealso: TSCreate(), TSSetCostGradients(), TSSetSolution(), TSAdjointStep() 1166 @*/ 1167 PetscErrorCode TSAdjointSolve(TS ts) 1168 { 1169 PetscErrorCode ierr; 1170 1171 PetscFunctionBegin; 1172 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1173 ierr = TSAdjointSetUp(ts);CHKERRQ(ierr); 1174 1175 /* reset time step and iteration counters */ 1176 ts->adjoint_steps = 0; 1177 ts->ksp_its = 0; 1178 ts->snes_its = 0; 1179 ts->num_snes_failures = 0; 1180 ts->reject = 0; 1181 ts->reason = TS_CONVERGED_ITERATING; 1182 1183 if (!ts->adjoint_max_steps) ts->adjoint_max_steps = ts->steps; 1184 if (ts->adjoint_steps >= ts->adjoint_max_steps) ts->reason = TS_CONVERGED_ITS; 1185 1186 while (!ts->reason) { 1187 ierr = TSTrajectoryGet(ts->trajectory,ts,ts->steps,&ts->ptime);CHKERRQ(ierr); 1188 ierr = TSAdjointMonitor(ts,ts->steps,ts->ptime,ts->vec_sol,ts->numcost,ts->vecs_sensi,ts->vecs_sensip);CHKERRQ(ierr); 1189 ierr = TSAdjointEventHandler(ts);CHKERRQ(ierr); 1190 ierr = TSAdjointStep(ts);CHKERRQ(ierr); 1191 if (ts->vec_costintegral && !ts->costintegralfwd) { 1192 ierr = TSAdjointCostIntegral(ts);CHKERRQ(ierr); 1193 } 1194 } 1195 ierr = TSTrajectoryGet(ts->trajectory,ts,ts->steps,&ts->ptime);CHKERRQ(ierr); 1196 ierr = TSAdjointMonitor(ts,ts->steps,ts->ptime,ts->vec_sol,ts->numcost,ts->vecs_sensi,ts->vecs_sensip);CHKERRQ(ierr); 1197 ts->solvetime = ts->ptime; 1198 ierr = TSTrajectoryViewFromOptions(ts->trajectory,NULL,"-ts_trajectory_view");CHKERRQ(ierr); 1199 ierr = VecViewFromOptions(ts->vecs_sensi[0],(PetscObject) ts, "-ts_adjoint_view_solution");CHKERRQ(ierr); 1200 ts->adjoint_max_steps = 0; 1201 PetscFunctionReturn(0); 1202 } 1203 1204 /*@C 1205 TSAdjointMonitor - Runs all user-provided adjoint monitor routines set using TSAdjointMonitorSet() 1206 1207 Collective on TS 1208 1209 Input Parameters: 1210 + ts - time stepping context obtained from TSCreate() 1211 . step - step number that has just completed 1212 . ptime - model time of the state 1213 . u - state at the current model time 1214 . numcost - number of cost functions (dimension of lambda or mu) 1215 . lambda - vectors containing the gradients of the cost functions with respect to the ODE/DAE solution variables 1216 - mu - vectors containing the gradients of the cost functions with respect to the problem parameters 1217 1218 Notes: 1219 TSAdjointMonitor() is typically used automatically within the time stepping implementations. 1220 Users would almost never call this routine directly. 1221 1222 Level: developer 1223 1224 .keywords: TS, timestep 1225 @*/ 1226 PetscErrorCode TSAdjointMonitor(TS ts,PetscInt step,PetscReal ptime,Vec u,PetscInt numcost,Vec *lambda, Vec *mu) 1227 { 1228 PetscErrorCode ierr; 1229 PetscInt i,n = ts->numberadjointmonitors; 1230 1231 PetscFunctionBegin; 1232 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1233 PetscValidHeaderSpecific(u,VEC_CLASSID,4); 1234 ierr = VecLockReadPush(u);CHKERRQ(ierr); 1235 for (i=0; i<n; i++) { 1236 ierr = (*ts->adjointmonitor[i])(ts,step,ptime,u,numcost,lambda,mu,ts->adjointmonitorcontext[i]);CHKERRQ(ierr); 1237 } 1238 ierr = VecLockReadPop(u);CHKERRQ(ierr); 1239 PetscFunctionReturn(0); 1240 } 1241 1242 /*@ 1243 TSAdjointCostIntegral - Evaluate the cost integral in the adjoint run. 1244 1245 Collective on TS 1246 1247 Input Arguments: 1248 . ts - time stepping context 1249 1250 Level: advanced 1251 1252 Notes: 1253 This function cannot be called until TSAdjointStep() has been completed. 1254 1255 .seealso: TSAdjointSolve(), TSAdjointStep 1256 @*/ 1257 PetscErrorCode TSAdjointCostIntegral(TS ts) 1258 { 1259 PetscErrorCode ierr; 1260 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1261 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); 1262 ierr = (*ts->ops->adjointintegral)(ts);CHKERRQ(ierr); 1263 PetscFunctionReturn(0); 1264 } 1265 1266 /* ------------------ Forward (tangent linear) sensitivity ------------------*/ 1267 1268 /*@ 1269 TSForwardSetUp - Sets up the internal data structures for the later use 1270 of forward sensitivity analysis 1271 1272 Collective on TS 1273 1274 Input Parameter: 1275 . ts - the TS context obtained from TSCreate() 1276 1277 Level: advanced 1278 1279 .keywords: TS, forward sensitivity, setup 1280 1281 .seealso: TSCreate(), TSDestroy(), TSSetUp() 1282 @*/ 1283 PetscErrorCode TSForwardSetUp(TS ts) 1284 { 1285 PetscErrorCode ierr; 1286 1287 PetscFunctionBegin; 1288 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1289 if (ts->forwardsetupcalled) PetscFunctionReturn(0); 1290 if (ts->vec_costintegral && !ts->vecs_integral_sensip ) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call TSForwardSetIntegralGradients() before TSSetCostIntegrand()"); 1291 if (ts->vecs_integral_sensip) { 1292 ierr = VecDuplicateVecs(ts->vec_sol,ts->numcost,&ts->vecs_drdu);CHKERRQ(ierr); 1293 ierr = VecDuplicateVecs(ts->vecs_integral_sensip[0],ts->numcost,&ts->vecs_drdp);CHKERRQ(ierr); 1294 } 1295 1296 if (ts->ops->forwardsetup) { 1297 ierr = (*ts->ops->forwardsetup)(ts);CHKERRQ(ierr); 1298 } 1299 ts->forwardsetupcalled = PETSC_TRUE; 1300 PetscFunctionReturn(0); 1301 } 1302 1303 /*@ 1304 TSForwardReset - Reset the internal data structures used by forward sensitivity analysis 1305 1306 Collective on TS 1307 1308 Input Parameter: 1309 . ts - the TS context obtained from TSCreate() 1310 1311 Level: advanced 1312 1313 .keywords: TS, forward sensitivity, reset 1314 1315 .seealso: TSCreate(), TSDestroy(), TSForwardSetUp() 1316 @*/ 1317 PetscErrorCode TSForwardReset(TS ts) 1318 { 1319 PetscErrorCode ierr; 1320 1321 PetscFunctionBegin; 1322 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1323 if (ts->ops->forwardreset) { 1324 ierr = (*ts->ops->forwardreset)(ts);CHKERRQ(ierr); 1325 } 1326 ierr = MatDestroy(&ts->mat_sensip);CHKERRQ(ierr); 1327 ts->vecs_integral_sensip = NULL; 1328 ts->forward_solve = PETSC_FALSE; 1329 ts->forwardsetupcalled = PETSC_FALSE; 1330 PetscFunctionReturn(0); 1331 } 1332 1333 /*@ 1334 TSForwardSetIntegralGradients - Set the vectors holding forward sensitivities of the integral term. 1335 1336 Input Parameter: 1337 . ts- the TS context obtained from TSCreate() 1338 . numfwdint- number of integrals 1339 . vp = the vectors containing the gradients for each integral w.r.t. parameters 1340 1341 Level: intermediate 1342 1343 .keywords: TS, forward sensitivity 1344 1345 .seealso: TSForwardGetSensitivities(), TSForwardSetIntegralGradients(), TSForwardGetIntegralGradients(), TSForwardStep() 1346 @*/ 1347 PetscErrorCode TSForwardSetIntegralGradients(TS ts,PetscInt numfwdint,Vec *vp) 1348 { 1349 PetscFunctionBegin; 1350 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1351 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()"); 1352 if (!ts->numcost) ts->numcost = numfwdint; 1353 1354 ts->vecs_integral_sensip = vp; 1355 PetscFunctionReturn(0); 1356 } 1357 1358 /*@ 1359 TSForwardGetIntegralGradients - Returns the forward sensitivities ofthe integral term. 1360 1361 Input Parameter: 1362 . ts- the TS context obtained from TSCreate() 1363 1364 Output Parameter: 1365 . vp = the vectors containing the gradients for each integral w.r.t. parameters 1366 1367 Level: intermediate 1368 1369 .keywords: TS, forward sensitivity 1370 1371 .seealso: TSForwardSetSensitivities(), TSForwardSetIntegralGradients(), TSForwardGetIntegralGradients(), TSForwardStep() 1372 @*/ 1373 PetscErrorCode TSForwardGetIntegralGradients(TS ts,PetscInt *numfwdint,Vec **vp) 1374 { 1375 PetscFunctionBegin; 1376 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1377 PetscValidPointer(vp,3); 1378 if (numfwdint) *numfwdint = ts->numcost; 1379 if (vp) *vp = ts->vecs_integral_sensip; 1380 PetscFunctionReturn(0); 1381 } 1382 1383 /*@ 1384 TSForwardStep - Compute the forward sensitivity for one time step. 1385 1386 Collective on TS 1387 1388 Input Arguments: 1389 . ts - time stepping context 1390 1391 Level: advanced 1392 1393 Notes: 1394 This function cannot be called until TSStep() has been completed. 1395 1396 .keywords: TS, forward sensitivity 1397 1398 .seealso: TSForwardSetSensitivities(), TSForwardGetSensitivities(), TSForwardSetIntegralGradients(), TSForwardGetIntegralGradients(), TSForwardSetUp() 1399 @*/ 1400 PetscErrorCode TSForwardStep(TS ts) 1401 { 1402 PetscErrorCode ierr; 1403 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1404 if (!ts->ops->forwardstep) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"%s does not provide forward sensitivity analysis",((PetscObject)ts)->type_name); 1405 ierr = PetscLogEventBegin(TS_ForwardStep,ts,0,0,0);CHKERRQ(ierr); 1406 ierr = (*ts->ops->forwardstep)(ts);CHKERRQ(ierr); 1407 ierr = PetscLogEventEnd(TS_ForwardStep,ts,0,0,0);CHKERRQ(ierr); 1408 PetscFunctionReturn(0); 1409 } 1410 1411 /*@ 1412 TSForwardSetSensitivities - Sets the initial value of the trajectory sensitivities of solution w.r.t. the problem parameters and initial values. 1413 1414 Logically Collective on TS and Vec 1415 1416 Input Parameters: 1417 + ts - the TS context obtained from TSCreate() 1418 . nump - number of parameters 1419 - Smat - sensitivities with respect to the parameters, the number of entries in these vectors is the same as the number of parameters 1420 1421 Level: beginner 1422 1423 Notes: 1424 Forward sensitivity is also called 'trajectory sensitivity' in some fields such as power systems. 1425 This function turns on a flag to trigger TSSolve() to compute forward sensitivities automatically. 1426 You must call this function before TSSolve(). 1427 The entries in the sensitivity matrix must be correctly initialized with the values S = dy/dp|startingtime. 1428 1429 .keywords: TS, timestep, set, forward sensitivity, initial values 1430 1431 .seealso: TSForwardGetSensitivities(), TSForwardSetIntegralGradients(), TSForwardGetIntegralGradients(), TSForwardStep() 1432 @*/ 1433 PetscErrorCode TSForwardSetSensitivities(TS ts,PetscInt nump,Mat Smat) 1434 { 1435 PetscErrorCode ierr; 1436 1437 PetscFunctionBegin; 1438 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1439 PetscValidHeaderSpecific(Smat,MAT_CLASSID,3); 1440 ts->forward_solve = PETSC_TRUE; 1441 if (nump == PETSC_DEFAULT) { 1442 ierr = MatGetSize(Smat,NULL,&ts->num_parameters);CHKERRQ(ierr); 1443 } else ts->num_parameters = nump; 1444 ierr = PetscObjectReference((PetscObject)Smat);CHKERRQ(ierr); 1445 ierr = MatDestroy(&ts->mat_sensip);CHKERRQ(ierr); 1446 ts->mat_sensip = Smat; 1447 PetscFunctionReturn(0); 1448 } 1449 1450 /*@ 1451 TSForwardGetSensitivities - Returns the trajectory sensitivities 1452 1453 Not Collective, but Vec returned is parallel if TS is parallel 1454 1455 Output Parameter: 1456 + ts - the TS context obtained from TSCreate() 1457 . nump - number of parameters 1458 - Smat - sensitivities with respect to the parameters, the number of entries in these vectors is the same as the number of parameters 1459 1460 Level: intermediate 1461 1462 .keywords: TS, forward sensitivity 1463 1464 .seealso: TSForwardSetSensitivities(), TSForwardSetIntegralGradients(), TSForwardGetIntegralGradients(), TSForwardStep() 1465 @*/ 1466 PetscErrorCode TSForwardGetSensitivities(TS ts,PetscInt *nump,Mat *Smat) 1467 { 1468 PetscFunctionBegin; 1469 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1470 if (nump) *nump = ts->num_parameters; 1471 if (Smat) *Smat = ts->mat_sensip; 1472 PetscFunctionReturn(0); 1473 } 1474 1475 /*@ 1476 TSForwardCostIntegral - Evaluate the cost integral in the forward run. 1477 1478 Collective on TS 1479 1480 Input Arguments: 1481 . ts - time stepping context 1482 1483 Level: advanced 1484 1485 Notes: 1486 This function cannot be called until TSStep() has been completed. 1487 1488 .seealso: TSSolve(), TSAdjointCostIntegral() 1489 @*/ 1490 PetscErrorCode TSForwardCostIntegral(TS ts) 1491 { 1492 PetscErrorCode ierr; 1493 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1494 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); 1495 ierr = (*ts->ops->forwardintegral)(ts);CHKERRQ(ierr); 1496 PetscFunctionReturn(0); 1497 } 1498 1499 /*@ 1500 TSForwardSetInitialSensitivities - Set initial values for tangent linear sensitivities 1501 1502 Collective on TS and Mat 1503 1504 Input Parameter 1505 + ts - the TS context obtained from TSCreate() 1506 - didp - parametric sensitivities of the initial condition 1507 1508 Level: intermediate 1509 1510 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. 1511 1512 .seealso: TSForwardSetSensitivities() 1513 @*/ 1514 PetscErrorCode TSForwardSetInitialSensitivities(TS ts,Mat didp) 1515 { 1516 Vec sp; 1517 PetscInt lsize; 1518 PetscScalar *xarr; 1519 PetscErrorCode ierr; 1520 1521 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1522 if (ts->vec_dir) { /* indicates second-order adjoint caculation */ 1523 Mat A; 1524 ierr = TSForwardGetSensitivities(ts,NULL,&A);CHKERRQ(ierr); 1525 if (!A) { /* create a single-column dense matrix */ 1526 ierr = VecGetLocalSize(ts->vec_dir,&lsize);CHKERRQ(ierr); 1527 ierr = MatCreateDense(PETSC_COMM_WORLD,lsize,PETSC_DECIDE,PETSC_DECIDE,1,NULL,&A);CHKERRQ(ierr); 1528 } 1529 ierr = VecDuplicate(ts->vec_dir,&sp);CHKERRQ(ierr); 1530 ierr = MatDenseGetColumn(A,0,&xarr);CHKERRQ(ierr); 1531 ierr = VecPlaceArray(sp,xarr);CHKERRQ(ierr); 1532 if (didp) { 1533 ierr = MatMult(didp,ts->vec_dir,sp);CHKERRQ(ierr); 1534 } else { /* identity matrix assumed */ 1535 ierr = VecCopy(ts->vec_dir,sp);CHKERRQ(ierr); 1536 } 1537 ierr = VecResetArray(sp);CHKERRQ(ierr); 1538 ierr = MatDenseRestoreColumn(A,&xarr);CHKERRQ(ierr); 1539 ierr = VecDestroy(&sp);CHKERRQ(ierr); 1540 ierr = TSForwardSetSensitivities(ts,1,A);CHKERRQ(ierr); 1541 } else { 1542 PetscValidHeaderSpecific(didp,MAT_CLASSID,2); 1543 if (!ts->mat_sensip) { 1544 ierr = TSForwardSetSensitivities(ts,PETSC_DEFAULT,didp);CHKERRQ(ierr); 1545 } 1546 } 1547 PetscFunctionReturn(0); 1548 } 1549 1550 /*@ 1551 TSForwardGetStages - Get the number of stages and the tangent linear sensitivities at the intermediate stages 1552 1553 Input Parameter: 1554 . ts - the TS context obtained from TSCreate() 1555 1556 Output Parameters: 1557 + ns - nu 1558 - S - tangent linear sensitivities at the intermediate stages 1559 1560 Level: advanced 1561 1562 .keywords: TS, second-order adjoint, forward sensitivity 1563 @*/ 1564 PetscErrorCode TSForwardGetStages(TS ts,PetscInt *ns,Mat **S) 1565 { 1566 PetscErrorCode ierr; 1567 1568 PetscFunctionBegin; 1569 PetscValidHeaderSpecific(ts, TS_CLASSID,1); 1570 1571 if (!ts->ops->getstages) *S=NULL; 1572 else { 1573 ierr = (*ts->ops->forwardgetstages)(ts,ns,S);CHKERRQ(ierr); 1574 } 1575 PetscFunctionReturn(0); 1576 } 1577