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 TSInitializePackage(). 632 633 Level: developer 634 635 .keywords: TS, TSRosW, initialize, package 636 .seealso: PetscInitialize() 637 @*/ 638 PetscErrorCode TSRosWInitializePackage(void) 639 { 640 PetscErrorCode ierr; 641 642 PetscFunctionBegin; 643 if (TSRosWPackageInitialized) PetscFunctionReturn(0); 644 TSRosWPackageInitialized = PETSC_TRUE; 645 ierr = TSRosWRegisterAll();CHKERRQ(ierr); 646 ierr = PetscRegisterFinalize(TSRosWFinalizePackage);CHKERRQ(ierr); 647 PetscFunctionReturn(0); 648 } 649 650 /*@C 651 TSRosWFinalizePackage - This function destroys everything in the TSRosW package. It is 652 called from PetscFinalize(). 653 654 Level: developer 655 656 .keywords: Petsc, destroy, package 657 .seealso: PetscFinalize() 658 @*/ 659 PetscErrorCode TSRosWFinalizePackage(void) 660 { 661 PetscErrorCode ierr; 662 663 PetscFunctionBegin; 664 TSRosWPackageInitialized = PETSC_FALSE; 665 ierr = TSRosWRegisterDestroy();CHKERRQ(ierr); 666 PetscFunctionReturn(0); 667 } 668 669 /*@C 670 TSRosWRegister - register a Rosenbrock W scheme by providing the entries in the Butcher tableau and optionally embedded approximations and interpolation 671 672 Not Collective, but the same schemes should be registered on all processes on which they will be used 673 674 Input Parameters: 675 + name - identifier for method 676 . order - approximation order of method 677 . s - number of stages, this is the dimension of the matrices below 678 . A - Table of propagated stage coefficients (dimension s*s, row-major), strictly lower triangular 679 . Gamma - Table of coefficients in implicit stage equations (dimension s*s, row-major), lower triangular with nonzero diagonal 680 . b - Step completion table (dimension s) 681 . bembed - Step completion table for a scheme of order one less (dimension s, NULL if no embedded scheme is available) 682 . pinterp - Order of the interpolation scheme, equal to the number of columns of binterpt 683 - binterpt - Coefficients of the interpolation formula (dimension s*pinterp) 684 685 Notes: 686 Several Rosenbrock W methods are provided, this function is only needed to create new methods. 687 688 Level: advanced 689 690 .keywords: TS, register 691 692 .seealso: TSRosW 693 @*/ 694 PetscErrorCode TSRosWRegister(TSRosWType name,PetscInt order,PetscInt s,const PetscReal A[],const PetscReal Gamma[],const PetscReal b[],const PetscReal bembed[], 695 PetscInt pinterp,const PetscReal binterpt[]) 696 { 697 PetscErrorCode ierr; 698 RosWTableauLink link; 699 RosWTableau t; 700 PetscInt i,j,k; 701 PetscScalar *GammaInv; 702 703 PetscFunctionBegin; 704 PetscValidCharPointer(name,1); 705 PetscValidPointer(A,4); 706 PetscValidPointer(Gamma,5); 707 PetscValidPointer(b,6); 708 if (bembed) PetscValidPointer(bembed,7); 709 710 ierr = TSRosWInitializePackage();CHKERRQ(ierr); 711 ierr = PetscCalloc1(1,&link);CHKERRQ(ierr); 712 t = &link->tab; 713 ierr = PetscStrallocpy(name,&t->name);CHKERRQ(ierr); 714 t->order = order; 715 t->s = s; 716 ierr = PetscMalloc5(s*s,&t->A,s*s,&t->Gamma,s,&t->b,s,&t->ASum,s,&t->GammaSum);CHKERRQ(ierr); 717 ierr = PetscMalloc5(s*s,&t->At,s,&t->bt,s*s,&t->GammaInv,s,&t->GammaZeroDiag,s*s,&t->GammaExplicitCorr);CHKERRQ(ierr); 718 ierr = PetscMemcpy(t->A,A,s*s*sizeof(A[0]));CHKERRQ(ierr); 719 ierr = PetscMemcpy(t->Gamma,Gamma,s*s*sizeof(Gamma[0]));CHKERRQ(ierr); 720 ierr = PetscMemcpy(t->GammaExplicitCorr,Gamma,s*s*sizeof(Gamma[0]));CHKERRQ(ierr); 721 ierr = PetscMemcpy(t->b,b,s*sizeof(b[0]));CHKERRQ(ierr); 722 if (bembed) { 723 ierr = PetscMalloc2(s,&t->bembed,s,&t->bembedt);CHKERRQ(ierr); 724 ierr = PetscMemcpy(t->bembed,bembed,s*sizeof(bembed[0]));CHKERRQ(ierr); 725 } 726 for (i=0; i<s; i++) { 727 t->ASum[i] = 0; 728 t->GammaSum[i] = 0; 729 for (j=0; j<s; j++) { 730 t->ASum[i] += A[i*s+j]; 731 t->GammaSum[i] += Gamma[i*s+j]; 732 } 733 } 734 ierr = PetscMalloc1(s*s,&GammaInv);CHKERRQ(ierr); /* Need to use Scalar for inverse, then convert back to Real */ 735 for (i=0; i<s*s; i++) GammaInv[i] = Gamma[i]; 736 for (i=0; i<s; i++) { 737 if (Gamma[i*s+i] == 0.0) { 738 GammaInv[i*s+i] = 1.0; 739 t->GammaZeroDiag[i] = PETSC_TRUE; 740 } else { 741 t->GammaZeroDiag[i] = PETSC_FALSE; 742 } 743 } 744 745 switch (s) { 746 case 1: GammaInv[0] = 1./GammaInv[0]; break; 747 case 2: ierr = PetscKernel_A_gets_inverse_A_2(GammaInv,0,PETSC_FALSE,NULL);CHKERRQ(ierr); break; 748 case 3: ierr = PetscKernel_A_gets_inverse_A_3(GammaInv,0,PETSC_FALSE,NULL);CHKERRQ(ierr); break; 749 case 4: ierr = PetscKernel_A_gets_inverse_A_4(GammaInv,0,PETSC_FALSE,NULL);CHKERRQ(ierr); break; 750 case 5: { 751 PetscInt ipvt5[5]; 752 MatScalar work5[5*5]; 753 ierr = PetscKernel_A_gets_inverse_A_5(GammaInv,ipvt5,work5,0,PETSC_FALSE,NULL);CHKERRQ(ierr); break; 754 } 755 case 6: ierr = PetscKernel_A_gets_inverse_A_6(GammaInv,0,PETSC_FALSE,NULL);CHKERRQ(ierr); break; 756 case 7: ierr = PetscKernel_A_gets_inverse_A_7(GammaInv,0,PETSC_FALSE,NULL);CHKERRQ(ierr); break; 757 default: SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented for %D stages",s); 758 } 759 for (i=0; i<s*s; i++) t->GammaInv[i] = PetscRealPart(GammaInv[i]); 760 ierr = PetscFree(GammaInv);CHKERRQ(ierr); 761 762 for (i=0; i<s; i++) { 763 for (k=0; k<i+1; k++) { 764 t->GammaExplicitCorr[i*s+k]=(t->GammaExplicitCorr[i*s+k])*(t->GammaInv[k*s+k]); 765 for (j=k+1; j<i+1; j++) { 766 t->GammaExplicitCorr[i*s+k]+=(t->GammaExplicitCorr[i*s+j])*(t->GammaInv[j*s+k]); 767 } 768 } 769 } 770 771 for (i=0; i<s; i++) { 772 for (j=0; j<s; j++) { 773 t->At[i*s+j] = 0; 774 for (k=0; k<s; k++) { 775 t->At[i*s+j] += t->A[i*s+k] * t->GammaInv[k*s+j]; 776 } 777 } 778 t->bt[i] = 0; 779 for (j=0; j<s; j++) { 780 t->bt[i] += t->b[j] * t->GammaInv[j*s+i]; 781 } 782 if (bembed) { 783 t->bembedt[i] = 0; 784 for (j=0; j<s; j++) { 785 t->bembedt[i] += t->bembed[j] * t->GammaInv[j*s+i]; 786 } 787 } 788 } 789 t->ccfl = 1.0; /* Fix this */ 790 791 t->pinterp = pinterp; 792 ierr = PetscMalloc1(s*pinterp,&t->binterpt);CHKERRQ(ierr); 793 ierr = PetscMemcpy(t->binterpt,binterpt,s*pinterp*sizeof(binterpt[0]));CHKERRQ(ierr); 794 link->next = RosWTableauList; 795 RosWTableauList = link; 796 PetscFunctionReturn(0); 797 } 798 799 /*@C 800 TSRosWRegisterRos4 - register a fourth order Rosenbrock scheme by providing paramter choices 801 802 Not Collective, but the same schemes should be registered on all processes on which they will be used 803 804 Input Parameters: 805 + name - identifier for method 806 . gamma - leading coefficient (diagonal entry) 807 . a2 - design parameter, see Table 7.2 of Hairer&Wanner 808 . a3 - design parameter or PETSC_DEFAULT to satisfy one of the order five conditions (Eq 7.22) 809 . b3 - design parameter, see Table 7.2 of Hairer&Wanner 810 . beta43 - design parameter or PETSC_DEFAULT to use Equation 7.21 of Hairer&Wanner 811 . e4 - design parameter for embedded method, see coefficient E4 in ros4.f code from Hairer 812 813 Notes: 814 This routine encodes the design of fourth order Rosenbrock methods as described in Hairer and Wanner volume 2. 815 It is used here to implement several methods from the book and can be used to experiment with new methods. 816 It was written this way instead of by copying coefficients in order to provide better than double precision satisfaction of the order conditions. 817 818 Level: developer 819 820 .keywords: TS, register 821 822 .seealso: TSRosW, TSRosWRegister() 823 @*/ 824 PetscErrorCode TSRosWRegisterRos4(TSRosWType name,PetscReal gamma,PetscReal a2,PetscReal a3,PetscReal b3,PetscReal e4) 825 { 826 PetscErrorCode ierr; 827 /* Declare numeric constants so they can be quad precision without being truncated at double */ 828 const PetscReal one = 1,two = 2,three = 3,four = 4,five = 5,six = 6,eight = 8,twelve = 12,twenty = 20,twentyfour = 24, 829 p32 = one/six - gamma + gamma*gamma, 830 p42 = one/eight - gamma/three, 831 p43 = one/twelve - gamma/three, 832 p44 = one/twentyfour - gamma/two + three/two*gamma*gamma - gamma*gamma*gamma, 833 p56 = one/twenty - gamma/four; 834 PetscReal a4,a32,a42,a43,b1,b2,b4,beta2p,beta3p,beta4p,beta32,beta42,beta43,beta32beta2p,beta4jbetajp; 835 PetscReal A[4][4],Gamma[4][4],b[4],bm[4]; 836 PetscScalar M[3][3],rhs[3]; 837 838 PetscFunctionBegin; 839 /* Step 1: choose Gamma (input) */ 840 /* Step 2: choose a2,a3,a4; b1,b2,b3,b4 to satisfy order conditions */ 841 if (a3 == PETSC_DEFAULT) a3 = (one/five - a2/four)/(one/four - a2/three); /* Eq 7.22 */ 842 a4 = a3; /* consequence of 7.20 */ 843 844 /* Solve order conditions 7.15a, 7.15c, 7.15e */ 845 M[0][0] = one; M[0][1] = one; M[0][2] = one; /* 7.15a */ 846 M[1][0] = 0.0; M[1][1] = a2*a2; M[1][2] = a4*a4; /* 7.15c */ 847 M[2][0] = 0.0; M[2][1] = a2*a2*a2; M[2][2] = a4*a4*a4; /* 7.15e */ 848 rhs[0] = one - b3; 849 rhs[1] = one/three - a3*a3*b3; 850 rhs[2] = one/four - a3*a3*a3*b3; 851 ierr = PetscKernel_A_gets_inverse_A_3(&M[0][0],0,PETSC_FALSE,NULL);CHKERRQ(ierr); 852 b1 = PetscRealPart(M[0][0]*rhs[0] + M[0][1]*rhs[1] + M[0][2]*rhs[2]); 853 b2 = PetscRealPart(M[1][0]*rhs[0] + M[1][1]*rhs[1] + M[1][2]*rhs[2]); 854 b4 = PetscRealPart(M[2][0]*rhs[0] + M[2][1]*rhs[1] + M[2][2]*rhs[2]); 855 856 /* Step 3 */ 857 beta43 = (p56 - a2*p43) / (b4*a3*a3*(a3 - a2)); /* 7.21 */ 858 beta32beta2p = p44 / (b4*beta43); /* 7.15h */ 859 beta4jbetajp = (p32 - b3*beta32beta2p) / b4; 860 M[0][0] = b2; M[0][1] = b3; M[0][2] = b4; 861 M[1][0] = a4*a4*beta32beta2p-a3*a3*beta4jbetajp; M[1][1] = a2*a2*beta4jbetajp; M[1][2] = -a2*a2*beta32beta2p; 862 M[2][0] = b4*beta43*a3*a3-p43; M[2][1] = -b4*beta43*a2*a2; M[2][2] = 0; 863 rhs[0] = one/two - gamma; rhs[1] = 0; rhs[2] = -a2*a2*p32; 864 ierr = PetscKernel_A_gets_inverse_A_3(&M[0][0],0,PETSC_FALSE,NULL);CHKERRQ(ierr); 865 beta2p = PetscRealPart(M[0][0]*rhs[0] + M[0][1]*rhs[1] + M[0][2]*rhs[2]); 866 beta3p = PetscRealPart(M[1][0]*rhs[0] + M[1][1]*rhs[1] + M[1][2]*rhs[2]); 867 beta4p = PetscRealPart(M[2][0]*rhs[0] + M[2][1]*rhs[1] + M[2][2]*rhs[2]); 868 869 /* Step 4: back-substitute */ 870 beta32 = beta32beta2p / beta2p; 871 beta42 = (beta4jbetajp - beta43*beta3p) / beta2p; 872 873 /* Step 5: 7.15f and 7.20, then 7.16 */ 874 a43 = 0; 875 a32 = p42 / (b3*a3*beta2p + b4*a4*beta2p); 876 a42 = a32; 877 878 A[0][0] = 0; A[0][1] = 0; A[0][2] = 0; A[0][3] = 0; 879 A[1][0] = a2; A[1][1] = 0; A[1][2] = 0; A[1][3] = 0; 880 A[2][0] = a3-a32; A[2][1] = a32; A[2][2] = 0; A[2][3] = 0; 881 A[3][0] = a4-a43-a42; A[3][1] = a42; A[3][2] = a43; A[3][3] = 0; 882 Gamma[0][0] = gamma; Gamma[0][1] = 0; Gamma[0][2] = 0; Gamma[0][3] = 0; 883 Gamma[1][0] = beta2p-A[1][0]; Gamma[1][1] = gamma; Gamma[1][2] = 0; Gamma[1][3] = 0; 884 Gamma[2][0] = beta3p-beta32-A[2][0]; Gamma[2][1] = beta32-A[2][1]; Gamma[2][2] = gamma; Gamma[2][3] = 0; 885 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; 886 b[0] = b1; b[1] = b2; b[2] = b3; b[3] = b4; 887 888 /* Construct embedded formula using given e4. We are solving Equation 7.18. */ 889 bm[3] = b[3] - e4*gamma; /* using definition of E4 */ 890 bm[2] = (p32 - beta4jbetajp*bm[3]) / (beta32*beta2p); /* fourth row of 7.18 */ 891 bm[1] = (one/two - gamma - beta3p*bm[2] - beta4p*bm[3]) / beta2p; /* second row */ 892 bm[0] = one - bm[1] - bm[2] - bm[3]; /* first row */ 893 894 { 895 const PetscReal misfit = a2*a2*bm[1] + a3*a3*bm[2] + a4*a4*bm[3] - one/three; 896 if (PetscAbs(misfit) > PETSC_SMALL) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Assumptions violated, could not construct a third order embedded method"); 897 } 898 ierr = TSRosWRegister(name,4,4,&A[0][0],&Gamma[0][0],b,bm,0,NULL);CHKERRQ(ierr); 899 PetscFunctionReturn(0); 900 } 901 902 /* 903 The step completion formula is 904 905 x1 = x0 + b^T Y 906 907 where Y is the multi-vector of stages corrections. This function can be called before or after ts->vec_sol has been 908 updated. Suppose we have a completion formula b and an embedded formula be of different order. We can write 909 910 x1e = x0 + be^T Y 911 = x1 - b^T Y + be^T Y 912 = x1 + (be - b)^T Y 913 914 so we can evaluate the method of different order even after the step has been optimistically completed. 915 */ 916 static PetscErrorCode TSEvaluateStep_RosW(TS ts,PetscInt order,Vec U,PetscBool *done) 917 { 918 TS_RosW *ros = (TS_RosW*)ts->data; 919 RosWTableau tab = ros->tableau; 920 PetscScalar *w = ros->work; 921 PetscInt i; 922 PetscErrorCode ierr; 923 924 PetscFunctionBegin; 925 if (order == tab->order) { 926 if (ros->status == TS_STEP_INCOMPLETE) { /* Use standard completion formula */ 927 ierr = VecCopy(ts->vec_sol,U);CHKERRQ(ierr); 928 for (i=0; i<tab->s; i++) w[i] = tab->bt[i]; 929 ierr = VecMAXPY(U,tab->s,w,ros->Y);CHKERRQ(ierr); 930 } else {ierr = VecCopy(ts->vec_sol,U);CHKERRQ(ierr);} 931 if (done) *done = PETSC_TRUE; 932 PetscFunctionReturn(0); 933 } else if (order == tab->order-1) { 934 if (!tab->bembedt) goto unavailable; 935 if (ros->status == TS_STEP_INCOMPLETE) { /* Use embedded completion formula */ 936 ierr = VecCopy(ts->vec_sol,U);CHKERRQ(ierr); 937 for (i=0; i<tab->s; i++) w[i] = tab->bembedt[i]; 938 ierr = VecMAXPY(U,tab->s,w,ros->Y);CHKERRQ(ierr); 939 } else { /* Use rollback-and-recomplete formula (bembedt - bt) */ 940 for (i=0; i<tab->s; i++) w[i] = tab->bembedt[i] - tab->bt[i]; 941 ierr = VecCopy(ts->vec_sol,U);CHKERRQ(ierr); 942 ierr = VecMAXPY(U,tab->s,w,ros->Y);CHKERRQ(ierr); 943 } 944 if (done) *done = PETSC_TRUE; 945 PetscFunctionReturn(0); 946 } 947 unavailable: 948 if (done) *done = PETSC_FALSE; 949 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); 950 PetscFunctionReturn(0); 951 } 952 953 static PetscErrorCode TSRollBack_RosW(TS ts) 954 { 955 TS_RosW *ros = (TS_RosW*)ts->data; 956 PetscErrorCode ierr; 957 958 PetscFunctionBegin; 959 ierr = VecCopy(ros->vec_sol_prev,ts->vec_sol);CHKERRQ(ierr); 960 PetscFunctionReturn(0); 961 } 962 963 static PetscErrorCode TSStep_RosW(TS ts) 964 { 965 TS_RosW *ros = (TS_RosW*)ts->data; 966 RosWTableau tab = ros->tableau; 967 const PetscInt s = tab->s; 968 const PetscReal *At = tab->At,*Gamma = tab->Gamma,*ASum = tab->ASum,*GammaInv = tab->GammaInv; 969 const PetscReal *GammaExplicitCorr = tab->GammaExplicitCorr; 970 const PetscBool *GammaZeroDiag = tab->GammaZeroDiag; 971 PetscScalar *w = ros->work; 972 Vec *Y = ros->Y,Ydot = ros->Ydot,Zdot = ros->Zdot,Zstage = ros->Zstage; 973 SNES snes; 974 TSAdapt adapt; 975 PetscInt i,j,its,lits; 976 PetscInt rejections = 0; 977 PetscBool stageok,accept = PETSC_TRUE; 978 PetscReal next_time_step = ts->time_step; 979 PetscErrorCode ierr; 980 981 PetscFunctionBegin; 982 if (!ts->steprollback) { 983 ierr = VecCopy(ts->vec_sol,ros->vec_sol_prev);CHKERRQ(ierr); 984 } 985 986 ros->status = TS_STEP_INCOMPLETE; 987 while (!ts->reason && ros->status != TS_STEP_COMPLETE) { 988 const PetscReal h = ts->time_step; 989 for (i=0; i<s; i++) { 990 ros->stage_time = ts->ptime + h*ASum[i]; 991 ierr = TSPreStage(ts,ros->stage_time);CHKERRQ(ierr); 992 if (GammaZeroDiag[i]) { 993 ros->stage_explicit = PETSC_TRUE; 994 ros->scoeff = 1.; 995 } else { 996 ros->stage_explicit = PETSC_FALSE; 997 ros->scoeff = 1./Gamma[i*s+i]; 998 } 999 1000 ierr = VecCopy(ts->vec_sol,Zstage);CHKERRQ(ierr); 1001 for (j=0; j<i; j++) w[j] = At[i*s+j]; 1002 ierr = VecMAXPY(Zstage,i,w,Y);CHKERRQ(ierr); 1003 1004 for (j=0; j<i; j++) w[j] = 1./h * GammaInv[i*s+j]; 1005 ierr = VecZeroEntries(Zdot);CHKERRQ(ierr); 1006 ierr = VecMAXPY(Zdot,i,w,Y);CHKERRQ(ierr); 1007 1008 /* Initial guess taken from last stage */ 1009 ierr = VecZeroEntries(Y[i]);CHKERRQ(ierr); 1010 1011 if (!ros->stage_explicit) { 1012 ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr); 1013 if (!ros->recompute_jacobian && !i) { 1014 ierr = SNESSetLagJacobian(snes,-2);CHKERRQ(ierr); /* Recompute the Jacobian on this solve, but not again */ 1015 } 1016 ierr = SNESSolve(snes,NULL,Y[i]);CHKERRQ(ierr); 1017 ierr = SNESGetIterationNumber(snes,&its);CHKERRQ(ierr); 1018 ierr = SNESGetLinearSolveIterations(snes,&lits);CHKERRQ(ierr); 1019 ts->snes_its += its; ts->ksp_its += lits; 1020 } else { 1021 Mat J,Jp; 1022 ierr = VecZeroEntries(Ydot);CHKERRQ(ierr); /* Evaluate Y[i]=G(t,Ydot=0,Zstage) */ 1023 ierr = TSComputeIFunction(ts,ros->stage_time,Zstage,Ydot,Y[i],PETSC_FALSE);CHKERRQ(ierr); 1024 ierr = VecScale(Y[i],-1.0);CHKERRQ(ierr); 1025 ierr = VecAXPY(Y[i],-1.0,Zdot);CHKERRQ(ierr); /*Y[i] = F(Zstage)-Zdot[=GammaInv*Y]*/ 1026 1027 ierr = VecZeroEntries(Zstage);CHKERRQ(ierr); /* Zstage = GammaExplicitCorr[i,j] * Y[j] */ 1028 for (j=0; j<i; j++) w[j] = GammaExplicitCorr[i*s+j]; 1029 ierr = VecMAXPY(Zstage,i,w,Y);CHKERRQ(ierr); 1030 1031 /* Y[i] = Y[i] + Jac*Zstage[=Jac*GammaExplicitCorr[i,j] * Y[j]] */ 1032 ierr = TSGetIJacobian(ts,&J,&Jp,NULL,NULL);CHKERRQ(ierr); 1033 ierr = TSComputeIJacobian(ts,ros->stage_time,ts->vec_sol,Ydot,0,J,Jp,PETSC_FALSE);CHKERRQ(ierr); 1034 ierr = MatMult(J,Zstage,Zdot);CHKERRQ(ierr); 1035 ierr = VecAXPY(Y[i],-1.0,Zdot);CHKERRQ(ierr); 1036 ts->ksp_its += 1; 1037 1038 ierr = VecScale(Y[i],h);CHKERRQ(ierr); 1039 } 1040 ierr = TSPostStage(ts,ros->stage_time,i,Y);CHKERRQ(ierr); 1041 ierr = TSGetAdapt(ts,&adapt);CHKERRQ(ierr); 1042 ierr = TSAdaptCheckStage(adapt,ts,ros->stage_time,Y[i],&stageok);CHKERRQ(ierr); 1043 if (!stageok) goto reject_step; 1044 } 1045 1046 ros->status = TS_STEP_INCOMPLETE; 1047 ierr = TSEvaluateStep_RosW(ts,tab->order,ts->vec_sol,NULL);CHKERRQ(ierr); 1048 ros->status = TS_STEP_PENDING; 1049 ierr = TSGetAdapt(ts,&adapt);CHKERRQ(ierr); 1050 ierr = TSAdaptCandidatesClear(adapt);CHKERRQ(ierr); 1051 ierr = TSAdaptCandidateAdd(adapt,tab->name,tab->order,1,tab->ccfl,(PetscReal)tab->s,PETSC_TRUE);CHKERRQ(ierr); 1052 ierr = TSAdaptChoose(adapt,ts,ts->time_step,NULL,&next_time_step,&accept);CHKERRQ(ierr); 1053 ros->status = accept ? TS_STEP_COMPLETE : TS_STEP_INCOMPLETE; 1054 if (!accept) { /* Roll back the current step */ 1055 ierr = TSRollBack_RosW(ts);CHKERRQ(ierr); 1056 ts->time_step = next_time_step; 1057 goto reject_step; 1058 } 1059 1060 ts->ptime += ts->time_step; 1061 ts->time_step = next_time_step; 1062 break; 1063 1064 reject_step: 1065 ts->reject++; accept = PETSC_FALSE; 1066 if (!ts->reason && ++rejections > ts->max_reject && ts->max_reject >= 0) { 1067 ts->reason = TS_DIVERGED_STEP_REJECTED; 1068 ierr = PetscInfo2(ts,"Step=%D, step rejections %D greater than current TS allowed, stopping solve\n",ts->steps,rejections);CHKERRQ(ierr); 1069 } 1070 } 1071 PetscFunctionReturn(0); 1072 } 1073 1074 static PetscErrorCode TSInterpolate_RosW(TS ts,PetscReal itime,Vec U) 1075 { 1076 TS_RosW *ros = (TS_RosW*)ts->data; 1077 PetscInt s = ros->tableau->s,pinterp = ros->tableau->pinterp,i,j; 1078 PetscReal h; 1079 PetscReal tt,t; 1080 PetscScalar *bt; 1081 const PetscReal *Bt = ros->tableau->binterpt; 1082 PetscErrorCode ierr; 1083 const PetscReal *GammaInv = ros->tableau->GammaInv; 1084 PetscScalar *w = ros->work; 1085 Vec *Y = ros->Y; 1086 1087 PetscFunctionBegin; 1088 if (!Bt) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSRosW %s does not have an interpolation formula",ros->tableau->name); 1089 1090 switch (ros->status) { 1091 case TS_STEP_INCOMPLETE: 1092 case TS_STEP_PENDING: 1093 h = ts->time_step; 1094 t = (itime - ts->ptime)/h; 1095 break; 1096 case TS_STEP_COMPLETE: 1097 h = ts->ptime - ts->ptime_prev; 1098 t = (itime - ts->ptime)/h + 1; /* In the interval [0,1] */ 1099 break; 1100 default: SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_PLIB,"Invalid TSStepStatus"); 1101 } 1102 ierr = PetscMalloc1(s,&bt);CHKERRQ(ierr); 1103 for (i=0; i<s; i++) bt[i] = 0; 1104 for (j=0,tt=t; j<pinterp; j++,tt*=t) { 1105 for (i=0; i<s; i++) { 1106 bt[i] += Bt[i*pinterp+j] * tt; 1107 } 1108 } 1109 1110 /* y(t+tt*h) = y(t) + Sum bt(tt) * GammaInv * Ydot */ 1111 /* U <- 0*/ 1112 ierr = VecZeroEntries(U);CHKERRQ(ierr); 1113 /* U <- Sum bt_i * GammaInv(i,1:i) * Y(1:i) */ 1114 for (j=0; j<s; j++) w[j] = 0; 1115 for (j=0; j<s; j++) { 1116 for (i=j; i<s; i++) { 1117 w[j] += bt[i]*GammaInv[i*s+j]; 1118 } 1119 } 1120 ierr = VecMAXPY(U,i,w,Y);CHKERRQ(ierr); 1121 /* U <- y(t) + U */ 1122 ierr = VecAXPY(U,1,ros->vec_sol_prev);CHKERRQ(ierr); 1123 1124 ierr = PetscFree(bt);CHKERRQ(ierr); 1125 PetscFunctionReturn(0); 1126 } 1127 1128 /*------------------------------------------------------------*/ 1129 1130 static PetscErrorCode TSRosWTableauReset(TS ts) 1131 { 1132 TS_RosW *ros = (TS_RosW*)ts->data; 1133 RosWTableau tab = ros->tableau; 1134 PetscErrorCode ierr; 1135 1136 PetscFunctionBegin; 1137 if (!tab) PetscFunctionReturn(0); 1138 ierr = VecDestroyVecs(tab->s,&ros->Y);CHKERRQ(ierr); 1139 ierr = PetscFree(ros->work);CHKERRQ(ierr); 1140 PetscFunctionReturn(0); 1141 } 1142 1143 static PetscErrorCode TSReset_RosW(TS ts) 1144 { 1145 TS_RosW *ros = (TS_RosW*)ts->data; 1146 PetscErrorCode ierr; 1147 1148 PetscFunctionBegin; 1149 ierr = TSRosWTableauReset(ts);CHKERRQ(ierr); 1150 ierr = VecDestroy(&ros->Ydot);CHKERRQ(ierr); 1151 ierr = VecDestroy(&ros->Ystage);CHKERRQ(ierr); 1152 ierr = VecDestroy(&ros->Zdot);CHKERRQ(ierr); 1153 ierr = VecDestroy(&ros->Zstage);CHKERRQ(ierr); 1154 ierr = VecDestroy(&ros->vec_sol_prev);CHKERRQ(ierr); 1155 PetscFunctionReturn(0); 1156 } 1157 1158 static PetscErrorCode TSRosWGetVecs(TS ts,DM dm,Vec *Ydot,Vec *Zdot,Vec *Ystage,Vec *Zstage) 1159 { 1160 TS_RosW *rw = (TS_RosW*)ts->data; 1161 PetscErrorCode ierr; 1162 1163 PetscFunctionBegin; 1164 if (Ydot) { 1165 if (dm && dm != ts->dm) { 1166 ierr = DMGetNamedGlobalVector(dm,"TSRosW_Ydot",Ydot);CHKERRQ(ierr); 1167 } else *Ydot = rw->Ydot; 1168 } 1169 if (Zdot) { 1170 if (dm && dm != ts->dm) { 1171 ierr = DMGetNamedGlobalVector(dm,"TSRosW_Zdot",Zdot);CHKERRQ(ierr); 1172 } else *Zdot = rw->Zdot; 1173 } 1174 if (Ystage) { 1175 if (dm && dm != ts->dm) { 1176 ierr = DMGetNamedGlobalVector(dm,"TSRosW_Ystage",Ystage);CHKERRQ(ierr); 1177 } else *Ystage = rw->Ystage; 1178 } 1179 if (Zstage) { 1180 if (dm && dm != ts->dm) { 1181 ierr = DMGetNamedGlobalVector(dm,"TSRosW_Zstage",Zstage);CHKERRQ(ierr); 1182 } else *Zstage = rw->Zstage; 1183 } 1184 PetscFunctionReturn(0); 1185 } 1186 1187 1188 static PetscErrorCode TSRosWRestoreVecs(TS ts,DM dm,Vec *Ydot,Vec *Zdot, Vec *Ystage, Vec *Zstage) 1189 { 1190 PetscErrorCode ierr; 1191 1192 PetscFunctionBegin; 1193 if (Ydot) { 1194 if (dm && dm != ts->dm) { 1195 ierr = DMRestoreNamedGlobalVector(dm,"TSRosW_Ydot",Ydot);CHKERRQ(ierr); 1196 } 1197 } 1198 if (Zdot) { 1199 if (dm && dm != ts->dm) { 1200 ierr = DMRestoreNamedGlobalVector(dm,"TSRosW_Zdot",Zdot);CHKERRQ(ierr); 1201 } 1202 } 1203 if (Ystage) { 1204 if (dm && dm != ts->dm) { 1205 ierr = DMRestoreNamedGlobalVector(dm,"TSRosW_Ystage",Ystage);CHKERRQ(ierr); 1206 } 1207 } 1208 if (Zstage) { 1209 if (dm && dm != ts->dm) { 1210 ierr = DMRestoreNamedGlobalVector(dm,"TSRosW_Zstage",Zstage);CHKERRQ(ierr); 1211 } 1212 } 1213 PetscFunctionReturn(0); 1214 } 1215 1216 static PetscErrorCode DMCoarsenHook_TSRosW(DM fine,DM coarse,void *ctx) 1217 { 1218 PetscFunctionBegin; 1219 PetscFunctionReturn(0); 1220 } 1221 1222 static PetscErrorCode DMRestrictHook_TSRosW(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse,void *ctx) 1223 { 1224 TS ts = (TS)ctx; 1225 PetscErrorCode ierr; 1226 Vec Ydot,Zdot,Ystage,Zstage; 1227 Vec Ydotc,Zdotc,Ystagec,Zstagec; 1228 1229 PetscFunctionBegin; 1230 ierr = TSRosWGetVecs(ts,fine,&Ydot,&Ystage,&Zdot,&Zstage);CHKERRQ(ierr); 1231 ierr = TSRosWGetVecs(ts,coarse,&Ydotc,&Ystagec,&Zdotc,&Zstagec);CHKERRQ(ierr); 1232 ierr = MatRestrict(restrct,Ydot,Ydotc);CHKERRQ(ierr); 1233 ierr = VecPointwiseMult(Ydotc,rscale,Ydotc);CHKERRQ(ierr); 1234 ierr = MatRestrict(restrct,Ystage,Ystagec);CHKERRQ(ierr); 1235 ierr = VecPointwiseMult(Ystagec,rscale,Ystagec);CHKERRQ(ierr); 1236 ierr = MatRestrict(restrct,Zdot,Zdotc);CHKERRQ(ierr); 1237 ierr = VecPointwiseMult(Zdotc,rscale,Zdotc);CHKERRQ(ierr); 1238 ierr = MatRestrict(restrct,Zstage,Zstagec);CHKERRQ(ierr); 1239 ierr = VecPointwiseMult(Zstagec,rscale,Zstagec);CHKERRQ(ierr); 1240 ierr = TSRosWRestoreVecs(ts,fine,&Ydot,&Ystage,&Zdot,&Zstage);CHKERRQ(ierr); 1241 ierr = TSRosWRestoreVecs(ts,coarse,&Ydotc,&Ystagec,&Zdotc,&Zstagec);CHKERRQ(ierr); 1242 PetscFunctionReturn(0); 1243 } 1244 1245 1246 static PetscErrorCode DMSubDomainHook_TSRosW(DM fine,DM coarse,void *ctx) 1247 { 1248 PetscFunctionBegin; 1249 PetscFunctionReturn(0); 1250 } 1251 1252 static PetscErrorCode DMSubDomainRestrictHook_TSRosW(DM dm,VecScatter gscat,VecScatter lscat,DM subdm,void *ctx) 1253 { 1254 TS ts = (TS)ctx; 1255 PetscErrorCode ierr; 1256 Vec Ydot,Zdot,Ystage,Zstage; 1257 Vec Ydots,Zdots,Ystages,Zstages; 1258 1259 PetscFunctionBegin; 1260 ierr = TSRosWGetVecs(ts,dm,&Ydot,&Ystage,&Zdot,&Zstage);CHKERRQ(ierr); 1261 ierr = TSRosWGetVecs(ts,subdm,&Ydots,&Ystages,&Zdots,&Zstages);CHKERRQ(ierr); 1262 1263 ierr = VecScatterBegin(gscat,Ydot,Ydots,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1264 ierr = VecScatterEnd(gscat,Ydot,Ydots,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1265 1266 ierr = VecScatterBegin(gscat,Ystage,Ystages,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1267 ierr = VecScatterEnd(gscat,Ystage,Ystages,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1268 1269 ierr = VecScatterBegin(gscat,Zdot,Zdots,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1270 ierr = VecScatterEnd(gscat,Zdot,Zdots,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1271 1272 ierr = VecScatterBegin(gscat,Zstage,Zstages,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1273 ierr = VecScatterEnd(gscat,Zstage,Zstages,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1274 1275 ierr = TSRosWRestoreVecs(ts,dm,&Ydot,&Ystage,&Zdot,&Zstage);CHKERRQ(ierr); 1276 ierr = TSRosWRestoreVecs(ts,subdm,&Ydots,&Ystages,&Zdots,&Zstages);CHKERRQ(ierr); 1277 PetscFunctionReturn(0); 1278 } 1279 1280 /* 1281 This defines the nonlinear equation that is to be solved with SNES 1282 G(U) = F[t0+Theta*dt, U, (U-U0)*shift] = 0 1283 */ 1284 static PetscErrorCode SNESTSFormFunction_RosW(SNES snes,Vec U,Vec F,TS ts) 1285 { 1286 TS_RosW *ros = (TS_RosW*)ts->data; 1287 PetscErrorCode ierr; 1288 Vec Ydot,Zdot,Ystage,Zstage; 1289 PetscReal shift = ros->scoeff / ts->time_step; 1290 DM dm,dmsave; 1291 1292 PetscFunctionBegin; 1293 ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 1294 ierr = TSRosWGetVecs(ts,dm,&Ydot,&Zdot,&Ystage,&Zstage);CHKERRQ(ierr); 1295 ierr = VecWAXPY(Ydot,shift,U,Zdot);CHKERRQ(ierr); /* Ydot = shift*U + Zdot */ 1296 ierr = VecWAXPY(Ystage,1.0,U,Zstage);CHKERRQ(ierr); /* Ystage = U + Zstage */ 1297 dmsave = ts->dm; 1298 ts->dm = dm; 1299 ierr = TSComputeIFunction(ts,ros->stage_time,Ystage,Ydot,F,PETSC_FALSE);CHKERRQ(ierr); 1300 ts->dm = dmsave; 1301 ierr = TSRosWRestoreVecs(ts,dm,&Ydot,&Zdot,&Ystage,&Zstage);CHKERRQ(ierr); 1302 PetscFunctionReturn(0); 1303 } 1304 1305 static PetscErrorCode SNESTSFormJacobian_RosW(SNES snes,Vec U,Mat A,Mat B,TS ts) 1306 { 1307 TS_RosW *ros = (TS_RosW*)ts->data; 1308 Vec Ydot,Zdot,Ystage,Zstage; 1309 PetscReal shift = ros->scoeff / ts->time_step; 1310 PetscErrorCode ierr; 1311 DM dm,dmsave; 1312 1313 PetscFunctionBegin; 1314 /* ros->Ydot and ros->Ystage have already been computed in SNESTSFormFunction_RosW (SNES guarantees this) */ 1315 ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 1316 ierr = TSRosWGetVecs(ts,dm,&Ydot,&Zdot,&Ystage,&Zstage);CHKERRQ(ierr); 1317 dmsave = ts->dm; 1318 ts->dm = dm; 1319 ierr = TSComputeIJacobian(ts,ros->stage_time,Ystage,Ydot,shift,A,B,PETSC_TRUE);CHKERRQ(ierr); 1320 ts->dm = dmsave; 1321 ierr = TSRosWRestoreVecs(ts,dm,&Ydot,&Zdot,&Ystage,&Zstage);CHKERRQ(ierr); 1322 PetscFunctionReturn(0); 1323 } 1324 1325 static PetscErrorCode TSRosWTableauSetUp(TS ts) 1326 { 1327 TS_RosW *ros = (TS_RosW*)ts->data; 1328 RosWTableau tab = ros->tableau; 1329 PetscErrorCode ierr; 1330 1331 PetscFunctionBegin; 1332 ierr = VecDuplicateVecs(ts->vec_sol,tab->s,&ros->Y);CHKERRQ(ierr); 1333 ierr = PetscMalloc1(tab->s,&ros->work);CHKERRQ(ierr); 1334 PetscFunctionReturn(0); 1335 } 1336 1337 static PetscErrorCode TSSetUp_RosW(TS ts) 1338 { 1339 TS_RosW *ros = (TS_RosW*)ts->data; 1340 PetscErrorCode ierr; 1341 DM dm; 1342 SNES snes; 1343 1344 PetscFunctionBegin; 1345 ierr = TSRosWTableauSetUp(ts);CHKERRQ(ierr); 1346 ierr = VecDuplicate(ts->vec_sol,&ros->Ydot);CHKERRQ(ierr); 1347 ierr = VecDuplicate(ts->vec_sol,&ros->Ystage);CHKERRQ(ierr); 1348 ierr = VecDuplicate(ts->vec_sol,&ros->Zdot);CHKERRQ(ierr); 1349 ierr = VecDuplicate(ts->vec_sol,&ros->Zstage);CHKERRQ(ierr); 1350 ierr = VecDuplicate(ts->vec_sol,&ros->vec_sol_prev);CHKERRQ(ierr); 1351 ierr = TSGetDM(ts,&dm);CHKERRQ(ierr); 1352 ierr = DMCoarsenHookAdd(dm,DMCoarsenHook_TSRosW,DMRestrictHook_TSRosW,ts);CHKERRQ(ierr); 1353 ierr = DMSubDomainHookAdd(dm,DMSubDomainHook_TSRosW,DMSubDomainRestrictHook_TSRosW,ts);CHKERRQ(ierr); 1354 /* Rosenbrock methods are linearly implicit, so set that unless the user has specifically asked for something else */ 1355 ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr); 1356 if (!((PetscObject)snes)->type_name) { 1357 ierr = SNESSetType(snes,SNESKSPONLY);CHKERRQ(ierr); 1358 } 1359 PetscFunctionReturn(0); 1360 } 1361 /*------------------------------------------------------------*/ 1362 1363 static PetscErrorCode TSSetFromOptions_RosW(PetscOptionItems *PetscOptionsObject,TS ts) 1364 { 1365 TS_RosW *ros = (TS_RosW*)ts->data; 1366 PetscErrorCode ierr; 1367 SNES snes; 1368 1369 PetscFunctionBegin; 1370 ierr = PetscOptionsHead(PetscOptionsObject,"RosW ODE solver options");CHKERRQ(ierr); 1371 { 1372 RosWTableauLink link; 1373 PetscInt count,choice; 1374 PetscBool flg; 1375 const char **namelist; 1376 1377 for (link=RosWTableauList,count=0; link; link=link->next,count++) ; 1378 ierr = PetscMalloc1(count,(char***)&namelist);CHKERRQ(ierr); 1379 for (link=RosWTableauList,count=0; link; link=link->next,count++) namelist[count] = link->tab.name; 1380 ierr = PetscOptionsEList("-ts_rosw_type","Family of Rosenbrock-W method","TSRosWSetType",(const char*const*)namelist,count,ros->tableau->name,&choice,&flg);CHKERRQ(ierr); 1381 if (flg) {ierr = TSRosWSetType(ts,namelist[choice]);CHKERRQ(ierr);} 1382 ierr = PetscFree(namelist);CHKERRQ(ierr); 1383 1384 ierr = PetscOptionsBool("-ts_rosw_recompute_jacobian","Recompute the Jacobian at each stage","TSRosWSetRecomputeJacobian",ros->recompute_jacobian,&ros->recompute_jacobian,NULL);CHKERRQ(ierr); 1385 } 1386 ierr = PetscOptionsTail();CHKERRQ(ierr); 1387 /* Rosenbrock methods are linearly implicit, so set that unless the user has specifically asked for something else */ 1388 ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr); 1389 if (!((PetscObject)snes)->type_name) { 1390 ierr = SNESSetType(snes,SNESKSPONLY);CHKERRQ(ierr); 1391 } 1392 PetscFunctionReturn(0); 1393 } 1394 1395 static PetscErrorCode TSView_RosW(TS ts,PetscViewer viewer) 1396 { 1397 TS_RosW *ros = (TS_RosW*)ts->data; 1398 PetscBool iascii; 1399 PetscErrorCode ierr; 1400 1401 PetscFunctionBegin; 1402 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 1403 if (iascii) { 1404 RosWTableau tab = ros->tableau; 1405 TSRosWType rostype; 1406 char buf[512]; 1407 PetscInt i; 1408 PetscReal abscissa[512]; 1409 ierr = TSRosWGetType(ts,&rostype);CHKERRQ(ierr); 1410 ierr = PetscViewerASCIIPrintf(viewer," Rosenbrock-W %s\n",rostype);CHKERRQ(ierr); 1411 ierr = PetscFormatRealArray(buf,sizeof(buf),"% 8.6f",tab->s,tab->ASum);CHKERRQ(ierr); 1412 ierr = PetscViewerASCIIPrintf(viewer," Abscissa of A = %s\n",buf);CHKERRQ(ierr); 1413 for (i=0; i<tab->s; i++) abscissa[i] = tab->ASum[i] + tab->Gamma[i]; 1414 ierr = PetscFormatRealArray(buf,sizeof(buf),"% 8.6f",tab->s,abscissa);CHKERRQ(ierr); 1415 ierr = PetscViewerASCIIPrintf(viewer," Abscissa of A+Gamma = %s\n",buf);CHKERRQ(ierr); 1416 } 1417 PetscFunctionReturn(0); 1418 } 1419 1420 static PetscErrorCode TSLoad_RosW(TS ts,PetscViewer viewer) 1421 { 1422 PetscErrorCode ierr; 1423 SNES snes; 1424 TSAdapt adapt; 1425 1426 PetscFunctionBegin; 1427 ierr = TSGetAdapt(ts,&adapt);CHKERRQ(ierr); 1428 ierr = TSAdaptLoad(adapt,viewer);CHKERRQ(ierr); 1429 ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr); 1430 ierr = SNESLoad(snes,viewer);CHKERRQ(ierr); 1431 /* function and Jacobian context for SNES when used with TS is always ts object */ 1432 ierr = SNESSetFunction(snes,NULL,NULL,ts);CHKERRQ(ierr); 1433 ierr = SNESSetJacobian(snes,NULL,NULL,NULL,ts);CHKERRQ(ierr); 1434 PetscFunctionReturn(0); 1435 } 1436 1437 /*@C 1438 TSRosWSetType - Set the type of Rosenbrock-W scheme 1439 1440 Logically collective 1441 1442 Input Parameter: 1443 + ts - timestepping context 1444 - roswtype - type of Rosenbrock-W scheme 1445 1446 Level: beginner 1447 1448 .seealso: TSRosWGetType(), TSROSW, TSROSW2M, TSROSW2P, TSROSWRA3PW, TSROSWRA34PW2, TSROSWRODAS3, TSROSWSANDU3, TSROSWASSP3P3S1C, TSROSWLASSP3P4S2C, TSROSWLLSSP3P4S2C, TSROSWARK3 1449 @*/ 1450 PetscErrorCode TSRosWSetType(TS ts,TSRosWType roswtype) 1451 { 1452 PetscErrorCode ierr; 1453 1454 PetscFunctionBegin; 1455 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1456 PetscValidCharPointer(roswtype,2); 1457 ierr = PetscTryMethod(ts,"TSRosWSetType_C",(TS,TSRosWType),(ts,roswtype));CHKERRQ(ierr); 1458 PetscFunctionReturn(0); 1459 } 1460 1461 /*@C 1462 TSRosWGetType - Get the type of Rosenbrock-W scheme 1463 1464 Logically collective 1465 1466 Input Parameter: 1467 . ts - timestepping context 1468 1469 Output Parameter: 1470 . rostype - type of Rosenbrock-W scheme 1471 1472 Level: intermediate 1473 1474 .seealso: TSRosWGetType() 1475 @*/ 1476 PetscErrorCode TSRosWGetType(TS ts,TSRosWType *rostype) 1477 { 1478 PetscErrorCode ierr; 1479 1480 PetscFunctionBegin; 1481 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1482 ierr = PetscUseMethod(ts,"TSRosWGetType_C",(TS,TSRosWType*),(ts,rostype));CHKERRQ(ierr); 1483 PetscFunctionReturn(0); 1484 } 1485 1486 /*@C 1487 TSRosWSetRecomputeJacobian - Set whether to recompute the Jacobian at each stage. The default is to update the Jacobian once per step. 1488 1489 Logically collective 1490 1491 Input Parameter: 1492 + ts - timestepping context 1493 - flg - PETSC_TRUE to recompute the Jacobian at each stage 1494 1495 Level: intermediate 1496 1497 .seealso: TSRosWGetType() 1498 @*/ 1499 PetscErrorCode TSRosWSetRecomputeJacobian(TS ts,PetscBool flg) 1500 { 1501 PetscErrorCode ierr; 1502 1503 PetscFunctionBegin; 1504 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1505 ierr = PetscTryMethod(ts,"TSRosWSetRecomputeJacobian_C",(TS,PetscBool),(ts,flg));CHKERRQ(ierr); 1506 PetscFunctionReturn(0); 1507 } 1508 1509 static PetscErrorCode TSRosWGetType_RosW(TS ts,TSRosWType *rostype) 1510 { 1511 TS_RosW *ros = (TS_RosW*)ts->data; 1512 1513 PetscFunctionBegin; 1514 *rostype = ros->tableau->name; 1515 PetscFunctionReturn(0); 1516 } 1517 1518 static PetscErrorCode TSRosWSetType_RosW(TS ts,TSRosWType rostype) 1519 { 1520 TS_RosW *ros = (TS_RosW*)ts->data; 1521 PetscErrorCode ierr; 1522 PetscBool match; 1523 RosWTableauLink link; 1524 1525 PetscFunctionBegin; 1526 if (ros->tableau) { 1527 ierr = PetscStrcmp(ros->tableau->name,rostype,&match);CHKERRQ(ierr); 1528 if (match) PetscFunctionReturn(0); 1529 } 1530 for (link = RosWTableauList; link; link=link->next) { 1531 ierr = PetscStrcmp(link->tab.name,rostype,&match);CHKERRQ(ierr); 1532 if (match) { 1533 if (ts->setupcalled) {ierr = TSRosWTableauReset(ts);CHKERRQ(ierr);} 1534 ros->tableau = &link->tab; 1535 if (ts->setupcalled) {ierr = TSRosWTableauSetUp(ts);CHKERRQ(ierr);} 1536 ts->default_adapt_type = ros->tableau->bembed ? TSADAPTBASIC : TSADAPTNONE; 1537 PetscFunctionReturn(0); 1538 } 1539 } 1540 SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_UNKNOWN_TYPE,"Could not find '%s'",rostype); 1541 PetscFunctionReturn(0); 1542 } 1543 1544 static PetscErrorCode TSRosWSetRecomputeJacobian_RosW(TS ts,PetscBool flg) 1545 { 1546 TS_RosW *ros = (TS_RosW*)ts->data; 1547 1548 PetscFunctionBegin; 1549 ros->recompute_jacobian = flg; 1550 PetscFunctionReturn(0); 1551 } 1552 1553 static PetscErrorCode TSDestroy_RosW(TS ts) 1554 { 1555 PetscErrorCode ierr; 1556 1557 PetscFunctionBegin; 1558 ierr = TSReset_RosW(ts);CHKERRQ(ierr); 1559 if (ts->dm) { 1560 ierr = DMCoarsenHookRemove(ts->dm,DMCoarsenHook_TSRosW,DMRestrictHook_TSRosW,ts);CHKERRQ(ierr); 1561 ierr = DMSubDomainHookRemove(ts->dm,DMSubDomainHook_TSRosW,DMSubDomainRestrictHook_TSRosW,ts);CHKERRQ(ierr); 1562 } 1563 ierr = PetscFree(ts->data);CHKERRQ(ierr); 1564 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSRosWGetType_C",NULL);CHKERRQ(ierr); 1565 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSRosWSetType_C",NULL);CHKERRQ(ierr); 1566 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSRosWSetRecomputeJacobian_C",NULL);CHKERRQ(ierr); 1567 PetscFunctionReturn(0); 1568 } 1569 1570 /* ------------------------------------------------------------ */ 1571 /*MC 1572 TSROSW - ODE solver using Rosenbrock-W schemes 1573 1574 These methods are intended for problems with well-separated time scales, especially when a slow scale is strongly 1575 nonlinear such that it is expensive to solve with a fully implicit method. The user should provide the stiff part 1576 of the equation using TSSetIFunction() and the non-stiff part with TSSetRHSFunction(). 1577 1578 Notes: 1579 This method currently only works with autonomous ODE and DAE. 1580 1581 Consider trying TSARKIMEX if the stiff part is strongly nonlinear. 1582 1583 Developer Notes: 1584 Rosenbrock-W methods are typically specified for autonomous ODE 1585 1586 $ udot = f(u) 1587 1588 by the stage equations 1589 1590 $ k_i = h f(u_0 + sum_j alpha_ij k_j) + h J sum_j gamma_ij k_j 1591 1592 and step completion formula 1593 1594 $ u_1 = u_0 + sum_j b_j k_j 1595 1596 with step size h and coefficients alpha_ij, gamma_ij, and b_i. Implementing the method in this form would require f(u) 1597 and the Jacobian J to be available, in addition to the shifted matrix I - h gamma_ii J. Following Hairer and Wanner, 1598 we define new variables for the stage equations 1599 1600 $ y_i = gamma_ij k_j 1601 1602 The k_j can be recovered because Gamma is invertible. Let C be the lower triangular part of Gamma^{-1} and define 1603 1604 $ A = Alpha Gamma^{-1}, bt^T = b^T Gamma^{-1} 1605 1606 to rewrite the method as 1607 1608 $ [M/(h gamma_ii) - J] y_i = f(u_0 + sum_j a_ij y_j) + M sum_j (c_ij/h) y_j 1609 $ u_1 = u_0 + sum_j bt_j y_j 1610 1611 where we have introduced the mass matrix M. Continue by defining 1612 1613 $ ydot_i = 1/(h gamma_ii) y_i - sum_j (c_ij/h) y_j 1614 1615 or, more compactly in tensor notation 1616 1617 $ Ydot = 1/h (Gamma^{-1} \otimes I) Y . 1618 1619 Note that Gamma^{-1} is lower triangular. With this definition of Ydot in terms of known quantities and the current 1620 stage y_i, the stage equations reduce to performing one Newton step (typically with a lagged Jacobian) on the 1621 equation 1622 1623 $ g(u_0 + sum_j a_ij y_j + y_i, ydot_i) = 0 1624 1625 with initial guess y_i = 0. 1626 1627 Level: beginner 1628 1629 .seealso: TSCreate(), TS, TSSetType(), TSRosWSetType(), TSRosWRegister(), TSROSWTHETA1, TSROSWTHETA2, TSROSW2M, TSROSW2P, TSROSWRA3PW, TSROSWRA34PW2, TSROSWRODAS3, 1630 TSROSWSANDU3, TSROSWASSP3P3S1C, TSROSWLASSP3P4S2C, TSROSWLLSSP3P4S2C, TSROSWGRK4T, TSROSWSHAMP4, TSROSWVELDD4, TSROSW4L 1631 M*/ 1632 PETSC_EXTERN PetscErrorCode TSCreate_RosW(TS ts) 1633 { 1634 TS_RosW *ros; 1635 PetscErrorCode ierr; 1636 1637 PetscFunctionBegin; 1638 ierr = TSRosWInitializePackage();CHKERRQ(ierr); 1639 1640 ts->ops->reset = TSReset_RosW; 1641 ts->ops->destroy = TSDestroy_RosW; 1642 ts->ops->view = TSView_RosW; 1643 ts->ops->load = TSLoad_RosW; 1644 ts->ops->setup = TSSetUp_RosW; 1645 ts->ops->step = TSStep_RosW; 1646 ts->ops->interpolate = TSInterpolate_RosW; 1647 ts->ops->evaluatestep = TSEvaluateStep_RosW; 1648 ts->ops->rollback = TSRollBack_RosW; 1649 ts->ops->setfromoptions = TSSetFromOptions_RosW; 1650 ts->ops->snesfunction = SNESTSFormFunction_RosW; 1651 ts->ops->snesjacobian = SNESTSFormJacobian_RosW; 1652 1653 ts->usessnes = PETSC_TRUE; 1654 1655 ierr = PetscNewLog(ts,&ros);CHKERRQ(ierr); 1656 ts->data = (void*)ros; 1657 1658 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSRosWGetType_C",TSRosWGetType_RosW);CHKERRQ(ierr); 1659 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSRosWSetType_C",TSRosWSetType_RosW);CHKERRQ(ierr); 1660 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSRosWSetRecomputeJacobian_C",TSRosWSetRecomputeJacobian_RosW);CHKERRQ(ierr); 1661 1662 ierr = TSRosWSetType(ts,TSRosWDefault);CHKERRQ(ierr); 1663 PetscFunctionReturn(0); 1664 } 1665