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