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