xref: /petsc/src/ts/impls/rosw/rosw.c (revision 5b6bfdb9644f185dbf5e5a09b808ec241507e1e7)
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     = PetscCalloc1(1,&link);CHKERRQ(ierr);
712   t        = &link->tab;
713   ierr     = PetscStrallocpy(name,&t->name);CHKERRQ(ierr);
714   t->order = order;
715   t->s     = s;
716   ierr     = PetscMalloc5(s*s,&t->A,s*s,&t->Gamma,s,&t->b,s,&t->ASum,s,&t->GammaSum);CHKERRQ(ierr);
717   ierr     = PetscMalloc5(s*s,&t->At,s,&t->bt,s*s,&t->GammaInv,s,&t->GammaZeroDiag,s*s,&t->GammaExplicitCorr);CHKERRQ(ierr);
718   ierr     = PetscMemcpy(t->A,A,s*s*sizeof(A[0]));CHKERRQ(ierr);
719   ierr     = PetscMemcpy(t->Gamma,Gamma,s*s*sizeof(Gamma[0]));CHKERRQ(ierr);
720   ierr     = PetscMemcpy(t->GammaExplicitCorr,Gamma,s*s*sizeof(Gamma[0]));CHKERRQ(ierr);
721   ierr     = PetscMemcpy(t->b,b,s*sizeof(b[0]));CHKERRQ(ierr);
722   if (bembed) {
723     ierr = PetscMalloc2(s,&t->bembed,s,&t->bembedt);CHKERRQ(ierr);
724     ierr = PetscMemcpy(t->bembed,bembed,s*sizeof(bembed[0]));CHKERRQ(ierr);
725   }
726   for (i=0; i<s; i++) {
727     t->ASum[i]     = 0;
728     t->GammaSum[i] = 0;
729     for (j=0; j<s; j++) {
730       t->ASum[i]     += A[i*s+j];
731       t->GammaSum[i] += Gamma[i*s+j];
732     }
733   }
734   ierr = PetscMalloc1(s*s,&GammaInv);CHKERRQ(ierr); /* Need to use Scalar for inverse, then convert back to Real */
735   for (i=0; i<s*s; i++) GammaInv[i] = Gamma[i];
736   for (i=0; i<s; i++) {
737     if (Gamma[i*s+i] == 0.0) {
738       GammaInv[i*s+i] = 1.0;
739       t->GammaZeroDiag[i] = PETSC_TRUE;
740     } else {
741       t->GammaZeroDiag[i] = PETSC_FALSE;
742     }
743   }
744 
745   switch (s) {
746   case 1: GammaInv[0] = 1./GammaInv[0]; break;
747   case 2: ierr = PetscKernel_A_gets_inverse_A_2(GammaInv,0,PETSC_FALSE,NULL);CHKERRQ(ierr); break;
748   case 3: ierr = PetscKernel_A_gets_inverse_A_3(GammaInv,0,PETSC_FALSE,NULL);CHKERRQ(ierr); break;
749   case 4: ierr = PetscKernel_A_gets_inverse_A_4(GammaInv,0,PETSC_FALSE,NULL);CHKERRQ(ierr); break;
750   case 5: {
751     PetscInt  ipvt5[5];
752     MatScalar work5[5*5];
753     ierr = PetscKernel_A_gets_inverse_A_5(GammaInv,ipvt5,work5,0,PETSC_FALSE,NULL);CHKERRQ(ierr); break;
754   }
755   case 6: ierr = PetscKernel_A_gets_inverse_A_6(GammaInv,0,PETSC_FALSE,NULL);CHKERRQ(ierr); break;
756   case 7: ierr = PetscKernel_A_gets_inverse_A_7(GammaInv,0,PETSC_FALSE,NULL);CHKERRQ(ierr); break;
757   default: SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented for %D stages",s);
758   }
759   for (i=0; i<s*s; i++) t->GammaInv[i] = PetscRealPart(GammaInv[i]);
760   ierr = PetscFree(GammaInv);CHKERRQ(ierr);
761 
762   for (i=0; i<s; i++) {
763     for (k=0; k<i+1; k++) {
764       t->GammaExplicitCorr[i*s+k]=(t->GammaExplicitCorr[i*s+k])*(t->GammaInv[k*s+k]);
765       for (j=k+1; j<i+1; j++) {
766         t->GammaExplicitCorr[i*s+k]+=(t->GammaExplicitCorr[i*s+j])*(t->GammaInv[j*s+k]);
767       }
768     }
769   }
770 
771   for (i=0; i<s; i++) {
772     for (j=0; j<s; j++) {
773       t->At[i*s+j] = 0;
774       for (k=0; k<s; k++) {
775         t->At[i*s+j] += t->A[i*s+k] * t->GammaInv[k*s+j];
776       }
777     }
778     t->bt[i] = 0;
779     for (j=0; j<s; j++) {
780       t->bt[i] += t->b[j] * t->GammaInv[j*s+i];
781     }
782     if (bembed) {
783       t->bembedt[i] = 0;
784       for (j=0; j<s; j++) {
785         t->bembedt[i] += t->bembed[j] * t->GammaInv[j*s+i];
786       }
787     }
788   }
789   t->ccfl = 1.0;                /* Fix this */
790 
791   t->pinterp = pinterp;
792   ierr = PetscMalloc1(s*pinterp,&t->binterpt);CHKERRQ(ierr);
793   ierr = PetscMemcpy(t->binterpt,binterpt,s*pinterp*sizeof(binterpt[0]));CHKERRQ(ierr);
794   link->next = RosWTableauList;
795   RosWTableauList = link;
796   PetscFunctionReturn(0);
797 }
798 
799 /*@C
800    TSRosWRegisterRos4 - register a fourth order Rosenbrock scheme by providing paramter choices
801 
802    Not Collective, but the same schemes should be registered on all processes on which they will be used
803 
804    Input Parameters:
805 +  name - identifier for method
806 .  gamma - leading coefficient (diagonal entry)
807 .  a2 - design parameter, see Table 7.2 of Hairer&Wanner
808 .  a3 - design parameter or PETSC_DEFAULT to satisfy one of the order five conditions (Eq 7.22)
809 .  b3 - design parameter, see Table 7.2 of Hairer&Wanner
810 .  beta43 - design parameter or PETSC_DEFAULT to use Equation 7.21 of Hairer&Wanner
811 .  e4 - design parameter for embedded method, see coefficient E4 in ros4.f code from Hairer
812 
813    Notes:
814    This routine encodes the design of fourth order Rosenbrock methods as described in Hairer and Wanner volume 2.
815    It is used here to implement several methods from the book and can be used to experiment with new methods.
816    It was written this way instead of by copying coefficients in order to provide better than double precision satisfaction of the order conditions.
817 
818    Level: developer
819 
820 .keywords: TS, register
821 
822 .seealso: TSRosW, TSRosWRegister()
823 @*/
824 PetscErrorCode TSRosWRegisterRos4(TSRosWType name,PetscReal gamma,PetscReal a2,PetscReal a3,PetscReal b3,PetscReal e4)
825 {
826   PetscErrorCode ierr;
827   /* Declare numeric constants so they can be quad precision without being truncated at double */
828   const PetscReal one = 1,two = 2,three = 3,four = 4,five = 5,six = 6,eight = 8,twelve = 12,twenty = 20,twentyfour = 24,
829     p32 = one/six - gamma + gamma*gamma,
830     p42 = one/eight - gamma/three,
831     p43 = one/twelve - gamma/three,
832     p44 = one/twentyfour - gamma/two + three/two*gamma*gamma - gamma*gamma*gamma,
833     p56 = one/twenty - gamma/four;
834   PetscReal   a4,a32,a42,a43,b1,b2,b4,beta2p,beta3p,beta4p,beta32,beta42,beta43,beta32beta2p,beta4jbetajp;
835   PetscReal   A[4][4],Gamma[4][4],b[4],bm[4];
836   PetscScalar M[3][3],rhs[3];
837 
838   PetscFunctionBegin;
839   /* Step 1: choose Gamma (input) */
840   /* Step 2: choose a2,a3,a4; b1,b2,b3,b4 to satisfy order conditions */
841   if (a3 == PETSC_DEFAULT) a3 = (one/five - a2/four)/(one/four - a2/three); /* Eq 7.22 */
842   a4 = a3;                                                  /* consequence of 7.20 */
843 
844   /* Solve order conditions 7.15a, 7.15c, 7.15e */
845   M[0][0] = one; M[0][1] = one;      M[0][2] = one;      /* 7.15a */
846   M[1][0] = 0.0; M[1][1] = a2*a2;    M[1][2] = a4*a4;    /* 7.15c */
847   M[2][0] = 0.0; M[2][1] = a2*a2*a2; M[2][2] = a4*a4*a4; /* 7.15e */
848   rhs[0]  = one - b3;
849   rhs[1]  = one/three - a3*a3*b3;
850   rhs[2]  = one/four - a3*a3*a3*b3;
851   ierr    = PetscKernel_A_gets_inverse_A_3(&M[0][0],0,PETSC_FALSE,NULL);CHKERRQ(ierr);
852   b1      = PetscRealPart(M[0][0]*rhs[0] + M[0][1]*rhs[1] + M[0][2]*rhs[2]);
853   b2      = PetscRealPart(M[1][0]*rhs[0] + M[1][1]*rhs[1] + M[1][2]*rhs[2]);
854   b4      = PetscRealPart(M[2][0]*rhs[0] + M[2][1]*rhs[1] + M[2][2]*rhs[2]);
855 
856   /* Step 3 */
857   beta43       = (p56 - a2*p43) / (b4*a3*a3*(a3 - a2)); /* 7.21 */
858   beta32beta2p =  p44 / (b4*beta43);                    /* 7.15h */
859   beta4jbetajp = (p32 - b3*beta32beta2p) / b4;
860   M[0][0]      = b2;                                    M[0][1] = b3;                 M[0][2] = b4;
861   M[1][0]      = a4*a4*beta32beta2p-a3*a3*beta4jbetajp; M[1][1] = a2*a2*beta4jbetajp; M[1][2] = -a2*a2*beta32beta2p;
862   M[2][0]      = b4*beta43*a3*a3-p43;                   M[2][1] = -b4*beta43*a2*a2;   M[2][2] = 0;
863   rhs[0]       = one/two - gamma; rhs[1] = 0; rhs[2] = -a2*a2*p32;
864   ierr         = PetscKernel_A_gets_inverse_A_3(&M[0][0],0,PETSC_FALSE,NULL);CHKERRQ(ierr);
865   beta2p       = PetscRealPart(M[0][0]*rhs[0] + M[0][1]*rhs[1] + M[0][2]*rhs[2]);
866   beta3p       = PetscRealPart(M[1][0]*rhs[0] + M[1][1]*rhs[1] + M[1][2]*rhs[2]);
867   beta4p       = PetscRealPart(M[2][0]*rhs[0] + M[2][1]*rhs[1] + M[2][2]*rhs[2]);
868 
869   /* Step 4: back-substitute */
870   beta32 = beta32beta2p / beta2p;
871   beta42 = (beta4jbetajp - beta43*beta3p) / beta2p;
872 
873   /* Step 5: 7.15f and 7.20, then 7.16 */
874   a43 = 0;
875   a32 = p42 / (b3*a3*beta2p + b4*a4*beta2p);
876   a42 = a32;
877 
878   A[0][0]     = 0;          A[0][1] = 0;   A[0][2] = 0;   A[0][3] = 0;
879   A[1][0]     = a2;         A[1][1] = 0;   A[1][2] = 0;   A[1][3] = 0;
880   A[2][0]     = a3-a32;     A[2][1] = a32; A[2][2] = 0;   A[2][3] = 0;
881   A[3][0]     = a4-a43-a42; A[3][1] = a42; A[3][2] = a43; A[3][3] = 0;
882   Gamma[0][0] = gamma;                        Gamma[0][1] = 0;              Gamma[0][2] = 0;              Gamma[0][3] = 0;
883   Gamma[1][0] = beta2p-A[1][0];               Gamma[1][1] = gamma;          Gamma[1][2] = 0;              Gamma[1][3] = 0;
884   Gamma[2][0] = beta3p-beta32-A[2][0];        Gamma[2][1] = beta32-A[2][1]; Gamma[2][2] = gamma;          Gamma[2][3] = 0;
885   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;
886   b[0] = b1; b[1] = b2; b[2] = b3; b[3] = b4;
887 
888   /* Construct embedded formula using given e4. We are solving Equation 7.18. */
889   bm[3] = b[3] - e4*gamma;                                          /* using definition of E4 */
890   bm[2] = (p32 - beta4jbetajp*bm[3]) / (beta32*beta2p);             /* fourth row of 7.18 */
891   bm[1] = (one/two - gamma - beta3p*bm[2] - beta4p*bm[3]) / beta2p; /* second row */
892   bm[0] = one - bm[1] - bm[2] - bm[3];                              /* first row */
893 
894   {
895     const PetscReal misfit = a2*a2*bm[1] + a3*a3*bm[2] + a4*a4*bm[3] - one/three;
896     if (PetscAbs(misfit) > PETSC_SMALL) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Assumptions violated, could not construct a third order embedded method");
897   }
898   ierr = TSRosWRegister(name,4,4,&A[0][0],&Gamma[0][0],b,bm,0,NULL);CHKERRQ(ierr);
899   PetscFunctionReturn(0);
900 }
901 
902 /*
903  The step completion formula is
904 
905  x1 = x0 + b^T Y
906 
907  where Y is the multi-vector of stages corrections. This function can be called before or after ts->vec_sol has been
908  updated. Suppose we have a completion formula b and an embedded formula be of different order. We can write
909 
910  x1e = x0 + be^T Y
911      = x1 - b^T Y + be^T Y
912      = x1 + (be - b)^T Y
913 
914  so we can evaluate the method of different order even after the step has been optimistically completed.
915 */
916 static PetscErrorCode TSEvaluateStep_RosW(TS ts,PetscInt order,Vec U,PetscBool *done)
917 {
918   TS_RosW        *ros = (TS_RosW*)ts->data;
919   RosWTableau    tab  = ros->tableau;
920   PetscScalar    *w   = ros->work;
921   PetscInt       i;
922   PetscErrorCode ierr;
923 
924   PetscFunctionBegin;
925   if (order == tab->order) {
926     if (ros->status == TS_STEP_INCOMPLETE) { /* Use standard completion formula */
927       ierr = VecCopy(ts->vec_sol,U);CHKERRQ(ierr);
928       for (i=0; i<tab->s; i++) w[i] = tab->bt[i];
929       ierr = VecMAXPY(U,tab->s,w,ros->Y);CHKERRQ(ierr);
930     } else {ierr = VecCopy(ts->vec_sol,U);CHKERRQ(ierr);}
931     if (done) *done = PETSC_TRUE;
932     PetscFunctionReturn(0);
933   } else if (order == tab->order-1) {
934     if (!tab->bembedt) goto unavailable;
935     if (ros->status == TS_STEP_INCOMPLETE) { /* Use embedded completion formula */
936       ierr = VecCopy(ts->vec_sol,U);CHKERRQ(ierr);
937       for (i=0; i<tab->s; i++) w[i] = tab->bembedt[i];
938       ierr = VecMAXPY(U,tab->s,w,ros->Y);CHKERRQ(ierr);
939     } else {                    /* Use rollback-and-recomplete formula (bembedt - bt) */
940       for (i=0; i<tab->s; i++) w[i] = tab->bembedt[i] - tab->bt[i];
941       ierr = VecCopy(ts->vec_sol,U);CHKERRQ(ierr);
942       ierr = VecMAXPY(U,tab->s,w,ros->Y);CHKERRQ(ierr);
943     }
944     if (done) *done = PETSC_TRUE;
945     PetscFunctionReturn(0);
946   }
947   unavailable:
948   if (done) *done = PETSC_FALSE;
949   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);
950   PetscFunctionReturn(0);
951 }
952 
953 static PetscErrorCode TSRollBack_RosW(TS ts)
954 {
955   TS_RosW        *ros = (TS_RosW*)ts->data;
956   PetscErrorCode ierr;
957 
958   PetscFunctionBegin;
959   ierr = VecCopy(ros->vec_sol_prev,ts->vec_sol);CHKERRQ(ierr);
960   PetscFunctionReturn(0);
961 }
962 
963 static PetscErrorCode TSStep_RosW(TS ts)
964 {
965   TS_RosW         *ros = (TS_RosW*)ts->data;
966   RosWTableau     tab  = ros->tableau;
967   const PetscInt  s    = tab->s;
968   const PetscReal *At  = tab->At,*Gamma = tab->Gamma,*ASum = tab->ASum,*GammaInv = tab->GammaInv;
969   const PetscReal *GammaExplicitCorr = tab->GammaExplicitCorr;
970   const PetscBool *GammaZeroDiag = tab->GammaZeroDiag;
971   PetscScalar     *w   = ros->work;
972   Vec             *Y   = ros->Y,Ydot = ros->Ydot,Zdot = ros->Zdot,Zstage = ros->Zstage;
973   SNES            snes;
974   TSAdapt         adapt;
975   PetscInt        i,j,its,lits;
976   PetscInt        rejections = 0;
977   PetscBool       stageok,accept = PETSC_TRUE;
978   PetscReal       next_time_step = ts->time_step;
979   PetscErrorCode  ierr;
980 
981   PetscFunctionBegin;
982   if (!ts->steprollback) {
983     ierr = VecCopy(ts->vec_sol,ros->vec_sol_prev);CHKERRQ(ierr);
984   }
985 
986   ros->status = TS_STEP_INCOMPLETE;
987   while (!ts->reason && ros->status != TS_STEP_COMPLETE) {
988     const PetscReal h = ts->time_step;
989     for (i=0; i<s; i++) {
990       ros->stage_time = ts->ptime + h*ASum[i];
991       ierr = TSPreStage(ts,ros->stage_time);CHKERRQ(ierr);
992       if (GammaZeroDiag[i]) {
993         ros->stage_explicit = PETSC_TRUE;
994         ros->scoeff         = 1.;
995       } else {
996         ros->stage_explicit = PETSC_FALSE;
997         ros->scoeff         = 1./Gamma[i*s+i];
998       }
999 
1000       ierr = VecCopy(ts->vec_sol,Zstage);CHKERRQ(ierr);
1001       for (j=0; j<i; j++) w[j] = At[i*s+j];
1002       ierr = VecMAXPY(Zstage,i,w,Y);CHKERRQ(ierr);
1003 
1004       for (j=0; j<i; j++) w[j] = 1./h * GammaInv[i*s+j];
1005       ierr = VecZeroEntries(Zdot);CHKERRQ(ierr);
1006       ierr = VecMAXPY(Zdot,i,w,Y);CHKERRQ(ierr);
1007 
1008       /* Initial guess taken from last stage */
1009       ierr = VecZeroEntries(Y[i]);CHKERRQ(ierr);
1010 
1011       if (!ros->stage_explicit) {
1012         ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
1013         if (!ros->recompute_jacobian && !i) {
1014           ierr = SNESSetLagJacobian(snes,-2);CHKERRQ(ierr); /* Recompute the Jacobian on this solve, but not again */
1015         }
1016         ierr = SNESSolve(snes,NULL,Y[i]);CHKERRQ(ierr);
1017         ierr = SNESGetIterationNumber(snes,&its);CHKERRQ(ierr);
1018         ierr = SNESGetLinearSolveIterations(snes,&lits);CHKERRQ(ierr);
1019         ts->snes_its += its; ts->ksp_its += lits;
1020       } else {
1021         Mat J,Jp;
1022         ierr = VecZeroEntries(Ydot);CHKERRQ(ierr); /* Evaluate Y[i]=G(t,Ydot=0,Zstage) */
1023         ierr = TSComputeIFunction(ts,ros->stage_time,Zstage,Ydot,Y[i],PETSC_FALSE);CHKERRQ(ierr);
1024         ierr = VecScale(Y[i],-1.0);CHKERRQ(ierr);
1025         ierr = VecAXPY(Y[i],-1.0,Zdot);CHKERRQ(ierr); /*Y[i] = F(Zstage)-Zdot[=GammaInv*Y]*/
1026 
1027         ierr = VecZeroEntries(Zstage);CHKERRQ(ierr); /* Zstage = GammaExplicitCorr[i,j] * Y[j] */
1028         for (j=0; j<i; j++) w[j] = GammaExplicitCorr[i*s+j];
1029         ierr = VecMAXPY(Zstage,i,w,Y);CHKERRQ(ierr);
1030 
1031         /* Y[i] = Y[i] + Jac*Zstage[=Jac*GammaExplicitCorr[i,j] * Y[j]] */
1032         ierr = TSGetIJacobian(ts,&J,&Jp,NULL,NULL);CHKERRQ(ierr);
1033         ierr = TSComputeIJacobian(ts,ros->stage_time,ts->vec_sol,Ydot,0,J,Jp,PETSC_FALSE);CHKERRQ(ierr);
1034         ierr = MatMult(J,Zstage,Zdot);CHKERRQ(ierr);
1035         ierr = VecAXPY(Y[i],-1.0,Zdot);CHKERRQ(ierr);
1036         ts->ksp_its += 1;
1037 
1038         ierr = VecScale(Y[i],h);CHKERRQ(ierr);
1039       }
1040       ierr = TSPostStage(ts,ros->stage_time,i,Y);CHKERRQ(ierr);
1041       ierr = TSGetAdapt(ts,&adapt);CHKERRQ(ierr);
1042       ierr = TSAdaptCheckStage(adapt,ts,ros->stage_time,Y[i],&stageok);CHKERRQ(ierr);
1043       if (!stageok) goto reject_step;
1044     }
1045 
1046     ros->status = TS_STEP_INCOMPLETE;
1047     ierr = TSEvaluateStep_RosW(ts,tab->order,ts->vec_sol,NULL);CHKERRQ(ierr);
1048     ros->status = TS_STEP_PENDING;
1049     ierr = TSGetAdapt(ts,&adapt);CHKERRQ(ierr);
1050     ierr = TSAdaptCandidatesClear(adapt);CHKERRQ(ierr);
1051     ierr = TSAdaptCandidateAdd(adapt,tab->name,tab->order,1,tab->ccfl,(PetscReal)tab->s,PETSC_TRUE);CHKERRQ(ierr);
1052     ierr = TSAdaptChoose(adapt,ts,ts->time_step,NULL,&next_time_step,&accept);CHKERRQ(ierr);
1053     ros->status = accept ? TS_STEP_COMPLETE : TS_STEP_INCOMPLETE;
1054     if (!accept) { /* Roll back the current step */
1055       ierr = TSRollBack_RosW(ts);CHKERRQ(ierr);
1056       ts->time_step = next_time_step;
1057       goto reject_step;
1058     }
1059 
1060     ts->ptime += ts->time_step;
1061     ts->time_step = next_time_step;
1062     break;
1063 
1064   reject_step:
1065     ts->reject++; accept = PETSC_FALSE;
1066     if (!ts->reason && ++rejections > ts->max_reject && ts->max_reject >= 0) {
1067       ts->reason = TS_DIVERGED_STEP_REJECTED;
1068       ierr = PetscInfo2(ts,"Step=%D, step rejections %D greater than current TS allowed, stopping solve\n",ts->steps,rejections);CHKERRQ(ierr);
1069     }
1070   }
1071   PetscFunctionReturn(0);
1072 }
1073 
1074 static PetscErrorCode TSInterpolate_RosW(TS ts,PetscReal itime,Vec U)
1075 {
1076   TS_RosW         *ros = (TS_RosW*)ts->data;
1077   PetscInt        s    = ros->tableau->s,pinterp = ros->tableau->pinterp,i,j;
1078   PetscReal       h;
1079   PetscReal       tt,t;
1080   PetscScalar     *bt;
1081   const PetscReal *Bt = ros->tableau->binterpt;
1082   PetscErrorCode  ierr;
1083   const PetscReal *GammaInv = ros->tableau->GammaInv;
1084   PetscScalar     *w        = ros->work;
1085   Vec             *Y        = ros->Y;
1086 
1087   PetscFunctionBegin;
1088   if (!Bt) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSRosW %s does not have an interpolation formula",ros->tableau->name);
1089 
1090   switch (ros->status) {
1091   case TS_STEP_INCOMPLETE:
1092   case TS_STEP_PENDING:
1093     h = ts->time_step;
1094     t = (itime - ts->ptime)/h;
1095     break;
1096   case TS_STEP_COMPLETE:
1097     h = ts->ptime - ts->ptime_prev;
1098     t = (itime - ts->ptime)/h + 1; /* In the interval [0,1] */
1099     break;
1100   default: SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_PLIB,"Invalid TSStepStatus");
1101   }
1102   ierr = PetscMalloc1(s,&bt);CHKERRQ(ierr);
1103   for (i=0; i<s; i++) bt[i] = 0;
1104   for (j=0,tt=t; j<pinterp; j++,tt*=t) {
1105     for (i=0; i<s; i++) {
1106       bt[i] += Bt[i*pinterp+j] * tt;
1107     }
1108   }
1109 
1110   /* y(t+tt*h) = y(t) + Sum bt(tt) * GammaInv * Ydot */
1111   /* U <- 0*/
1112   ierr = VecZeroEntries(U);CHKERRQ(ierr);
1113   /* U <- Sum bt_i * GammaInv(i,1:i) * Y(1:i) */
1114   for (j=0; j<s; j++) w[j] = 0;
1115   for (j=0; j<s; j++) {
1116     for (i=j; i<s; i++) {
1117       w[j] +=  bt[i]*GammaInv[i*s+j];
1118     }
1119   }
1120   ierr = VecMAXPY(U,i,w,Y);CHKERRQ(ierr);
1121   /* U <- y(t) + U */
1122   ierr = VecAXPY(U,1,ros->vec_sol_prev);CHKERRQ(ierr);
1123 
1124   ierr = PetscFree(bt);CHKERRQ(ierr);
1125   PetscFunctionReturn(0);
1126 }
1127 
1128 /*------------------------------------------------------------*/
1129 
1130 static PetscErrorCode TSRosWTableauReset(TS ts)
1131 {
1132   TS_RosW        *ros = (TS_RosW*)ts->data;
1133   RosWTableau    tab  = ros->tableau;
1134   PetscErrorCode ierr;
1135 
1136   PetscFunctionBegin;
1137   if (!tab) PetscFunctionReturn(0);
1138   ierr = VecDestroyVecs(tab->s,&ros->Y);CHKERRQ(ierr);
1139   ierr = PetscFree(ros->work);CHKERRQ(ierr);
1140   PetscFunctionReturn(0);
1141 }
1142 
1143 static PetscErrorCode TSReset_RosW(TS ts)
1144 {
1145   TS_RosW        *ros = (TS_RosW*)ts->data;
1146   PetscErrorCode ierr;
1147 
1148   PetscFunctionBegin;
1149   ierr = TSRosWTableauReset(ts);CHKERRQ(ierr);
1150   ierr = VecDestroy(&ros->Ydot);CHKERRQ(ierr);
1151   ierr = VecDestroy(&ros->Ystage);CHKERRQ(ierr);
1152   ierr = VecDestroy(&ros->Zdot);CHKERRQ(ierr);
1153   ierr = VecDestroy(&ros->Zstage);CHKERRQ(ierr);
1154   ierr = VecDestroy(&ros->vec_sol_prev);CHKERRQ(ierr);
1155   PetscFunctionReturn(0);
1156 }
1157 
1158 static PetscErrorCode TSRosWGetVecs(TS ts,DM dm,Vec *Ydot,Vec *Zdot,Vec *Ystage,Vec *Zstage)
1159 {
1160   TS_RosW        *rw = (TS_RosW*)ts->data;
1161   PetscErrorCode ierr;
1162 
1163   PetscFunctionBegin;
1164   if (Ydot) {
1165     if (dm && dm != ts->dm) {
1166       ierr = DMGetNamedGlobalVector(dm,"TSRosW_Ydot",Ydot);CHKERRQ(ierr);
1167     } else *Ydot = rw->Ydot;
1168   }
1169   if (Zdot) {
1170     if (dm && dm != ts->dm) {
1171       ierr = DMGetNamedGlobalVector(dm,"TSRosW_Zdot",Zdot);CHKERRQ(ierr);
1172     } else *Zdot = rw->Zdot;
1173   }
1174   if (Ystage) {
1175     if (dm && dm != ts->dm) {
1176       ierr = DMGetNamedGlobalVector(dm,"TSRosW_Ystage",Ystage);CHKERRQ(ierr);
1177     } else *Ystage = rw->Ystage;
1178   }
1179   if (Zstage) {
1180     if (dm && dm != ts->dm) {
1181       ierr = DMGetNamedGlobalVector(dm,"TSRosW_Zstage",Zstage);CHKERRQ(ierr);
1182     } else *Zstage = rw->Zstage;
1183   }
1184   PetscFunctionReturn(0);
1185 }
1186 
1187 
1188 static PetscErrorCode TSRosWRestoreVecs(TS ts,DM dm,Vec *Ydot,Vec *Zdot, Vec *Ystage, Vec *Zstage)
1189 {
1190   PetscErrorCode ierr;
1191 
1192   PetscFunctionBegin;
1193   if (Ydot) {
1194     if (dm && dm != ts->dm) {
1195       ierr = DMRestoreNamedGlobalVector(dm,"TSRosW_Ydot",Ydot);CHKERRQ(ierr);
1196     }
1197   }
1198   if (Zdot) {
1199     if (dm && dm != ts->dm) {
1200       ierr = DMRestoreNamedGlobalVector(dm,"TSRosW_Zdot",Zdot);CHKERRQ(ierr);
1201     }
1202   }
1203   if (Ystage) {
1204     if (dm && dm != ts->dm) {
1205       ierr = DMRestoreNamedGlobalVector(dm,"TSRosW_Ystage",Ystage);CHKERRQ(ierr);
1206     }
1207   }
1208   if (Zstage) {
1209     if (dm && dm != ts->dm) {
1210       ierr = DMRestoreNamedGlobalVector(dm,"TSRosW_Zstage",Zstage);CHKERRQ(ierr);
1211     }
1212   }
1213   PetscFunctionReturn(0);
1214 }
1215 
1216 static PetscErrorCode DMCoarsenHook_TSRosW(DM fine,DM coarse,void *ctx)
1217 {
1218   PetscFunctionBegin;
1219   PetscFunctionReturn(0);
1220 }
1221 
1222 static PetscErrorCode DMRestrictHook_TSRosW(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse,void *ctx)
1223 {
1224   TS             ts = (TS)ctx;
1225   PetscErrorCode ierr;
1226   Vec            Ydot,Zdot,Ystage,Zstage;
1227   Vec            Ydotc,Zdotc,Ystagec,Zstagec;
1228 
1229   PetscFunctionBegin;
1230   ierr = TSRosWGetVecs(ts,fine,&Ydot,&Ystage,&Zdot,&Zstage);CHKERRQ(ierr);
1231   ierr = TSRosWGetVecs(ts,coarse,&Ydotc,&Ystagec,&Zdotc,&Zstagec);CHKERRQ(ierr);
1232   ierr = MatRestrict(restrct,Ydot,Ydotc);CHKERRQ(ierr);
1233   ierr = VecPointwiseMult(Ydotc,rscale,Ydotc);CHKERRQ(ierr);
1234   ierr = MatRestrict(restrct,Ystage,Ystagec);CHKERRQ(ierr);
1235   ierr = VecPointwiseMult(Ystagec,rscale,Ystagec);CHKERRQ(ierr);
1236   ierr = MatRestrict(restrct,Zdot,Zdotc);CHKERRQ(ierr);
1237   ierr = VecPointwiseMult(Zdotc,rscale,Zdotc);CHKERRQ(ierr);
1238   ierr = MatRestrict(restrct,Zstage,Zstagec);CHKERRQ(ierr);
1239   ierr = VecPointwiseMult(Zstagec,rscale,Zstagec);CHKERRQ(ierr);
1240   ierr = TSRosWRestoreVecs(ts,fine,&Ydot,&Ystage,&Zdot,&Zstage);CHKERRQ(ierr);
1241   ierr = TSRosWRestoreVecs(ts,coarse,&Ydotc,&Ystagec,&Zdotc,&Zstagec);CHKERRQ(ierr);
1242   PetscFunctionReturn(0);
1243 }
1244 
1245 
1246 static PetscErrorCode DMSubDomainHook_TSRosW(DM fine,DM coarse,void *ctx)
1247 {
1248   PetscFunctionBegin;
1249   PetscFunctionReturn(0);
1250 }
1251 
1252 static PetscErrorCode DMSubDomainRestrictHook_TSRosW(DM dm,VecScatter gscat,VecScatter lscat,DM subdm,void *ctx)
1253 {
1254   TS             ts = (TS)ctx;
1255   PetscErrorCode ierr;
1256   Vec            Ydot,Zdot,Ystage,Zstage;
1257   Vec            Ydots,Zdots,Ystages,Zstages;
1258 
1259   PetscFunctionBegin;
1260   ierr = TSRosWGetVecs(ts,dm,&Ydot,&Ystage,&Zdot,&Zstage);CHKERRQ(ierr);
1261   ierr = TSRosWGetVecs(ts,subdm,&Ydots,&Ystages,&Zdots,&Zstages);CHKERRQ(ierr);
1262 
1263   ierr = VecScatterBegin(gscat,Ydot,Ydots,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1264   ierr = VecScatterEnd(gscat,Ydot,Ydots,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1265 
1266   ierr = VecScatterBegin(gscat,Ystage,Ystages,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1267   ierr = VecScatterEnd(gscat,Ystage,Ystages,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1268 
1269   ierr = VecScatterBegin(gscat,Zdot,Zdots,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1270   ierr = VecScatterEnd(gscat,Zdot,Zdots,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1271 
1272   ierr = VecScatterBegin(gscat,Zstage,Zstages,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1273   ierr = VecScatterEnd(gscat,Zstage,Zstages,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1274 
1275   ierr = TSRosWRestoreVecs(ts,dm,&Ydot,&Ystage,&Zdot,&Zstage);CHKERRQ(ierr);
1276   ierr = TSRosWRestoreVecs(ts,subdm,&Ydots,&Ystages,&Zdots,&Zstages);CHKERRQ(ierr);
1277   PetscFunctionReturn(0);
1278 }
1279 
1280 /*
1281   This defines the nonlinear equation that is to be solved with SNES
1282   G(U) = F[t0+Theta*dt, U, (U-U0)*shift] = 0
1283 */
1284 static PetscErrorCode SNESTSFormFunction_RosW(SNES snes,Vec U,Vec F,TS ts)
1285 {
1286   TS_RosW        *ros = (TS_RosW*)ts->data;
1287   PetscErrorCode ierr;
1288   Vec            Ydot,Zdot,Ystage,Zstage;
1289   PetscReal      shift = ros->scoeff / ts->time_step;
1290   DM             dm,dmsave;
1291 
1292   PetscFunctionBegin;
1293   ierr   = SNESGetDM(snes,&dm);CHKERRQ(ierr);
1294   ierr   = TSRosWGetVecs(ts,dm,&Ydot,&Zdot,&Ystage,&Zstage);CHKERRQ(ierr);
1295   ierr   = VecWAXPY(Ydot,shift,U,Zdot);CHKERRQ(ierr);    /* Ydot = shift*U + Zdot */
1296   ierr   = VecWAXPY(Ystage,1.0,U,Zstage);CHKERRQ(ierr);  /* Ystage = U + Zstage */
1297   dmsave = ts->dm;
1298   ts->dm = dm;
1299   ierr   = TSComputeIFunction(ts,ros->stage_time,Ystage,Ydot,F,PETSC_FALSE);CHKERRQ(ierr);
1300   ts->dm = dmsave;
1301   ierr   = TSRosWRestoreVecs(ts,dm,&Ydot,&Zdot,&Ystage,&Zstage);CHKERRQ(ierr);
1302   PetscFunctionReturn(0);
1303 }
1304 
1305 static PetscErrorCode SNESTSFormJacobian_RosW(SNES snes,Vec U,Mat A,Mat B,TS ts)
1306 {
1307   TS_RosW        *ros = (TS_RosW*)ts->data;
1308   Vec            Ydot,Zdot,Ystage,Zstage;
1309   PetscReal      shift = ros->scoeff / ts->time_step;
1310   PetscErrorCode ierr;
1311   DM             dm,dmsave;
1312 
1313   PetscFunctionBegin;
1314   /* ros->Ydot and ros->Ystage have already been computed in SNESTSFormFunction_RosW (SNES guarantees this) */
1315   ierr   = SNESGetDM(snes,&dm);CHKERRQ(ierr);
1316   ierr   = TSRosWGetVecs(ts,dm,&Ydot,&Zdot,&Ystage,&Zstage);CHKERRQ(ierr);
1317   dmsave = ts->dm;
1318   ts->dm = dm;
1319   ierr   = TSComputeIJacobian(ts,ros->stage_time,Ystage,Ydot,shift,A,B,PETSC_TRUE);CHKERRQ(ierr);
1320   ts->dm = dmsave;
1321   ierr   = TSRosWRestoreVecs(ts,dm,&Ydot,&Zdot,&Ystage,&Zstage);CHKERRQ(ierr);
1322   PetscFunctionReturn(0);
1323 }
1324 
1325 static PetscErrorCode TSRosWTableauSetUp(TS ts)
1326 {
1327   TS_RosW        *ros = (TS_RosW*)ts->data;
1328   RosWTableau    tab  = ros->tableau;
1329   PetscErrorCode ierr;
1330 
1331   PetscFunctionBegin;
1332   ierr = VecDuplicateVecs(ts->vec_sol,tab->s,&ros->Y);CHKERRQ(ierr);
1333   ierr = PetscMalloc1(tab->s,&ros->work);CHKERRQ(ierr);
1334   PetscFunctionReturn(0);
1335 }
1336 
1337 static PetscErrorCode TSSetUp_RosW(TS ts)
1338 {
1339   TS_RosW        *ros = (TS_RosW*)ts->data;
1340   PetscErrorCode ierr;
1341   DM             dm;
1342   SNES           snes;
1343 
1344   PetscFunctionBegin;
1345   ierr = TSRosWTableauSetUp(ts);CHKERRQ(ierr);
1346   ierr = VecDuplicate(ts->vec_sol,&ros->Ydot);CHKERRQ(ierr);
1347   ierr = VecDuplicate(ts->vec_sol,&ros->Ystage);CHKERRQ(ierr);
1348   ierr = VecDuplicate(ts->vec_sol,&ros->Zdot);CHKERRQ(ierr);
1349   ierr = VecDuplicate(ts->vec_sol,&ros->Zstage);CHKERRQ(ierr);
1350   ierr = VecDuplicate(ts->vec_sol,&ros->vec_sol_prev);CHKERRQ(ierr);
1351   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
1352   ierr = DMCoarsenHookAdd(dm,DMCoarsenHook_TSRosW,DMRestrictHook_TSRosW,ts);CHKERRQ(ierr);
1353   ierr = DMSubDomainHookAdd(dm,DMSubDomainHook_TSRosW,DMSubDomainRestrictHook_TSRosW,ts);CHKERRQ(ierr);
1354   /* Rosenbrock methods are linearly implicit, so set that unless the user has specifically asked for something else */
1355   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
1356   if (!((PetscObject)snes)->type_name) {
1357     ierr = SNESSetType(snes,SNESKSPONLY);CHKERRQ(ierr);
1358   }
1359   PetscFunctionReturn(0);
1360 }
1361 /*------------------------------------------------------------*/
1362 
1363 static PetscErrorCode TSSetFromOptions_RosW(PetscOptionItems *PetscOptionsObject,TS ts)
1364 {
1365   TS_RosW        *ros = (TS_RosW*)ts->data;
1366   PetscErrorCode ierr;
1367   SNES           snes;
1368 
1369   PetscFunctionBegin;
1370   ierr = PetscOptionsHead(PetscOptionsObject,"RosW ODE solver options");CHKERRQ(ierr);
1371   {
1372     RosWTableauLink link;
1373     PetscInt        count,choice;
1374     PetscBool       flg;
1375     const char      **namelist;
1376 
1377     for (link=RosWTableauList,count=0; link; link=link->next,count++) ;
1378     ierr = PetscMalloc1(count,(char***)&namelist);CHKERRQ(ierr);
1379     for (link=RosWTableauList,count=0; link; link=link->next,count++) namelist[count] = link->tab.name;
1380     ierr = PetscOptionsEList("-ts_rosw_type","Family of Rosenbrock-W method","TSRosWSetType",(const char*const*)namelist,count,ros->tableau->name,&choice,&flg);CHKERRQ(ierr);
1381     if (flg) {ierr = TSRosWSetType(ts,namelist[choice]);CHKERRQ(ierr);}
1382     ierr = PetscFree(namelist);CHKERRQ(ierr);
1383 
1384     ierr = PetscOptionsBool("-ts_rosw_recompute_jacobian","Recompute the Jacobian at each stage","TSRosWSetRecomputeJacobian",ros->recompute_jacobian,&ros->recompute_jacobian,NULL);CHKERRQ(ierr);
1385   }
1386   ierr = PetscOptionsTail();CHKERRQ(ierr);
1387   /* Rosenbrock methods are linearly implicit, so set that unless the user has specifically asked for something else */
1388   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
1389   if (!((PetscObject)snes)->type_name) {
1390     ierr = SNESSetType(snes,SNESKSPONLY);CHKERRQ(ierr);
1391   }
1392   PetscFunctionReturn(0);
1393 }
1394 
1395 static PetscErrorCode PetscFormatRealArray(char buf[],size_t len,const char *fmt,PetscInt n,const PetscReal x[])
1396 {
1397   PetscErrorCode ierr;
1398   PetscInt       i;
1399   size_t         left,count;
1400   char           *p;
1401 
1402   PetscFunctionBegin;
1403   for (i=0,p=buf,left=len; i<n; i++) {
1404     ierr = PetscSNPrintfCount(p,left,fmt,&count,(double)x[i]);CHKERRQ(ierr);
1405     if (count >= left) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Insufficient space in buffer");
1406     left -= count;
1407     p    += count;
1408     *p++  = ' ';
1409   }
1410   p[i ? 0 : -1] = 0;
1411   PetscFunctionReturn(0);
1412 }
1413 
1414 static PetscErrorCode TSView_RosW(TS ts,PetscViewer viewer)
1415 {
1416   TS_RosW        *ros = (TS_RosW*)ts->data;
1417   PetscBool      iascii;
1418   PetscErrorCode ierr;
1419 
1420   PetscFunctionBegin;
1421   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
1422   if (iascii) {
1423     RosWTableau tab  = ros->tableau;
1424     TSRosWType  rostype;
1425     char        buf[512];
1426     PetscInt    i;
1427     PetscReal   abscissa[512];
1428     ierr = TSRosWGetType(ts,&rostype);CHKERRQ(ierr);
1429     ierr = PetscViewerASCIIPrintf(viewer,"  Rosenbrock-W %s\n",rostype);CHKERRQ(ierr);
1430     ierr = PetscFormatRealArray(buf,sizeof(buf),"% 8.6f",tab->s,tab->ASum);CHKERRQ(ierr);
1431     ierr = PetscViewerASCIIPrintf(viewer,"  Abscissa of A       = %s\n",buf);CHKERRQ(ierr);
1432     for (i=0; i<tab->s; i++) abscissa[i] = tab->ASum[i] + tab->Gamma[i];
1433     ierr = PetscFormatRealArray(buf,sizeof(buf),"% 8.6f",tab->s,abscissa);CHKERRQ(ierr);
1434     ierr = PetscViewerASCIIPrintf(viewer,"  Abscissa of A+Gamma = %s\n",buf);CHKERRQ(ierr);
1435   }
1436   PetscFunctionReturn(0);
1437 }
1438 
1439 static PetscErrorCode TSLoad_RosW(TS ts,PetscViewer viewer)
1440 {
1441   PetscErrorCode ierr;
1442   SNES           snes;
1443   TSAdapt        adapt;
1444 
1445   PetscFunctionBegin;
1446   ierr = TSGetAdapt(ts,&adapt);CHKERRQ(ierr);
1447   ierr = TSAdaptLoad(adapt,viewer);CHKERRQ(ierr);
1448   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
1449   ierr = SNESLoad(snes,viewer);CHKERRQ(ierr);
1450   /* function and Jacobian context for SNES when used with TS is always ts object */
1451   ierr = SNESSetFunction(snes,NULL,NULL,ts);CHKERRQ(ierr);
1452   ierr = SNESSetJacobian(snes,NULL,NULL,NULL,ts);CHKERRQ(ierr);
1453   PetscFunctionReturn(0);
1454 }
1455 
1456 /*@C
1457   TSRosWSetType - Set the type of Rosenbrock-W scheme
1458 
1459   Logically collective
1460 
1461   Input Parameter:
1462 +  ts - timestepping context
1463 -  roswtype - type of Rosenbrock-W scheme
1464 
1465   Level: beginner
1466 
1467 .seealso: TSRosWGetType(), TSROSW, TSROSW2M, TSROSW2P, TSROSWRA3PW, TSROSWRA34PW2, TSROSWRODAS3, TSROSWSANDU3, TSROSWASSP3P3S1C, TSROSWLASSP3P4S2C, TSROSWLLSSP3P4S2C, TSROSWARK3
1468 @*/
1469 PetscErrorCode TSRosWSetType(TS ts,TSRosWType roswtype)
1470 {
1471   PetscErrorCode ierr;
1472 
1473   PetscFunctionBegin;
1474   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1475   PetscValidCharPointer(roswtype,2);
1476   ierr = PetscTryMethod(ts,"TSRosWSetType_C",(TS,TSRosWType),(ts,roswtype));CHKERRQ(ierr);
1477   PetscFunctionReturn(0);
1478 }
1479 
1480 /*@C
1481   TSRosWGetType - Get the type of Rosenbrock-W scheme
1482 
1483   Logically collective
1484 
1485   Input Parameter:
1486 .  ts - timestepping context
1487 
1488   Output Parameter:
1489 .  rostype - type of Rosenbrock-W scheme
1490 
1491   Level: intermediate
1492 
1493 .seealso: TSRosWGetType()
1494 @*/
1495 PetscErrorCode TSRosWGetType(TS ts,TSRosWType *rostype)
1496 {
1497   PetscErrorCode ierr;
1498 
1499   PetscFunctionBegin;
1500   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1501   ierr = PetscUseMethod(ts,"TSRosWGetType_C",(TS,TSRosWType*),(ts,rostype));CHKERRQ(ierr);
1502   PetscFunctionReturn(0);
1503 }
1504 
1505 /*@C
1506   TSRosWSetRecomputeJacobian - Set whether to recompute the Jacobian at each stage. The default is to update the Jacobian once per step.
1507 
1508   Logically collective
1509 
1510   Input Parameter:
1511 +  ts - timestepping context
1512 -  flg - PETSC_TRUE to recompute the Jacobian at each stage
1513 
1514   Level: intermediate
1515 
1516 .seealso: TSRosWGetType()
1517 @*/
1518 PetscErrorCode TSRosWSetRecomputeJacobian(TS ts,PetscBool flg)
1519 {
1520   PetscErrorCode ierr;
1521 
1522   PetscFunctionBegin;
1523   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1524   ierr = PetscTryMethod(ts,"TSRosWSetRecomputeJacobian_C",(TS,PetscBool),(ts,flg));CHKERRQ(ierr);
1525   PetscFunctionReturn(0);
1526 }
1527 
1528 static PetscErrorCode  TSRosWGetType_RosW(TS ts,TSRosWType *rostype)
1529 {
1530   TS_RosW        *ros = (TS_RosW*)ts->data;
1531 
1532   PetscFunctionBegin;
1533   *rostype = ros->tableau->name;
1534   PetscFunctionReturn(0);
1535 }
1536 
1537 static PetscErrorCode  TSRosWSetType_RosW(TS ts,TSRosWType rostype)
1538 {
1539   TS_RosW         *ros = (TS_RosW*)ts->data;
1540   PetscErrorCode  ierr;
1541   PetscBool       match;
1542   RosWTableauLink link;
1543 
1544   PetscFunctionBegin;
1545   if (ros->tableau) {
1546     ierr = PetscStrcmp(ros->tableau->name,rostype,&match);CHKERRQ(ierr);
1547     if (match) PetscFunctionReturn(0);
1548   }
1549   for (link = RosWTableauList; link; link=link->next) {
1550     ierr = PetscStrcmp(link->tab.name,rostype,&match);CHKERRQ(ierr);
1551     if (match) {
1552       if (ts->setupcalled) {ierr = TSRosWTableauReset(ts);CHKERRQ(ierr);}
1553       ros->tableau = &link->tab;
1554       if (ts->setupcalled) {ierr = TSRosWTableauSetUp(ts);CHKERRQ(ierr);}
1555       ts->default_adapt_type = ros->tableau->bembed ? TSADAPTBASIC : TSADAPTNONE;
1556       PetscFunctionReturn(0);
1557     }
1558   }
1559   SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_UNKNOWN_TYPE,"Could not find '%s'",rostype);
1560   PetscFunctionReturn(0);
1561 }
1562 
1563 static PetscErrorCode  TSRosWSetRecomputeJacobian_RosW(TS ts,PetscBool flg)
1564 {
1565   TS_RosW *ros = (TS_RosW*)ts->data;
1566 
1567   PetscFunctionBegin;
1568   ros->recompute_jacobian = flg;
1569   PetscFunctionReturn(0);
1570 }
1571 
1572 static PetscErrorCode TSDestroy_RosW(TS ts)
1573 {
1574   PetscErrorCode ierr;
1575 
1576   PetscFunctionBegin;
1577   ierr = TSReset_RosW(ts);CHKERRQ(ierr);
1578   if (ts->dm) {
1579     ierr = DMCoarsenHookRemove(ts->dm,DMCoarsenHook_TSRosW,DMRestrictHook_TSRosW,ts);CHKERRQ(ierr);
1580     ierr = DMSubDomainHookRemove(ts->dm,DMSubDomainHook_TSRosW,DMSubDomainRestrictHook_TSRosW,ts);CHKERRQ(ierr);
1581   }
1582   ierr = PetscFree(ts->data);CHKERRQ(ierr);
1583   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSRosWGetType_C",NULL);CHKERRQ(ierr);
1584   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSRosWSetType_C",NULL);CHKERRQ(ierr);
1585   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSRosWSetRecomputeJacobian_C",NULL);CHKERRQ(ierr);
1586   PetscFunctionReturn(0);
1587 }
1588 
1589 /* ------------------------------------------------------------ */
1590 /*MC
1591       TSROSW - ODE solver using Rosenbrock-W schemes
1592 
1593   These methods are intended for problems with well-separated time scales, especially when a slow scale is strongly
1594   nonlinear such that it is expensive to solve with a fully implicit method. The user should provide the stiff part
1595   of the equation using TSSetIFunction() and the non-stiff part with TSSetRHSFunction().
1596 
1597   Notes:
1598   This method currently only works with autonomous ODE and DAE.
1599 
1600   Consider trying TSARKIMEX if the stiff part is strongly nonlinear.
1601 
1602   Developer notes:
1603   Rosenbrock-W methods are typically specified for autonomous ODE
1604 
1605 $  udot = f(u)
1606 
1607   by the stage equations
1608 
1609 $  k_i = h f(u_0 + sum_j alpha_ij k_j) + h J sum_j gamma_ij k_j
1610 
1611   and step completion formula
1612 
1613 $  u_1 = u_0 + sum_j b_j k_j
1614 
1615   with step size h and coefficients alpha_ij, gamma_ij, and b_i. Implementing the method in this form would require f(u)
1616   and the Jacobian J to be available, in addition to the shifted matrix I - h gamma_ii J. Following Hairer and Wanner,
1617   we define new variables for the stage equations
1618 
1619 $  y_i = gamma_ij k_j
1620 
1621   The k_j can be recovered because Gamma is invertible. Let C be the lower triangular part of Gamma^{-1} and define
1622 
1623 $  A = Alpha Gamma^{-1}, bt^T = b^T Gamma^{-1}
1624 
1625   to rewrite the method as
1626 
1627 $  [M/(h gamma_ii) - J] y_i = f(u_0 + sum_j a_ij y_j) + M sum_j (c_ij/h) y_j
1628 $  u_1 = u_0 + sum_j bt_j y_j
1629 
1630    where we have introduced the mass matrix M. Continue by defining
1631 
1632 $  ydot_i = 1/(h gamma_ii) y_i - sum_j (c_ij/h) y_j
1633 
1634    or, more compactly in tensor notation
1635 
1636 $  Ydot = 1/h (Gamma^{-1} \otimes I) Y .
1637 
1638    Note that Gamma^{-1} is lower triangular. With this definition of Ydot in terms of known quantities and the current
1639    stage y_i, the stage equations reduce to performing one Newton step (typically with a lagged Jacobian) on the
1640    equation
1641 
1642 $  g(u_0 + sum_j a_ij y_j + y_i, ydot_i) = 0
1643 
1644    with initial guess y_i = 0.
1645 
1646   Level: beginner
1647 
1648 .seealso:  TSCreate(), TS, TSSetType(), TSRosWSetType(), TSRosWRegister(), TSROSWTHETA1, TSROSWTHETA2, TSROSW2M, TSROSW2P, TSROSWRA3PW, TSROSWRA34PW2, TSROSWRODAS3,
1649            TSROSWSANDU3, TSROSWASSP3P3S1C, TSROSWLASSP3P4S2C, TSROSWLLSSP3P4S2C, TSROSWGRK4T, TSROSWSHAMP4, TSROSWVELDD4, TSROSW4L
1650 M*/
1651 PETSC_EXTERN PetscErrorCode TSCreate_RosW(TS ts)
1652 {
1653   TS_RosW        *ros;
1654   PetscErrorCode ierr;
1655 
1656   PetscFunctionBegin;
1657   ierr = TSRosWInitializePackage();CHKERRQ(ierr);
1658 
1659   ts->ops->reset          = TSReset_RosW;
1660   ts->ops->destroy        = TSDestroy_RosW;
1661   ts->ops->view           = TSView_RosW;
1662   ts->ops->load           = TSLoad_RosW;
1663   ts->ops->setup          = TSSetUp_RosW;
1664   ts->ops->step           = TSStep_RosW;
1665   ts->ops->interpolate    = TSInterpolate_RosW;
1666   ts->ops->evaluatestep   = TSEvaluateStep_RosW;
1667   ts->ops->rollback       = TSRollBack_RosW;
1668   ts->ops->setfromoptions = TSSetFromOptions_RosW;
1669   ts->ops->snesfunction   = SNESTSFormFunction_RosW;
1670   ts->ops->snesjacobian   = SNESTSFormJacobian_RosW;
1671 
1672   ts->usessnes = PETSC_TRUE;
1673 
1674   ierr = PetscNewLog(ts,&ros);CHKERRQ(ierr);
1675   ts->data = (void*)ros;
1676 
1677   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSRosWGetType_C",TSRosWGetType_RosW);CHKERRQ(ierr);
1678   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSRosWSetType_C",TSRosWSetType_RosW);CHKERRQ(ierr);
1679   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSRosWSetRecomputeJacobian_C",TSRosWSetRecomputeJacobian_RosW);CHKERRQ(ierr);
1680 
1681   ierr = TSRosWSetType(ts,TSRosWDefault);CHKERRQ(ierr);
1682   PetscFunctionReturn(0);
1683 }
1684