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 <private/tsimpl.h> /*I "petscts.h" I*/ 14 15 #include <../src/mat/blockinvert.h> 16 17 static const TSRosWType TSRosWDefault = TSROSW2P; 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 PetscReal *A; /* Propagation table, strictly lower triangular */ 27 PetscReal *Gamma; /* Stage table, lower triangular with nonzero diagonal */ 28 PetscBool *GammaZeroDiag; /* Diagonal entries that are zero in stage table Gamma, vector indicating explicit statages */ 29 PetscReal *GammaExplicitCorr; /* Coefficients for correction terms needed for explicit stages in transformed variables*/ 30 PetscReal *b; /* Step completion table */ 31 PetscReal *bembed; /* Step completion table for embedded method of order one less */ 32 PetscReal *ASum; /* Row sum of A */ 33 PetscReal *GammaSum; /* Row sum of Gamma, only needed for non-autonomous systems */ 34 PetscReal *At; /* Propagation table in transformed variables */ 35 PetscReal *bt; /* Step completion table in transformed variables */ 36 PetscReal *bembedt; /* Step completion table of order one less in transformed variables */ 37 PetscReal *GammaInv; /* Inverse of Gamma, used for transformed variables */ 38 PetscReal ccfl; /* Placeholder for CFL coefficient relative to forward Euler */ 39 }; 40 typedef struct _RosWTableauLink *RosWTableauLink; 41 struct _RosWTableauLink { 42 struct _RosWTableau tab; 43 RosWTableauLink next; 44 }; 45 static RosWTableauLink RosWTableauList; 46 47 typedef struct { 48 RosWTableau tableau; 49 Vec *Y; /* States computed during the step, used to complete the step */ 50 Vec Ydot; /* Work vector holding Ydot during residual evaluation */ 51 Vec Ystage; /* Work vector for the state value at each stage */ 52 Vec Zdot; /* Ydot = Zdot + shift*Y */ 53 Vec Zstage; /* Y = Zstage + Y */ 54 PetscScalar *work; /* Scalar work space of length number of stages, used to prepare VecMAXPY() */ 55 PetscReal shift; 56 PetscReal stage_time; 57 PetscReal stage_explicit; /* Flag indicates that the current stage is explicit */ 58 PetscBool recompute_jacobian; /* Recompute the Jacobian at each stage, default is to freeze the Jacobian at the start of each step */ 59 TSStepStatus status; 60 } TS_RosW; 61 62 /*MC 63 TSROSW2M - Two stage second order L-stable Rosenbrock-W scheme. 64 65 Only an approximate Jacobian is needed. By default, it is only recomputed once per step. This method is a reflection of TSROSW2P. 66 67 Level: intermediate 68 69 .seealso: TSROSW 70 M*/ 71 72 /*MC 73 TSROSW2P - Two stage second order L-stable Rosenbrock-W scheme. 74 75 Only an approximate Jacobian is needed. By default, it is only recomputed once per step. This method is a reflection of TSROSW2M. 76 77 Level: intermediate 78 79 .seealso: TSROSW 80 M*/ 81 82 /*MC 83 TSROSWRA3PW - Three stage third order Rosenbrock-W scheme for PDAE of index 1. 84 85 Only an approximate Jacobian is needed. By default, it is only recomputed once per step. 86 87 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. 88 89 References: 90 Rang and Angermann, New Rosenbrock-W methods of order 3 for partial differential algebraic equations of index 1, 2005. 91 92 Level: intermediate 93 94 .seealso: TSROSW 95 M*/ 96 97 /*MC 98 TSROSWRA34PW2 - Four stage third order L-stable Rosenbrock-W scheme for PDAE of index 1. 99 100 Only an approximate Jacobian is needed. By default, it is only recomputed once per step. 101 102 This is strongly A-stable with R(infty) = 0. The embedded method of order 2 is strongly A-stable with R(infty) = 0.48. 103 104 References: 105 Rang and Angermann, New Rosenbrock-W methods of order 3 for partial differential algebraic equations of index 1, 2005. 106 107 Level: intermediate 108 109 .seealso: TSROSW 110 M*/ 111 112 /*MC 113 TSROSWRODAS3 - Four stage third order L-stable Rosenbrock scheme 114 115 By default, the Jacobian is only recomputed once per step. 116 117 Both the third order and embedded second order methods are stiffly accurate and L-stable. 118 119 References: 120 Sandu et al, Benchmarking stiff ODE solvers for atmospheric chemistry problems II, Rosenbrock solvers, 1997. 121 122 Level: intermediate 123 124 .seealso: TSROSW, TSROSWSANDU3 125 M*/ 126 127 /*MC 128 TSROSWSANDU3 - Three stage third order L-stable Rosenbrock scheme 129 130 By default, the Jacobian is only recomputed once per step. 131 132 The third order method is L-stable, but not stiffly accurate. 133 The second order embedded method is strongly A-stable with R(infty) = 0.5. 134 The internal stages are L-stable. 135 This method is called ROS3 in the paper. 136 137 References: 138 Sandu et al, Benchmarking stiff ODE solvers for atmospheric chemistry problems II, Rosenbrock solvers, 1997. 139 140 Level: intermediate 141 142 .seealso: TSROSW, TSROSWRODAS3 143 M*/ 144 145 /*MC 146 TSROSWASSP3P3S1C - A-stable Rosenbrock-W method with SSP explicit part, third order, three stages 147 148 By default, the Jacobian is only recomputed once per step. 149 150 A-stable SPP explicit order 3, 3 stages, CFL 1 (eff = 1/3) 151 152 References: 153 Emil Constantinescu 154 155 Level: intermediate 156 157 .seealso: TSROSW, TSROSWLASSP3P4S2C, TSROSWLLSSP3P4S2C, SSP 158 M*/ 159 160 /*MC 161 TSROSWLASSP3P4S2C - L-stable Rosenbrock-W method with SSP explicit part, third order, three stages 162 163 By default, the Jacobian is only recomputed once per step. 164 165 L-stable (A-stable embedded) SPP explicit order 3, 4 stages, CFL 2 (eff = 1/2) 166 167 References: 168 Emil Constantinescu 169 170 Level: intermediate 171 172 .seealso: TSROSW, TSROSWASSP3P3S1C, TSROSWLLSSP3P4S2C, TSSSP 173 M*/ 174 175 /*MC 176 TSROSWLLSSP3P4S2C - L-stable Rosenbrock-W method with SSP explicit part, third order, three stages 177 178 By default, the Jacobian is only recomputed once per step. 179 180 L-stable (L-stable embedded) SPP explicit order 3, 4 stages, CFL 2 (eff = 1/2) 181 182 References: 183 Emil Constantinescu 184 185 Level: intermediate 186 187 .seealso: TSROSW, TSROSWASSP3P3S1C, TSROSWLASSP3P4S2C, TSSSP 188 M*/ 189 190 #undef __FUNCT__ 191 #define __FUNCT__ "TSRosWRegisterAll" 192 /*@C 193 TSRosWRegisterAll - Registers all of the additive Runge-Kutta implicit-explicit methods in TSRosW 194 195 Not Collective, but should be called by all processes which will need the schemes to be registered 196 197 Level: advanced 198 199 .keywords: TS, TSRosW, register, all 200 201 .seealso: TSRosWRegisterDestroy() 202 @*/ 203 PetscErrorCode TSRosWRegisterAll(void) 204 { 205 PetscErrorCode ierr; 206 207 PetscFunctionBegin; 208 if (TSRosWRegisterAllCalled) PetscFunctionReturn(0); 209 TSRosWRegisterAllCalled = PETSC_TRUE; 210 211 { 212 const PetscReal g = 1. + 1./PetscSqrtReal(2.0); 213 const PetscReal 214 A[2][2] = {{0,0}, {1.,0}}, 215 Gamma[2][2] = {{g,0}, {-2.*g,g}}, 216 b[2] = {0.5,0.5}, 217 b1[2] = {1.0,0.0}; 218 ierr = TSRosWRegister(TSROSW2P,2,2,&A[0][0],&Gamma[0][0],b,b1);CHKERRQ(ierr); 219 } 220 { 221 const PetscReal g = 1. - 1./PetscSqrtReal(2.0); 222 const PetscReal 223 A[2][2] = {{0,0}, {1.,0}}, 224 Gamma[2][2] = {{g,0}, {-2.*g,g}}, 225 b[2] = {0.5,0.5}, 226 b1[2] = {1.0,0.0}; 227 ierr = TSRosWRegister(TSROSW2M,2,2,&A[0][0],&Gamma[0][0],b,b1);CHKERRQ(ierr); 228 } 229 { 230 const PetscReal g = 7.8867513459481287e-01; 231 const PetscReal 232 A[3][3] = {{0,0,0}, 233 {1.5773502691896257e+00,0,0}, 234 {0.5,0,0}}, 235 Gamma[3][3] = {{g,0,0}, 236 {-1.5773502691896257e+00,g,0}, 237 {-6.7075317547305480e-01,1.7075317547305482e-01,g}}, 238 b[3] = {1.0566243270259355e-01,4.9038105676657971e-02,8.4529946162074843e-01}, 239 b2[3] = {-1.7863279495408180e-01,1./3.,8.4529946162074843e-01}; 240 ierr = TSRosWRegister(TSROSWRA3PW,3,3,&A[0][0],&Gamma[0][0],b,b2);CHKERRQ(ierr); 241 } 242 { 243 const PetscReal g = 4.3586652150845900e-01; 244 const PetscReal 245 A[4][4] = {{0,0,0,0}, 246 {8.7173304301691801e-01,0,0,0}, 247 {8.4457060015369423e-01,-1.1299064236484185e-01,0,0}, 248 {0,0,1.,0}}, 249 Gamma[4][4] = {{g,0,0,0}, 250 {-8.7173304301691801e-01,g,0,0}, 251 {-9.0338057013044082e-01,5.4180672388095326e-02,g,0}, 252 {2.4212380706095346e-01,-1.2232505839045147e+00,5.4526025533510214e-01,g}}, 253 b[4] = {2.4212380706095346e-01,-1.2232505839045147e+00,1.5452602553351020e+00,4.3586652150845900e-01}, 254 b2[4] = {3.7810903145819369e-01,-9.6042292212423178e-02,5.0000000000000000e-01,2.1793326075422950e-01}; 255 ierr = TSRosWRegister(TSROSWRA34PW2,3,4,&A[0][0],&Gamma[0][0],b,b2);CHKERRQ(ierr); 256 } 257 { 258 const PetscReal g = 0.5; 259 const PetscReal 260 A[4][4] = {{0,0,0,0}, 261 {0,0,0,0}, 262 {1.,0,0,0}, 263 {0.75,-0.25,0.5,0}}, 264 Gamma[4][4] = {{g,0,0,0}, 265 {1.,g,0,0}, 266 {-0.25,-0.25,g,0}, 267 {1./12,1./12,-2./3,g}}, 268 b[4] = {5./6,-1./6,-1./6,0.5}, 269 b2[4] = {0.75,-0.25,0.5,0}; 270 ierr = TSRosWRegister(TSROSWRODAS3,3,4,&A[0][0],&Gamma[0][0],b,b2);CHKERRQ(ierr); 271 } 272 { 273 const PetscReal g = 0.43586652150845899941601945119356; 274 const PetscReal 275 A[3][3] = {{0,0,0}, 276 {g,0,0}, 277 {g,0,0}}, 278 Gamma[3][3] = {{g,0,0}, 279 {-0.19294655696029095575009695436041,g,0}, 280 {0,1.74927148125794685173529749738960,g}}, 281 b[3] = {-0.75457412385404315829818998646589,1.94100407061964420292840123379419,-0.18642994676560104463021124732829}, 282 b2[3] = {-1.53358745784149585370766523913002,2.81745131148625772213931745457622,-0.28386385364476186843165221544619}; 283 ierr = TSRosWRegister(TSROSWSANDU3,3,3,&A[0][0],&Gamma[0][0],b,b2);CHKERRQ(ierr); 284 } 285 { 286 const PetscReal s3 = PetscSqrtReal(3.),g = (3.0+s3)/6.0; 287 const PetscReal 288 A[3][3] = {{0,0,0}, 289 {1,0,0}, 290 {0.25,0.25,0}}, 291 Gamma[3][3] = {{0,0,0}, 292 {(-3.0-s3)/6.0,g,0}, 293 {(-3.0-s3)/24.0,(-3.0-s3)/8.0,g}}, 294 b[3] = {1./6.,1./6.,2./3.}, 295 b2[3] = {1./4.,1./4.,1./2.}; 296 ierr = TSRosWRegister(TSROSWASSP3P3S1C,3,3,&A[0][0],&Gamma[0][0],b,b2);CHKERRQ(ierr); 297 } 298 299 { 300 const PetscReal 301 A[4][4] = {{0,0,0,0}, 302 {1./2.,0,0,0}, 303 {1./2.,1./2.,0,0}, 304 {1./6.,1./6.,1./6.,0}}, 305 Gamma[4][4] = {{1./2.,0,0,0}, 306 {0.0,1./4.,0,0}, 307 {-2.,-2./3.,2./3.,0}, 308 {1./2.,5./36.,-2./9,0}}, 309 b[4] = {1./6.,1./6.,1./6.,1./2.}, 310 b2[4] = {1./8.,3./4.,1./8.,0}; 311 ierr = TSRosWRegister(TSROSWLASSP3P4S2C,3,4,&A[0][0],&Gamma[0][0],b,b2);CHKERRQ(ierr); 312 } 313 314 { 315 const PetscReal 316 A[4][4] = {{0,0,0,0}, 317 {1./2.,0,0,0}, 318 {1./2.,1./2.,0,0}, 319 {1./6.,1./6.,1./6.,0}}, 320 Gamma[4][4] = {{1./2.,0,0,0}, 321 {0.0,3./4.,0,0}, 322 {-2./3.,-23./9.,2./9.,0}, 323 {1./18.,65./108.,-2./27,0}}, 324 b[4] = {1./6.,1./6.,1./6.,1./2.}, 325 b2[4] = {3./16.,10./16.,3./16.,0}; 326 ierr = TSRosWRegister(TSROSWLLSSP3P4S2C,3,4,&A[0][0],&Gamma[0][0],b,b2);CHKERRQ(ierr); 327 } 328 329 { 330 PetscReal A[4][4],Gamma[4][4],b[4],b2[4]; 331 332 Gamma[0][0]=0.4358665215084589994160194475295062513822671686978816; 333 Gamma[0][1]=0; Gamma[0][2]=0; Gamma[0][3]=0; 334 Gamma[1][0]=-1.997527830934941248426324674704153457289527280554476; 335 Gamma[1][1]=0.4358665215084589994160194475295062513822671686978816; 336 Gamma[1][2]=0; Gamma[1][3]=0; 337 Gamma[2][0]=-1.007948511795029620852002345345404191008352770119903; 338 Gamma[2][1]=-0.004648958462629345562774289390054679806993396798458131; 339 Gamma[2][2]=0.4358665215084589994160194475295062513822671686978816; 340 Gamma[2][3]=0; 341 Gamma[3][0]=-0.6685429734233467180451604600279552604364311322650783; 342 Gamma[3][1]=0.6056625986449338476089525334450053439525178740492984; 343 Gamma[3][2]=-0.9717899277217721234705114616271378792182450260943198; 344 Gamma[3][3]=0; 345 346 A[0][0]=0; A[0][1]=0; A[0][2]=0; A[0][3]=0; 347 A[1][0]=0.8717330430169179988320388950590125027645343373957631; 348 A[1][1]=0; A[1][2]=0; A[1][3]=0; 349 A[2][0]=0.5275890119763004115618079766722914408876108660811028; 350 A[2][1]=0.07241098802369958843819203208518599088698057726988732; 351 A[2][2]=0; A[2][3]=0; 352 A[3][0]=0.3990960076760701320627260685975778145384666450351314; 353 A[3][1]=-0.4375576546135194437228463747348862825846903771419953; 354 A[3][2]=1.038461646937449311660120300601880176655352737312713; 355 A[3][3]=0; 356 357 b[0]=0.1876410243467238251612921333138006734899663569186926; 358 b[1]=-0.5952974735769549480478230473706443582188442040780541; 359 b[2]=0.9717899277217721234705114616271378792182450260943198; 360 b[3]=0.4358665215084589994160194475295062513822671686978816; 361 362 b2[0]=0.2147402862233891404862383521089097657790734483804460; 363 b2[1]=-0.4851622638849390928209050538171743017757490232519684; 364 b2[2]=0.8687250025203875511662123688667549217531982787600080; 365 b2[3]=0.4016969751411624011684543450940068201770721128357014; 366 367 ierr = TSRosWRegister(TSROSWARK3,3,4,&A[0][0],&Gamma[0][0],b,b2);CHKERRQ(ierr); 368 } 369 370 PetscFunctionReturn(0); 371 } 372 373 #undef __FUNCT__ 374 #define __FUNCT__ "TSRosWRegisterDestroy" 375 /*@C 376 TSRosWRegisterDestroy - Frees the list of schemes that were registered by TSRosWRegister(). 377 378 Not Collective 379 380 Level: advanced 381 382 .keywords: TSRosW, register, destroy 383 .seealso: TSRosWRegister(), TSRosWRegisterAll(), TSRosWRegisterDynamic() 384 @*/ 385 PetscErrorCode TSRosWRegisterDestroy(void) 386 { 387 PetscErrorCode ierr; 388 RosWTableauLink link; 389 390 PetscFunctionBegin; 391 while ((link = RosWTableauList)) { 392 RosWTableau t = &link->tab; 393 RosWTableauList = link->next; 394 ierr = PetscFree5(t->A,t->Gamma,t->b,t->ASum,t->GammaSum);CHKERRQ(ierr); 395 ierr = PetscFree5(t->At,t->bt,t->GammaInv,t->GammaZeroDiag,t->GammaExplicitCorr);CHKERRQ(ierr); 396 ierr = PetscFree2(t->bembed,t->bembedt);CHKERRQ(ierr); 397 ierr = PetscFree(t->name);CHKERRQ(ierr); 398 ierr = PetscFree(link);CHKERRQ(ierr); 399 } 400 TSRosWRegisterAllCalled = PETSC_FALSE; 401 PetscFunctionReturn(0); 402 } 403 404 #undef __FUNCT__ 405 #define __FUNCT__ "TSRosWInitializePackage" 406 /*@C 407 TSRosWInitializePackage - This function initializes everything in the TSRosW package. It is called 408 from PetscDLLibraryRegister() when using dynamic libraries, and on the first call to TSCreate_RosW() 409 when using static libraries. 410 411 Input Parameter: 412 path - The dynamic library path, or PETSC_NULL 413 414 Level: developer 415 416 .keywords: TS, TSRosW, initialize, package 417 .seealso: PetscInitialize() 418 @*/ 419 PetscErrorCode TSRosWInitializePackage(const char path[]) 420 { 421 PetscErrorCode ierr; 422 423 PetscFunctionBegin; 424 if (TSRosWPackageInitialized) PetscFunctionReturn(0); 425 TSRosWPackageInitialized = PETSC_TRUE; 426 ierr = TSRosWRegisterAll();CHKERRQ(ierr); 427 ierr = PetscRegisterFinalize(TSRosWFinalizePackage);CHKERRQ(ierr); 428 PetscFunctionReturn(0); 429 } 430 431 #undef __FUNCT__ 432 #define __FUNCT__ "TSRosWFinalizePackage" 433 /*@C 434 TSRosWFinalizePackage - This function destroys everything in the TSRosW package. It is 435 called from PetscFinalize(). 436 437 Level: developer 438 439 .keywords: Petsc, destroy, package 440 .seealso: PetscFinalize() 441 @*/ 442 PetscErrorCode TSRosWFinalizePackage(void) 443 { 444 PetscErrorCode ierr; 445 446 PetscFunctionBegin; 447 TSRosWPackageInitialized = PETSC_FALSE; 448 ierr = TSRosWRegisterDestroy();CHKERRQ(ierr); 449 PetscFunctionReturn(0); 450 } 451 452 #undef __FUNCT__ 453 #define __FUNCT__ "TSRosWRegister" 454 /*@C 455 TSRosWRegister - register a Rosenbrock W scheme by providing the entries in the Butcher tableau and optionally embedded approximations and interpolation 456 457 Not Collective, but the same schemes should be registered on all processes on which they will be used 458 459 Input Parameters: 460 + name - identifier for method 461 . order - approximation order of method 462 . s - number of stages, this is the dimension of the matrices below 463 . A - Table of propagated stage coefficients (dimension s*s, row-major), strictly lower triangular 464 . Gamma - Table of coefficients in implicit stage equations (dimension s*s, row-major), lower triangular with nonzero diagonal 465 . b - Step completion table (dimension s) 466 - bembed - Step completion table for a scheme of order one less (dimension s, PETSC_NULL if no embedded scheme is available) 467 468 Notes: 469 Several Rosenbrock W methods are provided, this function is only needed to create new methods. 470 471 Level: advanced 472 473 .keywords: TS, register 474 475 .seealso: TSRosW 476 @*/ 477 PetscErrorCode TSRosWRegister(const TSRosWType name,PetscInt order,PetscInt s, 478 const PetscReal A[],const PetscReal Gamma[],const PetscReal b[],const PetscReal bembed[]) 479 { 480 PetscErrorCode ierr; 481 RosWTableauLink link; 482 RosWTableau t; 483 PetscInt i,j,k; 484 PetscScalar *GammaInv; 485 486 PetscFunctionBegin; 487 PetscValidCharPointer(name,1); 488 PetscValidPointer(A,4); 489 PetscValidPointer(Gamma,5); 490 PetscValidPointer(b,6); 491 if (bembed) PetscValidPointer(bembed,7); 492 493 ierr = PetscMalloc(sizeof(*link),&link);CHKERRQ(ierr); 494 ierr = PetscMemzero(link,sizeof(*link));CHKERRQ(ierr); 495 t = &link->tab; 496 ierr = PetscStrallocpy(name,&t->name);CHKERRQ(ierr); 497 t->order = order; 498 t->s = s; 499 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); 500 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); 501 ierr = PetscMemcpy(t->A,A,s*s*sizeof(A[0]));CHKERRQ(ierr); 502 ierr = PetscMemcpy(t->Gamma,Gamma,s*s*sizeof(Gamma[0]));CHKERRQ(ierr); 503 ierr = PetscMemcpy(t->GammaExplicitCorr,Gamma,s*s*sizeof(Gamma[0]));CHKERRQ(ierr); 504 ierr = PetscMemcpy(t->b,b,s*sizeof(b[0]));CHKERRQ(ierr); 505 if (bembed) { 506 ierr = PetscMalloc2(s,PetscReal,&t->bembed,s,PetscReal,&t->bembedt);CHKERRQ(ierr); 507 ierr = PetscMemcpy(t->bembed,bembed,s*sizeof(bembed[0]));CHKERRQ(ierr); 508 } 509 for (i=0; i<s; i++) { 510 t->ASum[i] = 0; 511 t->GammaSum[i] = 0; 512 for (j=0; j<s; j++) { 513 t->ASum[i] += A[i*s+j]; 514 t->GammaSum[i] += Gamma[i*s+j]; 515 } 516 } 517 ierr = PetscMalloc(s*s*sizeof(PetscScalar),&GammaInv);CHKERRQ(ierr); /* Need to use Scalar for inverse, then convert back to Real */ 518 for (i=0; i<s*s; i++) GammaInv[i] = Gamma[i]; 519 for (i=0; i<s; i++) { 520 if (Gamma[i*s+i] == 0.0) { 521 GammaInv[i*s+i] = 1.0; 522 t->GammaZeroDiag[i] = PETSC_TRUE; 523 } else { 524 t->GammaZeroDiag[i] = PETSC_FALSE; 525 } 526 } 527 528 switch (s) { 529 case 1: GammaInv[0] = 1./GammaInv[0]; break; 530 case 2: ierr = Kernel_A_gets_inverse_A_2(GammaInv,0);CHKERRQ(ierr); break; 531 case 3: ierr = Kernel_A_gets_inverse_A_3(GammaInv,0);CHKERRQ(ierr); break; 532 case 4: ierr = Kernel_A_gets_inverse_A_4(GammaInv,0);CHKERRQ(ierr); break; 533 case 5: { 534 PetscInt ipvt5[5]; 535 MatScalar work5[5*5]; 536 ierr = Kernel_A_gets_inverse_A_5(GammaInv,ipvt5,work5,0);CHKERRQ(ierr); break; 537 } 538 case 6: ierr = Kernel_A_gets_inverse_A_6(GammaInv,0);CHKERRQ(ierr); break; 539 case 7: ierr = Kernel_A_gets_inverse_A_7(GammaInv,0);CHKERRQ(ierr); break; 540 default: SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented for %D stages",s); 541 } 542 for (i=0; i<s*s; i++) t->GammaInv[i] = PetscRealPart(GammaInv[i]); 543 ierr = PetscFree(GammaInv);CHKERRQ(ierr); 544 545 for (i=0; i<s; i++) { 546 for (k=0; k<i+1; k++) { 547 t->GammaExplicitCorr[i*s+k]=(t->GammaExplicitCorr[i*s+k])*(t->GammaInv[k*s+k]); 548 for (j=k+1; j<i+1; j++) { 549 t->GammaExplicitCorr[i*s+k]+=(t->GammaExplicitCorr[i*s+j])*(t->GammaInv[j*s+k]); 550 } 551 } 552 } 553 554 for (i=0; i<s; i++) { 555 for (j=0; j<s; j++) { 556 t->At[i*s+j] = 0; 557 for (k=0; k<s; k++) { 558 t->At[i*s+j] += t->A[i*s+k] * t->GammaInv[k*s+j]; 559 } 560 } 561 t->bt[i] = 0; 562 for (j=0; j<s; j++) { 563 t->bt[i] += t->b[j] * t->GammaInv[j*s+i]; 564 } 565 if (bembed) { 566 t->bembedt[i] = 0; 567 for (j=0; j<s; j++) { 568 t->bembedt[i] += t->bembed[j] * t->GammaInv[j*s+i]; 569 } 570 } 571 } 572 t->ccfl = 1.0; /* Fix this */ 573 574 link->next = RosWTableauList; 575 RosWTableauList = link; 576 PetscFunctionReturn(0); 577 } 578 579 #undef __FUNCT__ 580 #define __FUNCT__ "TSEvaluateStep_RosW" 581 /* 582 The step completion formula is 583 584 x1 = x0 + b^T Y 585 586 where Y is the multi-vector of stages corrections. This function can be called before or after ts->vec_sol has been 587 updated. Suppose we have a completion formula b and an embedded formula be of different order. We can write 588 589 x1e = x0 + be^T Y 590 = x1 - b^T Y + be^T Y 591 = x1 + (be - b)^T Y 592 593 so we can evaluate the method of different order even after the step has been optimistically completed. 594 */ 595 static PetscErrorCode TSEvaluateStep_RosW(TS ts,PetscInt order,Vec X,PetscBool *done) 596 { 597 TS_RosW *ros = (TS_RosW*)ts->data; 598 RosWTableau tab = ros->tableau; 599 PetscScalar *w = ros->work; 600 PetscInt i; 601 PetscErrorCode ierr; 602 603 PetscFunctionBegin; 604 if (order == tab->order) { 605 if (ros->status == TS_STEP_INCOMPLETE) { /* Use standard completion formula */ 606 ierr = VecCopy(ts->vec_sol,X);CHKERRQ(ierr); 607 for (i=0; i<tab->s; i++) w[i] = tab->bt[i]; 608 ierr = VecMAXPY(X,tab->s,w,ros->Y);CHKERRQ(ierr); 609 } else {ierr = VecCopy(ts->vec_sol,X);CHKERRQ(ierr);} 610 if (done) *done = PETSC_TRUE; 611 PetscFunctionReturn(0); 612 } else if (order == tab->order-1) { 613 if (!tab->bembedt) goto unavailable; 614 if (ros->status == TS_STEP_INCOMPLETE) { /* Use embedded completion formula */ 615 ierr = VecCopy(ts->vec_sol,X);CHKERRQ(ierr); 616 for (i=0; i<tab->s; i++) w[i] = tab->bembedt[i]; 617 ierr = VecMAXPY(X,tab->s,w,ros->Y);CHKERRQ(ierr); 618 } else { /* Use rollback-and-recomplete formula (bembedt - bt) */ 619 for (i=0; i<tab->s; i++) w[i] = tab->bembedt[i] - tab->bt[i]; 620 ierr = VecCopy(ts->vec_sol,X);CHKERRQ(ierr); 621 ierr = VecMAXPY(X,tab->s,w,ros->Y);CHKERRQ(ierr); 622 } 623 if (done) *done = PETSC_TRUE; 624 PetscFunctionReturn(0); 625 } 626 unavailable: 627 if (done) *done = PETSC_FALSE; 628 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); 629 PetscFunctionReturn(0); 630 } 631 632 #undef __FUNCT__ 633 #define __FUNCT__ "TSStep_RosW" 634 static PetscErrorCode TSStep_RosW(TS ts) 635 { 636 TS_RosW *ros = (TS_RosW*)ts->data; 637 RosWTableau tab = ros->tableau; 638 const PetscInt s = tab->s; 639 const PetscReal *At = tab->At,*Gamma = tab->Gamma,*ASum = tab->ASum,*GammaInv = tab->GammaInv; 640 const PetscBool *GammaZeroDiag = tab->GammaZeroDiag; 641 PetscScalar *w = ros->work; 642 Vec *Y = ros->Y,Ydot = ros->Ydot,Zdot = ros->Zdot,Zstage = ros->Zstage; 643 SNES snes; 644 TSAdapt adapt; 645 PetscInt i,j,its,lits,reject,next_scheme; 646 PetscReal next_time_step; 647 PetscBool accept; 648 PetscErrorCode ierr; 649 650 PetscFunctionBegin; 651 ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr); 652 next_time_step = ts->time_step; 653 accept = PETSC_TRUE; 654 ros->status = TS_STEP_INCOMPLETE; 655 656 for (reject=0; reject<ts->max_reject; reject++,ts->reject++) { 657 const PetscReal h = ts->time_step; 658 for (i=0; i<s; i++) { 659 ros->stage_time = ts->ptime + h*ASum[i]; 660 if (GammaZeroDiag[i]) { 661 ros->stage_explicit = PETSC_TRUE; 662 ros->shift = 1./h; 663 } else { 664 ros->stage_explicit = PETSC_FALSE; 665 ros->shift = 1./(h*Gamma[i*s+i]); 666 } 667 668 ierr = VecCopy(ts->vec_sol,Zstage);CHKERRQ(ierr); 669 for (j=0; j<i; j++) w[j] = At[i*s+j]; 670 ierr = VecMAXPY(Zstage,i,w,Y);CHKERRQ(ierr); 671 672 for (j=0; j<i; j++) w[j] = 1./h * GammaInv[i*s+j]; 673 ierr = VecZeroEntries(Zdot);CHKERRQ(ierr); 674 ierr = VecMAXPY(Zdot,i,w,Y);CHKERRQ(ierr); 675 676 /* Initial guess taken from last stage */ 677 ierr = VecZeroEntries(Y[i]);CHKERRQ(ierr); 678 679 if (!ros->stage_explicit) { 680 if (!ros->recompute_jacobian && !i) { 681 ierr = SNESSetLagJacobian(snes,-2);CHKERRQ(ierr); /* Recompute the Jacobian on this solve, but not again */ 682 } 683 ierr = SNESSolve(snes,PETSC_NULL,Y[i]);CHKERRQ(ierr); 684 ierr = SNESGetIterationNumber(snes,&its);CHKERRQ(ierr); 685 ierr = SNESGetLinearSolveIterations(snes,&lits);CHKERRQ(ierr); 686 ts->nonlinear_its += its; ts->linear_its += lits; 687 } else { 688 ierr = VecWAXPY(Ydot,1,ts->vec_sol,Zdot);CHKERRQ(ierr); /* Ydot = x0 + Zdot */ 689 ierr = TSComputeIFunction(ts,ros->stage_time,ros->Ystage,Ydot,Zdot,PETSC_FALSE);CHKERRQ(ierr); 690 ierr = VecWAXPY(ros->Ystage,1.0,Zdot,ros->Zstage);CHKERRQ(ierr); /* Ystage = F + Zstage */ 691 ts->linear_its += 1; 692 } 693 } 694 ierr = TSEvaluateStep(ts,tab->order,ts->vec_sol,PETSC_NULL);CHKERRQ(ierr); 695 ros->status = TS_STEP_PENDING; 696 697 /* Register only the current method as a candidate because we're not supporting multiple candidates yet. */ 698 ierr = TSGetAdapt(ts,&adapt);CHKERRQ(ierr); 699 ierr = TSAdaptCandidatesClear(adapt);CHKERRQ(ierr); 700 ierr = TSAdaptCandidateAdd(adapt,tab->name,tab->order,1,tab->ccfl,1.*tab->s,PETSC_TRUE);CHKERRQ(ierr); 701 ierr = TSAdaptChoose(adapt,ts,ts->time_step,&next_scheme,&next_time_step,&accept);CHKERRQ(ierr); 702 if (accept) { 703 /* ignore next_scheme for now */ 704 ts->ptime += ts->time_step; 705 ts->time_step = next_time_step; 706 ts->steps++; 707 ros->status = TS_STEP_COMPLETE; 708 break; 709 } else { /* Roll back the current step */ 710 for (i=0; i<s; i++) w[i] = -tab->bt[i]; 711 ierr = VecMAXPY(ts->vec_sol,s,w,Y);CHKERRQ(ierr); 712 ts->time_step = next_time_step; 713 ros->status = TS_STEP_INCOMPLETE; 714 } 715 } 716 PetscFunctionReturn(0); 717 } 718 719 #undef __FUNCT__ 720 #define __FUNCT__ "TSInterpolate_RosW" 721 static PetscErrorCode TSInterpolate_RosW(TS ts,PetscReal itime,Vec X) 722 { 723 TS_RosW *ros = (TS_RosW*)ts->data; 724 725 PetscFunctionBegin; 726 SETERRQ1(((PetscObject)ts)->comm,PETSC_ERR_SUP,"TSRosW %s does not have an interpolation formula",ros->tableau->name); 727 PetscFunctionReturn(0); 728 } 729 730 /*------------------------------------------------------------*/ 731 #undef __FUNCT__ 732 #define __FUNCT__ "TSReset_RosW" 733 static PetscErrorCode TSReset_RosW(TS ts) 734 { 735 TS_RosW *ros = (TS_RosW*)ts->data; 736 PetscInt s; 737 PetscErrorCode ierr; 738 739 PetscFunctionBegin; 740 if (!ros->tableau) PetscFunctionReturn(0); 741 s = ros->tableau->s; 742 ierr = VecDestroyVecs(s,&ros->Y);CHKERRQ(ierr); 743 ierr = VecDestroy(&ros->Ydot);CHKERRQ(ierr); 744 ierr = VecDestroy(&ros->Ystage);CHKERRQ(ierr); 745 ierr = VecDestroy(&ros->Zdot);CHKERRQ(ierr); 746 ierr = VecDestroy(&ros->Zstage);CHKERRQ(ierr); 747 ierr = PetscFree(ros->work);CHKERRQ(ierr); 748 PetscFunctionReturn(0); 749 } 750 751 #undef __FUNCT__ 752 #define __FUNCT__ "TSDestroy_RosW" 753 static PetscErrorCode TSDestroy_RosW(TS ts) 754 { 755 PetscErrorCode ierr; 756 757 PetscFunctionBegin; 758 ierr = TSReset_RosW(ts);CHKERRQ(ierr); 759 ierr = PetscFree(ts->data);CHKERRQ(ierr); 760 ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSRosWGetType_C","",PETSC_NULL);CHKERRQ(ierr); 761 ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSRosWSetType_C","",PETSC_NULL);CHKERRQ(ierr); 762 ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSRosWSetRecomputeJacobian_C","",PETSC_NULL);CHKERRQ(ierr); 763 PetscFunctionReturn(0); 764 } 765 766 /* 767 This defines the nonlinear equation that is to be solved with SNES 768 G(U) = F[t0+Theta*dt, U, (U-U0)*shift] = 0 769 */ 770 #undef __FUNCT__ 771 #define __FUNCT__ "SNESTSFormFunction_RosW" 772 static PetscErrorCode SNESTSFormFunction_RosW(SNES snes,Vec X,Vec F,TS ts) 773 { 774 TS_RosW *ros = (TS_RosW*)ts->data; 775 PetscErrorCode ierr; 776 777 PetscFunctionBegin; 778 ierr = VecWAXPY(ros->Ydot,ros->shift,X,ros->Zdot);CHKERRQ(ierr); /* Ydot = shift*X + Zdot */ 779 ierr = VecWAXPY(ros->Ystage,1.0,X,ros->Zstage);CHKERRQ(ierr); /* Ystage = X + Zstage */ 780 ierr = TSComputeIFunction(ts,ros->stage_time,ros->Ystage,ros->Ydot,F,PETSC_FALSE);CHKERRQ(ierr); 781 PetscFunctionReturn(0); 782 } 783 784 #undef __FUNCT__ 785 #define __FUNCT__ "SNESTSFormJacobian_RosW" 786 static PetscErrorCode SNESTSFormJacobian_RosW(SNES snes,Vec X,Mat *A,Mat *B,MatStructure *str,TS ts) 787 { 788 TS_RosW *ros = (TS_RosW*)ts->data; 789 PetscErrorCode ierr; 790 791 PetscFunctionBegin; 792 /* ros->Ydot and ros->Ystage have already been computed in SNESTSFormFunction_RosW (SNES guarantees this) */ 793 ierr = TSComputeIJacobian(ts,ros->stage_time,ros->Ystage,ros->Ydot,ros->shift,A,B,str,PETSC_TRUE);CHKERRQ(ierr); 794 PetscFunctionReturn(0); 795 } 796 797 #undef __FUNCT__ 798 #define __FUNCT__ "TSSetUp_RosW" 799 static PetscErrorCode TSSetUp_RosW(TS ts) 800 { 801 TS_RosW *ros = (TS_RosW*)ts->data; 802 RosWTableau tab = ros->tableau; 803 PetscInt s = tab->s; 804 PetscErrorCode ierr; 805 806 PetscFunctionBegin; 807 if (!ros->tableau) { 808 ierr = TSRosWSetType(ts,TSRosWDefault);CHKERRQ(ierr); 809 } 810 ierr = VecDuplicateVecs(ts->vec_sol,s,&ros->Y);CHKERRQ(ierr); 811 ierr = VecDuplicate(ts->vec_sol,&ros->Ydot);CHKERRQ(ierr); 812 ierr = VecDuplicate(ts->vec_sol,&ros->Ystage);CHKERRQ(ierr); 813 ierr = VecDuplicate(ts->vec_sol,&ros->Zdot);CHKERRQ(ierr); 814 ierr = VecDuplicate(ts->vec_sol,&ros->Zstage);CHKERRQ(ierr); 815 ierr = PetscMalloc(s*sizeof(ros->work[0]),&ros->work);CHKERRQ(ierr); 816 PetscFunctionReturn(0); 817 } 818 /*------------------------------------------------------------*/ 819 820 #undef __FUNCT__ 821 #define __FUNCT__ "TSSetFromOptions_RosW" 822 static PetscErrorCode TSSetFromOptions_RosW(TS ts) 823 { 824 TS_RosW *ros = (TS_RosW*)ts->data; 825 PetscErrorCode ierr; 826 char rostype[256]; 827 828 PetscFunctionBegin; 829 ierr = PetscOptionsHead("RosW ODE solver options");CHKERRQ(ierr); 830 { 831 RosWTableauLink link; 832 PetscInt count,choice; 833 PetscBool flg; 834 const char **namelist; 835 SNES snes; 836 837 ierr = PetscStrncpy(rostype,TSRosWDefault,sizeof rostype);CHKERRQ(ierr); 838 for (link=RosWTableauList,count=0; link; link=link->next,count++) ; 839 ierr = PetscMalloc(count*sizeof(char*),&namelist);CHKERRQ(ierr); 840 for (link=RosWTableauList,count=0; link; link=link->next,count++) namelist[count] = link->tab.name; 841 ierr = PetscOptionsEList("-ts_rosw_type","Family of Rosenbrock-W method","TSRosWSetType",(const char*const*)namelist,count,rostype,&choice,&flg);CHKERRQ(ierr); 842 ierr = TSRosWSetType(ts,flg ? namelist[choice] : rostype);CHKERRQ(ierr); 843 ierr = PetscFree(namelist);CHKERRQ(ierr); 844 845 ierr = PetscOptionsBool("-ts_rosw_recompute_jacobian","Recompute the Jacobian at each stage","TSRosWSetRecomputeJacobian",ros->recompute_jacobian,&ros->recompute_jacobian,PETSC_NULL);CHKERRQ(ierr); 846 847 /* Rosenbrock methods are linearly implicit, so set that unless the user has specifically asked for something else */ 848 ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr); 849 if (!((PetscObject)snes)->type_name) { 850 ierr = SNESSetType(snes,SNESKSPONLY);CHKERRQ(ierr); 851 } 852 ierr = SNESSetFromOptions(snes);CHKERRQ(ierr); 853 } 854 ierr = PetscOptionsTail();CHKERRQ(ierr); 855 PetscFunctionReturn(0); 856 } 857 858 #undef __FUNCT__ 859 #define __FUNCT__ "PetscFormatRealArray" 860 static PetscErrorCode PetscFormatRealArray(char buf[],size_t len,const char *fmt,PetscInt n,const PetscReal x[]) 861 { 862 PetscErrorCode ierr; 863 PetscInt i; 864 size_t left,count; 865 char *p; 866 867 PetscFunctionBegin; 868 for (i=0,p=buf,left=len; i<n; i++) { 869 ierr = PetscSNPrintfCount(p,left,fmt,&count,x[i]);CHKERRQ(ierr); 870 if (count >= left) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Insufficient space in buffer"); 871 left -= count; 872 p += count; 873 *p++ = ' '; 874 } 875 p[i ? 0 : -1] = 0; 876 PetscFunctionReturn(0); 877 } 878 879 #undef __FUNCT__ 880 #define __FUNCT__ "TSView_RosW" 881 static PetscErrorCode TSView_RosW(TS ts,PetscViewer viewer) 882 { 883 TS_RosW *ros = (TS_RosW*)ts->data; 884 RosWTableau tab = ros->tableau; 885 PetscBool iascii; 886 PetscErrorCode ierr; 887 888 PetscFunctionBegin; 889 ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 890 if (iascii) { 891 const TSRosWType rostype; 892 PetscInt i; 893 PetscReal abscissa[512]; 894 char buf[512]; 895 ierr = TSRosWGetType(ts,&rostype);CHKERRQ(ierr); 896 ierr = PetscViewerASCIIPrintf(viewer," Rosenbrock-W %s\n",rostype);CHKERRQ(ierr); 897 ierr = PetscFormatRealArray(buf,sizeof buf,"% 8.6f",tab->s,tab->ASum);CHKERRQ(ierr); 898 ierr = PetscViewerASCIIPrintf(viewer," Abscissa of A = %s\n",buf);CHKERRQ(ierr); 899 for (i=0; i<tab->s; i++) abscissa[i] = tab->ASum[i] + tab->Gamma[i]; 900 ierr = PetscFormatRealArray(buf,sizeof buf,"% 8.6f",tab->s,abscissa);CHKERRQ(ierr); 901 ierr = PetscViewerASCIIPrintf(viewer," Abscissa of A+Gamma = %s\n",buf);CHKERRQ(ierr); 902 } 903 ierr = SNESView(ts->snes,viewer);CHKERRQ(ierr); 904 PetscFunctionReturn(0); 905 } 906 907 #undef __FUNCT__ 908 #define __FUNCT__ "TSRosWSetType" 909 /*@C 910 TSRosWSetType - Set the type of Rosenbrock-W scheme 911 912 Logically collective 913 914 Input Parameter: 915 + ts - timestepping context 916 - rostype - type of Rosenbrock-W scheme 917 918 Level: intermediate 919 920 .seealso: TSRosWGetType() 921 @*/ 922 PetscErrorCode TSRosWSetType(TS ts,const TSRosWType rostype) 923 { 924 PetscErrorCode ierr; 925 926 PetscFunctionBegin; 927 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 928 ierr = PetscTryMethod(ts,"TSRosWSetType_C",(TS,const TSRosWType),(ts,rostype));CHKERRQ(ierr); 929 PetscFunctionReturn(0); 930 } 931 932 #undef __FUNCT__ 933 #define __FUNCT__ "TSRosWGetType" 934 /*@C 935 TSRosWGetType - Get the type of Rosenbrock-W scheme 936 937 Logically collective 938 939 Input Parameter: 940 . ts - timestepping context 941 942 Output Parameter: 943 . rostype - type of Rosenbrock-W scheme 944 945 Level: intermediate 946 947 .seealso: TSRosWGetType() 948 @*/ 949 PetscErrorCode TSRosWGetType(TS ts,const TSRosWType *rostype) 950 { 951 PetscErrorCode ierr; 952 953 PetscFunctionBegin; 954 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 955 ierr = PetscUseMethod(ts,"TSRosWGetType_C",(TS,const TSRosWType*),(ts,rostype));CHKERRQ(ierr); 956 PetscFunctionReturn(0); 957 } 958 959 #undef __FUNCT__ 960 #define __FUNCT__ "TSRosWSetRecomputeJacobian" 961 /*@C 962 TSRosWSetRecomputeJacobian - Set whether to recompute the Jacobian at each stage. The default is to update the Jacobian once per step. 963 964 Logically collective 965 966 Input Parameter: 967 + ts - timestepping context 968 - flg - PETSC_TRUE to recompute the Jacobian at each stage 969 970 Level: intermediate 971 972 .seealso: TSRosWGetType() 973 @*/ 974 PetscErrorCode TSRosWSetRecomputeJacobian(TS ts,PetscBool flg) 975 { 976 PetscErrorCode ierr; 977 978 PetscFunctionBegin; 979 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 980 ierr = PetscTryMethod(ts,"TSRosWSetRecomputeJacobian_C",(TS,PetscBool),(ts,flg));CHKERRQ(ierr); 981 PetscFunctionReturn(0); 982 } 983 984 EXTERN_C_BEGIN 985 #undef __FUNCT__ 986 #define __FUNCT__ "TSRosWGetType_RosW" 987 PetscErrorCode TSRosWGetType_RosW(TS ts,const TSRosWType *rostype) 988 { 989 TS_RosW *ros = (TS_RosW*)ts->data; 990 PetscErrorCode ierr; 991 992 PetscFunctionBegin; 993 if (!ros->tableau) {ierr = TSRosWSetType(ts,TSRosWDefault);CHKERRQ(ierr);} 994 *rostype = ros->tableau->name; 995 PetscFunctionReturn(0); 996 } 997 #undef __FUNCT__ 998 #define __FUNCT__ "TSRosWSetType_RosW" 999 PetscErrorCode TSRosWSetType_RosW(TS ts,const TSRosWType rostype) 1000 { 1001 TS_RosW *ros = (TS_RosW*)ts->data; 1002 PetscErrorCode ierr; 1003 PetscBool match; 1004 RosWTableauLink link; 1005 1006 PetscFunctionBegin; 1007 if (ros->tableau) { 1008 ierr = PetscStrcmp(ros->tableau->name,rostype,&match);CHKERRQ(ierr); 1009 if (match) PetscFunctionReturn(0); 1010 } 1011 for (link = RosWTableauList; link; link=link->next) { 1012 ierr = PetscStrcmp(link->tab.name,rostype,&match);CHKERRQ(ierr); 1013 if (match) { 1014 ierr = TSReset_RosW(ts);CHKERRQ(ierr); 1015 ros->tableau = &link->tab; 1016 PetscFunctionReturn(0); 1017 } 1018 } 1019 SETERRQ1(((PetscObject)ts)->comm,PETSC_ERR_ARG_UNKNOWN_TYPE,"Could not find '%s'",rostype); 1020 PetscFunctionReturn(0); 1021 } 1022 1023 #undef __FUNCT__ 1024 #define __FUNCT__ "TSRosWSetRecomputeJacobian_RosW" 1025 PetscErrorCode TSRosWSetRecomputeJacobian_RosW(TS ts,PetscBool flg) 1026 { 1027 TS_RosW *ros = (TS_RosW*)ts->data; 1028 1029 PetscFunctionBegin; 1030 ros->recompute_jacobian = flg; 1031 PetscFunctionReturn(0); 1032 } 1033 EXTERN_C_END 1034 1035 /* ------------------------------------------------------------ */ 1036 /*MC 1037 TSRosW - ODE solver using Rosenbrock-W schemes 1038 1039 These methods are intended for problems with well-separated time scales, especially when a slow scale is strongly 1040 nonlinear such that it is expensive to solve with a fully implicit method. The user should provide the stiff part 1041 of the equation using TSSetIFunction() and the non-stiff part with TSSetRHSFunction(). 1042 1043 Notes: 1044 This method currently only works with autonomous ODE and DAE. 1045 1046 Developer notes: 1047 Rosenbrock-W methods are typically specified for autonomous ODE 1048 1049 $ xdot = f(x) 1050 1051 by the stage equations 1052 1053 $ k_i = h f(x_0 + sum_j alpha_ij k_j) + h J sum_j gamma_ij k_j 1054 1055 and step completion formula 1056 1057 $ x_1 = x_0 + sum_j b_j k_j 1058 1059 with step size h and coefficients alpha_ij, gamma_ij, and b_i. Implementing the method in this form would require f(x) 1060 and the Jacobian J to be available, in addition to the shifted matrix I - h gamma_ii J. Following Hairer and Wanner, 1061 we define new variables for the stage equations 1062 1063 $ y_i = gamma_ij k_j 1064 1065 The k_j can be recovered because Gamma is invertible. Let C be the lower triangular part of Gamma^{-1} and define 1066 1067 $ A = Alpha Gamma^{-1}, bt^T = b^T Gamma^{-i} 1068 1069 to rewrite the method as 1070 1071 $ [M/(h gamma_ii) - J] y_i = f(x_0 + sum_j a_ij y_j) + M sum_j (c_ij/h) y_j 1072 $ x_1 = x_0 + sum_j bt_j y_j 1073 1074 where we have introduced the mass matrix M. Continue by defining 1075 1076 $ ydot_i = 1/(h gamma_ii) y_i - sum_j (c_ij/h) y_j 1077 1078 or, more compactly in tensor notation 1079 1080 $ Ydot = 1/h (Gamma^{-1} \otimes I) Y . 1081 1082 Note that Gamma^{-1} is lower triangular. With this definition of Ydot in terms of known quantities and the current 1083 stage y_i, the stage equations reduce to performing one Newton step (typically with a lagged Jacobian) on the 1084 equation 1085 1086 $ g(x_0 + sum_j a_ij y_j + y_i, ydot_i) = 0 1087 1088 with initial guess y_i = 0. 1089 1090 Level: beginner 1091 1092 .seealso: TSCreate(), TS, TSSetType(), TSRosWRegister() 1093 1094 M*/ 1095 EXTERN_C_BEGIN 1096 #undef __FUNCT__ 1097 #define __FUNCT__ "TSCreate_RosW" 1098 PetscErrorCode TSCreate_RosW(TS ts) 1099 { 1100 TS_RosW *ros; 1101 PetscErrorCode ierr; 1102 1103 PetscFunctionBegin; 1104 #if !defined(PETSC_USE_DYNAMIC_LIBRARIES) 1105 ierr = TSRosWInitializePackage(PETSC_NULL);CHKERRQ(ierr); 1106 #endif 1107 1108 ts->ops->reset = TSReset_RosW; 1109 ts->ops->destroy = TSDestroy_RosW; 1110 ts->ops->view = TSView_RosW; 1111 ts->ops->setup = TSSetUp_RosW; 1112 ts->ops->step = TSStep_RosW; 1113 ts->ops->interpolate = TSInterpolate_RosW; 1114 ts->ops->evaluatestep = TSEvaluateStep_RosW; 1115 ts->ops->setfromoptions = TSSetFromOptions_RosW; 1116 ts->ops->snesfunction = SNESTSFormFunction_RosW; 1117 ts->ops->snesjacobian = SNESTSFormJacobian_RosW; 1118 1119 ierr = PetscNewLog(ts,TS_RosW,&ros);CHKERRQ(ierr); 1120 ts->data = (void*)ros; 1121 1122 ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSRosWGetType_C","TSRosWGetType_RosW",TSRosWGetType_RosW);CHKERRQ(ierr); 1123 ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSRosWSetType_C","TSRosWSetType_RosW",TSRosWSetType_RosW);CHKERRQ(ierr); 1124 ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSRosWSetRecomputeJacobian_C","TSRosWSetRecomputeJacobian_RosW",TSRosWSetRecomputeJacobian_RosW);CHKERRQ(ierr); 1125 PetscFunctionReturn(0); 1126 } 1127 EXTERN_C_END 1128