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