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