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