1 /* 2 Code for time stepping with the General Linear with Error Estimation method 3 4 5 Notes: 6 The general system is written as 7 8 Udot = F(t,U) 9 10 */ 11 #include <petsc/private/tsimpl.h> /*I "petscts.h" I*/ 12 #include <petscdm.h> 13 14 static PetscBool cited = PETSC_FALSE; 15 static const char citation[] = 16 "@ARTICLE{Constantinescu_TR2016b,\n" 17 " author = {Constantinescu, E.M.},\n" 18 " title = {Estimating Global Errors in Time Stepping},\n" 19 " journal = {ArXiv e-prints},\n" 20 " year = 2016,\n" 21 " adsurl = {http://adsabs.harvard.edu/abs/2015arXiv150305166C}\n}\n"; 22 23 static TSGLEEType TSGLEEDefaultType = TSGLEE35; 24 static PetscBool TSGLEERegisterAllCalled; 25 static PetscBool TSGLEEPackageInitialized; 26 static PetscInt explicit_stage_time_id; 27 28 typedef struct _GLEETableau *GLEETableau; 29 struct _GLEETableau { 30 char *name; 31 PetscInt order; /* Classical approximation order of the method i*/ 32 PetscInt s; /* Number of stages */ 33 PetscInt r; /* Number of steps */ 34 PetscReal gamma; /* LTE ratio */ 35 PetscReal *A,*B,*U,*V,*S,*F,*c; /* Tableau */ 36 PetscReal *Fembed; /* Embedded final method coefficients */ 37 PetscReal *Ferror; /* Coefficients for computing error */ 38 PetscReal *Serror; /* Coefficients for initializing the error */ 39 PetscInt pinterp; /* Interpolation order */ 40 PetscReal *binterp; /* Interpolation coefficients */ 41 PetscReal ccfl; /* Placeholder for CFL coefficient relative to forward Euler */ 42 }; 43 typedef struct _GLEETableauLink *GLEETableauLink; 44 struct _GLEETableauLink { 45 struct _GLEETableau tab; 46 GLEETableauLink next; 47 }; 48 static GLEETableauLink GLEETableauList; 49 50 typedef struct { 51 GLEETableau tableau; 52 Vec *Y; /* Solution vector (along with auxiliary solution y~ or eps) */ 53 Vec *X; /* Temporary solution vector */ 54 Vec *YStage; /* Stage values */ 55 Vec *YdotStage; /* Stage right hand side */ 56 Vec W; /* Right-hand-side for implicit stage solve */ 57 Vec Ydot; /* Work vector holding Ydot during residual evaluation */ 58 Vec yGErr; /* Vector holding the global error after a step is completed */ 59 PetscScalar *work; /* Scalar work */ 60 PetscReal scoeff; /* shift = scoeff/dt */ 61 PetscReal stage_time; 62 TSStepStatus status; 63 } TS_GLEE; 64 65 /*MC 66 TSGLEE23 - Second order three stage GLEE method 67 68 This method has three stages. 69 s = 3, r = 2 70 71 Level: advanced 72 73 .seealso: TSGLEE 74 */ 75 /*MC 76 TSGLEE24 - Second order four stage GLEE method 77 78 This method has four stages. 79 s = 4, r = 2 80 81 Level: advanced 82 83 .seealso: TSGLEE 84 */ 85 /*MC 86 TSGLEE25i - Second order five stage GLEE method 87 88 This method has five stages. 89 s = 5, r = 2 90 91 Level: advanced 92 93 .seealso: TSGLEE 94 */ 95 /*MC 96 TSGLEE35 - Third order five stage GLEE method 97 98 This method has five stages. 99 s = 5, r = 2 100 101 Level: advanced 102 103 .seealso: TSGLEE 104 */ 105 /*MC 106 TSGLEEEXRK2A - Second order six stage GLEE method 107 108 This method has six stages. 109 s = 6, r = 2 110 111 Level: advanced 112 113 .seealso: TSGLEE 114 */ 115 /*MC 116 TSGLEERK32G1 - Third order eight stage GLEE method 117 118 This method has eight stages. 119 s = 8, r = 2 120 121 Level: advanced 122 123 .seealso: TSGLEE 124 */ 125 /*MC 126 TSGLEERK285EX - Second order nine stage GLEE method 127 128 This method has nine stages. 129 s = 9, r = 2 130 131 Level: advanced 132 133 .seealso: TSGLEE 134 */ 135 136 #undef __FUNCT__ 137 #define __FUNCT__ "TSGLEERegisterAll" 138 /*@C 139 TSGLEERegisterAll - Registers all of the General Linear with Error Estimation methods in TSGLEE 140 141 Not Collective, but should be called by all processes which will need the schemes to be registered 142 143 Level: advanced 144 145 .keywords: TS, TSGLEE, register, all 146 147 .seealso: TSGLEERegisterDestroy() 148 @*/ 149 PetscErrorCode TSGLEERegisterAll(void) 150 { 151 PetscErrorCode ierr; 152 153 PetscFunctionBegin; 154 if (TSGLEERegisterAllCalled) PetscFunctionReturn(0); 155 TSGLEERegisterAllCalled = PETSC_TRUE; 156 157 { 158 /* y-eps form */ 159 const PetscInt 160 p = 1, 161 s = 3, 162 r = 2; 163 const PetscReal 164 gamma = 0.5, 165 A[3][3] = {{1.0,0,0},{0,0.5,0},{0,0.5,0.5}}, 166 B[2][3] = {{1.0,0,0},{-2.0,1.0,1.0}}, 167 U[3][2] = {{1.0,0},{1.0,0.5},{1.0,0.5}}, 168 V[2][2] = {{1,0},{0,1}}, 169 S[2] = {1,0}, 170 F[2] = {1,0}, 171 Fembed[2] = {1,1-gamma}, 172 Ferror[2] = {0,1}, 173 Serror[2] = {1,0}; 174 ierr = TSGLEERegister(TSGLEEi1,p,s,r,gamma,&A[0][0],&B[0][0],&U[0][0],&V[0][0],S,F,NULL,Fembed,Ferror,Serror,0,NULL);CHKERRQ(ierr); 175 } 176 { 177 /* y-eps form */ 178 const PetscInt 179 p = 2, 180 s = 3, 181 r = 2; 182 const PetscReal 183 gamma = 0, 184 A[3][3] = {{0,0,0},{1,0,0},{0.25,0.25,0}}, 185 B[2][3] = {{1.0/12.0,1.0/12.0,5.0/6.0},{1.0/12.0,1.0/12.0,-1.0/6.0}}, 186 U[3][2] = {{1,0},{1,10},{1,-1}}, 187 V[2][2] = {{1,0},{0,1}}, 188 S[2] = {1,0}, 189 F[2] = {1,0}, 190 Fembed[2] = {1,1-gamma}, 191 Ferror[2] = {0,1}, 192 Serror[2] = {1,0}; 193 ierr = TSGLEERegister(TSGLEE23,p,s,r,gamma,&A[0][0],&B[0][0],&U[0][0],&V[0][0],S,F,NULL,Fembed,Ferror,Serror,0,NULL);CHKERRQ(ierr); 194 } 195 { 196 /* y-y~ form */ 197 const PetscInt 198 p = 2, 199 s = 4, 200 r = 2; 201 const PetscReal 202 gamma = 0, 203 A[4][4] = {{0,0,0,0},{0.75,0,0,0},{0.25,29.0/60.0,0,0},{-21.0/44.0,145.0/44.0,-20.0/11.0,0}}, 204 B[2][4] = {{109.0/275.0,58.0/75.0,-37.0/110.0,1.0/6.0},{3.0/11.0,0,75.0/88.0,-1.0/8.0}}, 205 U[4][2] = {{0,1},{75.0/58.0,-17.0/58.0},{0,1},{0,1}}, 206 V[2][2] = {{1,0},{0,1}}, 207 S[2] = {1,1}, 208 F[2] = {1,0}, 209 Fembed[2] = {0,1}, 210 Ferror[2] = {-1.0/(1.0-gamma),1.0/(1.0-gamma)}, 211 Serror[2] = {1.0-gamma,1.0}; 212 ierr = TSGLEERegister(TSGLEE24,p,s,r,gamma,&A[0][0],&B[0][0],&U[0][0],&V[0][0],S,F,NULL,Fembed,Ferror,Serror,0,NULL);CHKERRQ(ierr); 213 } 214 { 215 /* y-y~ form */ 216 const PetscInt 217 p = 2, 218 s = 5, 219 r = 2; 220 const PetscReal 221 gamma = 0, 222 A[5][5] = {{0,0,0,0,0}, 223 {-0.94079244066783383269,0,0,0,0}, 224 {0.64228187778301907108,0.10915356933958500042,0,0,0}, 225 {-0.51764297742287450812,0.74414270351096040738,-0.71404164927824538121,0,0}, 226 {-0.44696561556825969206,-0.76768425657590196518,0.20111608138142987881,0.93828186737840469796,0}}, 227 B[2][5] = {{-0.029309178948150356153,-0.49671981884013874923,0.34275801517650053274,0.32941112623949194988,0.85385985637229662276}, 228 {0.78133219686062535272,0.074238691892675897635,0.57957363498384957966,-0.24638502829674959968,-0.18875949544040123033}}, 229 U[5][2] = {{0.16911424754448327735,0.83088575245551672265}, 230 {0.53638465733199574340,0.46361534266800425660}, 231 {0.39901579167169582526,0.60098420832830417474}, 232 {0.87689005530618575480,0.12310994469381424520}, 233 {0.99056100455550913009,0.0094389954444908699092}}, 234 V[2][2] = {{1,0},{0,1}}, 235 S[2] = {1,1}, 236 F[2] = {1,0}, 237 Fembed[2] = {0,1}, 238 Ferror[2] = {-1.0/(1.0-gamma),1.0/(1.0-gamma)}, 239 Serror[2] = {1.0-gamma,1.0}; 240 ierr = TSGLEERegister(TSGLEE25I,p,s,r,gamma,&A[0][0],&B[0][0],&U[0][0],&V[0][0],S,F,NULL,Fembed,Ferror,Serror,0,NULL);CHKERRQ(ierr); 241 } 242 { 243 /* y-y~ form */ 244 const PetscInt 245 p = 3, 246 s = 5, 247 r = 2; 248 const PetscReal 249 gamma = 0, 250 A[5][5] = {{0,0,0,0,0}, 251 {- 2169604947363702313.0 / 24313474998937147335.0,0,0,0,0}, 252 {46526746497697123895.0 / 94116917485856474137.0,-10297879244026594958.0 / 49199457603717988219.0,0,0,0}, 253 {23364788935845982499.0 / 87425311444725389446.0,-79205144337496116638.0 / 148994349441340815519.0,40051189859317443782.0 / 36487615018004984309.0,0,0}, 254 {42089522664062539205.0 / 124911313006412840286.0,-15074384760342762939.0 / 137927286865289746282.0,-62274678522253371016.0 / 125918573676298591413.0,13755475729852471739.0 / 79257927066651693390.0}}, 255 B[2][5] = {{61546696837458703723.0 / 56982519523786160813.0,-55810892792806293355.0 / 206957624151308356511.0,24061048952676379087.0 / 158739347956038723465.0,3577972206874351339.0 / 7599733370677197135.0,-59449832954780563947.0 / 137360038685338563670.0}, 256 {- 9738262186984159168.0 / 99299082461487742983.0,-32797097931948613195.0 / 61521565616362163366.0,42895514606418420631.0 / 71714201188501437336.0,22608567633166065068.0 / 55371917805607957003.0,94655809487476459565.0 / 151517167160302729021.0}}, 257 U[5][2] = {{70820309139834661559.0 / 80863923579509469826.0,10043614439674808267.0 / 80863923579509469826.0}, 258 {161694774978034105510.0 / 106187653640211060371.0,-55507121337823045139.0 / 106187653640211060371.0}, 259 {78486094644566264568.0 / 88171030896733822981.0,9684936252167558413.0 / 88171030896733822981.0}, 260 {65394922146334854435.0 / 84570853840405479554.0,19175931694070625119.0 / 84570853840405479554.0}, 261 {8607282770183754108.0 / 108658046436496925911.0,100050763666313171803.0 / 108658046436496925911.0}}, 262 V[2][2] = {{1,0},{0,1}}, 263 S[2] = {1,1}, 264 F[2] = {1,0}, 265 Fembed[2] = {0,1}, 266 Ferror[2] = {-1.0/(1.0-gamma),1.0/(1.0-gamma)}, 267 Serror[2] = {1.0-gamma,1.0}; 268 ierr = TSGLEERegister(TSGLEE35,p,s,r,gamma,&A[0][0],&B[0][0],&U[0][0],&V[0][0],S,F,NULL,Fembed,Ferror,Serror,0,NULL);CHKERRQ(ierr); 269 } 270 { 271 /* y-eps form */ 272 const PetscInt 273 p = 2, 274 s = 6, 275 r = 2; 276 const PetscReal 277 gamma = 0.25, 278 A[6][6] = {{0,0,0,0,0,0}, 279 {1,0,0,0,0,0}, 280 {0,0,0,0,0,0}, 281 {0,0,0.5,0,0,0}, 282 {0,0,0.25,0.25,0,0}, 283 {0,0,0.25,0.25,0.5,0}}, 284 B[2][6] = {{0.5,0.5,0,0,0,0}, 285 {-2.0/3.0,-2.0/3.0,1.0/3.0,1.0/3.0,1.0/3.0,1.0/3.0}}, 286 U[6][2] = {{1,0},{1,0},{1,0.75},{1,0.75},{1,0.75},{1,0.75}}, 287 V[2][2] = {{1,0},{0,1}}, 288 S[2] = {1,0}, 289 F[2] = {1,0}, 290 Fembed[2] = {1,1-gamma}, 291 Ferror[2] = {0,1}, 292 Serror[2] = {1,0}; 293 ierr = TSGLEERegister(TSGLEEEXRK2A,p,s,r,gamma,&A[0][0],&B[0][0],&U[0][0],&V[0][0],S,F,NULL,Fembed,Ferror,Serror,0,NULL);CHKERRQ(ierr); 294 } 295 { 296 /* y-eps form */ 297 const PetscInt 298 p = 3, 299 s = 8, 300 r = 2; 301 const PetscReal 302 gamma = 0, 303 A[8][8] = {{0,0,0,0,0,0,0,0}, 304 {0.5,0,0,0,0,0,0,0}, 305 {-1,2,0,0,0,0,0,0}, 306 {1.0/6.0,2.0/3.0,1.0/6.0,0,0,0,0,0}, 307 {0,0,0,0,0,0,0,0}, 308 {-7.0/24.0,1.0/3.0,1.0/12.0,-1.0/8.0,0.5,0,0,0}, 309 {7.0/6.0,-4.0/3.0,-1.0/3.0,0.5,-1.0,2.0,0,0}, 310 {0,0,0,0,1.0/6.0,2.0/3.0,1.0/6.0,0}}, 311 B[2][8] = {{1.0/6.0,2.0/3.0,1.0/6.0,0,0,0,0,0}, 312 {-1.0/6.0,-2.0/3.0,-1.0/6.0,0,1.0/6.0,2.0/3.0,1.0/6.0,0}}, 313 U[8][2] = {{1,0},{1,0},{1,0},{1,0},{1,1},{1,1},{1,1},{1,1}}, 314 V[2][2] = {{1,0},{0,1}}, 315 S[2] = {1,0}, 316 F[2] = {1,0}, 317 Fembed[2] = {1,1-gamma}, 318 Ferror[2] = {0,1}, 319 Serror[2] = {1,0}; 320 ierr = TSGLEERegister(TSGLEERK32G1,p,s,r,gamma,&A[0][0],&B[0][0],&U[0][0],&V[0][0],S,F,NULL,Fembed,Ferror,Serror,0,NULL);CHKERRQ(ierr); 321 } 322 { 323 /* y-eps form */ 324 const PetscInt 325 p = 2, 326 s = 9, 327 r = 2; 328 const PetscReal 329 gamma = 0.25, 330 A[9][9] = {{0,0,0,0,0,0,0,0,0}, 331 {0.585786437626904966,0,0,0,0,0,0,0,0}, 332 {0.149999999999999994,0.849999999999999978,0,0,0,0,0,0,0}, 333 {0,0,0,0,0,0,0,0,0}, 334 {0,0,0,0.292893218813452483,0,0,0,0,0}, 335 {0,0,0,0.0749999999999999972,0.424999999999999989,0,0,0,0}, 336 {0,0,0,0.176776695296636893,0.176776695296636893,0.146446609406726241,0,0,0}, 337 {0,0,0,0.176776695296636893,0.176776695296636893,0.146446609406726241,0.292893218813452483,0,0}, 338 {0,0,0,0.176776695296636893,0.176776695296636893,0.146446609406726241,0.0749999999999999972,0.424999999999999989,0}}, 339 B[2][9] = {{0.353553390593273786,0.353553390593273786,0.292893218813452483,0,0,0,0,0,0}, 340 {-0.471404520791031678,-0.471404520791031678,-0.390524291751269959,0.235702260395515839,0.235702260395515839,0.195262145875634979,0.235702260395515839,0.235702260395515839,0.195262145875634979}}, 341 U[9][2] = {{1,0},{1,0},{1,0},{1,0.75},{1,0.75},{1,0.75},{1,0.75},{1,0.75},{1,0.75}}, 342 V[2][2] = {{1,0},{0,1}}, 343 S[2] = {1,0}, 344 F[2] = {1,0}, 345 Fembed[2] = {1,1-gamma}, 346 Ferror[2] = {0,1}, 347 Serror[2] = {1,0}; 348 ierr = TSGLEERegister(TSGLEERK285EX,p,s,r,gamma,&A[0][0],&B[0][0],&U[0][0],&V[0][0],S,F,NULL,Fembed,Ferror,Serror,0,NULL);CHKERRQ(ierr); 349 } 350 351 PetscFunctionReturn(0); 352 } 353 354 #undef __FUNCT__ 355 #define __FUNCT__ "TSGLEERegisterDestroy" 356 /*@C 357 TSGLEERegisterDestroy - Frees the list of schemes that were registered by TSGLEERegister(). 358 359 Not Collective 360 361 Level: advanced 362 363 .keywords: TSGLEE, register, destroy 364 .seealso: TSGLEERegister(), TSGLEERegisterAll() 365 @*/ 366 PetscErrorCode TSGLEERegisterDestroy(void) 367 { 368 PetscErrorCode ierr; 369 GLEETableauLink link; 370 371 PetscFunctionBegin; 372 while ((link = GLEETableauList)) { 373 GLEETableau t = &link->tab; 374 GLEETableauList = link->next; 375 ierr = PetscFree5(t->A,t->B,t->U,t->V,t->c); CHKERRQ(ierr); 376 ierr = PetscFree2(t->S,t->F); CHKERRQ(ierr); 377 ierr = PetscFree (t->Fembed); CHKERRQ(ierr); 378 ierr = PetscFree (t->Ferror); CHKERRQ(ierr); 379 ierr = PetscFree (t->Serror); CHKERRQ(ierr); 380 ierr = PetscFree (t->binterp); CHKERRQ(ierr); 381 ierr = PetscFree (t->name); CHKERRQ(ierr); 382 ierr = PetscFree (link); CHKERRQ(ierr); 383 } 384 TSGLEERegisterAllCalled = PETSC_FALSE; 385 PetscFunctionReturn(0); 386 } 387 388 #undef __FUNCT__ 389 #define __FUNCT__ "TSGLEEInitializePackage" 390 /*@C 391 TSGLEEInitializePackage - This function initializes everything in the TSGLEE package. It is called 392 from PetscDLLibraryRegister() when using dynamic libraries, and on the first call to TSCreate_GLEE() 393 when using static libraries. 394 395 Level: developer 396 397 .keywords: TS, TSGLEE, initialize, package 398 .seealso: PetscInitialize() 399 @*/ 400 PetscErrorCode TSGLEEInitializePackage(void) 401 { 402 PetscErrorCode ierr; 403 404 PetscFunctionBegin; 405 if (TSGLEEPackageInitialized) PetscFunctionReturn(0); 406 TSGLEEPackageInitialized = PETSC_TRUE; 407 ierr = TSGLEERegisterAll();CHKERRQ(ierr); 408 ierr = PetscObjectComposedDataRegister(&explicit_stage_time_id);CHKERRQ(ierr); 409 ierr = PetscRegisterFinalize(TSGLEEFinalizePackage);CHKERRQ(ierr); 410 PetscFunctionReturn(0); 411 } 412 413 #undef __FUNCT__ 414 #define __FUNCT__ "TSGLEEFinalizePackage" 415 /*@C 416 TSGLEEFinalizePackage - This function destroys everything in the TSGLEE package. It is 417 called from PetscFinalize(). 418 419 Level: developer 420 421 .keywords: Petsc, destroy, package 422 .seealso: PetscFinalize() 423 @*/ 424 PetscErrorCode TSGLEEFinalizePackage(void) 425 { 426 PetscErrorCode ierr; 427 428 PetscFunctionBegin; 429 TSGLEEPackageInitialized = PETSC_FALSE; 430 ierr = TSGLEERegisterDestroy();CHKERRQ(ierr); 431 PetscFunctionReturn(0); 432 } 433 434 #undef __FUNCT__ 435 #define __FUNCT__ "TSGLEERegister" 436 /*@C 437 TSGLEERegister - register an GLEE scheme by providing the entries in the Butcher tableau 438 439 Not Collective, but the same schemes should be registered on all processes on which they will be used 440 441 Input Parameters: 442 + name - identifier for method 443 . order - order of method 444 . s - number of stages 445 . r - number of steps 446 . gamma - LTE ratio 447 . A - stage coefficients (dimension s*s, row-major) 448 . B - step completion coefficients (dimension r*s, row-major) 449 . U - method coefficients (dimension s*r, row-major) 450 . V - method coefficients (dimension r*r, row-major) 451 . S - starting coefficients 452 . F - finishing coefficients 453 . c - abscissa (dimension s; NULL to use row sums of A) 454 . Fembed - step completion coefficients for embedded method 455 . Ferror - error computation coefficients 456 . Serror - error initialization coefficients 457 . pinterp - order of interpolation (0 if unavailable) 458 - binterp - array of interpolation coefficients (NULL if unavailable) 459 460 Notes: 461 Several GLEE methods are provided, this function is only needed to create new methods. 462 463 Level: advanced 464 465 .keywords: TS, register 466 467 .seealso: TSGLEE 468 @*/ 469 PetscErrorCode TSGLEERegister(TSGLEEType name,PetscInt order,PetscInt s, PetscInt r, 470 PetscReal gamma, 471 const PetscReal A[],const PetscReal B[], 472 const PetscReal U[],const PetscReal V[], 473 const PetscReal S[],const PetscReal F[], 474 const PetscReal c[], 475 const PetscReal Fembed[],const PetscReal Ferror[], 476 const PetscReal Serror[], 477 PetscInt pinterp, const PetscReal binterp[]) 478 { 479 PetscErrorCode ierr; 480 GLEETableauLink link; 481 GLEETableau t; 482 PetscInt i,j; 483 484 PetscFunctionBegin; 485 ierr = PetscMalloc(sizeof(*link),&link);CHKERRQ(ierr); 486 ierr = PetscMemzero(link,sizeof(*link));CHKERRQ(ierr); 487 t = &link->tab; 488 ierr = PetscStrallocpy(name,&t->name);CHKERRQ(ierr); 489 t->order = order; 490 t->s = s; 491 t->r = r; 492 t->gamma = gamma; 493 ierr = PetscMalloc5(s*s,&t->A,r*r,&t->V,s,&t->c,r*s,&t->B,s*r,&t->U); CHKERRQ(ierr); 494 ierr = PetscMalloc2(r,&t->S,r,&t->F); CHKERRQ(ierr); 495 ierr = PetscMemcpy(t->A,A,s*s*sizeof(A[0]));CHKERRQ(ierr); 496 ierr = PetscMemcpy(t->B,B,r*s*sizeof(B[0]));CHKERRQ(ierr); 497 ierr = PetscMemcpy(t->U,U,s*r*sizeof(U[0]));CHKERRQ(ierr); 498 ierr = PetscMemcpy(t->V,V,r*r*sizeof(V[0]));CHKERRQ(ierr); 499 ierr = PetscMemcpy(t->S,S,r *sizeof(S[0]));CHKERRQ(ierr); 500 ierr = PetscMemcpy(t->F,F,r *sizeof(F[0]));CHKERRQ(ierr); 501 if (c) { 502 ierr = PetscMemcpy(t->c,c,s*sizeof(c[0])); CHKERRQ(ierr); 503 } else { 504 for (i=0; i<s; i++) for (j=0,t->c[i]=0; j<s; j++) t->c[i] += A[i*s+j]; 505 } 506 ierr = PetscMalloc1(r,&t->Fembed);CHKERRQ(ierr); 507 ierr = PetscMalloc1(r,&t->Ferror);CHKERRQ(ierr); 508 ierr = PetscMalloc1(r,&t->Serror);CHKERRQ(ierr); 509 ierr = PetscMemcpy(t->Fembed,Fembed,r*sizeof(Fembed[0]));CHKERRQ(ierr); 510 ierr = PetscMemcpy(t->Ferror,Ferror,r*sizeof(Ferror[0]));CHKERRQ(ierr); 511 ierr = PetscMemcpy(t->Serror,Serror,r*sizeof(Serror[0]));CHKERRQ(ierr); 512 t->pinterp = pinterp; 513 ierr = PetscMalloc1(s*pinterp,&t->binterp);CHKERRQ(ierr); 514 ierr = PetscMemcpy(t->binterp,binterp,s*pinterp*sizeof(binterp[0]));CHKERRQ(ierr); 515 516 link->next = GLEETableauList; 517 GLEETableauList = link; 518 PetscFunctionReturn(0); 519 } 520 521 #undef __FUNCT__ 522 #define __FUNCT__ "TSEvaluateStep_GLEE" 523 static PetscErrorCode TSEvaluateStep_GLEE(TS ts,PetscInt order,Vec X,PetscBool *done) 524 { 525 TS_GLEE *glee = (TS_GLEE*) ts->data; 526 GLEETableau tab = glee->tableau; 527 PetscReal h, *B = tab->B, *V = tab->V, 528 *F = tab->F, 529 *Fembed = tab->Fembed; 530 PetscInt s = tab->s, r = tab->r, i, j; 531 Vec *Y = glee->Y, *YdotStage = glee->YdotStage; 532 PetscScalar *w = glee->work; 533 PetscErrorCode ierr; 534 535 PetscFunctionBegin; 536 537 switch (glee->status) { 538 case TS_STEP_INCOMPLETE: 539 case TS_STEP_PENDING: 540 h = ts->time_step; break; 541 case TS_STEP_COMPLETE: 542 h = ts->ptime - ts->ptime_prev; break; 543 default: SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_PLIB,"Invalid TSStepStatus"); 544 } 545 546 if (order == tab->order) { 547 548 /* Note: Irrespective of whether status is TS_STEP_INCOMPLETE 549 or TS_STEP_COMPLETE, glee->X has the solution at the 550 beginning of the time step. So no need to roll-back. 551 */ 552 if (glee->status == TS_STEP_INCOMPLETE) { 553 for (i=0; i<r; i++) { 554 ierr = VecZeroEntries(Y[i]); CHKERRQ(ierr); 555 ierr = VecMAXPY(Y[i],r,(V+i*r),glee->X); CHKERRQ(ierr); 556 for (j=0; j<s; j++) w[j] = h*B[i*s+j]; 557 ierr = VecMAXPY(Y[i],s,w,YdotStage); CHKERRQ(ierr); 558 } 559 ierr = VecZeroEntries(X);CHKERRQ(ierr); 560 ierr = VecMAXPY(X,r,F,Y);CHKERRQ(ierr); 561 } else {ierr = VecCopy(ts->vec_sol,X);CHKERRQ(ierr);} 562 PetscFunctionReturn(0); 563 564 } else if (order == tab->order-1) { 565 566 /* Complete with the embedded method (Fembed) */ 567 for (i=0; i<r; i++) { 568 ierr = VecZeroEntries(Y[i]); CHKERRQ(ierr); 569 ierr = VecMAXPY(Y[i],r,(V+i*r),glee->X); CHKERRQ(ierr); 570 for (j=0; j<s; j++) w[j] = h*B[i*s+j]; 571 ierr = VecMAXPY(Y[i],s,w,YdotStage); CHKERRQ(ierr); 572 } 573 ierr = VecZeroEntries(X);CHKERRQ(ierr); 574 ierr = VecMAXPY(X,r,Fembed,Y);CHKERRQ(ierr); 575 576 if (done) *done = PETSC_TRUE; 577 PetscFunctionReturn(0); 578 } 579 if (done) *done = PETSC_FALSE; 580 else SETERRQ3(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"GLEE '%s' of order %D cannot evaluate step at order %D",tab->name,tab->order,order); 581 PetscFunctionReturn(0); 582 } 583 584 #undef __FUNCT__ 585 #define __FUNCT__ "TSStep_GLEE" 586 static PetscErrorCode TSStep_GLEE(TS ts) 587 { 588 TS_GLEE *glee = (TS_GLEE*)ts->data; 589 GLEETableau tab = glee->tableau; 590 const PetscInt s = tab->s, r = tab->r; 591 PetscReal *A = tab->A, *U = tab->U, 592 *F = tab->F, 593 *c = tab->c; 594 Vec *Y = glee->Y, *X = glee->X, 595 *YStage = glee->YStage, 596 *YdotStage = glee->YdotStage, 597 W = glee->W; 598 SNES snes; 599 PetscScalar *w = glee->work; 600 TSAdapt adapt; 601 PetscInt i,j,reject,next_scheme,its,lits; 602 PetscReal next_time_step; 603 PetscReal t; 604 PetscBool accept; 605 PetscErrorCode ierr; 606 607 PetscFunctionBegin; 608 ierr = PetscCitationsRegister(citation,&cited);CHKERRQ(ierr); 609 610 for (i=0; i<r; i++) { ierr = VecCopy(Y[i],X[i]); CHKERRQ(ierr); } 611 612 ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr); 613 next_time_step = ts->time_step; 614 t = ts->ptime; 615 accept = PETSC_TRUE; 616 glee->status = TS_STEP_INCOMPLETE; 617 618 for (reject=0; reject<ts->max_reject && !ts->reason; reject++,ts->reject++) { 619 620 PetscReal h = ts->time_step; 621 ierr = TSPreStep(ts);CHKERRQ(ierr); 622 623 for (i=0; i<s; i++) { 624 625 glee->stage_time = t + h*c[i]; 626 ierr = TSPreStage(ts,glee->stage_time); CHKERRQ(ierr); 627 628 if (A[i*s+i] == 0) { /* Explicit stage */ 629 ierr = VecZeroEntries(YStage[i]);CHKERRQ(ierr); 630 ierr = VecMAXPY(YStage[i],r,(U+i*r),X);CHKERRQ(ierr); 631 for (j=0; j<i; j++) w[j] = h*A[i*s+j]; 632 ierr = VecMAXPY(YStage[i],i,w,YdotStage);CHKERRQ(ierr); 633 } else { /* Implicit stage */ 634 glee->scoeff = 1.0/A[i*s+i]; 635 /* compute right-hand-side */ 636 ierr = VecZeroEntries(W);CHKERRQ(ierr); 637 ierr = VecMAXPY(W,r,(U+i*r),X);CHKERRQ(ierr); 638 for (j=0; j<i; j++) w[j] = h*A[i*s+j]; 639 ierr = VecMAXPY(W,i,w,YdotStage);CHKERRQ(ierr); 640 ierr = VecScale(W,glee->scoeff/h);CHKERRQ(ierr); 641 /* set initial guess */ 642 ierr = VecCopy(i>0 ? YStage[i-1] : ts->vec_sol,YStage[i]);CHKERRQ(ierr); 643 /* solve for this stage */ 644 ierr = SNESSolve(snes,W,YStage[i]);CHKERRQ(ierr); 645 ierr = SNESGetIterationNumber(snes,&its);CHKERRQ(ierr); 646 ierr = SNESGetLinearSolveIterations(snes,&lits);CHKERRQ(ierr); 647 ts->snes_its += its; ts->ksp_its += lits; 648 } 649 ierr = TSGetAdapt(ts,&adapt);CHKERRQ(ierr); 650 ierr = TSAdaptCheckStage(adapt,ts,glee->stage_time,Y[i],&accept);CHKERRQ(ierr); 651 if (!accept) goto reject_step; 652 ierr = TSPostStage(ts,glee->stage_time,i,YStage); CHKERRQ(ierr); 653 ierr = TSComputeRHSFunction(ts,t+h*c[i],YStage[i],YdotStage[i]);CHKERRQ(ierr); 654 } 655 ierr = TSEvaluateStep(ts,tab->order,ts->vec_sol,NULL);CHKERRQ(ierr); 656 glee->status = TS_STEP_PENDING; 657 658 /* Register only the current method as a candidate because we're not supporting multiple candidates yet. */ 659 ierr = TSGetAdapt(ts,&adapt);CHKERRQ(ierr); 660 ierr = TSAdaptCandidatesClear(adapt);CHKERRQ(ierr); 661 ierr = TSAdaptCandidateAdd(adapt,tab->name,tab->order,1,tab->ccfl,1.*tab->s,PETSC_TRUE);CHKERRQ(ierr); 662 ierr = TSAdaptChoose(adapt,ts,ts->time_step,&next_scheme,&next_time_step,&accept);CHKERRQ(ierr); 663 if (accept) { 664 /* ignore next_scheme for now */ 665 ts->ptime += ts->time_step; 666 ts->time_step = next_time_step; 667 ts->steps++; 668 glee->status = TS_STEP_COMPLETE; 669 /* compute and store the global error */ 670 /* Note: this is not needed if TSAdaptGLEE is not used */ 671 ierr = TSGetTimeError(ts,0,&(glee->yGErr));CHKERRQ(ierr); 672 ierr = PetscObjectComposedDataSetReal((PetscObject)ts->vec_sol,explicit_stage_time_id,ts->ptime);CHKERRQ(ierr); 673 break; 674 } else { /* Roll back the current step */ 675 ierr = VecMAXPY(ts->vec_sol,r,F,X);CHKERRQ(ierr); 676 ts->time_step = next_time_step; 677 glee->status = TS_STEP_INCOMPLETE; 678 } 679 reject_step: continue; 680 } 681 if (glee->status != TS_STEP_COMPLETE && !ts->reason) ts->reason = TS_DIVERGED_STEP_REJECTED; 682 PetscFunctionReturn(0); 683 } 684 685 #undef __FUNCT__ 686 #define __FUNCT__ "TSInterpolate_GLEE" 687 static PetscErrorCode TSInterpolate_GLEE(TS ts,PetscReal itime,Vec X) 688 { 689 TS_GLEE *glee = (TS_GLEE*)ts->data; 690 PetscInt s=glee->tableau->s, pinterp=glee->tableau->pinterp,i,j; 691 PetscReal h,tt,t; 692 PetscScalar *b; 693 const PetscReal *B = glee->tableau->binterp; 694 PetscErrorCode ierr; 695 696 PetscFunctionBegin; 697 if (!B) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSGLEE %s does not have an interpolation formula",glee->tableau->name); 698 switch (glee->status) { 699 case TS_STEP_INCOMPLETE: 700 case TS_STEP_PENDING: 701 h = ts->time_step; 702 t = (itime - ts->ptime)/h; 703 break; 704 case TS_STEP_COMPLETE: 705 h = ts->ptime - ts->ptime_prev; 706 t = (itime - ts->ptime)/h + 1; /* In the interval [0,1] */ 707 break; 708 default: SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_PLIB,"Invalid TSStepStatus"); 709 } 710 ierr = PetscMalloc1(s,&b);CHKERRQ(ierr); 711 for (i=0; i<s; i++) b[i] = 0; 712 for (j=0,tt=t; j<pinterp; j++,tt*=t) { 713 for (i=0; i<s; i++) { 714 b[i] += h * B[i*pinterp+j] * tt; 715 } 716 } 717 ierr = VecCopy(glee->YStage[0],X);CHKERRQ(ierr); 718 ierr = VecMAXPY(X,s,b,glee->YdotStage);CHKERRQ(ierr); 719 ierr = PetscFree(b);CHKERRQ(ierr); 720 PetscFunctionReturn(0); 721 } 722 723 /*------------------------------------------------------------*/ 724 #undef __FUNCT__ 725 #define __FUNCT__ "TSReset_GLEE" 726 static PetscErrorCode TSReset_GLEE(TS ts) 727 { 728 TS_GLEE *glee = (TS_GLEE*)ts->data; 729 PetscInt s, r; 730 PetscErrorCode ierr; 731 732 PetscFunctionBegin; 733 if (!glee->tableau) PetscFunctionReturn(0); 734 s = glee->tableau->s; 735 r = glee->tableau->r; 736 ierr = VecDestroyVecs(r,&glee->Y);CHKERRQ(ierr); 737 ierr = VecDestroyVecs(r,&glee->X);CHKERRQ(ierr); 738 ierr = VecDestroyVecs(s,&glee->YStage);CHKERRQ(ierr); 739 ierr = VecDestroyVecs(s,&glee->YdotStage);CHKERRQ(ierr); 740 ierr = VecDestroy(&glee->Ydot);CHKERRQ(ierr); 741 ierr = VecDestroy(&glee->yGErr);CHKERRQ(ierr); 742 ierr = VecDestroy(&glee->W);CHKERRQ(ierr); 743 ierr = PetscFree(glee->work);CHKERRQ(ierr); 744 PetscFunctionReturn(0); 745 } 746 747 #undef __FUNCT__ 748 #define __FUNCT__ "TSDestroy_GLEE" 749 static PetscErrorCode TSDestroy_GLEE(TS ts) 750 { 751 PetscErrorCode ierr; 752 753 PetscFunctionBegin; 754 ierr = TSReset_GLEE(ts);CHKERRQ(ierr); 755 ierr = PetscFree(ts->data);CHKERRQ(ierr); 756 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSGLEEGetType_C",NULL);CHKERRQ(ierr); 757 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSGLEESetType_C",NULL);CHKERRQ(ierr); 758 PetscFunctionReturn(0); 759 } 760 761 #undef __FUNCT__ 762 #define __FUNCT__ "TSGLEEGetVecs" 763 static PetscErrorCode TSGLEEGetVecs(TS ts,DM dm,Vec *Ydot) 764 { 765 TS_GLEE *glee = (TS_GLEE*)ts->data; 766 PetscErrorCode ierr; 767 768 PetscFunctionBegin; 769 if (Ydot) { 770 if (dm && dm != ts->dm) { 771 ierr = DMGetNamedGlobalVector(dm,"TSGLEE_Ydot",Ydot);CHKERRQ(ierr); 772 } else *Ydot = glee->Ydot; 773 } 774 PetscFunctionReturn(0); 775 } 776 777 778 #undef __FUNCT__ 779 #define __FUNCT__ "TSGLEERestoreVecs" 780 static PetscErrorCode TSGLEERestoreVecs(TS ts,DM dm,Vec *Ydot) 781 { 782 PetscErrorCode ierr; 783 784 PetscFunctionBegin; 785 if (Ydot) { 786 if (dm && dm != ts->dm) { 787 ierr = DMRestoreNamedGlobalVector(dm,"TSGLEE_Ydot",Ydot);CHKERRQ(ierr); 788 } 789 } 790 PetscFunctionReturn(0); 791 } 792 793 /* 794 This defines the nonlinear equation that is to be solved with SNES 795 */ 796 #undef __FUNCT__ 797 #define __FUNCT__ "SNESTSFormFunction_GLEE" 798 static PetscErrorCode SNESTSFormFunction_GLEE(SNES snes,Vec X,Vec F,TS ts) 799 { 800 TS_GLEE *glee = (TS_GLEE*)ts->data; 801 DM dm,dmsave; 802 Vec Ydot; 803 PetscReal shift = glee->scoeff / ts->time_step; 804 PetscErrorCode ierr; 805 806 PetscFunctionBegin; 807 ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 808 ierr = TSGLEEGetVecs(ts,dm,&Ydot);CHKERRQ(ierr); 809 /* Set Ydot = shift*X */ 810 ierr = VecCopy(X,Ydot);CHKERRQ(ierr); 811 ierr = VecScale(Ydot,shift);CHKERRQ(ierr); 812 dmsave = ts->dm; 813 ts->dm = dm; 814 815 ierr = TSComputeIFunction(ts,glee->stage_time,X,Ydot,F,PETSC_FALSE);CHKERRQ(ierr); 816 817 ts->dm = dmsave; 818 ierr = TSGLEERestoreVecs(ts,dm,&Ydot);CHKERRQ(ierr); 819 PetscFunctionReturn(0); 820 } 821 822 #undef __FUNCT__ 823 #define __FUNCT__ "SNESTSFormJacobian_GLEE" 824 static PetscErrorCode SNESTSFormJacobian_GLEE(SNES snes,Vec X,Mat A,Mat B,TS ts) 825 { 826 TS_GLEE *glee = (TS_GLEE*)ts->data; 827 DM dm,dmsave; 828 Vec Ydot; 829 PetscReal shift = glee->scoeff / ts->time_step; 830 PetscErrorCode ierr; 831 832 PetscFunctionBegin; 833 ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 834 ierr = TSGLEEGetVecs(ts,dm,&Ydot);CHKERRQ(ierr); 835 /* glee->Ydot has already been computed in SNESTSFormFunction_GLEE (SNES guarantees this) */ 836 dmsave = ts->dm; 837 ts->dm = dm; 838 839 ierr = TSComputeIJacobian(ts,glee->stage_time,X,Ydot,shift,A,B,PETSC_FALSE);CHKERRQ(ierr); 840 841 ts->dm = dmsave; 842 ierr = TSGLEERestoreVecs(ts,dm,&Ydot);CHKERRQ(ierr); 843 PetscFunctionReturn(0); 844 } 845 846 #undef __FUNCT__ 847 #define __FUNCT__ "DMCoarsenHook_TSGLEE" 848 static PetscErrorCode DMCoarsenHook_TSGLEE(DM fine,DM coarse,void *ctx) 849 { 850 PetscFunctionBegin; 851 PetscFunctionReturn(0); 852 } 853 854 #undef __FUNCT__ 855 #define __FUNCT__ "DMRestrictHook_TSGLEE" 856 static PetscErrorCode DMRestrictHook_TSGLEE(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse,void *ctx) 857 { 858 PetscFunctionBegin; 859 PetscFunctionReturn(0); 860 } 861 862 863 #undef __FUNCT__ 864 #define __FUNCT__ "DMSubDomainHook_TSGLEE" 865 static PetscErrorCode DMSubDomainHook_TSGLEE(DM dm,DM subdm,void *ctx) 866 { 867 PetscFunctionBegin; 868 PetscFunctionReturn(0); 869 } 870 871 #undef __FUNCT__ 872 #define __FUNCT__ "DMSubDomainRestrictHook_TSGLEE" 873 static PetscErrorCode DMSubDomainRestrictHook_TSGLEE(DM dm,VecScatter gscat,VecScatter lscat,DM subdm,void *ctx) 874 { 875 PetscFunctionBegin; 876 PetscFunctionReturn(0); 877 } 878 879 #undef __FUNCT__ 880 #define __FUNCT__ "TSSetUp_GLEE" 881 static PetscErrorCode TSSetUp_GLEE(TS ts) 882 { 883 TS_GLEE *glee = (TS_GLEE*)ts->data; 884 GLEETableau tab; 885 PetscInt s,r; 886 PetscErrorCode ierr; 887 DM dm; 888 889 PetscFunctionBegin; 890 if (!glee->tableau) { 891 ierr = TSGLEESetType(ts,TSGLEEDefaultType);CHKERRQ(ierr); 892 } 893 tab = glee->tableau; 894 s = tab->s; 895 r = tab->r; 896 ierr = VecDuplicateVecs(ts->vec_sol,r,&glee->Y);CHKERRQ(ierr); 897 ierr = VecDuplicateVecs(ts->vec_sol,r,&glee->X);CHKERRQ(ierr); 898 ierr = VecDuplicateVecs(ts->vec_sol,s,&glee->YStage);CHKERRQ(ierr); 899 ierr = VecDuplicateVecs(ts->vec_sol,s,&glee->YdotStage);CHKERRQ(ierr); 900 ierr = VecDuplicate(ts->vec_sol,&glee->Ydot);CHKERRQ(ierr); 901 ierr = VecDuplicate(ts->vec_sol,&glee->yGErr);CHKERRQ(ierr); 902 ierr = VecDuplicate(ts->vec_sol,&glee->W);CHKERRQ(ierr); 903 ierr = PetscMalloc1(s,&glee->work);CHKERRQ(ierr); 904 ierr = TSGetDM(ts,&dm);CHKERRQ(ierr); 905 if (dm) { 906 ierr = DMCoarsenHookAdd(dm,DMCoarsenHook_TSGLEE,DMRestrictHook_TSGLEE,ts);CHKERRQ(ierr); 907 ierr = DMSubDomainHookAdd(dm,DMSubDomainHook_TSGLEE,DMSubDomainRestrictHook_TSGLEE,ts);CHKERRQ(ierr); 908 } 909 PetscFunctionReturn(0); 910 } 911 912 #undef __FUNCT__ 913 #define __FUNCT__ "TSStartingMethod_GLEE" 914 PetscErrorCode TSStartingMethod_GLEE(TS ts) 915 { 916 TS_GLEE *glee = (TS_GLEE*)ts->data; 917 GLEETableau tab = glee->tableau; 918 PetscInt r=tab->r,i; 919 PetscReal *S=tab->S; 920 PetscErrorCode ierr; 921 922 PetscFunctionBegin; 923 for (i=0; i<r; i++) { 924 ierr = VecZeroEntries(glee->Y[i]);CHKERRQ(ierr); 925 ierr = VecAXPY(glee->Y[i],S[i],ts->vec_sol);CHKERRQ(ierr); 926 } 927 928 PetscFunctionReturn(0); 929 } 930 931 932 /*------------------------------------------------------------*/ 933 934 #undef __FUNCT__ 935 #define __FUNCT__ "TSSetFromOptions_GLEE" 936 static PetscErrorCode TSSetFromOptions_GLEE(PetscOptionItems *PetscOptionsObject,TS ts) 937 { 938 PetscErrorCode ierr; 939 char gleetype[256]; 940 941 PetscFunctionBegin; 942 ierr = PetscOptionsHead(PetscOptionsObject,"GLEE ODE solver options");CHKERRQ(ierr); 943 { 944 GLEETableauLink link; 945 PetscInt count,choice; 946 PetscBool flg; 947 const char **namelist; 948 949 ierr = PetscStrncpy(gleetype,TSGLEEDefaultType,sizeof(gleetype));CHKERRQ(ierr); 950 for (link=GLEETableauList,count=0; link; link=link->next,count++) ; 951 ierr = PetscMalloc1(count,&namelist);CHKERRQ(ierr); 952 for (link=GLEETableauList,count=0; link; link=link->next,count++) namelist[count] = link->tab.name; 953 ierr = PetscOptionsEList("-ts_glee_type","Family of GLEE method","TSGLEESetType",(const char*const*)namelist,count,gleetype,&choice,&flg);CHKERRQ(ierr); 954 ierr = TSGLEESetType(ts,flg ? namelist[choice] : gleetype);CHKERRQ(ierr); 955 ierr = PetscFree(namelist);CHKERRQ(ierr); 956 } 957 ierr = PetscOptionsTail();CHKERRQ(ierr); 958 PetscFunctionReturn(0); 959 } 960 961 #undef __FUNCT__ 962 #define __FUNCT__ "PetscFormatRealArray" 963 static PetscErrorCode PetscFormatRealArray(char buf[],size_t len,const char *fmt,PetscInt n,const PetscReal x[]) 964 { 965 PetscErrorCode ierr; 966 PetscInt i; 967 size_t left,count; 968 char *p; 969 970 PetscFunctionBegin; 971 for (i=0,p=buf,left=len; i<n; i++) { 972 ierr = PetscSNPrintfCount(p,left,fmt,&count,x[i]);CHKERRQ(ierr); 973 if (count >= left) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Insufficient space in buffer"); 974 left -= count; 975 p += count; 976 *p++ = ' '; 977 } 978 p[i ? 0 : -1] = 0; 979 PetscFunctionReturn(0); 980 } 981 982 #undef __FUNCT__ 983 #define __FUNCT__ "TSView_GLEE" 984 static PetscErrorCode TSView_GLEE(TS ts,PetscViewer viewer) 985 { 986 TS_GLEE *glee = (TS_GLEE*)ts->data; 987 GLEETableau tab = glee->tableau; 988 PetscBool iascii; 989 PetscErrorCode ierr; 990 TSAdapt adapt; 991 992 PetscFunctionBegin; 993 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 994 if (iascii) { 995 TSGLEEType gleetype; 996 char buf[512]; 997 ierr = TSGLEEGetType(ts,&gleetype);CHKERRQ(ierr); 998 ierr = PetscViewerASCIIPrintf(viewer," GLEE %s\n",gleetype);CHKERRQ(ierr); 999 ierr = PetscFormatRealArray(buf,sizeof(buf),"% 8.6f",tab->s,tab->c);CHKERRQ(ierr); 1000 ierr = PetscViewerASCIIPrintf(viewer," Abscissa c = %s\n",buf);CHKERRQ(ierr); 1001 /* Note: print out r as well */ 1002 } 1003 ierr = TSGetAdapt(ts,&adapt);CHKERRQ(ierr); 1004 ierr = TSAdaptView(adapt,viewer);CHKERRQ(ierr); 1005 PetscFunctionReturn(0); 1006 } 1007 1008 #undef __FUNCT__ 1009 #define __FUNCT__ "TSLoad_GLEE" 1010 static PetscErrorCode TSLoad_GLEE(TS ts,PetscViewer viewer) 1011 { 1012 PetscErrorCode ierr; 1013 SNES snes; 1014 TSAdapt tsadapt; 1015 1016 PetscFunctionBegin; 1017 ierr = TSGetAdapt(ts,&tsadapt);CHKERRQ(ierr); 1018 ierr = TSAdaptLoad(tsadapt,viewer);CHKERRQ(ierr); 1019 ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr); 1020 ierr = SNESLoad(snes,viewer);CHKERRQ(ierr); 1021 /* function and Jacobian context for SNES when used with TS is always ts object */ 1022 ierr = SNESSetFunction(snes,NULL,NULL,ts);CHKERRQ(ierr); 1023 ierr = SNESSetJacobian(snes,NULL,NULL,NULL,ts);CHKERRQ(ierr); 1024 PetscFunctionReturn(0); 1025 } 1026 1027 #undef __FUNCT__ 1028 #define __FUNCT__ "TSGLEESetType" 1029 /*@C 1030 TSGLEESetType - Set the type of GLEE scheme 1031 1032 Logically collective 1033 1034 Input Parameter: 1035 + ts - timestepping context 1036 - gleetype - type of GLEE-scheme 1037 1038 Level: intermediate 1039 1040 .seealso: TSGLEEGetType(), TSGLEE 1041 @*/ 1042 PetscErrorCode TSGLEESetType(TS ts,TSGLEEType gleetype) 1043 { 1044 PetscErrorCode ierr; 1045 1046 PetscFunctionBegin; 1047 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1048 ierr = PetscTryMethod(ts,"TSGLEESetType_C",(TS,TSGLEEType),(ts,gleetype));CHKERRQ(ierr); 1049 PetscFunctionReturn(0); 1050 } 1051 1052 #undef __FUNCT__ 1053 #define __FUNCT__ "TSGLEEGetType" 1054 /*@C 1055 TSGLEEGetType - Get the type of GLEE scheme 1056 1057 Logically collective 1058 1059 Input Parameter: 1060 . ts - timestepping context 1061 1062 Output Parameter: 1063 . gleetype - type of GLEE-scheme 1064 1065 Level: intermediate 1066 1067 .seealso: TSGLEESetType() 1068 @*/ 1069 PetscErrorCode TSGLEEGetType(TS ts,TSGLEEType *gleetype) 1070 { 1071 PetscErrorCode ierr; 1072 1073 PetscFunctionBegin; 1074 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1075 ierr = PetscUseMethod(ts,"TSGLEEGetType_C",(TS,TSGLEEType*),(ts,gleetype));CHKERRQ(ierr); 1076 PetscFunctionReturn(0); 1077 } 1078 1079 #undef __FUNCT__ 1080 #define __FUNCT__ "TSGLEEGetType_GLEE" 1081 PetscErrorCode TSGLEEGetType_GLEE(TS ts,TSGLEEType *gleetype) 1082 { 1083 TS_GLEE *glee = (TS_GLEE*)ts->data; 1084 PetscErrorCode ierr; 1085 1086 PetscFunctionBegin; 1087 if (!glee->tableau) { 1088 ierr = TSGLEESetType(ts,TSGLEEDefaultType);CHKERRQ(ierr); 1089 } 1090 *gleetype = glee->tableau->name; 1091 PetscFunctionReturn(0); 1092 } 1093 #undef __FUNCT__ 1094 #define __FUNCT__ "TSGLEESetType_GLEE" 1095 PetscErrorCode TSGLEESetType_GLEE(TS ts,TSGLEEType gleetype) 1096 { 1097 TS_GLEE *glee = (TS_GLEE*)ts->data; 1098 PetscErrorCode ierr; 1099 PetscBool match; 1100 GLEETableauLink link; 1101 1102 PetscFunctionBegin; 1103 if (glee->tableau) { 1104 ierr = PetscStrcmp(glee->tableau->name,gleetype,&match);CHKERRQ(ierr); 1105 if (match) PetscFunctionReturn(0); 1106 } 1107 for (link = GLEETableauList; link; link=link->next) { 1108 ierr = PetscStrcmp(link->tab.name,gleetype,&match);CHKERRQ(ierr); 1109 if (match) { 1110 ierr = TSReset_GLEE(ts);CHKERRQ(ierr); 1111 glee->tableau = &link->tab; 1112 PetscFunctionReturn(0); 1113 } 1114 } 1115 SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_UNKNOWN_TYPE,"Could not find '%s'",gleetype); 1116 PetscFunctionReturn(0); 1117 } 1118 1119 #undef __FUNCT__ 1120 #define __FUNCT__ "TSGetStages_GLEE" 1121 static PetscErrorCode TSGetStages_GLEE(TS ts,PetscInt *ns,Vec **Y) 1122 { 1123 TS_GLEE *glee = (TS_GLEE*)ts->data; 1124 1125 PetscFunctionBegin; 1126 *ns = glee->tableau->s; 1127 if(Y) *Y = glee->Y; 1128 PetscFunctionReturn(0); 1129 } 1130 1131 #undef __FUNCT__ 1132 #define __FUNCT__ "TSGetSolutionComponents_GLEE" 1133 PetscErrorCode TSGetSolutionComponents_GLEE(TS ts,PetscInt *n,Vec *Y) 1134 { 1135 TS_GLEE *glee = (TS_GLEE*)ts->data; 1136 GLEETableau tab = glee->tableau; 1137 PetscErrorCode ierr; 1138 1139 PetscFunctionBegin; 1140 if (!Y) *n = tab->r; 1141 else { 1142 if ((*n >= 0) && (*n < tab->r)) { 1143 ierr = VecCopy(glee->Y[*n],*Y); CHKERRQ(ierr); 1144 } else SETERRQ3(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Second argument (%d) out of range[%d,%d].",*n,0,tab->r-1); 1145 } 1146 PetscFunctionReturn(0); 1147 } 1148 1149 #undef __FUNCT__ 1150 #define __FUNCT__ "TSGetAuxSolution_GLEE" 1151 PetscErrorCode TSGetAuxSolution_GLEE(TS ts,Vec *X) 1152 { 1153 TS_GLEE *glee = (TS_GLEE*)ts->data; 1154 GLEETableau tab = glee->tableau; 1155 PetscReal *F = tab->Fembed; 1156 PetscInt r = tab->r; 1157 Vec *Y = glee->Y; 1158 PetscErrorCode ierr; 1159 1160 PetscFunctionBegin; 1161 ierr = VecZeroEntries(*X);CHKERRQ(ierr); 1162 ierr = VecMAXPY((*X),r,F,Y);CHKERRQ(ierr); 1163 PetscFunctionReturn(0); 1164 } 1165 1166 #undef __FUNCT__ 1167 #define __FUNCT__ "TSGetTimeError_GLEE" 1168 PetscErrorCode TSGetTimeError_GLEE(TS ts,PetscInt n,Vec *X) 1169 { 1170 TS_GLEE *glee = (TS_GLEE*)ts->data; 1171 GLEETableau tab = glee->tableau; 1172 PetscReal *F = tab->Ferror; 1173 PetscInt r = tab->r; 1174 Vec *Y = glee->Y; 1175 PetscErrorCode ierr; 1176 1177 PetscFunctionBegin; 1178 if(n==0){ 1179 ierr = VecZeroEntries(*X);CHKERRQ(ierr); 1180 ierr = VecMAXPY((*X),r,F,Y);CHKERRQ(ierr); 1181 } else if(n==-1) { 1182 ierr = VecCopy(glee->yGErr,*X);CHKERRQ(ierr); 1183 } 1184 PetscFunctionReturn(0); 1185 } 1186 1187 #undef __FUNCT__ 1188 #define __FUNCT__ "TSSetTimeError_GLEE" 1189 PetscErrorCode TSSetTimeError_GLEE(TS ts,Vec X) 1190 { 1191 TS_GLEE *glee = (TS_GLEE*)ts->data; 1192 GLEETableau tab = glee->tableau; 1193 PetscReal *S = tab->Serror; 1194 PetscInt r = tab->r,i; 1195 Vec *Y = glee->Y; 1196 PetscErrorCode ierr; 1197 1198 PetscFunctionBegin; 1199 if (r != 2) SETERRQ2(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSSetTimeError_GLEE not supported for '%s' with r=%D.",tab->name,tab->r); 1200 for (i=1; i<r; i++) { 1201 ierr = VecCopy(ts->vec_sol,Y[i]); CHKERRQ(ierr); 1202 ierr = VecCopy(X,glee->yGErr); CHKERRQ(ierr); 1203 ierr = VecAXPBY(Y[i],S[0],S[1],X); CHKERRQ(ierr); 1204 } 1205 PetscFunctionReturn(0); 1206 } 1207 1208 /* ------------------------------------------------------------ */ 1209 /*MC 1210 TSGLEE - ODE and DAE solver using General Linear with Error Estimation schemes 1211 1212 The user should provide the right hand side of the equation 1213 using TSSetRHSFunction(). 1214 1215 Notes: 1216 The default is TSGLEE35, it can be changed with TSGLEESetType() or -ts_glee_type 1217 1218 Level: beginner 1219 1220 .seealso: TSCreate(), TS, TSSetType(), TSGLEESetType(), TSGLEEGetType(), 1221 TSGLEE23, TTSGLEE24, TSGLEE35, TSGLEE25I, TSGLEEEXRK2A, 1222 TSGLEERK32G1, TSGLEERK285EX, TSGLEEType, TSGLEERegister() 1223 1224 M*/ 1225 #undef __FUNCT__ 1226 #define __FUNCT__ "TSCreate_GLEE" 1227 PETSC_EXTERN PetscErrorCode TSCreate_GLEE(TS ts) 1228 { 1229 TS_GLEE *th; 1230 PetscErrorCode ierr; 1231 1232 PetscFunctionBegin; 1233 #if !defined(PETSC_USE_DYNAMIC_LIBRARIES) 1234 ierr = TSGLEEInitializePackage();CHKERRQ(ierr); 1235 #endif 1236 1237 ts->ops->reset = TSReset_GLEE; 1238 ts->ops->destroy = TSDestroy_GLEE; 1239 ts->ops->view = TSView_GLEE; 1240 ts->ops->load = TSLoad_GLEE; 1241 ts->ops->setup = TSSetUp_GLEE; 1242 ts->ops->step = TSStep_GLEE; 1243 ts->ops->interpolate = TSInterpolate_GLEE; 1244 ts->ops->evaluatestep = TSEvaluateStep_GLEE; 1245 ts->ops->setfromoptions = TSSetFromOptions_GLEE; 1246 ts->ops->getstages = TSGetStages_GLEE; 1247 ts->ops->snesfunction = SNESTSFormFunction_GLEE; 1248 ts->ops->snesjacobian = SNESTSFormJacobian_GLEE; 1249 ts->ops->getsolutioncomponents = TSGetSolutionComponents_GLEE; 1250 ts->ops->getauxsolution = TSGetAuxSolution_GLEE; 1251 ts->ops->gettimeerror = TSGetTimeError_GLEE; 1252 ts->ops->settimeerror = TSSetTimeError_GLEE; 1253 ts->ops->startingmethod = TSStartingMethod_GLEE; 1254 1255 ierr = PetscNewLog(ts,&th);CHKERRQ(ierr); 1256 ts->data = (void*)th; 1257 1258 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSGLEEGetType_C",TSGLEEGetType_GLEE);CHKERRQ(ierr); 1259 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSGLEESetType_C",TSGLEESetType_GLEE);CHKERRQ(ierr); 1260 PetscFunctionReturn(0); 1261 } 1262