1 /* 2 Code for time stepping with the Runge-Kutta method 3 4 Notes: 5 The general system is written as 6 7 Udot = F(t,U) 8 9 */ 10 11 #include <petsc/private/tsimpl.h> /*I "petscts.h" I*/ 12 #include <petscdm.h> 13 #include <../src/ts/impls/explicit/rk/rk.h> 14 #include <../src/ts/impls/explicit/rk/mrk.h> 15 16 static TSRKType TSRKDefault = TSRK3BS; 17 static PetscBool TSRKRegisterAllCalled; 18 static PetscBool TSRKPackageInitialized; 19 20 static RKTableauLink RKTableauList; 21 22 /*MC 23 TSRK1FE - First order forward Euler scheme. 24 25 This method has one stage. 26 27 Options database: 28 . -ts_rk_type 1fe 29 30 Level: advanced 31 32 .seealso: TSRK, TSRKType, TSRKSetType() 33 M*/ 34 /*MC 35 TSRK2A - Second order RK scheme. 36 37 This method has two stages. 38 39 Options database: 40 . -ts_rk_type 2a 41 42 Level: advanced 43 44 .seealso: TSRK, TSRKType, TSRKSetType() 45 M*/ 46 /*MC 47 TSRK3 - Third order RK scheme. 48 49 This method has three stages. 50 51 Options database: 52 . -ts_rk_type 3 53 54 Level: advanced 55 56 .seealso: TSRK, TSRKType, TSRKSetType() 57 M*/ 58 /*MC 59 TSRK3BS - Third order RK scheme of Bogacki-Shampine with 2nd order embedded method. 60 61 This method has four stages with the First Same As Last (FSAL) property. 62 63 Options database: 64 . -ts_rk_type 3bs 65 66 Level: advanced 67 68 References: https://doi.org/10.1016/0893-9659(89)90079-7 69 70 .seealso: TSRK, TSRKType, TSRKSetType() 71 M*/ 72 /*MC 73 TSRK4 - Fourth order RK scheme. 74 75 This is the classical Runge-Kutta method with four stages. 76 77 Options database: 78 . -ts_rk_type 4 79 80 Level: advanced 81 82 .seealso: TSRK, TSRKType, TSRKSetType() 83 M*/ 84 /*MC 85 TSRK5F - Fifth order Fehlberg RK scheme with a 4th order embedded method. 86 87 This method has six stages. 88 89 Options database: 90 . -ts_rk_type 5f 91 92 Level: advanced 93 94 .seealso: TSRK, TSRKType, TSRKSetType() 95 M*/ 96 /*MC 97 TSRK5DP - Fifth order Dormand-Prince RK scheme with the 4th order embedded method. 98 99 This method has seven stages with the First Same As Last (FSAL) property. 100 101 Options database: 102 . -ts_rk_type 5dp 103 104 Level: advanced 105 106 References: https://doi.org/10.1016/0771-050X(80)90013-3 107 108 .seealso: TSRK, TSRKType, TSRKSetType() 109 M*/ 110 /*MC 111 TSRK5BS - Fifth order Bogacki-Shampine RK scheme with 4th order embedded method. 112 113 This method has eight stages with the First Same As Last (FSAL) property. 114 115 Options database: 116 . -ts_rk_type 5bs 117 118 Level: advanced 119 120 References: https://doi.org/10.1016/0898-1221(96)00141-1 121 122 .seealso: TSRK, TSRKType, TSRKSetType() 123 M*/ 124 125 /*@C 126 TSRKRegisterAll - Registers all of the Runge-Kutta explicit methods in TSRK 127 128 Not Collective, but should be called by all processes which will need the schemes to be registered 129 130 Level: advanced 131 132 .keywords: TS, TSRK, register, all 133 134 .seealso: TSRKRegisterDestroy() 135 @*/ 136 PetscErrorCode TSRKRegisterAll(void) 137 { 138 PetscErrorCode ierr; 139 140 PetscFunctionBegin; 141 if (TSRKRegisterAllCalled) PetscFunctionReturn(0); 142 TSRKRegisterAllCalled = PETSC_TRUE; 143 144 #define RC PetscRealConstant 145 { 146 const PetscReal 147 A[1][1] = {{0}}, 148 b[1] = {RC(1.0)}; 149 ierr = TSRKRegister(TSRK1FE,1,1,&A[0][0],b,NULL,NULL,0,NULL);CHKERRQ(ierr); 150 } 151 { 152 const PetscReal 153 A[2][2] = {{0,0}, 154 {RC(1.0),0}}, 155 b[2] = {RC(0.5),RC(0.5)}, 156 bembed[2] = {RC(1.0),0}; 157 ierr = TSRKRegister(TSRK2A,2,2,&A[0][0],b,NULL,bembed,0,NULL);CHKERRQ(ierr); 158 } 159 { 160 const PetscReal 161 A[3][3] = {{0,0,0}, 162 {RC(2.0)/RC(3.0),0,0}, 163 {RC(-1.0)/RC(3.0),RC(1.0),0}}, 164 b[3] = {RC(0.25),RC(0.5),RC(0.25)}; 165 ierr = TSRKRegister(TSRK3,3,3,&A[0][0],b,NULL,NULL,0,NULL);CHKERRQ(ierr); 166 } 167 { 168 const PetscReal 169 A[4][4] = {{0,0,0,0}, 170 {RC(1.0)/RC(2.0),0,0,0}, 171 {0,RC(3.0)/RC(4.0),0,0}, 172 {RC(2.0)/RC(9.0),RC(1.0)/RC(3.0),RC(4.0)/RC(9.0),0}}, 173 b[4] = {RC(2.0)/RC(9.0),RC(1.0)/RC(3.0),RC(4.0)/RC(9.0),0}, 174 bembed[4] = {RC(7.0)/RC(24.0),RC(1.0)/RC(4.0),RC(1.0)/RC(3.0),RC(1.0)/RC(8.0)}; 175 ierr = TSRKRegister(TSRK3BS,3,4,&A[0][0],b,NULL,bembed,0,NULL);CHKERRQ(ierr); 176 } 177 { 178 const PetscReal 179 A[4][4] = {{0,0,0,0}, 180 {RC(0.5),0,0,0}, 181 {0,RC(0.5),0,0}, 182 {0,0,RC(1.0),0}}, 183 b[4] = {RC(1.0)/RC(6.0),RC(1.0)/RC(3.0),RC(1.0)/RC(3.0),RC(1.0)/RC(6.0)}; 184 ierr = TSRKRegister(TSRK4,4,4,&A[0][0],b,NULL,NULL,0,NULL);CHKERRQ(ierr); 185 } 186 { 187 const PetscReal 188 A[6][6] = {{0,0,0,0,0,0}, 189 {RC(0.25),0,0,0,0,0}, 190 {RC(3.0)/RC(32.0),RC(9.0)/RC(32.0),0,0,0,0}, 191 {RC(1932.0)/RC(2197.0),RC(-7200.0)/RC(2197.0),RC(7296.0)/RC(2197.0),0,0,0}, 192 {RC(439.0)/RC(216.0),RC(-8.0),RC(3680.0)/RC(513.0),RC(-845.0)/RC(4104.0),0,0}, 193 {RC(-8.0)/RC(27.0),RC(2.0),RC(-3544.0)/RC(2565.0),RC(1859.0)/RC(4104.0),RC(-11.0)/RC(40.0),0}}, 194 b[6] = {RC(16.0)/RC(135.0),0,RC(6656.0)/RC(12825.0),RC(28561.0)/RC(56430.0),RC(-9.0)/RC(50.0),RC(2.0)/RC(55.0)}, 195 bembed[6] = {RC(25.0)/RC(216.0),0,RC(1408.0)/RC(2565.0),RC(2197.0)/RC(4104.0),RC(-1.0)/RC(5.0),0}; 196 ierr = TSRKRegister(TSRK5F,5,6,&A[0][0],b,NULL,bembed,0,NULL);CHKERRQ(ierr); 197 } 198 { 199 const PetscReal 200 A[7][7] = {{0,0,0,0,0,0,0}, 201 {RC(1.0)/RC(5.0),0,0,0,0,0,0}, 202 {RC(3.0)/RC(40.0),RC(9.0)/RC(40.0),0,0,0,0,0}, 203 {RC(44.0)/RC(45.0),RC(-56.0)/RC(15.0),RC(32.0)/RC(9.0),0,0,0,0}, 204 {RC(19372.0)/RC(6561.0),RC(-25360.0)/RC(2187.0),RC(64448.0)/RC(6561.0),RC(-212.0)/RC(729.0),0,0,0}, 205 {RC(9017.0)/RC(3168.0),RC(-355.0)/RC(33.0),RC(46732.0)/RC(5247.0),RC(49.0)/RC(176.0),RC(-5103.0)/RC(18656.0),0,0}, 206 {RC(35.0)/RC(384.0),0,RC(500.0)/RC(1113.0),RC(125.0)/RC(192.0),RC(-2187.0)/RC(6784.0),RC(11.0)/RC(84.0),0}}, 207 b[7] = {RC(35.0)/RC(384.0),0,RC(500.0)/RC(1113.0),RC(125.0)/RC(192.0),RC(-2187.0)/RC(6784.0),RC(11.0)/RC(84.0),0}, 208 bembed[7] = {RC(5179.0)/RC(57600.0),0,RC(7571.0)/RC(16695.0),RC(393.0)/RC(640.0),RC(-92097.0)/RC(339200.0),RC(187.0)/RC(2100.0),RC(1.0)/RC(40.0)}, 209 binterp[7][5] = {{RC(1.0),RC(-4034104133.0)/RC(1410260304.0),RC(105330401.0)/RC(33982176.0),RC(-13107642775.0)/RC(11282082432.0),RC(6542295.0)/RC(470086768.0)}, 210 {0,0,0,0,0}, 211 {0,RC(132343189600.0)/RC(32700410799.0),RC(-833316000.0)/RC(131326951.0),RC(91412856700.0)/RC(32700410799.0),RC(-523383600.0)/RC(10900136933.0)}, 212 {0,RC(-115792950.0)/RC(29380423.0),RC(185270875.0)/RC(16991088.0),RC(-12653452475.0)/RC(1880347072.0),RC(98134425.0)/RC(235043384.0)}, 213 {0,RC(70805911779.0)/RC(24914598704.0),RC(-4531260609.0)/RC(600351776.0),RC(988140236175.0)/RC(199316789632.0),RC(-14307999165.0)/RC(24914598704.0)}, 214 {0,RC(-331320693.0)/RC(205662961.0),RC(31361737.0)/RC(7433601.0),RC(-2426908385.0)/RC(822651844.0),RC(97305120.0)/RC(205662961.0)}, 215 {0,RC(44764047.0)/RC(29380423.0),RC(-1532549.0)/RC(353981.0),RC(90730570.0)/RC(29380423.0),RC(-8293050.0)/RC(29380423.0)}}; 216 217 ierr = TSRKRegister(TSRK5DP,5,7,&A[0][0],b,NULL,bembed,5,binterp[0]);CHKERRQ(ierr); 218 } 219 { 220 const PetscReal 221 A[8][8] = {{0,0,0,0,0,0,0,0}, 222 {RC(1.0)/RC(6.0),0,0,0,0,0,0,0}, 223 {RC(2.0)/RC(27.0),RC(4.0)/RC(27.0),0,0,0,0,0,0}, 224 {RC(183.0)/RC(1372.0),RC(-162.0)/RC(343.0),RC(1053.0)/RC(1372.0),0,0,0,0,0}, 225 {RC(68.0)/RC(297.0),RC(-4.0)/RC(11.0),RC(42.0)/RC(143.0),RC(1960.0)/RC(3861.0),0,0,0,0}, 226 {RC(597.0)/RC(22528.0),RC(81.0)/RC(352.0),RC(63099.0)/RC(585728.0),RC(58653.0)/RC(366080.0),RC(4617.0)/RC(20480.0),0,0,0}, 227 {RC(174197.0)/RC(959244.0),RC(-30942.0)/RC(79937.0),RC(8152137.0)/RC(19744439.0),RC(666106.0)/RC(1039181.0),RC(-29421.0)/RC(29068.0),RC(482048.0)/RC(414219.0),0,0}, 228 {RC(587.0)/RC(8064.0),0,RC(4440339.0)/RC(15491840.0),RC(24353.0)/RC(124800.0),RC(387.0)/RC(44800.0),RC(2152.0)/RC(5985.0),RC(7267.0)/RC(94080.0),0}}, 229 b[8] = {RC(587.0)/RC(8064.0),0,RC(4440339.0)/RC(15491840.0),RC(24353.0)/RC(124800.0),RC(387.0)/RC(44800.0),RC(2152.0)/RC(5985.0),RC(7267.0)/RC(94080.0),0}, 230 bembed[8] = {RC(2479.0)/RC(34992.0),0,RC(123.0)/RC(416.0),RC(612941.0)/RC(3411720.0),RC(43.0)/RC(1440.0),RC(2272.0)/RC(6561.0),RC(79937.0)/RC(1113912.0),RC(3293.0)/RC(556956.0)}; 231 ierr = TSRKRegister(TSRK5BS,5,8,&A[0][0],b,NULL,bembed,0,NULL);CHKERRQ(ierr); 232 } 233 #undef RC 234 PetscFunctionReturn(0); 235 } 236 237 /*@C 238 TSRKRegisterDestroy - Frees the list of schemes that were registered by TSRKRegister(). 239 240 Not Collective 241 242 Level: advanced 243 244 .keywords: TSRK, register, destroy 245 .seealso: TSRKRegister(), TSRKRegisterAll() 246 @*/ 247 PetscErrorCode TSRKRegisterDestroy(void) 248 { 249 PetscErrorCode ierr; 250 RKTableauLink link; 251 252 PetscFunctionBegin; 253 while ((link = RKTableauList)) { 254 RKTableau t = &link->tab; 255 RKTableauList = link->next; 256 ierr = PetscFree3(t->A,t->b,t->c); CHKERRQ(ierr); 257 ierr = PetscFree (t->bembed); CHKERRQ(ierr); 258 ierr = PetscFree (t->binterp); CHKERRQ(ierr); 259 ierr = PetscFree (t->name); CHKERRQ(ierr); 260 ierr = PetscFree (link); CHKERRQ(ierr); 261 } 262 TSRKRegisterAllCalled = PETSC_FALSE; 263 PetscFunctionReturn(0); 264 } 265 266 /*@C 267 TSRKInitializePackage - This function initializes everything in the TSRK package. It is called 268 from TSInitializePackage(). 269 270 Level: developer 271 272 .keywords: TS, TSRK, initialize, package 273 .seealso: PetscInitialize() 274 @*/ 275 PetscErrorCode TSRKInitializePackage(void) 276 { 277 PetscErrorCode ierr; 278 279 PetscFunctionBegin; 280 if (TSRKPackageInitialized) PetscFunctionReturn(0); 281 TSRKPackageInitialized = PETSC_TRUE; 282 ierr = TSRKRegisterAll();CHKERRQ(ierr); 283 ierr = PetscRegisterFinalize(TSRKFinalizePackage);CHKERRQ(ierr); 284 PetscFunctionReturn(0); 285 } 286 287 /*@C 288 TSRKFinalizePackage - This function destroys everything in the TSRK package. It is 289 called from PetscFinalize(). 290 291 Level: developer 292 293 .keywords: Petsc, destroy, package 294 .seealso: PetscFinalize() 295 @*/ 296 PetscErrorCode TSRKFinalizePackage(void) 297 { 298 PetscErrorCode ierr; 299 300 PetscFunctionBegin; 301 TSRKPackageInitialized = PETSC_FALSE; 302 ierr = TSRKRegisterDestroy();CHKERRQ(ierr); 303 PetscFunctionReturn(0); 304 } 305 306 /*@C 307 TSRKRegister - register an RK scheme by providing the entries in the Butcher tableau and optionally embedded approximations and interpolation 308 309 Not Collective, but the same schemes should be registered on all processes on which they will be used 310 311 Input Parameters: 312 + name - identifier for method 313 . order - approximation order of method 314 . s - number of stages, this is the dimension of the matrices below 315 . A - stage coefficients (dimension s*s, row-major) 316 . b - step completion table (dimension s; NULL to use last row of A) 317 . c - abscissa (dimension s; NULL to use row sums of A) 318 . bembed - completion table for embedded method (dimension s; NULL if not available) 319 . p - Order of the interpolation scheme, equal to the number of columns of binterp 320 - binterp - Coefficients of the interpolation formula (dimension s*p; NULL to reuse b with p=1) 321 322 Notes: 323 Several RK methods are provided, this function is only needed to create new methods. 324 325 Level: advanced 326 327 .keywords: TS, register 328 329 .seealso: TSRK 330 @*/ 331 PetscErrorCode TSRKRegister(TSRKType name,PetscInt order,PetscInt s, 332 const PetscReal A[],const PetscReal b[],const PetscReal c[], 333 const PetscReal bembed[],PetscInt p,const PetscReal binterp[]) 334 { 335 PetscErrorCode ierr; 336 RKTableauLink link; 337 RKTableau t; 338 PetscInt i,j; 339 340 PetscFunctionBegin; 341 PetscValidCharPointer(name,1); 342 PetscValidRealPointer(A,4); 343 if (b) PetscValidRealPointer(b,5); 344 if (c) PetscValidRealPointer(c,6); 345 if (bembed) PetscValidRealPointer(bembed,7); 346 if (binterp || p > 1) PetscValidRealPointer(binterp,9); 347 348 ierr = TSRKInitializePackage();CHKERRQ(ierr); 349 ierr = PetscNew(&link);CHKERRQ(ierr); 350 t = &link->tab; 351 352 ierr = PetscStrallocpy(name,&t->name);CHKERRQ(ierr); 353 t->order = order; 354 t->s = s; 355 ierr = PetscMalloc3(s*s,&t->A,s,&t->b,s,&t->c);CHKERRQ(ierr); 356 ierr = PetscMemcpy(t->A,A,s*s*sizeof(A[0]));CHKERRQ(ierr); 357 if (b) { ierr = PetscMemcpy(t->b,b,s*sizeof(b[0]));CHKERRQ(ierr); } 358 else for (i=0; i<s; i++) t->b[i] = A[(s-1)*s+i]; 359 if (c) { ierr = PetscMemcpy(t->c,c,s*sizeof(c[0]));CHKERRQ(ierr); } 360 else for (i=0; i<s; i++) for (j=0,t->c[i]=0; j<s; j++) t->c[i] += A[i*s+j]; 361 t->FSAL = PETSC_TRUE; 362 for (i=0; i<s; i++) if (t->A[(s-1)*s+i] != t->b[i]) t->FSAL = PETSC_FALSE; 363 364 if (bembed) { 365 ierr = PetscMalloc1(s,&t->bembed);CHKERRQ(ierr); 366 ierr = PetscMemcpy(t->bembed,bembed,s*sizeof(bembed[0]));CHKERRQ(ierr); 367 } 368 369 if (!binterp) { p = 1; binterp = t->b; } 370 t->p = p; 371 ierr = PetscMalloc1(s*p,&t->binterp);CHKERRQ(ierr); 372 ierr = PetscMemcpy(t->binterp,binterp,s*p*sizeof(binterp[0]));CHKERRQ(ierr); 373 374 link->next = RKTableauList; 375 RKTableauList = link; 376 PetscFunctionReturn(0); 377 } 378 379 /* 380 This is for single-step RK method 381 The step completion formula is 382 383 x1 = x0 + h b^T YdotRHS 384 385 This function can be called before or after ts->vec_sol has been updated. 386 Suppose we have a completion formula (b) and an embedded formula (be) of different order. 387 We can write 388 389 x1e = x0 + h be^T YdotRHS 390 = x1 - h b^T YdotRHS + h be^T YdotRHS 391 = x1 + h (be - b)^T YdotRHS 392 393 so we can evaluate the method with different order even after the step has been optimistically completed. 394 */ 395 static PetscErrorCode TSEvaluateStep_RK(TS ts,PetscInt order,Vec X,PetscBool *done) 396 { 397 TS_RK *rk = (TS_RK*)ts->data; 398 RKTableau tab = rk->tableau; 399 PetscScalar *w = rk->work; 400 PetscReal h; 401 PetscInt s = tab->s,j; 402 PetscErrorCode ierr; 403 404 PetscFunctionBegin; 405 switch (rk->status) { 406 case TS_STEP_INCOMPLETE: 407 case TS_STEP_PENDING: 408 h = ts->time_step; break; 409 case TS_STEP_COMPLETE: 410 h = ts->ptime - ts->ptime_prev; break; 411 default: SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_PLIB,"Invalid TSStepStatus"); 412 } 413 if (order == tab->order) { 414 if (rk->status == TS_STEP_INCOMPLETE) { 415 ierr = VecCopy(ts->vec_sol,X);CHKERRQ(ierr); 416 for (j=0; j<s; j++) w[j] = h*tab->b[j]/rk->dtratio; 417 ierr = VecMAXPY(X,s,w,rk->YdotRHS);CHKERRQ(ierr); 418 } else {ierr = VecCopy(ts->vec_sol,X);CHKERRQ(ierr);} 419 PetscFunctionReturn(0); 420 } else if (order == tab->order-1) { 421 if (!tab->bembed) goto unavailable; 422 if (rk->status == TS_STEP_INCOMPLETE) { /*Complete with the embedded method (be)*/ 423 ierr = VecCopy(ts->vec_sol,X);CHKERRQ(ierr); 424 for (j=0; j<s; j++) w[j] = h*tab->bembed[j]; 425 ierr = VecMAXPY(X,s,w,rk->YdotRHS);CHKERRQ(ierr); 426 } else { /*Rollback and re-complete using (be-b) */ 427 ierr = VecCopy(ts->vec_sol,X);CHKERRQ(ierr); 428 for (j=0; j<s; j++) w[j] = h*(tab->bembed[j] - tab->b[j]); 429 ierr = VecMAXPY(X,s,w,rk->YdotRHS);CHKERRQ(ierr); 430 } 431 if (done) *done = PETSC_TRUE; 432 PetscFunctionReturn(0); 433 } 434 unavailable: 435 if (done) *done = PETSC_FALSE; 436 else SETERRQ3(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"RK '%s' of order %D cannot evaluate step at order %D. Consider using -ts_adapt_type none or a different method that has an embedded estimate.",tab->name,tab->order,order); 437 PetscFunctionReturn(0); 438 } 439 440 static PetscErrorCode TSForwardCostIntegral_RK(TS ts) 441 { 442 TS_RK *rk = (TS_RK*)ts->data; 443 RKTableau tab = rk->tableau; 444 const PetscInt s = tab->s; 445 const PetscReal *b = tab->b,*c = tab->c; 446 Vec *Y = rk->Y; 447 PetscInt i; 448 PetscErrorCode ierr; 449 450 PetscFunctionBegin; 451 /* backup cost integral */ 452 ierr = VecCopy(ts->vec_costintegral,rk->VecCostIntegral0);CHKERRQ(ierr); 453 for (i=s-1; i>=0; i--) { 454 /* Evolve ts->vec_costintegral to compute integrals */ 455 ierr = TSComputeCostIntegrand(ts,rk->ptime+rk->time_step*c[i],Y[i],ts->vec_costintegrand);CHKERRQ(ierr); 456 ierr = VecAXPY(ts->vec_costintegral,rk->time_step*b[i],ts->vec_costintegrand);CHKERRQ(ierr); 457 } 458 PetscFunctionReturn(0); 459 } 460 461 static PetscErrorCode TSAdjointCostIntegral_RK(TS ts) 462 { 463 TS_RK *rk = (TS_RK*)ts->data; 464 RKTableau tab = rk->tableau; 465 const PetscInt s = tab->s; 466 const PetscReal *b = tab->b,*c = tab->c; 467 Vec *Y = rk->Y; 468 PetscInt i; 469 PetscErrorCode ierr; 470 471 PetscFunctionBegin; 472 for (i=s-1; i>=0; i--) { 473 /* Evolve ts->vec_costintegral to compute integrals */ 474 ierr = TSComputeCostIntegrand(ts,ts->ptime+ts->time_step*(1.0-c[i]),Y[i],ts->vec_costintegrand);CHKERRQ(ierr); 475 ierr = VecAXPY(ts->vec_costintegral,-ts->time_step*b[i],ts->vec_costintegrand);CHKERRQ(ierr); 476 } 477 PetscFunctionReturn(0); 478 } 479 480 static PetscErrorCode TSRollBack_RK(TS ts) 481 { 482 TS_RK *rk = (TS_RK*)ts->data; 483 RKTableau tab = rk->tableau; 484 const PetscInt s = tab->s; 485 const PetscReal *b = tab->b; 486 PetscScalar *w = rk->work; 487 Vec *YdotRHS = rk->YdotRHS; 488 PetscInt j; 489 PetscReal h; 490 PetscErrorCode ierr; 491 492 PetscFunctionBegin; 493 switch (rk->status) { 494 case TS_STEP_INCOMPLETE: 495 case TS_STEP_PENDING: 496 h = ts->time_step; break; 497 case TS_STEP_COMPLETE: 498 h = ts->ptime - ts->ptime_prev; break; 499 default: SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_PLIB,"Invalid TSStepStatus"); 500 } 501 for (j=0; j<s; j++) w[j] = -h*b[j]; 502 ierr = VecMAXPY(ts->vec_sol,s,w,YdotRHS);CHKERRQ(ierr); 503 PetscFunctionReturn(0); 504 } 505 506 static PetscErrorCode TSStep_RK(TS ts) 507 { 508 TS_RK *rk = (TS_RK*)ts->data; 509 RKTableau tab = rk->tableau; 510 const PetscInt s = tab->s; 511 const PetscReal *A = tab->A,*c = tab->c; 512 PetscScalar *w = rk->work; 513 Vec *Y = rk->Y,*YdotRHS = rk->YdotRHS; 514 PetscBool FSAL = tab->FSAL; 515 TSAdapt adapt; 516 PetscInt i,j; 517 PetscInt rejections = 0; 518 PetscBool stageok,accept = PETSC_TRUE; 519 PetscReal next_time_step = ts->time_step; 520 PetscErrorCode ierr; 521 522 PetscFunctionBegin; 523 if (ts->steprollback || ts->steprestart) FSAL = PETSC_FALSE; 524 if (FSAL) { ierr = VecCopy(YdotRHS[s-1],YdotRHS[0]);CHKERRQ(ierr); } 525 526 rk->status = TS_STEP_INCOMPLETE; 527 while (!ts->reason && rk->status != TS_STEP_COMPLETE) { 528 PetscReal t = ts->ptime; 529 PetscReal h = ts->time_step; 530 for (i=0; i<s; i++) { 531 rk->stage_time = t + h*c[i]; 532 ierr = TSPreStage(ts,rk->stage_time); CHKERRQ(ierr); 533 ierr = VecCopy(ts->vec_sol,Y[i]);CHKERRQ(ierr); 534 for (j=0; j<i; j++) w[j] = h*A[i*s+j]; 535 ierr = VecMAXPY(Y[i],i,w,YdotRHS);CHKERRQ(ierr); 536 ierr = TSPostStage(ts,rk->stage_time,i,Y); CHKERRQ(ierr); 537 ierr = TSGetAdapt(ts,&adapt);CHKERRQ(ierr); 538 ierr = TSAdaptCheckStage(adapt,ts,rk->stage_time,Y[i],&stageok);CHKERRQ(ierr); 539 if (!stageok) goto reject_step; 540 if (FSAL && !i) continue; 541 ierr = TSComputeRHSFunction(ts,t+h*c[i],Y[i],YdotRHS[i]);CHKERRQ(ierr); 542 } 543 544 rk->status = TS_STEP_INCOMPLETE; 545 ierr = TSEvaluateStep(ts,tab->order,ts->vec_sol,NULL);CHKERRQ(ierr); 546 rk->status = TS_STEP_PENDING; 547 ierr = TSGetAdapt(ts,&adapt);CHKERRQ(ierr); 548 ierr = TSAdaptCandidatesClear(adapt);CHKERRQ(ierr); 549 ierr = TSAdaptCandidateAdd(adapt,tab->name,tab->order,1,tab->ccfl,(PetscReal)tab->s,PETSC_TRUE);CHKERRQ(ierr); 550 ierr = TSAdaptChoose(adapt,ts,ts->time_step,NULL,&next_time_step,&accept);CHKERRQ(ierr); 551 rk->status = accept ? TS_STEP_COMPLETE : TS_STEP_INCOMPLETE; 552 if (!accept) { /* Roll back the current step */ 553 ierr = TSRollBack_RK(ts);CHKERRQ(ierr); 554 ts->time_step = next_time_step; 555 goto reject_step; 556 } 557 558 if (ts->costintegralfwd) { /* Save the info for the later use in cost integral evaluation */ 559 rk->ptime = ts->ptime; 560 rk->time_step = ts->time_step; 561 } 562 563 ts->ptime += ts->time_step; 564 ts->time_step = next_time_step; 565 break; 566 567 reject_step: 568 ts->reject++; accept = PETSC_FALSE; 569 if (!ts->reason && ++rejections > ts->max_reject && ts->max_reject >= 0) { 570 ts->reason = TS_DIVERGED_STEP_REJECTED; 571 ierr = PetscInfo2(ts,"Step=%D, step rejections %D greater than current TS allowed, stopping solve\n",ts->steps,rejections);CHKERRQ(ierr); 572 } 573 } 574 PetscFunctionReturn(0); 575 } 576 577 static PetscErrorCode TSAdjointSetUp_RK(TS ts) 578 { 579 TS_RK *rk = (TS_RK*)ts->data; 580 RKTableau tab = rk->tableau; 581 PetscInt s = tab->s; 582 PetscErrorCode ierr; 583 584 PetscFunctionBegin; 585 if (ts->adjointsetupcalled++) PetscFunctionReturn(0); 586 ierr = VecDuplicateVecs(ts->vecs_sensi[0],s*ts->numcost,&rk->VecsDeltaLam);CHKERRQ(ierr); 587 ierr = VecDuplicateVecs(ts->vecs_sensi[0],ts->numcost,&rk->VecsSensiTemp);CHKERRQ(ierr); 588 if(ts->vecs_sensip) { 589 ierr = VecDuplicate(ts->vecs_sensip[0],&rk->VecDeltaMu);CHKERRQ(ierr); 590 } 591 PetscFunctionReturn(0); 592 } 593 594 static PetscErrorCode TSAdjointStep_RK(TS ts) 595 { 596 TS_RK *rk = (TS_RK*)ts->data; 597 RKTableau tab = rk->tableau; 598 Mat J; 599 const PetscInt s = tab->s; 600 const PetscReal *A = tab->A,*b = tab->b,*c = tab->c; 601 PetscScalar *w = rk->work; 602 Vec *Y = rk->Y,*VecsDeltaLam = rk->VecsDeltaLam,VecDeltaMu = rk->VecDeltaMu,*VecsSensiTemp = rk->VecsSensiTemp; 603 PetscInt i,j,nadj; 604 PetscReal t = ts->ptime; 605 PetscReal h = ts->time_step,stage_time; 606 PetscBool zero; 607 PetscErrorCode ierr; 608 609 PetscFunctionBegin; 610 rk->status = TS_STEP_INCOMPLETE; 611 612 for (i=s-1; i>=0; i--) { 613 stage_time = t + h*(1.0-c[i]); 614 zero = PETSC_FALSE; 615 ierr = TSGetRHSJacobian(ts,&J,NULL,NULL,NULL);CHKERRQ(ierr); 616 ierr = TSComputeRHSJacobian(ts,stage_time,Y[i],J,J);CHKERRQ(ierr); 617 if (ts->vec_costintegral) { 618 ierr = TSComputeDRDUFunction(ts,stage_time,Y[i],ts->vecs_drdu);CHKERRQ(ierr); 619 } 620 if (ts->vecs_sensip) { 621 ierr = TSComputeRHSJacobianP(ts,stage_time,Y[i],ts->Jacp);CHKERRQ(ierr); /* get f_p */ 622 if (ts->vec_costintegral) { 623 ierr = TSComputeDRDPFunction(ts,stage_time,Y[i],ts->vecs_drdp);CHKERRQ(ierr); 624 } 625 } 626 627 if (b[i] == 0 && i == s-1) zero = PETSC_TRUE; 628 629 for (j=i+1; j<s; j++) w[j-i-1] = -h*A[j*s+i]; /* coefficients for computing VecsSensiTemp */ 630 631 for (nadj=0; nadj<ts->numcost; nadj++) { 632 /* Stage values of lambda */ 633 if (!zero) { 634 ierr = VecCopy(ts->vecs_sensi[nadj],VecsSensiTemp[nadj]);CHKERRQ(ierr); /* VecDeltaLam is an vec array of size s by numcost */ 635 ierr = VecScale(VecsSensiTemp[nadj],-h*b[i]);CHKERRQ(ierr); 636 ierr = VecMAXPY(VecsSensiTemp[nadj],s-i-1,w,&VecsDeltaLam[nadj*s+i+1]);CHKERRQ(ierr); 637 ierr = MatMultTranspose(J,VecsSensiTemp[nadj],VecsDeltaLam[nadj*s+i]);CHKERRQ(ierr); 638 } else { 639 ierr = VecSet(VecsDeltaLam[nadj*s+i],0);CHKERRQ(ierr); 640 } 641 if (ts->vec_costintegral) { 642 ierr = VecAXPY(VecsDeltaLam[nadj*s+i],-h*b[i],ts->vecs_drdu[nadj]);CHKERRQ(ierr); 643 } 644 645 /* Stage values of mu */ 646 if (ts->vecs_sensip) { 647 if (!zero) { 648 ierr = MatMultTranspose(ts->Jacp,VecsSensiTemp[nadj],VecDeltaMu);CHKERRQ(ierr); 649 } else { 650 ierr = VecSet(VecDeltaMu,0);CHKERRQ(ierr); 651 } 652 if (ts->vec_costintegral) { 653 ierr = VecAXPY(VecDeltaMu,-h*b[i],ts->vecs_drdp[nadj]);CHKERRQ(ierr); 654 } 655 ierr = VecAXPY(ts->vecs_sensip[nadj],1.,VecDeltaMu);CHKERRQ(ierr); /* update sensip for each stage */ 656 } 657 } 658 } 659 660 for (j=0; j<s; j++) w[j] = 1.0; 661 for (nadj=0; nadj<ts->numcost; nadj++) { /* no need to do this for mu's */ 662 ierr = VecMAXPY(ts->vecs_sensi[nadj],s,w,&VecsDeltaLam[nadj*s]);CHKERRQ(ierr); 663 } 664 rk->status = TS_STEP_COMPLETE; 665 PetscFunctionReturn(0); 666 } 667 668 static PetscErrorCode TSInterpolate_RK(TS ts,PetscReal itime,Vec X) 669 { 670 TS_RK *rk = (TS_RK*)ts->data; 671 PetscInt s = rk->tableau->s,p = rk->tableau->p,i,j; 672 PetscReal h; 673 PetscReal tt,t; 674 PetscScalar *b; 675 const PetscReal *B = rk->tableau->binterp; 676 PetscErrorCode ierr; 677 678 PetscFunctionBegin; 679 if (!B) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSRK %s does not have an interpolation formula",rk->tableau->name); 680 681 switch (rk->status) { 682 case TS_STEP_INCOMPLETE: 683 case TS_STEP_PENDING: 684 h = ts->time_step; 685 t = (itime - ts->ptime)/h; 686 break; 687 case TS_STEP_COMPLETE: 688 h = ts->ptime - ts->ptime_prev; 689 t = (itime - ts->ptime)/h + 1; /* In the interval [0,1] */ 690 break; 691 default: SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_PLIB,"Invalid TSStepStatus"); 692 } 693 ierr = PetscMalloc1(s,&b);CHKERRQ(ierr); 694 for (i=0; i<s; i++) b[i] = 0; 695 for (j=0,tt=t; j<p; j++,tt*=t) { 696 for (i=0; i<s; i++) { 697 b[i] += h * B[i*p+j] * tt; 698 } 699 } 700 ierr = VecCopy(rk->Y[0],X);CHKERRQ(ierr); 701 ierr = VecMAXPY(X,s,b,rk->YdotRHS);CHKERRQ(ierr); 702 ierr = PetscFree(b);CHKERRQ(ierr); 703 PetscFunctionReturn(0); 704 } 705 706 /*------------------------------------------------------------*/ 707 708 static PetscErrorCode TSRKTableauReset(TS ts) 709 { 710 TS_RK *rk = (TS_RK*)ts->data; 711 RKTableau tab = rk->tableau; 712 PetscErrorCode ierr; 713 714 PetscFunctionBegin; 715 if (!tab) PetscFunctionReturn(0); 716 ierr = PetscFree(rk->work);CHKERRQ(ierr); 717 ierr = VecDestroyVecs(tab->s,&rk->Y);CHKERRQ(ierr); 718 ierr = VecDestroyVecs(tab->s,&rk->YdotRHS);CHKERRQ(ierr); 719 ierr = VecDestroyVecs(tab->s*ts->numcost,&rk->VecsDeltaLam);CHKERRQ(ierr); 720 ierr = VecDestroyVecs(ts->numcost,&rk->VecsSensiTemp);CHKERRQ(ierr); 721 ierr = VecDestroy(&rk->VecDeltaMu);CHKERRQ(ierr); 722 PetscFunctionReturn(0); 723 } 724 725 static PetscErrorCode TSReset_RK(TS ts) 726 { 727 TS_RK *rk = (TS_RK*)ts->data; 728 PetscErrorCode ierr; 729 730 PetscFunctionBegin; 731 ierr = TSRKTableauReset(ts);CHKERRQ(ierr); 732 ierr = VecDestroy(&rk->VecCostIntegral0);CHKERRQ(ierr); 733 if (ts->use_splitrhsfunction) { 734 ierr = PetscTryMethod(ts,"TSReset_RK_MultirateSplit_C",(TS),(ts));CHKERRQ(ierr); 735 } else { 736 ierr = PetscTryMethod(ts,"TSReset_RK_MultirateNonsplit_C",(TS),(ts));CHKERRQ(ierr); 737 } 738 PetscFunctionReturn(0); 739 } 740 741 static PetscErrorCode DMCoarsenHook_TSRK(DM fine,DM coarse,void *ctx) 742 { 743 PetscFunctionBegin; 744 PetscFunctionReturn(0); 745 } 746 747 static PetscErrorCode DMRestrictHook_TSRK(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse,void *ctx) 748 { 749 PetscFunctionBegin; 750 PetscFunctionReturn(0); 751 } 752 753 754 static PetscErrorCode DMSubDomainHook_TSRK(DM dm,DM subdm,void *ctx) 755 { 756 PetscFunctionBegin; 757 PetscFunctionReturn(0); 758 } 759 760 static PetscErrorCode DMSubDomainRestrictHook_TSRK(DM dm,VecScatter gscat,VecScatter lscat,DM subdm,void *ctx) 761 { 762 763 PetscFunctionBegin; 764 PetscFunctionReturn(0); 765 } 766 /* 767 static PetscErrorCode RKSetAdjCoe(RKTableau tab) 768 { 769 PetscReal *A,*b; 770 PetscInt s,i,j; 771 PetscErrorCode ierr; 772 773 PetscFunctionBegin; 774 s = tab->s; 775 ierr = PetscMalloc2(s*s,&A,s,&b);CHKERRQ(ierr); 776 777 for (i=0; i<s; i++) 778 for (j=0; j<s; j++) { 779 A[i*s+j] = (tab->b[s-1-i]==0) ? 0: -tab->A[s-1-i+(s-1-j)*s] * tab->b[s-1-j] / tab->b[s-1-i]; 780 ierr = PetscPrintf(PETSC_COMM_WORLD,"Coefficients: A[%D][%D]=%.6f\n",i,j,A[i*s+j]);CHKERRQ(ierr); 781 } 782 783 for (i=0; i<s; i++) b[i] = (tab->b[s-1-i]==0)? 0: -tab->b[s-1-i]; 784 785 ierr = PetscMemcpy(tab->A,A,s*s*sizeof(A[0]));CHKERRQ(ierr); 786 ierr = PetscMemcpy(tab->b,b,s*sizeof(b[0]));CHKERRQ(ierr); 787 ierr = PetscFree2(A,b);CHKERRQ(ierr); 788 PetscFunctionReturn(0); 789 } 790 */ 791 792 static PetscErrorCode TSRKTableauSetUp(TS ts) 793 { 794 TS_RK *rk = (TS_RK*)ts->data; 795 RKTableau tab = rk->tableau; 796 PetscErrorCode ierr; 797 798 PetscFunctionBegin; 799 ierr = PetscMalloc1(tab->s,&rk->work);CHKERRQ(ierr); 800 ierr = VecDuplicateVecs(ts->vec_sol,tab->s,&rk->Y);CHKERRQ(ierr); 801 ierr = VecDuplicateVecs(ts->vec_sol,tab->s,&rk->YdotRHS);CHKERRQ(ierr); 802 PetscFunctionReturn(0); 803 } 804 805 static PetscErrorCode TSSetUp_RK(TS ts) 806 { 807 TS_RK *rk = (TS_RK*)ts->data; 808 PetscErrorCode ierr; 809 DM dm; 810 811 PetscFunctionBegin; 812 ierr = TSCheckImplicitTerm(ts);CHKERRQ(ierr); 813 ierr = TSRKTableauSetUp(ts);CHKERRQ(ierr); 814 if (!rk->VecCostIntegral0 && ts->vec_costintegral && ts->costintegralfwd) { /* back up cost integral */ 815 ierr = VecDuplicate(ts->vec_costintegral,&rk->VecCostIntegral0);CHKERRQ(ierr); 816 } 817 ierr = TSGetDM(ts,&dm);CHKERRQ(ierr); 818 ierr = DMCoarsenHookAdd(dm,DMCoarsenHook_TSRK,DMRestrictHook_TSRK,ts);CHKERRQ(ierr); 819 ierr = DMSubDomainHookAdd(dm,DMSubDomainHook_TSRK,DMSubDomainRestrictHook_TSRK,ts);CHKERRQ(ierr); 820 if (ts->use_splitrhsfunction) { 821 ierr = PetscTryMethod(ts,"TSSetUp_RK_MultirateSplit_C",(TS),(ts));CHKERRQ(ierr); 822 } else { 823 ierr = PetscTryMethod(ts,"TSSetUp_RK_MultirateNonsplit_C",(TS),(ts));CHKERRQ(ierr); 824 } 825 PetscFunctionReturn(0); 826 } 827 828 static PetscErrorCode TSSetFromOptions_RK(PetscOptionItems *PetscOptionsObject,TS ts) 829 { 830 TS_RK *rk = (TS_RK*)ts->data; 831 PetscErrorCode ierr; 832 833 PetscFunctionBegin; 834 ierr = PetscOptionsHead(PetscOptionsObject,"RK ODE solver options");CHKERRQ(ierr); 835 { 836 RKTableauLink link; 837 PetscInt count,choice; 838 PetscBool flg,use_multirate = PETSC_FALSE; 839 const char **namelist; 840 841 for (link=RKTableauList,count=0; link; link=link->next,count++) ; 842 ierr = PetscMalloc1(count,(char***)&namelist);CHKERRQ(ierr); 843 for (link=RKTableauList,count=0; link; link=link->next,count++) namelist[count] = link->tab.name; 844 ierr = PetscOptionsBool("-ts_rk_multirate","Use interpolation-based multirate RK method","TSRKSetMultirate",rk->use_multirate,&use_multirate,&flg);CHKERRQ(ierr); 845 if (flg) { 846 ierr = TSRKSetMultirate(ts,use_multirate);CHKERRQ(ierr); 847 } 848 ierr = PetscOptionsEList("-ts_rk_type","Family of RK method","TSRKSetType",(const char*const*)namelist,count,rk->tableau->name,&choice,&flg);CHKERRQ(ierr); 849 if (flg) {ierr = TSRKSetType(ts,namelist[choice]);CHKERRQ(ierr);} 850 ierr = PetscFree(namelist);CHKERRQ(ierr); 851 } 852 ierr = PetscOptionsTail();CHKERRQ(ierr); 853 ierr = PetscOptionsBegin(PETSC_COMM_WORLD,NULL,"Multirate methods options","");CHKERRQ(ierr); 854 ierr = PetscOptionsInt("-ts_rk_dtratio","time step ratio between slow and fast","",rk->dtratio,&rk->dtratio,NULL);CHKERRQ(ierr); 855 ierr = PetscOptionsEnd();CHKERRQ(ierr); 856 PetscFunctionReturn(0); 857 } 858 859 static PetscErrorCode TSView_RK(TS ts,PetscViewer viewer) 860 { 861 TS_RK *rk = (TS_RK*)ts->data; 862 PetscBool iascii; 863 PetscErrorCode ierr; 864 865 PetscFunctionBegin; 866 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 867 if (iascii) { 868 RKTableau tab = rk->tableau; 869 TSRKType rktype; 870 char buf[512]; 871 ierr = TSRKGetType(ts,&rktype);CHKERRQ(ierr); 872 ierr = PetscViewerASCIIPrintf(viewer," RK type %s\n",rktype);CHKERRQ(ierr); 873 ierr = PetscViewerASCIIPrintf(viewer," Order: %D\n",tab->order);CHKERRQ(ierr); 874 ierr = PetscViewerASCIIPrintf(viewer," FSAL property: %s\n",tab->FSAL ? "yes" : "no");CHKERRQ(ierr); 875 ierr = PetscFormatRealArray(buf,sizeof(buf),"% 8.6f",tab->s,tab->c);CHKERRQ(ierr); 876 ierr = PetscViewerASCIIPrintf(viewer," Abscissa c = %s\n",buf);CHKERRQ(ierr); 877 } 878 PetscFunctionReturn(0); 879 } 880 881 static PetscErrorCode TSLoad_RK(TS ts,PetscViewer viewer) 882 { 883 PetscErrorCode ierr; 884 TSAdapt adapt; 885 886 PetscFunctionBegin; 887 ierr = TSGetAdapt(ts,&adapt);CHKERRQ(ierr); 888 ierr = TSAdaptLoad(adapt,viewer);CHKERRQ(ierr); 889 PetscFunctionReturn(0); 890 } 891 892 /*@C 893 TSRKSetType - Set the type of RK scheme 894 895 Logically collective 896 897 Input Parameter: 898 + ts - timestepping context 899 - rktype - type of RK-scheme 900 901 Options Database: 902 . -ts_rk_type - <1fe,2a,3,3bs,4,5f,5dp,5bs> 903 904 Level: intermediate 905 906 .seealso: TSRKGetType(), TSRK, TSRKType, TSRK1FE, TSRK2A, TSRK3, TSRK3BS, TSRK4, TSRK5F, TSRK5DP, TSRK5BS 907 @*/ 908 PetscErrorCode TSRKSetType(TS ts,TSRKType rktype) 909 { 910 PetscErrorCode ierr; 911 912 PetscFunctionBegin; 913 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 914 PetscValidCharPointer(rktype,2); 915 ierr = PetscTryMethod(ts,"TSRKSetType_C",(TS,TSRKType),(ts,rktype));CHKERRQ(ierr); 916 PetscFunctionReturn(0); 917 } 918 919 /*@C 920 TSRKGetType - Get the type of RK scheme 921 922 Logically collective 923 924 Input Parameter: 925 . ts - timestepping context 926 927 Output Parameter: 928 . rktype - type of RK-scheme 929 930 Level: intermediate 931 932 .seealso: TSRKGetType() 933 @*/ 934 PetscErrorCode TSRKGetType(TS ts,TSRKType *rktype) 935 { 936 PetscErrorCode ierr; 937 938 PetscFunctionBegin; 939 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 940 ierr = PetscUseMethod(ts,"TSRKGetType_C",(TS,TSRKType*),(ts,rktype));CHKERRQ(ierr); 941 PetscFunctionReturn(0); 942 } 943 944 static PetscErrorCode TSRKGetType_RK(TS ts,TSRKType *rktype) 945 { 946 TS_RK *rk = (TS_RK*)ts->data; 947 948 PetscFunctionBegin; 949 *rktype = rk->tableau->name; 950 PetscFunctionReturn(0); 951 } 952 953 static PetscErrorCode TSRKSetType_RK(TS ts,TSRKType rktype) 954 { 955 TS_RK *rk = (TS_RK*)ts->data; 956 PetscErrorCode ierr; 957 PetscBool match; 958 RKTableauLink link; 959 960 PetscFunctionBegin; 961 if (rk->tableau) { 962 ierr = PetscStrcmp(rk->tableau->name,rktype,&match);CHKERRQ(ierr); 963 if (match) PetscFunctionReturn(0); 964 } 965 for (link = RKTableauList; link; link=link->next) { 966 ierr = PetscStrcmp(link->tab.name,rktype,&match);CHKERRQ(ierr); 967 if (match) { 968 if (ts->setupcalled) {ierr = TSRKTableauReset(ts);CHKERRQ(ierr);} 969 rk->tableau = &link->tab; 970 if (ts->setupcalled) {ierr = TSRKTableauSetUp(ts);CHKERRQ(ierr);} 971 ts->default_adapt_type = rk->tableau->bembed ? TSADAPTBASIC : TSADAPTNONE; 972 PetscFunctionReturn(0); 973 } 974 } 975 SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_UNKNOWN_TYPE,"Could not find '%s'",rktype); 976 PetscFunctionReturn(0); 977 } 978 979 static PetscErrorCode TSGetStages_RK(TS ts,PetscInt *ns,Vec **Y) 980 { 981 TS_RK *rk = (TS_RK*)ts->data; 982 983 PetscFunctionBegin; 984 if (ns) *ns = rk->tableau->s; 985 if (Y) *Y = rk->Y; 986 PetscFunctionReturn(0); 987 } 988 989 static PetscErrorCode TSDestroy_RK(TS ts) 990 { 991 PetscErrorCode ierr; 992 993 PetscFunctionBegin; 994 ierr = TSReset_RK(ts);CHKERRQ(ierr); 995 if (ts->dm) { 996 ierr = DMCoarsenHookRemove(ts->dm,DMCoarsenHook_TSRK,DMRestrictHook_TSRK,ts);CHKERRQ(ierr); 997 ierr = DMSubDomainHookRemove(ts->dm,DMSubDomainHook_TSRK,DMSubDomainRestrictHook_TSRK,ts);CHKERRQ(ierr); 998 } 999 ierr = PetscFree(ts->data);CHKERRQ(ierr); 1000 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSRKGetType_C",NULL);CHKERRQ(ierr); 1001 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSRKSetType_C",NULL);CHKERRQ(ierr); 1002 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSRKSetMultirate_C",NULL);CHKERRQ(ierr); 1003 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSRKGetMultirate_C",NULL);CHKERRQ(ierr); 1004 PetscFunctionReturn(0); 1005 } 1006 1007 /*@C 1008 TSRKSetMultirate - Use the interpolation-based multirate RK method 1009 1010 Logically collective 1011 1012 Input Parameter: 1013 + ts - timestepping context 1014 - use_multirate - PETSC_TRUE enables the multirate RK method, sets the basic method to be RK2A and sets the ratio between slow stepsize and fast stepsize to be 2 1015 1016 Options Database: 1017 . -ts_rk_multirate - <true,false> 1018 1019 Notes: 1020 The multirate method requires interpolation. The default interpolation works for 1st- and 2nd- order RK, but not for high-order RKs except TSRK5DP which comes with the interpolation coeffcients (binterp). 1021 1022 Level: intermediate 1023 1024 .seealso: TSRKGetMultirate() 1025 @*/ 1026 PetscErrorCode TSRKSetMultirate(TS ts,PetscBool use_multirate) 1027 { 1028 PetscErrorCode ierr; 1029 1030 PetscFunctionBegin; 1031 ierr = PetscTryMethod(ts,"TSRKSetMultirate_C",(TS,PetscBool),(ts,use_multirate));CHKERRQ(ierr); 1032 PetscFunctionReturn(0); 1033 } 1034 1035 /*@C 1036 TSRKGetMultirate - Gets whether to Use the interpolation-based multirate RK method 1037 1038 Not collective 1039 1040 Input Parameter: 1041 . ts - timestepping context 1042 1043 Output Parameter: 1044 . use_multirate - PETSC_TRUE if the multirate RK method is enabled, PETSC_FALSE otherwise 1045 1046 Level: intermediate 1047 1048 .seealso: TSRKSetMultirate() 1049 @*/ 1050 PetscErrorCode TSRKGetMultirate(TS ts,PetscBool *use_multirate) 1051 { 1052 PetscErrorCode ierr; 1053 1054 PetscFunctionBegin; 1055 ierr = PetscUseMethod(ts,"TSRKGetMultirate_C",(TS,PetscBool*),(ts,use_multirate));CHKERRQ(ierr); 1056 PetscFunctionReturn(0); 1057 } 1058 1059 /*MC 1060 TSRK - ODE and DAE solver using Runge-Kutta schemes 1061 1062 The user should provide the right hand side of the equation 1063 using TSSetRHSFunction(). 1064 1065 Notes: 1066 The default is TSRK3BS, it can be changed with TSRKSetType() or -ts_rk_type 1067 1068 Level: beginner 1069 1070 .seealso: TSCreate(), TS, TSSetType(), TSRKSetType(), TSRKGetType(), TSRKSetFullyImplicit(), TSRK2D, TTSRK2E, TSRK3, 1071 TSRK4, TSRK5, TSRKPRSSP2, TSRKBPR3, TSRKType, TSRKRegister(), TSRKSetMultirate(), TSRKGetMultirate() 1072 1073 M*/ 1074 PETSC_EXTERN PetscErrorCode TSCreate_RK(TS ts) 1075 { 1076 TS_RK *rk; 1077 PetscErrorCode ierr; 1078 1079 PetscFunctionBegin; 1080 ierr = TSRKInitializePackage();CHKERRQ(ierr); 1081 1082 ts->ops->reset = TSReset_RK; 1083 ts->ops->destroy = TSDestroy_RK; 1084 ts->ops->view = TSView_RK; 1085 ts->ops->load = TSLoad_RK; 1086 ts->ops->setup = TSSetUp_RK; 1087 ts->ops->adjointsetup = TSAdjointSetUp_RK; 1088 ts->ops->interpolate = TSInterpolate_RK; 1089 ts->ops->step = TSStep_RK; 1090 ts->ops->evaluatestep = TSEvaluateStep_RK; 1091 ts->ops->rollback = TSRollBack_RK; 1092 ts->ops->setfromoptions = TSSetFromOptions_RK; 1093 ts->ops->getstages = TSGetStages_RK; 1094 ts->ops->adjointstep = TSAdjointStep_RK; 1095 1096 ts->ops->adjointintegral = TSAdjointCostIntegral_RK; 1097 ts->ops->forwardintegral = TSForwardCostIntegral_RK; 1098 1099 ierr = PetscNewLog(ts,&rk);CHKERRQ(ierr); 1100 ts->data = (void*)rk; 1101 1102 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSRKGetType_C",TSRKGetType_RK);CHKERRQ(ierr); 1103 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSRKSetType_C",TSRKSetType_RK);CHKERRQ(ierr); 1104 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSRKSetMultirate_C",TSRKSetMultirate_RK);CHKERRQ(ierr); 1105 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSRKGetMultirate_C",TSRKGetMultirate_RK);CHKERRQ(ierr); 1106 1107 ierr = TSRKSetType(ts,TSRKDefault);CHKERRQ(ierr); 1108 rk->dtratio = 1; 1109 PetscFunctionReturn(0); 1110 } 1111