1 /* 2 Code for timestepping with additive Runge-Kutta IMEX method or Diagonally Implicit Runge-Kutta methods. 3 4 Notes: 5 For ARK, the general system is written as 6 7 F(t,U,Udot) = G(t,U) 8 9 where F represents the stiff part of the physics and G represents the non-stiff part. 10 11 */ 12 #include <petsc/private/tsimpl.h> /*I "petscts.h" I*/ 13 #include <petscdm.h> 14 15 static TSARKIMEXType TSARKIMEXDefault = TSARKIMEX3; 16 static TSDIRKType TSDIRKDefault = TSDIRKES213SAL; 17 static PetscBool TSARKIMEXRegisterAllCalled; 18 static PetscBool TSARKIMEXPackageInitialized; 19 static PetscErrorCode TSExtrapolate_ARKIMEX(TS, PetscReal, Vec); 20 21 typedef struct _ARKTableau *ARKTableau; 22 struct _ARKTableau { 23 char *name; 24 PetscBool additive; /* If False, it is a DIRK method */ 25 PetscInt order; /* Classical approximation order of the method */ 26 PetscInt s; /* Number of stages */ 27 PetscBool stiffly_accurate; /* The implicit part is stiffly accurate */ 28 PetscBool FSAL_implicit; /* The implicit part is FSAL */ 29 PetscBool explicit_first_stage; /* The implicit part has an explicit first stage */ 30 PetscInt pinterp; /* Interpolation order */ 31 PetscReal *At, *bt, *ct; /* Stiff tableau */ 32 PetscReal *A, *b, *c; /* Non-stiff tableau */ 33 PetscReal *bembedt, *bembed; /* Embedded formula of order one less (order-1) */ 34 PetscReal *binterpt, *binterp; /* Dense output formula */ 35 PetscReal ccfl; /* Placeholder for CFL coefficient relative to forward Euler */ 36 }; 37 typedef struct _ARKTableauLink *ARKTableauLink; 38 struct _ARKTableauLink { 39 struct _ARKTableau tab; 40 ARKTableauLink next; 41 }; 42 static ARKTableauLink ARKTableauList; 43 44 typedef struct { 45 ARKTableau tableau; 46 Vec *Y; /* States computed during the step */ 47 Vec *YdotI; /* Time derivatives for the stiff part */ 48 Vec *YdotRHS; /* Function evaluations for the non-stiff part */ 49 Vec *Y_prev; /* States computed during the previous time step */ 50 Vec *YdotI_prev; /* Time derivatives for the stiff part for the previous time step*/ 51 Vec *YdotRHS_prev; /* Function evaluations for the non-stiff part for the previous time step*/ 52 Vec Ydot0; /* Holds the slope from the previous step in FSAL case */ 53 Vec Ydot; /* Work vector holding Ydot during residual evaluation */ 54 Vec Z; /* Ydot = shift(Y-Z) */ 55 PetscScalar *work; /* Scalar work */ 56 PetscReal scoeff; /* shift = scoeff/dt */ 57 PetscReal stage_time; 58 PetscBool imex; 59 PetscBool extrapolate; /* Extrapolate initial guess from previous time-step stage values */ 60 TSStepStatus status; 61 62 /* context for sensitivity analysis */ 63 Vec *VecsDeltaLam; /* Increment of the adjoint sensitivity w.r.t IC at stage */ 64 Vec *VecsSensiTemp; /* Vectors to be multiplied with Jacobian transpose */ 65 Vec *VecsSensiPTemp; /* Temporary Vectors to store JacobianP-transpose-vector product */ 66 } TS_ARKIMEX; 67 68 /*MC 69 TSARKIMEXARS122 - Second order ARK IMEX scheme, {cite}`ascher_1997` 70 71 This method has one explicit stage and one implicit stage. 72 73 Options Database Key: 74 . -ts_arkimex_type ars122 - set arkimex type to ars122 75 76 Level: advanced 77 78 .seealso: [](ch_ts), `TSARKIMEX`, `TSARKIMEXType`, `TSARKIMEXSetType()` 79 M*/ 80 81 /*MC 82 TSARKIMEXA2 - Second order ARK IMEX scheme with A-stable implicit part. 83 84 This method has an explicit stage and one implicit stage, and has an A-stable implicit scheme. This method was provided by Emil Constantinescu. 85 86 Options Database Key: 87 . -ts_arkimex_type a2 - set arkimex type to a2 88 89 Level: advanced 90 91 .seealso: [](ch_ts), `TSARKIMEX`, `TSARKIMEXType`, `TSARKIMEXSetType()` 92 M*/ 93 94 /*MC 95 TSARKIMEXL2 - Second order ARK IMEX scheme with L-stable implicit part, {cite}`pareschi_2005` 96 97 This method has two implicit stages, and L-stable implicit scheme. 98 99 Options Database Key: 100 . -ts_arkimex_type l2 - set arkimex type to l2 101 102 Level: advanced 103 104 .seealso: [](ch_ts), `TSARKIMEX`, `TSARKIMEXType`, `TSARKIMEXSetType()` 105 M*/ 106 107 /*MC 108 TSARKIMEX1BEE - First order backward Euler represented as an ARK IMEX scheme with extrapolation as error estimator. This is a 3-stage method. 109 110 This method is aimed at starting the integration of implicit DAEs when explicit first-stage ARK methods are used. 111 112 Options Database Key: 113 . -ts_arkimex_type 1bee - set arkimex type to 1bee 114 115 Level: advanced 116 117 .seealso: [](ch_ts), `TSARKIMEX`, `TSARKIMEXType`, `TSARKIMEXSetType()` 118 M*/ 119 120 /*MC 121 TSARKIMEX2C - Second order ARK IMEX scheme with L-stable implicit part. 122 123 This method has one explicit stage and two implicit stages. The implicit part is the same as in TSARKIMEX2D and TSARKIMEX2E, but the explicit part has a larger stability region on the negative real axis. This method was provided by Emil Constantinescu. 124 125 Options Database Key: 126 . -ts_arkimex_type 2c - set arkimex type to 2c 127 128 Level: advanced 129 130 .seealso: [](ch_ts), `TSARKIMEX`, `TSARKIMEXType`, `TSARKIMEXSetType()` 131 M*/ 132 133 /*MC 134 TSARKIMEX2D - Second order ARK IMEX scheme with L-stable implicit part. 135 136 This method has one explicit stage and two implicit stages. The stability function is independent of the explicit part in the infinity limit of the implicit component. This method was provided by Emil Constantinescu. 137 138 Options Database Key: 139 . -ts_arkimex_type 2d - set arkimex type to 2d 140 141 Level: advanced 142 143 .seealso: [](ch_ts), `TSARKIMEX`, `TSARKIMEXType`, `TSARKIMEXSetType()` 144 M*/ 145 146 /*MC 147 TSARKIMEX2E - Second order ARK IMEX scheme with L-stable implicit part. 148 149 This method has one explicit stage and two implicit stages. It is an optimal method developed by Emil Constantinescu. 150 151 Options Database Key: 152 . -ts_arkimex_type 2e - set arkimex type to 2e 153 154 Level: advanced 155 156 .seealso: [](ch_ts), `TSARKIMEX`, `TSARKIMEXType`, `TSARKIMEXSetType()` 157 M*/ 158 159 /*MC 160 TSARKIMEXPRSSP2 - Second order SSP ARK IMEX scheme, {cite}`pareschi_2005` 161 162 This method has three implicit stages. 163 164 This method is referred to as SSP2-(3,3,2) in <https://arxiv.org/abs/1110.4375> 165 166 Options Database Key: 167 . -ts_arkimex_type prssp2 - set arkimex type to prssp2 168 169 Level: advanced 170 171 .seealso: [](ch_ts), `TSARKIMEX`, `TSARKIMEXType`, `TSARKIMEXSetType()` 172 M*/ 173 174 /*MC 175 TSARKIMEX3 - Third order ARK IMEX scheme with L-stable implicit part, {cite}`kennedy_2003` 176 177 This method has one explicit stage and three implicit stages. 178 179 Options Database Key: 180 . -ts_arkimex_type 3 - set arkimex type to 3 181 182 Level: advanced 183 184 .seealso: [](ch_ts), `TSARKIMEX`, `TSARKIMEXType`, `TSARKIMEXSetType()` 185 M*/ 186 187 /*MC 188 TSARKIMEXARS443 - Third order ARK IMEX scheme, {cite}`ascher_1997` 189 190 This method has one explicit stage and four implicit stages. 191 192 Options Database Key: 193 . -ts_arkimex_type ars443 - set arkimex type to ars443 194 195 Level: advanced 196 197 Notes: 198 This method is referred to as ARS(4,4,3) in <https://arxiv.org/abs/1110.4375> 199 200 .seealso: [](ch_ts), `TSARKIMEX`, `TSARKIMEXType`, `TSARKIMEXSetType()` 201 M*/ 202 203 /*MC 204 TSARKIMEXBPR3 - Third order ARK IMEX scheme. Referred to as ARK3 in <https://arxiv.org/abs/1110.4375> 205 206 This method has one explicit stage and four implicit stages. 207 208 Options Database Key: 209 . -ts_arkimex_type bpr3 - set arkimex type to bpr3 210 211 Level: advanced 212 213 .seealso: [](ch_ts), `TSARKIMEX`, `TSARKIMEXType`, `TSARKIMEXSetType()` 214 M*/ 215 216 /*MC 217 TSARKIMEX4 - Fourth order ARK IMEX scheme with L-stable implicit part, {cite}`kennedy_2003`. 218 219 This method has one explicit stage and four implicit stages. 220 221 Options Database Key: 222 . -ts_arkimex_type 4 - set arkimex type to4 223 224 Level: advanced 225 226 .seealso: [](ch_ts), `TSARKIMEX`, `TSARKIMEXType`, `TSARKIMEXSetType()` 227 M*/ 228 229 /*MC 230 TSARKIMEX5 - Fifth order ARK IMEX scheme with L-stable implicit part, {cite}`kennedy_2003`. 231 232 This method has one explicit stage and five implicit stages. 233 234 Options Database Key: 235 . -ts_arkimex_type 5 - set arkimex type to 5 236 237 Level: advanced 238 239 .seealso: [](ch_ts), `TSARKIMEX`, `TSARKIMEXType`, `TSARKIMEXSetType()` 240 M*/ 241 242 /*MC 243 TSDIRKS212 - Second order DIRK scheme. 244 245 This method has two implicit stages with an embedded method of other 1. 246 See `TSDIRK` for additional details. 247 248 Options Database Key: 249 . -ts_dirk_type s212 - select this method. 250 251 Level: advanced 252 253 Note: 254 This is the default DIRK scheme in SUNDIALS. 255 256 .seealso: [](ch_ts), `TSDIRK`, `TSDIRKType`, `TSDIRKSetType()` 257 M*/ 258 259 /*MC 260 TSDIRKES122SAL - First order DIRK scheme <https://arxiv.org/abs/1803.01613> 261 262 Uses backward Euler as advancing method and trapezoidal rule as embedded method. See `TSDIRK` for additional details. 263 264 Options Database Key: 265 . -ts_dirk_type es122sal - select this method. 266 267 Level: advanced 268 269 .seealso: [](ch_ts), `TSDIRK`, `TSDIRKType`, `TSDIRKSetType()` 270 M*/ 271 272 /*MC 273 TSDIRKES213SAL - Second order DIRK scheme {cite}`kennedy2019diagonally`. Also known as TR-BDF2, see{cite}`hosea1996analysis` 274 275 See `TSDIRK` for additional details. 276 277 Options Database Key: 278 . -ts_dirk_type es213sal - select this method. 279 280 Level: advanced 281 282 Note: 283 This is the default DIRK scheme used in PETSc. 284 285 .seealso: [](ch_ts), `TSDIRK`, `TSDIRKType`, `TSDIRKSetType()` 286 M*/ 287 288 /*MC 289 TSDIRKES324SAL - Third order DIRK scheme, {cite}`kennedy2019diagonally` 290 291 See `TSDIRK` for additional details. 292 293 Options Database Key: 294 . -ts_dirk_type es324sal - select this method. 295 296 Level: advanced 297 298 .seealso: [](ch_ts), `TSDIRK`, `TSDIRKType`, `TSDIRKSetType()` 299 M*/ 300 301 /*MC 302 TSDIRKES325SAL - Third order DIRK scheme {cite}`kennedy2019diagonally`. 303 304 See `TSDIRK` for additional details. 305 306 Options Database Key: 307 . -ts_dirk_type es325sal - select this method. 308 309 Level: advanced 310 311 .seealso: [](ch_ts), `TSDIRK`, `TSDIRKType`, `TSDIRKSetType()` 312 M*/ 313 314 /*MC 315 TSDIRK657A - Sixth order DIRK scheme <https://github.com/yousefalamri55/High_Order_DIRK_Methods_Coeffs> 316 317 See `TSDIRK` for additional details. 318 319 Options Database Key: 320 . -ts_dirk_type 657a - select this method. 321 322 Level: advanced 323 324 .seealso: [](ch_ts), `TSDIRK`, `TSDIRKType`, `TSDIRKSetType()` 325 M*/ 326 327 /*MC 328 TSDIRKES648SA - Sixth order DIRK scheme <https://github.com/yousefalamri55/High_Order_DIRK_Methods_Coeffs> 329 330 See `TSDIRK` for additional details. 331 332 Options Database Key: 333 . -ts_dirk_type es648sa - select this method. 334 335 Level: advanced 336 337 .seealso: [](ch_ts), `TSDIRK`, `TSDIRKType`, `TSDIRKSetType()` 338 M*/ 339 340 /*MC 341 TSDIRK658A - Sixth order DIRK scheme <https://github.com/yousefalamri55/High_Order_DIRK_Methods_Coeffs> 342 343 See `TSDIRK` for additional details. 344 345 Options Database Key: 346 . -ts_dirk_type 658a - select this method. 347 348 Level: advanced 349 350 .seealso: [](ch_ts), `TSDIRK`, `TSDIRKType`, `TSDIRKSetType()` 351 M*/ 352 353 /*MC 354 TSDIRKS659A - Sixth order DIRK scheme <https://github.com/yousefalamri55/High_Order_DIRK_Methods_Coeffs> 355 356 See `TSDIRK` for additional details. 357 358 Options Database Key: 359 . -ts_dirk_type s659a - select this method. 360 361 Level: advanced 362 363 .seealso: [](ch_ts), `TSDIRK`, `TSDIRKType`, `TSDIRKSetType()` 364 M*/ 365 366 /*MC 367 TSDIRK7510SAL - Seventh order DIRK scheme <https://github.com/yousefalamri55/High_Order_DIRK_Methods_Coeffs> 368 369 See `TSDIRK` for additional details. 370 371 Options Database Key: 372 . -ts_dirk_type 7510sal - select this method. 373 374 Level: advanced 375 376 .seealso: [](ch_ts), `TSDIRK`, `TSDIRKType`, `TSDIRKSetType()` 377 M*/ 378 379 /*MC 380 TSDIRKES7510SA - Seventh order DIRK scheme <https://github.com/yousefalamri55/High_Order_DIRK_Methods_Coeffs> 381 382 See `TSDIRK` for additional details. 383 384 Options Database Key: 385 . -ts_dirk_type es7510sa - select this method. 386 387 Level: advanced 388 389 .seealso: [](ch_ts), `TSDIRK`, `TSDIRKType`, `TSDIRKSetType()` 390 M*/ 391 392 /*MC 393 TSDIRK759A - Seventh order DIRK scheme <https://github.com/yousefalamri55/High_Order_DIRK_Methods_Coeffs> 394 395 See `TSDIRK` for additional details. 396 397 Options Database Key: 398 . -ts_dirk_type 759a - select this method. 399 400 Level: advanced 401 402 .seealso: [](ch_ts), `TSDIRK`, `TSDIRKType`, `TSDIRKSetType()` 403 M*/ 404 405 /*MC 406 TSDIRKS7511SAL - Seventh order DIRK scheme <https://github.com/yousefalamri55/High_Order_DIRK_Methods_Coeffs> 407 408 See `TSDIRK` for additional details. 409 410 Options Database Key: 411 . -ts_dirk_type s7511sal - select this method. 412 413 Level: advanced 414 415 .seealso: [](ch_ts), `TSDIRK`, `TSDIRKType`, `TSDIRKSetType()` 416 M*/ 417 418 /*MC 419 TSDIRK8614A - Eighth order DIRK scheme <https://github.com/yousefalamri55/High_Order_DIRK_Methods_Coeffs> 420 421 See `TSDIRK` for additional details. 422 423 Options Database Key: 424 . -ts_dirk_type 8614a - select this method. 425 426 Level: advanced 427 428 .seealso: [](ch_ts), `TSDIRK`, `TSDIRKType`, `TSDIRKSetType()` 429 M*/ 430 431 /*MC 432 TSDIRK8616SAL - Eighth order DIRK scheme <https://github.com/yousefalamri55/High_Order_DIRK_Methods_Coeffs> 433 434 See `TSDIRK` for additional details. 435 436 Options Database Key: 437 . -ts_dirk_type 8616sal - select this method. 438 439 Level: advanced 440 441 .seealso: [](ch_ts), `TSDIRK`, `TSDIRKType`, `TSDIRKSetType()` 442 M*/ 443 444 /*MC 445 TSDIRKES8516SAL - Eighth order DIRK scheme <https://github.com/yousefalamri55/High_Order_DIRK_Methods_Coeffs> 446 447 See `TSDIRK` for additional details. 448 449 Options Database Key: 450 . -ts_dirk_type es8516sal - select this method. 451 452 Level: advanced 453 454 .seealso: [](ch_ts), `TSDIRK`, `TSDIRKType`, `TSDIRKSetType()` 455 M*/ 456 457 static PetscErrorCode TSHasRHSFunction(TS ts, PetscBool *has) 458 { 459 TSRHSFunctionFn *func; 460 461 PetscFunctionBegin; 462 *has = PETSC_FALSE; 463 PetscCall(DMTSGetRHSFunction(ts->dm, &func, NULL)); 464 if (func) *has = PETSC_TRUE; 465 PetscFunctionReturn(PETSC_SUCCESS); 466 } 467 468 /*@C 469 TSARKIMEXRegisterAll - Registers all of the additive Runge-Kutta implicit-explicit methods in `TSARKIMEX` 470 471 Not Collective, but should be called by all processes which will need the schemes to be registered 472 473 Level: advanced 474 475 .seealso: [](ch_ts), `TS`, `TSARKIMEX`, `TSARKIMEXRegisterDestroy()` 476 @*/ 477 PetscErrorCode TSARKIMEXRegisterAll(void) 478 { 479 PetscFunctionBegin; 480 if (TSARKIMEXRegisterAllCalled) PetscFunctionReturn(PETSC_SUCCESS); 481 TSARKIMEXRegisterAllCalled = PETSC_TRUE; 482 483 #define RC PetscRealConstant 484 #define s2 RC(1.414213562373095048802) /* PetscSqrtReal((PetscReal)2.0) */ 485 #define us2 RC(0.2928932188134524755992) /* 1.0-1.0/PetscSqrtReal((PetscReal)2.0); */ 486 487 /* Diagonally implicit methods */ 488 { 489 /* DIRK212, default of SUNDIALS */ 490 const PetscReal A[2][2] = { 491 {RC(1.0), RC(0.0)}, 492 {RC(-1.0), RC(1.0)} 493 }; 494 const PetscReal b[2] = {RC(0.5), RC(0.5)}; 495 const PetscReal bembed[2] = {RC(1.0), RC(0.0)}; 496 PetscCall(TSDIRKRegister(TSDIRKS212, 2, 2, &A[0][0], b, NULL, bembed, 1, b)); 497 } 498 499 { 500 /* ESDIRK12 from https://arxiv.org/pdf/1803.01613.pdf */ 501 const PetscReal A[2][2] = { 502 {RC(0.0), RC(0.0)}, 503 {RC(0.0), RC(1.0)} 504 }; 505 const PetscReal b[2] = {RC(0.0), RC(1.0)}; 506 const PetscReal bembed[2] = {RC(0.5), RC(0.5)}; 507 PetscCall(TSDIRKRegister(TSDIRKES122SAL, 1, 2, &A[0][0], b, NULL, bembed, 1, b)); 508 } 509 510 { 511 /* ESDIRK213L[2]SA from KC16. 512 TR-BDF2 from Hosea and Shampine 513 ESDIRK23 in https://arxiv.org/pdf/1803.01613.pdf */ 514 const PetscReal A[3][3] = { 515 {RC(0.0), RC(0.0), RC(0.0)}, 516 {us2, us2, RC(0.0)}, 517 {s2 / RC(4.0), s2 / RC(4.0), us2 }, 518 }; 519 const PetscReal b[3] = {s2 / RC(4.0), s2 / RC(4.0), us2}; 520 const PetscReal bembed[3] = {(RC(1.0) - s2 / RC(4.0)) / RC(3.0), (RC(3.0) * s2 / RC(4.0) + RC(1.0)) / RC(3.0), us2 / RC(3.0)}; 521 PetscCall(TSDIRKRegister(TSDIRKES213SAL, 2, 3, &A[0][0], b, NULL, bembed, 1, b)); 522 } 523 524 { 525 #define g RC(0.43586652150845899941601945) 526 #define g2 PetscSqr(g) 527 #define g3 g *g2 528 #define g4 PetscSqr(g2) 529 #define g5 g *g4 530 #define c3 RC(1.0) 531 #define a32 c3 *(c3 - RC(2.0) * g) / (RC(4.0) * g) 532 #define b2 (-RC(2.0) + RC(3.0) * c3 + RC(6.0) * g * (RC(1.0) - c3)) / (RC(12.0) * g * (c3 - RC(2.0) * g)) 533 #define b3 (RC(1.0) - RC(6.0) * g + RC(6.0) * g2) / (RC(3.0) * c3 * (c3 - RC(2.0) * g)) 534 #if 0 535 /* This is for c3 = 3/5 */ 536 #define bh2 \ 537 c3 * (-RC(1.0) + RC(6.0) * g - RC(23.0) * g3 + RC(12.0) * g4 - RC(6.0) * g5) / (RC(4.0) * (RC(2.0) * g - c3) * (RC(1.0) - RC(6.0) * g + RC(6.0) * g2)) + (RC(3.0) - RC(27.0) * g + RC(68.0) * g2 - RC(55.0) * g3 + RC(21.0) * g4 - RC(6.0) * g5) / (RC(2.0) * (RC(2.0) * g - c3) * (RC(1.0) - RC(6.0) * g + RC(6.0) * g2)) 538 #define bh3 -g * (-RC(2.0) + RC(21.0) * g - RC(68.0) * g2 + RC(79.0) * g3 - RC(33.0) * g4 + RC(12.0) * g5) / (RC(2.0) * (RC(2.0) * g - c3) * (RC(1.0) - RC(6.0) * g + RC(6.0) * g2)) 539 #define bh4 -RC(3.0) * g2 * (-RC(1.0) + RC(4.0) * g - RC(2.0) * g2 + g3) / (RC(1.0) - RC(6.0) * g + RC(6.0) * g2) 540 #else 541 /* This is for c3 = 1.0 */ 542 #define bh2 a32 543 #define bh3 g 544 #define bh4 RC(0.0) 545 #endif 546 /* ESDIRK3(2I)4L[2]SA from KC16 with c3 = 1.0 */ 547 /* Given by Kvaerno https://link.springer.com/article/10.1023/b:bitn.0000046811.70614.38 */ 548 const PetscReal A[4][4] = { 549 {RC(0.0), RC(0.0), RC(0.0), RC(0.0)}, 550 {g, g, RC(0.0), RC(0.0)}, 551 {c3 - a32 - g, a32, g, RC(0.0)}, 552 {RC(1.0) - b2 - b3 - g, b2, b3, g }, 553 }; 554 const PetscReal b[4] = {RC(1.0) - b2 - b3 - g, b2, b3, g}; 555 const PetscReal bembed[4] = {RC(1.0) - bh2 - bh3 - bh4, bh2, bh3, bh4}; 556 PetscCall(TSDIRKRegister(TSDIRKES324SAL, 3, 4, &A[0][0], b, NULL, bembed, 1, b)); 557 #undef g 558 #undef g2 559 #undef g3 560 #undef c3 561 #undef a32 562 #undef b2 563 #undef b3 564 #undef bh2 565 #undef bh3 566 #undef bh4 567 } 568 569 { 570 /* ESDIRK3(2I)5L[2]SA from KC16 */ 571 const PetscReal A[5][5] = { 572 {RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 573 {RC(9.0) / RC(40.0), RC(9.0) / RC(40.0), RC(0.0), RC(0.0), RC(0.0) }, 574 {RC(19.0) / RC(72.0), RC(14.0) / RC(45.0), RC(9.0) / RC(40.0), RC(0.0), RC(0.0) }, 575 {RC(3337.0) / RC(11520.0), RC(233.0) / RC(720.0), RC(207.0) / RC(1280.0), RC(9.0) / RC(40.0), RC(0.0) }, 576 {RC(7415.0) / RC(34776.0), RC(9920.0) / RC(30429.0), RC(4845.0) / RC(9016.0), -RC(5827.0) / RC(19320.0), RC(9.0) / RC(40.0)}, 577 }; 578 const PetscReal b[5] = {RC(7415.0) / RC(34776.0), RC(9920.0) / RC(30429.0), RC(4845.0) / RC(9016.0), -RC(5827.0) / RC(19320.0), RC(9.0) / RC(40.0)}; 579 const PetscReal bembed[5] = {RC(23705.0) / RC(104328.0), RC(29720.0) / RC(91287.0), RC(4225.0) / RC(9016.0), -RC(69304987.0) / RC(337732920.0), RC(42843.0) / RC(233080.0)}; 580 PetscCall(TSDIRKRegister(TSDIRKES325SAL, 3, 5, &A[0][0], b, NULL, bembed, 1, b)); 581 } 582 583 { 584 // DIRK(6,6)[1]A[(7,5)A] from https://github.com/yousefalamri55/High_Order_DIRK_Methods_Coeffs 585 const PetscReal A[7][7] = { 586 {RC(0.303487844706747), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 587 {RC(-0.279756492709814), RC(0.500032236020747), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 588 {RC(0.280583215743895), RC(-0.438560061586751), RC(0.217250734515736), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 589 {RC(-0.0677678738539846), RC(0.984312781232293), RC(-0.266720192540149), RC(0.2476680834526), RC(0.0), RC(0.0), RC(0.0) }, 590 {RC(0.125671616147993), RC(-0.995401751002415), RC(0.761333109549059), RC(-0.210281837202208), RC(0.866743712636936), RC(0.0), RC(0.0) }, 591 {RC(-0.368056238801488), RC(-0.999928082701516), RC(0.534734253232519), RC(-0.174856916279082), RC(0.615007160285509), RC(0.696549912132029), RC(0.0) }, 592 {RC(-0.00570546839653984), RC(-0.113110431835656), RC(-0.000965563207671587), RC(-0.000130490084629567), RC(0.00111737736895673), RC(-0.279385587378871), RC(0.618455906845342)} 593 }; 594 const PetscReal b[7] = {RC(0.257561510484877), RC(0.234281287047716), RC(0.126658904241469), RC(0.252363215441784), RC(0.396701083526306), RC(-0.267566000742152), RC(0.0)}; 595 const PetscReal bembed[7] = {RC(0.257561510484945), RC(0.387312822934391), RC(0.126658904241468), RC(0.252363215441784), RC(0.396701083526306), RC(-0.267566000742225), RC(-0.153031535886669)}; 596 PetscCall(TSDIRKRegister(TSDIRK657A, 6, 7, &A[0][0], b, NULL, bembed, 1, b)); 597 } 598 { 599 // ESDIRK(8,6)[2]SA[(8,4)] from https://github.com/yousefalamri55/High_Order_DIRK_Methods_Coeffs 600 const PetscReal A[8][8] = { 601 {RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 602 {RC(0.333222149217725), RC(0.333222149217725), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 603 {RC(0.0639743773182214), RC(-0.0830330224410214), RC(0.333222149217725), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 604 {RC(-0.728522201369326), RC(-0.210414479522485), RC(0.532519916559342), RC(0.333222149217725), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 605 {RC(-0.175135269272067), RC(0.666675582067552), RC(-0.304400907370867), RC(0.656797712445756), RC(0.333222149217725), RC(0.0), RC(0.0), RC(0.0) }, 606 {RC(0.222695802705462), RC(-0.0948971794681061), RC(-0.0234336346686545), RC(-0.45385925012042), RC(0.0283910313826958), RC(0.333222149217725), RC(0.0), RC(0.0) }, 607 {RC(-0.132534078051299), RC(0.702597935004879), RC(-0.433316453128078), RC(0.893717488547587), RC(0.057381454791406), RC(-0.207798411552402), RC(0.333222149217725), RC(0.0) }, 608 {RC(0.0802253121418085), RC(0.281196044671022), RC(0.406758926172157), RC(-0.01945708512416), RC(-0.41785600088526), RC(0.0545342658870322), RC(0.281376387919675), RC(0.333222149217725)} 609 }; 610 const PetscReal b[8] = {RC(0.0802253121418085), RC(0.281196044671022), RC(0.406758926172157), RC(-0.01945708512416), RC(-0.41785600088526), RC(0.0545342658870322), RC(0.281376387919675), RC(0.333222149217725)}; 611 const PetscReal bembed[8] = {RC(0.0), RC(0.292331064554014), RC(0.409676102283681), RC(-0.002094718084982), RC(-0.282771520835975), RC(0.113862336644901), RC(0.181973572260693), RC(0.287023163177669)}; 612 PetscCall(TSDIRKRegister(TSDIRKES648SA, 6, 8, &A[0][0], b, NULL, bembed, 1, b)); 613 } 614 { 615 // DIRK(8,6)[1]SAL[(8,5)A] from https://github.com/yousefalamri55/High_Order_DIRK_Methods_Coeffs 616 const PetscReal A[8][8] = { 617 {RC(0.477264457385826), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 618 {RC(-0.197052588415002), RC(0.476363428459584), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 619 {RC(-0.0347674430372966), RC(0.633051807335483), RC(0.193634310075028), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 620 {RC(0.0967797668578702), RC(-0.193533526466535), RC(-0.000207622945800473), RC(0.159572204849431), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 621 {RC(0.162527231819875), RC(-0.249672513547382), RC(-0.0459079972041795), RC(0.36579476400859), RC(0.255752838307699), RC(0.0), RC(0.0), RC(0.0) }, 622 {RC(-0.00707603197171262), RC(0.846299854860295), RC(0.344020016925018), RC(-0.0720926054548865), RC(-0.215492331980875), RC(0.104341097622161), RC(0.0), RC(0.0) }, 623 {RC(0.00176857935179744), RC(0.0779960013127515), RC(0.303333277564557), RC(0.213160806732836), RC(0.351769320319038), RC(-0.381545894386538), RC(0.433517909105558), RC(0.0) }, 624 {RC(0.0), RC(0.22732353410559), RC(0.308415837980118), RC(0.157263419573007), RC(0.243551137152275), RC(-0.120953626732831), RC(-0.0802678473399899), RC(0.264667545261832)} 625 }; 626 const PetscReal b[8] = {RC(0.0), RC(0.22732353410559), RC(0.308415837980118), RC(0.157263419573007), RC(0.243551137152275), RC(-0.120953626732831), RC(-0.0802678473399899), RC(0.264667545261832)}; 627 const PetscReal bembed[8] = {RC(0.0), RC(0.22732353410559), RC(0.308415837980118), RC(0.157263419573007), RC(0.243551137152275), RC(-0.103483943222765), RC(-0.0103721771642262), RC(0.177302191576001)}; 628 PetscCall(TSDIRKRegister(TSDIRK658A, 6, 8, &A[0][0], b, NULL, bembed, 1, b)); 629 } 630 { 631 // SDIRK(9,6)[1]SAL[(9,5)A] from https://github.com/yousefalamri55/High_Order_DIRK_Methods_Coeffs 632 const PetscReal A[9][9] = { 633 {RC(0.218127781944908), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 634 {RC(-0.0903514856119419), RC(0.218127781944908), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 635 {RC(0.172952039138937), RC(-0.35365501036282), RC(0.218127781944908), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 636 {RC(0.511999875919193), RC(0.0289640332201925), RC(-0.0144030945657094), RC(0.218127781944908), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 637 {RC(0.00465303495506782), RC(-0.075635818766597), RC(0.217273030786712), RC(-0.0206519428725472), RC(0.218127781944908), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 638 {RC(0.896145501762472), RC(0.139267327700498), RC(-0.186920979752805), RC(0.0672971012371723), RC(-0.350891963442176), RC(0.218127781944908), RC(0.0), RC(0.0), RC(0.0) }, 639 {RC(0.552959701885751), RC(-0.439360579793662), RC(0.333704002325091), RC(-0.0339426520778416), RC(-0.151947445912595), RC(0.0213825661026943), RC(0.218127781944908), RC(0.0), RC(0.0) }, 640 {RC(0.631360374036476), RC(0.724733619641466), RC(-0.432170625425258), RC(0.598611382182477), RC(-0.709087197034345), RC(-0.483986685696934), RC(0.378391562905131), RC(0.218127781944908), RC(0.0) }, 641 {RC(0.0), RC(-0.15504452530869), RC(0.194518478660789), RC(0.63515640279203), RC(0.81172278664173), RC(0.110736108691585), RC(-0.495304692414479), RC(-0.319912341007872), RC(0.218127781944908)} 642 }; 643 const PetscReal b[9] = {RC(0.0), RC(-0.15504452530869), RC(0.194518478660789), RC(0.63515640279203), RC(0.81172278664173), RC(0.110736108691585), RC(-0.495304692414479), RC(-0.319912341007872), RC(0.218127781944908)}; 644 const PetscReal bembed[9] = {RC(3.62671059311602e-16), RC(0.0736615558278942), RC(0.103527397262229), RC(1.00247481935499), RC(0.361377289250057), RC(-0.785425929961365), RC(-0.0170499047960784), RC(0.296321252214769), RC(-0.0348864791524953)}; 645 PetscCall(TSDIRKRegister(TSDIRKS659A, 6, 9, &A[0][0], b, NULL, bembed, 1, b)); 646 } 647 { 648 // DIRK(10,7)[1]SAL[(10,5)A] from https://github.com/yousefalamri55/High_Order_DIRK_Methods_Coeffs 649 const PetscReal A[10][10] = { 650 {RC(0.233704632125264), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 651 {RC(-0.0739324813149407), RC(0.200056838146104), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 652 {RC(0.0943790344044812), RC(0.264056067701605), RC(0.133245202456465), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 653 {RC(0.269084810601201), RC(-0.503479002548384), RC(-0.00486736469695022), RC(0.251518716213569), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 654 {RC(0.145665801918423), RC(0.204983170463176), RC(0.407154634069484), RC(-0.0121039135200389), RC(0.190243622486334), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 655 {RC(0.985450198547345), RC(0.806942652811456), RC(-0.808130934167263), RC(-0.669035819439391), RC(0.0269384406756128), RC(0.462144080607327), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 656 {RC(0.163902957809563), RC(0.228315094960095), RC(0.0745971021260249), RC(0.000509793400156559), RC(0.0166533681378294), RC(-0.0229383879045797), RC(0.103505486637336), RC(0.0), RC(0.0), RC(0.0) }, 657 {RC(-0.162694156858437), RC(0.0453478837428434), RC(0.997443481211424), RC(0.200251514941093), RC(-0.000161755458839048), RC(-0.0848134335980281), RC(-0.36438666566666), RC(0.158604420136055), RC(0.0), RC(0.0) }, 658 {RC(0.200733156477425), RC(0.239686443444433), RC(0.303837014418929), RC(-0.0534390596279896), RC(0.0314067599640569), RC(-0.00764032790448536), RC(0.0609191260198661), RC(-0.0736319201590642), RC(0.204602530607021), RC(0.0) }, 659 {RC(0.0), RC(0.235563761744267), RC(0.658651488684319), RC(0.0308877804992098), RC(-0.906514945595336), RC(-0.0248488551739974), RC(-0.309967582365257), RC(0.191663316925525), RC(0.923933712199542), RC(0.200631323081727)} 660 }; 661 const PetscReal b[10] = {RC(0.0), RC(0.235563761744267), RC(0.658651488684319), RC(0.0308877804992098), RC(-0.906514945595336), RC(-0.0248488551739974), RC(-0.309967582365257), RC(0.191663316925525), RC(0.923933712199542), RC(0.200631323081727)}; 662 const PetscReal bembed[10] = 663 {RC(0.0), RC(0.222929376486581), RC(0.950668440138169), RC(0.0342694607044032), RC(0.362875840545746), RC(0.223572979288581), RC(-0.764361723526727), RC(0.563476909230026), RC(-0.690896961894185), RC(0.0974656790270323)}; 664 PetscCall(TSDIRKRegister(TSDIRK7510SAL, 7, 10, &A[0][0], b, NULL, bembed, 1, b)); 665 } 666 { 667 // ESDIRK(10,7)[2]SA[(10,5)] from https://github.com/yousefalamri55/High_Order_DIRK_Methods_Coeffs 668 const PetscReal A[10][10] = { 669 {RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 670 {RC(0.210055790203419), RC(0.210055790203419), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 671 {RC(0.255781739921086), RC(0.239850916980976), RC(0.210055790203419), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 672 {RC(0.286789624880437), RC(0.230494748834778), RC(0.263925149885491), RC(0.210055790203419), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 673 {RC(-0.0219118128774335), RC(0.897684380345907), RC(-0.657954605498907), RC(0.124962304722633), RC(0.210055790203419), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 674 {RC(-0.065614879584776), RC(-0.0565630711859497), RC(0.0254881105065311), RC(-0.00368981790650006), RC(-0.0115178258446329), RC(0.210055790203419), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 675 {RC(0.399860851232098), RC(0.915588469718705), RC(-0.0758429094934412), RC(-0.263369154872759), RC(0.719687583564526), RC(-0.787410407015369), RC(0.210055790203419), RC(0.0), RC(0.0), RC(0.0) }, 676 {RC(0.51693616104628), RC(1.00000540846973), RC(-0.0485110663289207), RC(-0.315208041581942), RC(0.749742806451587), RC(-0.990975090921248), RC(0.0159279583407308), RC(0.210055790203419), RC(0.0), RC(0.0) }, 677 {RC(-0.0303062129076945), RC(-0.297035174659034), RC(0.184724697462164), RC(-0.0351876079516183), RC(-0.00324668230690761), RC(0.216151004053531), RC(-0.126676252098317), RC(0.114040254365262), RC(0.210055790203419), RC(0.0) }, 678 {RC(0.0705997961586714), RC(-0.0281516061956374), RC(0.314600470734633), RC(-0.0907057557963371), RC(0.168078953957742), RC(-0.00655694984590575), RC(0.0505384497804303), RC(-0.0569572058725042), RC(0.368498056875488), RC(0.210055790203419)} 679 }; 680 const PetscReal b[10] = {RC(0.0705997961586714), RC(-0.0281516061956374), RC(0.314600470734633), RC(-0.0907057557963371), RC(0.168078953957742), 681 RC(-0.00655694984590575), RC(0.0505384497804303), RC(-0.0569572058725042), RC(0.368498056875488), RC(0.210055790203419)}; 682 const PetscReal bembed[10] = {RC(-0.015494246543626), RC(0.167657963820093), RC(0.269858958144236), RC(-0.0443258997755156), RC(0.150049236875266), 683 RC(0.259452082755846), RC(0.244624573502521), RC(-0.215528446920284), RC(0.0487601760292619), RC(0.134945602112201)}; 684 PetscCall(TSDIRKRegister(TSDIRKES7510SA, 7, 10, &A[0][0], b, NULL, bembed, 1, b)); 685 } 686 { 687 // DIRK(9,7)[1]A[(9,5)A] from https://github.com/yousefalamri55/High_Order_DIRK_Methods_Coeffs 688 const PetscReal A[9][9] = { 689 {RC(0.179877789855839), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 690 {RC(-0.100405844885157), RC(0.214948590644819), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 691 {RC(0.112251360198995), RC(-0.206162139150298), RC(0.125159642941958), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 692 {RC(-0.0335164000768257), RC(0.999942349946143), RC(-0.491470853833294), RC(0.19820086325566), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 693 {RC(-0.0417345265478321), RC(0.187864510308215), RC(0.0533789224305102), RC(-0.00822060284862916), RC(0.127670843671646), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 694 {RC(-0.0278257925239257), RC(0.600979340683382), RC(-0.242632273241134), RC(-0.11318753652081), RC(0.164326917632931), RC(0.284116597781395), RC(0.0), RC(0.0), RC(0.0) }, 695 {RC(0.041465583858922), RC(0.429657872601836), RC(-0.381323410582524), RC(0.391934277498434), RC(-0.245918275501241), RC(-0.35960669741231), RC(0.184000022289158), RC(0.0), RC(0.0) }, 696 {RC(-0.105565651574538), RC(-0.0557833155018609), RC(0.358967568942643), RC(-0.13489263413921), RC(0.129553247260677), RC(0.0992493795371489), RC(-0.15716610563461), RC(0.17918862279814), RC(0.0) }, 697 {RC(0.00439696079965225), RC(0.960250486570491), RC(0.143558372286706), RC(0.0819015241056593), RC(0.999562318563625), RC(0.325203439314358), RC(-0.679013149331228), RC(-0.990589559837246), RC(0.0773648037639896)} 698 }; 699 700 const PetscReal b[9] = {RC(0.0), RC(0.179291520437966), RC(0.115310295273026), RC(-0.857943261453138), RC(0.654911318641998), RC(1.18713633508094), RC(-0.0949482361570542), RC(-0.37661430946407), RC(0.19285633764033)}; 701 const PetscReal bembed[9] = {RC(0.0), RC(0.1897135479408), RC(0.127461414808862), RC(-0.835810807663404), RC(0.665114177777166), RC(1.16481046518346), RC(-0.11661858889792), RC(-0.387303251022099), RC(0.192633041873135)}; 702 PetscCall(TSDIRKRegister(TSDIRK759A, 7, 9, &A[0][0], b, NULL, bembed, 1, b)); 703 } 704 { 705 // SDIRK(11,7)[1]SAL[(11,5)A] from https://github.com/yousefalamri55/High_Order_DIRK_Methods_Coeffs 706 const PetscReal A[11][11] = { 707 {RC(0.200252661187742), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 708 {RC(-0.082947368165267), RC(0.200252661187742), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 709 {RC(0.483452690540751), RC(0.0), RC(0.200252661187742), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 710 {RC(0.771076453481321), RC(-0.22936926341842), RC(0.289733373208823), RC(0.200252661187742), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 711 {RC(0.0329683054968892), RC(-0.162397421903366), RC(0.000951777538562805), RC(0.0), RC(0.200252661187742), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 712 {RC(0.265888743485945), RC(0.606743151103931), RC(0.173443800537369), RC(-0.0433968261546912), RC(-0.385211017224481), RC(0.200252661187742), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 713 {RC(0.220662294551146), RC(-0.0465078507657608), RC(-0.0333111995282464), RC(0.011801580836998), RC(0.169480801030105), RC(-0.0167974432139385), RC(0.200252661187742), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 714 {RC(0.323099728365267), RC(0.0288371831672575), RC(-0.0543404318773196), RC(0.0137765831431662), RC(0.0516799019060702), RC(-0.0421359763835713), RC(0.181297932037826), RC(0.200252661187742), RC(0.0), RC(0.0), RC(0.0) }, 715 {RC(-0.164226696476538), RC(0.187552004946792), RC(0.0628674420973025), RC(-0.0108886582703428), RC(-0.0117628641717889), RC(0.0432176880867965), RC(-0.0315206836275473), RC(-0.0846007021638797), RC(0.200252661187742), RC(0.0), RC(0.0) }, 716 {RC(0.651428598623771), RC(-0.10208078475356), RC(0.198305701801888), RC(-0.0117354096673789), RC(-0.0440385966743686), RC(-0.0358364455795087), RC(-0.0075408087654097), RC(0.160320941654639), RC(0.017940248694499), RC(0.200252661187742), RC(0.0) }, 717 {RC(0.0), RC(-0.266259448580236), RC(-0.615982357748271), RC(0.561474126687165), RC(0.266911112787025), RC(0.219775952207137), RC(0.387847665451514), RC(0.612483137773236), RC(0.330027015806089), RC(-0.6965298655714), RC(0.200252661187742)} 718 }; 719 const PetscReal b[11] = 720 {RC(0.0), RC(-0.266259448580236), RC(-0.615982357748271), RC(0.561474126687165), RC(0.266911112787025), RC(0.219775952207137), RC(0.387847665451514), RC(0.612483137773236), RC(0.330027015806089), RC(-0.6965298655714), RC(0.200252661187742)}; 721 const PetscReal bembed[11] = 722 {RC(0.0), RC(0.180185524442613), RC(-0.628869710835338), RC(0.186185675988647), RC(0.0484716652630425), RC(0.203927720607141), RC(0.44041662512573), RC(0.615710527731245), RC(0.0689648839032607), RC(-0.253599870605903), RC(0.138606958379488)}; 723 PetscCall(TSDIRKRegister(TSDIRKS7511SAL, 7, 11, &A[0][0], b, NULL, bembed, 1, b)); 724 } 725 { 726 // DIRK(13,8)[1]A[(14,6)A] from https://github.com/yousefalamri55/High_Order_DIRK_Methods_Coeffs 727 const PetscReal A[14][14] = { 728 {RC(0.421050745442291), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 729 {RC(-0.0761079419591268), RC(0.264353986580857), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 730 {RC(0.0727106904170694), RC(-0.204265976977285), RC(0.181608196544136), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 731 {RC(0.55763054816611), RC(-0.409773579543499), RC(0.510926516886944), RC(0.259892204518476), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 732 {RC(0.0228083864844437), RC(-0.445569051836454), RC(-0.0915242778636248), RC(0.00450055909321655), RC(0.6397807199983), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 733 {RC(-0.135945849505152), RC(0.0946509646963754), RC(-0.236110197279175), RC(0.00318944206456517), RC(0.255453021028118), RC(0.174805219173446), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 734 {RC(-0.147960260670772), RC(-0.402188192230535), RC(-0.703014530043888), RC(0.00941974677418186), RC(0.885747111289207), RC(0.261314066449028), RC(0.16307697503668), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 735 {RC(0.165597241042244), RC(0.824182962188923), RC(-0.0280136160783609), RC(0.282372386631758), RC(-0.957721354131182), RC(0.489439550159977), RC(0.170094415598103), RC(0.0522519785718563), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 736 {RC(0.0335292011495618), RC(0.575750388029166), RC(0.223289855356637), RC(-0.00317458833242804), RC(-0.112890382135193), RC(-0.419809267954284), RC(0.0466136902102104), RC(-0.00115413813041085), RC(0.109685363692383), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 737 {RC(-0.0512616878252355), RC(0.699261265830807), RC(-0.117939611738769), RC(0.0021745241931243), RC(-0.00932826702640947), RC(-0.267575057469428), RC(0.126949139814065), RC(0.00330353204502163), RC(0.185949445053766), RC(0.0938215615963721), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 738 {RC(-0.106521517960343), RC(0.41835889096168), RC(0.353585905881916), RC(-0.0746474161579599), RC(-0.015450626460289), RC(-0.46224659192275), RC(-0.0576406327329181), RC(-0.00712066942504018), RC(0.377776558014452), RC(0.36890054338294), RC(0.0618488746331837), RC(0.0), RC(0.0), RC(0.0) }, 739 {RC(-0.163079104890997), RC(0.644561721693806), RC(0.636968661639572), RC(-0.122346720085377), RC(-0.333062564990312), RC(-0.3054226490478), RC(-0.357820712828352), RC(-0.0125510510334706), RC(0.371263681186311), RC(0.371979640363694), RC(0.0531090658708968), RC(0.0518279459132049), RC(0.0), RC(0.0) }, 740 {RC(0.579993784455521), RC(-0.188833728676494), RC(0.999975696843775), RC(0.0572810855901161), RC(-0.264374735003671), RC(0.165091739976854), RC(-0.546675809010452), RC(-0.0283821822291982), RC(-0.102639860418374), RC(-0.0343251040446405), RC(0.4762598462591), RC(-0.304153104931261), RC(0.0953911855943621), RC(0.0) }, 741 {RC(0.0848552694007844), RC(0.287193912340074), RC(0.543683503004232), RC(-0.081311059300692), RC(-0.0328661289388557), RC(-0.323456834372922), RC(-0.240378871658975), RC(-0.0189913019930369), RC(0.220663114082036), RC(0.253029984360864), RC(0.252011799370563), RC(-0.154882222605423), RC(0.0315202264687415), RC(0.0514095812104714)} 742 }; 743 const PetscReal b[14] = {RC(0.0), RC(0.516650324205117), RC(0.0773227217357826), RC(-0.12474204666975), RC(-0.0241052115180679), RC(-0.325821145180359), RC(0.0907237460123951), RC(0.0459271880596652), RC(0.221012259404702), RC(0.235510906761942), RC(0.491109674204385), RC(-0.323506525837343), RC(0.119918108821531), RC(0.0)}; 744 const PetscReal bembed[14] = {RC(2.32345691433618e-16), RC(0.499150900944401), RC(0.080991997189243), RC(-0.0359440417166322), RC(-0.0258910397441454), RC(-0.304540350278636), RC(0.0836627473632563), 745 RC(0.0417664613347638), RC(0.223636394275293), RC(0.231569156867596), RC(0.240526201277663), RC(-0.222933582911926), RC(-0.0111479879597561), RC(0.19915314335888)}; 746 PetscCall(TSDIRKRegister(TSDIRK8614A, 8, 14, &A[0][0], b, NULL, bembed, 1, b)); 747 } 748 { 749 // DIRK(15,8)[1]SAL[(16,6)A] from https://github.com/yousefalamri55/High_Order_DIRK_Methods_Coeffs 750 const PetscReal A[16][16] = { 751 {RC(0.498904981271193), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 752 {RC(-0.303806037341816), RC(0.886299445992379), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 753 {RC(-0.581440223471476), RC(0.371003719460259), RC(0.43844717752802), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 754 {RC(0.531852638870051), RC(-0.339363014907108), RC(0.422373239795441), RC(0.223854203543397), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 755 {RC(0.118517891868867), RC(-0.0756235584174296), RC(-0.0864284870668712), RC(0.000536692838658312), RC(0.10101418329932), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 756 {RC(0.218733626116401), RC(-0.139568928299635), RC(0.30473612813488), RC(0.00354038623073564), RC(0.0932085751160559), RC(0.140161806097591), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 757 {RC(0.0692944686081835), RC(-0.0442152168939502), RC(-0.0903375348855603), RC(0.00259030241156141), RC(0.204514233679515), RC(-0.0245383758960002), RC(0.199289437094059), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 758 {RC(0.990640016505571), RC(-0.632104756315967), RC(0.856971425234221), RC(0.174494099232246), RC(-0.113715829680145), RC(-0.151494045307366), RC(-0.438268629569005), RC(0.120578398912139), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 759 {RC(-0.099415677713136), RC(0.211832014309207), RC(-0.245998265866888), RC(-0.182249672235861), RC(0.167897635713799), RC(0.212850335030069), RC(-0.391739299440123), RC(-0.0118718506876767), RC(0.526293701659093), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 760 {RC(0.383983914845461), RC(-0.245011361219604), RC(0.46717278554955), RC(-0.0361272447593202), RC(0.0742234660511333), RC(-0.0474816271948766), RC(-0.229859978525756), RC(0.0516283729206322), RC(0.0), RC(0.193823890777594), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 761 {RC(0.0967855003180134), RC(-0.0481037037916184), RC(0.191268138832434), RC(0.234977164564126), RC(0.0620265921753097), RC(0.403432826534738), RC(0.152403846687238), RC(-0.118420429237746), RC(0.0582141598685892), RC(-0.13924540906863), RC(0.106661313117545), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 762 {RC(0.133941307432055), RC(-0.0722076602896254), RC(0.217086297689275), RC(0.00495499602192887), RC(0.0306090174933995), RC(0.26483526755746), RC(0.204442440745605), RC(0.196883395136708), RC(0.056527012583996), RC(-0.150216381356784), RC(-0.217209415757333), RC(0.330353722743315), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 763 {RC(0.157014274561299), RC(-0.0883810256381874), RC(0.117193033885034), RC(-0.0362304243769466), RC(0.0169030211466111), RC(-0.169835753576141), RC(0.399749979234113), RC(0.31806704093008), RC(0.050340008347693), RC(0.120284837472214), RC(-0.235313193645423), RC(0.232488522208926), RC(0.117719679450729), RC(0.0), RC(0.0), RC(0.0) }, 764 {RC(0.00276453816875833), RC(-0.00366028255231782), RC(-0.331078914515559), RC(0.623377549031949), RC(0.167618142989491), RC(0.0748467945312516), RC(0.797629286699677), RC(-0.390714256799583), RC(-0.00808553925131555), RC(0.014840324980952), RC(-0.0856180410248133), RC(0.602943304937827), RC(-0.5771359338496), RC(0.112273026653282), RC(0.0), RC(0.0) }, 765 {RC(0.0), RC(0.0), RC(0.085283971980307), RC(0.51334393454179), RC(0.144355978013514), RC(0.255379109487853), RC(0.225075750790524), RC(-0.343241323394982), RC(0.0), RC(0.0798250392218852), RC(0.0528824734082655), RC(-0.0830350888900362), RC(0.022567388707279), RC(-0.0592631119040204), RC(0.106825878037621), RC(0.0) }, 766 {RC(0.173784481207652), RC(-0.110887906116241), RC(0.190052513365204), RC(-0.0688345422674029), RC(0.10326505079603), RC(0.267127097115219), RC(0.141703423176897), RC(0.0117966866651728), RC(-6.65650091812762e-15), RC(-0.0213725083662519), RC(-0.00931148598712566), RC(-0.10007679077114), RC(0.123471797451553), RC(0.00203684241073055), RC(-0.0294320891781173), RC(0.195746619921528)} 767 }; 768 const PetscReal b[16] = {RC(0.0), RC(0.0), RC(0.085283971980307), RC(0.51334393454179), RC(0.144355978013514), RC(0.255379109487853), RC(0.225075750790524), RC(-0.343241323394982), RC(0.0), RC(0.0798250392218852), RC(0.0528824734082655), RC(-0.0830350888900362), RC(0.022567388707279), RC(-0.0592631119040204), RC(0.106825878037621), RC(0.0)}; 769 const PetscReal bembed[16] = {RC(-1.31988512519898e-15), RC(7.53606601764004e-16), RC(0.0886789133915965), RC(0.0968726531622137), RC(0.143815375874267), RC(0.335214773313601), RC(0.221862366978063), RC(-0.147408947987273), 770 RC(4.16297599203445e-16), RC(0.000727276166520566), RC(-0.00284892677941246), RC(0.00512492274297611), RC(-0.000275595071215218), RC(0.0136014719350733), RC(0.0165190013607726), RC(0.228116714912817)}; 771 PetscCall(TSDIRKRegister(TSDIRK8616SAL, 8, 16, &A[0][0], b, NULL, bembed, 1, b)); 772 } 773 { 774 // ESDIRK(16,8)[2]SAL[(16,5)] from https://github.com/yousefalamri55/High_Order_DIRK_Methods_Coeffs 775 const PetscReal A[16][16] = { 776 {RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 777 {RC(0.117318819358521), RC(0.117318819358521), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 778 {RC(0.0557014605974616), RC(0.385525646638742), RC(0.117318819358521), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 779 {RC(0.063493276428895), RC(0.373556126263681), RC(0.0082994166438953), RC(0.117318819358521), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 780 {RC(0.0961351856230088), RC(0.335558324517178), RC(0.207077765910132), RC(-0.0581917140797146), RC(0.117318819358521), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 781 {RC(0.0497669214238319), RC(0.384288616546039), RC(0.0821728117583936), RC(0.120337007107103), RC(0.202262782645888), RC(0.117318819358521), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 782 {RC(0.00626710666809847), RC(0.496491452640725), RC(-0.111303249827358), RC(0.170478821683603), RC(0.166517073971103), RC(-0.0328669811542241), RC(0.117318819358521), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 783 {RC(0.0463439767281591), RC(0.00306724391019652), RC(-0.00816305222386205), RC(-0.0353302599538294), RC(0.0139313601702569), RC(-0.00992014507967429), RC(0.0210087909090165), RC(0.117318819358521), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 784 {RC(0.111574049232048), RC(0.467639166482209), RC(0.237773114804619), RC(0.0798895699267508), RC(0.109580615914593), RC(0.0307353103825936), RC(-0.0404391509541147), RC(-0.16942110744293), RC(0.117318819358521), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 785 {RC(-0.0107072484863877), RC(-0.231376703354252), RC(0.017541113036611), RC(0.144871527682418), RC(-0.041855459769806), RC(0.0841832168332261), RC(-0.0850020937282192), RC(0.486170343825899), RC(-0.0526717116822739), RC(0.117318819358521), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 786 {RC(-0.0142238262314935), RC(0.14752923682514), RC(0.238235830732566), RC(0.037950291904103), RC(0.252075123381518), RC(0.0474266904224567), RC(-0.00363139069342027), RC(0.274081442388563), RC(-0.0599166970745255), RC(-0.0527138812389185), RC(0.117318819358521), RC(0.0), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 787 {RC(-0.11837020183211), RC(-0.635712481821264), RC(0.239738832602538), RC(0.330058936651707), RC(-0.325784087988237), RC(-0.0506514314589253), RC(-0.281914404487009), RC(0.852596345144291), RC(0.651444614298805), RC(-0.103476387303591), RC(-0.354835880209975), RC(0.117318819358521), RC(0.0), RC(0.0), RC(0.0), RC(0.0) }, 788 {RC(-0.00458164025442349), RC(0.296219694015248), RC(0.322146049419995), RC(0.15917778285238), RC(0.284864871688843), RC(0.185509526463076), RC(-0.0784621067883274), RC(0.166312223692047), RC(-0.284152486083397), RC(-0.357125104338944), RC(0.078437074055306), RC(0.0884129667114481), RC(0.117318819358521), RC(0.0), RC(0.0), RC(0.0) }, 789 {RC(-0.0545561913848106), RC(0.675785423442753), RC(0.423066443201941), RC(-0.000165300126841193), RC(0.104252994793763), RC(-0.105763019303021), RC(-0.15988308809318), RC(0.0515050001032011), RC(0.56013979290924), RC(-0.45781539708603), RC(-0.255870699752664), RC(0.026960254296416), RC(-0.0721245985053681), RC(0.117318819358521), RC(0.0), RC(0.0) }, 790 {RC(0.0649253995775223), RC(-0.0216056457922249), RC(-0.073738139377975), RC(0.0931033310077225), RC(-0.0194339577299149), RC(-0.0879623837313009), RC(0.057125517179467), RC(0.205120850488097), RC(0.132576503537441), RC(0.489416890627328), RC(-0.1106765720501), RC(-0.081038793996096), RC(0.0606031613503788), RC(-0.00241467937442272), RC(0.117318819358521), RC(0.0) }, 791 {RC(0.0459979286336779), RC(0.0780075394482806), RC(0.015021874148058), RC(0.195180277284195), RC(-0.00246643310153235), RC(0.0473977117068314), RC(-0.0682773558610363), RC(0.19568019123878), RC(-0.0876765449323747), RC(0.177874852409192), RC(-0.337519251582222), RC(-0.0123255553640736), RC(0.311573291192553), RC(0.0458604327754991), RC(0.278352222645651), RC(0.117318819358521)} 792 }; 793 const PetscReal b[16] = {RC(0.0459979286336779), RC(0.0780075394482806), RC(0.015021874148058), RC(0.195180277284195), RC(-0.00246643310153235), RC(0.0473977117068314), RC(-0.0682773558610363), RC(0.19568019123878), 794 RC(-0.0876765449323747), RC(0.177874852409192), RC(-0.337519251582222), RC(-0.0123255553640736), RC(0.311573291192553), RC(0.0458604327754991), RC(0.278352222645651), RC(0.117318819358521)}; 795 const PetscReal bembed[16] = {RC(0.0603373529853206), RC(0.175453809423998), RC(0.0537707777611352), RC(0.195309248607308), RC(0.0135893741970232), RC(-0.0221160259296707), RC(-0.00726526156430691), RC(0.102961059369124), 796 RC(0.000900215457460583), RC(0.0547959465692338), RC(-0.334995726863153), RC(0.0464409662093384), RC(0.301388101652194), RC(0.00524851570622031), RC(0.229538601845236), RC(0.124643044573514)}; 797 PetscCall(TSDIRKRegister(TSDIRKES8516SAL, 8, 16, &A[0][0], b, NULL, bembed, 1, b)); 798 } 799 800 /* Additive methods */ 801 { 802 const PetscReal A[3][3] = { 803 {0.0, 0.0, 0.0}, 804 {0.0, 0.0, 0.0}, 805 {0.0, 0.5, 0.0} 806 }; 807 const PetscReal At[3][3] = { 808 {1.0, 0.0, 0.0}, 809 {0.0, 0.5, 0.0}, 810 {0.0, 0.5, 0.5} 811 }; 812 const PetscReal b[3] = {0.0, 0.5, 0.5}; 813 const PetscReal bembedt[3] = {1.0, 0.0, 0.0}; 814 PetscCall(TSARKIMEXRegister(TSARKIMEX1BEE, 2, 3, &At[0][0], b, NULL, &A[0][0], b, NULL, bembedt, bembedt, 1, b, NULL)); 815 } 816 { 817 const PetscReal A[2][2] = { 818 {0.0, 0.0}, 819 {0.5, 0.0} 820 }; 821 const PetscReal At[2][2] = { 822 {0.0, 0.0}, 823 {0.0, 0.5} 824 }; 825 const PetscReal b[2] = {0.0, 1.0}; 826 const PetscReal bembedt[2] = {0.5, 0.5}; 827 /* binterpt[2][2] = {{1.0,-1.0},{0.0,1.0}}; second order dense output has poor stability properties and hence it is not currently in use */ 828 PetscCall(TSARKIMEXRegister(TSARKIMEXARS122, 2, 2, &At[0][0], b, NULL, &A[0][0], b, NULL, bembedt, bembedt, 1, b, NULL)); 829 } 830 { 831 const PetscReal A[2][2] = { 832 {0.0, 0.0}, 833 {1.0, 0.0} 834 }; 835 const PetscReal At[2][2] = { 836 {0.0, 0.0}, 837 {0.5, 0.5} 838 }; 839 const PetscReal b[2] = {0.5, 0.5}; 840 const PetscReal bembedt[2] = {0.0, 1.0}; 841 /* binterpt[2][2] = {{1.0,-0.5},{0.0,0.5}} second order dense output has poor stability properties and hence it is not currently in use */ 842 PetscCall(TSARKIMEXRegister(TSARKIMEXA2, 2, 2, &At[0][0], b, NULL, &A[0][0], b, NULL, bembedt, bembedt, 1, b, NULL)); 843 } 844 { 845 const PetscReal A[2][2] = { 846 {0.0, 0.0}, 847 {1.0, 0.0} 848 }; 849 const PetscReal At[2][2] = { 850 {us2, 0.0}, 851 {1.0 - 2.0 * us2, us2} 852 }; 853 const PetscReal b[2] = {0.5, 0.5}; 854 const PetscReal bembedt[2] = {0.0, 1.0}; 855 const PetscReal binterpt[2][2] = { 856 {(us2 - 1.0) / (2.0 * us2 - 1.0), -1 / (2.0 * (1.0 - 2.0 * us2))}, 857 {1 - (us2 - 1.0) / (2.0 * us2 - 1.0), -1 / (2.0 * (1.0 - 2.0 * us2))} 858 }; 859 const PetscReal binterp[2][2] = { 860 {1.0, -0.5}, 861 {0.0, 0.5 } 862 }; 863 PetscCall(TSARKIMEXRegister(TSARKIMEXL2, 2, 2, &At[0][0], b, NULL, &A[0][0], b, NULL, bembedt, bembedt, 2, binterpt[0], binterp[0])); 864 } 865 { 866 const PetscReal A[3][3] = { 867 {0, 0, 0}, 868 {2 - s2, 0, 0}, 869 {0.5, 0.5, 0} 870 }; 871 const PetscReal At[3][3] = { 872 {0, 0, 0 }, 873 {1 - 1 / s2, 1 - 1 / s2, 0 }, 874 {1 / (2 * s2), 1 / (2 * s2), 1 - 1 / s2} 875 }; 876 const PetscReal bembedt[3] = {(4. - s2) / 8., (4. - s2) / 8., 1 / (2. * s2)}; 877 const PetscReal binterpt[3][2] = { 878 {1.0 / s2, -1.0 / (2.0 * s2)}, 879 {1.0 / s2, -1.0 / (2.0 * s2)}, 880 {1.0 - s2, 1.0 / s2 } 881 }; 882 PetscCall(TSARKIMEXRegister(TSARKIMEX2C, 2, 3, &At[0][0], NULL, NULL, &A[0][0], NULL, NULL, bembedt, bembedt, 2, binterpt[0], NULL)); 883 } 884 { 885 const PetscReal A[3][3] = { 886 {0, 0, 0}, 887 {2 - s2, 0, 0}, 888 {0.75, 0.25, 0} 889 }; 890 const PetscReal At[3][3] = { 891 {0, 0, 0 }, 892 {1 - 1 / s2, 1 - 1 / s2, 0 }, 893 {1 / (2 * s2), 1 / (2 * s2), 1 - 1 / s2} 894 }; 895 const PetscReal bembedt[3] = {(4. - s2) / 8., (4. - s2) / 8., 1 / (2. * s2)}; 896 const PetscReal binterpt[3][2] = { 897 {1.0 / s2, -1.0 / (2.0 * s2)}, 898 {1.0 / s2, -1.0 / (2.0 * s2)}, 899 {1.0 - s2, 1.0 / s2 } 900 }; 901 PetscCall(TSARKIMEXRegister(TSARKIMEX2D, 2, 3, &At[0][0], NULL, NULL, &A[0][0], NULL, NULL, bembedt, bembedt, 2, binterpt[0], NULL)); 902 } 903 { /* Optimal for linear implicit part */ 904 const PetscReal A[3][3] = { 905 {0, 0, 0}, 906 {2 - s2, 0, 0}, 907 {(3 - 2 * s2) / 6, (3 + 2 * s2) / 6, 0} 908 }; 909 const PetscReal At[3][3] = { 910 {0, 0, 0 }, 911 {1 - 1 / s2, 1 - 1 / s2, 0 }, 912 {1 / (2 * s2), 1 / (2 * s2), 1 - 1 / s2} 913 }; 914 const PetscReal bembedt[3] = {(4. - s2) / 8., (4. - s2) / 8., 1 / (2. * s2)}; 915 const PetscReal binterpt[3][2] = { 916 {1.0 / s2, -1.0 / (2.0 * s2)}, 917 {1.0 / s2, -1.0 / (2.0 * s2)}, 918 {1.0 - s2, 1.0 / s2 } 919 }; 920 PetscCall(TSARKIMEXRegister(TSARKIMEX2E, 2, 3, &At[0][0], NULL, NULL, &A[0][0], NULL, NULL, bembedt, bembedt, 2, binterpt[0], NULL)); 921 } 922 { /* Optimal for linear implicit part */ 923 const PetscReal A[3][3] = { 924 {0, 0, 0}, 925 {0.5, 0, 0}, 926 {0.5, 0.5, 0} 927 }; 928 const PetscReal At[3][3] = { 929 {0.25, 0, 0 }, 930 {0, 0.25, 0 }, 931 {1. / 3, 1. / 3, 1. / 3} 932 }; 933 PetscCall(TSARKIMEXRegister(TSARKIMEXPRSSP2, 2, 3, &At[0][0], NULL, NULL, &A[0][0], NULL, NULL, NULL, NULL, 0, NULL, NULL)); 934 } 935 { 936 const PetscReal A[4][4] = { 937 {0, 0, 0, 0}, 938 {1767732205903. / 2027836641118., 0, 0, 0}, 939 {5535828885825. / 10492691773637., 788022342437. / 10882634858940., 0, 0}, 940 {6485989280629. / 16251701735622., -4246266847089. / 9704473918619., 10755448449292. / 10357097424841., 0} 941 }; 942 const PetscReal At[4][4] = { 943 {0, 0, 0, 0 }, 944 {1767732205903. / 4055673282236., 1767732205903. / 4055673282236., 0, 0 }, 945 {2746238789719. / 10658868560708., -640167445237. / 6845629431997., 1767732205903. / 4055673282236., 0 }, 946 {1471266399579. / 7840856788654., -4482444167858. / 7529755066697., 11266239266428. / 11593286722821., 1767732205903. / 4055673282236.} 947 }; 948 const PetscReal bembedt[4] = {2756255671327. / 12835298489170., -10771552573575. / 22201958757719., 9247589265047. / 10645013368117., 2193209047091. / 5459859503100.}; 949 const PetscReal binterpt[4][2] = { 950 {4655552711362. / 22874653954995., -215264564351. / 13552729205753. }, 951 {-18682724506714. / 9892148508045., 17870216137069. / 13817060693119. }, 952 {34259539580243. / 13192909600954., -28141676662227. / 17317692491321.}, 953 {584795268549. / 6622622206610., 2508943948391. / 7218656332882. } 954 }; 955 PetscCall(TSARKIMEXRegister(TSARKIMEX3, 3, 4, &At[0][0], NULL, NULL, &A[0][0], NULL, NULL, bembedt, bembedt, 2, binterpt[0], NULL)); 956 } 957 { 958 const PetscReal A[5][5] = { 959 {0, 0, 0, 0, 0}, 960 {1. / 2, 0, 0, 0, 0}, 961 {11. / 18, 1. / 18, 0, 0, 0}, 962 {5. / 6, -5. / 6, .5, 0, 0}, 963 {1. / 4, 7. / 4, 3. / 4, -7. / 4, 0} 964 }; 965 const PetscReal At[5][5] = { 966 {0, 0, 0, 0, 0 }, 967 {0, 1. / 2, 0, 0, 0 }, 968 {0, 1. / 6, 1. / 2, 0, 0 }, 969 {0, -1. / 2, 1. / 2, 1. / 2, 0 }, 970 {0, 3. / 2, -3. / 2, 1. / 2, 1. / 2} 971 }; 972 PetscCall(TSARKIMEXRegister(TSARKIMEXARS443, 3, 5, &At[0][0], NULL, NULL, &A[0][0], NULL, NULL, NULL, NULL, 0, NULL, NULL)); 973 } 974 { 975 const PetscReal A[5][5] = { 976 {0, 0, 0, 0, 0}, 977 {1, 0, 0, 0, 0}, 978 {4. / 9, 2. / 9, 0, 0, 0}, 979 {1. / 4, 0, 3. / 4, 0, 0}, 980 {1. / 4, 0, 3. / 5, 0, 0} 981 }; 982 const PetscReal At[5][5] = { 983 {0, 0, 0, 0, 0 }, 984 {.5, .5, 0, 0, 0 }, 985 {5. / 18, -1. / 9, .5, 0, 0 }, 986 {.5, 0, 0, .5, 0 }, 987 {.25, 0, .75, -.5, .5} 988 }; 989 PetscCall(TSARKIMEXRegister(TSARKIMEXBPR3, 3, 5, &At[0][0], NULL, NULL, &A[0][0], NULL, NULL, NULL, NULL, 0, NULL, NULL)); 990 } 991 { 992 const PetscReal A[6][6] = { 993 {0, 0, 0, 0, 0, 0}, 994 {1. / 2, 0, 0, 0, 0, 0}, 995 {13861. / 62500., 6889. / 62500., 0, 0, 0, 0}, 996 {-116923316275. / 2393684061468., -2731218467317. / 15368042101831., 9408046702089. / 11113171139209., 0, 0, 0}, 997 {-451086348788. / 2902428689909., -2682348792572. / 7519795681897., 12662868775082. / 11960479115383., 3355817975965. / 11060851509271., 0, 0}, 998 {647845179188. / 3216320057751., 73281519250. / 8382639484533., 552539513391. / 3454668386233., 3354512671639. / 8306763924573., 4040. / 17871., 0} 999 }; 1000 const PetscReal At[6][6] = { 1001 {0, 0, 0, 0, 0, 0 }, 1002 {1. / 4, 1. / 4, 0, 0, 0, 0 }, 1003 {8611. / 62500., -1743. / 31250., 1. / 4, 0, 0, 0 }, 1004 {5012029. / 34652500., -654441. / 2922500., 174375. / 388108., 1. / 4, 0, 0 }, 1005 {15267082809. / 155376265600., -71443401. / 120774400., 730878875. / 902184768., 2285395. / 8070912., 1. / 4, 0 }, 1006 {82889. / 524892., 0, 15625. / 83664., 69875. / 102672., -2260. / 8211, 1. / 4} 1007 }; 1008 const PetscReal bembedt[6] = {4586570599. / 29645900160., 0, 178811875. / 945068544., 814220225. / 1159782912., -3700637. / 11593932., 61727. / 225920.}; 1009 const PetscReal binterpt[6][3] = { 1010 {6943876665148. / 7220017795957., -54480133. / 30881146., 6818779379841. / 7100303317025. }, 1011 {0, 0, 0 }, 1012 {7640104374378. / 9702883013639., -11436875. / 14766696., 2173542590792. / 12501825683035. }, 1013 {-20649996744609. / 7521556579894., 174696575. / 18121608., -31592104683404. / 5083833661969.}, 1014 {8854892464581. / 2390941311638., -12120380. / 966161., 61146701046299. / 7138195549469. }, 1015 {-11397109935349. / 6675773540249., 3843. / 706., -17219254887155. / 4939391667607.} 1016 }; 1017 PetscCall(TSARKIMEXRegister(TSARKIMEX4, 4, 6, &At[0][0], NULL, NULL, &A[0][0], NULL, NULL, bembedt, bembedt, 3, binterpt[0], NULL)); 1018 } 1019 { 1020 const PetscReal A[8][8] = { 1021 {0, 0, 0, 0, 0, 0, 0, 0}, 1022 {41. / 100, 0, 0, 0, 0, 0, 0, 0}, 1023 {367902744464. / 2072280473677., 677623207551. / 8224143866563., 0, 0, 0, 0, 0, 0}, 1024 {1268023523408. / 10340822734521., 0, 1029933939417. / 13636558850479., 0, 0, 0, 0, 0}, 1025 {14463281900351. / 6315353703477., 0, 66114435211212. / 5879490589093., -54053170152839. / 4284798021562., 0, 0, 0, 0}, 1026 {14090043504691. / 34967701212078., 0, 15191511035443. / 11219624916014., -18461159152457. / 12425892160975., -281667163811. / 9011619295870., 0, 0, 0}, 1027 {19230459214898. / 13134317526959., 0, 21275331358303. / 2942455364971., -38145345988419. / 4862620318723., -1. / 8, -1. / 8, 0, 0}, 1028 {-19977161125411. / 11928030595625., 0, -40795976796054. / 6384907823539., 177454434618887. / 12078138498510., 782672205425. / 8267701900261., -69563011059811. / 9646580694205., 7356628210526. / 4942186776405., 0} 1029 }; 1030 const PetscReal At[8][8] = { 1031 {0, 0, 0, 0, 0, 0, 0, 0 }, 1032 {41. / 200., 41. / 200., 0, 0, 0, 0, 0, 0 }, 1033 {41. / 400., -567603406766. / 11931857230679., 41. / 200., 0, 0, 0, 0, 0 }, 1034 {683785636431. / 9252920307686., 0, -110385047103. / 1367015193373., 41. / 200., 0, 0, 0, 0 }, 1035 {3016520224154. / 10081342136671., 0, 30586259806659. / 12414158314087., -22760509404356. / 11113319521817., 41. / 200., 0, 0, 0 }, 1036 {218866479029. / 1489978393911., 0, 638256894668. / 5436446318841., -1179710474555. / 5321154724896., -60928119172. / 8023461067671., 41. / 200., 0, 0 }, 1037 {1020004230633. / 5715676835656., 0, 25762820946817. / 25263940353407., -2161375909145. / 9755907335909., -211217309593. / 5846859502534., -4269925059573. / 7827059040749., 41. / 200, 0 }, 1038 {-872700587467. / 9133579230613., 0, 0, 22348218063261. / 9555858737531., -1143369518992. / 8141816002931., -39379526789629. / 19018526304540., 32727382324388. / 42900044865799., 41. / 200.} 1039 }; 1040 const PetscReal bembedt[8] = {-975461918565. / 9796059967033., 0, 0, 78070527104295. / 32432590147079., -548382580838. / 3424219808633., -33438840321285. / 15594753105479., 3629800801594. / 4656183773603., 4035322873751. / 18575991585200.}; 1041 const PetscReal binterpt[8][3] = { 1042 {-17674230611817. / 10670229744614., 43486358583215. / 12773830924787., -9257016797708. / 5021505065439. }, 1043 {0, 0, 0 }, 1044 {0, 0, 0 }, 1045 {65168852399939. / 7868540260826., -91478233927265. / 11067650958493., 26096422576131. / 11239449250142.}, 1046 {15494834004392. / 5936557850923., -79368583304911. / 10890268929626., 92396832856987. / 20362823103730.}, 1047 {-99329723586156. / 26959484932159., -12239297817655. / 9152339842473., 30029262896817. / 10175596800299.}, 1048 {-19024464361622. / 5461577185407., 115839755401235. / 10719374521269., -26136350496073. / 3983972220547.}, 1049 {-6511271360970. / 6095937251113., 5843115559534. / 2180450260947., -5289405421727. / 3760307252460. } 1050 }; 1051 PetscCall(TSARKIMEXRegister(TSARKIMEX5, 5, 8, &At[0][0], NULL, NULL, &A[0][0], NULL, NULL, bembedt, bembedt, 3, binterpt[0], NULL)); 1052 } 1053 #undef RC 1054 #undef us2 1055 #undef s2 1056 PetscFunctionReturn(PETSC_SUCCESS); 1057 } 1058 1059 /*@C 1060 TSARKIMEXRegisterDestroy - Frees the list of schemes that were registered by `TSARKIMEXRegister()`. 1061 1062 Not Collective 1063 1064 Level: advanced 1065 1066 .seealso: [](ch_ts), `TSARKIMEX`, `TSARKIMEXRegister()`, `TSARKIMEXRegisterAll()` 1067 @*/ 1068 PetscErrorCode TSARKIMEXRegisterDestroy(void) 1069 { 1070 ARKTableauLink link; 1071 1072 PetscFunctionBegin; 1073 while ((link = ARKTableauList)) { 1074 ARKTableau t = &link->tab; 1075 ARKTableauList = link->next; 1076 PetscCall(PetscFree6(t->At, t->bt, t->ct, t->A, t->b, t->c)); 1077 PetscCall(PetscFree2(t->bembedt, t->bembed)); 1078 PetscCall(PetscFree2(t->binterpt, t->binterp)); 1079 PetscCall(PetscFree(t->name)); 1080 PetscCall(PetscFree(link)); 1081 } 1082 TSARKIMEXRegisterAllCalled = PETSC_FALSE; 1083 PetscFunctionReturn(PETSC_SUCCESS); 1084 } 1085 1086 /*@C 1087 TSARKIMEXInitializePackage - This function initializes everything in the `TSARKIMEX` package. It is called 1088 from `TSInitializePackage()`. 1089 1090 Level: developer 1091 1092 .seealso: [](ch_ts), `PetscInitialize()`, `TSARKIMEXFinalizePackage()` 1093 @*/ 1094 PetscErrorCode TSARKIMEXInitializePackage(void) 1095 { 1096 PetscFunctionBegin; 1097 if (TSARKIMEXPackageInitialized) PetscFunctionReturn(PETSC_SUCCESS); 1098 TSARKIMEXPackageInitialized = PETSC_TRUE; 1099 PetscCall(TSARKIMEXRegisterAll()); 1100 PetscCall(PetscRegisterFinalize(TSARKIMEXFinalizePackage)); 1101 PetscFunctionReturn(PETSC_SUCCESS); 1102 } 1103 1104 /*@C 1105 TSARKIMEXFinalizePackage - This function destroys everything in the `TSARKIMEX` package. It is 1106 called from `PetscFinalize()`. 1107 1108 Level: developer 1109 1110 .seealso: [](ch_ts), `PetscFinalize()`, `TSARKIMEXInitializePackage()` 1111 @*/ 1112 PetscErrorCode TSARKIMEXFinalizePackage(void) 1113 { 1114 PetscFunctionBegin; 1115 TSARKIMEXPackageInitialized = PETSC_FALSE; 1116 PetscCall(TSARKIMEXRegisterDestroy()); 1117 PetscFunctionReturn(PETSC_SUCCESS); 1118 } 1119 1120 /*@C 1121 TSARKIMEXRegister - register a `TSARKIMEX` scheme by providing the entries in the Butcher tableau and optionally embedded approximations and interpolation 1122 1123 Logically Collective 1124 1125 Input Parameters: 1126 + name - identifier for method 1127 . order - approximation order of method 1128 . s - number of stages, this is the dimension of the matrices below 1129 . At - Butcher table of stage coefficients for stiff part (dimension s*s, row-major) 1130 . bt - Butcher table for completing the stiff part of the step (dimension s; NULL to use the last row of At) 1131 . ct - Abscissa of each stiff stage (dimension s, NULL to use row sums of At) 1132 . A - Non-stiff stage coefficients (dimension s*s, row-major) 1133 . b - Non-stiff step completion table (dimension s; NULL to use last row of At) 1134 . c - Non-stiff abscissa (dimension s; NULL to use row sums of A) 1135 . bembedt - Stiff part of completion table for embedded method (dimension s; NULL if not available) 1136 . bembed - Non-stiff part of completion table for embedded method (dimension s; NULL to use bembedt if provided) 1137 . pinterp - Order of the interpolation scheme, equal to the number of columns of binterpt and binterp 1138 . binterpt - Coefficients of the interpolation formula for the stiff part (dimension s*pinterp) 1139 - binterp - Coefficients of the interpolation formula for the non-stiff part (dimension s*pinterp; NULL to reuse binterpt) 1140 1141 Level: advanced 1142 1143 Note: 1144 Several `TSARKIMEX` methods are provided, this function is only needed to create new methods. 1145 1146 .seealso: [](ch_ts), `TSARKIMEX`, `TSType`, `TS` 1147 @*/ 1148 PetscErrorCode TSARKIMEXRegister(TSARKIMEXType name, PetscInt order, PetscInt s, const PetscReal At[], const PetscReal bt[], const PetscReal ct[], const PetscReal A[], const PetscReal b[], const PetscReal c[], const PetscReal bembedt[], const PetscReal bembed[], PetscInt pinterp, const PetscReal binterpt[], const PetscReal binterp[]) 1149 { 1150 ARKTableauLink link; 1151 ARKTableau t; 1152 PetscInt i, j; 1153 1154 PetscFunctionBegin; 1155 PetscCheck(s > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Expected number of stages s %" PetscInt_FMT " > 0", s); 1156 PetscCall(TSARKIMEXInitializePackage()); 1157 for (link = ARKTableauList; link; link = link->next) { 1158 PetscBool match; 1159 1160 PetscCall(PetscStrcmp(link->tab.name, name, &match)); 1161 PetscCheck(!match, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Method with name \"%s\" already registered", name); 1162 } 1163 PetscCall(PetscNew(&link)); 1164 t = &link->tab; 1165 PetscCall(PetscStrallocpy(name, &t->name)); 1166 t->order = order; 1167 t->s = s; 1168 PetscCall(PetscMalloc6(s * s, &t->At, s, &t->bt, s, &t->ct, s * s, &t->A, s, &t->b, s, &t->c)); 1169 PetscCall(PetscArraycpy(t->At, At, s * s)); 1170 if (A) { 1171 PetscCall(PetscArraycpy(t->A, A, s * s)); 1172 t->additive = PETSC_TRUE; 1173 } 1174 1175 if (bt) PetscCall(PetscArraycpy(t->bt, bt, s)); 1176 else 1177 for (i = 0; i < s; i++) t->bt[i] = At[(s - 1) * s + i]; 1178 1179 if (t->additive) { 1180 if (b) PetscCall(PetscArraycpy(t->b, b, s)); 1181 else 1182 for (i = 0; i < s; i++) t->b[i] = t->bt[i]; 1183 } else PetscCall(PetscArrayzero(t->b, s)); 1184 1185 if (ct) PetscCall(PetscArraycpy(t->ct, ct, s)); 1186 else 1187 for (i = 0; i < s; i++) 1188 for (j = 0, t->ct[i] = 0; j < s; j++) t->ct[i] += At[i * s + j]; 1189 1190 if (t->additive) { 1191 if (c) PetscCall(PetscArraycpy(t->c, c, s)); 1192 else 1193 for (i = 0; i < s; i++) 1194 for (j = 0, t->c[i] = 0; j < s; j++) t->c[i] += A[i * s + j]; 1195 } else PetscCall(PetscArrayzero(t->c, s)); 1196 1197 t->stiffly_accurate = PETSC_TRUE; 1198 for (i = 0; i < s; i++) 1199 if (t->At[(s - 1) * s + i] != t->bt[i]) t->stiffly_accurate = PETSC_FALSE; 1200 1201 t->explicit_first_stage = PETSC_TRUE; 1202 for (i = 0; i < s; i++) 1203 if (t->At[i] != 0.0) t->explicit_first_stage = PETSC_FALSE; 1204 1205 /* def of FSAL can be made more precise */ 1206 t->FSAL_implicit = (PetscBool)(t->explicit_first_stage && t->stiffly_accurate); 1207 1208 if (bembedt) { 1209 PetscCall(PetscMalloc2(s, &t->bembedt, s, &t->bembed)); 1210 PetscCall(PetscArraycpy(t->bembedt, bembedt, s)); 1211 PetscCall(PetscArraycpy(t->bembed, bembed ? bembed : bembedt, s)); 1212 } 1213 1214 t->pinterp = pinterp; 1215 PetscCall(PetscMalloc2(s * pinterp, &t->binterpt, s * pinterp, &t->binterp)); 1216 PetscCall(PetscArraycpy(t->binterpt, binterpt, s * pinterp)); 1217 PetscCall(PetscArraycpy(t->binterp, binterp ? binterp : binterpt, s * pinterp)); 1218 1219 link->next = ARKTableauList; 1220 ARKTableauList = link; 1221 PetscFunctionReturn(PETSC_SUCCESS); 1222 } 1223 1224 /*@C 1225 TSDIRKRegister - register a `TSDIRK` scheme by providing the entries in its Butcher tableau and, optionally, embedded approximations and interpolation 1226 1227 Logically Collective. 1228 1229 Input Parameters: 1230 + name - identifier for method 1231 . order - approximation order of method 1232 . s - number of stages, this is the dimension of the matrices below 1233 . At - Butcher table of stage coefficients (dimension `s`*`s`, row-major order) 1234 . bt - Butcher table for completing the step (dimension `s`; pass `NULL` to use the last row of `At`) 1235 . ct - Abscissa of each stage (dimension s, NULL to use row sums of At) 1236 . bembedt - Stiff part of completion table for embedded method (dimension s; `NULL` if not available) 1237 . pinterp - Order of the interpolation scheme, equal to the number of columns of `binterpt` and `binterp` 1238 - binterpt - Coefficients of the interpolation formula (dimension s*pinterp) 1239 1240 Level: advanced 1241 1242 Note: 1243 Several `TSDIRK` methods are provided, the use of this function is only needed to create new methods. 1244 1245 .seealso: [](ch_ts), `TSDIRK`, `TSType`, `TS` 1246 @*/ 1247 PetscErrorCode TSDIRKRegister(TSDIRKType name, PetscInt order, PetscInt s, const PetscReal At[], const PetscReal bt[], const PetscReal ct[], const PetscReal bembedt[], PetscInt pinterp, const PetscReal binterpt[]) 1248 { 1249 PetscFunctionBegin; 1250 PetscCall(TSARKIMEXRegister(name, order, s, At, bt, ct, NULL, NULL, NULL, bembedt, NULL, pinterp, binterpt, NULL)); 1251 PetscFunctionReturn(PETSC_SUCCESS); 1252 } 1253 1254 /* 1255 The step completion formula is 1256 1257 x1 = x0 - h bt^T YdotI + h b^T YdotRHS 1258 1259 This function can be called before or after ts->vec_sol has been updated. 1260 Suppose we have a completion formula (bt,b) and an embedded formula (bet,be) of different order. 1261 We can write 1262 1263 x1e = x0 - h bet^T YdotI + h be^T YdotRHS 1264 = x1 + h bt^T YdotI - h b^T YdotRHS - h bet^T YdotI + h be^T YdotRHS 1265 = x1 - h (bet - bt)^T YdotI + h (be - b)^T YdotRHS 1266 1267 so we can evaluate the method with different order even after the step has been optimistically completed. 1268 */ 1269 static PetscErrorCode TSEvaluateStep_ARKIMEX(TS ts, PetscInt order, Vec X, PetscBool *done) 1270 { 1271 TS_ARKIMEX *ark = (TS_ARKIMEX *)ts->data; 1272 ARKTableau tab = ark->tableau; 1273 PetscScalar *w = ark->work; 1274 PetscReal h; 1275 PetscInt s = tab->s, j; 1276 PetscBool hasE; 1277 1278 PetscFunctionBegin; 1279 switch (ark->status) { 1280 case TS_STEP_INCOMPLETE: 1281 case TS_STEP_PENDING: 1282 h = ts->time_step; 1283 break; 1284 case TS_STEP_COMPLETE: 1285 h = ts->ptime - ts->ptime_prev; 1286 break; 1287 default: 1288 SETERRQ(PetscObjectComm((PetscObject)ts), PETSC_ERR_PLIB, "Invalid TSStepStatus"); 1289 } 1290 if (order == tab->order) { 1291 if (ark->status == TS_STEP_INCOMPLETE) { 1292 if (!ark->imex && tab->stiffly_accurate) { /* Only the stiffly accurate implicit formula is used */ 1293 PetscCall(VecCopy(ark->Y[s - 1], X)); 1294 } else { /* Use the standard completion formula (bt,b) */ 1295 PetscCall(VecCopy(ts->vec_sol, X)); 1296 for (j = 0; j < s; j++) w[j] = h * tab->bt[j]; 1297 PetscCall(VecMAXPY(X, s, w, ark->YdotI)); 1298 if (tab->additive && ark->imex) { /* Method is IMEX, complete the explicit formula */ 1299 PetscCall(TSHasRHSFunction(ts, &hasE)); 1300 if (hasE) { 1301 for (j = 0; j < s; j++) w[j] = h * tab->b[j]; 1302 PetscCall(VecMAXPY(X, s, w, ark->YdotRHS)); 1303 } 1304 } 1305 } 1306 } else PetscCall(VecCopy(ts->vec_sol, X)); 1307 if (done) *done = PETSC_TRUE; 1308 PetscFunctionReturn(PETSC_SUCCESS); 1309 } else if (order == tab->order - 1) { 1310 if (!tab->bembedt) goto unavailable; 1311 if (ark->status == TS_STEP_INCOMPLETE) { /* Complete with the embedded method (bet,be) */ 1312 PetscCall(VecCopy(ts->vec_sol, X)); 1313 for (j = 0; j < s; j++) w[j] = h * tab->bembedt[j]; 1314 PetscCall(VecMAXPY(X, s, w, ark->YdotI)); 1315 if (tab->additive) { 1316 PetscCall(TSHasRHSFunction(ts, &hasE)); 1317 if (hasE) { 1318 for (j = 0; j < s; j++) w[j] = h * tab->bembed[j]; 1319 PetscCall(VecMAXPY(X, s, w, ark->YdotRHS)); 1320 } 1321 } 1322 } else { /* Rollback and re-complete using (bet-be,be-b) */ 1323 PetscCall(VecCopy(ts->vec_sol, X)); 1324 for (j = 0; j < s; j++) w[j] = h * (tab->bembedt[j] - tab->bt[j]); 1325 PetscCall(VecMAXPY(X, tab->s, w, ark->YdotI)); 1326 if (tab->additive) { 1327 PetscCall(TSHasRHSFunction(ts, &hasE)); 1328 if (hasE) { 1329 for (j = 0; j < s; j++) w[j] = h * (tab->bembed[j] - tab->b[j]); 1330 PetscCall(VecMAXPY(X, s, w, ark->YdotRHS)); 1331 } 1332 } 1333 } 1334 if (done) *done = PETSC_TRUE; 1335 PetscFunctionReturn(PETSC_SUCCESS); 1336 } 1337 unavailable: 1338 if (done) *done = PETSC_FALSE; 1339 else 1340 SETERRQ(PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "ARKIMEX '%s' of order %" PetscInt_FMT " cannot evaluate step at order %" PetscInt_FMT ". Consider using -ts_adapt_type none or a different method that has an embedded estimate.", tab->name, 1341 tab->order, order); 1342 PetscFunctionReturn(PETSC_SUCCESS); 1343 } 1344 1345 static PetscErrorCode TSARKIMEXTestMassIdentity(TS ts, PetscBool *id) 1346 { 1347 Vec Udot, Y1, Y2; 1348 TS_ARKIMEX *ark = (TS_ARKIMEX *)ts->data; 1349 PetscReal norm; 1350 1351 PetscFunctionBegin; 1352 PetscCall(VecDuplicate(ts->vec_sol, &Udot)); 1353 PetscCall(VecDuplicate(ts->vec_sol, &Y1)); 1354 PetscCall(VecDuplicate(ts->vec_sol, &Y2)); 1355 PetscCall(TSComputeIFunction(ts, ts->ptime, ts->vec_sol, Udot, Y1, ark->imex)); 1356 PetscCall(VecSetRandom(Udot, NULL)); 1357 PetscCall(TSComputeIFunction(ts, ts->ptime, ts->vec_sol, Udot, Y2, ark->imex)); 1358 PetscCall(VecAXPY(Y2, -1.0, Y1)); 1359 PetscCall(VecAXPY(Y2, -1.0, Udot)); 1360 PetscCall(VecNorm(Y2, NORM_2, &norm)); 1361 if (norm < 100.0 * PETSC_MACHINE_EPSILON) { 1362 *id = PETSC_TRUE; 1363 } else { 1364 *id = PETSC_FALSE; 1365 PetscCall(PetscInfo((PetscObject)ts, "IFunction(Udot = random) - IFunction(Udot = 0) is not near Udot, %g, suspect mass matrix implied in IFunction() is not the identity as required\n", (double)norm)); 1366 } 1367 PetscCall(VecDestroy(&Udot)); 1368 PetscCall(VecDestroy(&Y1)); 1369 PetscCall(VecDestroy(&Y2)); 1370 PetscFunctionReturn(PETSC_SUCCESS); 1371 } 1372 1373 static PetscErrorCode TSStep_ARKIMEX(TS ts) 1374 { 1375 TS_ARKIMEX *ark = (TS_ARKIMEX *)ts->data; 1376 ARKTableau tab = ark->tableau; 1377 const PetscInt s = tab->s; 1378 const PetscReal *At = tab->At, *A = tab->A, *ct = tab->ct, *c = tab->c; 1379 PetscScalar *w = ark->work; 1380 Vec *Y = ark->Y, *YdotI = ark->YdotI, *YdotRHS = ark->YdotRHS, Ydot = ark->Ydot, Ydot0 = ark->Ydot0, Z = ark->Z; 1381 PetscBool extrapolate = ark->extrapolate; 1382 TSAdapt adapt; 1383 SNES snes; 1384 PetscInt i, j, its, lits; 1385 PetscInt rejections = 0; 1386 PetscBool hasE = PETSC_FALSE, dirk = (PetscBool)(!tab->additive), stageok, accept = PETSC_TRUE; 1387 PetscReal next_time_step = ts->time_step; 1388 1389 PetscFunctionBegin; 1390 if (ark->extrapolate && !ark->Y_prev) { 1391 PetscCall(VecDuplicateVecs(ts->vec_sol, tab->s, &ark->Y_prev)); 1392 PetscCall(VecDuplicateVecs(ts->vec_sol, tab->s, &ark->YdotI_prev)); 1393 if (tab->additive) PetscCall(VecDuplicateVecs(ts->vec_sol, tab->s, &ark->YdotRHS_prev)); 1394 } 1395 1396 if (!dirk) PetscCall(TSHasRHSFunction(ts, &hasE)); 1397 if (!hasE) dirk = PETSC_TRUE; 1398 1399 if (!ts->steprollback) { 1400 if (dirk || ts->equation_type >= TS_EQ_IMPLICIT) { /* Save the initial slope for the next step */ 1401 PetscCall(VecCopy(YdotI[s - 1], Ydot0)); 1402 } 1403 if (ark->extrapolate && !ts->steprestart) { /* Save the Y, YdotI, YdotRHS for extrapolation initial guess */ 1404 for (i = 0; i < s; i++) { 1405 PetscCall(VecCopy(Y[i], ark->Y_prev[i])); 1406 PetscCall(VecCopy(YdotI[i], ark->YdotI_prev[i])); 1407 if (tab->additive && hasE) PetscCall(VecCopy(YdotRHS[i], ark->YdotRHS_prev[i])); 1408 } 1409 } 1410 } 1411 1412 /* 1413 For fully implicit formulations we must solve the equations 1414 1415 F(t_n,x_n,xdot) = 0 1416 1417 for the explicit first stage. 1418 Here we call SNESSolve using PETSC_MAX_REAL as shift to flag it. 1419 Special handling is inside SNESTSFormFunction_ARKIMEX and SNESTSFormJacobian_ARKIMEX 1420 */ 1421 if (dirk && tab->explicit_first_stage && ts->steprestart) { 1422 ark->scoeff = PETSC_MAX_REAL; 1423 PetscCall(VecCopy(ts->vec_sol, Z)); 1424 PetscCall(TSGetSNES(ts, &snes)); 1425 PetscCall(SNESSolve(snes, NULL, Ydot0)); 1426 } 1427 1428 /* For IMEX we compute a step */ 1429 if (!dirk && ts->equation_type >= TS_EQ_IMPLICIT && tab->explicit_first_stage && ts->steprestart) { 1430 TS ts_start; 1431 if (PetscDefined(USE_DEBUG) && hasE) { 1432 PetscBool id = PETSC_FALSE; 1433 PetscCall(TSARKIMEXTestMassIdentity(ts, &id)); 1434 PetscCheck(id, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_INCOMP, "This scheme requires an identity mass matrix, however the TSIFunctionFn you provided does not utilize an identity mass matrix"); 1435 } 1436 PetscCall(TSClone(ts, &ts_start)); 1437 PetscCall(TSSetSolution(ts_start, ts->vec_sol)); 1438 PetscCall(TSSetTime(ts_start, ts->ptime)); 1439 PetscCall(TSSetMaxSteps(ts_start, ts->steps + 1)); 1440 PetscCall(TSSetMaxTime(ts_start, ts->ptime + ts->time_step)); 1441 PetscCall(TSSetExactFinalTime(ts_start, TS_EXACTFINALTIME_STEPOVER)); 1442 PetscCall(TSSetTimeStep(ts_start, ts->time_step)); 1443 PetscCall(TSSetType(ts_start, TSARKIMEX)); 1444 PetscCall(TSARKIMEXSetFullyImplicit(ts_start, PETSC_TRUE)); 1445 PetscCall(TSARKIMEXSetType(ts_start, TSARKIMEX1BEE)); 1446 1447 PetscCall(TSRestartStep(ts_start)); 1448 PetscCall(TSSolve(ts_start, ts->vec_sol)); 1449 PetscCall(TSGetTime(ts_start, &ts->ptime)); 1450 PetscCall(TSGetTimeStep(ts_start, &ts->time_step)); 1451 1452 { /* Save the initial slope for the next step */ 1453 TS_ARKIMEX *ark_start = (TS_ARKIMEX *)ts_start->data; 1454 PetscCall(VecCopy(ark_start->YdotI[ark_start->tableau->s - 1], Ydot0)); 1455 } 1456 ts->steps++; 1457 1458 /* Set the correct TS in SNES */ 1459 /* We'll try to bypass this by changing the method on the fly */ 1460 { 1461 PetscCall(TSGetSNES(ts, &snes)); 1462 PetscCall(TSSetSNES(ts, snes)); 1463 } 1464 PetscCall(TSDestroy(&ts_start)); 1465 } 1466 1467 ark->status = TS_STEP_INCOMPLETE; 1468 while (!ts->reason && ark->status != TS_STEP_COMPLETE) { 1469 PetscReal t = ts->ptime; 1470 PetscReal h = ts->time_step; 1471 for (i = 0; i < s; i++) { 1472 ark->stage_time = t + h * ct[i]; 1473 PetscCall(TSPreStage(ts, ark->stage_time)); 1474 if (At[i * s + i] == 0) { /* This stage is explicit */ 1475 PetscCheck(i == 0 || ts->equation_type < TS_EQ_IMPLICIT, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "Explicit stages other than the first one are not supported for implicit problems"); 1476 PetscCall(VecCopy(ts->vec_sol, Y[i])); 1477 for (j = 0; j < i; j++) w[j] = h * At[i * s + j]; 1478 PetscCall(VecMAXPY(Y[i], i, w, YdotI)); 1479 if (tab->additive && hasE) { 1480 for (j = 0; j < i; j++) w[j] = h * A[i * s + j]; 1481 PetscCall(VecMAXPY(Y[i], i, w, YdotRHS)); 1482 } 1483 } else { 1484 ark->scoeff = 1. / At[i * s + i]; 1485 /* Ydot = shift*(Y-Z) */ 1486 PetscCall(VecCopy(ts->vec_sol, Z)); 1487 for (j = 0; j < i; j++) w[j] = h * At[i * s + j]; 1488 PetscCall(VecMAXPY(Z, i, w, YdotI)); 1489 if (tab->additive && hasE) { 1490 for (j = 0; j < i; j++) w[j] = h * A[i * s + j]; 1491 PetscCall(VecMAXPY(Z, i, w, YdotRHS)); 1492 } 1493 if (extrapolate && !ts->steprestart) { 1494 /* Initial guess extrapolated from previous time step stage values */ 1495 PetscCall(TSExtrapolate_ARKIMEX(ts, c[i], Y[i])); 1496 } else { 1497 /* Initial guess taken from last stage */ 1498 PetscCall(VecCopy(i > 0 ? Y[i - 1] : ts->vec_sol, Y[i])); 1499 } 1500 PetscCall(TSGetSNES(ts, &snes)); 1501 PetscCall(SNESSolve(snes, NULL, Y[i])); 1502 PetscCall(SNESGetIterationNumber(snes, &its)); 1503 PetscCall(SNESGetLinearSolveIterations(snes, &lits)); 1504 ts->snes_its += its; 1505 ts->ksp_its += lits; 1506 PetscCall(TSGetAdapt(ts, &adapt)); 1507 PetscCall(TSAdaptCheckStage(adapt, ts, ark->stage_time, Y[i], &stageok)); 1508 if (!stageok) { 1509 /* We are likely rejecting the step because of solver or function domain problems so we should not attempt to 1510 * use extrapolation to initialize the solves on the next attempt. */ 1511 extrapolate = PETSC_FALSE; 1512 goto reject_step; 1513 } 1514 } 1515 if (dirk || ts->equation_type >= TS_EQ_IMPLICIT) { 1516 if (i == 0 && tab->explicit_first_stage) { 1517 PetscCheck(tab->stiffly_accurate, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "%s %s is not stiffly accurate and therefore explicit-first stage methods cannot be used if the equation is implicit because the slope cannot be evaluated", 1518 ((PetscObject)ts)->type_name, ark->tableau->name); 1519 PetscCall(VecCopy(Ydot0, YdotI[0])); /* YdotI = YdotI(tn-1) */ 1520 } else { 1521 PetscCall(VecAXPBYPCZ(YdotI[i], -ark->scoeff / h, ark->scoeff / h, 0, Z, Y[i])); /* YdotI = shift*(X-Z) */ 1522 } 1523 } else { 1524 if (i == 0 && tab->explicit_first_stage) { 1525 PetscCall(VecZeroEntries(Ydot)); 1526 PetscCall(TSComputeIFunction(ts, t + h * ct[i], Y[i], Ydot, YdotI[i], ark->imex)); /* YdotI = -G(t,Y,0) */ 1527 PetscCall(VecScale(YdotI[i], -1.0)); 1528 } else { 1529 PetscCall(VecAXPBYPCZ(YdotI[i], -ark->scoeff / h, ark->scoeff / h, 0, Z, Y[i])); /* YdotI = shift*(X-Z) */ 1530 } 1531 if (hasE) { 1532 if (ark->imex) { 1533 PetscCall(TSComputeRHSFunction(ts, t + h * c[i], Y[i], YdotRHS[i])); 1534 } else { 1535 PetscCall(VecZeroEntries(YdotRHS[i])); 1536 } 1537 } 1538 } 1539 PetscCall(TSPostStage(ts, ark->stage_time, i, Y)); 1540 } 1541 1542 ark->status = TS_STEP_INCOMPLETE; 1543 PetscCall(TSEvaluateStep_ARKIMEX(ts, tab->order, ts->vec_sol, NULL)); 1544 ark->status = TS_STEP_PENDING; 1545 PetscCall(TSGetAdapt(ts, &adapt)); 1546 PetscCall(TSAdaptCandidatesClear(adapt)); 1547 PetscCall(TSAdaptCandidateAdd(adapt, tab->name, tab->order, 1, tab->ccfl, (PetscReal)tab->s, PETSC_TRUE)); 1548 PetscCall(TSAdaptChoose(adapt, ts, ts->time_step, NULL, &next_time_step, &accept)); 1549 ark->status = accept ? TS_STEP_COMPLETE : TS_STEP_INCOMPLETE; 1550 if (!accept) { /* Roll back the current step */ 1551 PetscCall(VecCopy(ts->vec_sol0, ts->vec_sol)); 1552 ts->time_step = next_time_step; 1553 goto reject_step; 1554 } 1555 1556 ts->ptime += ts->time_step; 1557 ts->time_step = next_time_step; 1558 break; 1559 1560 reject_step: 1561 ts->reject++; 1562 accept = PETSC_FALSE; 1563 if (!ts->reason && ++rejections > ts->max_reject && ts->max_reject >= 0) { 1564 ts->reason = TS_DIVERGED_STEP_REJECTED; 1565 PetscCall(PetscInfo(ts, "Step=%" PetscInt_FMT ", step rejections %" PetscInt_FMT " greater than current TS allowed, stopping solve\n", ts->steps, rejections)); 1566 } 1567 } 1568 PetscFunctionReturn(PETSC_SUCCESS); 1569 } 1570 1571 /* 1572 This adjoint step function assumes the partitioned ODE system has an identity mass matrix and thus can be represented in the form 1573 Udot = H(t,U) + G(t,U) 1574 This corresponds to F(t,U,Udot) = Udot-H(t,U). 1575 1576 The complete adjoint equations are 1577 (shift*I - dHdu) lambda_s[i] = 1/at[i][i] ( 1578 dGdU (b_i lambda_{n+1} + \sum_{j=i+1}^s a[j][i] lambda_s[j]) 1579 + dHdU (bt[i] lambda_{n+1} + \sum_{j=i+1}^s at[j][i] lambda_s[j])), i = s-1,...,0 1580 lambda_n = lambda_{n+1} + \sum_{j=1}^s lambda_s[j] 1581 mu_{n+1}[i] = h (at[i][i] dHdP lambda_s[i] 1582 + dGdP (b_i lambda_{n+1} + \sum_{j=i+1}^s a[j][i] lambda_s[j]) 1583 + dHdP (bt[i] lambda_{n+1} + \sum_{j=i+1}^s at[j][i] lambda_s[j])), i = s-1,...,0 1584 mu_n = mu_{n+1} + \sum_{j=1}^s mu_{n+1}[j] 1585 where shift = 1/(at[i][i]*h) 1586 1587 If at[i][i] is 0, the first equation falls back to 1588 lambda_s[i] = h ( 1589 (b_i dGdU + bt[i] dHdU) lambda_{n+1} + dGdU \sum_{j=i+1}^s a[j][i] lambda_s[j] 1590 + dHdU \sum_{j=i+1}^s at[j][i] lambda_s[j]) 1591 1592 */ 1593 static PetscErrorCode TSAdjointStep_ARKIMEX(TS ts) 1594 { 1595 TS_ARKIMEX *ark = (TS_ARKIMEX *)ts->data; 1596 ARKTableau tab = ark->tableau; 1597 const PetscInt s = tab->s; 1598 const PetscReal *At = tab->At, *A = tab->A, *ct = tab->ct, *c = tab->c, *b = tab->b, *bt = tab->bt; 1599 PetscScalar *w = ark->work; 1600 Vec *Y = ark->Y, Ydot = ark->Ydot, *VecsDeltaLam = ark->VecsDeltaLam, *VecsSensiTemp = ark->VecsSensiTemp, *VecsSensiPTemp = ark->VecsSensiPTemp; 1601 Mat Jex, Jim, Jimpre; 1602 PetscInt i, j, nadj; 1603 PetscReal t = ts->ptime, stage_time_ex; 1604 PetscReal adjoint_time_step = -ts->time_step; /* always positive since ts->time_step is negative */ 1605 KSP ksp; 1606 1607 PetscFunctionBegin; 1608 ark->status = TS_STEP_INCOMPLETE; 1609 PetscCall(SNESGetKSP(ts->snes, &ksp)); 1610 PetscCall(TSGetRHSMats_Private(ts, &Jex, NULL)); 1611 PetscCall(TSGetIJacobian(ts, &Jim, &Jimpre, NULL, NULL)); 1612 1613 for (i = s - 1; i >= 0; i--) { 1614 ark->stage_time = t - adjoint_time_step * (1.0 - ct[i]); 1615 stage_time_ex = t - adjoint_time_step * (1.0 - c[i]); 1616 if (At[i * s + i] == 0) { // This stage is explicit 1617 ark->scoeff = 0.; 1618 } else { 1619 ark->scoeff = -1. / At[i * s + i]; // this makes shift=ark->scoeff/ts->time_step positive since ts->time_step is negative 1620 } 1621 PetscCall(TSComputeSNESJacobian(ts, Y[i], Jim, Jimpre)); 1622 PetscCall(TSComputeRHSJacobian(ts, stage_time_ex, Y[i], Jex, Jex)); 1623 if (ts->vecs_sensip) { 1624 PetscCall(TSComputeIJacobianP(ts, ark->stage_time, Y[i], Ydot, ark->scoeff / adjoint_time_step, ts->Jacp, PETSC_TRUE)); // get dFdP (-dHdP), Ydot not really used since mass matrix is identity 1625 PetscCall(TSComputeRHSJacobianP(ts, stage_time_ex, Y[i], ts->Jacprhs)); // get dGdP 1626 } 1627 /* Build RHS (stored in VecsDeltaLam) for first-order adjoint */ 1628 for (nadj = 0; nadj < ts->numcost; nadj++) { 1629 /* build implicit part */ 1630 PetscCall(VecSet(VecsSensiTemp[nadj], 0)); 1631 if (s - i - 1 > 0) { 1632 /* Temp = -\sum_{j=i+1}^s at[j][i] lambda_s[j] */ 1633 for (j = i + 1; j < s; j++) w[j - i - 1] = -At[j * s + i]; 1634 PetscCall(VecMAXPY(VecsSensiTemp[nadj], s - i - 1, w, &VecsDeltaLam[nadj * s + i + 1])); 1635 } 1636 /* Temp = Temp - bt[i] lambda_{n+1} */ 1637 PetscCall(VecAXPY(VecsSensiTemp[nadj], -bt[i], ts->vecs_sensi[nadj])); 1638 if (bt[i] || s - i - 1 > 0) { 1639 /* (shift I - dHdU) Temp */ 1640 PetscCall(MatMultTranspose(Jim, VecsSensiTemp[nadj], VecsDeltaLam[nadj * s + i])); 1641 /* cancel out shift Temp where shift=-scoeff/h */ 1642 PetscCall(VecAXPY(VecsDeltaLam[nadj * s + i], ark->scoeff / adjoint_time_step, VecsSensiTemp[nadj])); 1643 if (ts->vecs_sensip) { 1644 /* - dHdP Temp */ 1645 PetscCall(MatMultTranspose(ts->Jacp, VecsSensiTemp[nadj], VecsSensiPTemp[nadj])); 1646 /* mu_n += -h dHdP Temp */ 1647 PetscCall(VecAXPY(ts->vecs_sensip[nadj], adjoint_time_step, VecsSensiPTemp[nadj])); 1648 } 1649 } else { 1650 PetscCall(VecSet(VecsDeltaLam[nadj * s + i], 0)); // make sure it is initialized 1651 } 1652 /* build explicit part */ 1653 PetscCall(VecSet(VecsSensiTemp[nadj], 0)); 1654 if (s - i - 1 > 0) { 1655 /* Temp = \sum_{j=i+1}^s a[j][i] lambda_s[j] */ 1656 for (j = i + 1; j < s; j++) w[j - i - 1] = A[j * s + i]; 1657 PetscCall(VecMAXPY(VecsSensiTemp[nadj], s - i - 1, w, &VecsDeltaLam[nadj * s + i + 1])); 1658 } 1659 /* Temp = Temp + b[i] lambda_{n+1} */ 1660 PetscCall(VecAXPY(VecsSensiTemp[nadj], b[i], ts->vecs_sensi[nadj])); 1661 if (b[i] || s - i - 1 > 0) { 1662 /* dGdU Temp */ 1663 PetscCall(MatMultTransposeAdd(Jex, VecsSensiTemp[nadj], VecsDeltaLam[nadj * s + i], VecsDeltaLam[nadj * s + i])); 1664 if (ts->vecs_sensip) { 1665 /* dGdP Temp */ 1666 PetscCall(MatMultTranspose(ts->Jacprhs, VecsSensiTemp[nadj], VecsSensiPTemp[nadj])); 1667 /* mu_n += h dGdP Temp */ 1668 PetscCall(VecAXPY(ts->vecs_sensip[nadj], adjoint_time_step, VecsSensiPTemp[nadj])); 1669 } 1670 } 1671 /* Build LHS for first-order adjoint */ 1672 if (At[i * s + i] == 0) { // This stage is explicit 1673 PetscCall(VecScale(VecsDeltaLam[nadj * s + i], adjoint_time_step)); 1674 } else { 1675 KSP ksp; 1676 KSPConvergedReason kspreason; 1677 PetscCall(SNESGetKSP(ts->snes, &ksp)); 1678 PetscCall(KSPSetOperators(ksp, Jim, Jimpre)); 1679 PetscCall(VecScale(VecsDeltaLam[nadj * s + i], 1. / At[i * s + i])); 1680 PetscCall(KSPSolveTranspose(ksp, VecsDeltaLam[nadj * s + i], VecsDeltaLam[nadj * s + i])); 1681 PetscCall(KSPGetConvergedReason(ksp, &kspreason)); 1682 if (kspreason < 0) { 1683 ts->reason = TSADJOINT_DIVERGED_LINEAR_SOLVE; 1684 PetscCall(PetscInfo(ts, "Step=%" PetscInt_FMT ", %" PetscInt_FMT "th cost function, transposed linear solve fails, stopping 1st-order adjoint solve\n", ts->steps, nadj)); 1685 } 1686 if (ts->vecs_sensip) { 1687 /* -dHdP lambda_s[i] */ 1688 PetscCall(MatMultTranspose(ts->Jacp, VecsDeltaLam[nadj * s + i], VecsSensiPTemp[nadj])); 1689 /* mu_n += h at[i][i] dHdP lambda_s[i] */ 1690 PetscCall(VecAXPY(ts->vecs_sensip[nadj], -At[i * s + i] * adjoint_time_step, VecsSensiPTemp[nadj])); 1691 } 1692 } 1693 } 1694 } 1695 for (j = 0; j < s; j++) w[j] = 1.0; 1696 for (nadj = 0; nadj < ts->numcost; nadj++) // no need to do this for mu's 1697 PetscCall(VecMAXPY(ts->vecs_sensi[nadj], s, w, &VecsDeltaLam[nadj * s])); 1698 ark->status = TS_STEP_COMPLETE; 1699 PetscFunctionReturn(PETSC_SUCCESS); 1700 } 1701 1702 static PetscErrorCode TSInterpolate_ARKIMEX(TS ts, PetscReal itime, Vec X) 1703 { 1704 TS_ARKIMEX *ark = (TS_ARKIMEX *)ts->data; 1705 ARKTableau tab = ark->tableau; 1706 PetscInt s = tab->s, pinterp = tab->pinterp, i, j; 1707 PetscReal h; 1708 PetscReal tt, t; 1709 PetscScalar *bt = ark->work, *b = ark->work + s; 1710 const PetscReal *Bt = tab->binterpt, *B = tab->binterp; 1711 1712 PetscFunctionBegin; 1713 PetscCheck(Bt && B, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "%s %s does not have an interpolation formula", ((PetscObject)ts)->type_name, ark->tableau->name); 1714 switch (ark->status) { 1715 case TS_STEP_INCOMPLETE: 1716 case TS_STEP_PENDING: 1717 h = ts->time_step; 1718 t = (itime - ts->ptime) / h; 1719 break; 1720 case TS_STEP_COMPLETE: 1721 h = ts->ptime - ts->ptime_prev; 1722 t = (itime - ts->ptime) / h + 1; /* In the interval [0,1] */ 1723 break; 1724 default: 1725 SETERRQ(PetscObjectComm((PetscObject)ts), PETSC_ERR_PLIB, "Invalid TSStepStatus"); 1726 } 1727 for (i = 0; i < s; i++) bt[i] = b[i] = 0; 1728 for (j = 0, tt = t; j < pinterp; j++, tt *= t) { 1729 for (i = 0; i < s; i++) { 1730 bt[i] += h * Bt[i * pinterp + j] * tt; 1731 b[i] += h * B[i * pinterp + j] * tt; 1732 } 1733 } 1734 PetscCall(VecCopy(ark->Y[0], X)); 1735 PetscCall(VecMAXPY(X, s, bt, ark->YdotI)); 1736 if (tab->additive) { 1737 PetscBool hasE; 1738 PetscCall(TSHasRHSFunction(ts, &hasE)); 1739 if (hasE) PetscCall(VecMAXPY(X, s, b, ark->YdotRHS)); 1740 } 1741 PetscFunctionReturn(PETSC_SUCCESS); 1742 } 1743 1744 static PetscErrorCode TSExtrapolate_ARKIMEX(TS ts, PetscReal c, Vec X) 1745 { 1746 TS_ARKIMEX *ark = (TS_ARKIMEX *)ts->data; 1747 ARKTableau tab = ark->tableau; 1748 PetscInt s = tab->s, pinterp = tab->pinterp, i, j; 1749 PetscReal h, h_prev, t, tt; 1750 PetscScalar *bt = ark->work, *b = ark->work + s; 1751 const PetscReal *Bt = tab->binterpt, *B = tab->binterp; 1752 1753 PetscFunctionBegin; 1754 PetscCheck(Bt && B, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "TSARKIMEX %s does not have an interpolation formula", ark->tableau->name); 1755 h = ts->time_step; 1756 h_prev = ts->ptime - ts->ptime_prev; 1757 t = 1 + h / h_prev * c; 1758 for (i = 0; i < s; i++) bt[i] = b[i] = 0; 1759 for (j = 0, tt = t; j < pinterp; j++, tt *= t) { 1760 for (i = 0; i < s; i++) { 1761 bt[i] += h * Bt[i * pinterp + j] * tt; 1762 b[i] += h * B[i * pinterp + j] * tt; 1763 } 1764 } 1765 PetscCheck(ark->Y_prev, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "Stages from previous step have not been stored"); 1766 PetscCall(VecCopy(ark->Y_prev[0], X)); 1767 PetscCall(VecMAXPY(X, s, bt, ark->YdotI_prev)); 1768 if (tab->additive) { 1769 PetscBool hasE; 1770 PetscCall(TSHasRHSFunction(ts, &hasE)); 1771 if (hasE) PetscCall(VecMAXPY(X, s, b, ark->YdotRHS_prev)); 1772 } 1773 PetscFunctionReturn(PETSC_SUCCESS); 1774 } 1775 1776 static PetscErrorCode TSARKIMEXTableauReset(TS ts) 1777 { 1778 TS_ARKIMEX *ark = (TS_ARKIMEX *)ts->data; 1779 ARKTableau tab = ark->tableau; 1780 1781 PetscFunctionBegin; 1782 if (!tab) PetscFunctionReturn(PETSC_SUCCESS); 1783 PetscCall(PetscFree(ark->work)); 1784 PetscCall(VecDestroyVecs(tab->s, &ark->Y)); 1785 PetscCall(VecDestroyVecs(tab->s, &ark->YdotI)); 1786 PetscCall(VecDestroyVecs(tab->s, &ark->YdotRHS)); 1787 PetscCall(VecDestroyVecs(tab->s, &ark->Y_prev)); 1788 PetscCall(VecDestroyVecs(tab->s, &ark->YdotI_prev)); 1789 PetscCall(VecDestroyVecs(tab->s, &ark->YdotRHS_prev)); 1790 PetscFunctionReturn(PETSC_SUCCESS); 1791 } 1792 1793 static PetscErrorCode TSReset_ARKIMEX(TS ts) 1794 { 1795 TS_ARKIMEX *ark = (TS_ARKIMEX *)ts->data; 1796 1797 PetscFunctionBegin; 1798 PetscCall(TSARKIMEXTableauReset(ts)); 1799 PetscCall(VecDestroy(&ark->Ydot)); 1800 PetscCall(VecDestroy(&ark->Ydot0)); 1801 PetscCall(VecDestroy(&ark->Z)); 1802 PetscFunctionReturn(PETSC_SUCCESS); 1803 } 1804 1805 static PetscErrorCode TSAdjointReset_ARKIMEX(TS ts) 1806 { 1807 TS_ARKIMEX *ark = (TS_ARKIMEX *)ts->data; 1808 ARKTableau tab = ark->tableau; 1809 1810 PetscFunctionBegin; 1811 PetscCall(VecDestroyVecs(tab->s * ts->numcost, &ark->VecsDeltaLam)); 1812 PetscCall(VecDestroyVecs(ts->numcost, &ark->VecsSensiTemp)); 1813 PetscCall(VecDestroyVecs(ts->numcost, &ark->VecsSensiPTemp)); 1814 PetscFunctionReturn(PETSC_SUCCESS); 1815 } 1816 1817 static PetscErrorCode TSARKIMEXGetVecs(TS ts, DM dm, Vec *Z, Vec *Ydot) 1818 { 1819 TS_ARKIMEX *ax = (TS_ARKIMEX *)ts->data; 1820 1821 PetscFunctionBegin; 1822 if (Z) { 1823 if (dm && dm != ts->dm) { 1824 PetscCall(DMGetNamedGlobalVector(dm, "TSARKIMEX_Z", Z)); 1825 } else *Z = ax->Z; 1826 } 1827 if (Ydot) { 1828 if (dm && dm != ts->dm) { 1829 PetscCall(DMGetNamedGlobalVector(dm, "TSARKIMEX_Ydot", Ydot)); 1830 } else *Ydot = ax->Ydot; 1831 } 1832 PetscFunctionReturn(PETSC_SUCCESS); 1833 } 1834 1835 static PetscErrorCode TSARKIMEXRestoreVecs(TS ts, DM dm, Vec *Z, Vec *Ydot) 1836 { 1837 PetscFunctionBegin; 1838 if (Z) { 1839 if (dm && dm != ts->dm) PetscCall(DMRestoreNamedGlobalVector(dm, "TSARKIMEX_Z", Z)); 1840 } 1841 if (Ydot) { 1842 if (dm && dm != ts->dm) PetscCall(DMRestoreNamedGlobalVector(dm, "TSARKIMEX_Ydot", Ydot)); 1843 } 1844 PetscFunctionReturn(PETSC_SUCCESS); 1845 } 1846 1847 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat, PetscBool, PetscReal, IS *); 1848 1849 /* This defines the nonlinear equation that is to be solved with SNES */ 1850 static PetscErrorCode SNESTSFormFunction_ARKIMEX(SNES snes, Vec X, Vec F, TS ts) 1851 { 1852 TS_ARKIMEX *ark = (TS_ARKIMEX *)ts->data; 1853 DM dm, dmsave; 1854 Vec Z, Ydot; 1855 1856 PetscFunctionBegin; 1857 PetscCall(SNESGetDM(snes, &dm)); 1858 PetscCall(TSARKIMEXGetVecs(ts, dm, &Z, &Ydot)); 1859 dmsave = ts->dm; 1860 ts->dm = dm; 1861 1862 if (ark->scoeff == PETSC_MAX_REAL) { 1863 /* We are solving F(t_n,x_n,xdot) = 0 to start the method */ 1864 PetscCall(TSComputeIFunction(ts, ark->stage_time, Z, X, F, ark->imex)); 1865 } else { 1866 PetscReal shift = ark->scoeff / ts->time_step; 1867 PetscCall(VecAXPBYPCZ(Ydot, -shift, shift, 0, Z, X)); /* Ydot = shift*(X-Z) */ 1868 PetscCall(TSComputeIFunction(ts, ark->stage_time, X, Ydot, F, ark->imex)); 1869 } 1870 1871 ts->dm = dmsave; 1872 PetscCall(TSARKIMEXRestoreVecs(ts, dm, &Z, &Ydot)); 1873 PetscFunctionReturn(PETSC_SUCCESS); 1874 } 1875 1876 static PetscErrorCode SNESTSFormJacobian_ARKIMEX(SNES snes, Vec X, Mat A, Mat B, TS ts) 1877 { 1878 TS_ARKIMEX *ark = (TS_ARKIMEX *)ts->data; 1879 DM dm, dmsave; 1880 Vec Ydot, Z; 1881 PetscReal shift; 1882 1883 PetscFunctionBegin; 1884 PetscCall(SNESGetDM(snes, &dm)); 1885 PetscCall(TSARKIMEXGetVecs(ts, dm, &Z, &Ydot)); 1886 /* ark->Ydot has already been computed in SNESTSFormFunction_ARKIMEX (SNES guarantees this) */ 1887 dmsave = ts->dm; 1888 ts->dm = dm; 1889 1890 if (ark->scoeff == PETSC_MAX_REAL) { 1891 PetscBool hasZeroRows; 1892 IS alg_is; 1893 1894 /* We are solving F(t_n,x_n,xdot) = 0 to start the method 1895 Jed's proposal is to compute with a very large shift and then scale back the matrix */ 1896 shift = 1.0 / PETSC_MACHINE_EPSILON; 1897 PetscCall(TSComputeIJacobian(ts, ark->stage_time, Z, X, shift, A, B, ark->imex)); 1898 PetscCall(MatScale(B, PETSC_MACHINE_EPSILON)); 1899 /* DAEs need special handling for preconditioning purposes only. 1900 We need to locate the algebraic variables and modify the preconditioning matrix by 1901 calling MatZeroRows with identity on these variables. 1902 We must store the IS in the DM since this function can be called by multilevel solvers. 1903 */ 1904 PetscCall(PetscObjectQuery((PetscObject)dm, "TSARKIMEX_ALG_IS", (PetscObject *)&alg_is)); 1905 if (!alg_is) { 1906 PetscInt m, n; 1907 IS nonzeroRows; 1908 1909 PetscCall(MatViewFromOptions(B, (PetscObject)snes, "-ts_arkimex_alg_mat_view_pre")); 1910 PetscCall(MatFindNonzeroRowsOrCols_Basic(B, PETSC_FALSE, 100 * PETSC_MACHINE_EPSILON, &nonzeroRows)); 1911 if (nonzeroRows) PetscCall(ISViewFromOptions(nonzeroRows, (PetscObject)snes, "-ts_arkimex_alg_is_view_pre")); 1912 PetscCall(MatGetOwnershipRange(B, &m, &n)); 1913 if (nonzeroRows) PetscCall(ISComplement(nonzeroRows, m, n, &alg_is)); 1914 else PetscCall(ISCreateStride(PetscObjectComm((PetscObject)snes), 0, m, 1, &alg_is)); 1915 PetscCall(ISDestroy(&nonzeroRows)); 1916 PetscCall(PetscObjectCompose((PetscObject)dm, "TSARKIMEX_ALG_IS", (PetscObject)alg_is)); 1917 PetscCall(ISDestroy(&alg_is)); 1918 } 1919 PetscCall(PetscObjectQuery((PetscObject)dm, "TSARKIMEX_ALG_IS", (PetscObject *)&alg_is)); 1920 PetscCall(ISViewFromOptions(alg_is, (PetscObject)snes, "-ts_arkimex_alg_is_view")); 1921 PetscCall(MatHasOperation(B, MATOP_ZERO_ROWS, &hasZeroRows)); 1922 if (hasZeroRows) { 1923 /* the default of AIJ is to not keep the pattern! We should probably change it someday */ 1924 PetscCall(MatSetOption(B, MAT_KEEP_NONZERO_PATTERN, PETSC_TRUE)); 1925 PetscCall(MatZeroRowsIS(B, alg_is, 1.0, NULL, NULL)); 1926 } 1927 PetscCall(MatViewFromOptions(B, (PetscObject)snes, "-ts_arkimex_alg_mat_view")); 1928 if (A != B) PetscCall(MatScale(A, PETSC_MACHINE_EPSILON)); 1929 } else { 1930 shift = ark->scoeff / ts->time_step; 1931 PetscCall(TSComputeIJacobian(ts, ark->stage_time, X, Ydot, shift, A, B, ark->imex)); 1932 } 1933 ts->dm = dmsave; 1934 PetscCall(TSARKIMEXRestoreVecs(ts, dm, &Z, &Ydot)); 1935 PetscFunctionReturn(PETSC_SUCCESS); 1936 } 1937 1938 static PetscErrorCode TSGetStages_ARKIMEX(TS ts, PetscInt *ns, Vec *Y[]) 1939 { 1940 TS_ARKIMEX *ark = (TS_ARKIMEX *)ts->data; 1941 1942 PetscFunctionBegin; 1943 if (ns) *ns = ark->tableau->s; 1944 if (Y) *Y = ark->Y; 1945 PetscFunctionReturn(PETSC_SUCCESS); 1946 } 1947 1948 static PetscErrorCode DMCoarsenHook_TSARKIMEX(DM fine, DM coarse, void *ctx) 1949 { 1950 PetscFunctionBegin; 1951 PetscFunctionReturn(PETSC_SUCCESS); 1952 } 1953 1954 static PetscErrorCode DMRestrictHook_TSARKIMEX(DM fine, Mat restrct, Vec rscale, Mat inject, DM coarse, void *ctx) 1955 { 1956 TS ts = (TS)ctx; 1957 Vec Z, Z_c; 1958 1959 PetscFunctionBegin; 1960 PetscCall(TSARKIMEXGetVecs(ts, fine, &Z, NULL)); 1961 PetscCall(TSARKIMEXGetVecs(ts, coarse, &Z_c, NULL)); 1962 PetscCall(MatRestrict(restrct, Z, Z_c)); 1963 PetscCall(VecPointwiseMult(Z_c, rscale, Z_c)); 1964 PetscCall(TSARKIMEXRestoreVecs(ts, fine, &Z, NULL)); 1965 PetscCall(TSARKIMEXRestoreVecs(ts, coarse, &Z_c, NULL)); 1966 PetscFunctionReturn(PETSC_SUCCESS); 1967 } 1968 1969 static PetscErrorCode DMSubDomainHook_TSARKIMEX(DM dm, DM subdm, void *ctx) 1970 { 1971 PetscFunctionBegin; 1972 PetscFunctionReturn(PETSC_SUCCESS); 1973 } 1974 1975 static PetscErrorCode DMSubDomainRestrictHook_TSARKIMEX(DM dm, VecScatter gscat, VecScatter lscat, DM subdm, void *ctx) 1976 { 1977 TS ts = (TS)ctx; 1978 Vec Z, Z_c; 1979 1980 PetscFunctionBegin; 1981 PetscCall(TSARKIMEXGetVecs(ts, dm, &Z, NULL)); 1982 PetscCall(TSARKIMEXGetVecs(ts, subdm, &Z_c, NULL)); 1983 1984 PetscCall(VecScatterBegin(gscat, Z, Z_c, INSERT_VALUES, SCATTER_FORWARD)); 1985 PetscCall(VecScatterEnd(gscat, Z, Z_c, INSERT_VALUES, SCATTER_FORWARD)); 1986 1987 PetscCall(TSARKIMEXRestoreVecs(ts, dm, &Z, NULL)); 1988 PetscCall(TSARKIMEXRestoreVecs(ts, subdm, &Z_c, NULL)); 1989 PetscFunctionReturn(PETSC_SUCCESS); 1990 } 1991 1992 static PetscErrorCode TSARKIMEXTableauSetUp(TS ts) 1993 { 1994 TS_ARKIMEX *ark = (TS_ARKIMEX *)ts->data; 1995 ARKTableau tab = ark->tableau; 1996 1997 PetscFunctionBegin; 1998 PetscCall(PetscMalloc1(2 * tab->s, &ark->work)); 1999 PetscCall(VecDuplicateVecs(ts->vec_sol, tab->s, &ark->Y)); 2000 PetscCall(VecDuplicateVecs(ts->vec_sol, tab->s, &ark->YdotI)); 2001 if (tab->additive) PetscCall(VecDuplicateVecs(ts->vec_sol, tab->s, &ark->YdotRHS)); 2002 if (ark->extrapolate) { 2003 PetscCall(VecDuplicateVecs(ts->vec_sol, tab->s, &ark->Y_prev)); 2004 PetscCall(VecDuplicateVecs(ts->vec_sol, tab->s, &ark->YdotI_prev)); 2005 if (tab->additive) PetscCall(VecDuplicateVecs(ts->vec_sol, tab->s, &ark->YdotRHS_prev)); 2006 } 2007 PetscFunctionReturn(PETSC_SUCCESS); 2008 } 2009 2010 static PetscErrorCode TSSetUp_ARKIMEX(TS ts) 2011 { 2012 TS_ARKIMEX *ark = (TS_ARKIMEX *)ts->data; 2013 DM dm; 2014 SNES snes; 2015 2016 PetscFunctionBegin; 2017 PetscCall(TSARKIMEXTableauSetUp(ts)); 2018 PetscCall(VecDuplicate(ts->vec_sol, &ark->Ydot)); 2019 PetscCall(VecDuplicate(ts->vec_sol, &ark->Ydot0)); 2020 PetscCall(VecDuplicate(ts->vec_sol, &ark->Z)); 2021 PetscCall(TSGetDM(ts, &dm)); 2022 PetscCall(DMCoarsenHookAdd(dm, DMCoarsenHook_TSARKIMEX, DMRestrictHook_TSARKIMEX, ts)); 2023 PetscCall(DMSubDomainHookAdd(dm, DMSubDomainHook_TSARKIMEX, DMSubDomainRestrictHook_TSARKIMEX, ts)); 2024 PetscCall(TSGetSNES(ts, &snes)); 2025 PetscFunctionReturn(PETSC_SUCCESS); 2026 } 2027 2028 static PetscErrorCode TSAdjointSetUp_ARKIMEX(TS ts) 2029 { 2030 TS_ARKIMEX *ark = (TS_ARKIMEX *)ts->data; 2031 ARKTableau tab = ark->tableau; 2032 2033 PetscFunctionBegin; 2034 PetscCall(VecDuplicateVecs(ts->vecs_sensi[0], tab->s * ts->numcost, &ark->VecsDeltaLam)); 2035 PetscCall(VecDuplicateVecs(ts->vecs_sensi[0], ts->numcost, &ark->VecsSensiTemp)); 2036 if (ts->vecs_sensip) { PetscCall(VecDuplicateVecs(ts->vecs_sensip[0], ts->numcost, &ark->VecsSensiPTemp)); } 2037 if (PetscDefined(USE_DEBUG)) { 2038 PetscBool id = PETSC_FALSE; 2039 PetscCall(TSARKIMEXTestMassIdentity(ts, &id)); 2040 PetscCheck(id, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_INCOMP, "Adjoint ARKIMEX requires an identity mass matrix, however the TSIFunctionFn you provided does not utilize an identity mass matrix"); 2041 } 2042 PetscFunctionReturn(PETSC_SUCCESS); 2043 } 2044 2045 static PetscErrorCode TSSetFromOptions_ARKIMEX(TS ts, PetscOptionItems *PetscOptionsObject) 2046 { 2047 TS_ARKIMEX *ark = (TS_ARKIMEX *)ts->data; 2048 PetscBool dirk; 2049 2050 PetscFunctionBegin; 2051 PetscCall(PetscObjectTypeCompare((PetscObject)ts, TSDIRK, &dirk)); 2052 PetscOptionsHeadBegin(PetscOptionsObject, dirk ? "DIRK ODE solver options" : "ARKIMEX ODE solver options"); 2053 { 2054 ARKTableauLink link; 2055 PetscInt count, choice; 2056 PetscBool flg; 2057 const char **namelist; 2058 for (link = ARKTableauList, count = 0; link; link = link->next) { 2059 if (!dirk && link->tab.additive) count++; 2060 if (dirk && !link->tab.additive) count++; 2061 } 2062 PetscCall(PetscMalloc1(count, (char ***)&namelist)); 2063 for (link = ARKTableauList, count = 0; link; link = link->next) { 2064 if (!dirk && link->tab.additive) namelist[count++] = link->tab.name; 2065 if (dirk && !link->tab.additive) namelist[count++] = link->tab.name; 2066 } 2067 if (dirk) { 2068 PetscCall(PetscOptionsEList("-ts_dirk_type", "Family of DIRK method", "TSDIRKSetType", (const char *const *)namelist, count, ark->tableau->name, &choice, &flg)); 2069 if (flg) PetscCall(TSDIRKSetType(ts, namelist[choice])); 2070 } else { 2071 PetscCall(PetscOptionsEList("-ts_arkimex_type", "Family of ARK IMEX method", "TSARKIMEXSetType", (const char *const *)namelist, count, ark->tableau->name, &choice, &flg)); 2072 if (flg) PetscCall(TSARKIMEXSetType(ts, namelist[choice])); 2073 flg = (PetscBool)!ark->imex; 2074 PetscCall(PetscOptionsBool("-ts_arkimex_fully_implicit", "Solve the problem fully implicitly", "TSARKIMEXSetFullyImplicit", flg, &flg, NULL)); 2075 ark->imex = (PetscBool)!flg; 2076 } 2077 PetscCall(PetscFree(namelist)); 2078 PetscCall(PetscOptionsBool("-ts_arkimex_initial_guess_extrapolate", "Extrapolate the initial guess for the stage solution from stage values of the previous time step", "", ark->extrapolate, &ark->extrapolate, NULL)); 2079 } 2080 PetscOptionsHeadEnd(); 2081 PetscFunctionReturn(PETSC_SUCCESS); 2082 } 2083 2084 static PetscErrorCode TSView_ARKIMEX(TS ts, PetscViewer viewer) 2085 { 2086 TS_ARKIMEX *ark = (TS_ARKIMEX *)ts->data; 2087 PetscBool iascii, dirk; 2088 2089 PetscFunctionBegin; 2090 PetscCall(PetscObjectTypeCompare((PetscObject)ts, TSDIRK, &dirk)); 2091 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 2092 if (iascii) { 2093 PetscViewerFormat format; 2094 ARKTableau tab = ark->tableau; 2095 TSARKIMEXType arktype; 2096 char buf[2048]; 2097 PetscBool flg; 2098 2099 PetscCall(TSARKIMEXGetType(ts, &arktype)); 2100 PetscCall(TSARKIMEXGetFullyImplicit(ts, &flg)); 2101 PetscCall(PetscViewerASCIIPrintf(viewer, " %s %s\n", dirk ? "DIRK" : "ARK IMEX", arktype)); 2102 PetscCall(PetscFormatRealArray(buf, sizeof(buf), "% 8.6f", tab->s, tab->ct)); 2103 PetscCall(PetscViewerASCIIPrintf(viewer, " %sabscissa ct = %s\n", dirk ? "" : "Stiff ", buf)); 2104 PetscCall(PetscViewerGetFormat(viewer, &format)); 2105 if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 2106 PetscCall(PetscViewerASCIIPrintf(viewer, " %sAt =\n", dirk ? "" : "Stiff ")); 2107 for (PetscInt i = 0; i < tab->s; i++) { 2108 PetscCall(PetscFormatRealArray(buf, sizeof(buf), "% 8.6f", tab->s, tab->At + i * tab->s)); 2109 PetscCall(PetscViewerASCIIPrintf(viewer, " %s\n", buf)); 2110 } 2111 PetscCall(PetscFormatRealArray(buf, sizeof(buf), "% 8.6f", tab->s, tab->bt)); 2112 PetscCall(PetscViewerASCIIPrintf(viewer, " %sbt = %s\n", dirk ? "" : "Stiff ", buf)); 2113 PetscCall(PetscFormatRealArray(buf, sizeof(buf), "% 8.6f", tab->s, tab->bembedt)); 2114 PetscCall(PetscViewerASCIIPrintf(viewer, " %sbet = %s\n", dirk ? "" : "Stiff ", buf)); 2115 } 2116 PetscCall(PetscViewerASCIIPrintf(viewer, "Fully implicit: %s\n", flg ? "yes" : "no")); 2117 PetscCall(PetscViewerASCIIPrintf(viewer, "Stiffly accurate: %s\n", tab->stiffly_accurate ? "yes" : "no")); 2118 PetscCall(PetscViewerASCIIPrintf(viewer, "Explicit first stage: %s\n", tab->explicit_first_stage ? "yes" : "no")); 2119 PetscCall(PetscViewerASCIIPrintf(viewer, "FSAL property: %s\n", tab->FSAL_implicit ? "yes" : "no")); 2120 if (!dirk) { 2121 PetscCall(PetscFormatRealArray(buf, sizeof(buf), "% 8.6f", tab->s, tab->c)); 2122 PetscCall(PetscViewerASCIIPrintf(viewer, " Nonstiff abscissa c = %s\n", buf)); 2123 } 2124 } 2125 PetscFunctionReturn(PETSC_SUCCESS); 2126 } 2127 2128 static PetscErrorCode TSLoad_ARKIMEX(TS ts, PetscViewer viewer) 2129 { 2130 SNES snes; 2131 TSAdapt adapt; 2132 2133 PetscFunctionBegin; 2134 PetscCall(TSGetAdapt(ts, &adapt)); 2135 PetscCall(TSAdaptLoad(adapt, viewer)); 2136 PetscCall(TSGetSNES(ts, &snes)); 2137 PetscCall(SNESLoad(snes, viewer)); 2138 /* function and Jacobian context for SNES when used with TS is always ts object */ 2139 PetscCall(SNESSetFunction(snes, NULL, NULL, ts)); 2140 PetscCall(SNESSetJacobian(snes, NULL, NULL, NULL, ts)); 2141 PetscFunctionReturn(PETSC_SUCCESS); 2142 } 2143 2144 /*@ 2145 TSARKIMEXSetType - Set the type of `TSARKIMEX` scheme 2146 2147 Logically Collective 2148 2149 Input Parameters: 2150 + ts - timestepping context 2151 - arktype - type of `TSARKIMEX` scheme 2152 2153 Options Database Key: 2154 . -ts_arkimex_type <1bee,a2,l2,ars122,2c,2d,2e,prssp2,3,bpr3,ars443,4,5> - set `TSARKIMEX` scheme type 2155 2156 Level: intermediate 2157 2158 .seealso: [](ch_ts), `TSARKIMEXGetType()`, `TSARKIMEX`, `TSARKIMEXType`, `TSARKIMEX1BEE`, `TSARKIMEXA2`, `TSARKIMEXL2`, `TSARKIMEXARS122`, `TSARKIMEX2C`, `TSARKIMEX2D`, `TSARKIMEX2E`, `TSARKIMEXPRSSP2`, 2159 `TSARKIMEX3`, `TSARKIMEXBPR3`, `TSARKIMEXARS443`, `TSARKIMEX4`, `TSARKIMEX5` 2160 @*/ 2161 PetscErrorCode TSARKIMEXSetType(TS ts, TSARKIMEXType arktype) 2162 { 2163 PetscFunctionBegin; 2164 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2165 PetscAssertPointer(arktype, 2); 2166 PetscTryMethod(ts, "TSARKIMEXSetType_C", (TS, TSARKIMEXType), (ts, arktype)); 2167 PetscFunctionReturn(PETSC_SUCCESS); 2168 } 2169 2170 /*@ 2171 TSARKIMEXGetType - Get the type of `TSARKIMEX` scheme 2172 2173 Logically Collective 2174 2175 Input Parameter: 2176 . ts - timestepping context 2177 2178 Output Parameter: 2179 . arktype - type of `TSARKIMEX` scheme 2180 2181 Level: intermediate 2182 2183 .seealso: [](ch_ts), `TSARKIMEXc` 2184 @*/ 2185 PetscErrorCode TSARKIMEXGetType(TS ts, TSARKIMEXType *arktype) 2186 { 2187 PetscFunctionBegin; 2188 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2189 PetscUseMethod(ts, "TSARKIMEXGetType_C", (TS, TSARKIMEXType *), (ts, arktype)); 2190 PetscFunctionReturn(PETSC_SUCCESS); 2191 } 2192 2193 /*@ 2194 TSARKIMEXSetFullyImplicit - Solve both parts of the equation implicitly, including the part that is normally solved explicitly 2195 2196 Logically Collective 2197 2198 Input Parameters: 2199 + ts - timestepping context 2200 - flg - `PETSC_TRUE` for fully implicit 2201 2202 Level: intermediate 2203 2204 .seealso: [](ch_ts), `TSARKIMEX`, `TSARKIMEXGetType()`, `TSARKIMEXGetFullyImplicit()` 2205 @*/ 2206 PetscErrorCode TSARKIMEXSetFullyImplicit(TS ts, PetscBool flg) 2207 { 2208 PetscFunctionBegin; 2209 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2210 PetscValidLogicalCollectiveBool(ts, flg, 2); 2211 PetscTryMethod(ts, "TSARKIMEXSetFullyImplicit_C", (TS, PetscBool), (ts, flg)); 2212 PetscFunctionReturn(PETSC_SUCCESS); 2213 } 2214 2215 /*@ 2216 TSARKIMEXGetFullyImplicit - Inquires if both parts of the equation are solved implicitly 2217 2218 Logically Collective 2219 2220 Input Parameter: 2221 . ts - timestepping context 2222 2223 Output Parameter: 2224 . flg - `PETSC_TRUE` for fully implicit 2225 2226 Level: intermediate 2227 2228 .seealso: [](ch_ts), `TSARKIMEXGetType()`, `TSARKIMEXSetFullyImplicit()` 2229 @*/ 2230 PetscErrorCode TSARKIMEXGetFullyImplicit(TS ts, PetscBool *flg) 2231 { 2232 PetscFunctionBegin; 2233 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2234 PetscAssertPointer(flg, 2); 2235 PetscUseMethod(ts, "TSARKIMEXGetFullyImplicit_C", (TS, PetscBool *), (ts, flg)); 2236 PetscFunctionReturn(PETSC_SUCCESS); 2237 } 2238 2239 static PetscErrorCode TSARKIMEXGetType_ARKIMEX(TS ts, TSARKIMEXType *arktype) 2240 { 2241 TS_ARKIMEX *ark = (TS_ARKIMEX *)ts->data; 2242 2243 PetscFunctionBegin; 2244 *arktype = ark->tableau->name; 2245 PetscFunctionReturn(PETSC_SUCCESS); 2246 } 2247 2248 static PetscErrorCode TSARKIMEXSetType_ARKIMEX(TS ts, TSARKIMEXType arktype) 2249 { 2250 TS_ARKIMEX *ark = (TS_ARKIMEX *)ts->data; 2251 PetscBool match; 2252 ARKTableauLink link; 2253 2254 PetscFunctionBegin; 2255 if (ark->tableau) { 2256 PetscCall(PetscStrcmp(ark->tableau->name, arktype, &match)); 2257 if (match) PetscFunctionReturn(PETSC_SUCCESS); 2258 } 2259 for (link = ARKTableauList; link; link = link->next) { 2260 PetscCall(PetscStrcmp(link->tab.name, arktype, &match)); 2261 if (match) { 2262 if (ts->setupcalled) PetscCall(TSARKIMEXTableauReset(ts)); 2263 ark->tableau = &link->tab; 2264 if (ts->setupcalled) PetscCall(TSARKIMEXTableauSetUp(ts)); 2265 ts->default_adapt_type = ark->tableau->bembed ? TSADAPTBASIC : TSADAPTNONE; 2266 PetscFunctionReturn(PETSC_SUCCESS); 2267 } 2268 } 2269 SETERRQ(PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_UNKNOWN_TYPE, "Could not find '%s'", arktype); 2270 } 2271 2272 static PetscErrorCode TSARKIMEXSetFullyImplicit_ARKIMEX(TS ts, PetscBool flg) 2273 { 2274 TS_ARKIMEX *ark = (TS_ARKIMEX *)ts->data; 2275 2276 PetscFunctionBegin; 2277 ark->imex = (PetscBool)!flg; 2278 PetscFunctionReturn(PETSC_SUCCESS); 2279 } 2280 2281 static PetscErrorCode TSARKIMEXGetFullyImplicit_ARKIMEX(TS ts, PetscBool *flg) 2282 { 2283 TS_ARKIMEX *ark = (TS_ARKIMEX *)ts->data; 2284 2285 PetscFunctionBegin; 2286 *flg = (PetscBool)!ark->imex; 2287 PetscFunctionReturn(PETSC_SUCCESS); 2288 } 2289 2290 static PetscErrorCode TSDestroy_ARKIMEX(TS ts) 2291 { 2292 PetscFunctionBegin; 2293 PetscCall(TSReset_ARKIMEX(ts)); 2294 if (ts->dm) { 2295 PetscCall(DMCoarsenHookRemove(ts->dm, DMCoarsenHook_TSARKIMEX, DMRestrictHook_TSARKIMEX, ts)); 2296 PetscCall(DMSubDomainHookRemove(ts->dm, DMSubDomainHook_TSARKIMEX, DMSubDomainRestrictHook_TSARKIMEX, ts)); 2297 } 2298 PetscCall(PetscFree(ts->data)); 2299 PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSDIRKGetType_C", NULL)); 2300 PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSDIRKSetType_C", NULL)); 2301 PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSARKIMEXGetType_C", NULL)); 2302 PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSARKIMEXSetType_C", NULL)); 2303 PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSARKIMEXSetFullyImplicit_C", NULL)); 2304 PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSARKIMEXGetFullyImplicit_C", NULL)); 2305 PetscFunctionReturn(PETSC_SUCCESS); 2306 } 2307 2308 /* ------------------------------------------------------------ */ 2309 /*MC 2310 TSARKIMEX - ODE and DAE solver using additive Runge-Kutta IMEX schemes 2311 2312 These methods are intended for problems with well-separated time scales, especially when a slow scale is strongly 2313 nonlinear such that it is expensive to solve with a fully implicit method. The user should provide the stiff part 2314 of the equation using `TSSetIFunction()` and the non-stiff part with `TSSetRHSFunction()`. 2315 2316 Level: beginner 2317 2318 Notes: 2319 The default is `TSARKIMEX3`, it can be changed with `TSARKIMEXSetType()` or -ts_arkimex_type 2320 2321 If the equation is implicit or a DAE, then `TSSetEquationType()` needs to be set accordingly. Refer to the manual for further information. 2322 2323 Methods with an explicit stage can only be used with ODE in which the stiff part G(t,X,Xdot) has the form Xdot + Ghat(t,X). 2324 2325 Consider trying `TSROSW` if the stiff part is linear or weakly nonlinear. 2326 2327 .seealso: [](ch_ts), `TSCreate()`, `TS`, `TSSetType()`, `TSARKIMEXSetType()`, `TSARKIMEXGetType()`, `TSARKIMEXSetFullyImplicit()`, `TSARKIMEXGetFullyImplicit()`, 2328 `TSARKIMEX1BEE`, `TSARKIMEX2C`, `TSARKIMEX2D`, `TSARKIMEX2E`, `TSARKIMEX3`, `TSARKIMEXL2`, `TSARKIMEXA2`, `TSARKIMEXARS122`, 2329 `TSARKIMEX4`, `TSARKIMEX5`, `TSARKIMEXPRSSP2`, `TSARKIMEXARS443`, `TSARKIMEXBPR3`, `TSARKIMEXType`, `TSARKIMEXRegister()`, `TSType` 2330 M*/ 2331 PETSC_EXTERN PetscErrorCode TSCreate_ARKIMEX(TS ts) 2332 { 2333 TS_ARKIMEX *ark; 2334 PetscBool dirk; 2335 2336 PetscFunctionBegin; 2337 PetscCall(TSARKIMEXInitializePackage()); 2338 PetscCall(PetscObjectTypeCompare((PetscObject)ts, TSDIRK, &dirk)); 2339 2340 ts->ops->reset = TSReset_ARKIMEX; 2341 ts->ops->adjointreset = TSAdjointReset_ARKIMEX; 2342 ts->ops->destroy = TSDestroy_ARKIMEX; 2343 ts->ops->view = TSView_ARKIMEX; 2344 ts->ops->load = TSLoad_ARKIMEX; 2345 ts->ops->setup = TSSetUp_ARKIMEX; 2346 ts->ops->adjointsetup = TSAdjointSetUp_ARKIMEX; 2347 ts->ops->step = TSStep_ARKIMEX; 2348 ts->ops->interpolate = TSInterpolate_ARKIMEX; 2349 ts->ops->evaluatestep = TSEvaluateStep_ARKIMEX; 2350 ts->ops->setfromoptions = TSSetFromOptions_ARKIMEX; 2351 ts->ops->snesfunction = SNESTSFormFunction_ARKIMEX; 2352 ts->ops->snesjacobian = SNESTSFormJacobian_ARKIMEX; 2353 ts->ops->getstages = TSGetStages_ARKIMEX; 2354 ts->ops->adjointstep = TSAdjointStep_ARKIMEX; 2355 2356 ts->usessnes = PETSC_TRUE; 2357 2358 PetscCall(PetscNew(&ark)); 2359 ts->data = (void *)ark; 2360 ark->imex = dirk ? PETSC_FALSE : PETSC_TRUE; 2361 2362 ark->VecsDeltaLam = NULL; 2363 ark->VecsSensiTemp = NULL; 2364 ark->VecsSensiPTemp = NULL; 2365 2366 PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSARKIMEXGetType_C", TSARKIMEXGetType_ARKIMEX)); 2367 PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSARKIMEXGetFullyImplicit_C", TSARKIMEXGetFullyImplicit_ARKIMEX)); 2368 if (!dirk) { 2369 PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSARKIMEXSetType_C", TSARKIMEXSetType_ARKIMEX)); 2370 PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSARKIMEXSetFullyImplicit_C", TSARKIMEXSetFullyImplicit_ARKIMEX)); 2371 PetscCall(TSARKIMEXSetType(ts, TSARKIMEXDefault)); 2372 } 2373 PetscFunctionReturn(PETSC_SUCCESS); 2374 } 2375 2376 /* ------------------------------------------------------------ */ 2377 2378 static PetscErrorCode TSDIRKSetType_DIRK(TS ts, TSDIRKType dirktype) 2379 { 2380 TS_ARKIMEX *ark = (TS_ARKIMEX *)ts->data; 2381 2382 PetscFunctionBegin; 2383 PetscCall(TSARKIMEXSetType_ARKIMEX(ts, dirktype)); 2384 PetscCheck(!ark->tableau->additive, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Method \"%s\" is not DIRK", dirktype); 2385 PetscFunctionReturn(PETSC_SUCCESS); 2386 } 2387 2388 /*@ 2389 TSDIRKSetType - Set the type of `TSDIRK` scheme 2390 2391 Logically Collective 2392 2393 Input Parameters: 2394 + ts - timestepping context 2395 - dirktype - type of `TSDIRK` scheme 2396 2397 Options Database Key: 2398 . -ts_dirkimex_type - set `TSDIRK` scheme type 2399 2400 Level: intermediate 2401 2402 .seealso: [](ch_ts), `TSDIRKGetType()`, `TSDIRK`, `TSDIRKType` 2403 @*/ 2404 PetscErrorCode TSDIRKSetType(TS ts, TSDIRKType dirktype) 2405 { 2406 PetscFunctionBegin; 2407 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2408 PetscAssertPointer(dirktype, 2); 2409 PetscTryMethod(ts, "TSDIRKSetType_C", (TS, TSDIRKType), (ts, dirktype)); 2410 PetscFunctionReturn(PETSC_SUCCESS); 2411 } 2412 2413 /*@ 2414 TSDIRKGetType - Get the type of `TSDIRK` scheme 2415 2416 Logically Collective 2417 2418 Input Parameter: 2419 . ts - timestepping context 2420 2421 Output Parameter: 2422 . dirktype - type of `TSDIRK` scheme 2423 2424 Level: intermediate 2425 2426 .seealso: [](ch_ts), `TSDIRKSetType()` 2427 @*/ 2428 PetscErrorCode TSDIRKGetType(TS ts, TSDIRKType *dirktype) 2429 { 2430 PetscFunctionBegin; 2431 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2432 PetscUseMethod(ts, "TSDIRKGetType_C", (TS, TSDIRKType *), (ts, dirktype)); 2433 PetscFunctionReturn(PETSC_SUCCESS); 2434 } 2435 2436 /*MC 2437 TSDIRK - ODE and DAE solver using Diagonally implicit Runge-Kutta schemes. 2438 2439 Level: beginner 2440 2441 Notes: 2442 The default is `TSDIRKES213SAL`, it can be changed with `TSDIRKSetType()` or -ts_dirk_type. 2443 The convention used in PETSc to name the DIRK methods is TSDIRK[E][S]PQS[SA][L][A] with: 2444 + E - whether the method has an explicit first stage 2445 . S - whether the method is single diagonal 2446 . P - order of the advancing method 2447 . Q - order of the embedded method 2448 . S - number of stages 2449 . SA - whether the method is stiffly accurate 2450 . L - whether the method is L-stable 2451 - A - whether the method is A-stable 2452 2453 .seealso: [](ch_ts), `TSCreate()`, `TS`, `TSSetType()`, `TSDIRKSetType()`, `TSDIRKGetType()`, `TSDIRKRegister()`. 2454 M*/ 2455 PETSC_EXTERN PetscErrorCode TSCreate_DIRK(TS ts) 2456 { 2457 PetscFunctionBegin; 2458 PetscCall(TSCreate_ARKIMEX(ts)); 2459 PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSDIRKGetType_C", TSARKIMEXGetType_ARKIMEX)); 2460 PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSDIRKSetType_C", TSDIRKSetType_DIRK)); 2461 PetscCall(TSDIRKSetType(ts, TSDIRKDefault)); 2462 PetscFunctionReturn(PETSC_SUCCESS); 2463 } 2464