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