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