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