xref: /petsc/src/ts/impls/glee/glee.c (revision 9f4d3c52fa2fe0bb72fec4f4e85d8e495867af35)
1 /*
2   Code for time stepping with the General Linear with Error Estimation method
3 
4 
5   Notes:
6   The general system is written as
7 
8   Udot = F(t,U)
9 
10 */
11 #include <petsc/private/tsimpl.h>                /*I   "petscts.h"   I*/
12 #include <petscdm.h>
13 
14 static PetscBool  cited = PETSC_FALSE;
15 static const char citation[] =
16   "@ARTICLE{Constantinescu_TR2016b,\n"
17   " author = {Constantinescu, E.M.},\n"
18   " title = {Estimating Global Errors in Time Stepping},\n"
19   " journal = {ArXiv e-prints},\n"
20   " year = 2016,\n"
21   " adsurl = {http://adsabs.harvard.edu/abs/2015arXiv150305166C}\n}\n";
22 
23 static TSGLEEType   TSGLEEDefaultType = TSGLEE35;
24 static PetscBool    TSGLEERegisterAllCalled;
25 static PetscBool    TSGLEEPackageInitialized;
26 static PetscInt     explicit_stage_time_id;
27 
28 typedef struct _GLEETableau *GLEETableau;
29 struct _GLEETableau {
30   char      *name;
31   PetscInt   order;               /* Classical approximation order of the method i*/
32   PetscInt   s;                   /* Number of stages */
33   PetscInt   r;                   /* Number of steps */
34   PetscReal  gamma;               /* LTE ratio */
35   PetscReal *A,*B,*U,*V,*S,*F,*c; /* Tableau */
36   PetscReal *Fembed;              /* Embedded final method coefficients */
37   PetscReal *Ferror;              /* Coefficients for computing error   */
38   PetscReal *Serror;              /* Coefficients for initializing the error   */
39   PetscInt   pinterp;             /* Interpolation order */
40   PetscReal *binterp;             /* Interpolation coefficients */
41   PetscReal  ccfl;                /* Placeholder for CFL coefficient relative to forward Euler  */
42 };
43 typedef struct _GLEETableauLink *GLEETableauLink;
44 struct _GLEETableauLink {
45   struct _GLEETableau tab;
46   GLEETableauLink     next;
47 };
48 static GLEETableauLink GLEETableauList;
49 
50 typedef struct {
51   GLEETableau  tableau;
52   Vec          *Y;         /* Solution vector (along with auxiliary solution y~ or eps) */
53   Vec          *X;         /* Temporary solution vector */
54   Vec          *YStage;    /* Stage values */
55   Vec          *YdotStage; /* Stage right hand side */
56   Vec          W;          /* Right-hand-side for implicit stage solve */
57   Vec          Ydot;       /* Work vector holding Ydot during residual evaluation */
58   Vec          yGErr;      /* Vector holding the global error after a step is completed */
59   PetscScalar  *swork;     /* Scalar work (size of the number of stages)*/
60   PetscScalar  *rwork;     /* Scalar work (size of the number of steps)*/
61   PetscReal    scoeff;     /* shift = scoeff/dt */
62   PetscReal    stage_time;
63   TSStepStatus status;
64 } TS_GLEE;
65 
66 /*MC
67      TSGLEE23 - Second order three stage GLEE method
68 
69      This method has three stages.
70      s = 3, r = 2
71 
72      Level: advanced
73 
74 .seealso: TSGLEE
75 M*/
76 /*MC
77      TSGLEE24 - Second order four stage GLEE method
78 
79      This method has four stages.
80      s = 4, r = 2
81 
82      Level: advanced
83 
84 .seealso: TSGLEE
85 M*/
86 /*MC
87      TSGLEE25i - Second order five stage GLEE method
88 
89      This method has five stages.
90      s = 5, r = 2
91 
92      Level: advanced
93 
94 .seealso: TSGLEE
95 M*/
96 /*MC
97      TSGLEE35  - Third order five stage GLEE method
98 
99      This method has five stages.
100      s = 5, r = 2
101 
102      Level: advanced
103 
104 .seealso: TSGLEE
105 M*/
106 /*MC
107      TSGLEEEXRK2A  - Second order six stage GLEE method
108 
109      This method has six stages.
110      s = 6, r = 2
111 
112      Level: advanced
113 
114 .seealso: TSGLEE
115 M*/
116 /*MC
117      TSGLEERK32G1  - Third order eight stage GLEE method
118 
119      This method has eight stages.
120      s = 8, r = 2
121 
122      Level: advanced
123 
124 .seealso: TSGLEE
125 M*/
126 /*MC
127      TSGLEERK285EX  - Second order nine stage GLEE method
128 
129      This method has nine stages.
130      s = 9, r = 2
131 
132      Level: advanced
133 
134 .seealso: TSGLEE
135 M*/
136 
137 /*@C
138   TSGLEERegisterAll - Registers all of the General Linear with Error Estimation methods in TSGLEE
139 
140   Not Collective, but should be called by all processes which will need the schemes to be registered
141 
142   Level: advanced
143 
144 .keywords: TS, TSGLEE, register, all
145 
146 .seealso:  TSGLEERegisterDestroy()
147 @*/
148 PetscErrorCode TSGLEERegisterAll(void)
149 {
150   PetscErrorCode ierr;
151 
152   PetscFunctionBegin;
153   if (TSGLEERegisterAllCalled) PetscFunctionReturn(0);
154   TSGLEERegisterAllCalled = PETSC_TRUE;
155 
156   {
157 #define GAMMA 0.5
158     /* y-eps form */
159     const PetscInt
160       p = 1,
161       s = 3,
162       r = 2;
163     const PetscReal
164       A[3][3]   = {{1.0,0,0},{0,0.5,0},{0,0.5,0.5}},
165       B[2][3]   = {{1.0,0,0},{-2.0,1.0,1.0}},
166       U[3][2]   = {{1.0,0},{1.0,0.5},{1.0,0.5}},
167       V[2][2]   = {{1,0},{0,1}},
168       S[2]      = {1,0},
169       F[2]      = {1,0},
170       Fembed[2] = {1,1-GAMMA},
171       Ferror[2] = {0,1},
172       Serror[2] = {1,0};
173     ierr = TSGLEERegister(TSGLEEi1,p,s,r,GAMMA,&A[0][0],&B[0][0],&U[0][0],&V[0][0],S,F,NULL,Fembed,Ferror,Serror,0,NULL);CHKERRQ(ierr);
174   }
175   {
176 #undef GAMMA
177 #define GAMMA 0.0
178     /* y-eps form */
179     const PetscInt
180       p = 2,
181       s = 3,
182       r = 2;
183     const PetscReal
184       A[3][3]   = {{0,0,0},{1,0,0},{0.25,0.25,0}},
185       B[2][3]   = {{1.0/12.0,1.0/12.0,5.0/6.0},{1.0/12.0,1.0/12.0,-1.0/6.0}},
186       U[3][2]   = {{1,0},{1,10},{1,-1}},
187       V[2][2]   = {{1,0},{0,1}},
188       S[2]      = {1,0},
189       F[2]      = {1,0},
190       Fembed[2] = {1,1-GAMMA},
191       Ferror[2] = {0,1},
192       Serror[2] = {1,0};
193     ierr = TSGLEERegister(TSGLEE23,p,s,r,GAMMA,&A[0][0],&B[0][0],&U[0][0],&V[0][0],S,F,NULL,Fembed,Ferror,Serror,0,NULL);CHKERRQ(ierr);
194   }
195   {
196 #undef GAMMA
197 #define GAMMA 0.0
198     /* y-y~ form */
199     const PetscInt
200       p = 2,
201       s = 4,
202       r = 2;
203     const PetscReal
204       A[4][4]   = {{0,0,0,0},{0.75,0,0,0},{0.25,29.0/60.0,0,0},{-21.0/44.0,145.0/44.0,-20.0/11.0,0}},
205       B[2][4]   = {{109.0/275.0,58.0/75.0,-37.0/110.0,1.0/6.0},{3.0/11.0,0,75.0/88.0,-1.0/8.0}},
206       U[4][2]   = {{0,1},{75.0/58.0,-17.0/58.0},{0,1},{0,1}},
207       V[2][2]   = {{1,0},{0,1}},
208       S[2]      = {1,1},
209       F[2]      = {1,0},
210       Fembed[2] = {0,1},
211       Ferror[2] = {-1.0/(1.0-GAMMA),1.0/(1.0-GAMMA)},
212       Serror[2] = {1.0-GAMMA,1.0};
213       ierr = TSGLEERegister(TSGLEE24,p,s,r,GAMMA,&A[0][0],&B[0][0],&U[0][0],&V[0][0],S,F,NULL,Fembed,Ferror,Serror,0,NULL);CHKERRQ(ierr);
214   }
215   {
216 #undef GAMMA
217 #define GAMMA 0.0
218     /* y-y~ form */
219     const PetscInt
220       p = 2,
221       s = 5,
222       r = 2;
223     const PetscReal
224       A[5][5]   = {{0,0,0,0,0},
225                    {-0.94079244066783383269,0,0,0,0},
226                    {0.64228187778301907108,0.10915356933958500042,0,0,0},
227                    {-0.51764297742287450812,0.74414270351096040738,-0.71404164927824538121,0,0},
228                    {-0.44696561556825969206,-0.76768425657590196518,0.20111608138142987881,0.93828186737840469796,0}},
229       B[2][5]   = {{-0.029309178948150356153,-0.49671981884013874923,0.34275801517650053274,0.32941112623949194988,0.85385985637229662276},
230                    {0.78133219686062535272,0.074238691892675897635,0.57957363498384957966,-0.24638502829674959968,-0.18875949544040123033}},
231       U[5][2]   = {{0.16911424754448327735,0.83088575245551672265},
232                    {0.53638465733199574340,0.46361534266800425660},
233                    {0.39901579167169582526,0.60098420832830417474},
234                    {0.87689005530618575480,0.12310994469381424520},
235                    {0.99056100455550913009,0.0094389954444908699092}},
236       V[2][2]   = {{1,0},{0,1}},
237       S[2]      = {1,1},
238       F[2]      = {1,0},
239       Fembed[2] = {0,1},
240       Ferror[2] = {-1.0/(1.0-GAMMA),1.0/(1.0-GAMMA)},
241       Serror[2] = {1.0-GAMMA,1.0};
242     ierr = TSGLEERegister(TSGLEE25I,p,s,r,GAMMA,&A[0][0],&B[0][0],&U[0][0],&V[0][0],S,F,NULL,Fembed,Ferror,Serror,0,NULL);CHKERRQ(ierr);
243   }
244   {
245 #undef GAMMA
246 #define GAMMA 0.0
247     /* y-y~ form */
248     const PetscInt
249       p = 3,
250       s = 5,
251       r = 2;
252     const PetscReal
253       A[5][5]   = {{0,0,0,0,0},
254                    {- 2169604947363702313.0 /  24313474998937147335.0,0,0,0,0},
255                    {46526746497697123895.0 /  94116917485856474137.0,-10297879244026594958.0 /  49199457603717988219.0,0,0,0},
256                    {23364788935845982499.0 /  87425311444725389446.0,-79205144337496116638.0 / 148994349441340815519.0,40051189859317443782.0 /  36487615018004984309.0,0,0},
257                    {42089522664062539205.0 / 124911313006412840286.0,-15074384760342762939.0 / 137927286865289746282.0,-62274678522253371016.0 / 125918573676298591413.0,13755475729852471739.0 /  79257927066651693390.0,0}},
258       B[2][5]   = {{61546696837458703723.0 /  56982519523786160813.0,-55810892792806293355.0 / 206957624151308356511.0,24061048952676379087.0 / 158739347956038723465.0,3577972206874351339.0 /   7599733370677197135.0,-59449832954780563947.0 / 137360038685338563670.0},
259                    {- 9738262186984159168.0 /  99299082461487742983.0,-32797097931948613195.0 /  61521565616362163366.0,42895514606418420631.0 /  71714201188501437336.0,22608567633166065068.0 /  55371917805607957003.0,94655809487476459565.0 / 151517167160302729021.0}},
260       U[5][2]   = {{70820309139834661559.0 /  80863923579509469826.0,10043614439674808267.0 /  80863923579509469826.0},
261                    {161694774978034105510.0 / 106187653640211060371.0,-55507121337823045139.0 / 106187653640211060371.0},
262                    {78486094644566264568.0 /  88171030896733822981.0,9684936252167558413.0 /  88171030896733822981.0},
263                    {65394922146334854435.0 /  84570853840405479554.0,19175931694070625119.0 /  84570853840405479554.0},
264                    {8607282770183754108.0 / 108658046436496925911.0,100050763666313171803.0 / 108658046436496925911.0}},
265       V[2][2]   = {{1,0},{0,1}},
266       S[2]      = {1,1},
267       F[2]      = {1,0},
268       Fembed[2] = {0,1},
269       Ferror[2] = {-1.0/(1.0-GAMMA),1.0/(1.0-GAMMA)},
270       Serror[2] = {1.0-GAMMA,1.0};
271     ierr = TSGLEERegister(TSGLEE35,p,s,r,GAMMA,&A[0][0],&B[0][0],&U[0][0],&V[0][0],S,F,NULL,Fembed,Ferror,Serror,0,NULL);CHKERRQ(ierr);
272   }
273   {
274 #undef GAMMA
275 #define GAMMA 0.25
276     /* y-eps form */
277     const PetscInt
278       p = 2,
279       s = 6,
280       r = 2;
281     const PetscReal
282       A[6][6]   = {{0,0,0,0,0,0},
283                    {1,0,0,0,0,0},
284                    {0,0,0,0,0,0},
285                    {0,0,0.5,0,0,0},
286                    {0,0,0.25,0.25,0,0},
287                    {0,0,0.25,0.25,0.5,0}},
288       B[2][6]   = {{0.5,0.5,0,0,0,0},
289                    {-2.0/3.0,-2.0/3.0,1.0/3.0,1.0/3.0,1.0/3.0,1.0/3.0}},
290       U[6][2]   = {{1,0},{1,0},{1,0.75},{1,0.75},{1,0.75},{1,0.75}},
291       V[2][2]   = {{1,0},{0,1}},
292       S[2]      = {1,0},
293       F[2]      = {1,0},
294       Fembed[2] = {1,1-GAMMA},
295       Ferror[2] = {0,1},
296       Serror[2] = {1,0};
297     ierr = TSGLEERegister(TSGLEEEXRK2A,p,s,r,GAMMA,&A[0][0],&B[0][0],&U[0][0],&V[0][0],S,F,NULL,Fembed,Ferror,Serror,0,NULL);CHKERRQ(ierr);
298   }
299   {
300 #undef GAMMA
301 #define GAMMA 0.0
302     /* y-eps form */
303     const PetscInt
304       p = 3,
305       s = 8,
306       r = 2;
307     const PetscReal
308       A[8][8]   = {{0,0,0,0,0,0,0,0},
309                    {0.5,0,0,0,0,0,0,0},
310                    {-1,2,0,0,0,0,0,0},
311                    {1.0/6.0,2.0/3.0,1.0/6.0,0,0,0,0,0},
312                    {0,0,0,0,0,0,0,0},
313                    {-7.0/24.0,1.0/3.0,1.0/12.0,-1.0/8.0,0.5,0,0,0},
314                    {7.0/6.0,-4.0/3.0,-1.0/3.0,0.5,-1.0,2.0,0,0},
315                    {0,0,0,0,1.0/6.0,2.0/3.0,1.0/6.0,0}},
316       B[2][8]   = {{1.0/6.0,2.0/3.0,1.0/6.0,0,0,0,0,0},
317                    {-1.0/6.0,-2.0/3.0,-1.0/6.0,0,1.0/6.0,2.0/3.0,1.0/6.0,0}},
318       U[8][2]   = {{1,0},{1,0},{1,0},{1,0},{1,1},{1,1},{1,1},{1,1}},
319       V[2][2]   = {{1,0},{0,1}},
320       S[2]      = {1,0},
321       F[2]      = {1,0},
322       Fembed[2] = {1,1-GAMMA},
323       Ferror[2] = {0,1},
324       Serror[2] = {1,0};
325     ierr = TSGLEERegister(TSGLEERK32G1,p,s,r,GAMMA,&A[0][0],&B[0][0],&U[0][0],&V[0][0],S,F,NULL,Fembed,Ferror,Serror,0,NULL);CHKERRQ(ierr);
326   }
327   {
328 #undef GAMMA
329 #define GAMMA 0.25
330     /* y-eps form */
331     const PetscInt
332       p = 2,
333       s = 9,
334       r = 2;
335     const PetscReal
336       A[9][9]   = {{0,0,0,0,0,0,0,0,0},
337                    {0.585786437626904966,0,0,0,0,0,0,0,0},
338                    {0.149999999999999994,0.849999999999999978,0,0,0,0,0,0,0},
339                    {0,0,0,0,0,0,0,0,0},
340                    {0,0,0,0.292893218813452483,0,0,0,0,0},
341                    {0,0,0,0.0749999999999999972,0.424999999999999989,0,0,0,0},
342                    {0,0,0,0.176776695296636893,0.176776695296636893,0.146446609406726241,0,0,0},
343                    {0,0,0,0.176776695296636893,0.176776695296636893,0.146446609406726241,0.292893218813452483,0,0},
344                    {0,0,0,0.176776695296636893,0.176776695296636893,0.146446609406726241,0.0749999999999999972,0.424999999999999989,0}},
345       B[2][9]   = {{0.353553390593273786,0.353553390593273786,0.292893218813452483,0,0,0,0,0,0},
346                    {-0.471404520791031678,-0.471404520791031678,-0.390524291751269959,0.235702260395515839,0.235702260395515839,0.195262145875634979,0.235702260395515839,0.235702260395515839,0.195262145875634979}},
347       U[9][2]   = {{1,0},{1,0},{1,0},{1,0.75},{1,0.75},{1,0.75},{1,0.75},{1,0.75},{1,0.75}},
348       V[2][2]   = {{1,0},{0,1}},
349       S[2]      = {1,0},
350       F[2]      = {1,0},
351       Fembed[2] = {1,1-GAMMA},
352       Ferror[2] = {0,1},
353       Serror[2] = {1,0};
354     ierr = TSGLEERegister(TSGLEERK285EX,p,s,r,GAMMA,&A[0][0],&B[0][0],&U[0][0],&V[0][0],S,F,NULL,Fembed,Ferror,Serror,0,NULL);CHKERRQ(ierr);
355   }
356 
357   PetscFunctionReturn(0);
358 }
359 
360 /*@C
361    TSGLEERegisterDestroy - Frees the list of schemes that were registered by TSGLEERegister().
362 
363    Not Collective
364 
365    Level: advanced
366 
367 .keywords: TSGLEE, register, destroy
368 .seealso: TSGLEERegister(), TSGLEERegisterAll()
369 @*/
370 PetscErrorCode TSGLEERegisterDestroy(void)
371 {
372   PetscErrorCode ierr;
373   GLEETableauLink link;
374 
375   PetscFunctionBegin;
376   while ((link = GLEETableauList)) {
377     GLEETableau t = &link->tab;
378     GLEETableauList = link->next;
379     ierr = PetscFree5(t->A,t->B,t->U,t->V,t->c);  CHKERRQ(ierr);
380     ierr = PetscFree2(t->S,t->F);                 CHKERRQ(ierr);
381     ierr = PetscFree (t->Fembed);                 CHKERRQ(ierr);
382     ierr = PetscFree (t->Ferror);                 CHKERRQ(ierr);
383     ierr = PetscFree (t->Serror);                 CHKERRQ(ierr);
384     ierr = PetscFree (t->binterp);                CHKERRQ(ierr);
385     ierr = PetscFree (t->name);                   CHKERRQ(ierr);
386     ierr = PetscFree (link);                      CHKERRQ(ierr);
387   }
388   TSGLEERegisterAllCalled = PETSC_FALSE;
389   PetscFunctionReturn(0);
390 }
391 
392 /*@C
393   TSGLEEInitializePackage - This function initializes everything in the TSGLEE package. It is called
394   from PetscDLLibraryRegister() when using dynamic libraries, and on the first call to TSCreate_GLEE()
395   when using static libraries.
396 
397   Level: developer
398 
399 .keywords: TS, TSGLEE, initialize, package
400 .seealso: PetscInitialize()
401 @*/
402 PetscErrorCode TSGLEEInitializePackage(void)
403 {
404   PetscErrorCode ierr;
405 
406   PetscFunctionBegin;
407   if (TSGLEEPackageInitialized) PetscFunctionReturn(0);
408   TSGLEEPackageInitialized = PETSC_TRUE;
409   ierr = TSGLEERegisterAll();CHKERRQ(ierr);
410   ierr = PetscObjectComposedDataRegister(&explicit_stage_time_id);CHKERRQ(ierr);
411   ierr = PetscRegisterFinalize(TSGLEEFinalizePackage);CHKERRQ(ierr);
412   PetscFunctionReturn(0);
413 }
414 
415 /*@C
416   TSGLEEFinalizePackage - This function destroys everything in the TSGLEE package. It is
417   called from PetscFinalize().
418 
419   Level: developer
420 
421 .keywords: Petsc, destroy, package
422 .seealso: PetscFinalize()
423 @*/
424 PetscErrorCode TSGLEEFinalizePackage(void)
425 {
426   PetscErrorCode ierr;
427 
428   PetscFunctionBegin;
429   TSGLEEPackageInitialized = PETSC_FALSE;
430   ierr = TSGLEERegisterDestroy();CHKERRQ(ierr);
431   PetscFunctionReturn(0);
432 }
433 
434 /*@C
435    TSGLEERegister - register an GLEE scheme by providing the entries in the Butcher tableau
436 
437    Not Collective, but the same schemes should be registered on all processes on which they will be used
438 
439    Input Parameters:
440 +  name   - identifier for method
441 .  order  - order of method
442 .  s - number of stages
443 .  r - number of steps
444 .  gamma - LTE ratio
445 .  A - stage coefficients (dimension s*s, row-major)
446 .  B - step completion coefficients (dimension r*s, row-major)
447 .  U - method coefficients (dimension s*r, row-major)
448 .  V - method coefficients (dimension r*r, row-major)
449 .  S - starting coefficients
450 .  F - finishing coefficients
451 .  c - abscissa (dimension s; NULL to use row sums of A)
452 .  Fembed - step completion coefficients for embedded method
453 .  Ferror - error computation coefficients
454 .  Serror - error initialization coefficients
455 .  pinterp - order of interpolation (0 if unavailable)
456 -  binterp - array of interpolation coefficients (NULL if unavailable)
457 
458    Notes:
459    Several GLEE methods are provided, this function is only needed to create new methods.
460 
461    Level: advanced
462 
463 .keywords: TS, register
464 
465 .seealso: TSGLEE
466 @*/
467 PetscErrorCode TSGLEERegister(TSGLEEType name,PetscInt order,PetscInt s, PetscInt r,
468                               PetscReal gamma,
469                               const PetscReal A[],const PetscReal B[],
470                               const PetscReal U[],const PetscReal V[],
471                               const PetscReal S[],const PetscReal F[],
472                               const PetscReal c[],
473                               const PetscReal Fembed[],const PetscReal Ferror[],
474                               const PetscReal Serror[],
475                               PetscInt pinterp, const PetscReal binterp[])
476 {
477   PetscErrorCode    ierr;
478   GLEETableauLink   link;
479   GLEETableau       t;
480   PetscInt          i,j;
481 
482   PetscFunctionBegin;
483   ierr     = PetscMalloc(sizeof(*link),&link);CHKERRQ(ierr);
484   ierr     = PetscMemzero(link,sizeof(*link));CHKERRQ(ierr);
485   t        = &link->tab;
486   ierr     = PetscStrallocpy(name,&t->name);CHKERRQ(ierr);
487   t->order = order;
488   t->s     = s;
489   t->r     = r;
490   t->gamma = gamma;
491   ierr     = PetscMalloc5(s*s,&t->A,r*r,&t->V,s,&t->c,r*s,&t->B,s*r,&t->U); CHKERRQ(ierr);
492   ierr     = PetscMalloc2(r,&t->S,r,&t->F); CHKERRQ(ierr);
493   ierr     = PetscMemcpy(t->A,A,s*s*sizeof(A[0]));CHKERRQ(ierr);
494   ierr     = PetscMemcpy(t->B,B,r*s*sizeof(B[0]));CHKERRQ(ierr);
495   ierr     = PetscMemcpy(t->U,U,s*r*sizeof(U[0]));CHKERRQ(ierr);
496   ierr     = PetscMemcpy(t->V,V,r*r*sizeof(V[0]));CHKERRQ(ierr);
497   ierr     = PetscMemcpy(t->S,S,r  *sizeof(S[0]));CHKERRQ(ierr);
498   ierr     = PetscMemcpy(t->F,F,r  *sizeof(F[0]));CHKERRQ(ierr);
499   if (c) {
500     ierr   = PetscMemcpy(t->c,c,s*sizeof(c[0])); CHKERRQ(ierr);
501   } else {
502     for (i=0; i<s; i++) for (j=0,t->c[i]=0; j<s; j++) t->c[i] += A[i*s+j];
503   }
504   ierr = PetscMalloc1(r,&t->Fembed);CHKERRQ(ierr);
505   ierr = PetscMalloc1(r,&t->Ferror);CHKERRQ(ierr);
506   ierr = PetscMalloc1(r,&t->Serror);CHKERRQ(ierr);
507   ierr = PetscMemcpy(t->Fembed,Fembed,r*sizeof(Fembed[0]));CHKERRQ(ierr);
508   ierr = PetscMemcpy(t->Ferror,Ferror,r*sizeof(Ferror[0]));CHKERRQ(ierr);
509   ierr = PetscMemcpy(t->Serror,Serror,r*sizeof(Serror[0]));CHKERRQ(ierr);
510   t->pinterp = pinterp;
511   ierr       = PetscMalloc1(s*pinterp,&t->binterp);CHKERRQ(ierr);
512   ierr       = PetscMemcpy(t->binterp,binterp,s*pinterp*sizeof(binterp[0]));CHKERRQ(ierr);
513 
514   link->next      = GLEETableauList;
515   GLEETableauList = link;
516   PetscFunctionReturn(0);
517 }
518 
519 static PetscErrorCode TSEvaluateStep_GLEE(TS ts,PetscInt order,Vec X,PetscBool *done)
520 {
521   TS_GLEE         *glee = (TS_GLEE*) ts->data;
522   GLEETableau     tab = glee->tableau;
523   PetscReal       h, *B = tab->B, *V = tab->V,
524                   *F = tab->F,
525                   *Fembed = tab->Fembed;
526   PetscInt        s = tab->s, r = tab->r, i, j;
527   Vec             *Y = glee->Y, *YdotStage = glee->YdotStage;
528   PetscScalar     *ws = glee->swork, *wr = glee->rwork;
529   PetscErrorCode  ierr;
530 
531   PetscFunctionBegin;
532 
533   switch (glee->status) {
534     case TS_STEP_INCOMPLETE:
535     case TS_STEP_PENDING:
536       h = ts->time_step; break;
537     case TS_STEP_COMPLETE:
538       h = ts->ptime - ts->ptime_prev; break;
539     default: SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_PLIB,"Invalid TSStepStatus");
540   }
541 
542   if (order == tab->order) {
543 
544     /* Note: Irrespective of whether status is TS_STEP_INCOMPLETE
545              or TS_STEP_COMPLETE, glee->X has the solution at the
546              beginning of the time step. So no need to roll-back.
547     */
548     if (glee->status == TS_STEP_INCOMPLETE) {
549       for (i=0; i<r; i++) {
550         ierr = VecZeroEntries(Y[i]); CHKERRQ(ierr);
551         for (j=0; j<r; j++) wr[j] = V[i*r+j];
552         ierr = VecMAXPY(Y[i],r,wr,glee->X); CHKERRQ(ierr);
553         for (j=0; j<s; j++) ws[j] = h*B[i*s+j];
554         ierr = VecMAXPY(Y[i],s,ws,YdotStage); CHKERRQ(ierr);
555       }
556       ierr = VecZeroEntries(X);CHKERRQ(ierr);
557       for (j=0; j<r; j++) wr[j] = F[j];
558       ierr = VecMAXPY(X,r,wr,Y);CHKERRQ(ierr);
559     } else {ierr = VecCopy(ts->vec_sol,X);CHKERRQ(ierr);}
560     PetscFunctionReturn(0);
561 
562   } else if (order == tab->order-1) {
563 
564     /* Complete with the embedded method (Fembed) */
565     for (i=0; i<r; i++) {
566       ierr = VecZeroEntries(Y[i]); CHKERRQ(ierr);
567       for (j=0; j<r; j++) wr[j] = V[i*r+j];
568       ierr = VecMAXPY(Y[i],r,wr,glee->X); CHKERRQ(ierr);
569       for (j=0; j<s; j++) ws[j] = h*B[i*s+j];
570       ierr = VecMAXPY(Y[i],s,ws,YdotStage); CHKERRQ(ierr);
571     }
572     ierr = VecZeroEntries(X);CHKERRQ(ierr);
573     for (j=0; j<r; j++) wr[j] = Fembed[j];
574     ierr = VecMAXPY(X,r,wr,Y);CHKERRQ(ierr);
575 
576     if (done) *done = PETSC_TRUE;
577     PetscFunctionReturn(0);
578   }
579   if (done) *done = PETSC_FALSE;
580   else SETERRQ3(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"GLEE '%s' of order %D cannot evaluate step at order %D",tab->name,tab->order,order);
581   PetscFunctionReturn(0);
582 }
583 
584 static PetscErrorCode TSStep_GLEE(TS ts)
585 {
586   TS_GLEE         *glee = (TS_GLEE*)ts->data;
587   GLEETableau     tab = glee->tableau;
588   const PetscInt  s = tab->s, r = tab->r;
589   PetscReal       *A = tab->A, *U = tab->U,
590                   *F = tab->F,
591                   *c = tab->c;
592   Vec             *Y = glee->Y, *X = glee->X,
593                   *YStage = glee->YStage,
594                   *YdotStage = glee->YdotStage,
595                   W = glee->W;
596   SNES            snes;
597   PetscScalar     *ws = glee->swork, *wr = glee->rwork;
598   TSAdapt         adapt;
599   PetscInt        i,j,reject,next_scheme,its,lits;
600   PetscReal       next_time_step;
601   PetscReal       t;
602   PetscBool       accept;
603   PetscErrorCode  ierr;
604 
605   PetscFunctionBegin;
606   ierr = PetscCitationsRegister(citation,&cited);CHKERRQ(ierr);
607 
608   for (i=0; i<r; i++) { ierr = VecCopy(Y[i],X[i]); CHKERRQ(ierr); }
609 
610   ierr           = TSGetSNES(ts,&snes);CHKERRQ(ierr);
611   next_time_step = ts->time_step;
612   t              = ts->ptime;
613   accept         = PETSC_TRUE;
614   glee->status   = TS_STEP_INCOMPLETE;
615 
616   for (reject=0; reject<ts->max_reject && !ts->reason; reject++,ts->reject++) {
617 
618     PetscReal h = ts->time_step;
619     ierr = TSPreStep(ts);CHKERRQ(ierr);
620 
621     for (i=0; i<s; i++) {
622 
623       glee->stage_time = t + h*c[i];
624       ierr = TSPreStage(ts,glee->stage_time); CHKERRQ(ierr);
625 
626       if (A[i*s+i] == 0) {  /* Explicit stage */
627         ierr = VecZeroEntries(YStage[i]);CHKERRQ(ierr);
628         for (j=0; j<r; j++) wr[j] = U[i*r+j];
629         ierr = VecMAXPY(YStage[i],r,wr,X);CHKERRQ(ierr);
630         for (j=0; j<i; j++) ws[j] = h*A[i*s+j];
631         ierr = VecMAXPY(YStage[i],i,ws,YdotStage);CHKERRQ(ierr);
632       } else {              /* Implicit stage */
633         glee->scoeff = 1.0/A[i*s+i];
634         /* compute right-hand-side */
635         ierr = VecZeroEntries(W);CHKERRQ(ierr);
636         for (j=0; j<r; j++) wr[j] = U[i*r+j];
637         ierr = VecMAXPY(W,r,wr,X);CHKERRQ(ierr);
638         for (j=0; j<i; j++) ws[j] = h*A[i*s+j];
639         ierr = VecMAXPY(W,i,ws,YdotStage);CHKERRQ(ierr);
640         ierr = VecScale(W,glee->scoeff/h);CHKERRQ(ierr);
641         /* set initial guess */
642         ierr = VecCopy(i>0 ? YStage[i-1] : ts->vec_sol,YStage[i]);CHKERRQ(ierr);
643         /* solve for this stage */
644         ierr = SNESSolve(snes,W,YStage[i]);CHKERRQ(ierr);
645         ierr = SNESGetIterationNumber(snes,&its);CHKERRQ(ierr);
646         ierr = SNESGetLinearSolveIterations(snes,&lits);CHKERRQ(ierr);
647         ts->snes_its += its; ts->ksp_its += lits;
648       }
649       ierr = TSGetAdapt(ts,&adapt);CHKERRQ(ierr);
650       ierr = TSAdaptCheckStage(adapt,ts,glee->stage_time,YStage[i],&accept);CHKERRQ(ierr);
651       if (!accept) goto reject_step;
652       ierr = TSPostStage(ts,glee->stage_time,i,YStage); CHKERRQ(ierr);
653       ierr = TSComputeRHSFunction(ts,t+h*c[i],YStage[i],YdotStage[i]);CHKERRQ(ierr);
654     }
655     ierr = TSEvaluateStep(ts,tab->order,ts->vec_sol,NULL);CHKERRQ(ierr);
656     glee->status = TS_STEP_PENDING;
657 
658     /* Register only the current method as a candidate because we're not supporting multiple candidates yet. */
659     ierr = TSGetAdapt(ts,&adapt);CHKERRQ(ierr);
660     ierr = TSAdaptCandidatesClear(adapt);CHKERRQ(ierr);
661     ierr = TSAdaptCandidateAdd(adapt,tab->name,tab->order,1,tab->ccfl,(PetscReal)tab->s,PETSC_TRUE);CHKERRQ(ierr);
662     ierr = TSAdaptChoose(adapt,ts,ts->time_step,&next_scheme,&next_time_step,&accept);CHKERRQ(ierr);
663     if (accept) {
664       /* ignore next_scheme for now */
665       ts->ptime     += ts->time_step;
666       ts->time_step  = next_time_step;
667       glee->status = TS_STEP_COMPLETE;
668       /* compute and store the global error */
669       /* Note: this is not needed if TSAdaptGLEE is not used */
670       ierr = TSGetTimeError(ts,0,&(glee->yGErr));CHKERRQ(ierr);
671       ierr = PetscObjectComposedDataSetReal((PetscObject)ts->vec_sol,explicit_stage_time_id,ts->ptime);CHKERRQ(ierr);
672       break;
673     } else {                    /* Roll back the current step */
674       for (j=0; j<r; j++) wr[j] = F[j];
675       ierr = VecMAXPY(ts->vec_sol,r,wr,X);CHKERRQ(ierr);
676       ts->time_step = next_time_step;
677       glee->status  = TS_STEP_INCOMPLETE;
678     }
679 reject_step: continue;
680   }
681   if (glee->status != TS_STEP_COMPLETE && !ts->reason) ts->reason = TS_DIVERGED_STEP_REJECTED;
682   PetscFunctionReturn(0);
683 }
684 
685 static PetscErrorCode TSInterpolate_GLEE(TS ts,PetscReal itime,Vec X)
686 {
687   TS_GLEE         *glee = (TS_GLEE*)ts->data;
688   PetscInt        s=glee->tableau->s, pinterp=glee->tableau->pinterp,i,j;
689   PetscReal       h,tt,t;
690   PetscScalar     *b;
691   const PetscReal *B = glee->tableau->binterp;
692   PetscErrorCode  ierr;
693 
694   PetscFunctionBegin;
695   if (!B) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSGLEE %s does not have an interpolation formula",glee->tableau->name);
696   switch (glee->status) {
697     case TS_STEP_INCOMPLETE:
698     case TS_STEP_PENDING:
699       h = ts->time_step;
700       t = (itime - ts->ptime)/h;
701       break;
702     case TS_STEP_COMPLETE:
703       h = ts->ptime - ts->ptime_prev;
704       t = (itime - ts->ptime)/h + 1; /* In the interval [0,1] */
705       break;
706     default: SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_PLIB,"Invalid TSStepStatus");
707   }
708   ierr = PetscMalloc1(s,&b);CHKERRQ(ierr);
709   for (i=0; i<s; i++) b[i] = 0;
710   for (j=0,tt=t; j<pinterp; j++,tt*=t) {
711     for (i=0; i<s; i++) {
712       b[i]  += h * B[i*pinterp+j] * tt;
713     }
714   }
715   ierr = VecCopy(glee->YStage[0],X);CHKERRQ(ierr);
716   ierr = VecMAXPY(X,s,b,glee->YdotStage);CHKERRQ(ierr);
717   ierr = PetscFree(b);CHKERRQ(ierr);
718   PetscFunctionReturn(0);
719 }
720 
721 /*------------------------------------------------------------*/
722 static PetscErrorCode TSReset_GLEE(TS ts)
723 {
724   TS_GLEE        *glee = (TS_GLEE*)ts->data;
725   PetscInt       s, r;
726   PetscErrorCode ierr;
727 
728   PetscFunctionBegin;
729   if (!glee->tableau) PetscFunctionReturn(0);
730   s    = glee->tableau->s;
731   r    = glee->tableau->r;
732   ierr = VecDestroyVecs(r,&glee->Y);CHKERRQ(ierr);
733   ierr = VecDestroyVecs(r,&glee->X);CHKERRQ(ierr);
734   ierr = VecDestroyVecs(s,&glee->YStage);CHKERRQ(ierr);
735   ierr = VecDestroyVecs(s,&glee->YdotStage);CHKERRQ(ierr);
736   ierr = VecDestroy(&glee->Ydot);CHKERRQ(ierr);
737   ierr = VecDestroy(&glee->yGErr);CHKERRQ(ierr);
738   ierr = VecDestroy(&glee->W);CHKERRQ(ierr);
739   ierr = PetscFree2(glee->swork,glee->rwork);CHKERRQ(ierr);
740   PetscFunctionReturn(0);
741 }
742 
743 static PetscErrorCode TSGLEEGetVecs(TS ts,DM dm,Vec *Ydot)
744 {
745   TS_GLEE     *glee = (TS_GLEE*)ts->data;
746   PetscErrorCode ierr;
747 
748   PetscFunctionBegin;
749   if (Ydot) {
750     if (dm && dm != ts->dm) {
751       ierr = DMGetNamedGlobalVector(dm,"TSGLEE_Ydot",Ydot);CHKERRQ(ierr);
752     } else *Ydot = glee->Ydot;
753   }
754   PetscFunctionReturn(0);
755 }
756 
757 
758 static PetscErrorCode TSGLEERestoreVecs(TS ts,DM dm,Vec *Ydot)
759 {
760   PetscErrorCode ierr;
761 
762   PetscFunctionBegin;
763   if (Ydot) {
764     if (dm && dm != ts->dm) {
765       ierr = DMRestoreNamedGlobalVector(dm,"TSGLEE_Ydot",Ydot);CHKERRQ(ierr);
766     }
767   }
768   PetscFunctionReturn(0);
769 }
770 
771 /*
772   This defines the nonlinear equation that is to be solved with SNES
773 */
774 static PetscErrorCode SNESTSFormFunction_GLEE(SNES snes,Vec X,Vec F,TS ts)
775 {
776   TS_GLEE       *glee = (TS_GLEE*)ts->data;
777   DM             dm,dmsave;
778   Vec            Ydot;
779   PetscReal      shift = glee->scoeff / ts->time_step;
780   PetscErrorCode ierr;
781 
782   PetscFunctionBegin;
783   ierr   = SNESGetDM(snes,&dm);CHKERRQ(ierr);
784   ierr   = TSGLEEGetVecs(ts,dm,&Ydot);CHKERRQ(ierr);
785   /* Set Ydot = shift*X */
786   ierr   = VecCopy(X,Ydot);CHKERRQ(ierr);
787   ierr   = VecScale(Ydot,shift);CHKERRQ(ierr);
788   dmsave = ts->dm;
789   ts->dm = dm;
790 
791   ierr = TSComputeIFunction(ts,glee->stage_time,X,Ydot,F,PETSC_FALSE);CHKERRQ(ierr);
792 
793   ts->dm = dmsave;
794   ierr   = TSGLEERestoreVecs(ts,dm,&Ydot);CHKERRQ(ierr);
795   PetscFunctionReturn(0);
796 }
797 
798 static PetscErrorCode SNESTSFormJacobian_GLEE(SNES snes,Vec X,Mat A,Mat B,TS ts)
799 {
800   TS_GLEE        *glee = (TS_GLEE*)ts->data;
801   DM             dm,dmsave;
802   Vec            Ydot;
803   PetscReal      shift = glee->scoeff / ts->time_step;
804   PetscErrorCode ierr;
805 
806   PetscFunctionBegin;
807   ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr);
808   ierr = TSGLEEGetVecs(ts,dm,&Ydot);CHKERRQ(ierr);
809   /* glee->Ydot has already been computed in SNESTSFormFunction_GLEE (SNES guarantees this) */
810   dmsave = ts->dm;
811   ts->dm = dm;
812 
813   ierr = TSComputeIJacobian(ts,glee->stage_time,X,Ydot,shift,A,B,PETSC_FALSE);CHKERRQ(ierr);
814 
815   ts->dm = dmsave;
816   ierr   = TSGLEERestoreVecs(ts,dm,&Ydot);CHKERRQ(ierr);
817   PetscFunctionReturn(0);
818 }
819 
820 static PetscErrorCode DMCoarsenHook_TSGLEE(DM fine,DM coarse,void *ctx)
821 {
822   PetscFunctionBegin;
823   PetscFunctionReturn(0);
824 }
825 
826 static PetscErrorCode DMRestrictHook_TSGLEE(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse,void *ctx)
827 {
828   PetscFunctionBegin;
829   PetscFunctionReturn(0);
830 }
831 
832 
833 static PetscErrorCode DMSubDomainHook_TSGLEE(DM dm,DM subdm,void *ctx)
834 {
835   PetscFunctionBegin;
836   PetscFunctionReturn(0);
837 }
838 
839 static PetscErrorCode DMSubDomainRestrictHook_TSGLEE(DM dm,VecScatter gscat,VecScatter lscat,DM subdm,void *ctx)
840 {
841   PetscFunctionBegin;
842   PetscFunctionReturn(0);
843 }
844 
845 static PetscErrorCode TSSetUp_GLEE(TS ts)
846 {
847   TS_GLEE        *glee = (TS_GLEE*)ts->data;
848   GLEETableau    tab;
849   PetscInt       s,r;
850   PetscErrorCode ierr;
851   DM             dm;
852 
853   PetscFunctionBegin;
854   if (!glee->tableau) {
855     ierr = TSGLEESetType(ts,TSGLEEDefaultType);CHKERRQ(ierr);
856   }
857   tab  = glee->tableau;
858   s    = tab->s;
859   r    = tab->r;
860   ierr = VecDuplicateVecs(ts->vec_sol,r,&glee->Y);CHKERRQ(ierr);
861   ierr = VecDuplicateVecs(ts->vec_sol,r,&glee->X);CHKERRQ(ierr);
862   ierr = VecDuplicateVecs(ts->vec_sol,s,&glee->YStage);CHKERRQ(ierr);
863   ierr = VecDuplicateVecs(ts->vec_sol,s,&glee->YdotStage);CHKERRQ(ierr);
864   ierr = VecDuplicate(ts->vec_sol,&glee->Ydot);CHKERRQ(ierr);
865   ierr = VecDuplicate(ts->vec_sol,&glee->yGErr);CHKERRQ(ierr);
866   ierr = VecZeroEntries(glee->yGErr);CHKERRQ(ierr);
867   ierr = VecDuplicate(ts->vec_sol,&glee->W);CHKERRQ(ierr);
868   ierr = PetscMalloc2(s,&glee->swork,r,&glee->rwork); CHKERRQ(ierr);
869   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
870   ierr = DMCoarsenHookAdd(dm,DMCoarsenHook_TSGLEE,DMRestrictHook_TSGLEE,ts);CHKERRQ(ierr);
871   ierr = DMSubDomainHookAdd(dm,DMSubDomainHook_TSGLEE,DMSubDomainRestrictHook_TSGLEE,ts);CHKERRQ(ierr);
872   PetscFunctionReturn(0);
873 }
874 
875 PetscErrorCode TSStartingMethod_GLEE(TS ts)
876 {
877   TS_GLEE        *glee = (TS_GLEE*)ts->data;
878   GLEETableau    tab  = glee->tableau;
879   PetscInt       r=tab->r,i;
880   PetscReal      *S=tab->S;
881   PetscErrorCode ierr;
882 
883   PetscFunctionBegin;
884   for (i=0; i<r; i++) {
885     ierr = VecZeroEntries(glee->Y[i]);CHKERRQ(ierr);
886     ierr = VecAXPY(glee->Y[i],S[i],ts->vec_sol);CHKERRQ(ierr);
887   }
888 
889   PetscFunctionReturn(0);
890 }
891 
892 
893 /*------------------------------------------------------------*/
894 
895 static PetscErrorCode TSSetFromOptions_GLEE(PetscOptionItems *PetscOptionsObject,TS ts)
896 {
897   PetscErrorCode ierr;
898   char           gleetype[256];
899 
900   PetscFunctionBegin;
901   ierr = PetscOptionsHead(PetscOptionsObject,"GLEE ODE solver options");CHKERRQ(ierr);
902   {
903     GLEETableauLink link;
904     PetscInt        count,choice;
905     PetscBool       flg;
906     const char      **namelist;
907 
908     ierr = PetscStrncpy(gleetype,TSGLEEDefaultType,sizeof(gleetype));CHKERRQ(ierr);
909     for (link=GLEETableauList,count=0; link; link=link->next,count++) ;
910     ierr = PetscMalloc1(count,(char***)&namelist);CHKERRQ(ierr);
911     for (link=GLEETableauList,count=0; link; link=link->next,count++) namelist[count] = link->tab.name;
912     ierr = PetscOptionsEList("-ts_glee_type","Family of GLEE method","TSGLEESetType",(const char*const*)namelist,count,gleetype,&choice,&flg);CHKERRQ(ierr);
913     ierr = TSGLEESetType(ts,flg ? namelist[choice] : gleetype);CHKERRQ(ierr);
914     ierr = PetscFree(namelist);CHKERRQ(ierr);
915   }
916   ierr = PetscOptionsTail();CHKERRQ(ierr);
917   PetscFunctionReturn(0);
918 }
919 
920 static PetscErrorCode PetscFormatRealArray(char buf[],size_t len,const char *fmt,PetscInt n,const PetscReal x[])
921 {
922   PetscErrorCode ierr;
923   PetscInt       i;
924   size_t         left,count;
925   char           *p;
926 
927   PetscFunctionBegin;
928   for (i=0,p=buf,left=len; i<n; i++) {
929     ierr = PetscSNPrintfCount(p,left,fmt,&count,x[i]);CHKERRQ(ierr);
930     if (count >= left) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Insufficient space in buffer");
931     left -= count;
932     p    += count;
933     *p++  = ' ';
934   }
935   p[i ? 0 : -1] = 0;
936   PetscFunctionReturn(0);
937 }
938 
939 static PetscErrorCode TSView_GLEE(TS ts,PetscViewer viewer)
940 {
941   TS_GLEE        *glee   = (TS_GLEE*)ts->data;
942   GLEETableau    tab  = glee->tableau;
943   PetscBool      iascii;
944   PetscErrorCode ierr;
945 
946   PetscFunctionBegin;
947   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
948   if (iascii) {
949     TSGLEEType gleetype;
950     char   buf[512];
951     ierr = TSGLEEGetType(ts,&gleetype);CHKERRQ(ierr);
952     ierr = PetscViewerASCIIPrintf(viewer,"  GLEE type %s\n",gleetype);CHKERRQ(ierr);
953     ierr = PetscFormatRealArray(buf,sizeof(buf),"% 8.6f",tab->s,tab->c);CHKERRQ(ierr);
954     ierr = PetscViewerASCIIPrintf(viewer,"  Abscissa     c = %s\n",buf);CHKERRQ(ierr);
955     /* Note: print out r as well */
956   }
957   PetscFunctionReturn(0);
958 }
959 
960 static PetscErrorCode TSLoad_GLEE(TS ts,PetscViewer viewer)
961 {
962   PetscErrorCode ierr;
963   SNES           snes;
964   TSAdapt        tsadapt;
965 
966   PetscFunctionBegin;
967   ierr = TSGetAdapt(ts,&tsadapt);CHKERRQ(ierr);
968   ierr = TSAdaptLoad(tsadapt,viewer);CHKERRQ(ierr);
969   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
970   ierr = SNESLoad(snes,viewer);CHKERRQ(ierr);
971   /* function and Jacobian context for SNES when used with TS is always ts object */
972   ierr = SNESSetFunction(snes,NULL,NULL,ts);CHKERRQ(ierr);
973   ierr = SNESSetJacobian(snes,NULL,NULL,NULL,ts);CHKERRQ(ierr);
974   PetscFunctionReturn(0);
975 }
976 
977 /*@C
978   TSGLEESetType - Set the type of GLEE scheme
979 
980   Logically collective
981 
982   Input Parameter:
983 +  ts - timestepping context
984 -  gleetype - type of GLEE-scheme
985 
986   Level: intermediate
987 
988 .seealso: TSGLEEGetType(), TSGLEE
989 @*/
990 PetscErrorCode TSGLEESetType(TS ts,TSGLEEType gleetype)
991 {
992   PetscErrorCode ierr;
993 
994   PetscFunctionBegin;
995   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
996   PetscValidCharPointer(gleetype,2);
997   ierr = PetscTryMethod(ts,"TSGLEESetType_C",(TS,TSGLEEType),(ts,gleetype));CHKERRQ(ierr);
998   PetscFunctionReturn(0);
999 }
1000 
1001 /*@C
1002   TSGLEEGetType - Get the type of GLEE scheme
1003 
1004   Logically collective
1005 
1006   Input Parameter:
1007 .  ts - timestepping context
1008 
1009   Output Parameter:
1010 .  gleetype - type of GLEE-scheme
1011 
1012   Level: intermediate
1013 
1014 .seealso: TSGLEESetType()
1015 @*/
1016 PetscErrorCode TSGLEEGetType(TS ts,TSGLEEType *gleetype)
1017 {
1018   PetscErrorCode ierr;
1019 
1020   PetscFunctionBegin;
1021   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1022   ierr = PetscUseMethod(ts,"TSGLEEGetType_C",(TS,TSGLEEType*),(ts,gleetype));CHKERRQ(ierr);
1023   PetscFunctionReturn(0);
1024 }
1025 
1026 PetscErrorCode  TSGLEEGetType_GLEE(TS ts,TSGLEEType *gleetype)
1027 {
1028   TS_GLEE     *glee = (TS_GLEE*)ts->data;
1029   PetscErrorCode ierr;
1030 
1031   PetscFunctionBegin;
1032   if (!glee->tableau) {
1033     ierr = TSGLEESetType(ts,TSGLEEDefaultType);CHKERRQ(ierr);
1034   }
1035   *gleetype = glee->tableau->name;
1036   PetscFunctionReturn(0);
1037 }
1038 PetscErrorCode  TSGLEESetType_GLEE(TS ts,TSGLEEType gleetype)
1039 {
1040   TS_GLEE         *glee = (TS_GLEE*)ts->data;
1041   PetscErrorCode  ierr;
1042   PetscBool       match;
1043   GLEETableauLink link;
1044 
1045   PetscFunctionBegin;
1046   if (glee->tableau) {
1047     ierr = PetscStrcmp(glee->tableau->name,gleetype,&match);CHKERRQ(ierr);
1048     if (match) PetscFunctionReturn(0);
1049   }
1050   for (link = GLEETableauList; link; link=link->next) {
1051     ierr = PetscStrcmp(link->tab.name,gleetype,&match);CHKERRQ(ierr);
1052     if (match) {
1053       ierr = TSReset_GLEE(ts);CHKERRQ(ierr);
1054       glee->tableau = &link->tab;
1055       PetscFunctionReturn(0);
1056     }
1057   }
1058   SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_UNKNOWN_TYPE,"Could not find '%s'",gleetype);
1059   PetscFunctionReturn(0);
1060 }
1061 
1062 static PetscErrorCode  TSGetStages_GLEE(TS ts,PetscInt *ns,Vec **Y)
1063 {
1064   TS_GLEE *glee = (TS_GLEE*)ts->data;
1065 
1066   PetscFunctionBegin;
1067   *ns = glee->tableau->s;
1068   if(Y) *Y  = glee->YStage;
1069   PetscFunctionReturn(0);
1070 }
1071 
1072 PetscErrorCode TSGetSolutionComponents_GLEE(TS ts,PetscInt *n,Vec *Y)
1073 {
1074   TS_GLEE         *glee = (TS_GLEE*)ts->data;
1075   GLEETableau     tab   = glee->tableau;
1076   PetscErrorCode  ierr;
1077 
1078   PetscFunctionBegin;
1079   if (!Y) *n = tab->r;
1080   else {
1081     if ((*n >= 0) && (*n < tab->r)) {
1082       ierr = VecCopy(glee->Y[*n],*Y); CHKERRQ(ierr);
1083     } else SETERRQ3(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Second argument (%d) out of range[%d,%d].",*n,0,tab->r-1);
1084   }
1085   PetscFunctionReturn(0);
1086 }
1087 
1088 PetscErrorCode TSGetAuxSolution_GLEE(TS ts,Vec *X)
1089 {
1090   TS_GLEE         *glee = (TS_GLEE*)ts->data;
1091   GLEETableau     tab   = glee->tableau;
1092   PetscReal       *F    = tab->Fembed;
1093   PetscInt        r     = tab->r;
1094   Vec             *Y    = glee->Y;
1095   PetscScalar     *wr   = glee->rwork;
1096   PetscInt        i;
1097   PetscErrorCode  ierr;
1098 
1099   PetscFunctionBegin;
1100   ierr = VecZeroEntries(*X);CHKERRQ(ierr);
1101   for (i=0; i<r; i++) wr[i] = F[i];
1102   ierr = VecMAXPY((*X),r,wr,Y);CHKERRQ(ierr);
1103   PetscFunctionReturn(0);
1104 }
1105 
1106 PetscErrorCode TSGetTimeError_GLEE(TS ts,PetscInt n,Vec *X)
1107 {
1108   TS_GLEE         *glee = (TS_GLEE*)ts->data;
1109   GLEETableau     tab   = glee->tableau;
1110   PetscReal       *F    = tab->Ferror;
1111   PetscInt        r     = tab->r;
1112   Vec             *Y    = glee->Y;
1113   PetscScalar     *wr   = glee->rwork;
1114   PetscInt        i;
1115   PetscErrorCode  ierr;
1116 
1117   PetscFunctionBegin;
1118   ierr = VecZeroEntries(*X);CHKERRQ(ierr);
1119   if(n==0){
1120     for (i=0; i<r; i++) wr[i] = F[i];
1121     ierr = VecMAXPY((*X),r,wr,Y);CHKERRQ(ierr);
1122   } else if(n==-1) {
1123     *X=glee->yGErr;
1124   }
1125   PetscFunctionReturn(0);
1126 }
1127 
1128 PetscErrorCode TSSetTimeError_GLEE(TS ts,Vec X)
1129 {
1130   TS_GLEE         *glee = (TS_GLEE*)ts->data;
1131   GLEETableau     tab   = glee->tableau;
1132   PetscReal       *S    = tab->Serror;
1133   PetscInt        r     = tab->r,i;
1134   Vec             *Y    = glee->Y;
1135   PetscErrorCode  ierr;
1136 
1137   PetscFunctionBegin;
1138   if (r != 2) SETERRQ2(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSSetTimeError_GLEE not supported for '%s' with r=%D.",tab->name,tab->r);
1139   for (i=1; i<r; i++) {
1140     ierr = VecCopy(ts->vec_sol,Y[i]); CHKERRQ(ierr);
1141     ierr = VecAXPBY(Y[i],S[0],S[1],X); CHKERRQ(ierr);
1142     ierr = VecCopy(X,glee->yGErr); CHKERRQ(ierr);
1143   }
1144   PetscFunctionReturn(0);
1145 }
1146 
1147 static PetscErrorCode TSDestroy_GLEE(TS ts)
1148 {
1149   PetscErrorCode ierr;
1150 
1151   PetscFunctionBegin;
1152   ierr = TSReset_GLEE(ts);CHKERRQ(ierr);
1153   if (ts->dm) {
1154     ierr = DMCoarsenHookRemove(ts->dm,DMCoarsenHook_TSGLEE,DMRestrictHook_TSGLEE,ts);CHKERRQ(ierr);
1155     ierr = DMSubDomainHookRemove(ts->dm,DMSubDomainHook_TSGLEE,DMSubDomainRestrictHook_TSGLEE,ts);CHKERRQ(ierr);
1156   }
1157   ierr = PetscFree(ts->data);CHKERRQ(ierr);
1158   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSGLEEGetType_C",NULL);CHKERRQ(ierr);
1159   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSGLEESetType_C",NULL);CHKERRQ(ierr);
1160   PetscFunctionReturn(0);
1161 }
1162 
1163 /* ------------------------------------------------------------ */
1164 /*MC
1165       TSGLEE - ODE and DAE solver using General Linear with Error Estimation schemes
1166 
1167   The user should provide the right hand side of the equation
1168   using TSSetRHSFunction().
1169 
1170   Notes:
1171   The default is TSGLEE35, it can be changed with TSGLEESetType() or -ts_glee_type
1172 
1173   Level: beginner
1174 
1175 .seealso:  TSCreate(), TS, TSSetType(), TSGLEESetType(), TSGLEEGetType(),
1176            TSGLEE23, TTSGLEE24, TSGLEE35, TSGLEE25I, TSGLEEEXRK2A,
1177            TSGLEERK32G1, TSGLEERK285EX, TSGLEEType, TSGLEERegister()
1178 
1179 M*/
1180 PETSC_EXTERN PetscErrorCode TSCreate_GLEE(TS ts)
1181 {
1182   TS_GLEE         *th;
1183   PetscErrorCode  ierr;
1184 
1185   PetscFunctionBegin;
1186 #if !defined(PETSC_USE_DYNAMIC_LIBRARIES)
1187   ierr = TSGLEEInitializePackage();CHKERRQ(ierr);
1188 #endif
1189 
1190   ts->ops->reset                  = TSReset_GLEE;
1191   ts->ops->destroy                = TSDestroy_GLEE;
1192   ts->ops->view                   = TSView_GLEE;
1193   ts->ops->load                   = TSLoad_GLEE;
1194   ts->ops->setup                  = TSSetUp_GLEE;
1195   ts->ops->step                   = TSStep_GLEE;
1196   ts->ops->interpolate            = TSInterpolate_GLEE;
1197   ts->ops->evaluatestep           = TSEvaluateStep_GLEE;
1198   ts->ops->setfromoptions         = TSSetFromOptions_GLEE;
1199   ts->ops->getstages              = TSGetStages_GLEE;
1200   ts->ops->snesfunction           = SNESTSFormFunction_GLEE;
1201   ts->ops->snesjacobian           = SNESTSFormJacobian_GLEE;
1202   ts->ops->getsolutioncomponents  = TSGetSolutionComponents_GLEE;
1203   ts->ops->getauxsolution         = TSGetAuxSolution_GLEE;
1204   ts->ops->gettimeerror           = TSGetTimeError_GLEE;
1205   ts->ops->settimeerror           = TSSetTimeError_GLEE;
1206   ts->ops->startingmethod         = TSStartingMethod_GLEE;
1207   ts->default_adapt_type          = TSADAPTGLEE;
1208 
1209   ts->usessnes = PETSC_TRUE;
1210 
1211   ierr = PetscNewLog(ts,&th);CHKERRQ(ierr);
1212   ts->data = (void*)th;
1213 
1214   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSGLEEGetType_C",TSGLEEGetType_GLEE);CHKERRQ(ierr);
1215   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSGLEESetType_C",TSGLEESetType_GLEE);CHKERRQ(ierr);
1216   PetscFunctionReturn(0);
1217 }
1218