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