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