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