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