xref: /petsc/src/ts/impls/rosw/rosw.c (revision 4e269d778a4980f937dbf53e8c867b2c3b45d02b)
1 /*
2   Code for timestepping with Rosenbrock W methods
3 
4   Notes:
5   The general system is written as
6 
7   G(t,X,Xdot) = F(t,X)
8 
9   where G represents the stiff part of the physics and F represents the non-stiff part.
10   This method is designed to be linearly implicit on G and can use an approximate and lagged Jacobian.
11 
12 */
13 #include <petsc-private/tsimpl.h>                /*I   "petscts.h"   I*/
14 
15 #include <../src/mat/blockinvert.h>
16 
17 static const TSRosWType TSRosWDefault = TSROSWRA34PW2;
18 static PetscBool TSRosWRegisterAllCalled;
19 static PetscBool TSRosWPackageInitialized;
20 
21 typedef struct _RosWTableau *RosWTableau;
22 struct _RosWTableau {
23   char      *name;
24   PetscInt  order;              /* Classical approximation order of the method */
25   PetscInt  s;                  /* Number of stages */
26   PetscInt  pinterp;            /* Interpolation order */
27   PetscReal *A;                 /* Propagation table, strictly lower triangular */
28   PetscReal *Gamma;             /* Stage table, lower triangular with nonzero diagonal */
29   PetscBool *GammaZeroDiag;     /* Diagonal entries that are zero in stage table Gamma, vector indicating explicit statages */
30   PetscReal *GammaExplicitCorr; /* Coefficients for correction terms needed for explicit stages in transformed variables*/
31   PetscReal *b;                 /* Step completion table */
32   PetscReal *bembed;            /* Step completion table for embedded method of order one less */
33   PetscReal *ASum;              /* Row sum of A */
34   PetscReal *GammaSum;          /* Row sum of Gamma, only needed for non-autonomous systems */
35   PetscReal *At;                /* Propagation table in transformed variables */
36   PetscReal *bt;                /* Step completion table in transformed variables */
37   PetscReal *bembedt;           /* Step completion table of order one less in transformed variables */
38   PetscReal *GammaInv;          /* Inverse of Gamma, used for transformed variables */
39   PetscReal ccfl;               /* Placeholder for CFL coefficient relative to forward Euler */
40   PetscReal *binterpt;          /* Dense output formula */
41 };
42 typedef struct _RosWTableauLink *RosWTableauLink;
43 struct _RosWTableauLink {
44   struct _RosWTableau tab;
45   RosWTableauLink next;
46 };
47 static RosWTableauLink RosWTableauList;
48 
49 typedef struct {
50   RosWTableau tableau;
51   Vec         *Y;               /* States computed during the step, used to complete the step */
52   Vec         Ydot;             /* Work vector holding Ydot during residual evaluation */
53   Vec         Ystage;           /* Work vector for the state value at each stage */
54   Vec         Zdot;             /* Ydot = Zdot + shift*Y */
55   Vec         Zstage;           /* Y = Zstage + Y */
56   Vec         VecSolPrev;       /* Work vector holding the solution from the previous step (used for interpolation)*/
57   PetscScalar *work;            /* Scalar work space of length number of stages, used to prepare VecMAXPY() */
58   PetscReal   shift;
59   PetscReal   stage_time;
60   PetscReal   stage_explicit;     /* Flag indicates that the current stage is explicit */
61   PetscBool   recompute_jacobian; /* Recompute the Jacobian at each stage, default is to freeze the Jacobian at the start of each step */
62   TSStepStatus status;
63 } TS_RosW;
64 
65 /*MC
66      TSROSWTHETA1 - One stage first order L-stable Rosenbrock-W scheme (aka theta method).
67 
68      Only an approximate Jacobian is needed.
69 
70      Level: intermediate
71 
72 .seealso: TSROSW
73 M*/
74 
75 /*MC
76      TSROSWTHETA2 - One stage second order A-stable Rosenbrock-W scheme (aka theta method).
77 
78      Only an approximate Jacobian is needed.
79 
80      Level: intermediate
81 
82 .seealso: TSROSW
83 M*/
84 
85 /*MC
86      TSROSW2M - Two stage second order L-stable Rosenbrock-W scheme.
87 
88      Only an approximate Jacobian is needed. By default, it is only recomputed once per step. This method is a reflection of TSROSW2P.
89 
90      Level: intermediate
91 
92 .seealso: TSROSW
93 M*/
94 
95 /*MC
96      TSROSW2P - Two stage second order L-stable Rosenbrock-W scheme.
97 
98      Only an approximate Jacobian is needed. By default, it is only recomputed once per step. This method is a reflection of TSROSW2M.
99 
100      Level: intermediate
101 
102 .seealso: TSROSW
103 M*/
104 
105 /*MC
106      TSROSWRA3PW - Three stage third order Rosenbrock-W scheme for PDAE of index 1.
107 
108      Only an approximate Jacobian is needed. By default, it is only recomputed once per step.
109 
110      This is strongly A-stable with R(infty) = 0.73. The embedded method of order 2 is strongly A-stable with R(infty) = 0.73.
111 
112      References:
113      Rang and Angermann, New Rosenbrock-W methods of order 3 for partial differential algebraic equations of index 1, 2005.
114 
115      Level: intermediate
116 
117 .seealso: TSROSW
118 M*/
119 
120 /*MC
121      TSROSWRA34PW2 - Four stage third order L-stable Rosenbrock-W scheme for PDAE of index 1.
122 
123      Only an approximate Jacobian is needed. By default, it is only recomputed once per step.
124 
125      This is strongly A-stable with R(infty) = 0. The embedded method of order 2 is strongly A-stable with R(infty) = 0.48.
126 
127      References:
128      Rang and Angermann, New Rosenbrock-W methods of order 3 for partial differential algebraic equations of index 1, 2005.
129 
130      Level: intermediate
131 
132 .seealso: TSROSW
133 M*/
134 
135 /*MC
136      TSROSWRODAS3 - Four stage third order L-stable Rosenbrock scheme
137 
138      By default, the Jacobian is only recomputed once per step.
139 
140      Both the third order and embedded second order methods are stiffly accurate and L-stable.
141 
142      References:
143      Sandu et al, Benchmarking stiff ODE solvers for atmospheric chemistry problems II, Rosenbrock solvers, 1997.
144 
145      Level: intermediate
146 
147 .seealso: TSROSW, TSROSWSANDU3
148 M*/
149 
150 /*MC
151      TSROSWSANDU3 - Three stage third order L-stable Rosenbrock scheme
152 
153      By default, the Jacobian is only recomputed once per step.
154 
155      The third order method is L-stable, but not stiffly accurate.
156      The second order embedded method is strongly A-stable with R(infty) = 0.5.
157      The internal stages are L-stable.
158      This method is called ROS3 in the paper.
159 
160      References:
161      Sandu et al, Benchmarking stiff ODE solvers for atmospheric chemistry problems II, Rosenbrock solvers, 1997.
162 
163      Level: intermediate
164 
165 .seealso: TSROSW, TSROSWRODAS3
166 M*/
167 
168 /*MC
169      TSROSWASSP3P3S1C - A-stable Rosenbrock-W method with SSP explicit part, third order, three stages
170 
171      By default, the Jacobian is only recomputed once per step.
172 
173      A-stable SPP explicit order 3, 3 stages, CFL 1 (eff = 1/3)
174 
175      References:
176      Emil Constantinescu
177 
178      Level: intermediate
179 
180 .seealso: TSROSW, TSROSWLASSP3P4S2C, TSROSWLLSSP3P4S2C, SSP
181 M*/
182 
183 /*MC
184      TSROSWLASSP3P4S2C - L-stable Rosenbrock-W method with SSP explicit part, third order, four stages
185 
186      By default, the Jacobian is only recomputed once per step.
187 
188      L-stable (A-stable embedded) SPP explicit order 3, 4 stages, CFL 2 (eff = 1/2)
189 
190      References:
191      Emil Constantinescu
192 
193      Level: intermediate
194 
195 .seealso: TSROSW, TSROSWASSP3P3S1C, TSROSWLLSSP3P4S2C, TSSSP
196 M*/
197 
198 /*MC
199      TSROSWLLSSP3P4S2C - L-stable Rosenbrock-W method with SSP explicit part, third order, four stages
200 
201      By default, the Jacobian is only recomputed once per step.
202 
203      L-stable (L-stable embedded) SPP explicit order 3, 4 stages, CFL 2 (eff = 1/2)
204 
205      References:
206      Emil Constantinescu
207 
208      Level: intermediate
209 
210 .seealso: TSROSW, TSROSWASSP3P3S1C, TSROSWLASSP3P4S2C, TSSSP
211 M*/
212 
213 /*MC
214      TSROSWGRK4T - four stage, fourth order Rosenbrock (not W) method from Kaps and Rentrop
215 
216      By default, the Jacobian is only recomputed once per step.
217 
218      A(89.3 degrees)-stable, |R(infty)| = 0.454.
219 
220      This method does not provide a dense output formula.
221 
222      References:
223      Kaps and Rentrop, Generalized Runge-Kutta methods of order four with stepsize control for stiff ordinary differential equations, 1979.
224 
225      Hairer and Wanner, Solving Ordinary Differential Equations II, Section 4 Table 7.2.
226 
227      Hairer's code ros4.f
228 
229      Level: intermediate
230 
231 .seealso: TSROSW, TSROSWSHAMP4, TSROSWVELDD4, TSROSW4L
232 M*/
233 
234 /*MC
235      TSROSWSHAMP4 - four stage, fourth order Rosenbrock (not W) method from Shampine
236 
237      By default, the Jacobian is only recomputed once per step.
238 
239      A-stable, |R(infty)| = 1/3.
240 
241      This method does not provide a dense output formula.
242 
243      References:
244      Shampine, Implementation of Rosenbrock methods, 1982.
245 
246      Hairer and Wanner, Solving Ordinary Differential Equations II, Section 4 Table 7.2.
247 
248      Hairer's code ros4.f
249 
250      Level: intermediate
251 
252 .seealso: TSROSW, TSROSWGRK4T, TSROSWVELDD4, TSROSW4L
253 M*/
254 
255 /*MC
256      TSROSWVELDD4 - four stage, fourth order Rosenbrock (not W) method from van Veldhuizen
257 
258      By default, the Jacobian is only recomputed once per step.
259 
260      A(89.5 degrees)-stable, |R(infty)| = 0.24.
261 
262      This method does not provide a dense output formula.
263 
264      References:
265      van Veldhuizen, D-stability and Kaps-Rentrop methods, 1984.
266 
267      Hairer and Wanner, Solving Ordinary Differential Equations II, Section 4 Table 7.2.
268 
269      Hairer's code ros4.f
270 
271      Level: intermediate
272 
273 .seealso: TSROSW, TSROSWGRK4T, TSROSWSHAMP4, TSROSW4L
274 M*/
275 
276 /*MC
277      TSROSW4L - four stage, fourth order Rosenbrock (not W) method
278 
279      By default, the Jacobian is only recomputed once per step.
280 
281      A-stable and L-stable
282 
283      This method does not provide a dense output formula.
284 
285      References:
286      Hairer and Wanner, Solving Ordinary Differential Equations II, Section 4 Table 7.2.
287 
288      Hairer's code ros4.f
289 
290      Level: intermediate
291 
292 .seealso: TSROSW, TSROSWGRK4T, TSROSWSHAMP4, TSROSW4L
293 M*/
294 
295 #undef __FUNCT__
296 #define __FUNCT__ "TSRosWRegisterAll"
297 /*@C
298   TSRosWRegisterAll - Registers all of the additive Runge-Kutta implicit-explicit methods in TSRosW
299 
300   Not Collective, but should be called by all processes which will need the schemes to be registered
301 
302   Level: advanced
303 
304 .keywords: TS, TSRosW, register, all
305 
306 .seealso:  TSRosWRegisterDestroy()
307 @*/
308 PetscErrorCode TSRosWRegisterAll(void)
309 {
310   PetscErrorCode ierr;
311 
312   PetscFunctionBegin;
313   if (TSRosWRegisterAllCalled) PetscFunctionReturn(0);
314   TSRosWRegisterAllCalled = PETSC_TRUE;
315 
316   {
317     const PetscReal
318       A = 0,
319       Gamma = 1,
320       b = 1,
321       binterpt=1;
322 
323     ierr = TSRosWRegister(TSROSWTHETA1,1,1,&A,&Gamma,&b,PETSC_NULL,1,&binterpt);CHKERRQ(ierr);
324   }
325 
326   {
327     const PetscReal
328       A= 0,
329       Gamma = 0.5,
330       b = 1,
331       binterpt=1;
332     ierr = TSRosWRegister(TSROSWTHETA2,2,1,&A,&Gamma,&b,PETSC_NULL,1,&binterpt);CHKERRQ(ierr);
333   }
334 
335   {
336     const PetscReal g = 1. + 1./PetscSqrtReal(2.0);
337     const PetscReal
338       A[2][2] = {{0,0}, {1.,0}},
339       Gamma[2][2] = {{g,0}, {-2.*g,g}},
340       b[2] = {0.5,0.5},
341       b1[2] = {1.0,0.0};
342       PetscReal  binterpt[2][2];
343       binterpt[0][0]=g-1.0;
344       binterpt[1][0]=2.0-g;
345       binterpt[0][1]=g-1.5;
346       binterpt[1][1]=1.5-g;
347       ierr = TSRosWRegister(TSROSW2P,2,2,&A[0][0],&Gamma[0][0],b,b1,2,&binterpt[0][0]);CHKERRQ(ierr);
348   }
349   {
350     const PetscReal g = 1. - 1./PetscSqrtReal(2.0);
351     const PetscReal
352       A[2][2] = {{0,0}, {1.,0}},
353       Gamma[2][2] = {{g,0}, {-2.*g,g}},
354       b[2] = {0.5,0.5},
355       b1[2] = {1.0,0.0};
356       PetscReal  binterpt[2][2];
357       binterpt[0][0]=g-1.0;
358       binterpt[1][0]=2.0-g;
359       binterpt[0][1]=g-1.5;
360       binterpt[1][1]=1.5-g;
361     ierr = TSRosWRegister(TSROSW2M,2,2,&A[0][0],&Gamma[0][0],b,b1,2,&binterpt[0][0]);CHKERRQ(ierr);
362   }
363   {
364     const PetscReal g = 7.8867513459481287e-01;
365     PetscReal  binterpt[3][2];
366     const PetscReal
367       A[3][3] = {{0,0,0},
368                  {1.5773502691896257e+00,0,0},
369                  {0.5,0,0}},
370       Gamma[3][3] = {{g,0,0},
371                      {-1.5773502691896257e+00,g,0},
372                      {-6.7075317547305480e-01,-1.7075317547305482e-01,g}},
373       b[3] = {1.0566243270259355e-01,4.9038105676657971e-02,8.4529946162074843e-01},
374       b2[3] = {-1.7863279495408180e-01,1./3.,8.4529946162074843e-01};
375 
376       binterpt[0][0]=-0.8094010767585034;
377       binterpt[1][0]=-0.5;
378       binterpt[2][0]=2.3094010767585034;
379       binterpt[0][1]=0.9641016151377548;
380       binterpt[1][1]=0.5;
381       binterpt[2][1]=-1.4641016151377548;
382       ierr = TSRosWRegister(TSROSWRA3PW,3,3,&A[0][0],&Gamma[0][0],b,b2,2,&binterpt[0][0]);CHKERRQ(ierr);
383   }
384   {
385     PetscReal  binterpt[4][3];
386     const PetscReal g = 4.3586652150845900e-01;
387     const PetscReal
388       A[4][4] = {{0,0,0,0},
389                  {8.7173304301691801e-01,0,0,0},
390                  {8.4457060015369423e-01,-1.1299064236484185e-01,0,0},
391                  {0,0,1.,0}},
392       Gamma[4][4] = {{g,0,0,0},
393                      {-8.7173304301691801e-01,g,0,0},
394                      {-9.0338057013044082e-01,5.4180672388095326e-02,g,0},
395                      {2.4212380706095346e-01,-1.2232505839045147e+00,5.4526025533510214e-01,g}},
396         b[4] = {2.4212380706095346e-01,-1.2232505839045147e+00,1.5452602553351020e+00,4.3586652150845900e-01},
397           b2[4] = {3.7810903145819369e-01,-9.6042292212423178e-02,5.0000000000000000e-01,2.1793326075422950e-01};
398 
399           binterpt[0][0]=1.0564298455794094;
400           binterpt[1][0]=2.296429974281067;
401           binterpt[2][0]=-1.307599564525376;
402           binterpt[3][0]=-1.045260255335102;
403           binterpt[0][1]=-1.3864882699759573;
404           binterpt[1][1]=-8.262611700275677;
405           binterpt[2][1]=7.250979895056055;
406           binterpt[3][1]=2.398120075195581;
407           binterpt[0][2]=0.5721822314575016;
408           binterpt[1][2]=4.742931142090097;
409           binterpt[2][2]=-4.398120075195578;
410           binterpt[3][2]=-0.9169932983520199;
411 
412           ierr = TSRosWRegister(TSROSWRA34PW2,3,4,&A[0][0],&Gamma[0][0],b,b2,3,&binterpt[0][0]);CHKERRQ(ierr);
413   }
414   {
415     const PetscReal g = 0.5;
416     const PetscReal
417       A[4][4] = {{0,0,0,0},
418                  {0,0,0,0},
419                  {1.,0,0,0},
420                  {0.75,-0.25,0.5,0}},
421       Gamma[4][4] = {{g,0,0,0},
422                      {1.,g,0,0},
423                      {-0.25,-0.25,g,0},
424                      {1./12,1./12,-2./3,g}},
425       b[4] = {5./6,-1./6,-1./6,0.5},
426       b2[4] = {0.75,-0.25,0.5,0};
427     ierr = TSRosWRegister(TSROSWRODAS3,3,4,&A[0][0],&Gamma[0][0],b,b2,0,PETSC_NULL);CHKERRQ(ierr);
428   }
429   {
430     const PetscReal g = 0.43586652150845899941601945119356;
431     const PetscReal
432       A[3][3] = {{0,0,0},
433                  {g,0,0},
434                  {g,0,0}},
435       Gamma[3][3] = {{g,0,0},
436                      {-0.19294655696029095575009695436041,g,0},
437                      {0,1.74927148125794685173529749738960,g}},
438       b[3] = {-0.75457412385404315829818998646589,1.94100407061964420292840123379419,-0.18642994676560104463021124732829},
439       b2[3] = {-1.53358745784149585370766523913002,2.81745131148625772213931745457622,-0.28386385364476186843165221544619};
440 
441       PetscReal  binterpt[3][2];
442       binterpt[0][0]=3.793692883777660870425141387941;
443       binterpt[1][0]=-2.918692883777660870425141387941;
444       binterpt[2][0]=0.125;
445       binterpt[0][1]=-0.725741064379812106687651020584;
446       binterpt[1][1]=0.559074397713145440020984353917;
447       binterpt[2][1]=0.16666666666666666666666666666667;
448 
449       ierr = TSRosWRegister(TSROSWSANDU3,3,3,&A[0][0],&Gamma[0][0],b,b2,2,&binterpt[0][0]);CHKERRQ(ierr);
450   }
451   {
452     const PetscReal s3 = PetscSqrtReal(3.),g = (3.0+s3)/6.0;
453     const PetscReal
454       A[3][3] = {{0,0,0},
455                  {1,0,0},
456                  {0.25,0.25,0}},
457       Gamma[3][3] = {{0,0,0},
458                      {(-3.0-s3)/6.0,g,0},
459                      {(-3.0-s3)/24.0,(-3.0-s3)/8.0,g}},
460         b[3] = {1./6.,1./6.,2./3.},
461           b2[3] = {1./4.,1./4.,1./2.};
462 
463         PetscReal  binterpt[3][2];
464         binterpt[0][0]=0.089316397477040902157517886164709;
465         binterpt[1][0]=-0.91068360252295909784248211383529;
466         binterpt[2][0]=1.8213672050459181956849642276706;
467         binterpt[0][1]=0.077350269189625764509148780501957;
468         binterpt[1][1]=1.077350269189625764509148780502;
469         binterpt[2][1]=-1.1547005383792515290182975610039;
470     ierr = TSRosWRegister(TSROSWASSP3P3S1C,3,3,&A[0][0],&Gamma[0][0],b,b2,2,&binterpt[0][0]);CHKERRQ(ierr);
471   }
472 
473   {
474     const PetscReal
475       A[4][4] = {{0,0,0,0},
476                  {1./2.,0,0,0},
477                  {1./2.,1./2.,0,0},
478                  {1./6.,1./6.,1./6.,0}},
479       Gamma[4][4] = {{1./2.,0,0,0},
480                      {0.0,1./4.,0,0},
481                      {-2.,-2./3.,2./3.,0},
482                      {1./2.,5./36.,-2./9,0}},
483         b[4] = {1./6.,1./6.,1./6.,1./2.},
484         b2[4] = {1./8.,3./4.,1./8.,0};
485         PetscReal  binterpt[4][3];
486         binterpt[0][0]=6.25;
487         binterpt[1][0]=-30.25;
488         binterpt[2][0]=1.75;
489         binterpt[3][0]=23.25;
490         binterpt[0][1]=-9.75;
491         binterpt[1][1]=58.75;
492         binterpt[2][1]=-3.25;
493         binterpt[3][1]=-45.75;
494         binterpt[0][2]=3.6666666666666666666666666666667;
495         binterpt[1][2]=-28.333333333333333333333333333333;
496         binterpt[2][2]=1.6666666666666666666666666666667;
497         binterpt[3][2]=23.;
498         ierr = TSRosWRegister(TSROSWLASSP3P4S2C,3,4,&A[0][0],&Gamma[0][0],b,b2,3,&binterpt[0][0]);CHKERRQ(ierr);
499   }
500 
501   {
502     const PetscReal
503       A[4][4] = {{0,0,0,0},
504                  {1./2.,0,0,0},
505                  {1./2.,1./2.,0,0},
506                  {1./6.,1./6.,1./6.,0}},
507       Gamma[4][4] = {{1./2.,0,0,0},
508                      {0.0,3./4.,0,0},
509                      {-2./3.,-23./9.,2./9.,0},
510                      {1./18.,65./108.,-2./27,0}},
511         b[4] = {1./6.,1./6.,1./6.,1./2.},
512         b2[4] = {3./16.,10./16.,3./16.,0};
513 
514         PetscReal  binterpt[4][3];
515         binterpt[0][0]=1.6911764705882352941176470588235;
516         binterpt[1][0]=3.6813725490196078431372549019608;
517         binterpt[2][0]=0.23039215686274509803921568627451;
518         binterpt[3][0]=-4.6029411764705882352941176470588;
519         binterpt[0][1]=-0.95588235294117647058823529411765;
520         binterpt[1][1]=-6.2401960784313725490196078431373;
521         binterpt[2][1]=-0.31862745098039215686274509803922;
522         binterpt[3][1]=7.5147058823529411764705882352941;
523         binterpt[0][2]=-0.56862745098039215686274509803922;
524         binterpt[1][2]=2.7254901960784313725490196078431;
525         binterpt[2][2]=0.25490196078431372549019607843137;
526         binterpt[3][2]=-2.4117647058823529411764705882353;
527         ierr = TSRosWRegister(TSROSWLLSSP3P4S2C,3,4,&A[0][0],&Gamma[0][0],b,b2,3,&binterpt[0][0]);CHKERRQ(ierr);
528   }
529 
530   {
531     PetscReal A[4][4],Gamma[4][4],b[4],b2[4];
532     PetscReal  binterpt[4][3];
533 
534     Gamma[0][0]=0.4358665215084589994160194475295062513822671686978816;
535     Gamma[0][1]=0; Gamma[0][2]=0; Gamma[0][3]=0;
536     Gamma[1][0]=-1.997527830934941248426324674704153457289527280554476;
537     Gamma[1][1]=0.4358665215084589994160194475295062513822671686978816;
538     Gamma[1][2]=0; Gamma[1][3]=0;
539     Gamma[2][0]=-1.007948511795029620852002345345404191008352770119903;
540     Gamma[2][1]=-0.004648958462629345562774289390054679806993396798458131;
541     Gamma[2][2]=0.4358665215084589994160194475295062513822671686978816;
542     Gamma[2][3]=0;
543     Gamma[3][0]=-0.6685429734233467180451604600279552604364311322650783;
544     Gamma[3][1]=0.6056625986449338476089525334450053439525178740492984;
545     Gamma[3][2]=-0.9717899277217721234705114616271378792182450260943198;
546     Gamma[3][3]=0;
547 
548     A[0][0]=0; A[0][1]=0; A[0][2]=0; A[0][3]=0;
549     A[1][0]=0.8717330430169179988320388950590125027645343373957631;
550     A[1][1]=0; A[1][2]=0; A[1][3]=0;
551     A[2][0]=0.5275890119763004115618079766722914408876108660811028;
552     A[2][1]=0.07241098802369958843819203208518599088698057726988732;
553     A[2][2]=0; A[2][3]=0;
554     A[3][0]=0.3990960076760701320627260685975778145384666450351314;
555     A[3][1]=-0.4375576546135194437228463747348862825846903771419953;
556     A[3][2]=1.038461646937449311660120300601880176655352737312713;
557     A[3][3]=0;
558 
559     b[0]=0.1876410243467238251612921333138006734899663569186926;
560     b[1]=-0.5952974735769549480478230473706443582188442040780541;
561     b[2]=0.9717899277217721234705114616271378792182450260943198;
562     b[3]=0.4358665215084589994160194475295062513822671686978816;
563 
564     b2[0]=0.2147402862233891404862383521089097657790734483804460;
565     b2[1]=-0.4851622638849390928209050538171743017757490232519684;
566     b2[2]=0.8687250025203875511662123688667549217531982787600080;
567     b2[3]=0.4016969751411624011684543450940068201770721128357014;
568 
569     binterpt[0][0]=2.2565812720167954547104627844105;
570     binterpt[1][0]=1.349166413351089573796243820819;
571     binterpt[2][0]=-2.4695174540533503758652847586647;
572     binterpt[3][0]=-0.13623023131453465264142184656474;
573     binterpt[0][1]=-3.0826699111559187902922463354557;
574     binterpt[1][1]=-2.4689115685996042534544925650515;
575     binterpt[2][1]=5.7428279814696677152129332773553;
576     binterpt[3][1]=-0.19124650171414467146619437684812;
577     binterpt[0][2]=1.0137296634858471607430756831148;
578     binterpt[1][2]=0.52444768167155973161042570784064;
579     binterpt[2][2]=-2.3015205996945452158771370439586;
580     binterpt[3][2]=0.76334325453713832352363565300308;
581 
582     ierr = TSRosWRegister(TSROSWARK3,3,4,&A[0][0],&Gamma[0][0],b,b2,3,&binterpt[0][0]);CHKERRQ(ierr);
583   }
584   ierr = TSRosWRegisterRos4(TSROSWGRK4T,0.231,PETSC_DEFAULT,PETSC_DEFAULT,0,-0.1282612945269037e+01);CHKERRQ(ierr);
585   ierr = TSRosWRegisterRos4(TSROSWSHAMP4,0.5,PETSC_DEFAULT,PETSC_DEFAULT,0,125./108.);CHKERRQ(ierr);
586   ierr = TSRosWRegisterRos4(TSROSWVELDD4,0.22570811482256823492,PETSC_DEFAULT,PETSC_DEFAULT,0,-1.355958941201148);CHKERRQ(ierr);
587   ierr = TSRosWRegisterRos4(TSROSW4L,0.57282,PETSC_DEFAULT,PETSC_DEFAULT,0,-1.093502252409163);CHKERRQ(ierr);
588   PetscFunctionReturn(0);
589 }
590 
591 #undef __FUNCT__
592 #define __FUNCT__ "TSRosWRegisterDestroy"
593 /*@C
594    TSRosWRegisterDestroy - Frees the list of schemes that were registered by TSRosWRegister().
595 
596    Not Collective
597 
598    Level: advanced
599 
600 .keywords: TSRosW, register, destroy
601 .seealso: TSRosWRegister(), TSRosWRegisterAll(), TSRosWRegisterDynamic()
602 @*/
603 PetscErrorCode TSRosWRegisterDestroy(void)
604 {
605   PetscErrorCode ierr;
606   RosWTableauLink link;
607 
608   PetscFunctionBegin;
609   while ((link = RosWTableauList)) {
610     RosWTableau t = &link->tab;
611     RosWTableauList = link->next;
612     ierr = PetscFree5(t->A,t->Gamma,t->b,t->ASum,t->GammaSum);CHKERRQ(ierr);
613     ierr = PetscFree5(t->At,t->bt,t->GammaInv,t->GammaZeroDiag,t->GammaExplicitCorr);CHKERRQ(ierr);
614     ierr = PetscFree2(t->bembed,t->bembedt);CHKERRQ(ierr);
615     ierr = PetscFree(t->binterpt);CHKERRQ(ierr);
616     ierr = PetscFree(t->name);CHKERRQ(ierr);
617     ierr = PetscFree(link);CHKERRQ(ierr);
618   }
619   TSRosWRegisterAllCalled = PETSC_FALSE;
620   PetscFunctionReturn(0);
621 }
622 
623 #undef __FUNCT__
624 #define __FUNCT__ "TSRosWInitializePackage"
625 /*@C
626   TSRosWInitializePackage - This function initializes everything in the TSRosW package. It is called
627   from PetscDLLibraryRegister() when using dynamic libraries, and on the first call to TSCreate_RosW()
628   when using static libraries.
629 
630   Input Parameter:
631   path - The dynamic library path, or PETSC_NULL
632 
633   Level: developer
634 
635 .keywords: TS, TSRosW, initialize, package
636 .seealso: PetscInitialize()
637 @*/
638 PetscErrorCode TSRosWInitializePackage(const char path[])
639 {
640   PetscErrorCode ierr;
641 
642   PetscFunctionBegin;
643   if (TSRosWPackageInitialized) PetscFunctionReturn(0);
644   TSRosWPackageInitialized = PETSC_TRUE;
645   ierr = TSRosWRegisterAll();CHKERRQ(ierr);
646   ierr = PetscRegisterFinalize(TSRosWFinalizePackage);CHKERRQ(ierr);
647   PetscFunctionReturn(0);
648 }
649 
650 #undef __FUNCT__
651 #define __FUNCT__ "TSRosWFinalizePackage"
652 /*@C
653   TSRosWFinalizePackage - This function destroys everything in the TSRosW package. It is
654   called from PetscFinalize().
655 
656   Level: developer
657 
658 .keywords: Petsc, destroy, package
659 .seealso: PetscFinalize()
660 @*/
661 PetscErrorCode TSRosWFinalizePackage(void)
662 {
663   PetscErrorCode ierr;
664 
665   PetscFunctionBegin;
666   TSRosWPackageInitialized = PETSC_FALSE;
667   ierr = TSRosWRegisterDestroy();CHKERRQ(ierr);
668   PetscFunctionReturn(0);
669 }
670 
671 #undef __FUNCT__
672 #define __FUNCT__ "TSRosWRegister"
673 /*@C
674    TSRosWRegister - register a Rosenbrock W scheme by providing the entries in the Butcher tableau and optionally embedded approximations and interpolation
675 
676    Not Collective, but the same schemes should be registered on all processes on which they will be used
677 
678    Input Parameters:
679 +  name - identifier for method
680 .  order - approximation order of method
681 .  s - number of stages, this is the dimension of the matrices below
682 .  A - Table of propagated stage coefficients (dimension s*s, row-major), strictly lower triangular
683 .  Gamma - Table of coefficients in implicit stage equations (dimension s*s, row-major), lower triangular with nonzero diagonal
684 .  b - Step completion table (dimension s)
685 .  bembed - Step completion table for a scheme of order one less (dimension s, PETSC_NULL if no embedded scheme is available)
686 .  pinterp - Order of the interpolation scheme, equal to the number of columns of binterpt
687 -  binterpt - Coefficients of the interpolation formula (dimension s*pinterp)
688 
689    Notes:
690    Several Rosenbrock W methods are provided, this function is only needed to create new methods.
691 
692    Level: advanced
693 
694 .keywords: TS, register
695 
696 .seealso: TSRosW
697 @*/
698 PetscErrorCode TSRosWRegister(const TSRosWType name,PetscInt order,PetscInt s,
699                               const PetscReal A[],const PetscReal Gamma[],const PetscReal b[],const PetscReal bembed[],
700                                  PetscInt pinterp,const PetscReal binterpt[])
701 {
702   PetscErrorCode ierr;
703   RosWTableauLink link;
704   RosWTableau t;
705   PetscInt i,j,k;
706   PetscScalar *GammaInv;
707 
708   PetscFunctionBegin;
709   PetscValidCharPointer(name,1);
710   PetscValidPointer(A,4);
711   PetscValidPointer(Gamma,5);
712   PetscValidPointer(b,6);
713   if (bembed) PetscValidPointer(bembed,7);
714 
715   ierr = PetscMalloc(sizeof(*link),&link);CHKERRQ(ierr);
716   ierr = PetscMemzero(link,sizeof(*link));CHKERRQ(ierr);
717   t = &link->tab;
718   ierr = PetscStrallocpy(name,&t->name);CHKERRQ(ierr);
719   t->order = order;
720   t->s = s;
721   ierr = PetscMalloc5(s*s,PetscReal,&t->A,s*s,PetscReal,&t->Gamma,s,PetscReal,&t->b,s,PetscReal,&t->ASum,s,PetscReal,&t->GammaSum);CHKERRQ(ierr);
722   ierr = PetscMalloc5(s*s,PetscReal,&t->At,s,PetscReal,&t->bt,s*s,PetscReal,&t->GammaInv,s,PetscBool,&t->GammaZeroDiag,s*s,PetscReal,&t->GammaExplicitCorr);CHKERRQ(ierr);
723   ierr = PetscMemcpy(t->A,A,s*s*sizeof(A[0]));CHKERRQ(ierr);
724   ierr = PetscMemcpy(t->Gamma,Gamma,s*s*sizeof(Gamma[0]));CHKERRQ(ierr);
725   ierr = PetscMemcpy(t->GammaExplicitCorr,Gamma,s*s*sizeof(Gamma[0]));CHKERRQ(ierr);
726   ierr = PetscMemcpy(t->b,b,s*sizeof(b[0]));CHKERRQ(ierr);
727   if (bembed) {
728     ierr = PetscMalloc2(s,PetscReal,&t->bembed,s,PetscReal,&t->bembedt);CHKERRQ(ierr);
729     ierr = PetscMemcpy(t->bembed,bembed,s*sizeof(bembed[0]));CHKERRQ(ierr);
730   }
731   for (i=0; i<s; i++) {
732     t->ASum[i] = 0;
733     t->GammaSum[i] = 0;
734     for (j=0; j<s; j++) {
735       t->ASum[i] += A[i*s+j];
736       t->GammaSum[i] += Gamma[i*s+j];
737     }
738   }
739   ierr = PetscMalloc(s*s*sizeof(PetscScalar),&GammaInv);CHKERRQ(ierr); /* Need to use Scalar for inverse, then convert back to Real */
740   for (i=0; i<s*s; i++) GammaInv[i] = Gamma[i];
741   for (i=0; i<s; i++) {
742     if (Gamma[i*s+i] == 0.0) {
743       GammaInv[i*s+i] = 1.0;
744       t->GammaZeroDiag[i] = PETSC_TRUE;
745     } else {
746       t->GammaZeroDiag[i] = PETSC_FALSE;
747     }
748   }
749 
750   switch (s) {
751   case 1: GammaInv[0] = 1./GammaInv[0]; break;
752   case 2: ierr = PetscKernel_A_gets_inverse_A_2(GammaInv,0);CHKERRQ(ierr); break;
753   case 3: ierr = PetscKernel_A_gets_inverse_A_3(GammaInv,0);CHKERRQ(ierr); break;
754   case 4: ierr = PetscKernel_A_gets_inverse_A_4(GammaInv,0);CHKERRQ(ierr); break;
755   case 5: {
756     PetscInt ipvt5[5];
757     MatScalar work5[5*5];
758     ierr = PetscKernel_A_gets_inverse_A_5(GammaInv,ipvt5,work5,0);CHKERRQ(ierr); break;
759   }
760   case 6: ierr = PetscKernel_A_gets_inverse_A_6(GammaInv,0);CHKERRQ(ierr); break;
761   case 7: ierr = PetscKernel_A_gets_inverse_A_7(GammaInv,0);CHKERRQ(ierr); break;
762   default: SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented for %D stages",s);
763   }
764   for (i=0; i<s*s; i++) t->GammaInv[i] = PetscRealPart(GammaInv[i]);
765   ierr = PetscFree(GammaInv);CHKERRQ(ierr);
766 
767   for (i=0; i<s; i++) {
768     for (k=0; k<i+1; k++) {
769       t->GammaExplicitCorr[i*s+k]=(t->GammaExplicitCorr[i*s+k])*(t->GammaInv[k*s+k]);
770       for (j=k+1; j<i+1; j++) {
771         t->GammaExplicitCorr[i*s+k]+=(t->GammaExplicitCorr[i*s+j])*(t->GammaInv[j*s+k]);
772       }
773     }
774   }
775 
776   for (i=0; i<s; i++) {
777     for (j=0; j<s; j++) {
778       t->At[i*s+j] = 0;
779       for (k=0; k<s; k++) {
780         t->At[i*s+j] += t->A[i*s+k] * t->GammaInv[k*s+j];
781       }
782     }
783     t->bt[i] = 0;
784     for (j=0; j<s; j++) {
785       t->bt[i] += t->b[j] * t->GammaInv[j*s+i];
786     }
787     if (bembed) {
788       t->bembedt[i] = 0;
789       for (j=0; j<s; j++) {
790         t->bembedt[i] += t->bembed[j] * t->GammaInv[j*s+i];
791       }
792     }
793   }
794   t->ccfl = 1.0;                /* Fix this */
795 
796   t->pinterp = pinterp;
797   ierr = PetscMalloc(s*pinterp*sizeof(binterpt[0]),&t->binterpt);CHKERRQ(ierr);
798   ierr = PetscMemcpy(t->binterpt,binterpt,s*pinterp*sizeof(binterpt[0]));CHKERRQ(ierr);
799   link->next = RosWTableauList;
800   RosWTableauList = link;
801   PetscFunctionReturn(0);
802 }
803 
804 #undef __FUNCT__
805 #define __FUNCT__ "TSRosWRegisterRos4"
806 /*@C
807    TSRosWRegisterRos4 - register a fourth order Rosenbrock scheme by providing paramter choices
808 
809    Not Collective, but the same schemes should be registered on all processes on which they will be used
810 
811    Input Parameters:
812 +  name - identifier for method
813 .  gamma - leading coefficient (diagonal entry)
814 .  a2 - design parameter, see Table 7.2 of Hairer&Wanner
815 .  a3 - design parameter or PETSC_DEFAULT to satisfy one of the order five conditions (Eq 7.22)
816 .  b3 - design parameter, see Table 7.2 of Hairer&Wanner
817 .  beta43 - design parameter or PETSC_DEFAULT to use Equation 7.21 of Hairer&Wanner
818 .  e4 - design parameter for embedded method, see coefficient E4 in ros4.f code from Hairer
819 
820    Notes:
821    This routine encodes the design of fourth order Rosenbrock methods as described in Hairer and Wanner volume 2.
822    It is used here to implement several methods from the book and can be used to experiment with new methods.
823    It was written this way instead of by copying coefficients in order to provide better than double precision satisfaction of the order conditions.
824 
825    Level: developer
826 
827 .keywords: TS, register
828 
829 .seealso: TSRosW, TSRosWRegister()
830 @*/
831 PetscErrorCode TSRosWRegisterRos4(const TSRosWType name,PetscReal gamma,PetscReal a2,PetscReal a3,PetscReal b3,PetscReal e4)
832 {
833   PetscErrorCode ierr;
834   /* Declare numeric constants so they can be quad precision without being truncated at double */
835   const PetscReal one = 1,two = 2,three = 3,four = 4,five = 5,six = 6,eight = 8,twelve = 12,twenty = 20,twentyfour = 24,
836     p32 = one/six - gamma + gamma*gamma,
837     p42 = one/eight - gamma/three,
838     p43 = one/twelve - gamma/three,
839     p44 = one/twentyfour - gamma/two + three/two*gamma*gamma - gamma*gamma*gamma,
840     p56 = one/twenty - gamma/four;
841   PetscReal a4,a32,a42,a43,b1,b2,b4,beta2p,beta3p,beta4p,beta32,beta42,beta43,beta32beta2p,beta4jbetajp;
842   PetscReal A[4][4],Gamma[4][4],b[4],bm[4];
843   PetscScalar M[3][3],rhs[3];
844 
845   PetscFunctionBegin;
846   /* Step 1: choose Gamma (input) */
847   /* Step 2: choose a2,a3,a4; b1,b2,b3,b4 to satisfy order conditions */
848   if (a3 == PETSC_DEFAULT) a3 = (one/five - a2/four)/(one/four - a2/three); /* Eq 7.22 */
849   a4 = a3;                                                  /* consequence of 7.20 */
850 
851   /* Solve order conditions 7.15a, 7.15c, 7.15e */
852   M[0][0] = one; M[0][1] = one;      M[0][2] = one;      /* 7.15a */
853   M[1][0] = 0.0; M[1][1] = a2*a2;    M[1][2] = a4*a4;    /* 7.15c */
854   M[2][0] = 0.0; M[2][1] = a2*a2*a2; M[2][2] = a4*a4*a4; /* 7.15e */
855   rhs[0] = one - b3;
856   rhs[1] = one/three - a3*a3*b3;
857   rhs[2] = one/four - a3*a3*a3*b3;
858   ierr = PetscKernel_A_gets_inverse_A_3(&M[0][0],0);CHKERRQ(ierr);
859   b1 = PetscRealPart(M[0][0]*rhs[0] + M[0][1]*rhs[1] + M[0][2]*rhs[2]);
860   b2 = PetscRealPart(M[1][0]*rhs[0] + M[1][1]*rhs[1] + M[1][2]*rhs[2]);
861   b4 = PetscRealPart(M[2][0]*rhs[0] + M[2][1]*rhs[1] + M[2][2]*rhs[2]);
862 
863   /* Step 3 */
864   beta43 = (p56 - a2*p43) / (b4*a3*a3*(a3 - a2)); /* 7.21 */
865   beta32beta2p =  p44 / (b4*beta43);              /* 7.15h */
866   beta4jbetajp = (p32 - b3*beta32beta2p) / b4;
867   M[0][0] = b2;                                    M[0][1] = b3;                 M[0][2] = b4;
868   M[1][0] = a4*a4*beta32beta2p-a3*a3*beta4jbetajp; M[1][1] = a2*a2*beta4jbetajp; M[1][2] = -a2*a2*beta32beta2p;
869   M[2][0] = b4*beta43*a3*a3-p43;                   M[2][1] = -b4*beta43*a2*a2;   M[2][2] = 0;
870   rhs[0] = one/two - gamma; rhs[1] = 0; rhs[2] = -a2*a2*p32;
871   ierr = PetscKernel_A_gets_inverse_A_3(&M[0][0],0);CHKERRQ(ierr);
872   beta2p = PetscRealPart(M[0][0]*rhs[0] + M[0][1]*rhs[1] + M[0][2]*rhs[2]);
873   beta3p = PetscRealPart(M[1][0]*rhs[0] + M[1][1]*rhs[1] + M[1][2]*rhs[2]);
874   beta4p = PetscRealPart(M[2][0]*rhs[0] + M[2][1]*rhs[1] + M[2][2]*rhs[2]);
875 
876   /* Step 4: back-substitute */
877   beta32 = beta32beta2p / beta2p;
878   beta42 = (beta4jbetajp - beta43*beta3p) / beta2p;
879 
880   /* Step 5: 7.15f and 7.20, then 7.16 */
881   a43 = 0;
882   a32 = p42 / (b3*a3*beta2p + b4*a4*beta2p);
883   a42 = a32;
884 
885   A[0][0] = 0;          A[0][1] = 0;   A[0][2] = 0;   A[0][3] = 0;
886   A[1][0] = a2;         A[1][1] = 0;   A[1][2] = 0;   A[1][3] = 0;
887   A[2][0] = a3-a32;     A[2][1] = a32; A[2][2] = 0;   A[2][3] = 0;
888   A[3][0] = a4-a43-a42; A[3][1] = a42; A[3][2] = a43; A[3][3] = 0;
889   Gamma[0][0] = gamma;                        Gamma[0][1] = 0;              Gamma[0][2] = 0;              Gamma[0][3] = 0;
890   Gamma[1][0] = beta2p-A[1][0];               Gamma[1][1] = gamma;          Gamma[1][2] = 0;              Gamma[1][3] = 0;
891   Gamma[2][0] = beta3p-beta32-A[2][0];        Gamma[2][1] = beta32-A[2][1]; Gamma[2][2] = gamma;          Gamma[2][3] = 0;
892   Gamma[3][0] = beta4p-beta42-beta43-A[3][0]; Gamma[3][1] = beta42-A[3][1]; Gamma[3][2] = beta43-A[3][2]; Gamma[3][3] = gamma;
893   b[0] = b1; b[1] = b2; b[2] = b3; b[3] = b4;
894 
895   /* Construct embedded formula using given e4. We are solving Equation 7.18. */
896   bm[3] = b[3] - e4*gamma;                                          /* using definition of E4 */
897   bm[2] = (p32 - beta4jbetajp*bm[3]) / (beta32*beta2p);             /* fourth row of 7.18 */
898   bm[1] = (one/two - gamma - beta3p*bm[2] - beta4p*bm[3]) / beta2p; /* second row */
899   bm[0] = one - bm[1] - bm[2] - bm[3];                              /* first row */
900 
901   {
902     const PetscReal misfit = a2*a2*bm[1] + a3*a3*bm[2] + a4*a4*bm[3] - one/three;
903     if (PetscAbs(misfit) > PETSC_SMALL) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Assumptions violated, could not construct a third order embedded method");
904   }
905   ierr = TSRosWRegister(name,4,4,&A[0][0],&Gamma[0][0],b,bm,0,PETSC_NULL);CHKERRQ(ierr);
906   PetscFunctionReturn(0);
907 }
908 
909 #undef __FUNCT__
910 #define __FUNCT__ "TSEvaluateStep_RosW"
911 /*
912  The step completion formula is
913 
914  x1 = x0 + b^T Y
915 
916  where Y is the multi-vector of stages corrections. This function can be called before or after ts->vec_sol has been
917  updated. Suppose we have a completion formula b and an embedded formula be of different order. We can write
918 
919  x1e = x0 + be^T Y
920      = x1 - b^T Y + be^T Y
921      = x1 + (be - b)^T Y
922 
923  so we can evaluate the method of different order even after the step has been optimistically completed.
924 */
925 static PetscErrorCode TSEvaluateStep_RosW(TS ts,PetscInt order,Vec X,PetscBool *done)
926 {
927   TS_RosW        *ros = (TS_RosW*)ts->data;
928   RosWTableau    tab  = ros->tableau;
929   PetscScalar    *w = ros->work;
930   PetscInt       i;
931   PetscErrorCode ierr;
932 
933   PetscFunctionBegin;
934   if (order == tab->order) {
935     if (ros->status == TS_STEP_INCOMPLETE) { /* Use standard completion formula */
936       ierr = VecCopy(ts->vec_sol,X);CHKERRQ(ierr);
937       for (i=0; i<tab->s; i++) w[i] = tab->bt[i];
938       ierr = VecMAXPY(X,tab->s,w,ros->Y);CHKERRQ(ierr);
939     } else {ierr = VecCopy(ts->vec_sol,X);CHKERRQ(ierr);}
940     if (done) *done = PETSC_TRUE;
941     PetscFunctionReturn(0);
942   } else if (order == tab->order-1) {
943     if (!tab->bembedt) goto unavailable;
944     if (ros->status == TS_STEP_INCOMPLETE) { /* Use embedded completion formula */
945       ierr = VecCopy(ts->vec_sol,X);CHKERRQ(ierr);
946       for (i=0; i<tab->s; i++) w[i] = tab->bembedt[i];
947       ierr = VecMAXPY(X,tab->s,w,ros->Y);CHKERRQ(ierr);
948     } else {                    /* Use rollback-and-recomplete formula (bembedt - bt) */
949       for (i=0; i<tab->s; i++) w[i] = tab->bembedt[i] - tab->bt[i];
950       ierr = VecCopy(ts->vec_sol,X);CHKERRQ(ierr);
951       ierr = VecMAXPY(X,tab->s,w,ros->Y);CHKERRQ(ierr);
952     }
953     if (done) *done = PETSC_TRUE;
954     PetscFunctionReturn(0);
955   }
956   unavailable:
957   if (done) *done = PETSC_FALSE;
958   else SETERRQ3(((PetscObject)ts)->comm,PETSC_ERR_SUP,"Rosenbrock-W '%s' of order %D cannot evaluate step at order %D",tab->name,tab->order,order);
959   PetscFunctionReturn(0);
960 }
961 
962 #undef __FUNCT__
963 #define __FUNCT__ "TSStep_RosW"
964 static PetscErrorCode TSStep_RosW(TS ts)
965 {
966   TS_RosW         *ros = (TS_RosW*)ts->data;
967   RosWTableau     tab  = ros->tableau;
968   const PetscInt  s    = tab->s;
969   const PetscReal *At  = tab->At,*Gamma = tab->Gamma,*ASum = tab->ASum,*GammaInv = tab->GammaInv;
970   const PetscReal *GammaExplicitCorr = tab->GammaExplicitCorr;
971   const PetscBool *GammaZeroDiag = tab->GammaZeroDiag;
972   PetscScalar     *w   = ros->work;
973   Vec             *Y   = ros->Y,Ydot = ros->Ydot,Zdot = ros->Zdot,Zstage = ros->Zstage;
974   SNES            snes;
975   TSAdapt         adapt;
976   PetscInt        i,j,its,lits,reject,next_scheme;
977   PetscReal       next_time_step;
978   PetscBool       accept;
979   PetscErrorCode  ierr;
980   MatStructure    str;
981 
982   PetscFunctionBegin;
983   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
984   next_time_step = ts->time_step;
985   accept = PETSC_TRUE;
986   ros->status = TS_STEP_INCOMPLETE;
987 
988   for (reject=0; reject<ts->max_reject && !ts->reason; reject++,ts->reject++) {
989     const PetscReal h = ts->time_step;
990     ierr = VecCopy(ts->vec_sol,ros->VecSolPrev);CHKERRQ(ierr);/*move this at the end*/
991     for (i=0; i<s; i++) {
992       ros->stage_time = ts->ptime + h*ASum[i];
993       if (GammaZeroDiag[i]) {
994         ros->stage_explicit = PETSC_TRUE;
995         ros->shift = 1./h;
996       } else {
997         ros->stage_explicit = PETSC_FALSE;
998         ros->shift = 1./(h*Gamma[i*s+i]);
999       }
1000 
1001       ierr = VecCopy(ts->vec_sol,Zstage);CHKERRQ(ierr);
1002       for (j=0; j<i; j++) w[j] = At[i*s+j];
1003       ierr = VecMAXPY(Zstage,i,w,Y);CHKERRQ(ierr);
1004 
1005       for (j=0; j<i; j++) w[j] = 1./h * GammaInv[i*s+j];
1006       ierr = VecZeroEntries(Zdot);CHKERRQ(ierr);
1007       ierr = VecMAXPY(Zdot,i,w,Y);CHKERRQ(ierr);
1008 
1009       /* Initial guess taken from last stage */
1010       ierr = VecZeroEntries(Y[i]);CHKERRQ(ierr);
1011 
1012       if (!ros->stage_explicit) {
1013         if (!ros->recompute_jacobian && !i) {
1014           ierr = SNESSetLagJacobian(snes,-2);CHKERRQ(ierr); /* Recompute the Jacobian on this solve, but not again */
1015         }
1016         ierr = SNESSolve(snes,PETSC_NULL,Y[i]);CHKERRQ(ierr);
1017         ierr = SNESGetIterationNumber(snes,&its);CHKERRQ(ierr);
1018         ierr = SNESGetLinearSolveIterations(snes,&lits);CHKERRQ(ierr);
1019         ts->snes_its += its; ts->ksp_its += lits;
1020         ierr = TSGetAdapt(ts,&adapt);CHKERRQ(ierr);
1021         ierr = TSAdaptCheckStage(adapt,ts,&accept);CHKERRQ(ierr);
1022         if (!accept) goto reject_step;
1023       } else {
1024         Mat J,Jp;
1025         ierr = VecZeroEntries(Ydot);CHKERRQ(ierr); /* Evaluate Y[i]=G(t,Ydot=0,Zstage) */
1026         ierr = TSComputeIFunction(ts,ros->stage_time,Zstage,Ydot,Y[i],PETSC_FALSE);CHKERRQ(ierr);
1027         ierr = VecScale(Y[i],-1.0);
1028         ierr = VecAXPY(Y[i],-1.0,Zdot);CHKERRQ(ierr); /*Y[i]=F(Zstage)-Zdot[=GammaInv*Y]*/
1029 
1030         ierr = VecZeroEntries(Zstage);CHKERRQ(ierr); /* Zstage = GammaExplicitCorr[i,j] * Y[j] */
1031         for (j=0; j<i; j++) w[j] = GammaExplicitCorr[i*s+j];
1032         ierr = VecMAXPY(Zstage,i,w,Y);CHKERRQ(ierr);
1033         /*Y[i] += Y[i] + Jac*Zstage[=Jac*GammaExplicitCorr[i,j] * Y[j]] */
1034         str = SAME_NONZERO_PATTERN;
1035         ierr = TSGetIJacobian(ts,&J,&Jp,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
1036         ierr = TSComputeIJacobian(ts,ros->stage_time,ts->vec_sol,Ydot,0,&J,&Jp,&str,PETSC_FALSE);CHKERRQ(ierr);
1037         ierr = MatMult(J,Zstage,Zdot);
1038 
1039         ierr = VecAXPY(Y[i],-1.0,Zdot);CHKERRQ(ierr);
1040         ierr = VecScale(Y[i],h);
1041         ts->ksp_its += 1;
1042       }
1043     }
1044     ierr = TSEvaluateStep(ts,tab->order,ts->vec_sol,PETSC_NULL);CHKERRQ(ierr);
1045     ros->status = TS_STEP_PENDING;
1046 
1047     /* Register only the current method as a candidate because we're not supporting multiple candidates yet. */
1048     ierr = TSGetAdapt(ts,&adapt);CHKERRQ(ierr);
1049     ierr = TSAdaptCandidatesClear(adapt);CHKERRQ(ierr);
1050     ierr = TSAdaptCandidateAdd(adapt,tab->name,tab->order,1,tab->ccfl,1.*tab->s,PETSC_TRUE);CHKERRQ(ierr);
1051     ierr = TSAdaptChoose(adapt,ts,ts->time_step,&next_scheme,&next_time_step,&accept);CHKERRQ(ierr);
1052     if (accept) {
1053       /* ignore next_scheme for now */
1054       ts->ptime += ts->time_step;
1055       ts->time_step = next_time_step;
1056       ts->steps++;
1057       ros->status = TS_STEP_COMPLETE;
1058       break;
1059     } else {                    /* Roll back the current step */
1060       for (i=0; i<s; i++) w[i] = -tab->bt[i];
1061       ierr = VecMAXPY(ts->vec_sol,s,w,Y);CHKERRQ(ierr);
1062       ts->time_step = next_time_step;
1063       ros->status = TS_STEP_INCOMPLETE;
1064     }
1065     reject_step: continue;
1066   }
1067   if (ros->status != TS_STEP_COMPLETE && !ts->reason) ts->reason = TS_DIVERGED_STEP_REJECTED;
1068   PetscFunctionReturn(0);
1069 }
1070 
1071 #undef __FUNCT__
1072 #define __FUNCT__ "TSInterpolate_RosW"
1073 static PetscErrorCode TSInterpolate_RosW(TS ts,PetscReal itime,Vec X)
1074 {
1075   TS_RosW        *ros = (TS_RosW*)ts->data;
1076   PetscInt s = ros->tableau->s,pinterp = ros->tableau->pinterp,i,j;
1077   PetscReal h;
1078   PetscReal tt,t;
1079   PetscScalar *bt;
1080   const PetscReal *Bt = ros->tableau->binterpt;
1081   PetscErrorCode ierr;
1082   const PetscReal *GammaInv = ros->tableau->GammaInv;
1083   PetscScalar     *w   = ros->work;
1084   Vec             *Y   = ros->Y;
1085 
1086   PetscFunctionBegin;
1087   if (!Bt) SETERRQ1(((PetscObject)ts)->comm,PETSC_ERR_SUP,"TSRosW %s does not have an interpolation formula",ros->tableau->name);
1088 
1089   switch (ros->status) {
1090   case TS_STEP_INCOMPLETE:
1091   case TS_STEP_PENDING:
1092     h = ts->time_step;
1093     t = (itime - ts->ptime)/h;
1094     break;
1095   case TS_STEP_COMPLETE:
1096     h = ts->time_step_prev;
1097     t = (itime - ts->ptime)/h + 1; /* In the interval [0,1] */
1098     break;
1099   default: SETERRQ(((PetscObject)ts)->comm,PETSC_ERR_PLIB,"Invalid TSStepStatus");
1100   }
1101   ierr = PetscMalloc(s*sizeof(bt[0]),&bt);CHKERRQ(ierr);
1102   for (i=0; i<s; i++) bt[i] = 0;
1103   for (j=0,tt=t; j<pinterp; j++,tt*=t) {
1104     for (i=0; i<s; i++) {
1105       bt[i] += Bt[i*pinterp+j] * tt;
1106     }
1107   }
1108 
1109   /* y(t+tt*h) = y(t) + Sum bt(tt) * GammaInv * Ydot */
1110   /*X<-0*/
1111   ierr = VecZeroEntries(X);CHKERRQ(ierr);
1112 
1113   /*X<- Sum bt_i * GammaInv(i,1:i) * Y(1:i) */
1114   for (j=0; j<s; j++)  w[j]=0;
1115   for (j=0; j<s; j++) {
1116     for (i=j; i<s; i++) {
1117       w[j] +=  bt[i]*GammaInv[i*s+j];
1118     }
1119   }
1120   ierr = VecMAXPY(X,i,w,Y);CHKERRQ(ierr);
1121 
1122   /*X<-y(t) + X*/
1123   ierr = VecAXPY(X,1.0,ros->VecSolPrev);CHKERRQ(ierr);
1124 
1125   ierr = PetscFree(bt);CHKERRQ(ierr);
1126 
1127   PetscFunctionReturn(0);
1128 }
1129 
1130 /*------------------------------------------------------------*/
1131 #undef __FUNCT__
1132 #define __FUNCT__ "TSReset_RosW"
1133 static PetscErrorCode TSReset_RosW(TS ts)
1134 {
1135   TS_RosW        *ros = (TS_RosW*)ts->data;
1136   PetscInt       s;
1137   PetscErrorCode ierr;
1138 
1139   PetscFunctionBegin;
1140   if (!ros->tableau) PetscFunctionReturn(0);
1141    s = ros->tableau->s;
1142   ierr = VecDestroyVecs(s,&ros->Y);CHKERRQ(ierr);
1143   ierr = VecDestroy(&ros->Ydot);CHKERRQ(ierr);
1144   ierr = VecDestroy(&ros->Ystage);CHKERRQ(ierr);
1145   ierr = VecDestroy(&ros->Zdot);CHKERRQ(ierr);
1146   ierr = VecDestroy(&ros->Zstage);CHKERRQ(ierr);
1147   ierr = VecDestroy(&ros->VecSolPrev);CHKERRQ(ierr);
1148   ierr = PetscFree(ros->work);CHKERRQ(ierr);
1149   PetscFunctionReturn(0);
1150 }
1151 
1152 #undef __FUNCT__
1153 #define __FUNCT__ "TSDestroy_RosW"
1154 static PetscErrorCode TSDestroy_RosW(TS ts)
1155 {
1156   PetscErrorCode  ierr;
1157 
1158   PetscFunctionBegin;
1159   ierr = TSReset_RosW(ts);CHKERRQ(ierr);
1160   ierr = PetscFree(ts->data);CHKERRQ(ierr);
1161   ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSRosWGetType_C","",PETSC_NULL);CHKERRQ(ierr);
1162   ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSRosWSetType_C","",PETSC_NULL);CHKERRQ(ierr);
1163   ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSRosWSetRecomputeJacobian_C","",PETSC_NULL);CHKERRQ(ierr);
1164   PetscFunctionReturn(0);
1165 }
1166 
1167 /*
1168   This defines the nonlinear equation that is to be solved with SNES
1169   G(U) = F[t0+Theta*dt, U, (U-U0)*shift] = 0
1170 */
1171 #undef __FUNCT__
1172 #define __FUNCT__ "SNESTSFormFunction_RosW"
1173 static PetscErrorCode SNESTSFormFunction_RosW(SNES snes,Vec X,Vec F,TS ts)
1174 {
1175   TS_RosW        *ros = (TS_RosW*)ts->data;
1176   PetscErrorCode ierr;
1177 
1178   PetscFunctionBegin;
1179   ierr = VecWAXPY(ros->Ydot,ros->shift,X,ros->Zdot);CHKERRQ(ierr); /* Ydot = shift*X + Zdot */
1180   ierr = VecWAXPY(ros->Ystage,1.0,X,ros->Zstage);CHKERRQ(ierr);    /* Ystage = X + Zstage */
1181   ierr = TSComputeIFunction(ts,ros->stage_time,ros->Ystage,ros->Ydot,F,PETSC_FALSE);CHKERRQ(ierr);
1182   PetscFunctionReturn(0);
1183 }
1184 
1185 #undef __FUNCT__
1186 #define __FUNCT__ "SNESTSFormJacobian_RosW"
1187 static PetscErrorCode SNESTSFormJacobian_RosW(SNES snes,Vec X,Mat *A,Mat *B,MatStructure *str,TS ts)
1188 {
1189   TS_RosW        *ros = (TS_RosW*)ts->data;
1190   PetscErrorCode ierr;
1191 
1192   PetscFunctionBegin;
1193   /* ros->Ydot and ros->Ystage have already been computed in SNESTSFormFunction_RosW (SNES guarantees this) */
1194   ierr = TSComputeIJacobian(ts,ros->stage_time,ros->Ystage,ros->Ydot,ros->shift,A,B,str,PETSC_TRUE);CHKERRQ(ierr);
1195   PetscFunctionReturn(0);
1196 }
1197 
1198 #undef __FUNCT__
1199 #define __FUNCT__ "TSSetUp_RosW"
1200 static PetscErrorCode TSSetUp_RosW(TS ts)
1201 {
1202   TS_RosW        *ros = (TS_RosW*)ts->data;
1203   RosWTableau    tab  = ros->tableau;
1204   PetscInt       s    = tab->s;
1205   PetscErrorCode ierr;
1206 
1207   PetscFunctionBegin;
1208   if (!ros->tableau) {
1209     ierr = TSRosWSetType(ts,TSRosWDefault);CHKERRQ(ierr);
1210   }
1211   ierr = VecDuplicateVecs(ts->vec_sol,s,&ros->Y);CHKERRQ(ierr);
1212   ierr = VecDuplicate(ts->vec_sol,&ros->Ydot);CHKERRQ(ierr);
1213   ierr = VecDuplicate(ts->vec_sol,&ros->Ystage);CHKERRQ(ierr);
1214   ierr = VecDuplicate(ts->vec_sol,&ros->Zdot);CHKERRQ(ierr);
1215   ierr = VecDuplicate(ts->vec_sol,&ros->Zstage);CHKERRQ(ierr);
1216   ierr = VecDuplicate(ts->vec_sol,&ros->VecSolPrev);CHKERRQ(ierr);
1217   ierr = PetscMalloc(s*sizeof(ros->work[0]),&ros->work);CHKERRQ(ierr);
1218   PetscFunctionReturn(0);
1219 }
1220 /*------------------------------------------------------------*/
1221 
1222 #undef __FUNCT__
1223 #define __FUNCT__ "TSSetFromOptions_RosW"
1224 static PetscErrorCode TSSetFromOptions_RosW(TS ts)
1225 {
1226   TS_RosW        *ros = (TS_RosW*)ts->data;
1227   PetscErrorCode ierr;
1228   char           rostype[256];
1229 
1230   PetscFunctionBegin;
1231   ierr = PetscOptionsHead("RosW ODE solver options");CHKERRQ(ierr);
1232   {
1233     RosWTableauLink link;
1234     PetscInt count,choice;
1235     PetscBool flg;
1236     const char **namelist;
1237     SNES snes;
1238 
1239     ierr = PetscStrncpy(rostype,TSRosWDefault,sizeof rostype);CHKERRQ(ierr);
1240     for (link=RosWTableauList,count=0; link; link=link->next,count++) ;
1241     ierr = PetscMalloc(count*sizeof(char*),&namelist);CHKERRQ(ierr);
1242     for (link=RosWTableauList,count=0; link; link=link->next,count++) namelist[count] = link->tab.name;
1243     ierr = PetscOptionsEList("-ts_rosw_type","Family of Rosenbrock-W method","TSRosWSetType",(const char*const*)namelist,count,rostype,&choice,&flg);CHKERRQ(ierr);
1244     ierr = TSRosWSetType(ts,flg ? namelist[choice] : rostype);CHKERRQ(ierr);
1245     ierr = PetscFree(namelist);CHKERRQ(ierr);
1246 
1247     ierr = PetscOptionsBool("-ts_rosw_recompute_jacobian","Recompute the Jacobian at each stage","TSRosWSetRecomputeJacobian",ros->recompute_jacobian,&ros->recompute_jacobian,PETSC_NULL);CHKERRQ(ierr);
1248 
1249     /* Rosenbrock methods are linearly implicit, so set that unless the user has specifically asked for something else */
1250     ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
1251     if (!((PetscObject)snes)->type_name) {
1252       ierr = SNESSetType(snes,SNESKSPONLY);CHKERRQ(ierr);
1253     }
1254     ierr = SNESSetFromOptions(snes);CHKERRQ(ierr);
1255   }
1256   ierr = PetscOptionsTail();CHKERRQ(ierr);
1257   PetscFunctionReturn(0);
1258 }
1259 
1260 #undef __FUNCT__
1261 #define __FUNCT__ "PetscFormatRealArray"
1262 static PetscErrorCode PetscFormatRealArray(char buf[],size_t len,const char *fmt,PetscInt n,const PetscReal x[])
1263 {
1264   PetscErrorCode ierr;
1265   PetscInt i;
1266   size_t left,count;
1267   char *p;
1268 
1269   PetscFunctionBegin;
1270   for (i=0,p=buf,left=len; i<n; i++) {
1271     ierr = PetscSNPrintfCount(p,left,fmt,&count,x[i]);CHKERRQ(ierr);
1272     if (count >= left) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Insufficient space in buffer");
1273     left -= count;
1274     p += count;
1275     *p++ = ' ';
1276   }
1277   p[i ? 0 : -1] = 0;
1278   PetscFunctionReturn(0);
1279 }
1280 
1281 #undef __FUNCT__
1282 #define __FUNCT__ "TSView_RosW"
1283 static PetscErrorCode TSView_RosW(TS ts,PetscViewer viewer)
1284 {
1285   TS_RosW        *ros = (TS_RosW*)ts->data;
1286   RosWTableau    tab  = ros->tableau;
1287   PetscBool      iascii;
1288   PetscErrorCode ierr;
1289 
1290   PetscFunctionBegin;
1291   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
1292   if (iascii) {
1293     const TSRosWType rostype;
1294     PetscInt i;
1295     PetscReal abscissa[512];
1296     char buf[512];
1297     ierr = TSRosWGetType(ts,&rostype);CHKERRQ(ierr);
1298     ierr = PetscViewerASCIIPrintf(viewer,"  Rosenbrock-W %s\n",rostype);CHKERRQ(ierr);
1299     ierr = PetscFormatRealArray(buf,sizeof buf,"% 8.6f",tab->s,tab->ASum);CHKERRQ(ierr);
1300     ierr = PetscViewerASCIIPrintf(viewer,"  Abscissa of A       = %s\n",buf);CHKERRQ(ierr);
1301     for (i=0; i<tab->s; i++) abscissa[i] = tab->ASum[i] + tab->Gamma[i];
1302     ierr = PetscFormatRealArray(buf,sizeof buf,"% 8.6f",tab->s,abscissa);CHKERRQ(ierr);
1303     ierr = PetscViewerASCIIPrintf(viewer,"  Abscissa of A+Gamma = %s\n",buf);CHKERRQ(ierr);
1304   }
1305   ierr = SNESView(ts->snes,viewer);CHKERRQ(ierr);
1306   PetscFunctionReturn(0);
1307 }
1308 
1309 #undef __FUNCT__
1310 #define __FUNCT__ "TSRosWSetType"
1311 /*@C
1312   TSRosWSetType - Set the type of Rosenbrock-W scheme
1313 
1314   Logically collective
1315 
1316   Input Parameter:
1317 +  ts - timestepping context
1318 -  rostype - type of Rosenbrock-W scheme
1319 
1320   Level: beginner
1321 
1322 .seealso: TSRosWGetType(), TSROSW, TSROSW2M, TSROSW2P, TSROSWRA3PW, TSROSWRA34PW2, TSROSWRODAS3, TSROSWSANDU3, TSROSWASSP3P3S1C, TSROSWLASSP3P4S2C, TSROSWLLSSP3P4S2C, TSROSWARK3
1323 @*/
1324 PetscErrorCode TSRosWSetType(TS ts,const TSRosWType rostype)
1325 {
1326   PetscErrorCode ierr;
1327 
1328   PetscFunctionBegin;
1329   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1330   ierr = PetscTryMethod(ts,"TSRosWSetType_C",(TS,const TSRosWType),(ts,rostype));CHKERRQ(ierr);
1331   PetscFunctionReturn(0);
1332 }
1333 
1334 #undef __FUNCT__
1335 #define __FUNCT__ "TSRosWGetType"
1336 /*@C
1337   TSRosWGetType - Get the type of Rosenbrock-W scheme
1338 
1339   Logically collective
1340 
1341   Input Parameter:
1342 .  ts - timestepping context
1343 
1344   Output Parameter:
1345 .  rostype - type of Rosenbrock-W scheme
1346 
1347   Level: intermediate
1348 
1349 .seealso: TSRosWGetType()
1350 @*/
1351 PetscErrorCode TSRosWGetType(TS ts,const TSRosWType *rostype)
1352 {
1353   PetscErrorCode ierr;
1354 
1355   PetscFunctionBegin;
1356   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1357   ierr = PetscUseMethod(ts,"TSRosWGetType_C",(TS,const TSRosWType*),(ts,rostype));CHKERRQ(ierr);
1358   PetscFunctionReturn(0);
1359 }
1360 
1361 #undef __FUNCT__
1362 #define __FUNCT__ "TSRosWSetRecomputeJacobian"
1363 /*@C
1364   TSRosWSetRecomputeJacobian - Set whether to recompute the Jacobian at each stage. The default is to update the Jacobian once per step.
1365 
1366   Logically collective
1367 
1368   Input Parameter:
1369 +  ts - timestepping context
1370 -  flg - PETSC_TRUE to recompute the Jacobian at each stage
1371 
1372   Level: intermediate
1373 
1374 .seealso: TSRosWGetType()
1375 @*/
1376 PetscErrorCode TSRosWSetRecomputeJacobian(TS ts,PetscBool flg)
1377 {
1378   PetscErrorCode ierr;
1379 
1380   PetscFunctionBegin;
1381   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1382   ierr = PetscTryMethod(ts,"TSRosWSetRecomputeJacobian_C",(TS,PetscBool),(ts,flg));CHKERRQ(ierr);
1383   PetscFunctionReturn(0);
1384 }
1385 
1386 EXTERN_C_BEGIN
1387 #undef __FUNCT__
1388 #define __FUNCT__ "TSRosWGetType_RosW"
1389 PetscErrorCode  TSRosWGetType_RosW(TS ts,const TSRosWType *rostype)
1390 {
1391   TS_RosW        *ros = (TS_RosW*)ts->data;
1392   PetscErrorCode ierr;
1393 
1394   PetscFunctionBegin;
1395   if (!ros->tableau) {ierr = TSRosWSetType(ts,TSRosWDefault);CHKERRQ(ierr);}
1396   *rostype = ros->tableau->name;
1397   PetscFunctionReturn(0);
1398 }
1399 #undef __FUNCT__
1400 #define __FUNCT__ "TSRosWSetType_RosW"
1401 PetscErrorCode  TSRosWSetType_RosW(TS ts,const TSRosWType rostype)
1402 {
1403   TS_RosW         *ros = (TS_RosW*)ts->data;
1404   PetscErrorCode  ierr;
1405   PetscBool       match;
1406   RosWTableauLink link;
1407 
1408   PetscFunctionBegin;
1409   if (ros->tableau) {
1410     ierr = PetscStrcmp(ros->tableau->name,rostype,&match);CHKERRQ(ierr);
1411     if (match) PetscFunctionReturn(0);
1412   }
1413   for (link = RosWTableauList; link; link=link->next) {
1414     ierr = PetscStrcmp(link->tab.name,rostype,&match);CHKERRQ(ierr);
1415     if (match) {
1416       ierr = TSReset_RosW(ts);CHKERRQ(ierr);
1417       ros->tableau = &link->tab;
1418       PetscFunctionReturn(0);
1419     }
1420   }
1421   SETERRQ1(((PetscObject)ts)->comm,PETSC_ERR_ARG_UNKNOWN_TYPE,"Could not find '%s'",rostype);
1422   PetscFunctionReturn(0);
1423 }
1424 
1425 #undef __FUNCT__
1426 #define __FUNCT__ "TSRosWSetRecomputeJacobian_RosW"
1427 PetscErrorCode  TSRosWSetRecomputeJacobian_RosW(TS ts,PetscBool flg)
1428 {
1429   TS_RosW *ros = (TS_RosW*)ts->data;
1430 
1431   PetscFunctionBegin;
1432   ros->recompute_jacobian = flg;
1433   PetscFunctionReturn(0);
1434 }
1435 EXTERN_C_END
1436 
1437 /* ------------------------------------------------------------ */
1438 /*MC
1439       TSROSW - ODE solver using Rosenbrock-W schemes
1440 
1441   These methods are intended for problems with well-separated time scales, especially when a slow scale is strongly
1442   nonlinear such that it is expensive to solve with a fully implicit method. The user should provide the stiff part
1443   of the equation using TSSetIFunction() and the non-stiff part with TSSetRHSFunction().
1444 
1445   Notes:
1446   This method currently only works with autonomous ODE and DAE.
1447 
1448   Developer notes:
1449   Rosenbrock-W methods are typically specified for autonomous ODE
1450 
1451 $  xdot = f(x)
1452 
1453   by the stage equations
1454 
1455 $  k_i = h f(x_0 + sum_j alpha_ij k_j) + h J sum_j gamma_ij k_j
1456 
1457   and step completion formula
1458 
1459 $  x_1 = x_0 + sum_j b_j k_j
1460 
1461   with step size h and coefficients alpha_ij, gamma_ij, and b_i. Implementing the method in this form would require f(x)
1462   and the Jacobian J to be available, in addition to the shifted matrix I - h gamma_ii J. Following Hairer and Wanner,
1463   we define new variables for the stage equations
1464 
1465 $  y_i = gamma_ij k_j
1466 
1467   The k_j can be recovered because Gamma is invertible. Let C be the lower triangular part of Gamma^{-1} and define
1468 
1469 $  A = Alpha Gamma^{-1}, bt^T = b^T Gamma^{-i}
1470 
1471   to rewrite the method as
1472 
1473 $  [M/(h gamma_ii) - J] y_i = f(x_0 + sum_j a_ij y_j) + M sum_j (c_ij/h) y_j
1474 $  x_1 = x_0 + sum_j bt_j y_j
1475 
1476    where we have introduced the mass matrix M. Continue by defining
1477 
1478 $  ydot_i = 1/(h gamma_ii) y_i - sum_j (c_ij/h) y_j
1479 
1480    or, more compactly in tensor notation
1481 
1482 $  Ydot = 1/h (Gamma^{-1} \otimes I) Y .
1483 
1484    Note that Gamma^{-1} is lower triangular. With this definition of Ydot in terms of known quantities and the current
1485    stage y_i, the stage equations reduce to performing one Newton step (typically with a lagged Jacobian) on the
1486    equation
1487 
1488 $  g(x_0 + sum_j a_ij y_j + y_i, ydot_i) = 0
1489 
1490    with initial guess y_i = 0.
1491 
1492   Level: beginner
1493 
1494 .seealso:  TSCreate(), TS, TSSetType(), TSRosWSetType(), TSRosWRegister()
1495 
1496 M*/
1497 EXTERN_C_BEGIN
1498 #undef __FUNCT__
1499 #define __FUNCT__ "TSCreate_RosW"
1500 PetscErrorCode  TSCreate_RosW(TS ts)
1501 {
1502   TS_RosW        *ros;
1503   PetscErrorCode ierr;
1504 
1505   PetscFunctionBegin;
1506 #if !defined(PETSC_USE_DYNAMIC_LIBRARIES)
1507   ierr = TSRosWInitializePackage(PETSC_NULL);CHKERRQ(ierr);
1508 #endif
1509 
1510   ts->ops->reset          = TSReset_RosW;
1511   ts->ops->destroy        = TSDestroy_RosW;
1512   ts->ops->view           = TSView_RosW;
1513   ts->ops->setup          = TSSetUp_RosW;
1514   ts->ops->step           = TSStep_RosW;
1515   ts->ops->interpolate    = TSInterpolate_RosW;
1516   ts->ops->evaluatestep   = TSEvaluateStep_RosW;
1517   ts->ops->setfromoptions = TSSetFromOptions_RosW;
1518   ts->ops->snesfunction   = SNESTSFormFunction_RosW;
1519   ts->ops->snesjacobian   = SNESTSFormJacobian_RosW;
1520 
1521   ierr = PetscNewLog(ts,TS_RosW,&ros);CHKERRQ(ierr);
1522   ts->data = (void*)ros;
1523 
1524   ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSRosWGetType_C","TSRosWGetType_RosW",TSRosWGetType_RosW);CHKERRQ(ierr);
1525   ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSRosWSetType_C","TSRosWSetType_RosW",TSRosWSetType_RosW);CHKERRQ(ierr);
1526   ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSRosWSetRecomputeJacobian_C","TSRosWSetRecomputeJacobian_RosW",TSRosWSetRecomputeJacobian_RosW);CHKERRQ(ierr);
1527   PetscFunctionReturn(0);
1528 }
1529 EXTERN_C_END
1530