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 = 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 TSDestroy_RosW(TS ts) 1159 { 1160 PetscErrorCode ierr; 1161 1162 PetscFunctionBegin; 1163 ierr = TSReset_RosW(ts);CHKERRQ(ierr); 1164 ierr = PetscFree(ts->data);CHKERRQ(ierr); 1165 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSRosWGetType_C",NULL);CHKERRQ(ierr); 1166 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSRosWSetType_C",NULL);CHKERRQ(ierr); 1167 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSRosWSetRecomputeJacobian_C",NULL);CHKERRQ(ierr); 1168 PetscFunctionReturn(0); 1169 } 1170 1171 1172 static PetscErrorCode TSRosWGetVecs(TS ts,DM dm,Vec *Ydot,Vec *Zdot,Vec *Ystage,Vec *Zstage) 1173 { 1174 TS_RosW *rw = (TS_RosW*)ts->data; 1175 PetscErrorCode ierr; 1176 1177 PetscFunctionBegin; 1178 if (Ydot) { 1179 if (dm && dm != ts->dm) { 1180 ierr = DMGetNamedGlobalVector(dm,"TSRosW_Ydot",Ydot);CHKERRQ(ierr); 1181 } else *Ydot = rw->Ydot; 1182 } 1183 if (Zdot) { 1184 if (dm && dm != ts->dm) { 1185 ierr = DMGetNamedGlobalVector(dm,"TSRosW_Zdot",Zdot);CHKERRQ(ierr); 1186 } else *Zdot = rw->Zdot; 1187 } 1188 if (Ystage) { 1189 if (dm && dm != ts->dm) { 1190 ierr = DMGetNamedGlobalVector(dm,"TSRosW_Ystage",Ystage);CHKERRQ(ierr); 1191 } else *Ystage = rw->Ystage; 1192 } 1193 if (Zstage) { 1194 if (dm && dm != ts->dm) { 1195 ierr = DMGetNamedGlobalVector(dm,"TSRosW_Zstage",Zstage);CHKERRQ(ierr); 1196 } else *Zstage = rw->Zstage; 1197 } 1198 PetscFunctionReturn(0); 1199 } 1200 1201 1202 static PetscErrorCode TSRosWRestoreVecs(TS ts,DM dm,Vec *Ydot,Vec *Zdot, Vec *Ystage, Vec *Zstage) 1203 { 1204 PetscErrorCode ierr; 1205 1206 PetscFunctionBegin; 1207 if (Ydot) { 1208 if (dm && dm != ts->dm) { 1209 ierr = DMRestoreNamedGlobalVector(dm,"TSRosW_Ydot",Ydot);CHKERRQ(ierr); 1210 } 1211 } 1212 if (Zdot) { 1213 if (dm && dm != ts->dm) { 1214 ierr = DMRestoreNamedGlobalVector(dm,"TSRosW_Zdot",Zdot);CHKERRQ(ierr); 1215 } 1216 } 1217 if (Ystage) { 1218 if (dm && dm != ts->dm) { 1219 ierr = DMRestoreNamedGlobalVector(dm,"TSRosW_Ystage",Ystage);CHKERRQ(ierr); 1220 } 1221 } 1222 if (Zstage) { 1223 if (dm && dm != ts->dm) { 1224 ierr = DMRestoreNamedGlobalVector(dm,"TSRosW_Zstage",Zstage);CHKERRQ(ierr); 1225 } 1226 } 1227 PetscFunctionReturn(0); 1228 } 1229 1230 static PetscErrorCode DMCoarsenHook_TSRosW(DM fine,DM coarse,void *ctx) 1231 { 1232 PetscFunctionBegin; 1233 PetscFunctionReturn(0); 1234 } 1235 1236 static PetscErrorCode DMRestrictHook_TSRosW(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse,void *ctx) 1237 { 1238 TS ts = (TS)ctx; 1239 PetscErrorCode ierr; 1240 Vec Ydot,Zdot,Ystage,Zstage; 1241 Vec Ydotc,Zdotc,Ystagec,Zstagec; 1242 1243 PetscFunctionBegin; 1244 ierr = TSRosWGetVecs(ts,fine,&Ydot,&Ystage,&Zdot,&Zstage);CHKERRQ(ierr); 1245 ierr = TSRosWGetVecs(ts,coarse,&Ydotc,&Ystagec,&Zdotc,&Zstagec);CHKERRQ(ierr); 1246 ierr = MatRestrict(restrct,Ydot,Ydotc);CHKERRQ(ierr); 1247 ierr = VecPointwiseMult(Ydotc,rscale,Ydotc);CHKERRQ(ierr); 1248 ierr = MatRestrict(restrct,Ystage,Ystagec);CHKERRQ(ierr); 1249 ierr = VecPointwiseMult(Ystagec,rscale,Ystagec);CHKERRQ(ierr); 1250 ierr = MatRestrict(restrct,Zdot,Zdotc);CHKERRQ(ierr); 1251 ierr = VecPointwiseMult(Zdotc,rscale,Zdotc);CHKERRQ(ierr); 1252 ierr = MatRestrict(restrct,Zstage,Zstagec);CHKERRQ(ierr); 1253 ierr = VecPointwiseMult(Zstagec,rscale,Zstagec);CHKERRQ(ierr); 1254 ierr = TSRosWRestoreVecs(ts,fine,&Ydot,&Ystage,&Zdot,&Zstage);CHKERRQ(ierr); 1255 ierr = TSRosWRestoreVecs(ts,coarse,&Ydotc,&Ystagec,&Zdotc,&Zstagec);CHKERRQ(ierr); 1256 PetscFunctionReturn(0); 1257 } 1258 1259 1260 static PetscErrorCode DMSubDomainHook_TSRosW(DM fine,DM coarse,void *ctx) 1261 { 1262 PetscFunctionBegin; 1263 PetscFunctionReturn(0); 1264 } 1265 1266 static PetscErrorCode DMSubDomainRestrictHook_TSRosW(DM dm,VecScatter gscat,VecScatter lscat,DM subdm,void *ctx) 1267 { 1268 TS ts = (TS)ctx; 1269 PetscErrorCode ierr; 1270 Vec Ydot,Zdot,Ystage,Zstage; 1271 Vec Ydots,Zdots,Ystages,Zstages; 1272 1273 PetscFunctionBegin; 1274 ierr = TSRosWGetVecs(ts,dm,&Ydot,&Ystage,&Zdot,&Zstage);CHKERRQ(ierr); 1275 ierr = TSRosWGetVecs(ts,subdm,&Ydots,&Ystages,&Zdots,&Zstages);CHKERRQ(ierr); 1276 1277 ierr = VecScatterBegin(gscat,Ydot,Ydots,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1278 ierr = VecScatterEnd(gscat,Ydot,Ydots,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1279 1280 ierr = VecScatterBegin(gscat,Ystage,Ystages,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1281 ierr = VecScatterEnd(gscat,Ystage,Ystages,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1282 1283 ierr = VecScatterBegin(gscat,Zdot,Zdots,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1284 ierr = VecScatterEnd(gscat,Zdot,Zdots,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1285 1286 ierr = VecScatterBegin(gscat,Zstage,Zstages,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1287 ierr = VecScatterEnd(gscat,Zstage,Zstages,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1288 1289 ierr = TSRosWRestoreVecs(ts,dm,&Ydot,&Ystage,&Zdot,&Zstage);CHKERRQ(ierr); 1290 ierr = TSRosWRestoreVecs(ts,subdm,&Ydots,&Ystages,&Zdots,&Zstages);CHKERRQ(ierr); 1291 PetscFunctionReturn(0); 1292 } 1293 1294 /* 1295 This defines the nonlinear equation that is to be solved with SNES 1296 G(U) = F[t0+Theta*dt, U, (U-U0)*shift] = 0 1297 */ 1298 static PetscErrorCode SNESTSFormFunction_RosW(SNES snes,Vec U,Vec F,TS ts) 1299 { 1300 TS_RosW *ros = (TS_RosW*)ts->data; 1301 PetscErrorCode ierr; 1302 Vec Ydot,Zdot,Ystage,Zstage; 1303 PetscReal shift = ros->scoeff / ts->time_step; 1304 DM dm,dmsave; 1305 1306 PetscFunctionBegin; 1307 ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 1308 ierr = TSRosWGetVecs(ts,dm,&Ydot,&Zdot,&Ystage,&Zstage);CHKERRQ(ierr); 1309 ierr = VecWAXPY(Ydot,shift,U,Zdot);CHKERRQ(ierr); /* Ydot = shift*U + Zdot */ 1310 ierr = VecWAXPY(Ystage,1.0,U,Zstage);CHKERRQ(ierr); /* Ystage = U + Zstage */ 1311 dmsave = ts->dm; 1312 ts->dm = dm; 1313 ierr = TSComputeIFunction(ts,ros->stage_time,Ystage,Ydot,F,PETSC_FALSE);CHKERRQ(ierr); 1314 ts->dm = dmsave; 1315 ierr = TSRosWRestoreVecs(ts,dm,&Ydot,&Zdot,&Ystage,&Zstage);CHKERRQ(ierr); 1316 PetscFunctionReturn(0); 1317 } 1318 1319 static PetscErrorCode SNESTSFormJacobian_RosW(SNES snes,Vec U,Mat A,Mat B,TS ts) 1320 { 1321 TS_RosW *ros = (TS_RosW*)ts->data; 1322 Vec Ydot,Zdot,Ystage,Zstage; 1323 PetscReal shift = ros->scoeff / ts->time_step; 1324 PetscErrorCode ierr; 1325 DM dm,dmsave; 1326 1327 PetscFunctionBegin; 1328 /* ros->Ydot and ros->Ystage have already been computed in SNESTSFormFunction_RosW (SNES guarantees this) */ 1329 ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 1330 ierr = TSRosWGetVecs(ts,dm,&Ydot,&Zdot,&Ystage,&Zstage);CHKERRQ(ierr); 1331 dmsave = ts->dm; 1332 ts->dm = dm; 1333 ierr = TSComputeIJacobian(ts,ros->stage_time,Ystage,Ydot,shift,A,B,PETSC_TRUE);CHKERRQ(ierr); 1334 ts->dm = dmsave; 1335 ierr = TSRosWRestoreVecs(ts,dm,&Ydot,&Zdot,&Ystage,&Zstage);CHKERRQ(ierr); 1336 PetscFunctionReturn(0); 1337 } 1338 1339 static PetscErrorCode TSRosWTableauSetUp(TS ts) 1340 { 1341 TS_RosW *ros = (TS_RosW*)ts->data; 1342 RosWTableau tab = ros->tableau; 1343 PetscErrorCode ierr; 1344 1345 PetscFunctionBegin; 1346 ierr = VecDuplicateVecs(ts->vec_sol,tab->s,&ros->Y);CHKERRQ(ierr); 1347 ierr = PetscMalloc1(tab->s,&ros->work);CHKERRQ(ierr); 1348 PetscFunctionReturn(0); 1349 } 1350 1351 static PetscErrorCode TSSetUp_RosW(TS ts) 1352 { 1353 TS_RosW *ros = (TS_RosW*)ts->data; 1354 PetscErrorCode ierr; 1355 DM dm; 1356 SNES snes; 1357 1358 PetscFunctionBegin; 1359 ierr = TSRosWTableauSetUp(ts);CHKERRQ(ierr); 1360 ierr = VecDuplicate(ts->vec_sol,&ros->Ydot);CHKERRQ(ierr); 1361 ierr = VecDuplicate(ts->vec_sol,&ros->Ystage);CHKERRQ(ierr); 1362 ierr = VecDuplicate(ts->vec_sol,&ros->Zdot);CHKERRQ(ierr); 1363 ierr = VecDuplicate(ts->vec_sol,&ros->Zstage);CHKERRQ(ierr); 1364 ierr = VecDuplicate(ts->vec_sol,&ros->vec_sol_prev);CHKERRQ(ierr); 1365 ierr = TSGetDM(ts,&dm);CHKERRQ(ierr); 1366 if (dm) { 1367 ierr = DMCoarsenHookAdd(dm,DMCoarsenHook_TSRosW,DMRestrictHook_TSRosW,ts);CHKERRQ(ierr); 1368 ierr = DMSubDomainHookAdd(dm,DMSubDomainHook_TSRosW,DMSubDomainRestrictHook_TSRosW,ts);CHKERRQ(ierr); 1369 } 1370 /* Rosenbrock methods are linearly implicit, so set that unless the user has specifically asked for something else */ 1371 ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr); 1372 if (!((PetscObject)snes)->type_name) { 1373 ierr = SNESSetType(snes,SNESKSPONLY);CHKERRQ(ierr); 1374 } 1375 PetscFunctionReturn(0); 1376 } 1377 /*------------------------------------------------------------*/ 1378 1379 static PetscErrorCode TSSetFromOptions_RosW(PetscOptionItems *PetscOptionsObject,TS ts) 1380 { 1381 TS_RosW *ros = (TS_RosW*)ts->data; 1382 PetscErrorCode ierr; 1383 SNES snes; 1384 1385 PetscFunctionBegin; 1386 ierr = PetscOptionsHead(PetscOptionsObject,"RosW ODE solver options");CHKERRQ(ierr); 1387 { 1388 RosWTableauLink link; 1389 PetscInt count,choice; 1390 PetscBool flg; 1391 const char **namelist; 1392 1393 for (link=RosWTableauList,count=0; link; link=link->next,count++) ; 1394 ierr = PetscMalloc1(count,&namelist);CHKERRQ(ierr); 1395 for (link=RosWTableauList,count=0; link; link=link->next,count++) namelist[count] = link->tab.name; 1396 ierr = PetscOptionsEList("-ts_rosw_type","Family of Rosenbrock-W method","TSRosWSetType",(const char*const*)namelist,count,ros->tableau->name,&choice,&flg);CHKERRQ(ierr); 1397 if (flg) {ierr = TSRosWSetType(ts,namelist[choice]);CHKERRQ(ierr);} 1398 ierr = PetscFree(namelist);CHKERRQ(ierr); 1399 1400 ierr = PetscOptionsBool("-ts_rosw_recompute_jacobian","Recompute the Jacobian at each stage","TSRosWSetRecomputeJacobian",ros->recompute_jacobian,&ros->recompute_jacobian,NULL);CHKERRQ(ierr); 1401 } 1402 ierr = PetscOptionsTail();CHKERRQ(ierr); 1403 /* Rosenbrock methods are linearly implicit, so set that unless the user has specifically asked for something else */ 1404 ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr); 1405 if (!((PetscObject)snes)->type_name) { 1406 ierr = SNESSetType(snes,SNESKSPONLY);CHKERRQ(ierr); 1407 } 1408 PetscFunctionReturn(0); 1409 } 1410 1411 static PetscErrorCode PetscFormatRealArray(char buf[],size_t len,const char *fmt,PetscInt n,const PetscReal x[]) 1412 { 1413 PetscErrorCode ierr; 1414 PetscInt i; 1415 size_t left,count; 1416 char *p; 1417 1418 PetscFunctionBegin; 1419 for (i=0,p=buf,left=len; i<n; i++) { 1420 ierr = PetscSNPrintfCount(p,left,fmt,&count,(double)x[i]);CHKERRQ(ierr); 1421 if (count >= left) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Insufficient space in buffer"); 1422 left -= count; 1423 p += count; 1424 *p++ = ' '; 1425 } 1426 p[i ? 0 : -1] = 0; 1427 PetscFunctionReturn(0); 1428 } 1429 1430 static PetscErrorCode TSView_RosW(TS ts,PetscViewer viewer) 1431 { 1432 TS_RosW *ros = (TS_RosW*)ts->data; 1433 PetscBool iascii; 1434 PetscErrorCode ierr; 1435 1436 PetscFunctionBegin; 1437 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 1438 if (iascii) { 1439 RosWTableau tab = ros->tableau; 1440 TSRosWType rostype; 1441 char buf[512]; 1442 PetscInt i; 1443 PetscReal abscissa[512]; 1444 ierr = TSRosWGetType(ts,&rostype);CHKERRQ(ierr); 1445 ierr = PetscViewerASCIIPrintf(viewer," Rosenbrock-W %s\n",rostype);CHKERRQ(ierr); 1446 ierr = PetscFormatRealArray(buf,sizeof(buf),"% 8.6f",tab->s,tab->ASum);CHKERRQ(ierr); 1447 ierr = PetscViewerASCIIPrintf(viewer," Abscissa of A = %s\n",buf);CHKERRQ(ierr); 1448 for (i=0; i<tab->s; i++) abscissa[i] = tab->ASum[i] + tab->Gamma[i]; 1449 ierr = PetscFormatRealArray(buf,sizeof(buf),"% 8.6f",tab->s,abscissa);CHKERRQ(ierr); 1450 ierr = PetscViewerASCIIPrintf(viewer," Abscissa of A+Gamma = %s\n",buf);CHKERRQ(ierr); 1451 } 1452 PetscFunctionReturn(0); 1453 } 1454 1455 static PetscErrorCode TSLoad_RosW(TS ts,PetscViewer viewer) 1456 { 1457 PetscErrorCode ierr; 1458 SNES snes; 1459 TSAdapt adapt; 1460 1461 PetscFunctionBegin; 1462 ierr = TSGetAdapt(ts,&adapt);CHKERRQ(ierr); 1463 ierr = TSAdaptLoad(adapt,viewer);CHKERRQ(ierr); 1464 ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr); 1465 ierr = SNESLoad(snes,viewer);CHKERRQ(ierr); 1466 /* function and Jacobian context for SNES when used with TS is always ts object */ 1467 ierr = SNESSetFunction(snes,NULL,NULL,ts);CHKERRQ(ierr); 1468 ierr = SNESSetJacobian(snes,NULL,NULL,NULL,ts);CHKERRQ(ierr); 1469 PetscFunctionReturn(0); 1470 } 1471 1472 /*@C 1473 TSRosWSetType - Set the type of Rosenbrock-W scheme 1474 1475 Logically collective 1476 1477 Input Parameter: 1478 + ts - timestepping context 1479 - roswtype - type of Rosenbrock-W scheme 1480 1481 Level: beginner 1482 1483 .seealso: TSRosWGetType(), TSROSW, TSROSW2M, TSROSW2P, TSROSWRA3PW, TSROSWRA34PW2, TSROSWRODAS3, TSROSWSANDU3, TSROSWASSP3P3S1C, TSROSWLASSP3P4S2C, TSROSWLLSSP3P4S2C, TSROSWARK3 1484 @*/ 1485 PetscErrorCode TSRosWSetType(TS ts,TSRosWType roswtype) 1486 { 1487 PetscErrorCode ierr; 1488 1489 PetscFunctionBegin; 1490 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1491 PetscValidCharPointer(roswtype,2); 1492 ierr = PetscTryMethod(ts,"TSRosWSetType_C",(TS,TSRosWType),(ts,roswtype));CHKERRQ(ierr); 1493 PetscFunctionReturn(0); 1494 } 1495 1496 /*@C 1497 TSRosWGetType - Get the type of Rosenbrock-W scheme 1498 1499 Logically collective 1500 1501 Input Parameter: 1502 . ts - timestepping context 1503 1504 Output Parameter: 1505 . rostype - type of Rosenbrock-W scheme 1506 1507 Level: intermediate 1508 1509 .seealso: TSRosWGetType() 1510 @*/ 1511 PetscErrorCode TSRosWGetType(TS ts,TSRosWType *rostype) 1512 { 1513 PetscErrorCode ierr; 1514 1515 PetscFunctionBegin; 1516 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1517 ierr = PetscUseMethod(ts,"TSRosWGetType_C",(TS,TSRosWType*),(ts,rostype));CHKERRQ(ierr); 1518 PetscFunctionReturn(0); 1519 } 1520 1521 /*@C 1522 TSRosWSetRecomputeJacobian - Set whether to recompute the Jacobian at each stage. The default is to update the Jacobian once per step. 1523 1524 Logically collective 1525 1526 Input Parameter: 1527 + ts - timestepping context 1528 - flg - PETSC_TRUE to recompute the Jacobian at each stage 1529 1530 Level: intermediate 1531 1532 .seealso: TSRosWGetType() 1533 @*/ 1534 PetscErrorCode TSRosWSetRecomputeJacobian(TS ts,PetscBool flg) 1535 { 1536 PetscErrorCode ierr; 1537 1538 PetscFunctionBegin; 1539 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1540 ierr = PetscTryMethod(ts,"TSRosWSetRecomputeJacobian_C",(TS,PetscBool),(ts,flg));CHKERRQ(ierr); 1541 PetscFunctionReturn(0); 1542 } 1543 1544 static PetscErrorCode TSRosWGetType_RosW(TS ts,TSRosWType *rostype) 1545 { 1546 TS_RosW *ros = (TS_RosW*)ts->data; 1547 1548 PetscFunctionBegin; 1549 *rostype = ros->tableau->name; 1550 PetscFunctionReturn(0); 1551 } 1552 1553 static PetscErrorCode TSRosWSetType_RosW(TS ts,TSRosWType rostype) 1554 { 1555 TS_RosW *ros = (TS_RosW*)ts->data; 1556 PetscErrorCode ierr; 1557 PetscBool match; 1558 RosWTableauLink link; 1559 1560 PetscFunctionBegin; 1561 if (ros->tableau) { 1562 ierr = PetscStrcmp(ros->tableau->name,rostype,&match);CHKERRQ(ierr); 1563 if (match) PetscFunctionReturn(0); 1564 } 1565 for (link = RosWTableauList; link; link=link->next) { 1566 ierr = PetscStrcmp(link->tab.name,rostype,&match);CHKERRQ(ierr); 1567 if (match) { 1568 if (ts->setupcalled) {ierr = TSRosWTableauReset(ts);CHKERRQ(ierr);} 1569 ros->tableau = &link->tab; 1570 if (ts->setupcalled) {ierr = TSRosWTableauSetUp(ts);CHKERRQ(ierr);} 1571 ts->default_adapt_type = ros->tableau->bembed ? TSADAPTBASIC : TSADAPTNONE; 1572 PetscFunctionReturn(0); 1573 } 1574 } 1575 SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_UNKNOWN_TYPE,"Could not find '%s'",rostype); 1576 PetscFunctionReturn(0); 1577 } 1578 1579 static PetscErrorCode TSRosWSetRecomputeJacobian_RosW(TS ts,PetscBool flg) 1580 { 1581 TS_RosW *ros = (TS_RosW*)ts->data; 1582 1583 PetscFunctionBegin; 1584 ros->recompute_jacobian = flg; 1585 PetscFunctionReturn(0); 1586 } 1587 1588 1589 /* ------------------------------------------------------------ */ 1590 /*MC 1591 TSROSW - ODE solver using Rosenbrock-W schemes 1592 1593 These methods are intended for problems with well-separated time scales, especially when a slow scale is strongly 1594 nonlinear such that it is expensive to solve with a fully implicit method. The user should provide the stiff part 1595 of the equation using TSSetIFunction() and the non-stiff part with TSSetRHSFunction(). 1596 1597 Notes: 1598 This method currently only works with autonomous ODE and DAE. 1599 1600 Consider trying TSARKIMEX if the stiff part is strongly nonlinear. 1601 1602 Developer notes: 1603 Rosenbrock-W methods are typically specified for autonomous ODE 1604 1605 $ udot = f(u) 1606 1607 by the stage equations 1608 1609 $ k_i = h f(u_0 + sum_j alpha_ij k_j) + h J sum_j gamma_ij k_j 1610 1611 and step completion formula 1612 1613 $ u_1 = u_0 + sum_j b_j k_j 1614 1615 with step size h and coefficients alpha_ij, gamma_ij, and b_i. Implementing the method in this form would require f(u) 1616 and the Jacobian J to be available, in addition to the shifted matrix I - h gamma_ii J. Following Hairer and Wanner, 1617 we define new variables for the stage equations 1618 1619 $ y_i = gamma_ij k_j 1620 1621 The k_j can be recovered because Gamma is invertible. Let C be the lower triangular part of Gamma^{-1} and define 1622 1623 $ A = Alpha Gamma^{-1}, bt^T = b^T Gamma^{-1} 1624 1625 to rewrite the method as 1626 1627 $ [M/(h gamma_ii) - J] y_i = f(u_0 + sum_j a_ij y_j) + M sum_j (c_ij/h) y_j 1628 $ u_1 = u_0 + sum_j bt_j y_j 1629 1630 where we have introduced the mass matrix M. Continue by defining 1631 1632 $ ydot_i = 1/(h gamma_ii) y_i - sum_j (c_ij/h) y_j 1633 1634 or, more compactly in tensor notation 1635 1636 $ Ydot = 1/h (Gamma^{-1} \otimes I) Y . 1637 1638 Note that Gamma^{-1} is lower triangular. With this definition of Ydot in terms of known quantities and the current 1639 stage y_i, the stage equations reduce to performing one Newton step (typically with a lagged Jacobian) on the 1640 equation 1641 1642 $ g(u_0 + sum_j a_ij y_j + y_i, ydot_i) = 0 1643 1644 with initial guess y_i = 0. 1645 1646 Level: beginner 1647 1648 .seealso: TSCreate(), TS, TSSetType(), TSRosWSetType(), TSRosWRegister(), TSROSWTHETA1, TSROSWTHETA2, TSROSW2M, TSROSW2P, TSROSWRA3PW, TSROSWRA34PW2, TSROSWRODAS3, 1649 TSROSWSANDU3, TSROSWASSP3P3S1C, TSROSWLASSP3P4S2C, TSROSWLLSSP3P4S2C, TSROSWGRK4T, TSROSWSHAMP4, TSROSWVELDD4, TSROSW4L 1650 M*/ 1651 PETSC_EXTERN PetscErrorCode TSCreate_RosW(TS ts) 1652 { 1653 TS_RosW *ros; 1654 PetscErrorCode ierr; 1655 1656 PetscFunctionBegin; 1657 ierr = TSRosWInitializePackage();CHKERRQ(ierr); 1658 1659 ts->ops->reset = TSReset_RosW; 1660 ts->ops->destroy = TSDestroy_RosW; 1661 ts->ops->view = TSView_RosW; 1662 ts->ops->load = TSLoad_RosW; 1663 ts->ops->setup = TSSetUp_RosW; 1664 ts->ops->step = TSStep_RosW; 1665 ts->ops->interpolate = TSInterpolate_RosW; 1666 ts->ops->evaluatestep = TSEvaluateStep_RosW; 1667 ts->ops->rollback = TSRollBack_RosW; 1668 ts->ops->setfromoptions = TSSetFromOptions_RosW; 1669 ts->ops->snesfunction = SNESTSFormFunction_RosW; 1670 ts->ops->snesjacobian = SNESTSFormJacobian_RosW; 1671 1672 ts->usessnes = PETSC_TRUE; 1673 1674 ierr = PetscNewLog(ts,&ros);CHKERRQ(ierr); 1675 ts->data = (void*)ros; 1676 1677 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSRosWGetType_C",TSRosWGetType_RosW);CHKERRQ(ierr); 1678 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSRosWSetType_C",TSRosWSetType_RosW);CHKERRQ(ierr); 1679 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSRosWSetRecomputeJacobian_C",TSRosWSetRecomputeJacobian_RosW);CHKERRQ(ierr); 1680 1681 ierr = TSRosWSetType(ts,TSRosWDefault);CHKERRQ(ierr); 1682 PetscFunctionReturn(0); 1683 } 1684