xref: /petsc/src/ts/impls/arkimex/arkimex.c (revision bd030d652f5d3cd4109cb5ea0f396aec124820bc)
1 /*
2   Code for timestepping with additive Runge-Kutta IMEX method
3 
4   Notes:
5   The general system is written as
6 
7   F(t,U,Udot) = G(t,U)
8 
9   where F represents the stiff part of the physics and G represents the non-stiff part.
10 
11 */
12 #include <petsc/private/tsimpl.h>                /*I   "petscts.h"   I*/
13 #include <petscdm.h>
14 
15 static TSARKIMEXType  TSARKIMEXDefault = TSARKIMEX3;
16 static PetscBool      TSARKIMEXRegisterAllCalled;
17 static PetscBool      TSARKIMEXPackageInitialized;
18 static PetscErrorCode TSExtrapolate_ARKIMEX(TS,PetscReal,Vec);
19 
20 typedef struct _ARKTableau *ARKTableau;
21 struct _ARKTableau {
22   char      *name;
23   PetscInt  order;                /* Classical approximation order of the method */
24   PetscInt  s;                    /* Number of stages */
25   PetscBool stiffly_accurate;     /* The implicit part is stiffly accurate*/
26   PetscBool FSAL_implicit;        /* The implicit part is FSAL*/
27   PetscBool explicit_first_stage; /* The implicit part has an explicit first stage*/
28   PetscInt  pinterp;              /* Interpolation order */
29   PetscReal *At,*bt,*ct;          /* Stiff tableau */
30   PetscReal *A,*b,*c;             /* Non-stiff tableau */
31   PetscReal *bembedt,*bembed;     /* Embedded formula of order one less (order-1) */
32   PetscReal *binterpt,*binterp;   /* Dense output formula */
33   PetscReal ccfl;                 /* Placeholder for CFL coefficient relative to forward Euler */
34 };
35 typedef struct _ARKTableauLink *ARKTableauLink;
36 struct _ARKTableauLink {
37   struct _ARKTableau tab;
38   ARKTableauLink     next;
39 };
40 static ARKTableauLink ARKTableauList;
41 
42 typedef struct {
43   ARKTableau   tableau;
44   Vec          *Y;               /* States computed during the step */
45   Vec          *YdotI;           /* Time derivatives for the stiff part */
46   Vec          *YdotRHS;         /* Function evaluations for the non-stiff part */
47   Vec          *Y_prev;          /* States computed during the previous time step */
48   Vec          *YdotI_prev;      /* Time derivatives for the stiff part for the previous time step*/
49   Vec          *YdotRHS_prev;    /* Function evaluations for the non-stiff part for the previous time step*/
50   Vec          Ydot0;            /* Holds the slope from the previous step in FSAL case */
51   Vec          Ydot;             /* Work vector holding Ydot during residual evaluation */
52   Vec          Z;                /* Ydot = shift(Y-Z) */
53   PetscScalar  *work;            /* Scalar work */
54   PetscReal    scoeff;           /* shift = scoeff/dt */
55   PetscReal    stage_time;
56   PetscBool    imex;
57   PetscBool    extrapolate;      /* Extrapolate initial guess from previous time-step stage values */
58   TSStepStatus status;
59 } TS_ARKIMEX;
60 /*MC
61      TSARKIMEXARS122 - Second order ARK IMEX scheme.
62 
63      This method has one explicit stage and one implicit stage.
64 
65      References:
66 .   1. -  U. Ascher, S. Ruuth, R. J. Spiteri, Implicit explicit Runge Kutta methods for time dependent Partial Differential Equations. Appl. Numer. Math. 25, (1997).
67 
68      Level: advanced
69 
70 .seealso: TSARKIMEX
71 M*/
72 /*MC
73      TSARKIMEXA2 - Second order ARK IMEX scheme with A-stable implicit part.
74 
75      This method has an explicit stage and one implicit stage, and has an A-stable implicit scheme. This method was provided by Emil Constantinescu.
76 
77      Level: advanced
78 
79 .seealso: TSARKIMEX
80 M*/
81 /*MC
82      TSARKIMEXL2 - Second order ARK IMEX scheme with L-stable implicit part.
83 
84      This method has two implicit stages, and L-stable implicit scheme.
85 
86     References:
87 .   1. -  L. Pareschi, G. Russo, Implicit Explicit Runge Kutta schemes and applications to hyperbolic systems with relaxations. Journal of Scientific Computing Volume: 25, Issue: 1, October, 2005.
88 
89      Level: advanced
90 
91 .seealso: TSARKIMEX
92 M*/
93 /*MC
94      TSARKIMEX1BEE - First order Backward Euler represented as an ARK IMEX scheme with extrapolation as error estimator. This is a 3-stage method.
95 
96      This method is aimed at starting the integration of implicit DAEs when explicit first-stage ARK methods are used.
97 
98      Level: advanced
99 
100 .seealso: TSARKIMEX
101 M*/
102 /*MC
103      TSARKIMEX2C - Second order ARK IMEX scheme with L-stable implicit part.
104 
105      This method has one explicit stage and two implicit stages. The implicit part is the same as in TSARKIMEX2D and TSARKIMEX2E, but the explicit part has a larger stability region on the negative real axis. This method was provided by Emil Constantinescu.
106 
107      Level: advanced
108 
109 .seealso: TSARKIMEX
110 M*/
111 /*MC
112      TSARKIMEX2D - Second order ARK IMEX scheme with L-stable implicit part.
113 
114      This method has one explicit stage and two implicit stages. The stability function is independent of the explicit part in the infinity limit of the implict component. This method was provided by Emil Constantinescu.
115 
116      Level: advanced
117 
118 .seealso: TSARKIMEX
119 M*/
120 /*MC
121      TSARKIMEX2E - Second order ARK IMEX scheme with L-stable implicit part.
122 
123      This method has one explicit stage and two implicit stages. It is is an optimal method developed by Emil Constantinescu.
124 
125      Level: advanced
126 
127 .seealso: TSARKIMEX
128 M*/
129 /*MC
130      TSARKIMEXPRSSP2 - Second order SSP ARK IMEX scheme.
131 
132      This method has three implicit stages.
133 
134      References:
135 .   1. -  L. Pareschi, G. Russo, Implicit Explicit Runge Kutta schemes and applications to hyperbolic systems with relaxations. Journal of Scientific Computing Volume: 25, Issue: 1, October, 2005.
136 
137      This method is referred to as SSP2-(3,3,2) in http://arxiv.org/abs/1110.4375
138 
139      Level: advanced
140 
141 .seealso: TSARKIMEX
142 M*/
143 /*MC
144      TSARKIMEX3 - Third order ARK IMEX scheme with L-stable implicit part.
145 
146      This method has one explicit stage and three implicit stages.
147 
148      References:
149 .   1. -  Kennedy and Carpenter 2003.
150 
151      Level: advanced
152 
153 .seealso: TSARKIMEX
154 M*/
155 /*MC
156      TSARKIMEXARS443 - Third order ARK IMEX scheme.
157 
158      This method has one explicit stage and four implicit stages.
159 
160      References:
161 +   1. -  U. Ascher, S. Ruuth, R. J. Spiteri, Implicit explicit Runge Kutta methods for time dependent Partial Differential Equations. Appl. Numer. Math. 25, (1997).
162 -   2. -  This method is referred to as ARS(4,4,3) in http://arxiv.org/abs/1110.4375
163 
164      Level: advanced
165 
166 .seealso: TSARKIMEX
167 M*/
168 /*MC
169      TSARKIMEXBPR3 - Third order ARK IMEX scheme.
170 
171      This method has one explicit stage and four implicit stages.
172 
173      References:
174  .    This method is referred to as ARK3 in http://arxiv.org/abs/1110.4375
175 
176      Level: advanced
177 
178 .seealso: TSARKIMEX
179 M*/
180 /*MC
181      TSARKIMEX4 - Fourth order ARK IMEX scheme with L-stable implicit part.
182 
183      This method has one explicit stage and four implicit stages.
184 
185      References:
186 .     Kennedy and Carpenter 2003.
187 
188      Level: advanced
189 
190 .seealso: TSARKIMEX
191 M*/
192 /*MC
193      TSARKIMEX5 - Fifth order ARK IMEX scheme with L-stable implicit part.
194 
195      This method has one explicit stage and five implicit stages.
196 
197      References:
198 .     Kennedy and Carpenter 2003.
199 
200      Level: advanced
201 
202 .seealso: TSARKIMEX
203 M*/
204 
205 #undef __FUNCT__
206 #define __FUNCT__ "TSARKIMEXRegisterAll"
207 /*@C
208   TSARKIMEXRegisterAll - Registers all of the additive Runge-Kutta implicit-explicit methods in TSARKIMEX
209 
210   Not Collective, but should be called by all processes which will need the schemes to be registered
211 
212   Level: advanced
213 
214 .keywords: TS, TSARKIMEX, register, all
215 
216 .seealso:  TSARKIMEXRegisterDestroy()
217 @*/
218 PetscErrorCode TSARKIMEXRegisterAll(void)
219 {
220   PetscErrorCode ierr;
221 
222   PetscFunctionBegin;
223   if (TSARKIMEXRegisterAllCalled) PetscFunctionReturn(0);
224   TSARKIMEXRegisterAllCalled = PETSC_TRUE;
225 
226   {
227     const PetscReal
228       A[3][3] = {{0.0,0.0,0.0},
229                  {0.0,0.0,0.0},
230                  {0.0,0.5,0.0}},
231       At[3][3] = {{1.0,0.0,0.0},
232                   {0.0,0.5,0.0},
233                   {0.0,0.5,0.5}},
234       b[3]       = {0.0,0.5,0.5},
235       bembedt[3] = {1.0,0.0,0.0};
236     ierr = TSARKIMEXRegister(TSARKIMEX1BEE,2,3,&At[0][0],b,NULL,&A[0][0],b,NULL,bembedt,bembedt,1,b,NULL);CHKERRQ(ierr);
237   }
238   {
239     const PetscReal
240       A[2][2] = {{0.0,0.0},
241                  {0.5,0.0}},
242       At[2][2] = {{0.0,0.0},
243                   {0.0,0.5}},
244       b[2]       = {0.0,1.0},
245       bembedt[2] = {0.5,0.5};
246     /* binterpt[2][2] = {{1.0,-1.0},{0.0,1.0}};  second order dense output has poor stability properties and hence it is not currently in use*/
247     ierr = TSARKIMEXRegister(TSARKIMEXARS122,2,2,&At[0][0],b,NULL,&A[0][0],b,NULL,bembedt,bembedt,1,b,NULL);CHKERRQ(ierr);
248   }
249   {
250     const PetscReal
251       A[2][2] = {{0.0,0.0},
252                  {1.0,0.0}},
253       At[2][2] = {{0.0,0.0},
254                   {0.5,0.5}},
255       b[2]       = {0.5,0.5},
256       bembedt[2] = {0.0,1.0};
257     /* binterpt[2][2] = {{1.0,-0.5},{0.0,0.5}}  second order dense output has poor stability properties and hence it is not currently in use*/
258     ierr = TSARKIMEXRegister(TSARKIMEXA2,2,2,&At[0][0],b,NULL,&A[0][0],b,NULL,bembedt,bembedt,1,b,NULL);CHKERRQ(ierr);
259   }
260   {
261     /* const PetscReal us2 = 1.0-1.0/PetscSqrtReal((PetscReal)2.0);    Direct evaluation: 0.2928932188134524755992. Used below to ensure all values are available at compile time   */
262     const PetscReal
263       A[2][2] = {{0.0,0.0},
264                  {1.0,0.0}},
265       At[2][2] = {{0.2928932188134524755992,0.0},
266                   {1.0-2.0*0.2928932188134524755992,0.2928932188134524755992}},
267       b[2]       = {0.5,0.5},
268       bembedt[2] = {0.0,1.0},
269       binterpt[2][2] = {{  (0.2928932188134524755992-1.0)/(2.0*0.2928932188134524755992-1.0),-1/(2.0*(1.0-2.0*0.2928932188134524755992))},
270                         {1-(0.2928932188134524755992-1.0)/(2.0*0.2928932188134524755992-1.0),-1/(2.0*(1.0-2.0*0.2928932188134524755992))}},
271       binterp[2][2] = {{1.0,-0.5},{0.0,0.5}};
272     ierr = TSARKIMEXRegister(TSARKIMEXL2,2,2,&At[0][0],b,NULL,&A[0][0],b,NULL,bembedt,bembedt,2,binterpt[0],binterp[0]);CHKERRQ(ierr);
273   }
274   {
275     /* const PetscReal s2 = PetscSqrtReal((PetscReal)2.0),  Direct evaluation: 1.414213562373095048802. Used below to ensure all values are available at compile time   */
276     const PetscReal
277       A[3][3] = {{0,0,0},
278                  {2-1.414213562373095048802,0,0},
279                  {0.5,0.5,0}},
280       At[3][3] = {{0,0,0},
281                   {1-1/1.414213562373095048802,1-1/1.414213562373095048802,0},
282                   {1/(2*1.414213562373095048802),1/(2*1.414213562373095048802),1-1/1.414213562373095048802}},
283       bembedt[3] = {(4.-1.414213562373095048802)/8.,(4.-1.414213562373095048802)/8.,1/(2.*1.414213562373095048802)},
284       binterpt[3][2] = {{1.0/1.414213562373095048802,-1.0/(2.0*1.414213562373095048802)},
285                         {1.0/1.414213562373095048802,-1.0/(2.0*1.414213562373095048802)},
286                         {1.0-1.414213562373095048802,1.0/1.414213562373095048802}};
287     ierr = TSARKIMEXRegister(TSARKIMEX2C,2,3,&At[0][0],NULL,NULL,&A[0][0],NULL,NULL,bembedt,bembedt,2,binterpt[0],NULL);CHKERRQ(ierr);
288   }
289   {
290     /* const PetscReal s2 = PetscSqrtReal((PetscReal)2.0),  Direct evaluation: 1.414213562373095048802. Used below to ensure all values are available at compile time   */
291     const PetscReal
292       A[3][3] = {{0,0,0},
293                  {2-1.414213562373095048802,0,0},
294                  {0.75,0.25,0}},
295       At[3][3] = {{0,0,0},
296                   {1-1/1.414213562373095048802,1-1/1.414213562373095048802,0},
297                   {1/(2*1.414213562373095048802),1/(2*1.414213562373095048802),1-1/1.414213562373095048802}},
298       bembedt[3] = {(4.-1.414213562373095048802)/8.,(4.-1.414213562373095048802)/8.,1/(2.*1.414213562373095048802)},
299       binterpt[3][2] =  {{1.0/1.414213562373095048802,-1.0/(2.0*1.414213562373095048802)},
300                          {1.0/1.414213562373095048802,-1.0/(2.0*1.414213562373095048802)},
301                          {1.0-1.414213562373095048802,1.0/1.414213562373095048802}};
302     ierr = TSARKIMEXRegister(TSARKIMEX2D,2,3,&At[0][0],NULL,NULL,&A[0][0],NULL,NULL,bembedt,bembedt,2,binterpt[0],NULL);CHKERRQ(ierr);
303   }
304   {                             /* Optimal for linear implicit part */
305     /* const PetscReal s2 = PetscSqrtReal((PetscReal)2.0),  Direct evaluation: 1.414213562373095048802. Used below to ensure all values are available at compile time   */
306     const PetscReal
307       A[3][3] = {{0,0,0},
308                  {2-1.414213562373095048802,0,0},
309                  {(3-2*1.414213562373095048802)/6,(3+2*1.414213562373095048802)/6,0}},
310       At[3][3] = {{0,0,0},
311                   {1-1/1.414213562373095048802,1-1/1.414213562373095048802,0},
312                   {1/(2*1.414213562373095048802),1/(2*1.414213562373095048802),1-1/1.414213562373095048802}},
313       bembedt[3] = {(4.-1.414213562373095048802)/8.,(4.-1.414213562373095048802)/8.,1/(2.*1.414213562373095048802)},
314       binterpt[3][2] =  {{1.0/1.414213562373095048802,-1.0/(2.0*1.414213562373095048802)},
315                          {1.0/1.414213562373095048802,-1.0/(2.0*1.414213562373095048802)},
316                          {1.0-1.414213562373095048802,1.0/1.414213562373095048802}};
317     ierr = TSARKIMEXRegister(TSARKIMEX2E,2,3,&At[0][0],NULL,NULL,&A[0][0],NULL,NULL,bembedt,bembedt,2,binterpt[0],NULL);CHKERRQ(ierr);
318   }
319   {                             /* Optimal for linear implicit part */
320     const PetscReal
321       A[3][3] = {{0,0,0},
322                  {0.5,0,0},
323                  {0.5,0.5,0}},
324       At[3][3] = {{0.25,0,0},
325                   {0,0.25,0},
326                   {1./3,1./3,1./3}};
327     ierr = TSARKIMEXRegister(TSARKIMEXPRSSP2,2,3,&At[0][0],NULL,NULL,&A[0][0],NULL,NULL,NULL,NULL,0,NULL,NULL);CHKERRQ(ierr);
328   }
329   {
330     const PetscReal
331       A[4][4] = {{0,0,0,0},
332                  {1767732205903./2027836641118.,0,0,0},
333                  {5535828885825./10492691773637.,788022342437./10882634858940.,0,0},
334                  {6485989280629./16251701735622.,-4246266847089./9704473918619.,10755448449292./10357097424841.,0}},
335       At[4][4] = {{0,0,0,0},
336                   {1767732205903./4055673282236.,1767732205903./4055673282236.,0,0},
337                   {2746238789719./10658868560708.,-640167445237./6845629431997.,1767732205903./4055673282236.,0},
338                   {1471266399579./7840856788654.,-4482444167858./7529755066697.,11266239266428./11593286722821.,1767732205903./4055673282236.}},
339       bembedt[4]     = {2756255671327./12835298489170.,-10771552573575./22201958757719.,9247589265047./10645013368117.,2193209047091./5459859503100.},
340       binterpt[4][2] = {{4655552711362./22874653954995., -215264564351./13552729205753.},
341                         {-18682724506714./9892148508045.,17870216137069./13817060693119.},
342                         {34259539580243./13192909600954.,-28141676662227./17317692491321.},
343                         {584795268549./6622622206610.,   2508943948391./7218656332882.}};
344     ierr = TSARKIMEXRegister(TSARKIMEX3,3,4,&At[0][0],NULL,NULL,&A[0][0],NULL,NULL,bembedt,bembedt,2,binterpt[0],NULL);CHKERRQ(ierr);
345   }
346   {
347     const PetscReal
348       A[5][5] = {{0,0,0,0,0},
349                  {1./2,0,0,0,0},
350                  {11./18,1./18,0,0,0},
351                  {5./6,-5./6,.5,0,0},
352                  {1./4,7./4,3./4,-7./4,0}},
353       At[5][5] = {{0,0,0,0,0},
354                   {0,1./2,0,0,0},
355                   {0,1./6,1./2,0,0},
356                   {0,-1./2,1./2,1./2,0},
357                   {0,3./2,-3./2,1./2,1./2}},
358     *bembedt = NULL;
359     ierr = TSARKIMEXRegister(TSARKIMEXARS443,3,5,&At[0][0],NULL,NULL,&A[0][0],NULL,NULL,bembedt,bembedt,0,NULL,NULL);CHKERRQ(ierr);
360   }
361   {
362     const PetscReal
363       A[5][5] = {{0,0,0,0,0},
364                  {1,0,0,0,0},
365                  {4./9,2./9,0,0,0},
366                  {1./4,0,3./4,0,0},
367                  {1./4,0,3./5,0,0}},
368       At[5][5] = {{0,0,0,0,0},
369                   {.5,.5,0,0,0},
370                   {5./18,-1./9,.5,0,0},
371                   {.5,0,0,.5,0},
372                   {.25,0,.75,-.5,.5}},
373     *bembedt = NULL;
374     ierr = TSARKIMEXRegister(TSARKIMEXBPR3,3,5,&At[0][0],NULL,NULL,&A[0][0],NULL,NULL,bembedt,bembedt,0,NULL,NULL);CHKERRQ(ierr);
375   }
376   {
377     const PetscReal
378       A[6][6] = {{0,0,0,0,0,0},
379                  {1./2,0,0,0,0,0},
380                  {13861./62500.,6889./62500.,0,0,0,0},
381                  {-116923316275./2393684061468.,-2731218467317./15368042101831.,9408046702089./11113171139209.,0,0,0},
382                  {-451086348788./2902428689909.,-2682348792572./7519795681897.,12662868775082./11960479115383.,3355817975965./11060851509271.,0,0},
383                  {647845179188./3216320057751.,73281519250./8382639484533.,552539513391./3454668386233.,3354512671639./8306763924573.,4040./17871.,0}},
384       At[6][6] = {{0,0,0,0,0,0},
385                   {1./4,1./4,0,0,0,0},
386                   {8611./62500.,-1743./31250.,1./4,0,0,0},
387                   {5012029./34652500.,-654441./2922500.,174375./388108.,1./4,0,0},
388                   {15267082809./155376265600.,-71443401./120774400.,730878875./902184768.,2285395./8070912.,1./4,0},
389                   {82889./524892.,0,15625./83664.,69875./102672.,-2260./8211,1./4}},
390       bembedt[6]     = {4586570599./29645900160.,0,178811875./945068544.,814220225./1159782912.,-3700637./11593932.,61727./225920.},
391       binterpt[6][3] = {{6943876665148./7220017795957.,-54480133./30881146.,6818779379841./7100303317025.},
392                         {0,0,0},
393                         {7640104374378./9702883013639.,-11436875./14766696.,2173542590792./12501825683035.},
394                         {-20649996744609./7521556579894.,174696575./18121608.,-31592104683404./5083833661969.},
395                         {8854892464581./2390941311638.,-12120380./966161.,61146701046299./7138195549469.},
396                         {-11397109935349./6675773540249.,3843./706.,-17219254887155./4939391667607.}};
397     ierr = TSARKIMEXRegister(TSARKIMEX4,4,6,&At[0][0],NULL,NULL,&A[0][0],NULL,NULL,bembedt,bembedt,3,binterpt[0],NULL);CHKERRQ(ierr);
398   }
399   {
400     const PetscReal
401       A[8][8] = {{0,0,0,0,0,0,0,0},
402                  {41./100,0,0,0,0,0,0,0},
403                  {367902744464./2072280473677.,677623207551./8224143866563.,0,0,0,0,0,0},
404                  {1268023523408./10340822734521.,0,1029933939417./13636558850479.,0,0,0,0,0},
405                  {14463281900351./6315353703477.,0,66114435211212./5879490589093.,-54053170152839./4284798021562.,0,0,0,0},
406                  {14090043504691./34967701212078.,0,15191511035443./11219624916014.,-18461159152457./12425892160975.,-281667163811./9011619295870.,0,0,0},
407                  {19230459214898./13134317526959.,0,21275331358303./2942455364971.,-38145345988419./4862620318723.,-1./8,-1./8,0,0},
408                  {-19977161125411./11928030595625.,0,-40795976796054./6384907823539.,177454434618887./12078138498510.,782672205425./8267701900261.,-69563011059811./9646580694205.,7356628210526./4942186776405.,0}},
409       At[8][8] = {{0,0,0,0,0,0,0,0},
410                   {41./200.,41./200.,0,0,0,0,0,0},
411                   {41./400.,-567603406766./11931857230679.,41./200.,0,0,0,0,0},
412                   {683785636431./9252920307686.,0,-110385047103./1367015193373.,41./200.,0,0,0,0},
413                   {3016520224154./10081342136671.,0,30586259806659./12414158314087.,-22760509404356./11113319521817.,41./200.,0,0,0},
414                   {218866479029./1489978393911.,0,638256894668./5436446318841.,-1179710474555./5321154724896.,-60928119172./8023461067671.,41./200.,0,0},
415                   {1020004230633./5715676835656.,0,25762820946817./25263940353407.,-2161375909145./9755907335909.,-211217309593./5846859502534.,-4269925059573./7827059040749.,41./200,0},
416                   {-872700587467./9133579230613.,0,0,22348218063261./9555858737531.,-1143369518992./8141816002931.,-39379526789629./19018526304540.,32727382324388./42900044865799.,41./200.}},
417       bembedt[8]     = {-975461918565./9796059967033.,0,0,78070527104295./32432590147079.,-548382580838./3424219808633.,-33438840321285./15594753105479.,3629800801594./4656183773603.,4035322873751./18575991585200.},
418       binterpt[8][3] = {{-17674230611817./10670229744614.,  43486358583215./12773830924787., -9257016797708./5021505065439.},
419                         {0,  0, 0                            },
420                         {0,  0, 0                            },
421                         {65168852399939./7868540260826.,  -91478233927265./11067650958493., 26096422576131./11239449250142.},
422                         {15494834004392./5936557850923.,  -79368583304911./10890268929626., 92396832856987./20362823103730.},
423                         {-99329723586156./26959484932159.,  -12239297817655./9152339842473., 30029262896817./10175596800299.},
424                         {-19024464361622./5461577185407.,  115839755401235./10719374521269., -26136350496073./3983972220547.},
425                         {-6511271360970./6095937251113.,  5843115559534./2180450260947., -5289405421727./3760307252460. }};
426     ierr = TSARKIMEXRegister(TSARKIMEX5,5,8,&At[0][0],NULL,NULL,&A[0][0],NULL,NULL,bembedt,bembedt,3,binterpt[0],NULL);CHKERRQ(ierr);
427   }
428   PetscFunctionReturn(0);
429 }
430 
431 #undef __FUNCT__
432 #define __FUNCT__ "TSARKIMEXRegisterDestroy"
433 /*@C
434    TSARKIMEXRegisterDestroy - Frees the list of schemes that were registered by TSARKIMEXRegister().
435 
436    Not Collective
437 
438    Level: advanced
439 
440 .keywords: TSARKIMEX, register, destroy
441 .seealso: TSARKIMEXRegister(), TSARKIMEXRegisterAll()
442 @*/
443 PetscErrorCode TSARKIMEXRegisterDestroy(void)
444 {
445   PetscErrorCode ierr;
446   ARKTableauLink link;
447 
448   PetscFunctionBegin;
449   while ((link = ARKTableauList)) {
450     ARKTableau t = &link->tab;
451     ARKTableauList = link->next;
452     ierr = PetscFree6(t->At,t->bt,t->ct,t->A,t->b,t->c);CHKERRQ(ierr);
453     ierr = PetscFree2(t->bembedt,t->bembed);CHKERRQ(ierr);
454     ierr = PetscFree2(t->binterpt,t->binterp);CHKERRQ(ierr);
455     ierr = PetscFree(t->name);CHKERRQ(ierr);
456     ierr = PetscFree(link);CHKERRQ(ierr);
457   }
458   TSARKIMEXRegisterAllCalled = PETSC_FALSE;
459   PetscFunctionReturn(0);
460 }
461 
462 #undef __FUNCT__
463 #define __FUNCT__ "TSARKIMEXInitializePackage"
464 /*@C
465   TSARKIMEXInitializePackage - This function initializes everything in the TSARKIMEX package. It is called
466   from PetscDLLibraryRegister() when using dynamic libraries, and on the first call to TSCreate_ARKIMEX()
467   when using static libraries.
468 
469   Level: developer
470 
471 .keywords: TS, TSARKIMEX, initialize, package
472 .seealso: PetscInitialize()
473 @*/
474 PetscErrorCode TSARKIMEXInitializePackage(void)
475 {
476   PetscErrorCode ierr;
477 
478   PetscFunctionBegin;
479   if (TSARKIMEXPackageInitialized) PetscFunctionReturn(0);
480   TSARKIMEXPackageInitialized = PETSC_TRUE;
481   ierr = TSARKIMEXRegisterAll();CHKERRQ(ierr);
482   ierr = PetscRegisterFinalize(TSARKIMEXFinalizePackage);CHKERRQ(ierr);
483   PetscFunctionReturn(0);
484 }
485 
486 #undef __FUNCT__
487 #define __FUNCT__ "TSARKIMEXFinalizePackage"
488 /*@C
489   TSARKIMEXFinalizePackage - This function destroys everything in the TSARKIMEX package. It is
490   called from PetscFinalize().
491 
492   Level: developer
493 
494 .keywords: Petsc, destroy, package
495 .seealso: PetscFinalize()
496 @*/
497 PetscErrorCode TSARKIMEXFinalizePackage(void)
498 {
499   PetscErrorCode ierr;
500 
501   PetscFunctionBegin;
502   TSARKIMEXPackageInitialized = PETSC_FALSE;
503   ierr = TSARKIMEXRegisterDestroy();CHKERRQ(ierr);
504   PetscFunctionReturn(0);
505 }
506 
507 #undef __FUNCT__
508 #define __FUNCT__ "TSARKIMEXRegister"
509 /*@C
510    TSARKIMEXRegister - register an ARK IMEX scheme by providing the entries in the Butcher tableau and optionally embedded approximations and interpolation
511 
512    Not Collective, but the same schemes should be registered on all processes on which they will be used
513 
514    Input Parameters:
515 +  name - identifier for method
516 .  order - approximation order of method
517 .  s - number of stages, this is the dimension of the matrices below
518 .  At - Butcher table of stage coefficients for stiff part (dimension s*s, row-major)
519 .  bt - Butcher table for completing the stiff part of the step (dimension s; NULL to use the last row of At)
520 .  ct - Abscissa of each stiff stage (dimension s, NULL to use row sums of At)
521 .  A - Non-stiff stage coefficients (dimension s*s, row-major)
522 .  b - Non-stiff step completion table (dimension s; NULL to use last row of At)
523 .  c - Non-stiff abscissa (dimension s; NULL to use row sums of A)
524 .  bembedt - Stiff part of completion table for embedded method (dimension s; NULL if not available)
525 .  bembed - Non-stiff part of completion table for embedded method (dimension s; NULL to use bembedt if provided)
526 .  pinterp - Order of the interpolation scheme, equal to the number of columns of binterpt and binterp
527 .  binterpt - Coefficients of the interpolation formula for the stiff part (dimension s*pinterp)
528 -  binterp - Coefficients of the interpolation formula for the non-stiff part (dimension s*pinterp; NULL to reuse binterpt)
529 
530    Notes:
531    Several ARK IMEX methods are provided, this function is only needed to create new methods.
532 
533    Level: advanced
534 
535 .keywords: TS, register
536 
537 .seealso: TSARKIMEX
538 @*/
539 PetscErrorCode TSARKIMEXRegister(TSARKIMEXType name,PetscInt order,PetscInt s,
540                                  const PetscReal At[],const PetscReal bt[],const PetscReal ct[],
541                                  const PetscReal A[],const PetscReal b[],const PetscReal c[],
542                                  const PetscReal bembedt[],const PetscReal bembed[],
543                                  PetscInt pinterp,const PetscReal binterpt[],const PetscReal binterp[])
544 {
545   PetscErrorCode ierr;
546   ARKTableauLink link;
547   ARKTableau     t;
548   PetscInt       i,j;
549 
550   PetscFunctionBegin;
551   ierr     = PetscCalloc1(1,&link);CHKERRQ(ierr);
552   t        = &link->tab;
553   ierr     = PetscStrallocpy(name,&t->name);CHKERRQ(ierr);
554   t->order = order;
555   t->s     = s;
556   ierr     = PetscMalloc6(s*s,&t->At,s,&t->bt,s,&t->ct,s*s,&t->A,s,&t->b,s,&t->c);CHKERRQ(ierr);
557   ierr     = PetscMemcpy(t->At,At,s*s*sizeof(At[0]));CHKERRQ(ierr);
558   ierr     = PetscMemcpy(t->A,A,s*s*sizeof(A[0]));CHKERRQ(ierr);
559   if (bt) { ierr = PetscMemcpy(t->bt,bt,s*sizeof(bt[0]));CHKERRQ(ierr); }
560   else for (i=0; i<s; i++) t->bt[i] = At[(s-1)*s+i];
561   if (b)  { ierr = PetscMemcpy(t->b,b,s*sizeof(b[0]));CHKERRQ(ierr); }
562   else for (i=0; i<s; i++) t->b[i] = t->bt[i];
563   if (ct) { ierr = PetscMemcpy(t->ct,ct,s*sizeof(ct[0]));CHKERRQ(ierr); }
564   else for (i=0; i<s; i++) for (j=0,t->ct[i]=0; j<s; j++) t->ct[i] += At[i*s+j];
565   if (c)  { ierr = PetscMemcpy(t->c,c,s*sizeof(c[0]));CHKERRQ(ierr); }
566   else for (i=0; i<s; i++) for (j=0,t->c[i]=0; j<s; j++) t->c[i] += A[i*s+j];
567   t->stiffly_accurate = PETSC_TRUE;
568   for (i=0; i<s; i++) if (t->At[(s-1)*s+i] != t->bt[i]) t->stiffly_accurate = PETSC_FALSE;
569   t->explicit_first_stage = PETSC_TRUE;
570   for (i=0; i<s; i++) if (t->At[i] != 0.0) t->explicit_first_stage = PETSC_FALSE;
571   /*def of FSAL can be made more precise*/
572   t->FSAL_implicit = (PetscBool)(t->explicit_first_stage && t->stiffly_accurate);
573   if (bembedt) {
574     ierr = PetscMalloc2(s,&t->bembedt,s,&t->bembed);CHKERRQ(ierr);
575     ierr = PetscMemcpy(t->bembedt,bembedt,s*sizeof(bembedt[0]));CHKERRQ(ierr);
576     ierr = PetscMemcpy(t->bembed,bembed ? bembed : bembedt,s*sizeof(bembed[0]));CHKERRQ(ierr);
577   }
578 
579   t->pinterp     = pinterp;
580   ierr           = PetscMalloc2(s*pinterp,&t->binterpt,s*pinterp,&t->binterp);CHKERRQ(ierr);
581   ierr           = PetscMemcpy(t->binterpt,binterpt,s*pinterp*sizeof(binterpt[0]));CHKERRQ(ierr);
582   ierr           = PetscMemcpy(t->binterp,binterp ? binterp : binterpt,s*pinterp*sizeof(binterpt[0]));CHKERRQ(ierr);
583   link->next     = ARKTableauList;
584   ARKTableauList = link;
585   PetscFunctionReturn(0);
586 }
587 
588 #undef __FUNCT__
589 #define __FUNCT__ "TSEvaluateStep_ARKIMEX"
590 /*
591  The step completion formula is
592 
593  x1 = x0 - h bt^T YdotI + h b^T YdotRHS
594 
595  This function can be called before or after ts->vec_sol has been updated.
596  Suppose we have a completion formula (bt,b) and an embedded formula (bet,be) of different order.
597  We can write
598 
599  x1e = x0 - h bet^T YdotI + h be^T YdotRHS
600      = x1 + h bt^T YdotI - h b^T YdotRHS - h bet^T YdotI + h be^T YdotRHS
601      = x1 - h (bet - bt)^T YdotI + h (be - b)^T YdotRHS
602 
603  so we can evaluate the method with different order even after the step has been optimistically completed.
604 */
605 static PetscErrorCode TSEvaluateStep_ARKIMEX(TS ts,PetscInt order,Vec X,PetscBool *done)
606 {
607   TS_ARKIMEX     *ark = (TS_ARKIMEX*)ts->data;
608   ARKTableau     tab  = ark->tableau;
609   PetscScalar    *w   = ark->work;
610   PetscReal      h;
611   PetscInt       s = tab->s,j;
612   PetscErrorCode ierr;
613 
614   PetscFunctionBegin;
615   switch (ark->status) {
616   case TS_STEP_INCOMPLETE:
617   case TS_STEP_PENDING:
618     h = ts->time_step; break;
619   case TS_STEP_COMPLETE:
620     h = ts->ptime - ts->ptime_prev; break;
621   default: SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_PLIB,"Invalid TSStepStatus");
622   }
623   if (order == tab->order) {
624     if (ark->status == TS_STEP_INCOMPLETE) {
625       if (!ark->imex && tab->stiffly_accurate) { /* Only the stiffly accurate implicit formula is used */
626         ierr = VecCopy(ark->Y[s-1],X);CHKERRQ(ierr);
627       } else { /* Use the standard completion formula (bt,b) */
628         ierr = VecCopy(ts->vec_sol,X);CHKERRQ(ierr);
629         for (j=0; j<s; j++) w[j] = h*tab->bt[j];
630         ierr = VecMAXPY(X,s,w,ark->YdotI);CHKERRQ(ierr);
631         if (ark->imex) { /* Method is IMEX, complete the explicit formula */
632           for (j=0; j<s; j++) w[j] = h*tab->b[j];
633           ierr = VecMAXPY(X,s,w,ark->YdotRHS);CHKERRQ(ierr);
634         }
635       }
636     } else {ierr = VecCopy(ts->vec_sol,X);CHKERRQ(ierr);}
637     if (done) *done = PETSC_TRUE;
638     PetscFunctionReturn(0);
639   } else if (order == tab->order-1) {
640     if (!tab->bembedt) goto unavailable;
641     if (ark->status == TS_STEP_INCOMPLETE) { /* Complete with the embedded method (bet,be) */
642       ierr = VecCopy(ts->vec_sol,X);CHKERRQ(ierr);
643       for (j=0; j<s; j++) w[j] = h*tab->bembedt[j];
644       ierr = VecMAXPY(X,s,w,ark->YdotI);CHKERRQ(ierr);
645       for (j=0; j<s; j++) w[j] = h*tab->bembed[j];
646       ierr = VecMAXPY(X,s,w,ark->YdotRHS);CHKERRQ(ierr);
647     } else { /* Rollback and re-complete using (bet-be,be-b) */
648       ierr = VecCopy(ts->vec_sol,X);CHKERRQ(ierr);
649       for (j=0; j<s; j++) w[j] = h*(tab->bembedt[j] - tab->bt[j]);
650       ierr = VecMAXPY(X,tab->s,w,ark->YdotI);CHKERRQ(ierr);
651       for (j=0; j<s; j++) w[j] = h*(tab->bembed[j] - tab->b[j]);
652       ierr = VecMAXPY(X,s,w,ark->YdotRHS);CHKERRQ(ierr);
653     }
654     if (done) *done = PETSC_TRUE;
655     PetscFunctionReturn(0);
656   }
657 unavailable:
658   if (done) *done = PETSC_FALSE;
659   else SETERRQ3(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"ARKIMEX '%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);
660   PetscFunctionReturn(0);
661 }
662 
663 #undef __FUNCT__
664 #define __FUNCT__ "TSRollBack_ARKIMEX"
665 static PetscErrorCode TSRollBack_ARKIMEX(TS ts)
666 {
667   TS_ARKIMEX      *ark = (TS_ARKIMEX*)ts->data;
668   ARKTableau      tab  = ark->tableau;
669   const PetscInt  s    = tab->s;
670   const PetscReal *bt  = tab->bt,*b = tab->b;
671   PetscScalar     *w   = ark->work;
672   Vec             *YdotI = ark->YdotI,*YdotRHS = ark->YdotRHS;
673   PetscInt        j;
674   PetscReal       h;
675   PetscErrorCode  ierr;
676 
677   PetscFunctionBegin;
678   switch (ark->status) {
679   case TS_STEP_INCOMPLETE:
680   case TS_STEP_PENDING:
681     h = ts->time_step; break;
682   case TS_STEP_COMPLETE:
683     h = ts->ptime - ts->ptime_prev; break;
684   default: SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_PLIB,"Invalid TSStepStatus");
685   }
686   for (j=0; j<s; j++) w[j] = -h*bt[j];
687   ierr = VecMAXPY(ts->vec_sol,s,w,YdotI);CHKERRQ(ierr);
688   for (j=0; j<s; j++) w[j] = -h*b[j];
689   ierr = VecMAXPY(ts->vec_sol,s,w,YdotRHS);CHKERRQ(ierr);
690   PetscFunctionReturn(0);
691 }
692 
693 #undef __FUNCT__
694 #define __FUNCT__ "TSStep_ARKIMEX"
695 static PetscErrorCode TSStep_ARKIMEX(TS ts)
696 {
697   TS_ARKIMEX      *ark = (TS_ARKIMEX*)ts->data;
698   ARKTableau      tab  = ark->tableau;
699   const PetscInt  s    = tab->s;
700   const PetscReal *At  = tab->At,*A = tab->A,*ct = tab->ct,*c = tab->c;
701   PetscScalar     *w   = ark->work;
702   Vec             *Y   = ark->Y,*YdotI = ark->YdotI,*YdotRHS = ark->YdotRHS,Ydot = ark->Ydot,Ydot0 = ark->Ydot0,Z = ark->Z;
703   PetscBool       extrapolate = ark->extrapolate;
704   TSAdapt         adapt;
705   SNES            snes;
706   PetscInt        i,j,its,lits;
707   PetscInt        rejections = 0;
708   PetscBool       stageok,accept = PETSC_TRUE;
709   PetscReal       next_time_step = ts->time_step;
710   PetscErrorCode  ierr;
711 
712   PetscFunctionBegin;
713   if (ark->extrapolate && !ark->Y_prev) {
714     ierr = VecDuplicateVecs(ts->vec_sol,tab->s,&ark->Y_prev);CHKERRQ(ierr);
715     ierr = VecDuplicateVecs(ts->vec_sol,tab->s,&ark->YdotI_prev);CHKERRQ(ierr);
716     ierr = VecDuplicateVecs(ts->vec_sol,tab->s,&ark->YdotRHS_prev);CHKERRQ(ierr);
717   }
718 
719   if (!ts->steprollback) {
720     if (ts->equation_type >= TS_EQ_IMPLICIT) { /* Save the initial slope for the next step */
721       ierr = VecCopy(YdotI[s-1],Ydot0);CHKERRQ(ierr);
722     }
723     if (ark->extrapolate && !ts->steprestart) { /* Save the Y, YdotI, YdotRHS for extrapolation initial guess */
724       for (i = 0; i<s; i++) {
725         ierr = VecCopy(Y[i],ark->Y_prev[i]);CHKERRQ(ierr);
726         ierr = VecCopy(YdotRHS[i],ark->YdotRHS_prev[i]);CHKERRQ(ierr);
727         ierr = VecCopy(YdotI[i],ark->YdotI_prev[i]);CHKERRQ(ierr);
728       }
729     }
730   }
731 
732   if (ts->equation_type >= TS_EQ_IMPLICIT && tab->explicit_first_stage && ts->steprestart) {
733     TS ts_start;
734     ierr = TSClone(ts,&ts_start);CHKERRQ(ierr);
735     ierr = TSSetSolution(ts_start,ts->vec_sol);CHKERRQ(ierr);
736     ierr = TSSetTime(ts_start,ts->ptime);CHKERRQ(ierr);
737     ierr = TSSetDuration(ts_start,1,ts->ptime+ts->time_step);CHKERRQ(ierr);
738     ierr = TSSetExactFinalTime(ts_start,TS_EXACTFINALTIME_STEPOVER);CHKERRQ(ierr);
739     ierr = TSSetTimeStep(ts_start,ts->time_step);CHKERRQ(ierr);
740     ierr = TSSetType(ts_start,TSARKIMEX);CHKERRQ(ierr);
741     ierr = TSARKIMEXSetFullyImplicit(ts_start,PETSC_TRUE);CHKERRQ(ierr);
742     ierr = TSARKIMEXSetType(ts_start,TSARKIMEX1BEE);CHKERRQ(ierr);
743 
744     ts_start->steprestart = PETSC_TRUE;
745     ierr = TSSolve(ts_start,ts->vec_sol);CHKERRQ(ierr);
746     ierr = TSGetTime(ts_start,&ts->ptime);CHKERRQ(ierr);
747     ierr = TSGetTimeStep(ts_start,&ts->time_step);CHKERRQ(ierr);
748 
749     { /* Save the initial slope for the next step */
750       TS_ARKIMEX *ark_start = (TS_ARKIMEX*)ts_start->data;
751       ierr = VecCopy(ark_start->YdotI[ark_start->tableau->s-1],Ydot0);CHKERRQ(ierr);
752     }
753     ts->steps++;
754     ts->total_steps++;
755 
756     /* Set the correct TS in SNES */
757     /* We'll try to bypass this by changing the method on the fly */
758     {
759       ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
760       ierr = TSSetSNES(ts,snes);CHKERRQ(ierr);
761     }
762     ierr = TSDestroy(&ts_start);CHKERRQ(ierr);
763   }
764 
765   ark->status = TS_STEP_INCOMPLETE;
766   while (!ts->reason && ark->status != TS_STEP_COMPLETE) {
767     PetscReal t = ts->ptime;
768     PetscReal h = ts->time_step;
769     for (i=0; i<s; i++) {
770       ark->stage_time = t + h*ct[i];
771       ierr = TSPreStage(ts,ark->stage_time);CHKERRQ(ierr);
772       if (At[i*s+i] == 0) { /* This stage is explicit */
773         if (i!=0 && ts->equation_type >= TS_EQ_IMPLICIT) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Explicit stages other than the first one are not supported for implicit problems");
774         ierr = VecCopy(ts->vec_sol,Y[i]);CHKERRQ(ierr);
775         for (j=0; j<i; j++) w[j] = h*At[i*s+j];
776         ierr = VecMAXPY(Y[i],i,w,YdotI);CHKERRQ(ierr);
777         for (j=0; j<i; j++) w[j] = h*A[i*s+j];
778         ierr = VecMAXPY(Y[i],i,w,YdotRHS);CHKERRQ(ierr);
779       } else {
780         ark->scoeff = 1./At[i*s+i];
781         /* Ydot = shift*(Y-Z) */
782         ierr = VecCopy(ts->vec_sol,Z);CHKERRQ(ierr);
783         for (j=0; j<i; j++) w[j] = h*At[i*s+j];
784         ierr = VecMAXPY(Z,i,w,YdotI);CHKERRQ(ierr);
785         for (j=0; j<i; j++) w[j] = h*A[i*s+j];
786         ierr = VecMAXPY(Z,i,w,YdotRHS);CHKERRQ(ierr);
787         if (extrapolate && !ts->steprestart) {
788           /* Initial guess extrapolated from previous time step stage values */
789           ierr = TSExtrapolate_ARKIMEX(ts,c[i],Y[i]);CHKERRQ(ierr);
790         } else {
791           /* Initial guess taken from last stage */
792           ierr = VecCopy(i>0 ? Y[i-1] : ts->vec_sol,Y[i]);CHKERRQ(ierr);
793         }
794         ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
795         ierr = SNESSolve(snes,NULL,Y[i]);CHKERRQ(ierr);
796         ierr = SNESGetIterationNumber(snes,&its);CHKERRQ(ierr);
797         ierr = SNESGetLinearSolveIterations(snes,&lits);CHKERRQ(ierr);
798         ts->snes_its += its; ts->ksp_its += lits;
799         ierr = TSGetAdapt(ts,&adapt);CHKERRQ(ierr);
800         ierr = TSAdaptCheckStage(adapt,ts,ark->stage_time,Y[i],&stageok);CHKERRQ(ierr);
801         if (!stageok) {
802           /* We are likely rejecting the step because of solver or function domain problems so we should not attempt to
803            * use extrapolation to initialize the solves on the next attempt. */
804           extrapolate = PETSC_FALSE;
805           goto reject_step;
806         }
807       }
808       if (ts->equation_type >= TS_EQ_IMPLICIT) {
809         if (i==0 && tab->explicit_first_stage) {
810           if (!tab->stiffly_accurate ) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSARKIMEX %s is not stiffly accurate and therefore explicit-first stage methods cannot be used if the equation is implicit because the slope cannot be evaluated",ark->tableau->name);
811           ierr = VecCopy(Ydot0,YdotI[0]);CHKERRQ(ierr);                                      /* YdotI = YdotI(tn-1) */
812         } else {
813           ierr = VecAXPBYPCZ(YdotI[i],-ark->scoeff/h,ark->scoeff/h,0,Z,Y[i]);CHKERRQ(ierr);  /* YdotI = shift*(X-Z) */
814         }
815       } else {
816         if (i==0 && tab->explicit_first_stage) {
817           ierr = VecZeroEntries(Ydot);CHKERRQ(ierr);
818           ierr = TSComputeIFunction(ts,t+h*ct[i],Y[i],Ydot,YdotI[i],ark->imex);CHKERRQ(ierr);/* YdotI = -G(t,Y,0)   */
819           ierr = VecScale(YdotI[i],-1.0);CHKERRQ(ierr);
820         } else {
821           ierr = VecAXPBYPCZ(YdotI[i],-ark->scoeff/h,ark->scoeff/h,0,Z,Y[i]);CHKERRQ(ierr);  /* YdotI = shift*(X-Z) */
822         }
823         if (ark->imex) {
824           ierr = TSComputeRHSFunction(ts,t+h*c[i],Y[i],YdotRHS[i]);CHKERRQ(ierr);
825         } else {
826           ierr = VecZeroEntries(YdotRHS[i]);CHKERRQ(ierr);
827         }
828       }
829       ierr = TSPostStage(ts,ark->stage_time,i,Y); CHKERRQ(ierr);
830     }
831 
832     ark->status = TS_STEP_INCOMPLETE;
833     ierr = TSEvaluateStep_ARKIMEX(ts,tab->order,ts->vec_sol,NULL);CHKERRQ(ierr);
834     ark->status = TS_STEP_PENDING;
835     ierr = TSGetAdapt(ts,&adapt);CHKERRQ(ierr);
836     ierr = TSAdaptCandidatesClear(adapt);CHKERRQ(ierr);
837     ierr = TSAdaptCandidateAdd(adapt,tab->name,tab->order,1,tab->ccfl,(PetscReal)tab->s,PETSC_TRUE);CHKERRQ(ierr);
838     ierr = TSAdaptChoose(adapt,ts,ts->time_step,NULL,&next_time_step,&accept);CHKERRQ(ierr);
839     ark->status = accept ? TS_STEP_COMPLETE : TS_STEP_INCOMPLETE;
840     if (!accept) { /* Roll back the current step */
841       ierr = TSRollBack_ARKIMEX(ts);CHKERRQ(ierr);
842       ts->time_step = next_time_step;
843       goto reject_step;
844     }
845 
846     ts->ptime += ts->time_step;
847     ts->time_step = next_time_step;
848     break;
849 
850   reject_step:
851     ts->reject++; accept = PETSC_FALSE;
852     if (!ts->reason && ++rejections > ts->max_reject && ts->max_reject >= 0) {
853       ts->reason = TS_DIVERGED_STEP_REJECTED;
854       ierr = PetscInfo2(ts,"Step=%D, step rejections %D greater than current TS allowed, stopping solve\n",ts->steps,rejections);CHKERRQ(ierr);
855     }
856   }
857   PetscFunctionReturn(0);
858 }
859 
860 #undef __FUNCT__
861 #define __FUNCT__ "TSInterpolate_ARKIMEX"
862 static PetscErrorCode TSInterpolate_ARKIMEX(TS ts,PetscReal itime,Vec X)
863 {
864   TS_ARKIMEX      *ark = (TS_ARKIMEX*)ts->data;
865   PetscInt        s    = ark->tableau->s,pinterp = ark->tableau->pinterp,i,j;
866   PetscReal       h;
867   PetscReal       tt,t;
868   PetscScalar     *bt,*b;
869   const PetscReal *Bt = ark->tableau->binterpt,*B = ark->tableau->binterp;
870   PetscErrorCode  ierr;
871 
872   PetscFunctionBegin;
873   if (!Bt || !B) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSARKIMEX %s does not have an interpolation formula",ark->tableau->name);
874   switch (ark->status) {
875   case TS_STEP_INCOMPLETE:
876   case TS_STEP_PENDING:
877     h = ts->time_step;
878     t = (itime - ts->ptime)/h;
879     break;
880   case TS_STEP_COMPLETE:
881     h = ts->ptime - ts->ptime_prev;
882     t = (itime - ts->ptime)/h + 1; /* In the interval [0,1] */
883     break;
884   default: SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_PLIB,"Invalid TSStepStatus");
885   }
886   ierr = PetscMalloc2(s,&bt,s,&b);CHKERRQ(ierr);
887   for (i=0; i<s; i++) bt[i] = b[i] = 0;
888   for (j=0,tt=t; j<pinterp; j++,tt*=t) {
889     for (i=0; i<s; i++) {
890       bt[i] += h * Bt[i*pinterp+j] * tt;
891       b[i]  += h * B[i*pinterp+j] * tt;
892     }
893   }
894   ierr = VecCopy(ark->Y[0],X);CHKERRQ(ierr);
895   ierr = VecMAXPY(X,s,bt,ark->YdotI);CHKERRQ(ierr);
896   ierr = VecMAXPY(X,s,b,ark->YdotRHS);CHKERRQ(ierr);
897   ierr = PetscFree2(bt,b);CHKERRQ(ierr);
898   PetscFunctionReturn(0);
899 }
900 
901 #undef __FUNCT__
902 #define __FUNCT__ "TSExtrapolate_ARKIMEX"
903 static PetscErrorCode TSExtrapolate_ARKIMEX(TS ts,PetscReal c,Vec X)
904 {
905   TS_ARKIMEX      *ark = (TS_ARKIMEX*)ts->data;
906   PetscInt        s = ark->tableau->s,pinterp = ark->tableau->pinterp,i,j;
907   PetscReal       h,h_prev,t,tt;
908   PetscScalar     *bt,*b;
909   const PetscReal *Bt = ark->tableau->binterpt,*B = ark->tableau->binterp;
910   PetscErrorCode  ierr;
911 
912   PetscFunctionBegin;
913   if (!Bt || !B) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSARKIMEX %s does not have an interpolation formula",ark->tableau->name);
914   ierr = PetscCalloc2(s,&bt,s,&b);CHKERRQ(ierr);
915   h = ts->time_step;
916   h_prev = ts->ptime - ts->ptime_prev;
917   t = 1 + h/h_prev*c;
918   for (j=0,tt=t; j<pinterp; j++,tt*=t) {
919     for (i=0; i<s; i++) {
920       bt[i] += h * Bt[i*pinterp+j] * tt;
921       b[i]  += h * B[i*pinterp+j] * tt;
922     }
923   }
924   if (!ark->Y_prev) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Stages from previous step have not been stored");
925   ierr = VecCopy(ark->Y_prev[0],X);CHKERRQ(ierr);
926   ierr = VecMAXPY(X,s,bt,ark->YdotI_prev);CHKERRQ(ierr);
927   ierr = VecMAXPY(X,s,b,ark->YdotRHS_prev);CHKERRQ(ierr);
928   ierr = PetscFree2(bt,b);CHKERRQ(ierr);
929   PetscFunctionReturn(0);
930 }
931 
932 /*------------------------------------------------------------*/
933 
934 #undef __FUNCT__
935 #define __FUNCT__ "TSARKIMEXTableauReset"
936 static PetscErrorCode TSARKIMEXTableauReset(TS ts)
937 {
938   TS_ARKIMEX     *ark = (TS_ARKIMEX*)ts->data;
939   ARKTableau     tab  = ark->tableau;
940   PetscErrorCode ierr;
941 
942   PetscFunctionBegin;
943   if (!tab) PetscFunctionReturn(0);
944   ierr = PetscFree(ark->work);CHKERRQ(ierr);
945   ierr = VecDestroyVecs(tab->s,&ark->Y);CHKERRQ(ierr);
946   ierr = VecDestroyVecs(tab->s,&ark->YdotI);CHKERRQ(ierr);
947   ierr = VecDestroyVecs(tab->s,&ark->YdotRHS);CHKERRQ(ierr);
948   ierr = VecDestroyVecs(tab->s,&ark->Y_prev);CHKERRQ(ierr);
949   ierr = VecDestroyVecs(tab->s,&ark->YdotI_prev);CHKERRQ(ierr);
950   ierr = VecDestroyVecs(tab->s,&ark->YdotRHS_prev);CHKERRQ(ierr);
951   PetscFunctionReturn(0);
952 }
953 
954 #undef __FUNCT__
955 #define __FUNCT__ "TSReset_ARKIMEX"
956 static PetscErrorCode TSReset_ARKIMEX(TS ts)
957 {
958   TS_ARKIMEX     *ark = (TS_ARKIMEX*)ts->data;
959   PetscErrorCode ierr;
960 
961   PetscFunctionBegin;
962   ierr = TSARKIMEXTableauReset(ts);CHKERRQ(ierr);
963   ierr = VecDestroy(&ark->Ydot);CHKERRQ(ierr);
964   ierr = VecDestroy(&ark->Ydot0);CHKERRQ(ierr);
965   ierr = VecDestroy(&ark->Z);CHKERRQ(ierr);
966   PetscFunctionReturn(0);
967 }
968 
969 #undef __FUNCT__
970 #define __FUNCT__ "TSDestroy_ARKIMEX"
971 static PetscErrorCode TSDestroy_ARKIMEX(TS ts)
972 {
973   PetscErrorCode ierr;
974 
975   PetscFunctionBegin;
976   ierr = TSReset_ARKIMEX(ts);CHKERRQ(ierr);
977   ierr = PetscFree(ts->data);CHKERRQ(ierr);
978   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSARKIMEXGetType_C",NULL);CHKERRQ(ierr);
979   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSARKIMEXSetType_C",NULL);CHKERRQ(ierr);
980   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSARKIMEXSetFullyImplicit_C",NULL);CHKERRQ(ierr);
981   PetscFunctionReturn(0);
982 }
983 
984 
985 #undef __FUNCT__
986 #define __FUNCT__ "TSARKIMEXGetVecs"
987 static PetscErrorCode TSARKIMEXGetVecs(TS ts,DM dm,Vec *Z,Vec *Ydot)
988 {
989   TS_ARKIMEX     *ax = (TS_ARKIMEX*)ts->data;
990   PetscErrorCode ierr;
991 
992   PetscFunctionBegin;
993   if (Z) {
994     if (dm && dm != ts->dm) {
995       ierr = DMGetNamedGlobalVector(dm,"TSARKIMEX_Z",Z);CHKERRQ(ierr);
996     } else *Z = ax->Z;
997   }
998   if (Ydot) {
999     if (dm && dm != ts->dm) {
1000       ierr = DMGetNamedGlobalVector(dm,"TSARKIMEX_Ydot",Ydot);CHKERRQ(ierr);
1001     } else *Ydot = ax->Ydot;
1002   }
1003   PetscFunctionReturn(0);
1004 }
1005 
1006 
1007 #undef __FUNCT__
1008 #define __FUNCT__ "TSARKIMEXRestoreVecs"
1009 static PetscErrorCode TSARKIMEXRestoreVecs(TS ts,DM dm,Vec *Z,Vec *Ydot)
1010 {
1011   PetscErrorCode ierr;
1012 
1013   PetscFunctionBegin;
1014   if (Z) {
1015     if (dm && dm != ts->dm) {
1016       ierr = DMRestoreNamedGlobalVector(dm,"TSARKIMEX_Z",Z);CHKERRQ(ierr);
1017     }
1018   }
1019   if (Ydot) {
1020     if (dm && dm != ts->dm) {
1021       ierr = DMRestoreNamedGlobalVector(dm,"TSARKIMEX_Ydot",Ydot);CHKERRQ(ierr);
1022     }
1023   }
1024   PetscFunctionReturn(0);
1025 }
1026 
1027 /*
1028   This defines the nonlinear equation that is to be solved with SNES
1029   G(U) = F[t0+Theta*dt, U, (U-U0)*shift] = 0
1030 */
1031 #undef __FUNCT__
1032 #define __FUNCT__ "SNESTSFormFunction_ARKIMEX"
1033 static PetscErrorCode SNESTSFormFunction_ARKIMEX(SNES snes,Vec X,Vec F,TS ts)
1034 {
1035   TS_ARKIMEX     *ark = (TS_ARKIMEX*)ts->data;
1036   DM             dm,dmsave;
1037   Vec            Z,Ydot;
1038   PetscReal      shift = ark->scoeff / ts->time_step;
1039   PetscErrorCode ierr;
1040 
1041   PetscFunctionBegin;
1042   ierr   = SNESGetDM(snes,&dm);CHKERRQ(ierr);
1043   ierr   = TSARKIMEXGetVecs(ts,dm,&Z,&Ydot);CHKERRQ(ierr);
1044   ierr   = VecAXPBYPCZ(Ydot,-shift,shift,0,Z,X);CHKERRQ(ierr); /* Ydot = shift*(X-Z) */
1045   dmsave = ts->dm;
1046   ts->dm = dm;
1047 
1048   ierr = TSComputeIFunction(ts,ark->stage_time,X,Ydot,F,ark->imex);CHKERRQ(ierr);
1049 
1050   ts->dm = dmsave;
1051   ierr   = TSARKIMEXRestoreVecs(ts,dm,&Z,&Ydot);CHKERRQ(ierr);
1052   PetscFunctionReturn(0);
1053 }
1054 
1055 #undef __FUNCT__
1056 #define __FUNCT__ "SNESTSFormJacobian_ARKIMEX"
1057 static PetscErrorCode SNESTSFormJacobian_ARKIMEX(SNES snes,Vec X,Mat A,Mat B,TS ts)
1058 {
1059   TS_ARKIMEX     *ark = (TS_ARKIMEX*)ts->data;
1060   DM             dm,dmsave;
1061   Vec            Ydot;
1062   PetscReal      shift = ark->scoeff / ts->time_step;
1063   PetscErrorCode ierr;
1064 
1065   PetscFunctionBegin;
1066   ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr);
1067   ierr = TSARKIMEXGetVecs(ts,dm,NULL,&Ydot);CHKERRQ(ierr);
1068   /* ark->Ydot has already been computed in SNESTSFormFunction_ARKIMEX (SNES guarantees this) */
1069   dmsave = ts->dm;
1070   ts->dm = dm;
1071 
1072   ierr = TSComputeIJacobian(ts,ark->stage_time,X,Ydot,shift,A,B,ark->imex);CHKERRQ(ierr);
1073 
1074   ts->dm = dmsave;
1075   ierr   = TSARKIMEXRestoreVecs(ts,dm,NULL,&Ydot);CHKERRQ(ierr);
1076   PetscFunctionReturn(0);
1077 }
1078 
1079 #undef __FUNCT__
1080 #define __FUNCT__ "DMCoarsenHook_TSARKIMEX"
1081 static PetscErrorCode DMCoarsenHook_TSARKIMEX(DM fine,DM coarse,void *ctx)
1082 {
1083   PetscFunctionBegin;
1084   PetscFunctionReturn(0);
1085 }
1086 
1087 #undef __FUNCT__
1088 #define __FUNCT__ "DMRestrictHook_TSARKIMEX"
1089 static PetscErrorCode DMRestrictHook_TSARKIMEX(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse,void *ctx)
1090 {
1091   TS             ts = (TS)ctx;
1092   PetscErrorCode ierr;
1093   Vec            Z,Z_c;
1094 
1095   PetscFunctionBegin;
1096   ierr = TSARKIMEXGetVecs(ts,fine,&Z,NULL);CHKERRQ(ierr);
1097   ierr = TSARKIMEXGetVecs(ts,coarse,&Z_c,NULL);CHKERRQ(ierr);
1098   ierr = MatRestrict(restrct,Z,Z_c);CHKERRQ(ierr);
1099   ierr = VecPointwiseMult(Z_c,rscale,Z_c);CHKERRQ(ierr);
1100   ierr = TSARKIMEXRestoreVecs(ts,fine,&Z,NULL);CHKERRQ(ierr);
1101   ierr = TSARKIMEXRestoreVecs(ts,coarse,&Z_c,NULL);CHKERRQ(ierr);
1102   PetscFunctionReturn(0);
1103 }
1104 
1105 
1106 #undef __FUNCT__
1107 #define __FUNCT__ "DMSubDomainHook_TSARKIMEX"
1108 static PetscErrorCode DMSubDomainHook_TSARKIMEX(DM dm,DM subdm,void *ctx)
1109 {
1110   PetscFunctionBegin;
1111   PetscFunctionReturn(0);
1112 }
1113 
1114 #undef __FUNCT__
1115 #define __FUNCT__ "DMSubDomainRestrictHook_TSARKIMEX"
1116 static PetscErrorCode DMSubDomainRestrictHook_TSARKIMEX(DM dm,VecScatter gscat,VecScatter lscat,DM subdm,void *ctx)
1117 {
1118   TS             ts = (TS)ctx;
1119   PetscErrorCode ierr;
1120   Vec            Z,Z_c;
1121 
1122   PetscFunctionBegin;
1123   ierr = TSARKIMEXGetVecs(ts,dm,&Z,NULL);CHKERRQ(ierr);
1124   ierr = TSARKIMEXGetVecs(ts,subdm,&Z_c,NULL);CHKERRQ(ierr);
1125 
1126   ierr = VecScatterBegin(gscat,Z,Z_c,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1127   ierr = VecScatterEnd(gscat,Z,Z_c,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1128 
1129   ierr = TSARKIMEXRestoreVecs(ts,dm,&Z,NULL);CHKERRQ(ierr);
1130   ierr = TSARKIMEXRestoreVecs(ts,subdm,&Z_c,NULL);CHKERRQ(ierr);
1131   PetscFunctionReturn(0);
1132 }
1133 
1134 #undef __FUNCT__
1135 #define __FUNCT__ "TSARKIMEXTableauSetUp"
1136 static PetscErrorCode TSARKIMEXTableauSetUp(TS ts)
1137 {
1138   TS_ARKIMEX     *ark = (TS_ARKIMEX*)ts->data;
1139   ARKTableau     tab  = ark->tableau;
1140   PetscErrorCode ierr;
1141 
1142   PetscFunctionBegin;
1143   ierr = PetscMalloc1(tab->s,&ark->work);CHKERRQ(ierr);
1144   ierr = VecDuplicateVecs(ts->vec_sol,tab->s,&ark->Y);CHKERRQ(ierr);
1145   ierr = VecDuplicateVecs(ts->vec_sol,tab->s,&ark->YdotI);CHKERRQ(ierr);
1146   ierr = VecDuplicateVecs(ts->vec_sol,tab->s,&ark->YdotRHS);CHKERRQ(ierr);
1147   if (ark->extrapolate) {
1148     ierr = VecDuplicateVecs(ts->vec_sol,tab->s,&ark->Y_prev);CHKERRQ(ierr);
1149     ierr = VecDuplicateVecs(ts->vec_sol,tab->s,&ark->YdotI_prev);CHKERRQ(ierr);
1150     ierr = VecDuplicateVecs(ts->vec_sol,tab->s,&ark->YdotRHS_prev);CHKERRQ(ierr);
1151   }
1152   PetscFunctionReturn(0);
1153 }
1154 
1155 #undef __FUNCT__
1156 #define __FUNCT__ "TSSetUp_ARKIMEX"
1157 static PetscErrorCode TSSetUp_ARKIMEX(TS ts)
1158 {
1159   TS_ARKIMEX     *ark = (TS_ARKIMEX*)ts->data;
1160   PetscErrorCode ierr;
1161   DM             dm;
1162   SNES           snes;
1163 
1164   PetscFunctionBegin;
1165   ierr = TSARKIMEXTableauSetUp(ts);CHKERRQ(ierr);
1166   ierr = VecDuplicate(ts->vec_sol,&ark->Ydot);CHKERRQ(ierr);
1167   ierr = VecDuplicate(ts->vec_sol,&ark->Ydot0);CHKERRQ(ierr);
1168   ierr = VecDuplicate(ts->vec_sol,&ark->Z);CHKERRQ(ierr);
1169   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
1170   if (dm) {
1171     ierr = DMCoarsenHookAdd(dm,DMCoarsenHook_TSARKIMEX,DMRestrictHook_TSARKIMEX,ts);CHKERRQ(ierr);
1172     ierr = DMSubDomainHookAdd(dm,DMSubDomainHook_TSARKIMEX,DMSubDomainRestrictHook_TSARKIMEX,ts);CHKERRQ(ierr);
1173   }
1174   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
1175   PetscFunctionReturn(0);
1176 }
1177 /*------------------------------------------------------------*/
1178 
1179 #undef __FUNCT__
1180 #define __FUNCT__ "TSSetFromOptions_ARKIMEX"
1181 static PetscErrorCode TSSetFromOptions_ARKIMEX(PetscOptionItems *PetscOptionsObject,TS ts)
1182 {
1183   TS_ARKIMEX     *ark = (TS_ARKIMEX*)ts->data;
1184   PetscErrorCode ierr;
1185 
1186   PetscFunctionBegin;
1187   ierr = PetscOptionsHead(PetscOptionsObject,"ARKIMEX ODE solver options");CHKERRQ(ierr);
1188   {
1189     ARKTableauLink link;
1190     PetscInt       count,choice;
1191     PetscBool      flg;
1192     const char     **namelist;
1193     for (link=ARKTableauList,count=0; link; link=link->next,count++) ;
1194     ierr = PetscMalloc1(count,&namelist);CHKERRQ(ierr);
1195     for (link=ARKTableauList,count=0; link; link=link->next,count++) namelist[count] = link->tab.name;
1196     ierr = PetscOptionsEList("-ts_arkimex_type","Family of ARK IMEX method","TSARKIMEXSetType",(const char*const*)namelist,count,ark->tableau->name,&choice,&flg);CHKERRQ(ierr);
1197     if (flg) {ierr = TSARKIMEXSetType(ts,namelist[choice]);CHKERRQ(ierr);}
1198     ierr = PetscFree(namelist);CHKERRQ(ierr);
1199 
1200     flg  = (PetscBool) !ark->imex;
1201     ierr = PetscOptionsBool("-ts_arkimex_fully_implicit","Solve the problem fully implicitly","TSARKIMEXSetFullyImplicit",flg,&flg,NULL);CHKERRQ(ierr);
1202     ark->imex = (PetscBool) !flg;
1203     ierr = PetscOptionsBool("-ts_arkimex_initial_guess_extrapolate","Extrapolate the initial guess for the stage solution from stage values of the previous time step","",ark->extrapolate,&ark->extrapolate,NULL);CHKERRQ(ierr);
1204   }
1205   ierr = PetscOptionsTail();CHKERRQ(ierr);
1206   PetscFunctionReturn(0);
1207 }
1208 
1209 #undef __FUNCT__
1210 #define __FUNCT__ "PetscFormatRealArray"
1211 static PetscErrorCode PetscFormatRealArray(char buf[],size_t len,const char *fmt,PetscInt n,const PetscReal x[])
1212 {
1213   PetscErrorCode ierr;
1214   PetscInt       i;
1215   size_t         left,count;
1216   char           *p;
1217 
1218   PetscFunctionBegin;
1219   for (i=0,p=buf,left=len; i<n; i++) {
1220     ierr = PetscSNPrintfCount(p,left,fmt,&count,(double)x[i]);CHKERRQ(ierr);
1221     if (count >= left) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Insufficient space in buffer");
1222     left -= count;
1223     p    += count;
1224     *p++  = ' ';
1225   }
1226   p[i ? 0 : -1] = 0;
1227   PetscFunctionReturn(0);
1228 }
1229 
1230 #undef __FUNCT__
1231 #define __FUNCT__ "TSView_ARKIMEX"
1232 static PetscErrorCode TSView_ARKIMEX(TS ts,PetscViewer viewer)
1233 {
1234   TS_ARKIMEX     *ark = (TS_ARKIMEX*)ts->data;
1235   PetscBool      iascii;
1236   PetscErrorCode ierr;
1237 
1238   PetscFunctionBegin;
1239   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
1240   if (iascii) {
1241     ARKTableau    tab = ark->tableau;
1242     TSARKIMEXType arktype;
1243     char          buf[512];
1244     ierr = TSARKIMEXGetType(ts,&arktype);CHKERRQ(ierr);
1245     ierr = PetscViewerASCIIPrintf(viewer,"  ARK IMEX %s\n",arktype);CHKERRQ(ierr);
1246     ierr = PetscFormatRealArray(buf,sizeof(buf),"% 8.6f",tab->s,tab->ct);CHKERRQ(ierr);
1247     ierr = PetscViewerASCIIPrintf(viewer,"  Stiff abscissa       ct = %s\n",buf);CHKERRQ(ierr);
1248     ierr = PetscFormatRealArray(buf,sizeof(buf),"% 8.6f",tab->s,tab->c);CHKERRQ(ierr);
1249     ierr = PetscViewerASCIIPrintf(viewer,"Stiffly accurate: %s\n",tab->stiffly_accurate ? "yes" : "no");CHKERRQ(ierr);
1250     ierr = PetscViewerASCIIPrintf(viewer,"Explicit first stage: %s\n",tab->explicit_first_stage ? "yes" : "no");CHKERRQ(ierr);
1251     ierr = PetscViewerASCIIPrintf(viewer,"FSAL property: %s\n",tab->FSAL_implicit ? "yes" : "no");CHKERRQ(ierr);
1252     ierr = PetscViewerASCIIPrintf(viewer,"  Nonstiff abscissa     c = %s\n",buf);CHKERRQ(ierr);
1253   }
1254   if (ts->adapt) {ierr = TSAdaptView(ts->adapt,viewer);CHKERRQ(ierr);}
1255   if (ts->snes)  {ierr = SNESView(ts->snes,viewer);CHKERRQ(ierr);}
1256   PetscFunctionReturn(0);
1257 }
1258 
1259 #undef __FUNCT__
1260 #define __FUNCT__ "TSLoad_ARKIMEX"
1261 static PetscErrorCode TSLoad_ARKIMEX(TS ts,PetscViewer viewer)
1262 {
1263   PetscErrorCode ierr;
1264   SNES           snes;
1265   TSAdapt        adapt;
1266 
1267   PetscFunctionBegin;
1268   ierr = TSGetAdapt(ts,&adapt);CHKERRQ(ierr);
1269   ierr = TSAdaptLoad(adapt,viewer);CHKERRQ(ierr);
1270   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
1271   ierr = SNESLoad(snes,viewer);CHKERRQ(ierr);
1272   /* function and Jacobian context for SNES when used with TS is always ts object */
1273   ierr = SNESSetFunction(snes,NULL,NULL,ts);CHKERRQ(ierr);
1274   ierr = SNESSetJacobian(snes,NULL,NULL,NULL,ts);CHKERRQ(ierr);
1275   PetscFunctionReturn(0);
1276 }
1277 
1278 #undef __FUNCT__
1279 #define __FUNCT__ "TSARKIMEXSetType"
1280 /*@C
1281   TSARKIMEXSetType - Set the type of ARK IMEX scheme
1282 
1283   Logically collective
1284 
1285   Input Parameter:
1286 +  ts - timestepping context
1287 -  arktype - type of ARK-IMEX scheme
1288 
1289   Level: intermediate
1290 
1291 .seealso: TSARKIMEXGetType(), TSARKIMEX, TSARKIMEX2D, TSARKIMEX2E, TSARKIMEXPRSSP2, TSARKIMEX3, TSARKIMEXBPR3, TSARKIMEXARS443, TSARKIMEX4, TSARKIMEX5
1292 @*/
1293 PetscErrorCode TSARKIMEXSetType(TS ts,TSARKIMEXType arktype)
1294 {
1295   PetscErrorCode ierr;
1296 
1297   PetscFunctionBegin;
1298   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1299   ierr = PetscTryMethod(ts,"TSARKIMEXSetType_C",(TS,TSARKIMEXType),(ts,arktype));CHKERRQ(ierr);
1300   PetscFunctionReturn(0);
1301 }
1302 
1303 #undef __FUNCT__
1304 #define __FUNCT__ "TSARKIMEXGetType"
1305 /*@C
1306   TSARKIMEXGetType - Get the type of ARK IMEX scheme
1307 
1308   Logically collective
1309 
1310   Input Parameter:
1311 .  ts - timestepping context
1312 
1313   Output Parameter:
1314 .  arktype - type of ARK-IMEX scheme
1315 
1316   Level: intermediate
1317 
1318 .seealso: TSARKIMEXGetType()
1319 @*/
1320 PetscErrorCode TSARKIMEXGetType(TS ts,TSARKIMEXType *arktype)
1321 {
1322   PetscErrorCode ierr;
1323 
1324   PetscFunctionBegin;
1325   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1326   ierr = PetscUseMethod(ts,"TSARKIMEXGetType_C",(TS,TSARKIMEXType*),(ts,arktype));CHKERRQ(ierr);
1327   PetscFunctionReturn(0);
1328 }
1329 
1330 #undef __FUNCT__
1331 #define __FUNCT__ "TSARKIMEXSetFullyImplicit"
1332 /*@
1333   TSARKIMEXSetFullyImplicit - Solve both parts of the equation implicitly
1334 
1335   Logically collective
1336 
1337   Input Parameter:
1338 +  ts - timestepping context
1339 -  flg - PETSC_TRUE for fully implicit
1340 
1341   Level: intermediate
1342 
1343 .seealso: TSARKIMEXGetType()
1344 @*/
1345 PetscErrorCode TSARKIMEXSetFullyImplicit(TS ts,PetscBool flg)
1346 {
1347   PetscErrorCode ierr;
1348 
1349   PetscFunctionBegin;
1350   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1351   ierr = PetscTryMethod(ts,"TSARKIMEXSetFullyImplicit_C",(TS,PetscBool),(ts,flg));CHKERRQ(ierr);
1352   PetscFunctionReturn(0);
1353 }
1354 
1355 #undef __FUNCT__
1356 #define __FUNCT__ "TSARKIMEXGetType_ARKIMEX"
1357 static PetscErrorCode  TSARKIMEXGetType_ARKIMEX(TS ts,TSARKIMEXType *arktype)
1358 {
1359   TS_ARKIMEX     *ark = (TS_ARKIMEX*)ts->data;
1360 
1361   PetscFunctionBegin;
1362   *arktype = ark->tableau->name;
1363   PetscFunctionReturn(0);
1364 }
1365 #undef __FUNCT__
1366 #define __FUNCT__ "TSARKIMEXSetType_ARKIMEX"
1367 static PetscErrorCode  TSARKIMEXSetType_ARKIMEX(TS ts,TSARKIMEXType arktype)
1368 {
1369   TS_ARKIMEX     *ark = (TS_ARKIMEX*)ts->data;
1370   PetscErrorCode ierr;
1371   PetscBool      match;
1372   ARKTableauLink link;
1373 
1374   PetscFunctionBegin;
1375   if (ark->tableau) {
1376     ierr = PetscStrcmp(ark->tableau->name,arktype,&match);CHKERRQ(ierr);
1377     if (match) PetscFunctionReturn(0);
1378   }
1379   for (link = ARKTableauList; link; link=link->next) {
1380     ierr = PetscStrcmp(link->tab.name,arktype,&match);CHKERRQ(ierr);
1381     if (match) {
1382       if (ts->setupcalled) {ierr = TSARKIMEXTableauReset(ts);CHKERRQ(ierr);}
1383       ark->tableau = &link->tab;
1384       if (ts->setupcalled) {ierr = TSARKIMEXTableauSetUp(ts);CHKERRQ(ierr);}
1385       PetscFunctionReturn(0);
1386     }
1387   }
1388   SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_UNKNOWN_TYPE,"Could not find '%s'",arktype);
1389   PetscFunctionReturn(0);
1390 }
1391 
1392 #undef __FUNCT__
1393 #define __FUNCT__ "TSARKIMEXSetFullyImplicit_ARKIMEX"
1394 static PetscErrorCode  TSARKIMEXSetFullyImplicit_ARKIMEX(TS ts,PetscBool flg)
1395 {
1396   TS_ARKIMEX *ark = (TS_ARKIMEX*)ts->data;
1397 
1398   PetscFunctionBegin;
1399   ark->imex = (PetscBool)!flg;
1400   PetscFunctionReturn(0);
1401 }
1402 
1403 /* ------------------------------------------------------------ */
1404 /*MC
1405       TSARKIMEX - ODE and DAE solver using Additive Runge-Kutta IMEX schemes
1406 
1407   These methods are intended for problems with well-separated time scales, especially when a slow scale is strongly
1408   nonlinear such that it is expensive to solve with a fully implicit method. The user should provide the stiff part
1409   of the equation using TSSetIFunction() and the non-stiff part with TSSetRHSFunction().
1410 
1411   Notes:
1412   The default is TSARKIMEX3, it can be changed with TSARKIMEXSetType() or -ts_arkimex_type
1413 
1414   If the equation is implicit or a DAE, then TSSetEquationType() needs to be set accordingly. Refer to the manual for further information.
1415 
1416   Methods with an explicit stage can only be used with ODE in which the stiff part G(t,X,Xdot) has the form Xdot + Ghat(t,X).
1417 
1418   Consider trying TSROSW if the stiff part is linear or weakly nonlinear.
1419 
1420   Level: beginner
1421 
1422 .seealso:  TSCreate(), TS, TSSetType(), TSARKIMEXSetType(), TSARKIMEXGetType(), TSARKIMEXSetFullyImplicit(), TSARKIMEX1BEE,
1423            TSARKIMEX2C, TSARKIMEX2D, TSARKIMEX2E, TSARKIMEX3, TSARKIMEXL2, TSARKIMEXA2, TSARKIMEXARS122,
1424            TSARKIMEX4, TSARKIMEX5, TSARKIMEXPRSSP2, TSARKIMEXARS443, TSARKIMEXBPR3, TSARKIMEXType, TSARKIMEXRegister()
1425 
1426 M*/
1427 #undef __FUNCT__
1428 #define __FUNCT__ "TSCreate_ARKIMEX"
1429 PETSC_EXTERN PetscErrorCode TSCreate_ARKIMEX(TS ts)
1430 {
1431   TS_ARKIMEX     *th;
1432   PetscErrorCode ierr;
1433 
1434   PetscFunctionBegin;
1435   ierr = TSARKIMEXInitializePackage();CHKERRQ(ierr);
1436 
1437   ts->ops->reset          = TSReset_ARKIMEX;
1438   ts->ops->destroy        = TSDestroy_ARKIMEX;
1439   ts->ops->view           = TSView_ARKIMEX;
1440   ts->ops->load           = TSLoad_ARKIMEX;
1441   ts->ops->setup          = TSSetUp_ARKIMEX;
1442   ts->ops->step           = TSStep_ARKIMEX;
1443   ts->ops->interpolate    = TSInterpolate_ARKIMEX;
1444   ts->ops->evaluatestep   = TSEvaluateStep_ARKIMEX;
1445   ts->ops->rollback       = TSRollBack_ARKIMEX;
1446   ts->ops->setfromoptions = TSSetFromOptions_ARKIMEX;
1447   ts->ops->snesfunction   = SNESTSFormFunction_ARKIMEX;
1448   ts->ops->snesjacobian   = SNESTSFormJacobian_ARKIMEX;
1449 
1450   ierr = PetscNewLog(ts,&th);CHKERRQ(ierr);
1451   ts->data = (void*)th;
1452   th->imex = PETSC_TRUE;
1453 
1454   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSARKIMEXGetType_C",TSARKIMEXGetType_ARKIMEX);CHKERRQ(ierr);
1455   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSARKIMEXSetType_C",TSARKIMEXSetType_ARKIMEX);CHKERRQ(ierr);
1456   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSARKIMEXSetFullyImplicit_C",TSARKIMEXSetFullyImplicit_ARKIMEX);CHKERRQ(ierr);
1457 
1458   ierr = TSARKIMEXSetType(ts,TSARKIMEXDefault);CHKERRQ(ierr);
1459   PetscFunctionReturn(0);
1460 }
1461