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