1 /* 2 Code for timestepping with Rosenbrock W methods 3 4 Notes: 5 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 This method is designed to be linearly implicit on F and can use an approximate and lagged Jacobian. 11 12 */ 13 #include <petsc/private/tsimpl.h> /*I "petscts.h" I*/ 14 #include <petscdm.h> 15 16 #include <petsc/private/kernels/blockinvert.h> 17 18 static TSRosWType TSRosWDefault = TSROSWRA34PW2; 19 static PetscBool TSRosWRegisterAllCalled; 20 static PetscBool TSRosWPackageInitialized; 21 22 typedef struct _RosWTableau *RosWTableau; 23 struct _RosWTableau { 24 char *name; 25 PetscInt order; /* Classical approximation order of the method */ 26 PetscInt s; /* Number of stages */ 27 PetscInt pinterp; /* Interpolation order */ 28 PetscReal *A; /* Propagation table, strictly lower triangular */ 29 PetscReal *Gamma; /* Stage table, lower triangular with nonzero diagonal */ 30 PetscBool *GammaZeroDiag; /* Diagonal entries that are zero in stage table Gamma, vector indicating explicit statages */ 31 PetscReal *GammaExplicitCorr; /* Coefficients for correction terms needed for explicit stages in transformed variables*/ 32 PetscReal *b; /* Step completion table */ 33 PetscReal *bembed; /* Step completion table for embedded method of order one less */ 34 PetscReal *ASum; /* Row sum of A */ 35 PetscReal *GammaSum; /* Row sum of Gamma, only needed for non-autonomous systems */ 36 PetscReal *At; /* Propagation table in transformed variables */ 37 PetscReal *bt; /* Step completion table in transformed variables */ 38 PetscReal *bembedt; /* Step completion table of order one less in transformed variables */ 39 PetscReal *GammaInv; /* Inverse of Gamma, used for transformed variables */ 40 PetscReal ccfl; /* Placeholder for CFL coefficient relative to forward Euler */ 41 PetscReal *binterpt; /* Dense output formula */ 42 }; 43 typedef struct _RosWTableauLink *RosWTableauLink; 44 struct _RosWTableauLink { 45 struct _RosWTableau tab; 46 RosWTableauLink next; 47 }; 48 static RosWTableauLink RosWTableauList; 49 50 typedef struct { 51 RosWTableau tableau; 52 Vec *Y; /* States computed during the step, used to complete the step */ 53 Vec Ydot; /* Work vector holding Ydot during residual evaluation */ 54 Vec Ystage; /* Work vector for the state value at each stage */ 55 Vec Zdot; /* Ydot = Zdot + shift*Y */ 56 Vec Zstage; /* Y = Zstage + Y */ 57 Vec vec_sol_prev; /* Solution from the previous step (used for interpolation and rollback)*/ 58 PetscScalar *work; /* Scalar work space of length number of stages, used to prepare VecMAXPY() */ 59 PetscReal scoeff; /* shift = scoeff/dt */ 60 PetscReal stage_time; 61 PetscReal stage_explicit; /* Flag indicates that the current stage is explicit */ 62 PetscBool recompute_jacobian; /* Recompute the Jacobian at each stage, default is to freeze the Jacobian at the start of each step */ 63 TSStepStatus status; 64 } TS_RosW; 65 66 /*MC 67 TSROSWTHETA1 - One stage first order L-stable Rosenbrock-W scheme (aka theta method). 68 69 Only an approximate Jacobian is needed. 70 71 Level: intermediate 72 73 .seealso: TSROSW 74 M*/ 75 76 /*MC 77 TSROSWTHETA2 - One stage second order A-stable Rosenbrock-W scheme (aka theta method). 78 79 Only an approximate Jacobian is needed. 80 81 Level: intermediate 82 83 .seealso: TSROSW 84 M*/ 85 86 /*MC 87 TSROSW2M - Two stage second order L-stable Rosenbrock-W scheme. 88 89 Only an approximate Jacobian is needed. By default, it is only recomputed once per step. This method is a reflection of TSROSW2P. 90 91 Level: intermediate 92 93 .seealso: TSROSW 94 M*/ 95 96 /*MC 97 TSROSW2P - Two stage second order L-stable Rosenbrock-W scheme. 98 99 Only an approximate Jacobian is needed. By default, it is only recomputed once per step. This method is a reflection of TSROSW2M. 100 101 Level: intermediate 102 103 .seealso: TSROSW 104 M*/ 105 106 /*MC 107 TSROSWRA3PW - Three stage third order Rosenbrock-W scheme for PDAE of index 1. 108 109 Only an approximate Jacobian is needed. By default, it is only recomputed once per step. 110 111 This is strongly A-stable with R(infty) = 0.73. The embedded method of order 2 is strongly A-stable with R(infty) = 0.73. 112 113 References: 114 . 1. - Rang and Angermann, New Rosenbrock W methods of order 3 for partial differential algebraic equations of index 1, 2005. 115 116 Level: intermediate 117 118 .seealso: TSROSW 119 M*/ 120 121 /*MC 122 TSROSWRA34PW2 - Four stage third order L-stable Rosenbrock-W scheme for PDAE of index 1. 123 124 Only an approximate Jacobian is needed. By default, it is only recomputed once per step. 125 126 This is strongly A-stable with R(infty) = 0. The embedded method of order 2 is strongly A-stable with R(infty) = 0.48. 127 128 References: 129 . 1. - Rang and Angermann, New Rosenbrock W methods of order 3 for partial differential algebraic equations of index 1, 2005. 130 131 Level: intermediate 132 133 .seealso: TSROSW 134 M*/ 135 136 /*MC 137 TSROSWRODAS3 - Four stage third order L-stable Rosenbrock scheme 138 139 By default, the Jacobian is only recomputed once per step. 140 141 Both the third order and embedded second order methods are stiffly accurate and L-stable. 142 143 References: 144 . 1. - Sandu et al, Benchmarking stiff ODE solvers for atmospheric chemistry problems II, Rosenbrock solvers, 1997. 145 146 Level: intermediate 147 148 .seealso: TSROSW, TSROSWSANDU3 149 M*/ 150 151 /*MC 152 TSROSWSANDU3 - Three stage third order L-stable Rosenbrock scheme 153 154 By default, the Jacobian is only recomputed once per step. 155 156 The third order method is L-stable, but not stiffly accurate. 157 The second order embedded method is strongly A-stable with R(infty) = 0.5. 158 The internal stages are L-stable. 159 This method is called ROS3 in the paper. 160 161 References: 162 . 1. - Sandu et al, Benchmarking stiff ODE solvers for atmospheric chemistry problems II, Rosenbrock solvers, 1997. 163 164 Level: intermediate 165 166 .seealso: TSROSW, TSROSWRODAS3 167 M*/ 168 169 /*MC 170 TSROSWASSP3P3S1C - A-stable Rosenbrock-W method with SSP explicit part, third order, three stages 171 172 By default, the Jacobian is only recomputed once per step. 173 174 A-stable SPP explicit order 3, 3 stages, CFL 1 (eff = 1/3) 175 176 References: 177 . Emil Constantinescu 178 179 Level: intermediate 180 181 .seealso: TSROSW, TSROSWLASSP3P4S2C, TSROSWLLSSP3P4S2C, SSP 182 M*/ 183 184 /*MC 185 TSROSWLASSP3P4S2C - L-stable Rosenbrock-W method with SSP explicit part, third order, four stages 186 187 By default, the Jacobian is only recomputed once per step. 188 189 L-stable (A-stable embedded) SPP explicit order 3, 4 stages, CFL 2 (eff = 1/2) 190 191 References: 192 . Emil Constantinescu 193 194 Level: intermediate 195 196 .seealso: TSROSW, TSROSWASSP3P3S1C, TSROSWLLSSP3P4S2C, TSSSP 197 M*/ 198 199 /*MC 200 TSROSWLLSSP3P4S2C - L-stable Rosenbrock-W method with SSP explicit part, third order, four stages 201 202 By default, the Jacobian is only recomputed once per step. 203 204 L-stable (L-stable embedded) SPP explicit order 3, 4 stages, CFL 2 (eff = 1/2) 205 206 References: 207 . Emil Constantinescu 208 209 Level: intermediate 210 211 .seealso: TSROSW, TSROSWASSP3P3S1C, TSROSWLASSP3P4S2C, TSSSP 212 M*/ 213 214 /*MC 215 TSROSWGRK4T - four stage, fourth order Rosenbrock (not W) method from Kaps and Rentrop 216 217 By default, the Jacobian is only recomputed once per step. 218 219 A(89.3 degrees)-stable, |R(infty)| = 0.454. 220 221 This method does not provide a dense output formula. 222 223 References: 224 + 1. - Kaps and Rentrop, Generalized Runge Kutta methods of order four with stepsize control for stiff ordinary differential equations, 1979. 225 - 2. - Hairer and Wanner, Solving Ordinary Differential Equations II, Section 4 Table 7.2. 226 227 Hairer's code ros4.f 228 229 Level: intermediate 230 231 .seealso: TSROSW, TSROSWSHAMP4, TSROSWVELDD4, TSROSW4L 232 M*/ 233 234 /*MC 235 TSROSWSHAMP4 - four stage, fourth order Rosenbrock (not W) method from Shampine 236 237 By default, the Jacobian is only recomputed once per step. 238 239 A-stable, |R(infty)| = 1/3. 240 241 This method does not provide a dense output formula. 242 243 References: 244 + 1. - Shampine, Implementation of Rosenbrock methods, 1982. 245 - 2. - Hairer and Wanner, Solving Ordinary Differential Equations II, Section 4 Table 7.2. 246 247 Hairer's code ros4.f 248 249 Level: intermediate 250 251 .seealso: TSROSW, TSROSWGRK4T, TSROSWVELDD4, TSROSW4L 252 M*/ 253 254 /*MC 255 TSROSWVELDD4 - four stage, fourth order Rosenbrock (not W) method from van Veldhuizen 256 257 By default, the Jacobian is only recomputed once per step. 258 259 A(89.5 degrees)-stable, |R(infty)| = 0.24. 260 261 This method does not provide a dense output formula. 262 263 References: 264 + 1. - van Veldhuizen, D stability and Kaps Rentrop methods, 1984. 265 - 2. - Hairer and Wanner, Solving Ordinary Differential Equations II, Section 4 Table 7.2. 266 267 Hairer's code ros4.f 268 269 Level: intermediate 270 271 .seealso: TSROSW, TSROSWGRK4T, TSROSWSHAMP4, TSROSW4L 272 M*/ 273 274 /*MC 275 TSROSW4L - four stage, fourth order Rosenbrock (not W) method 276 277 By default, the Jacobian is only recomputed once per step. 278 279 A-stable and L-stable 280 281 This method does not provide a dense output formula. 282 283 References: 284 . 1. - Hairer and Wanner, Solving Ordinary Differential Equations II, Section 4 Table 7.2. 285 286 Hairer's code ros4.f 287 288 Level: intermediate 289 290 .seealso: TSROSW, TSROSWGRK4T, TSROSWSHAMP4, TSROSW4L 291 M*/ 292 293 /*@C 294 TSRosWRegisterAll - Registers all of the Rosenbrock-W methods in TSRosW 295 296 Not Collective, but should be called by all processes which will need the schemes to be registered 297 298 Level: advanced 299 300 .keywords: TS, TSRosW, register, all 301 302 .seealso: TSRosWRegisterDestroy() 303 @*/ 304 PetscErrorCode TSRosWRegisterAll(void) 305 { 306 PetscErrorCode ierr; 307 308 PetscFunctionBegin; 309 if (TSRosWRegisterAllCalled) PetscFunctionReturn(0); 310 TSRosWRegisterAllCalled = PETSC_TRUE; 311 312 { 313 const PetscReal A = 0; 314 const PetscReal Gamma = 1; 315 const PetscReal b = 1; 316 const PetscReal binterpt=1; 317 318 ierr = TSRosWRegister(TSROSWTHETA1,1,1,&A,&Gamma,&b,NULL,1,&binterpt);CHKERRQ(ierr); 319 } 320 321 { 322 const PetscReal A = 0; 323 const PetscReal Gamma = 0.5; 324 const PetscReal b = 1; 325 const PetscReal binterpt=1; 326 327 ierr = TSRosWRegister(TSROSWTHETA2,2,1,&A,&Gamma,&b,NULL,1,&binterpt);CHKERRQ(ierr); 328 } 329 330 { 331 /*const PetscReal g = 1. + 1./PetscSqrtReal(2.0); Direct evaluation: 1.707106781186547524401. Used for setting up arrays of values known at compile time below. */ 332 const PetscReal 333 A[2][2] = {{0,0}, {1.,0}}, 334 Gamma[2][2] = {{1.707106781186547524401,0}, {-2.*1.707106781186547524401,1.707106781186547524401}}, 335 b[2] = {0.5,0.5}, 336 b1[2] = {1.0,0.0}; 337 PetscReal binterpt[2][2]; 338 binterpt[0][0] = 1.707106781186547524401 - 1.0; 339 binterpt[1][0] = 2.0 - 1.707106781186547524401; 340 binterpt[0][1] = 1.707106781186547524401 - 1.5; 341 binterpt[1][1] = 1.5 - 1.707106781186547524401; 342 343 ierr = TSRosWRegister(TSROSW2P,2,2,&A[0][0],&Gamma[0][0],b,b1,2,&binterpt[0][0]);CHKERRQ(ierr); 344 } 345 { 346 /*const PetscReal g = 1. - 1./PetscSqrtReal(2.0); Direct evaluation: 0.2928932188134524755992. Used for setting up arrays of values known at compile time below. */ 347 const PetscReal 348 A[2][2] = {{0,0}, {1.,0}}, 349 Gamma[2][2] = {{0.2928932188134524755992,0}, {-2.*0.2928932188134524755992,0.2928932188134524755992}}, 350 b[2] = {0.5,0.5}, 351 b1[2] = {1.0,0.0}; 352 PetscReal binterpt[2][2]; 353 binterpt[0][0] = 0.2928932188134524755992 - 1.0; 354 binterpt[1][0] = 2.0 - 0.2928932188134524755992; 355 binterpt[0][1] = 0.2928932188134524755992 - 1.5; 356 binterpt[1][1] = 1.5 - 0.2928932188134524755992; 357 358 ierr = TSRosWRegister(TSROSW2M,2,2,&A[0][0],&Gamma[0][0],b,b1,2,&binterpt[0][0]);CHKERRQ(ierr); 359 } 360 { 361 /*const PetscReal g = 7.8867513459481287e-01; Directly written in-place below */ 362 PetscReal binterpt[3][2]; 363 const PetscReal 364 A[3][3] = {{0,0,0}, 365 {1.5773502691896257e+00,0,0}, 366 {0.5,0,0}}, 367 Gamma[3][3] = {{7.8867513459481287e-01,0,0}, 368 {-1.5773502691896257e+00,7.8867513459481287e-01,0}, 369 {-6.7075317547305480e-01,-1.7075317547305482e-01,7.8867513459481287e-01}}, 370 b[3] = {1.0566243270259355e-01,4.9038105676657971e-02,8.4529946162074843e-01}, 371 b2[3] = {-1.7863279495408180e-01,1./3.,8.4529946162074843e-01}; 372 373 binterpt[0][0] = -0.8094010767585034; 374 binterpt[1][0] = -0.5; 375 binterpt[2][0] = 2.3094010767585034; 376 binterpt[0][1] = 0.9641016151377548; 377 binterpt[1][1] = 0.5; 378 binterpt[2][1] = -1.4641016151377548; 379 380 ierr = TSRosWRegister(TSROSWRA3PW,3,3,&A[0][0],&Gamma[0][0],b,b2,2,&binterpt[0][0]);CHKERRQ(ierr); 381 } 382 { 383 PetscReal binterpt[4][3]; 384 /*const PetscReal g = 4.3586652150845900e-01; Directly written in-place below */ 385 const PetscReal 386 A[4][4] = {{0,0,0,0}, 387 {8.7173304301691801e-01,0,0,0}, 388 {8.4457060015369423e-01,-1.1299064236484185e-01,0,0}, 389 {0,0,1.,0}}, 390 Gamma[4][4] = {{4.3586652150845900e-01,0,0,0}, 391 {-8.7173304301691801e-01,4.3586652150845900e-01,0,0}, 392 {-9.0338057013044082e-01,5.4180672388095326e-02,4.3586652150845900e-01,0}, 393 {2.4212380706095346e-01,-1.2232505839045147e+00,5.4526025533510214e-01,4.3586652150845900e-01}}, 394 b[4] = {2.4212380706095346e-01,-1.2232505839045147e+00,1.5452602553351020e+00,4.3586652150845900e-01}, 395 b2[4] = {3.7810903145819369e-01,-9.6042292212423178e-02,5.0000000000000000e-01,2.1793326075422950e-01}; 396 397 binterpt[0][0]=1.0564298455794094; 398 binterpt[1][0]=2.296429974281067; 399 binterpt[2][0]=-1.307599564525376; 400 binterpt[3][0]=-1.045260255335102; 401 binterpt[0][1]=-1.3864882699759573; 402 binterpt[1][1]=-8.262611700275677; 403 binterpt[2][1]=7.250979895056055; 404 binterpt[3][1]=2.398120075195581; 405 binterpt[0][2]=0.5721822314575016; 406 binterpt[1][2]=4.742931142090097; 407 binterpt[2][2]=-4.398120075195578; 408 binterpt[3][2]=-0.9169932983520199; 409 410 ierr = TSRosWRegister(TSROSWRA34PW2,3,4,&A[0][0],&Gamma[0][0],b,b2,3,&binterpt[0][0]);CHKERRQ(ierr); 411 } 412 { 413 /* const PetscReal g = 0.5; Directly written in-place below */ 414 const PetscReal 415 A[4][4] = {{0,0,0,0}, 416 {0,0,0,0}, 417 {1.,0,0,0}, 418 {0.75,-0.25,0.5,0}}, 419 Gamma[4][4] = {{0.5,0,0,0}, 420 {1.,0.5,0,0}, 421 {-0.25,-0.25,0.5,0}, 422 {1./12,1./12,-2./3,0.5}}, 423 b[4] = {5./6,-1./6,-1./6,0.5}, 424 b2[4] = {0.75,-0.25,0.5,0}; 425 426 ierr = TSRosWRegister(TSROSWRODAS3,3,4,&A[0][0],&Gamma[0][0],b,b2,0,NULL);CHKERRQ(ierr); 427 } 428 { 429 /*const PetscReal g = 0.43586652150845899941601945119356; Directly written in-place below */ 430 const PetscReal 431 A[3][3] = {{0,0,0}, 432 {0.43586652150845899941601945119356,0,0}, 433 {0.43586652150845899941601945119356,0,0}}, 434 Gamma[3][3] = {{0.43586652150845899941601945119356,0,0}, 435 {-0.19294655696029095575009695436041,0.43586652150845899941601945119356,0}, 436 {0,1.74927148125794685173529749738960,0.43586652150845899941601945119356}}, 437 b[3] = {-0.75457412385404315829818998646589,1.94100407061964420292840123379419,-0.18642994676560104463021124732829}, 438 b2[3] = {-1.53358745784149585370766523913002,2.81745131148625772213931745457622,-0.28386385364476186843165221544619}; 439 440 PetscReal binterpt[3][2]; 441 binterpt[0][0] = 3.793692883777660870425141387941; 442 binterpt[1][0] = -2.918692883777660870425141387941; 443 binterpt[2][0] = 0.125; 444 binterpt[0][1] = -0.725741064379812106687651020584; 445 binterpt[1][1] = 0.559074397713145440020984353917; 446 binterpt[2][1] = 0.16666666666666666666666666666667; 447 448 ierr = TSRosWRegister(TSROSWSANDU3,3,3,&A[0][0],&Gamma[0][0],b,b2,2,&binterpt[0][0]);CHKERRQ(ierr); 449 } 450 { 451 /*const PetscReal s3 = PetscSqrtReal(3.),g = (3.0+s3)/6.0; 452 * Direct evaluation: s3 = 1.732050807568877293527; 453 * g = 0.7886751345948128822546; 454 * Values are directly inserted below to ensure availability at compile time (compiler warnings otherwise...) */ 455 const PetscReal 456 A[3][3] = {{0,0,0}, 457 {1,0,0}, 458 {0.25,0.25,0}}, 459 Gamma[3][3] = {{0,0,0}, 460 {(-3.0-1.732050807568877293527)/6.0,0.7886751345948128822546,0}, 461 {(-3.0-1.732050807568877293527)/24.0,(-3.0-1.732050807568877293527)/8.0,0.7886751345948128822546}}, 462 b[3] = {1./6.,1./6.,2./3.}, 463 b2[3] = {1./4.,1./4.,1./2.}; 464 PetscReal binterpt[3][2]; 465 466 binterpt[0][0]=0.089316397477040902157517886164709; 467 binterpt[1][0]=-0.91068360252295909784248211383529; 468 binterpt[2][0]=1.8213672050459181956849642276706; 469 binterpt[0][1]=0.077350269189625764509148780501957; 470 binterpt[1][1]=1.077350269189625764509148780502; 471 binterpt[2][1]=-1.1547005383792515290182975610039; 472 473 ierr = TSRosWRegister(TSROSWASSP3P3S1C,3,3,&A[0][0],&Gamma[0][0],b,b2,2,&binterpt[0][0]);CHKERRQ(ierr); 474 } 475 476 { 477 const PetscReal 478 A[4][4] = {{0,0,0,0}, 479 {1./2.,0,0,0}, 480 {1./2.,1./2.,0,0}, 481 {1./6.,1./6.,1./6.,0}}, 482 Gamma[4][4] = {{1./2.,0,0,0}, 483 {0.0,1./4.,0,0}, 484 {-2.,-2./3.,2./3.,0}, 485 {1./2.,5./36.,-2./9,0}}, 486 b[4] = {1./6.,1./6.,1./6.,1./2.}, 487 b2[4] = {1./8.,3./4.,1./8.,0}; 488 PetscReal binterpt[4][3]; 489 490 binterpt[0][0]=6.25; 491 binterpt[1][0]=-30.25; 492 binterpt[2][0]=1.75; 493 binterpt[3][0]=23.25; 494 binterpt[0][1]=-9.75; 495 binterpt[1][1]=58.75; 496 binterpt[2][1]=-3.25; 497 binterpt[3][1]=-45.75; 498 binterpt[0][2]=3.6666666666666666666666666666667; 499 binterpt[1][2]=-28.333333333333333333333333333333; 500 binterpt[2][2]=1.6666666666666666666666666666667; 501 binterpt[3][2]=23.; 502 503 ierr = TSRosWRegister(TSROSWLASSP3P4S2C,3,4,&A[0][0],&Gamma[0][0],b,b2,3,&binterpt[0][0]);CHKERRQ(ierr); 504 } 505 506 { 507 const PetscReal 508 A[4][4] = {{0,0,0,0}, 509 {1./2.,0,0,0}, 510 {1./2.,1./2.,0,0}, 511 {1./6.,1./6.,1./6.,0}}, 512 Gamma[4][4] = {{1./2.,0,0,0}, 513 {0.0,3./4.,0,0}, 514 {-2./3.,-23./9.,2./9.,0}, 515 {1./18.,65./108.,-2./27,0}}, 516 b[4] = {1./6.,1./6.,1./6.,1./2.}, 517 b2[4] = {3./16.,10./16.,3./16.,0}; 518 PetscReal binterpt[4][3]; 519 520 binterpt[0][0]=1.6911764705882352941176470588235; 521 binterpt[1][0]=3.6813725490196078431372549019608; 522 binterpt[2][0]=0.23039215686274509803921568627451; 523 binterpt[3][0]=-4.6029411764705882352941176470588; 524 binterpt[0][1]=-0.95588235294117647058823529411765; 525 binterpt[1][1]=-6.2401960784313725490196078431373; 526 binterpt[2][1]=-0.31862745098039215686274509803922; 527 binterpt[3][1]=7.5147058823529411764705882352941; 528 binterpt[0][2]=-0.56862745098039215686274509803922; 529 binterpt[1][2]=2.7254901960784313725490196078431; 530 binterpt[2][2]=0.25490196078431372549019607843137; 531 binterpt[3][2]=-2.4117647058823529411764705882353; 532 533 ierr = TSRosWRegister(TSROSWLLSSP3P4S2C,3,4,&A[0][0],&Gamma[0][0],b,b2,3,&binterpt[0][0]);CHKERRQ(ierr); 534 } 535 536 { 537 PetscReal A[4][4],Gamma[4][4],b[4],b2[4]; 538 PetscReal binterpt[4][3]; 539 540 Gamma[0][0]=0.4358665215084589994160194475295062513822671686978816; 541 Gamma[0][1]=0; Gamma[0][2]=0; Gamma[0][3]=0; 542 Gamma[1][0]=-1.997527830934941248426324674704153457289527280554476; 543 Gamma[1][1]=0.4358665215084589994160194475295062513822671686978816; 544 Gamma[1][2]=0; Gamma[1][3]=0; 545 Gamma[2][0]=-1.007948511795029620852002345345404191008352770119903; 546 Gamma[2][1]=-0.004648958462629345562774289390054679806993396798458131; 547 Gamma[2][2]=0.4358665215084589994160194475295062513822671686978816; 548 Gamma[2][3]=0; 549 Gamma[3][0]=-0.6685429734233467180451604600279552604364311322650783; 550 Gamma[3][1]=0.6056625986449338476089525334450053439525178740492984; 551 Gamma[3][2]=-0.9717899277217721234705114616271378792182450260943198; 552 Gamma[3][3]=0; 553 554 A[0][0]=0; A[0][1]=0; A[0][2]=0; A[0][3]=0; 555 A[1][0]=0.8717330430169179988320388950590125027645343373957631; 556 A[1][1]=0; A[1][2]=0; A[1][3]=0; 557 A[2][0]=0.5275890119763004115618079766722914408876108660811028; 558 A[2][1]=0.07241098802369958843819203208518599088698057726988732; 559 A[2][2]=0; A[2][3]=0; 560 A[3][0]=0.3990960076760701320627260685975778145384666450351314; 561 A[3][1]=-0.4375576546135194437228463747348862825846903771419953; 562 A[3][2]=1.038461646937449311660120300601880176655352737312713; 563 A[3][3]=0; 564 565 b[0]=0.1876410243467238251612921333138006734899663569186926; 566 b[1]=-0.5952974735769549480478230473706443582188442040780541; 567 b[2]=0.9717899277217721234705114616271378792182450260943198; 568 b[3]=0.4358665215084589994160194475295062513822671686978816; 569 570 b2[0]=0.2147402862233891404862383521089097657790734483804460; 571 b2[1]=-0.4851622638849390928209050538171743017757490232519684; 572 b2[2]=0.8687250025203875511662123688667549217531982787600080; 573 b2[3]=0.4016969751411624011684543450940068201770721128357014; 574 575 binterpt[0][0]=2.2565812720167954547104627844105; 576 binterpt[1][0]=1.349166413351089573796243820819; 577 binterpt[2][0]=-2.4695174540533503758652847586647; 578 binterpt[3][0]=-0.13623023131453465264142184656474; 579 binterpt[0][1]=-3.0826699111559187902922463354557; 580 binterpt[1][1]=-2.4689115685996042534544925650515; 581 binterpt[2][1]=5.7428279814696677152129332773553; 582 binterpt[3][1]=-0.19124650171414467146619437684812; 583 binterpt[0][2]=1.0137296634858471607430756831148; 584 binterpt[1][2]=0.52444768167155973161042570784064; 585 binterpt[2][2]=-2.3015205996945452158771370439586; 586 binterpt[3][2]=0.76334325453713832352363565300308; 587 588 ierr = TSRosWRegister(TSROSWARK3,3,4,&A[0][0],&Gamma[0][0],b,b2,3,&binterpt[0][0]);CHKERRQ(ierr); 589 } 590 ierr = TSRosWRegisterRos4(TSROSWGRK4T,0.231,PETSC_DEFAULT,PETSC_DEFAULT,0,-0.1282612945269037e+01);CHKERRQ(ierr); 591 ierr = TSRosWRegisterRos4(TSROSWSHAMP4,0.5,PETSC_DEFAULT,PETSC_DEFAULT,0,125./108.);CHKERRQ(ierr); 592 ierr = TSRosWRegisterRos4(TSROSWVELDD4,0.22570811482256823492,PETSC_DEFAULT,PETSC_DEFAULT,0,-1.355958941201148);CHKERRQ(ierr); 593 ierr = TSRosWRegisterRos4(TSROSW4L,0.57282,PETSC_DEFAULT,PETSC_DEFAULT,0,-1.093502252409163);CHKERRQ(ierr); 594 PetscFunctionReturn(0); 595 } 596 597 598 599 /*@C 600 TSRosWRegisterDestroy - Frees the list of schemes that were registered by TSRosWRegister(). 601 602 Not Collective 603 604 Level: advanced 605 606 .keywords: TSRosW, register, destroy 607 .seealso: TSRosWRegister(), TSRosWRegisterAll() 608 @*/ 609 PetscErrorCode TSRosWRegisterDestroy(void) 610 { 611 PetscErrorCode ierr; 612 RosWTableauLink link; 613 614 PetscFunctionBegin; 615 while ((link = RosWTableauList)) { 616 RosWTableau t = &link->tab; 617 RosWTableauList = link->next; 618 ierr = PetscFree5(t->A,t->Gamma,t->b,t->ASum,t->GammaSum);CHKERRQ(ierr); 619 ierr = PetscFree5(t->At,t->bt,t->GammaInv,t->GammaZeroDiag,t->GammaExplicitCorr);CHKERRQ(ierr); 620 ierr = PetscFree2(t->bembed,t->bembedt);CHKERRQ(ierr); 621 ierr = PetscFree(t->binterpt);CHKERRQ(ierr); 622 ierr = PetscFree(t->name);CHKERRQ(ierr); 623 ierr = PetscFree(link);CHKERRQ(ierr); 624 } 625 TSRosWRegisterAllCalled = PETSC_FALSE; 626 PetscFunctionReturn(0); 627 } 628 629 /*@C 630 TSRosWInitializePackage - This function initializes everything in the TSRosW package. It is called 631 from PetscDLLibraryRegister() when using dynamic libraries, and on the first call to TSCreate_RosW() 632 when using static libraries. 633 634 Level: developer 635 636 .keywords: TS, TSRosW, initialize, package 637 .seealso: PetscInitialize() 638 @*/ 639 PetscErrorCode TSRosWInitializePackage(void) 640 { 641 PetscErrorCode ierr; 642 643 PetscFunctionBegin; 644 if (TSRosWPackageInitialized) PetscFunctionReturn(0); 645 TSRosWPackageInitialized = PETSC_TRUE; 646 ierr = TSRosWRegisterAll();CHKERRQ(ierr); 647 ierr = PetscRegisterFinalize(TSRosWFinalizePackage);CHKERRQ(ierr); 648 PetscFunctionReturn(0); 649 } 650 651 /*@C 652 TSRosWFinalizePackage - This function destroys everything in the TSRosW package. It is 653 called from PetscFinalize(). 654 655 Level: developer 656 657 .keywords: Petsc, destroy, package 658 .seealso: PetscFinalize() 659 @*/ 660 PetscErrorCode TSRosWFinalizePackage(void) 661 { 662 PetscErrorCode ierr; 663 664 PetscFunctionBegin; 665 TSRosWPackageInitialized = PETSC_FALSE; 666 ierr = TSRosWRegisterDestroy();CHKERRQ(ierr); 667 PetscFunctionReturn(0); 668 } 669 670 /*@C 671 TSRosWRegister - register a Rosenbrock W scheme by providing the entries in the Butcher tableau and optionally embedded approximations and interpolation 672 673 Not Collective, but the same schemes should be registered on all processes on which they will be used 674 675 Input Parameters: 676 + name - identifier for method 677 . order - approximation order of method 678 . s - number of stages, this is the dimension of the matrices below 679 . A - Table of propagated stage coefficients (dimension s*s, row-major), strictly lower triangular 680 . Gamma - Table of coefficients in implicit stage equations (dimension s*s, row-major), lower triangular with nonzero diagonal 681 . b - Step completion table (dimension s) 682 . bembed - Step completion table for a scheme of order one less (dimension s, NULL if no embedded scheme is available) 683 . pinterp - Order of the interpolation scheme, equal to the number of columns of binterpt 684 - binterpt - Coefficients of the interpolation formula (dimension s*pinterp) 685 686 Notes: 687 Several Rosenbrock W methods are provided, this function is only needed to create new methods. 688 689 Level: advanced 690 691 .keywords: TS, register 692 693 .seealso: TSRosW 694 @*/ 695 PetscErrorCode TSRosWRegister(TSRosWType name,PetscInt order,PetscInt s,const PetscReal A[],const PetscReal Gamma[],const PetscReal b[],const PetscReal bembed[], 696 PetscInt pinterp,const PetscReal binterpt[]) 697 { 698 PetscErrorCode ierr; 699 RosWTableauLink link; 700 RosWTableau t; 701 PetscInt i,j,k; 702 PetscScalar *GammaInv; 703 704 PetscFunctionBegin; 705 PetscValidCharPointer(name,1); 706 PetscValidPointer(A,4); 707 PetscValidPointer(Gamma,5); 708 PetscValidPointer(b,6); 709 if (bembed) PetscValidPointer(bembed,7); 710 711 ierr = TSRosWInitializePackage();CHKERRQ(ierr); 712 ierr = PetscCalloc1(1,&link);CHKERRQ(ierr); 713 t = &link->tab; 714 ierr = PetscStrallocpy(name,&t->name);CHKERRQ(ierr); 715 t->order = order; 716 t->s = s; 717 ierr = PetscMalloc5(s*s,&t->A,s*s,&t->Gamma,s,&t->b,s,&t->ASum,s,&t->GammaSum);CHKERRQ(ierr); 718 ierr = PetscMalloc5(s*s,&t->At,s,&t->bt,s*s,&t->GammaInv,s,&t->GammaZeroDiag,s*s,&t->GammaExplicitCorr);CHKERRQ(ierr); 719 ierr = PetscMemcpy(t->A,A,s*s*sizeof(A[0]));CHKERRQ(ierr); 720 ierr = PetscMemcpy(t->Gamma,Gamma,s*s*sizeof(Gamma[0]));CHKERRQ(ierr); 721 ierr = PetscMemcpy(t->GammaExplicitCorr,Gamma,s*s*sizeof(Gamma[0]));CHKERRQ(ierr); 722 ierr = PetscMemcpy(t->b,b,s*sizeof(b[0]));CHKERRQ(ierr); 723 if (bembed) { 724 ierr = PetscMalloc2(s,&t->bembed,s,&t->bembedt);CHKERRQ(ierr); 725 ierr = PetscMemcpy(t->bembed,bembed,s*sizeof(bembed[0]));CHKERRQ(ierr); 726 } 727 for (i=0; i<s; i++) { 728 t->ASum[i] = 0; 729 t->GammaSum[i] = 0; 730 for (j=0; j<s; j++) { 731 t->ASum[i] += A[i*s+j]; 732 t->GammaSum[i] += Gamma[i*s+j]; 733 } 734 } 735 ierr = PetscMalloc1(s*s,&GammaInv);CHKERRQ(ierr); /* Need to use Scalar for inverse, then convert back to Real */ 736 for (i=0; i<s*s; i++) GammaInv[i] = Gamma[i]; 737 for (i=0; i<s; i++) { 738 if (Gamma[i*s+i] == 0.0) { 739 GammaInv[i*s+i] = 1.0; 740 t->GammaZeroDiag[i] = PETSC_TRUE; 741 } else { 742 t->GammaZeroDiag[i] = PETSC_FALSE; 743 } 744 } 745 746 switch (s) { 747 case 1: GammaInv[0] = 1./GammaInv[0]; break; 748 case 2: ierr = PetscKernel_A_gets_inverse_A_2(GammaInv,0,PETSC_FALSE,NULL);CHKERRQ(ierr); break; 749 case 3: ierr = PetscKernel_A_gets_inverse_A_3(GammaInv,0,PETSC_FALSE,NULL);CHKERRQ(ierr); break; 750 case 4: ierr = PetscKernel_A_gets_inverse_A_4(GammaInv,0,PETSC_FALSE,NULL);CHKERRQ(ierr); break; 751 case 5: { 752 PetscInt ipvt5[5]; 753 MatScalar work5[5*5]; 754 ierr = PetscKernel_A_gets_inverse_A_5(GammaInv,ipvt5,work5,0,PETSC_FALSE,NULL);CHKERRQ(ierr); break; 755 } 756 case 6: ierr = PetscKernel_A_gets_inverse_A_6(GammaInv,0,PETSC_FALSE,NULL);CHKERRQ(ierr); break; 757 case 7: ierr = PetscKernel_A_gets_inverse_A_7(GammaInv,0,PETSC_FALSE,NULL);CHKERRQ(ierr); break; 758 default: SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented for %D stages",s); 759 } 760 for (i=0; i<s*s; i++) t->GammaInv[i] = PetscRealPart(GammaInv[i]); 761 ierr = PetscFree(GammaInv);CHKERRQ(ierr); 762 763 for (i=0; i<s; i++) { 764 for (k=0; k<i+1; k++) { 765 t->GammaExplicitCorr[i*s+k]=(t->GammaExplicitCorr[i*s+k])*(t->GammaInv[k*s+k]); 766 for (j=k+1; j<i+1; j++) { 767 t->GammaExplicitCorr[i*s+k]+=(t->GammaExplicitCorr[i*s+j])*(t->GammaInv[j*s+k]); 768 } 769 } 770 } 771 772 for (i=0; i<s; i++) { 773 for (j=0; j<s; j++) { 774 t->At[i*s+j] = 0; 775 for (k=0; k<s; k++) { 776 t->At[i*s+j] += t->A[i*s+k] * t->GammaInv[k*s+j]; 777 } 778 } 779 t->bt[i] = 0; 780 for (j=0; j<s; j++) { 781 t->bt[i] += t->b[j] * t->GammaInv[j*s+i]; 782 } 783 if (bembed) { 784 t->bembedt[i] = 0; 785 for (j=0; j<s; j++) { 786 t->bembedt[i] += t->bembed[j] * t->GammaInv[j*s+i]; 787 } 788 } 789 } 790 t->ccfl = 1.0; /* Fix this */ 791 792 t->pinterp = pinterp; 793 ierr = PetscMalloc1(s*pinterp,&t->binterpt);CHKERRQ(ierr); 794 ierr = PetscMemcpy(t->binterpt,binterpt,s*pinterp*sizeof(binterpt[0]));CHKERRQ(ierr); 795 link->next = RosWTableauList; 796 RosWTableauList = link; 797 PetscFunctionReturn(0); 798 } 799 800 /*@C 801 TSRosWRegisterRos4 - register a fourth order Rosenbrock scheme by providing paramter choices 802 803 Not Collective, but the same schemes should be registered on all processes on which they will be used 804 805 Input Parameters: 806 + name - identifier for method 807 . gamma - leading coefficient (diagonal entry) 808 . a2 - design parameter, see Table 7.2 of Hairer&Wanner 809 . a3 - design parameter or PETSC_DEFAULT to satisfy one of the order five conditions (Eq 7.22) 810 . b3 - design parameter, see Table 7.2 of Hairer&Wanner 811 . beta43 - design parameter or PETSC_DEFAULT to use Equation 7.21 of Hairer&Wanner 812 . e4 - design parameter for embedded method, see coefficient E4 in ros4.f code from Hairer 813 814 Notes: 815 This routine encodes the design of fourth order Rosenbrock methods as described in Hairer and Wanner volume 2. 816 It is used here to implement several methods from the book and can be used to experiment with new methods. 817 It was written this way instead of by copying coefficients in order to provide better than double precision satisfaction of the order conditions. 818 819 Level: developer 820 821 .keywords: TS, register 822 823 .seealso: TSRosW, TSRosWRegister() 824 @*/ 825 PetscErrorCode TSRosWRegisterRos4(TSRosWType name,PetscReal gamma,PetscReal a2,PetscReal a3,PetscReal b3,PetscReal e4) 826 { 827 PetscErrorCode ierr; 828 /* Declare numeric constants so they can be quad precision without being truncated at double */ 829 const PetscReal one = 1,two = 2,three = 3,four = 4,five = 5,six = 6,eight = 8,twelve = 12,twenty = 20,twentyfour = 24, 830 p32 = one/six - gamma + gamma*gamma, 831 p42 = one/eight - gamma/three, 832 p43 = one/twelve - gamma/three, 833 p44 = one/twentyfour - gamma/two + three/two*gamma*gamma - gamma*gamma*gamma, 834 p56 = one/twenty - gamma/four; 835 PetscReal a4,a32,a42,a43,b1,b2,b4,beta2p,beta3p,beta4p,beta32,beta42,beta43,beta32beta2p,beta4jbetajp; 836 PetscReal A[4][4],Gamma[4][4],b[4],bm[4]; 837 PetscScalar M[3][3],rhs[3]; 838 839 PetscFunctionBegin; 840 /* Step 1: choose Gamma (input) */ 841 /* Step 2: choose a2,a3,a4; b1,b2,b3,b4 to satisfy order conditions */ 842 if (a3 == PETSC_DEFAULT) a3 = (one/five - a2/four)/(one/four - a2/three); /* Eq 7.22 */ 843 a4 = a3; /* consequence of 7.20 */ 844 845 /* Solve order conditions 7.15a, 7.15c, 7.15e */ 846 M[0][0] = one; M[0][1] = one; M[0][2] = one; /* 7.15a */ 847 M[1][0] = 0.0; M[1][1] = a2*a2; M[1][2] = a4*a4; /* 7.15c */ 848 M[2][0] = 0.0; M[2][1] = a2*a2*a2; M[2][2] = a4*a4*a4; /* 7.15e */ 849 rhs[0] = one - b3; 850 rhs[1] = one/three - a3*a3*b3; 851 rhs[2] = one/four - a3*a3*a3*b3; 852 ierr = PetscKernel_A_gets_inverse_A_3(&M[0][0],0,PETSC_FALSE,NULL);CHKERRQ(ierr); 853 b1 = PetscRealPart(M[0][0]*rhs[0] + M[0][1]*rhs[1] + M[0][2]*rhs[2]); 854 b2 = PetscRealPart(M[1][0]*rhs[0] + M[1][1]*rhs[1] + M[1][2]*rhs[2]); 855 b4 = PetscRealPart(M[2][0]*rhs[0] + M[2][1]*rhs[1] + M[2][2]*rhs[2]); 856 857 /* Step 3 */ 858 beta43 = (p56 - a2*p43) / (b4*a3*a3*(a3 - a2)); /* 7.21 */ 859 beta32beta2p = p44 / (b4*beta43); /* 7.15h */ 860 beta4jbetajp = (p32 - b3*beta32beta2p) / b4; 861 M[0][0] = b2; M[0][1] = b3; M[0][2] = b4; 862 M[1][0] = a4*a4*beta32beta2p-a3*a3*beta4jbetajp; M[1][1] = a2*a2*beta4jbetajp; M[1][2] = -a2*a2*beta32beta2p; 863 M[2][0] = b4*beta43*a3*a3-p43; M[2][1] = -b4*beta43*a2*a2; M[2][2] = 0; 864 rhs[0] = one/two - gamma; rhs[1] = 0; rhs[2] = -a2*a2*p32; 865 ierr = PetscKernel_A_gets_inverse_A_3(&M[0][0],0,PETSC_FALSE,NULL);CHKERRQ(ierr); 866 beta2p = PetscRealPart(M[0][0]*rhs[0] + M[0][1]*rhs[1] + M[0][2]*rhs[2]); 867 beta3p = PetscRealPart(M[1][0]*rhs[0] + M[1][1]*rhs[1] + M[1][2]*rhs[2]); 868 beta4p = PetscRealPart(M[2][0]*rhs[0] + M[2][1]*rhs[1] + M[2][2]*rhs[2]); 869 870 /* Step 4: back-substitute */ 871 beta32 = beta32beta2p / beta2p; 872 beta42 = (beta4jbetajp - beta43*beta3p) / beta2p; 873 874 /* Step 5: 7.15f and 7.20, then 7.16 */ 875 a43 = 0; 876 a32 = p42 / (b3*a3*beta2p + b4*a4*beta2p); 877 a42 = a32; 878 879 A[0][0] = 0; A[0][1] = 0; A[0][2] = 0; A[0][3] = 0; 880 A[1][0] = a2; A[1][1] = 0; A[1][2] = 0; A[1][3] = 0; 881 A[2][0] = a3-a32; A[2][1] = a32; A[2][2] = 0; A[2][3] = 0; 882 A[3][0] = a4-a43-a42; A[3][1] = a42; A[3][2] = a43; A[3][3] = 0; 883 Gamma[0][0] = gamma; Gamma[0][1] = 0; Gamma[0][2] = 0; Gamma[0][3] = 0; 884 Gamma[1][0] = beta2p-A[1][0]; Gamma[1][1] = gamma; Gamma[1][2] = 0; Gamma[1][3] = 0; 885 Gamma[2][0] = beta3p-beta32-A[2][0]; Gamma[2][1] = beta32-A[2][1]; Gamma[2][2] = gamma; Gamma[2][3] = 0; 886 Gamma[3][0] = beta4p-beta42-beta43-A[3][0]; Gamma[3][1] = beta42-A[3][1]; Gamma[3][2] = beta43-A[3][2]; Gamma[3][3] = gamma; 887 b[0] = b1; b[1] = b2; b[2] = b3; b[3] = b4; 888 889 /* Construct embedded formula using given e4. We are solving Equation 7.18. */ 890 bm[3] = b[3] - e4*gamma; /* using definition of E4 */ 891 bm[2] = (p32 - beta4jbetajp*bm[3]) / (beta32*beta2p); /* fourth row of 7.18 */ 892 bm[1] = (one/two - gamma - beta3p*bm[2] - beta4p*bm[3]) / beta2p; /* second row */ 893 bm[0] = one - bm[1] - bm[2] - bm[3]; /* first row */ 894 895 { 896 const PetscReal misfit = a2*a2*bm[1] + a3*a3*bm[2] + a4*a4*bm[3] - one/three; 897 if (PetscAbs(misfit) > PETSC_SMALL) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Assumptions violated, could not construct a third order embedded method"); 898 } 899 ierr = TSRosWRegister(name,4,4,&A[0][0],&Gamma[0][0],b,bm,0,NULL);CHKERRQ(ierr); 900 PetscFunctionReturn(0); 901 } 902 903 /* 904 The step completion formula is 905 906 x1 = x0 + b^T Y 907 908 where Y is the multi-vector of stages corrections. This function can be called before or after ts->vec_sol has been 909 updated. Suppose we have a completion formula b and an embedded formula be of different order. We can write 910 911 x1e = x0 + be^T Y 912 = x1 - b^T Y + be^T Y 913 = x1 + (be - b)^T Y 914 915 so we can evaluate the method of different order even after the step has been optimistically completed. 916 */ 917 static PetscErrorCode TSEvaluateStep_RosW(TS ts,PetscInt order,Vec U,PetscBool *done) 918 { 919 TS_RosW *ros = (TS_RosW*)ts->data; 920 RosWTableau tab = ros->tableau; 921 PetscScalar *w = ros->work; 922 PetscInt i; 923 PetscErrorCode ierr; 924 925 PetscFunctionBegin; 926 if (order == tab->order) { 927 if (ros->status == TS_STEP_INCOMPLETE) { /* Use standard completion formula */ 928 ierr = VecCopy(ts->vec_sol,U);CHKERRQ(ierr); 929 for (i=0; i<tab->s; i++) w[i] = tab->bt[i]; 930 ierr = VecMAXPY(U,tab->s,w,ros->Y);CHKERRQ(ierr); 931 } else {ierr = VecCopy(ts->vec_sol,U);CHKERRQ(ierr);} 932 if (done) *done = PETSC_TRUE; 933 PetscFunctionReturn(0); 934 } else if (order == tab->order-1) { 935 if (!tab->bembedt) goto unavailable; 936 if (ros->status == TS_STEP_INCOMPLETE) { /* Use embedded completion formula */ 937 ierr = VecCopy(ts->vec_sol,U);CHKERRQ(ierr); 938 for (i=0; i<tab->s; i++) w[i] = tab->bembedt[i]; 939 ierr = VecMAXPY(U,tab->s,w,ros->Y);CHKERRQ(ierr); 940 } else { /* Use rollback-and-recomplete formula (bembedt - bt) */ 941 for (i=0; i<tab->s; i++) w[i] = tab->bembedt[i] - tab->bt[i]; 942 ierr = VecCopy(ts->vec_sol,U);CHKERRQ(ierr); 943 ierr = VecMAXPY(U,tab->s,w,ros->Y);CHKERRQ(ierr); 944 } 945 if (done) *done = PETSC_TRUE; 946 PetscFunctionReturn(0); 947 } 948 unavailable: 949 if (done) *done = PETSC_FALSE; 950 else SETERRQ3(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Rosenbrock-W '%s' of order %D cannot evaluate step at order %D. Consider using -ts_adapt_type none or a different method that has an embedded estimate.",tab->name,tab->order,order); 951 PetscFunctionReturn(0); 952 } 953 954 static PetscErrorCode TSRollBack_RosW(TS ts) 955 { 956 TS_RosW *ros = (TS_RosW*)ts->data; 957 PetscErrorCode ierr; 958 959 PetscFunctionBegin; 960 ierr = VecCopy(ros->vec_sol_prev,ts->vec_sol);CHKERRQ(ierr); 961 PetscFunctionReturn(0); 962 } 963 964 static PetscErrorCode TSStep_RosW(TS ts) 965 { 966 TS_RosW *ros = (TS_RosW*)ts->data; 967 RosWTableau tab = ros->tableau; 968 const PetscInt s = tab->s; 969 const PetscReal *At = tab->At,*Gamma = tab->Gamma,*ASum = tab->ASum,*GammaInv = tab->GammaInv; 970 const PetscReal *GammaExplicitCorr = tab->GammaExplicitCorr; 971 const PetscBool *GammaZeroDiag = tab->GammaZeroDiag; 972 PetscScalar *w = ros->work; 973 Vec *Y = ros->Y,Ydot = ros->Ydot,Zdot = ros->Zdot,Zstage = ros->Zstage; 974 SNES snes; 975 TSAdapt adapt; 976 PetscInt i,j,its,lits; 977 PetscInt rejections = 0; 978 PetscBool stageok,accept = PETSC_TRUE; 979 PetscReal next_time_step = ts->time_step; 980 PetscErrorCode ierr; 981 982 PetscFunctionBegin; 983 if (!ts->steprollback) { 984 ierr = VecCopy(ts->vec_sol,ros->vec_sol_prev);CHKERRQ(ierr); 985 } 986 987 ros->status = TS_STEP_INCOMPLETE; 988 while (!ts->reason && ros->status != TS_STEP_COMPLETE) { 989 const PetscReal h = ts->time_step; 990 for (i=0; i<s; i++) { 991 ros->stage_time = ts->ptime + h*ASum[i]; 992 ierr = TSPreStage(ts,ros->stage_time);CHKERRQ(ierr); 993 if (GammaZeroDiag[i]) { 994 ros->stage_explicit = PETSC_TRUE; 995 ros->scoeff = 1.; 996 } else { 997 ros->stage_explicit = PETSC_FALSE; 998 ros->scoeff = 1./Gamma[i*s+i]; 999 } 1000 1001 ierr = VecCopy(ts->vec_sol,Zstage);CHKERRQ(ierr); 1002 for (j=0; j<i; j++) w[j] = At[i*s+j]; 1003 ierr = VecMAXPY(Zstage,i,w,Y);CHKERRQ(ierr); 1004 1005 for (j=0; j<i; j++) w[j] = 1./h * GammaInv[i*s+j]; 1006 ierr = VecZeroEntries(Zdot);CHKERRQ(ierr); 1007 ierr = VecMAXPY(Zdot,i,w,Y);CHKERRQ(ierr); 1008 1009 /* Initial guess taken from last stage */ 1010 ierr = VecZeroEntries(Y[i]);CHKERRQ(ierr); 1011 1012 if (!ros->stage_explicit) { 1013 ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr); 1014 if (!ros->recompute_jacobian && !i) { 1015 ierr = SNESSetLagJacobian(snes,-2);CHKERRQ(ierr); /* Recompute the Jacobian on this solve, but not again */ 1016 } 1017 ierr = SNESSolve(snes,NULL,Y[i]);CHKERRQ(ierr); 1018 ierr = SNESGetIterationNumber(snes,&its);CHKERRQ(ierr); 1019 ierr = SNESGetLinearSolveIterations(snes,&lits);CHKERRQ(ierr); 1020 ts->snes_its += its; ts->ksp_its += lits; 1021 } else { 1022 Mat J,Jp; 1023 ierr = VecZeroEntries(Ydot);CHKERRQ(ierr); /* Evaluate Y[i]=G(t,Ydot=0,Zstage) */ 1024 ierr = TSComputeIFunction(ts,ros->stage_time,Zstage,Ydot,Y[i],PETSC_FALSE);CHKERRQ(ierr); 1025 ierr = VecScale(Y[i],-1.0);CHKERRQ(ierr); 1026 ierr = VecAXPY(Y[i],-1.0,Zdot);CHKERRQ(ierr); /*Y[i] = F(Zstage)-Zdot[=GammaInv*Y]*/ 1027 1028 ierr = VecZeroEntries(Zstage);CHKERRQ(ierr); /* Zstage = GammaExplicitCorr[i,j] * Y[j] */ 1029 for (j=0; j<i; j++) w[j] = GammaExplicitCorr[i*s+j]; 1030 ierr = VecMAXPY(Zstage,i,w,Y);CHKERRQ(ierr); 1031 1032 /* Y[i] = Y[i] + Jac*Zstage[=Jac*GammaExplicitCorr[i,j] * Y[j]] */ 1033 ierr = TSGetIJacobian(ts,&J,&Jp,NULL,NULL);CHKERRQ(ierr); 1034 ierr = TSComputeIJacobian(ts,ros->stage_time,ts->vec_sol,Ydot,0,J,Jp,PETSC_FALSE);CHKERRQ(ierr); 1035 ierr = MatMult(J,Zstage,Zdot);CHKERRQ(ierr); 1036 ierr = VecAXPY(Y[i],-1.0,Zdot);CHKERRQ(ierr); 1037 ts->ksp_its += 1; 1038 1039 ierr = VecScale(Y[i],h);CHKERRQ(ierr); 1040 } 1041 ierr = TSPostStage(ts,ros->stage_time,i,Y);CHKERRQ(ierr); 1042 ierr = TSGetAdapt(ts,&adapt);CHKERRQ(ierr); 1043 ierr = TSAdaptCheckStage(adapt,ts,ros->stage_time,Y[i],&stageok);CHKERRQ(ierr); 1044 if (!stageok) goto reject_step; 1045 } 1046 1047 ros->status = TS_STEP_INCOMPLETE; 1048 ierr = TSEvaluateStep_RosW(ts,tab->order,ts->vec_sol,NULL);CHKERRQ(ierr); 1049 ros->status = TS_STEP_PENDING; 1050 ierr = TSGetAdapt(ts,&adapt);CHKERRQ(ierr); 1051 ierr = TSAdaptCandidatesClear(adapt);CHKERRQ(ierr); 1052 ierr = TSAdaptCandidateAdd(adapt,tab->name,tab->order,1,tab->ccfl,(PetscReal)tab->s,PETSC_TRUE);CHKERRQ(ierr); 1053 ierr = TSAdaptChoose(adapt,ts,ts->time_step,NULL,&next_time_step,&accept);CHKERRQ(ierr); 1054 ros->status = accept ? TS_STEP_COMPLETE : TS_STEP_INCOMPLETE; 1055 if (!accept) { /* Roll back the current step */ 1056 ierr = TSRollBack_RosW(ts);CHKERRQ(ierr); 1057 ts->time_step = next_time_step; 1058 goto reject_step; 1059 } 1060 1061 ts->ptime += ts->time_step; 1062 ts->time_step = next_time_step; 1063 break; 1064 1065 reject_step: 1066 ts->reject++; accept = PETSC_FALSE; 1067 if (!ts->reason && ++rejections > ts->max_reject && ts->max_reject >= 0) { 1068 ts->reason = TS_DIVERGED_STEP_REJECTED; 1069 ierr = PetscInfo2(ts,"Step=%D, step rejections %D greater than current TS allowed, stopping solve\n",ts->steps,rejections);CHKERRQ(ierr); 1070 } 1071 } 1072 PetscFunctionReturn(0); 1073 } 1074 1075 static PetscErrorCode TSInterpolate_RosW(TS ts,PetscReal itime,Vec U) 1076 { 1077 TS_RosW *ros = (TS_RosW*)ts->data; 1078 PetscInt s = ros->tableau->s,pinterp = ros->tableau->pinterp,i,j; 1079 PetscReal h; 1080 PetscReal tt,t; 1081 PetscScalar *bt; 1082 const PetscReal *Bt = ros->tableau->binterpt; 1083 PetscErrorCode ierr; 1084 const PetscReal *GammaInv = ros->tableau->GammaInv; 1085 PetscScalar *w = ros->work; 1086 Vec *Y = ros->Y; 1087 1088 PetscFunctionBegin; 1089 if (!Bt) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSRosW %s does not have an interpolation formula",ros->tableau->name); 1090 1091 switch (ros->status) { 1092 case TS_STEP_INCOMPLETE: 1093 case TS_STEP_PENDING: 1094 h = ts->time_step; 1095 t = (itime - ts->ptime)/h; 1096 break; 1097 case TS_STEP_COMPLETE: 1098 h = ts->ptime - ts->ptime_prev; 1099 t = (itime - ts->ptime)/h + 1; /* In the interval [0,1] */ 1100 break; 1101 default: SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_PLIB,"Invalid TSStepStatus"); 1102 } 1103 ierr = PetscMalloc1(s,&bt);CHKERRQ(ierr); 1104 for (i=0; i<s; i++) bt[i] = 0; 1105 for (j=0,tt=t; j<pinterp; j++,tt*=t) { 1106 for (i=0; i<s; i++) { 1107 bt[i] += Bt[i*pinterp+j] * tt; 1108 } 1109 } 1110 1111 /* y(t+tt*h) = y(t) + Sum bt(tt) * GammaInv * Ydot */ 1112 /* U <- 0*/ 1113 ierr = VecZeroEntries(U);CHKERRQ(ierr); 1114 /* U <- Sum bt_i * GammaInv(i,1:i) * Y(1:i) */ 1115 for (j=0; j<s; j++) w[j] = 0; 1116 for (j=0; j<s; j++) { 1117 for (i=j; i<s; i++) { 1118 w[j] += bt[i]*GammaInv[i*s+j]; 1119 } 1120 } 1121 ierr = VecMAXPY(U,i,w,Y);CHKERRQ(ierr); 1122 /* U <- y(t) + U */ 1123 ierr = VecAXPY(U,1,ros->vec_sol_prev);CHKERRQ(ierr); 1124 1125 ierr = PetscFree(bt);CHKERRQ(ierr); 1126 PetscFunctionReturn(0); 1127 } 1128 1129 /*------------------------------------------------------------*/ 1130 1131 static PetscErrorCode TSRosWTableauReset(TS ts) 1132 { 1133 TS_RosW *ros = (TS_RosW*)ts->data; 1134 RosWTableau tab = ros->tableau; 1135 PetscErrorCode ierr; 1136 1137 PetscFunctionBegin; 1138 if (!tab) PetscFunctionReturn(0); 1139 ierr = VecDestroyVecs(tab->s,&ros->Y);CHKERRQ(ierr); 1140 ierr = PetscFree(ros->work);CHKERRQ(ierr); 1141 PetscFunctionReturn(0); 1142 } 1143 1144 static PetscErrorCode TSReset_RosW(TS ts) 1145 { 1146 TS_RosW *ros = (TS_RosW*)ts->data; 1147 PetscErrorCode ierr; 1148 1149 PetscFunctionBegin; 1150 ierr = TSRosWTableauReset(ts);CHKERRQ(ierr); 1151 ierr = VecDestroy(&ros->Ydot);CHKERRQ(ierr); 1152 ierr = VecDestroy(&ros->Ystage);CHKERRQ(ierr); 1153 ierr = VecDestroy(&ros->Zdot);CHKERRQ(ierr); 1154 ierr = VecDestroy(&ros->Zstage);CHKERRQ(ierr); 1155 ierr = VecDestroy(&ros->vec_sol_prev);CHKERRQ(ierr); 1156 PetscFunctionReturn(0); 1157 } 1158 1159 static PetscErrorCode TSRosWGetVecs(TS ts,DM dm,Vec *Ydot,Vec *Zdot,Vec *Ystage,Vec *Zstage) 1160 { 1161 TS_RosW *rw = (TS_RosW*)ts->data; 1162 PetscErrorCode ierr; 1163 1164 PetscFunctionBegin; 1165 if (Ydot) { 1166 if (dm && dm != ts->dm) { 1167 ierr = DMGetNamedGlobalVector(dm,"TSRosW_Ydot",Ydot);CHKERRQ(ierr); 1168 } else *Ydot = rw->Ydot; 1169 } 1170 if (Zdot) { 1171 if (dm && dm != ts->dm) { 1172 ierr = DMGetNamedGlobalVector(dm,"TSRosW_Zdot",Zdot);CHKERRQ(ierr); 1173 } else *Zdot = rw->Zdot; 1174 } 1175 if (Ystage) { 1176 if (dm && dm != ts->dm) { 1177 ierr = DMGetNamedGlobalVector(dm,"TSRosW_Ystage",Ystage);CHKERRQ(ierr); 1178 } else *Ystage = rw->Ystage; 1179 } 1180 if (Zstage) { 1181 if (dm && dm != ts->dm) { 1182 ierr = DMGetNamedGlobalVector(dm,"TSRosW_Zstage",Zstage);CHKERRQ(ierr); 1183 } else *Zstage = rw->Zstage; 1184 } 1185 PetscFunctionReturn(0); 1186 } 1187 1188 1189 static PetscErrorCode TSRosWRestoreVecs(TS ts,DM dm,Vec *Ydot,Vec *Zdot, Vec *Ystage, Vec *Zstage) 1190 { 1191 PetscErrorCode ierr; 1192 1193 PetscFunctionBegin; 1194 if (Ydot) { 1195 if (dm && dm != ts->dm) { 1196 ierr = DMRestoreNamedGlobalVector(dm,"TSRosW_Ydot",Ydot);CHKERRQ(ierr); 1197 } 1198 } 1199 if (Zdot) { 1200 if (dm && dm != ts->dm) { 1201 ierr = DMRestoreNamedGlobalVector(dm,"TSRosW_Zdot",Zdot);CHKERRQ(ierr); 1202 } 1203 } 1204 if (Ystage) { 1205 if (dm && dm != ts->dm) { 1206 ierr = DMRestoreNamedGlobalVector(dm,"TSRosW_Ystage",Ystage);CHKERRQ(ierr); 1207 } 1208 } 1209 if (Zstage) { 1210 if (dm && dm != ts->dm) { 1211 ierr = DMRestoreNamedGlobalVector(dm,"TSRosW_Zstage",Zstage);CHKERRQ(ierr); 1212 } 1213 } 1214 PetscFunctionReturn(0); 1215 } 1216 1217 static PetscErrorCode DMCoarsenHook_TSRosW(DM fine,DM coarse,void *ctx) 1218 { 1219 PetscFunctionBegin; 1220 PetscFunctionReturn(0); 1221 } 1222 1223 static PetscErrorCode DMRestrictHook_TSRosW(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse,void *ctx) 1224 { 1225 TS ts = (TS)ctx; 1226 PetscErrorCode ierr; 1227 Vec Ydot,Zdot,Ystage,Zstage; 1228 Vec Ydotc,Zdotc,Ystagec,Zstagec; 1229 1230 PetscFunctionBegin; 1231 ierr = TSRosWGetVecs(ts,fine,&Ydot,&Ystage,&Zdot,&Zstage);CHKERRQ(ierr); 1232 ierr = TSRosWGetVecs(ts,coarse,&Ydotc,&Ystagec,&Zdotc,&Zstagec);CHKERRQ(ierr); 1233 ierr = MatRestrict(restrct,Ydot,Ydotc);CHKERRQ(ierr); 1234 ierr = VecPointwiseMult(Ydotc,rscale,Ydotc);CHKERRQ(ierr); 1235 ierr = MatRestrict(restrct,Ystage,Ystagec);CHKERRQ(ierr); 1236 ierr = VecPointwiseMult(Ystagec,rscale,Ystagec);CHKERRQ(ierr); 1237 ierr = MatRestrict(restrct,Zdot,Zdotc);CHKERRQ(ierr); 1238 ierr = VecPointwiseMult(Zdotc,rscale,Zdotc);CHKERRQ(ierr); 1239 ierr = MatRestrict(restrct,Zstage,Zstagec);CHKERRQ(ierr); 1240 ierr = VecPointwiseMult(Zstagec,rscale,Zstagec);CHKERRQ(ierr); 1241 ierr = TSRosWRestoreVecs(ts,fine,&Ydot,&Ystage,&Zdot,&Zstage);CHKERRQ(ierr); 1242 ierr = TSRosWRestoreVecs(ts,coarse,&Ydotc,&Ystagec,&Zdotc,&Zstagec);CHKERRQ(ierr); 1243 PetscFunctionReturn(0); 1244 } 1245 1246 1247 static PetscErrorCode DMSubDomainHook_TSRosW(DM fine,DM coarse,void *ctx) 1248 { 1249 PetscFunctionBegin; 1250 PetscFunctionReturn(0); 1251 } 1252 1253 static PetscErrorCode DMSubDomainRestrictHook_TSRosW(DM dm,VecScatter gscat,VecScatter lscat,DM subdm,void *ctx) 1254 { 1255 TS ts = (TS)ctx; 1256 PetscErrorCode ierr; 1257 Vec Ydot,Zdot,Ystage,Zstage; 1258 Vec Ydots,Zdots,Ystages,Zstages; 1259 1260 PetscFunctionBegin; 1261 ierr = TSRosWGetVecs(ts,dm,&Ydot,&Ystage,&Zdot,&Zstage);CHKERRQ(ierr); 1262 ierr = TSRosWGetVecs(ts,subdm,&Ydots,&Ystages,&Zdots,&Zstages);CHKERRQ(ierr); 1263 1264 ierr = VecScatterBegin(gscat,Ydot,Ydots,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1265 ierr = VecScatterEnd(gscat,Ydot,Ydots,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1266 1267 ierr = VecScatterBegin(gscat,Ystage,Ystages,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1268 ierr = VecScatterEnd(gscat,Ystage,Ystages,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1269 1270 ierr = VecScatterBegin(gscat,Zdot,Zdots,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1271 ierr = VecScatterEnd(gscat,Zdot,Zdots,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1272 1273 ierr = VecScatterBegin(gscat,Zstage,Zstages,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1274 ierr = VecScatterEnd(gscat,Zstage,Zstages,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1275 1276 ierr = TSRosWRestoreVecs(ts,dm,&Ydot,&Ystage,&Zdot,&Zstage);CHKERRQ(ierr); 1277 ierr = TSRosWRestoreVecs(ts,subdm,&Ydots,&Ystages,&Zdots,&Zstages);CHKERRQ(ierr); 1278 PetscFunctionReturn(0); 1279 } 1280 1281 /* 1282 This defines the nonlinear equation that is to be solved with SNES 1283 G(U) = F[t0+Theta*dt, U, (U-U0)*shift] = 0 1284 */ 1285 static PetscErrorCode SNESTSFormFunction_RosW(SNES snes,Vec U,Vec F,TS ts) 1286 { 1287 TS_RosW *ros = (TS_RosW*)ts->data; 1288 PetscErrorCode ierr; 1289 Vec Ydot,Zdot,Ystage,Zstage; 1290 PetscReal shift = ros->scoeff / ts->time_step; 1291 DM dm,dmsave; 1292 1293 PetscFunctionBegin; 1294 ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 1295 ierr = TSRosWGetVecs(ts,dm,&Ydot,&Zdot,&Ystage,&Zstage);CHKERRQ(ierr); 1296 ierr = VecWAXPY(Ydot,shift,U,Zdot);CHKERRQ(ierr); /* Ydot = shift*U + Zdot */ 1297 ierr = VecWAXPY(Ystage,1.0,U,Zstage);CHKERRQ(ierr); /* Ystage = U + Zstage */ 1298 dmsave = ts->dm; 1299 ts->dm = dm; 1300 ierr = TSComputeIFunction(ts,ros->stage_time,Ystage,Ydot,F,PETSC_FALSE);CHKERRQ(ierr); 1301 ts->dm = dmsave; 1302 ierr = TSRosWRestoreVecs(ts,dm,&Ydot,&Zdot,&Ystage,&Zstage);CHKERRQ(ierr); 1303 PetscFunctionReturn(0); 1304 } 1305 1306 static PetscErrorCode SNESTSFormJacobian_RosW(SNES snes,Vec U,Mat A,Mat B,TS ts) 1307 { 1308 TS_RosW *ros = (TS_RosW*)ts->data; 1309 Vec Ydot,Zdot,Ystage,Zstage; 1310 PetscReal shift = ros->scoeff / ts->time_step; 1311 PetscErrorCode ierr; 1312 DM dm,dmsave; 1313 1314 PetscFunctionBegin; 1315 /* ros->Ydot and ros->Ystage have already been computed in SNESTSFormFunction_RosW (SNES guarantees this) */ 1316 ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 1317 ierr = TSRosWGetVecs(ts,dm,&Ydot,&Zdot,&Ystage,&Zstage);CHKERRQ(ierr); 1318 dmsave = ts->dm; 1319 ts->dm = dm; 1320 ierr = TSComputeIJacobian(ts,ros->stage_time,Ystage,Ydot,shift,A,B,PETSC_TRUE);CHKERRQ(ierr); 1321 ts->dm = dmsave; 1322 ierr = TSRosWRestoreVecs(ts,dm,&Ydot,&Zdot,&Ystage,&Zstage);CHKERRQ(ierr); 1323 PetscFunctionReturn(0); 1324 } 1325 1326 static PetscErrorCode TSRosWTableauSetUp(TS ts) 1327 { 1328 TS_RosW *ros = (TS_RosW*)ts->data; 1329 RosWTableau tab = ros->tableau; 1330 PetscErrorCode ierr; 1331 1332 PetscFunctionBegin; 1333 ierr = VecDuplicateVecs(ts->vec_sol,tab->s,&ros->Y);CHKERRQ(ierr); 1334 ierr = PetscMalloc1(tab->s,&ros->work);CHKERRQ(ierr); 1335 PetscFunctionReturn(0); 1336 } 1337 1338 static PetscErrorCode TSSetUp_RosW(TS ts) 1339 { 1340 TS_RosW *ros = (TS_RosW*)ts->data; 1341 PetscErrorCode ierr; 1342 DM dm; 1343 SNES snes; 1344 1345 PetscFunctionBegin; 1346 ierr = TSRosWTableauSetUp(ts);CHKERRQ(ierr); 1347 ierr = VecDuplicate(ts->vec_sol,&ros->Ydot);CHKERRQ(ierr); 1348 ierr = VecDuplicate(ts->vec_sol,&ros->Ystage);CHKERRQ(ierr); 1349 ierr = VecDuplicate(ts->vec_sol,&ros->Zdot);CHKERRQ(ierr); 1350 ierr = VecDuplicate(ts->vec_sol,&ros->Zstage);CHKERRQ(ierr); 1351 ierr = VecDuplicate(ts->vec_sol,&ros->vec_sol_prev);CHKERRQ(ierr); 1352 ierr = TSGetDM(ts,&dm);CHKERRQ(ierr); 1353 ierr = DMCoarsenHookAdd(dm,DMCoarsenHook_TSRosW,DMRestrictHook_TSRosW,ts);CHKERRQ(ierr); 1354 ierr = DMSubDomainHookAdd(dm,DMSubDomainHook_TSRosW,DMSubDomainRestrictHook_TSRosW,ts);CHKERRQ(ierr); 1355 /* Rosenbrock methods are linearly implicit, so set that unless the user has specifically asked for something else */ 1356 ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr); 1357 if (!((PetscObject)snes)->type_name) { 1358 ierr = SNESSetType(snes,SNESKSPONLY);CHKERRQ(ierr); 1359 } 1360 PetscFunctionReturn(0); 1361 } 1362 /*------------------------------------------------------------*/ 1363 1364 static PetscErrorCode TSSetFromOptions_RosW(PetscOptionItems *PetscOptionsObject,TS ts) 1365 { 1366 TS_RosW *ros = (TS_RosW*)ts->data; 1367 PetscErrorCode ierr; 1368 SNES snes; 1369 1370 PetscFunctionBegin; 1371 ierr = PetscOptionsHead(PetscOptionsObject,"RosW ODE solver options");CHKERRQ(ierr); 1372 { 1373 RosWTableauLink link; 1374 PetscInt count,choice; 1375 PetscBool flg; 1376 const char **namelist; 1377 1378 for (link=RosWTableauList,count=0; link; link=link->next,count++) ; 1379 ierr = PetscMalloc1(count,(char***)&namelist);CHKERRQ(ierr); 1380 for (link=RosWTableauList,count=0; link; link=link->next,count++) namelist[count] = link->tab.name; 1381 ierr = PetscOptionsEList("-ts_rosw_type","Family of Rosenbrock-W method","TSRosWSetType",(const char*const*)namelist,count,ros->tableau->name,&choice,&flg);CHKERRQ(ierr); 1382 if (flg) {ierr = TSRosWSetType(ts,namelist[choice]);CHKERRQ(ierr);} 1383 ierr = PetscFree(namelist);CHKERRQ(ierr); 1384 1385 ierr = PetscOptionsBool("-ts_rosw_recompute_jacobian","Recompute the Jacobian at each stage","TSRosWSetRecomputeJacobian",ros->recompute_jacobian,&ros->recompute_jacobian,NULL);CHKERRQ(ierr); 1386 } 1387 ierr = PetscOptionsTail();CHKERRQ(ierr); 1388 /* Rosenbrock methods are linearly implicit, so set that unless the user has specifically asked for something else */ 1389 ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr); 1390 if (!((PetscObject)snes)->type_name) { 1391 ierr = SNESSetType(snes,SNESKSPONLY);CHKERRQ(ierr); 1392 } 1393 PetscFunctionReturn(0); 1394 } 1395 1396 static PetscErrorCode TSView_RosW(TS ts,PetscViewer viewer) 1397 { 1398 TS_RosW *ros = (TS_RosW*)ts->data; 1399 PetscBool iascii; 1400 PetscErrorCode ierr; 1401 1402 PetscFunctionBegin; 1403 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 1404 if (iascii) { 1405 RosWTableau tab = ros->tableau; 1406 TSRosWType rostype; 1407 char buf[512]; 1408 PetscInt i; 1409 PetscReal abscissa[512]; 1410 ierr = TSRosWGetType(ts,&rostype);CHKERRQ(ierr); 1411 ierr = PetscViewerASCIIPrintf(viewer," Rosenbrock-W %s\n",rostype);CHKERRQ(ierr); 1412 ierr = PetscFormatRealArray(buf,sizeof(buf),"% 8.6f",tab->s,tab->ASum);CHKERRQ(ierr); 1413 ierr = PetscViewerASCIIPrintf(viewer," Abscissa of A = %s\n",buf);CHKERRQ(ierr); 1414 for (i=0; i<tab->s; i++) abscissa[i] = tab->ASum[i] + tab->Gamma[i]; 1415 ierr = PetscFormatRealArray(buf,sizeof(buf),"% 8.6f",tab->s,abscissa);CHKERRQ(ierr); 1416 ierr = PetscViewerASCIIPrintf(viewer," Abscissa of A+Gamma = %s\n",buf);CHKERRQ(ierr); 1417 } 1418 PetscFunctionReturn(0); 1419 } 1420 1421 static PetscErrorCode TSLoad_RosW(TS ts,PetscViewer viewer) 1422 { 1423 PetscErrorCode ierr; 1424 SNES snes; 1425 TSAdapt adapt; 1426 1427 PetscFunctionBegin; 1428 ierr = TSGetAdapt(ts,&adapt);CHKERRQ(ierr); 1429 ierr = TSAdaptLoad(adapt,viewer);CHKERRQ(ierr); 1430 ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr); 1431 ierr = SNESLoad(snes,viewer);CHKERRQ(ierr); 1432 /* function and Jacobian context for SNES when used with TS is always ts object */ 1433 ierr = SNESSetFunction(snes,NULL,NULL,ts);CHKERRQ(ierr); 1434 ierr = SNESSetJacobian(snes,NULL,NULL,NULL,ts);CHKERRQ(ierr); 1435 PetscFunctionReturn(0); 1436 } 1437 1438 /*@C 1439 TSRosWSetType - Set the type of Rosenbrock-W scheme 1440 1441 Logically collective 1442 1443 Input Parameter: 1444 + ts - timestepping context 1445 - roswtype - type of Rosenbrock-W scheme 1446 1447 Level: beginner 1448 1449 .seealso: TSRosWGetType(), TSROSW, TSROSW2M, TSROSW2P, TSROSWRA3PW, TSROSWRA34PW2, TSROSWRODAS3, TSROSWSANDU3, TSROSWASSP3P3S1C, TSROSWLASSP3P4S2C, TSROSWLLSSP3P4S2C, TSROSWARK3 1450 @*/ 1451 PetscErrorCode TSRosWSetType(TS ts,TSRosWType roswtype) 1452 { 1453 PetscErrorCode ierr; 1454 1455 PetscFunctionBegin; 1456 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1457 PetscValidCharPointer(roswtype,2); 1458 ierr = PetscTryMethod(ts,"TSRosWSetType_C",(TS,TSRosWType),(ts,roswtype));CHKERRQ(ierr); 1459 PetscFunctionReturn(0); 1460 } 1461 1462 /*@C 1463 TSRosWGetType - Get the type of Rosenbrock-W scheme 1464 1465 Logically collective 1466 1467 Input Parameter: 1468 . ts - timestepping context 1469 1470 Output Parameter: 1471 . rostype - type of Rosenbrock-W scheme 1472 1473 Level: intermediate 1474 1475 .seealso: TSRosWGetType() 1476 @*/ 1477 PetscErrorCode TSRosWGetType(TS ts,TSRosWType *rostype) 1478 { 1479 PetscErrorCode ierr; 1480 1481 PetscFunctionBegin; 1482 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1483 ierr = PetscUseMethod(ts,"TSRosWGetType_C",(TS,TSRosWType*),(ts,rostype));CHKERRQ(ierr); 1484 PetscFunctionReturn(0); 1485 } 1486 1487 /*@C 1488 TSRosWSetRecomputeJacobian - Set whether to recompute the Jacobian at each stage. The default is to update the Jacobian once per step. 1489 1490 Logically collective 1491 1492 Input Parameter: 1493 + ts - timestepping context 1494 - flg - PETSC_TRUE to recompute the Jacobian at each stage 1495 1496 Level: intermediate 1497 1498 .seealso: TSRosWGetType() 1499 @*/ 1500 PetscErrorCode TSRosWSetRecomputeJacobian(TS ts,PetscBool flg) 1501 { 1502 PetscErrorCode ierr; 1503 1504 PetscFunctionBegin; 1505 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1506 ierr = PetscTryMethod(ts,"TSRosWSetRecomputeJacobian_C",(TS,PetscBool),(ts,flg));CHKERRQ(ierr); 1507 PetscFunctionReturn(0); 1508 } 1509 1510 static PetscErrorCode TSRosWGetType_RosW(TS ts,TSRosWType *rostype) 1511 { 1512 TS_RosW *ros = (TS_RosW*)ts->data; 1513 1514 PetscFunctionBegin; 1515 *rostype = ros->tableau->name; 1516 PetscFunctionReturn(0); 1517 } 1518 1519 static PetscErrorCode TSRosWSetType_RosW(TS ts,TSRosWType rostype) 1520 { 1521 TS_RosW *ros = (TS_RosW*)ts->data; 1522 PetscErrorCode ierr; 1523 PetscBool match; 1524 RosWTableauLink link; 1525 1526 PetscFunctionBegin; 1527 if (ros->tableau) { 1528 ierr = PetscStrcmp(ros->tableau->name,rostype,&match);CHKERRQ(ierr); 1529 if (match) PetscFunctionReturn(0); 1530 } 1531 for (link = RosWTableauList; link; link=link->next) { 1532 ierr = PetscStrcmp(link->tab.name,rostype,&match);CHKERRQ(ierr); 1533 if (match) { 1534 if (ts->setupcalled) {ierr = TSRosWTableauReset(ts);CHKERRQ(ierr);} 1535 ros->tableau = &link->tab; 1536 if (ts->setupcalled) {ierr = TSRosWTableauSetUp(ts);CHKERRQ(ierr);} 1537 ts->default_adapt_type = ros->tableau->bembed ? TSADAPTBASIC : TSADAPTNONE; 1538 PetscFunctionReturn(0); 1539 } 1540 } 1541 SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_UNKNOWN_TYPE,"Could not find '%s'",rostype); 1542 PetscFunctionReturn(0); 1543 } 1544 1545 static PetscErrorCode TSRosWSetRecomputeJacobian_RosW(TS ts,PetscBool flg) 1546 { 1547 TS_RosW *ros = (TS_RosW*)ts->data; 1548 1549 PetscFunctionBegin; 1550 ros->recompute_jacobian = flg; 1551 PetscFunctionReturn(0); 1552 } 1553 1554 static PetscErrorCode TSDestroy_RosW(TS ts) 1555 { 1556 PetscErrorCode ierr; 1557 1558 PetscFunctionBegin; 1559 ierr = TSReset_RosW(ts);CHKERRQ(ierr); 1560 if (ts->dm) { 1561 ierr = DMCoarsenHookRemove(ts->dm,DMCoarsenHook_TSRosW,DMRestrictHook_TSRosW,ts);CHKERRQ(ierr); 1562 ierr = DMSubDomainHookRemove(ts->dm,DMSubDomainHook_TSRosW,DMSubDomainRestrictHook_TSRosW,ts);CHKERRQ(ierr); 1563 } 1564 ierr = PetscFree(ts->data);CHKERRQ(ierr); 1565 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSRosWGetType_C",NULL);CHKERRQ(ierr); 1566 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSRosWSetType_C",NULL);CHKERRQ(ierr); 1567 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSRosWSetRecomputeJacobian_C",NULL);CHKERRQ(ierr); 1568 PetscFunctionReturn(0); 1569 } 1570 1571 /* ------------------------------------------------------------ */ 1572 /*MC 1573 TSROSW - ODE solver using Rosenbrock-W schemes 1574 1575 These methods are intended for problems with well-separated time scales, especially when a slow scale is strongly 1576 nonlinear such that it is expensive to solve with a fully implicit method. The user should provide the stiff part 1577 of the equation using TSSetIFunction() and the non-stiff part with TSSetRHSFunction(). 1578 1579 Notes: 1580 This method currently only works with autonomous ODE and DAE. 1581 1582 Consider trying TSARKIMEX if the stiff part is strongly nonlinear. 1583 1584 Developer Notes: 1585 Rosenbrock-W methods are typically specified for autonomous ODE 1586 1587 $ udot = f(u) 1588 1589 by the stage equations 1590 1591 $ k_i = h f(u_0 + sum_j alpha_ij k_j) + h J sum_j gamma_ij k_j 1592 1593 and step completion formula 1594 1595 $ u_1 = u_0 + sum_j b_j k_j 1596 1597 with step size h and coefficients alpha_ij, gamma_ij, and b_i. Implementing the method in this form would require f(u) 1598 and the Jacobian J to be available, in addition to the shifted matrix I - h gamma_ii J. Following Hairer and Wanner, 1599 we define new variables for the stage equations 1600 1601 $ y_i = gamma_ij k_j 1602 1603 The k_j can be recovered because Gamma is invertible. Let C be the lower triangular part of Gamma^{-1} and define 1604 1605 $ A = Alpha Gamma^{-1}, bt^T = b^T Gamma^{-1} 1606 1607 to rewrite the method as 1608 1609 $ [M/(h gamma_ii) - J] y_i = f(u_0 + sum_j a_ij y_j) + M sum_j (c_ij/h) y_j 1610 $ u_1 = u_0 + sum_j bt_j y_j 1611 1612 where we have introduced the mass matrix M. Continue by defining 1613 1614 $ ydot_i = 1/(h gamma_ii) y_i - sum_j (c_ij/h) y_j 1615 1616 or, more compactly in tensor notation 1617 1618 $ Ydot = 1/h (Gamma^{-1} \otimes I) Y . 1619 1620 Note that Gamma^{-1} is lower triangular. With this definition of Ydot in terms of known quantities and the current 1621 stage y_i, the stage equations reduce to performing one Newton step (typically with a lagged Jacobian) on the 1622 equation 1623 1624 $ g(u_0 + sum_j a_ij y_j + y_i, ydot_i) = 0 1625 1626 with initial guess y_i = 0. 1627 1628 Level: beginner 1629 1630 .seealso: TSCreate(), TS, TSSetType(), TSRosWSetType(), TSRosWRegister(), TSROSWTHETA1, TSROSWTHETA2, TSROSW2M, TSROSW2P, TSROSWRA3PW, TSROSWRA34PW2, TSROSWRODAS3, 1631 TSROSWSANDU3, TSROSWASSP3P3S1C, TSROSWLASSP3P4S2C, TSROSWLLSSP3P4S2C, TSROSWGRK4T, TSROSWSHAMP4, TSROSWVELDD4, TSROSW4L 1632 M*/ 1633 PETSC_EXTERN PetscErrorCode TSCreate_RosW(TS ts) 1634 { 1635 TS_RosW *ros; 1636 PetscErrorCode ierr; 1637 1638 PetscFunctionBegin; 1639 ierr = TSRosWInitializePackage();CHKERRQ(ierr); 1640 1641 ts->ops->reset = TSReset_RosW; 1642 ts->ops->destroy = TSDestroy_RosW; 1643 ts->ops->view = TSView_RosW; 1644 ts->ops->load = TSLoad_RosW; 1645 ts->ops->setup = TSSetUp_RosW; 1646 ts->ops->step = TSStep_RosW; 1647 ts->ops->interpolate = TSInterpolate_RosW; 1648 ts->ops->evaluatestep = TSEvaluateStep_RosW; 1649 ts->ops->rollback = TSRollBack_RosW; 1650 ts->ops->setfromoptions = TSSetFromOptions_RosW; 1651 ts->ops->snesfunction = SNESTSFormFunction_RosW; 1652 ts->ops->snesjacobian = SNESTSFormJacobian_RosW; 1653 1654 ts->usessnes = PETSC_TRUE; 1655 1656 ierr = PetscNewLog(ts,&ros);CHKERRQ(ierr); 1657 ts->data = (void*)ros; 1658 1659 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSRosWGetType_C",TSRosWGetType_RosW);CHKERRQ(ierr); 1660 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSRosWSetType_C",TSRosWSetType_RosW);CHKERRQ(ierr); 1661 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSRosWSetRecomputeJacobian_C",TSRosWSetRecomputeJacobian_RosW);CHKERRQ(ierr); 1662 1663 ierr = TSRosWSetType(ts,TSRosWDefault);CHKERRQ(ierr); 1664 PetscFunctionReturn(0); 1665 } 1666