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