xref: /petsc/src/ts/impls/explicit/rk/rk.c (revision 2e7b7f96234fe412e30f42a61403d5ed8380abcc)
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