xref: /petsc/src/ts/impls/rosw/rosw.c (revision f73f8d2c34b175c91d916331f941e255591e9aaf)
1e27a552bSJed Brown /*
261692a83SJed Brown   Code for timestepping with Rosenbrock W methods
3e27a552bSJed Brown 
4e27a552bSJed Brown   Notes:
5e27a552bSJed Brown   The general system is written as
6e27a552bSJed Brown 
761692a83SJed Brown   G(t,X,Xdot) = F(t,X)
8e27a552bSJed Brown 
961692a83SJed Brown   where G represents the stiff part of the physics and F represents the non-stiff part.
1061692a83SJed Brown   This method is designed to be linearly implicit on G and can use an approximate and lagged Jacobian.
11e27a552bSJed Brown 
12e27a552bSJed Brown */
13e27a552bSJed Brown #include <private/tsimpl.h>                /*I   "petscts.h"   I*/
14e27a552bSJed Brown 
1561692a83SJed Brown #include <../src/mat/blockinvert.h>
1661692a83SJed Brown 
17ae6f9490SJed Brown static const TSRosWType TSRosWDefault = TSROSWRA34PW2;
18e27a552bSJed Brown static PetscBool TSRosWRegisterAllCalled;
19e27a552bSJed Brown static PetscBool TSRosWPackageInitialized;
20e27a552bSJed Brown 
2161692a83SJed Brown typedef struct _RosWTableau *RosWTableau;
2261692a83SJed Brown struct _RosWTableau {
23e27a552bSJed Brown   char      *name;
24e27a552bSJed Brown   PetscInt  order;              /* Classical approximation order of the method */
25e27a552bSJed Brown   PetscInt  s;                  /* Number of stages */
26f4aed992SEmil Constantinescu   PetscInt  pinterp;            /* Interpolation order */
2761692a83SJed Brown   PetscReal *A;                 /* Propagation table, strictly lower triangular */
2861692a83SJed Brown   PetscReal *Gamma;             /* Stage table, lower triangular with nonzero diagonal */
29c17803e7SJed Brown   PetscBool *GammaZeroDiag;     /* Diagonal entries that are zero in stage table Gamma, vector indicating explicit statages */
3043b21953SEmil Constantinescu   PetscReal *GammaExplicitCorr; /* Coefficients for correction terms needed for explicit stages in transformed variables*/
3161692a83SJed Brown   PetscReal *b;                 /* Step completion table */
32fe7e6d57SJed Brown   PetscReal *bembed;            /* Step completion table for embedded method of order one less */
3361692a83SJed Brown   PetscReal *ASum;              /* Row sum of A */
3461692a83SJed Brown   PetscReal *GammaSum;          /* Row sum of Gamma, only needed for non-autonomous systems */
3561692a83SJed Brown   PetscReal *At;                /* Propagation table in transformed variables */
3661692a83SJed Brown   PetscReal *bt;                /* Step completion table in transformed variables */
37fe7e6d57SJed Brown   PetscReal *bembedt;           /* Step completion table of order one less in transformed variables */
3861692a83SJed Brown   PetscReal *GammaInv;          /* Inverse of Gamma, used for transformed variables */
398d59e960SJed Brown   PetscReal ccfl;               /* Placeholder for CFL coefficient relative to forward Euler */
40f4aed992SEmil Constantinescu   PetscReal *binterpt,*binterp; /* Dense output formula */
41e27a552bSJed Brown };
4261692a83SJed Brown typedef struct _RosWTableauLink *RosWTableauLink;
4361692a83SJed Brown struct _RosWTableauLink {
4461692a83SJed Brown   struct _RosWTableau tab;
4561692a83SJed Brown   RosWTableauLink next;
46e27a552bSJed Brown };
4761692a83SJed Brown static RosWTableauLink RosWTableauList;
48e27a552bSJed Brown 
49e27a552bSJed Brown typedef struct {
5061692a83SJed Brown   RosWTableau tableau;
5161692a83SJed Brown   Vec         *Y;               /* States computed during the step, used to complete the step */
52e27a552bSJed Brown   Vec         Ydot;             /* Work vector holding Ydot during residual evaluation */
5361692a83SJed Brown   Vec         Ystage;           /* Work vector for the state value at each stage */
5461692a83SJed Brown   Vec         Zdot;             /* Ydot = Zdot + shift*Y */
5561692a83SJed Brown   Vec         Zstage;           /* Y = Zstage + Y */
561c3436cfSJed Brown   PetscScalar *work;            /* Scalar work space of length number of stages, used to prepare VecMAXPY() */
57e27a552bSJed Brown   PetscReal   shift;
58e27a552bSJed Brown   PetscReal   stage_time;
59c17803e7SJed Brown   PetscReal   stage_explicit;     /* Flag indicates that the current stage is explicit */
6061692a83SJed Brown   PetscBool   recompute_jacobian; /* Recompute the Jacobian at each stage, default is to freeze the Jacobian at the start of each step */
61108c343cSJed Brown   TSStepStatus status;
62e27a552bSJed Brown } TS_RosW;
63e27a552bSJed Brown 
64fe7e6d57SJed Brown /*MC
653606a31eSEmil Constantinescu      TSROSWTHETA1 - One stage first order L-stable Rosenbrock-W scheme (aka theta method).
663606a31eSEmil Constantinescu 
673606a31eSEmil Constantinescu      Only an approximate Jacobian is needed.
683606a31eSEmil Constantinescu 
693606a31eSEmil Constantinescu      Level: intermediate
703606a31eSEmil Constantinescu 
713606a31eSEmil Constantinescu .seealso: TSROSW
723606a31eSEmil Constantinescu M*/
733606a31eSEmil Constantinescu 
743606a31eSEmil Constantinescu /*MC
753606a31eSEmil Constantinescu      TSROSWTHETA2 - One stage second order A-stable Rosenbrock-W scheme (aka theta method).
763606a31eSEmil Constantinescu 
773606a31eSEmil Constantinescu      Only an approximate Jacobian is needed.
783606a31eSEmil Constantinescu 
793606a31eSEmil Constantinescu      Level: intermediate
803606a31eSEmil Constantinescu 
813606a31eSEmil Constantinescu .seealso: TSROSW
823606a31eSEmil Constantinescu M*/
833606a31eSEmil Constantinescu 
843606a31eSEmil Constantinescu /*MC
85fe7e6d57SJed Brown      TSROSW2M - Two stage second order L-stable Rosenbrock-W scheme.
86fe7e6d57SJed Brown 
87fe7e6d57SJed Brown      Only an approximate Jacobian is needed. By default, it is only recomputed once per step. This method is a reflection of TSROSW2P.
88fe7e6d57SJed Brown 
89fe7e6d57SJed Brown      Level: intermediate
90fe7e6d57SJed Brown 
91fe7e6d57SJed Brown .seealso: TSROSW
92fe7e6d57SJed Brown M*/
93fe7e6d57SJed Brown 
94fe7e6d57SJed Brown /*MC
95fe7e6d57SJed Brown      TSROSW2P - Two stage second order L-stable Rosenbrock-W scheme.
96fe7e6d57SJed Brown 
97fe7e6d57SJed Brown      Only an approximate Jacobian is needed. By default, it is only recomputed once per step. This method is a reflection of TSROSW2M.
98fe7e6d57SJed Brown 
99fe7e6d57SJed Brown      Level: intermediate
100fe7e6d57SJed Brown 
101fe7e6d57SJed Brown .seealso: TSROSW
102fe7e6d57SJed Brown M*/
103fe7e6d57SJed Brown 
104fe7e6d57SJed Brown /*MC
105fe7e6d57SJed Brown      TSROSWRA3PW - Three stage third order Rosenbrock-W scheme for PDAE of index 1.
106fe7e6d57SJed Brown 
107fe7e6d57SJed Brown      Only an approximate Jacobian is needed. By default, it is only recomputed once per step.
108fe7e6d57SJed Brown 
109fe7e6d57SJed Brown      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.
110fe7e6d57SJed Brown 
111fe7e6d57SJed Brown      References:
112fe7e6d57SJed Brown      Rang and Angermann, New Rosenbrock-W methods of order 3 for partial differential algebraic equations of index 1, 2005.
113fe7e6d57SJed Brown 
114fe7e6d57SJed Brown      Level: intermediate
115fe7e6d57SJed Brown 
116fe7e6d57SJed Brown .seealso: TSROSW
117fe7e6d57SJed Brown M*/
118fe7e6d57SJed Brown 
119fe7e6d57SJed Brown /*MC
120fe7e6d57SJed Brown      TSROSWRA34PW2 - Four stage third order L-stable Rosenbrock-W scheme for PDAE of index 1.
121fe7e6d57SJed Brown 
122fe7e6d57SJed Brown      Only an approximate Jacobian is needed. By default, it is only recomputed once per step.
123fe7e6d57SJed Brown 
124fe7e6d57SJed Brown      This is strongly A-stable with R(infty) = 0. The embedded method of order 2 is strongly A-stable with R(infty) = 0.48.
125fe7e6d57SJed Brown 
126fe7e6d57SJed Brown      References:
127fe7e6d57SJed Brown      Rang and Angermann, New Rosenbrock-W methods of order 3 for partial differential algebraic equations of index 1, 2005.
128fe7e6d57SJed Brown 
129fe7e6d57SJed Brown      Level: intermediate
130fe7e6d57SJed Brown 
131fe7e6d57SJed Brown .seealso: TSROSW
132fe7e6d57SJed Brown M*/
133fe7e6d57SJed Brown 
134ef3c5b88SJed Brown /*MC
135ef3c5b88SJed Brown      TSROSWRODAS3 - Four stage third order L-stable Rosenbrock scheme
136ef3c5b88SJed Brown 
137ef3c5b88SJed Brown      By default, the Jacobian is only recomputed once per step.
138ef3c5b88SJed Brown 
139ef3c5b88SJed Brown      Both the third order and embedded second order methods are stiffly accurate and L-stable.
140ef3c5b88SJed Brown 
141ef3c5b88SJed Brown      References:
142ef3c5b88SJed Brown      Sandu et al, Benchmarking stiff ODE solvers for atmospheric chemistry problems II, Rosenbrock solvers, 1997.
143ef3c5b88SJed Brown 
144ef3c5b88SJed Brown      Level: intermediate
145ef3c5b88SJed Brown 
146ef3c5b88SJed Brown .seealso: TSROSW, TSROSWSANDU3
147ef3c5b88SJed Brown M*/
148ef3c5b88SJed Brown 
149ef3c5b88SJed Brown /*MC
150ef3c5b88SJed Brown      TSROSWSANDU3 - Three stage third order L-stable Rosenbrock scheme
151ef3c5b88SJed Brown 
152ef3c5b88SJed Brown      By default, the Jacobian is only recomputed once per step.
153ef3c5b88SJed Brown 
154ef3c5b88SJed Brown      The third order method is L-stable, but not stiffly accurate.
155ef3c5b88SJed Brown      The second order embedded method is strongly A-stable with R(infty) = 0.5.
156ef3c5b88SJed Brown      The internal stages are L-stable.
157ef3c5b88SJed Brown      This method is called ROS3 in the paper.
158ef3c5b88SJed Brown 
159ef3c5b88SJed Brown      References:
160ef3c5b88SJed Brown      Sandu et al, Benchmarking stiff ODE solvers for atmospheric chemistry problems II, Rosenbrock solvers, 1997.
161ef3c5b88SJed Brown 
162ef3c5b88SJed Brown      Level: intermediate
163ef3c5b88SJed Brown 
164ef3c5b88SJed Brown .seealso: TSROSW, TSROSWRODAS3
165ef3c5b88SJed Brown M*/
166ef3c5b88SJed Brown 
167961f28d0SJed Brown /*MC
168961f28d0SJed Brown      TSROSWASSP3P3S1C - A-stable Rosenbrock-W method with SSP explicit part, third order, three stages
169961f28d0SJed Brown 
170961f28d0SJed Brown      By default, the Jacobian is only recomputed once per step.
171961f28d0SJed Brown 
172961f28d0SJed Brown      A-stable SPP explicit order 3, 3 stages, CFL 1 (eff = 1/3)
173961f28d0SJed Brown 
174961f28d0SJed Brown      References:
175961f28d0SJed Brown      Emil Constantinescu
176961f28d0SJed Brown 
177961f28d0SJed Brown      Level: intermediate
178961f28d0SJed Brown 
17943b21953SEmil Constantinescu .seealso: TSROSW, TSROSWLASSP3P4S2C, TSROSWLLSSP3P4S2C, SSP
180961f28d0SJed Brown M*/
181961f28d0SJed Brown 
182961f28d0SJed Brown /*MC
183961f28d0SJed Brown      TSROSWLASSP3P4S2C - L-stable Rosenbrock-W method with SSP explicit part, third order, three stages
184961f28d0SJed Brown 
185961f28d0SJed Brown      By default, the Jacobian is only recomputed once per step.
186961f28d0SJed Brown 
187961f28d0SJed Brown      L-stable (A-stable embedded) SPP explicit order 3, 4 stages, CFL 2 (eff = 1/2)
188961f28d0SJed Brown 
189961f28d0SJed Brown      References:
190961f28d0SJed Brown      Emil Constantinescu
191961f28d0SJed Brown 
192961f28d0SJed Brown      Level: intermediate
193961f28d0SJed Brown 
19443b21953SEmil Constantinescu .seealso: TSROSW, TSROSWASSP3P3S1C, TSROSWLLSSP3P4S2C, TSSSP
195961f28d0SJed Brown M*/
196961f28d0SJed Brown 
197961f28d0SJed Brown /*MC
19843b21953SEmil Constantinescu      TSROSWLLSSP3P4S2C - L-stable Rosenbrock-W method with SSP explicit part, third order, three stages
199961f28d0SJed Brown 
200961f28d0SJed Brown      By default, the Jacobian is only recomputed once per step.
201961f28d0SJed Brown 
202961f28d0SJed Brown      L-stable (L-stable embedded) SPP explicit order 3, 4 stages, CFL 2 (eff = 1/2)
203961f28d0SJed Brown 
204961f28d0SJed Brown      References:
205961f28d0SJed Brown      Emil Constantinescu
206961f28d0SJed Brown 
207961f28d0SJed Brown      Level: intermediate
208961f28d0SJed Brown 
209961f28d0SJed Brown .seealso: TSROSW, TSROSWASSP3P3S1C, TSROSWLASSP3P4S2C, TSSSP
210961f28d0SJed Brown M*/
211961f28d0SJed Brown 
212e27a552bSJed Brown #undef __FUNCT__
213e27a552bSJed Brown #define __FUNCT__ "TSRosWRegisterAll"
214e27a552bSJed Brown /*@C
215e27a552bSJed Brown   TSRosWRegisterAll - Registers all of the additive Runge-Kutta implicit-explicit methods in TSRosW
216e27a552bSJed Brown 
217e27a552bSJed Brown   Not Collective, but should be called by all processes which will need the schemes to be registered
218e27a552bSJed Brown 
219e27a552bSJed Brown   Level: advanced
220e27a552bSJed Brown 
221e27a552bSJed Brown .keywords: TS, TSRosW, register, all
222e27a552bSJed Brown 
223e27a552bSJed Brown .seealso:  TSRosWRegisterDestroy()
224e27a552bSJed Brown @*/
225e27a552bSJed Brown PetscErrorCode TSRosWRegisterAll(void)
226e27a552bSJed Brown {
227e27a552bSJed Brown   PetscErrorCode ierr;
228e27a552bSJed Brown 
229e27a552bSJed Brown   PetscFunctionBegin;
230e27a552bSJed Brown   if (TSRosWRegisterAllCalled) PetscFunctionReturn(0);
231e27a552bSJed Brown   TSRosWRegisterAllCalled = PETSC_TRUE;
232e27a552bSJed Brown 
233e27a552bSJed Brown   {
2343606a31eSEmil Constantinescu     const PetscReal
2353606a31eSEmil Constantinescu       A = 0,
2363606a31eSEmil Constantinescu       Gamma = 1,
2373606a31eSEmil Constantinescu       b = 1;
238f4aed992SEmil Constantinescu     ierr = TSRosWRegister(TSROSWTHETA1,1,1,&A,&Gamma,&b,PETSC_NULL,0,PETSC_NULL);CHKERRQ(ierr);
2393606a31eSEmil Constantinescu   }
2403606a31eSEmil Constantinescu 
2413606a31eSEmil Constantinescu   {
2423606a31eSEmil Constantinescu     const PetscReal
2433606a31eSEmil Constantinescu       A= 0,
2443606a31eSEmil Constantinescu       Gamma = 0.5,
2453606a31eSEmil Constantinescu       b = 1;
246f4aed992SEmil Constantinescu     ierr = TSRosWRegister(TSROSWTHETA2,2,1,&A,&Gamma,&b,PETSC_NULL,0,PETSC_NULL);CHKERRQ(ierr);
2473606a31eSEmil Constantinescu   }
2483606a31eSEmil Constantinescu 
2493606a31eSEmil Constantinescu   {
25061692a83SJed Brown     const PetscReal g = 1. + 1./PetscSqrtReal(2.0);
251e27a552bSJed Brown     const PetscReal
25261692a83SJed Brown       A[2][2] = {{0,0}, {1.,0}},
25361692a83SJed Brown       Gamma[2][2] = {{g,0}, {-2.*g,g}},
2541c3436cfSJed Brown       b[2] = {0.5,0.5},
2551c3436cfSJed Brown       b1[2] = {1.0,0.0};
256f4aed992SEmil Constantinescu     ierr = TSRosWRegister(TSROSW2P,2,2,&A[0][0],&Gamma[0][0],b,b1,0,PETSC_NULL);CHKERRQ(ierr);
257e27a552bSJed Brown   }
258e27a552bSJed Brown   {
25961692a83SJed Brown     const PetscReal g = 1. - 1./PetscSqrtReal(2.0);
260e27a552bSJed Brown     const PetscReal
26161692a83SJed Brown       A[2][2] = {{0,0}, {1.,0}},
26261692a83SJed Brown       Gamma[2][2] = {{g,0}, {-2.*g,g}},
2631c3436cfSJed Brown       b[2] = {0.5,0.5},
2641c3436cfSJed Brown       b1[2] = {1.0,0.0};
265f4aed992SEmil Constantinescu     ierr = TSRosWRegister(TSROSW2M,2,2,&A[0][0],&Gamma[0][0],b,b1,0,PETSC_NULL);CHKERRQ(ierr);
266fe7e6d57SJed Brown   }
267fe7e6d57SJed Brown   {
268fe7e6d57SJed Brown     const PetscReal g = 7.8867513459481287e-01;
269fe7e6d57SJed Brown     const PetscReal
270fe7e6d57SJed Brown       A[3][3] = {{0,0,0},
271fe7e6d57SJed Brown                  {1.5773502691896257e+00,0,0},
272fe7e6d57SJed Brown                  {0.5,0,0}},
273fe7e6d57SJed Brown       Gamma[3][3] = {{g,0,0},
274fe7e6d57SJed Brown                      {-1.5773502691896257e+00,g,0},
27525833a80SEmil Constantinescu                      {-6.7075317547305480e-01,-1.7075317547305482e-01,g}},
276fe7e6d57SJed Brown       b[3] = {1.0566243270259355e-01,4.9038105676657971e-02,8.4529946162074843e-01},
277fe7e6d57SJed Brown       b2[3] = {-1.7863279495408180e-01,1./3.,8.4529946162074843e-01};
278f4aed992SEmil Constantinescu     ierr = TSRosWRegister(TSROSWRA3PW,3,3,&A[0][0],&Gamma[0][0],b,b2,0,PETSC_NULL);CHKERRQ(ierr);
279fe7e6d57SJed Brown   }
280fe7e6d57SJed Brown   {
281fe7e6d57SJed Brown     const PetscReal g = 4.3586652150845900e-01;
282fe7e6d57SJed Brown     const PetscReal
283fe7e6d57SJed Brown       A[4][4] = {{0,0,0,0},
284fe7e6d57SJed Brown                  {8.7173304301691801e-01,0,0,0},
285fe7e6d57SJed Brown                  {8.4457060015369423e-01,-1.1299064236484185e-01,0,0},
286fe7e6d57SJed Brown                  {0,0,1.,0}},
287fe7e6d57SJed Brown       Gamma[4][4] = {{g,0,0,0},
288fe7e6d57SJed Brown                      {-8.7173304301691801e-01,g,0,0},
289fe7e6d57SJed Brown                      {-9.0338057013044082e-01,5.4180672388095326e-02,g,0},
290fe7e6d57SJed Brown                      {2.4212380706095346e-01,-1.2232505839045147e+00,5.4526025533510214e-01,g}},
291fe7e6d57SJed Brown         b[4] = {2.4212380706095346e-01,-1.2232505839045147e+00,1.5452602553351020e+00,4.3586652150845900e-01},
292f4aed992SEmil Constantinescu           b2[4] = {3.7810903145819369e-01,-9.6042292212423178e-02,5.0000000000000000e-01,2.1793326075422950e-01},
293f4aed992SEmil Constantinescu             binterpt[4][3]={{1.0564298455794094,-1.3864882699759573,0.5721822314575016},{2.296429974281067,-8.262611700275677,4.742931142090097},{-1.307599564525376,7.250979895056055,-4.398120075195578},{-1.045260255335102,2.398120075195581,-0.9169932983520199}};
294f4aed992SEmil Constantinescu       ierr = TSRosWRegister(TSROSWRA34PW2,3,4,&A[0][0],&Gamma[0][0],b,b2,3,binterpt[0]);CHKERRQ(ierr);
295e27a552bSJed Brown   }
296ef3c5b88SJed Brown   {
297ef3c5b88SJed Brown     const PetscReal g = 0.5;
298ef3c5b88SJed Brown     const PetscReal
299ef3c5b88SJed Brown       A[4][4] = {{0,0,0,0},
300ef3c5b88SJed Brown                  {0,0,0,0},
301ef3c5b88SJed Brown                  {1.,0,0,0},
302ef3c5b88SJed Brown                  {0.75,-0.25,0.5,0}},
303ef3c5b88SJed Brown       Gamma[4][4] = {{g,0,0,0},
304ef3c5b88SJed Brown                      {1.,g,0,0},
305ef3c5b88SJed Brown                      {-0.25,-0.25,g,0},
306ef3c5b88SJed Brown                      {1./12,1./12,-2./3,g}},
307ef3c5b88SJed Brown       b[4] = {5./6,-1./6,-1./6,0.5},
308ef3c5b88SJed Brown       b2[4] = {0.75,-0.25,0.5,0};
309f4aed992SEmil Constantinescu     ierr = TSRosWRegister(TSROSWRODAS3,3,4,&A[0][0],&Gamma[0][0],b,b2,0,PETSC_NULL);CHKERRQ(ierr);
310ef3c5b88SJed Brown   }
311ef3c5b88SJed Brown   {
312ef3c5b88SJed Brown     const PetscReal g = 0.43586652150845899941601945119356;
313ef3c5b88SJed Brown     const PetscReal
314ef3c5b88SJed Brown       A[3][3] = {{0,0,0},
315ef3c5b88SJed Brown                  {g,0,0},
316ef3c5b88SJed Brown                  {g,0,0}},
317ef3c5b88SJed Brown       Gamma[3][3] = {{g,0,0},
318ef3c5b88SJed Brown                      {-0.19294655696029095575009695436041,g,0},
319ef3c5b88SJed Brown                      {0,1.74927148125794685173529749738960,g}},
320ef3c5b88SJed Brown       b[3] = {-0.75457412385404315829818998646589,1.94100407061964420292840123379419,-0.18642994676560104463021124732829},
321ef3c5b88SJed Brown       b2[3] = {-1.53358745784149585370766523913002,2.81745131148625772213931745457622,-0.28386385364476186843165221544619};
322f4aed992SEmil Constantinescu     ierr = TSRosWRegister(TSROSWSANDU3,3,3,&A[0][0],&Gamma[0][0],b,b2,0,PETSC_NULL);CHKERRQ(ierr);
323ef3c5b88SJed Brown   }
324b1c69cc3SEmil Constantinescu   {
325aaf9cf16SJed Brown     const PetscReal s3 = PetscSqrtReal(3.),g = (3.0+s3)/6.0;
326b1c69cc3SEmil Constantinescu     const PetscReal
327b1c69cc3SEmil Constantinescu       A[3][3] = {{0,0,0},
328b1c69cc3SEmil Constantinescu                  {1,0,0},
329b1c69cc3SEmil Constantinescu                  {0.25,0.25,0}},
330b1c69cc3SEmil Constantinescu       Gamma[3][3] = {{0,0,0},
331aaf9cf16SJed Brown                      {(-3.0-s3)/6.0,g,0},
332aaf9cf16SJed Brown                      {(-3.0-s3)/24.0,(-3.0-s3)/8.0,g}},
333b1c69cc3SEmil Constantinescu         b[3] = {1./6.,1./6.,2./3.},
334b1c69cc3SEmil Constantinescu           b2[3] = {1./4.,1./4.,1./2.};
335f4aed992SEmil Constantinescu     ierr = TSRosWRegister(TSROSWASSP3P3S1C,3,3,&A[0][0],&Gamma[0][0],b,b2,0,PETSC_NULL);CHKERRQ(ierr);
336b1c69cc3SEmil Constantinescu   }
337b1c69cc3SEmil Constantinescu 
338b1c69cc3SEmil Constantinescu   {
339b1c69cc3SEmil Constantinescu     const PetscReal
340b1c69cc3SEmil Constantinescu       A[4][4] = {{0,0,0,0},
341b1c69cc3SEmil Constantinescu                  {1./2.,0,0,0},
342b1c69cc3SEmil Constantinescu                  {1./2.,1./2.,0,0},
343b1c69cc3SEmil Constantinescu                  {1./6.,1./6.,1./6.,0}},
344b1c69cc3SEmil Constantinescu       Gamma[4][4] = {{1./2.,0,0,0},
345b1c69cc3SEmil Constantinescu                      {0.0,1./4.,0,0},
346b1c69cc3SEmil Constantinescu                      {-2.,-2./3.,2./3.,0},
347b1c69cc3SEmil Constantinescu                      {1./2.,5./36.,-2./9,0}},
348b1c69cc3SEmil Constantinescu         b[4] = {1./6.,1./6.,1./6.,1./2.},
349b1c69cc3SEmil Constantinescu         b2[4] = {1./8.,3./4.,1./8.,0};
350f4aed992SEmil Constantinescu      ierr = TSRosWRegister(TSROSWLASSP3P4S2C,3,4,&A[0][0],&Gamma[0][0],b,b2,0,PETSC_NULL);CHKERRQ(ierr);
351b1c69cc3SEmil Constantinescu   }
352b1c69cc3SEmil Constantinescu 
353b1c69cc3SEmil Constantinescu   {
354b1c69cc3SEmil Constantinescu     const PetscReal
355b1c69cc3SEmil Constantinescu       A[4][4] = {{0,0,0,0},
356b1c69cc3SEmil Constantinescu                  {1./2.,0,0,0},
357b1c69cc3SEmil Constantinescu                  {1./2.,1./2.,0,0},
358b1c69cc3SEmil Constantinescu                  {1./6.,1./6.,1./6.,0}},
359b1c69cc3SEmil Constantinescu       Gamma[4][4] = {{1./2.,0,0,0},
360b1c69cc3SEmil Constantinescu                      {0.0,3./4.,0,0},
361b1c69cc3SEmil Constantinescu                      {-2./3.,-23./9.,2./9.,0},
362b1c69cc3SEmil Constantinescu                      {1./18.,65./108.,-2./27,0}},
363b1c69cc3SEmil Constantinescu         b[4] = {1./6.,1./6.,1./6.,1./2.},
364b1c69cc3SEmil Constantinescu         b2[4] = {3./16.,10./16.,3./16.,0};
365f4aed992SEmil Constantinescu      ierr = TSRosWRegister(TSROSWLLSSP3P4S2C,3,4,&A[0][0],&Gamma[0][0],b,b2,0,PETSC_NULL);CHKERRQ(ierr);
366b1c69cc3SEmil Constantinescu   }
367753f8adbSEmil Constantinescu 
368753f8adbSEmil Constantinescu  {
369753f8adbSEmil Constantinescu    PetscReal A[4][4],Gamma[4][4],b[4],b2[4];
370753f8adbSEmil Constantinescu 
371753f8adbSEmil Constantinescu    Gamma[0][0]=0.4358665215084589994160194475295062513822671686978816;
37205e8e825SJed Brown    Gamma[0][1]=0; Gamma[0][2]=0; Gamma[0][3]=0;
373753f8adbSEmil Constantinescu    Gamma[1][0]=-1.997527830934941248426324674704153457289527280554476;
374753f8adbSEmil Constantinescu    Gamma[1][1]=0.4358665215084589994160194475295062513822671686978816;
37505e8e825SJed Brown    Gamma[1][2]=0; Gamma[1][3]=0;
376753f8adbSEmil Constantinescu    Gamma[2][0]=-1.007948511795029620852002345345404191008352770119903;
377753f8adbSEmil Constantinescu    Gamma[2][1]=-0.004648958462629345562774289390054679806993396798458131;
378753f8adbSEmil Constantinescu    Gamma[2][2]=0.4358665215084589994160194475295062513822671686978816;
37905e8e825SJed Brown    Gamma[2][3]=0;
380753f8adbSEmil Constantinescu    Gamma[3][0]=-0.6685429734233467180451604600279552604364311322650783;
381753f8adbSEmil Constantinescu    Gamma[3][1]=0.6056625986449338476089525334450053439525178740492984;
382753f8adbSEmil Constantinescu    Gamma[3][2]=-0.9717899277217721234705114616271378792182450260943198;
383753f8adbSEmil Constantinescu    Gamma[3][3]=0;
384753f8adbSEmil Constantinescu 
38505e8e825SJed Brown    A[0][0]=0; A[0][1]=0; A[0][2]=0; A[0][3]=0;
386753f8adbSEmil Constantinescu    A[1][0]=0.8717330430169179988320388950590125027645343373957631;
38705e8e825SJed Brown    A[1][1]=0; A[1][2]=0; A[1][3]=0;
388753f8adbSEmil Constantinescu    A[2][0]=0.5275890119763004115618079766722914408876108660811028;
389753f8adbSEmil Constantinescu    A[2][1]=0.07241098802369958843819203208518599088698057726988732;
39005e8e825SJed Brown    A[2][2]=0; A[2][3]=0;
391753f8adbSEmil Constantinescu    A[3][0]=0.3990960076760701320627260685975778145384666450351314;
392753f8adbSEmil Constantinescu    A[3][1]=-0.4375576546135194437228463747348862825846903771419953;
393753f8adbSEmil Constantinescu    A[3][2]=1.038461646937449311660120300601880176655352737312713;
39405e8e825SJed Brown    A[3][3]=0;
395753f8adbSEmil Constantinescu 
396753f8adbSEmil Constantinescu    b[0]=0.1876410243467238251612921333138006734899663569186926;
397753f8adbSEmil Constantinescu    b[1]=-0.5952974735769549480478230473706443582188442040780541;
398753f8adbSEmil Constantinescu    b[2]=0.9717899277217721234705114616271378792182450260943198;
399753f8adbSEmil Constantinescu    b[3]=0.4358665215084589994160194475295062513822671686978816;
400753f8adbSEmil Constantinescu 
401753f8adbSEmil Constantinescu    b2[0]=0.2147402862233891404862383521089097657790734483804460;
402753f8adbSEmil Constantinescu    b2[1]=-0.4851622638849390928209050538171743017757490232519684;
403753f8adbSEmil Constantinescu    b2[2]=0.8687250025203875511662123688667549217531982787600080;
404753f8adbSEmil Constantinescu    b2[3]=0.4016969751411624011684543450940068201770721128357014;
405753f8adbSEmil Constantinescu 
406f4aed992SEmil Constantinescu    PetscReal binterpt[4][3]={{2.2565812720167954547104627844105,-3.0826699111559187902922463354557,1.0137296634858471607430756831148},{1.349166413351089573796243820819,-2.4689115685996042534544925650515,0.52444768167155973161042570784064},{-2.4695174540533503758652847586647,5.7428279814696677152129332773553,-2.3015205996945452158771370439586},{-0.13623023131453465264142184656474,-0.19124650171414467146619437684812,0.76334325453713832352363565300308}};
407f4aed992SEmil Constantinescu 
408*f73f8d2cSSatish Balay    ierr = TSRosWRegister(TSROSWARK3,3,4,&A[0][0],&Gamma[0][0],b,b2,3,&binterpt[0][0]);CHKERRQ(ierr);
409753f8adbSEmil Constantinescu   }
410753f8adbSEmil Constantinescu 
411e27a552bSJed Brown   PetscFunctionReturn(0);
412e27a552bSJed Brown }
413e27a552bSJed Brown 
414e27a552bSJed Brown #undef __FUNCT__
415e27a552bSJed Brown #define __FUNCT__ "TSRosWRegisterDestroy"
416e27a552bSJed Brown /*@C
417e27a552bSJed Brown    TSRosWRegisterDestroy - Frees the list of schemes that were registered by TSRosWRegister().
418e27a552bSJed Brown 
419e27a552bSJed Brown    Not Collective
420e27a552bSJed Brown 
421e27a552bSJed Brown    Level: advanced
422e27a552bSJed Brown 
423e27a552bSJed Brown .keywords: TSRosW, register, destroy
424e27a552bSJed Brown .seealso: TSRosWRegister(), TSRosWRegisterAll(), TSRosWRegisterDynamic()
425e27a552bSJed Brown @*/
426e27a552bSJed Brown PetscErrorCode TSRosWRegisterDestroy(void)
427e27a552bSJed Brown {
428e27a552bSJed Brown   PetscErrorCode ierr;
42961692a83SJed Brown   RosWTableauLink link;
430e27a552bSJed Brown 
431e27a552bSJed Brown   PetscFunctionBegin;
43261692a83SJed Brown   while ((link = RosWTableauList)) {
43361692a83SJed Brown     RosWTableau t = &link->tab;
43461692a83SJed Brown     RosWTableauList = link->next;
43561692a83SJed Brown     ierr = PetscFree5(t->A,t->Gamma,t->b,t->ASum,t->GammaSum);CHKERRQ(ierr);
43643b21953SEmil Constantinescu     ierr = PetscFree5(t->At,t->bt,t->GammaInv,t->GammaZeroDiag,t->GammaExplicitCorr);CHKERRQ(ierr);
437fe7e6d57SJed Brown     ierr = PetscFree2(t->bembed,t->bembedt);CHKERRQ(ierr);
438f4aed992SEmil Constantinescu     ierr = PetscFree(t->binterpt);CHKERRQ(ierr);
439e27a552bSJed Brown     ierr = PetscFree(t->name);CHKERRQ(ierr);
440e27a552bSJed Brown     ierr = PetscFree(link);CHKERRQ(ierr);
441e27a552bSJed Brown   }
442e27a552bSJed Brown   TSRosWRegisterAllCalled = PETSC_FALSE;
443e27a552bSJed Brown   PetscFunctionReturn(0);
444e27a552bSJed Brown }
445e27a552bSJed Brown 
446e27a552bSJed Brown #undef __FUNCT__
447e27a552bSJed Brown #define __FUNCT__ "TSRosWInitializePackage"
448e27a552bSJed Brown /*@C
449e27a552bSJed Brown   TSRosWInitializePackage - This function initializes everything in the TSRosW package. It is called
450e27a552bSJed Brown   from PetscDLLibraryRegister() when using dynamic libraries, and on the first call to TSCreate_RosW()
451e27a552bSJed Brown   when using static libraries.
452e27a552bSJed Brown 
453e27a552bSJed Brown   Input Parameter:
454e27a552bSJed Brown   path - The dynamic library path, or PETSC_NULL
455e27a552bSJed Brown 
456e27a552bSJed Brown   Level: developer
457e27a552bSJed Brown 
458e27a552bSJed Brown .keywords: TS, TSRosW, initialize, package
459e27a552bSJed Brown .seealso: PetscInitialize()
460e27a552bSJed Brown @*/
461e27a552bSJed Brown PetscErrorCode TSRosWInitializePackage(const char path[])
462e27a552bSJed Brown {
463e27a552bSJed Brown   PetscErrorCode ierr;
464e27a552bSJed Brown 
465e27a552bSJed Brown   PetscFunctionBegin;
466e27a552bSJed Brown   if (TSRosWPackageInitialized) PetscFunctionReturn(0);
467e27a552bSJed Brown   TSRosWPackageInitialized = PETSC_TRUE;
468e27a552bSJed Brown   ierr = TSRosWRegisterAll();CHKERRQ(ierr);
469e27a552bSJed Brown   ierr = PetscRegisterFinalize(TSRosWFinalizePackage);CHKERRQ(ierr);
470e27a552bSJed Brown   PetscFunctionReturn(0);
471e27a552bSJed Brown }
472e27a552bSJed Brown 
473e27a552bSJed Brown #undef __FUNCT__
474e27a552bSJed Brown #define __FUNCT__ "TSRosWFinalizePackage"
475e27a552bSJed Brown /*@C
476e27a552bSJed Brown   TSRosWFinalizePackage - This function destroys everything in the TSRosW package. It is
477e27a552bSJed Brown   called from PetscFinalize().
478e27a552bSJed Brown 
479e27a552bSJed Brown   Level: developer
480e27a552bSJed Brown 
481e27a552bSJed Brown .keywords: Petsc, destroy, package
482e27a552bSJed Brown .seealso: PetscFinalize()
483e27a552bSJed Brown @*/
484e27a552bSJed Brown PetscErrorCode TSRosWFinalizePackage(void)
485e27a552bSJed Brown {
486e27a552bSJed Brown   PetscErrorCode ierr;
487e27a552bSJed Brown 
488e27a552bSJed Brown   PetscFunctionBegin;
489e27a552bSJed Brown   TSRosWPackageInitialized = PETSC_FALSE;
490e27a552bSJed Brown   ierr = TSRosWRegisterDestroy();CHKERRQ(ierr);
491e27a552bSJed Brown   PetscFunctionReturn(0);
492e27a552bSJed Brown }
493e27a552bSJed Brown 
494e27a552bSJed Brown #undef __FUNCT__
495e27a552bSJed Brown #define __FUNCT__ "TSRosWRegister"
496e27a552bSJed Brown /*@C
49761692a83SJed Brown    TSRosWRegister - register a Rosenbrock W scheme by providing the entries in the Butcher tableau and optionally embedded approximations and interpolation
498e27a552bSJed Brown 
499e27a552bSJed Brown    Not Collective, but the same schemes should be registered on all processes on which they will be used
500e27a552bSJed Brown 
501e27a552bSJed Brown    Input Parameters:
502e27a552bSJed Brown +  name - identifier for method
503e27a552bSJed Brown .  order - approximation order of method
504e27a552bSJed Brown .  s - number of stages, this is the dimension of the matrices below
50561692a83SJed Brown .  A - Table of propagated stage coefficients (dimension s*s, row-major), strictly lower triangular
50661692a83SJed Brown .  Gamma - Table of coefficients in implicit stage equations (dimension s*s, row-major), lower triangular with nonzero diagonal
507fe7e6d57SJed Brown .  b - Step completion table (dimension s)
508fe7e6d57SJed Brown -  bembed - Step completion table for a scheme of order one less (dimension s, PETSC_NULL if no embedded scheme is available)
509f4aed992SEmil Constantinescu .  pinterp - Order of the interpolation scheme, equal to the number of columns of binterpt
510f4aed992SEmil Constantinescu .  binterpt - Coefficients of the interpolation formula (dimension s*pinterp)
511e27a552bSJed Brown 
512e27a552bSJed Brown    Notes:
51361692a83SJed Brown    Several Rosenbrock W methods are provided, this function is only needed to create new methods.
514e27a552bSJed Brown 
515e27a552bSJed Brown    Level: advanced
516e27a552bSJed Brown 
517e27a552bSJed Brown .keywords: TS, register
518e27a552bSJed Brown 
519e27a552bSJed Brown .seealso: TSRosW
520e27a552bSJed Brown @*/
521e27a552bSJed Brown PetscErrorCode TSRosWRegister(const TSRosWType name,PetscInt order,PetscInt s,
522f4aed992SEmil Constantinescu                               const PetscReal A[],const PetscReal Gamma[],const PetscReal b[],const PetscReal bembed[],
523f4aed992SEmil Constantinescu                                  PetscInt pinterp,const PetscReal binterpt[])
524e27a552bSJed Brown {
525e27a552bSJed Brown   PetscErrorCode ierr;
52661692a83SJed Brown   RosWTableauLink link;
52761692a83SJed Brown   RosWTableau t;
52861692a83SJed Brown   PetscInt i,j,k;
52961692a83SJed Brown   PetscScalar *GammaInv;
530e27a552bSJed Brown 
531e27a552bSJed Brown   PetscFunctionBegin;
532fe7e6d57SJed Brown   PetscValidCharPointer(name,1);
533fe7e6d57SJed Brown   PetscValidPointer(A,4);
534fe7e6d57SJed Brown   PetscValidPointer(Gamma,5);
535fe7e6d57SJed Brown   PetscValidPointer(b,6);
536fe7e6d57SJed Brown   if (bembed) PetscValidPointer(bembed,7);
537fe7e6d57SJed Brown 
538e27a552bSJed Brown   ierr = PetscMalloc(sizeof(*link),&link);CHKERRQ(ierr);
539e27a552bSJed Brown   ierr = PetscMemzero(link,sizeof(*link));CHKERRQ(ierr);
540e27a552bSJed Brown   t = &link->tab;
541e27a552bSJed Brown   ierr = PetscStrallocpy(name,&t->name);CHKERRQ(ierr);
542e27a552bSJed Brown   t->order = order;
543e27a552bSJed Brown   t->s = s;
54461692a83SJed Brown   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);
54543b21953SEmil Constantinescu   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);
546e27a552bSJed Brown   ierr = PetscMemcpy(t->A,A,s*s*sizeof(A[0]));CHKERRQ(ierr);
54761692a83SJed Brown   ierr = PetscMemcpy(t->Gamma,Gamma,s*s*sizeof(Gamma[0]));CHKERRQ(ierr);
54843b21953SEmil Constantinescu   ierr = PetscMemcpy(t->GammaExplicitCorr,Gamma,s*s*sizeof(Gamma[0]));CHKERRQ(ierr);
54961692a83SJed Brown   ierr = PetscMemcpy(t->b,b,s*sizeof(b[0]));CHKERRQ(ierr);
550fe7e6d57SJed Brown   if (bembed) {
551fe7e6d57SJed Brown     ierr = PetscMalloc2(s,PetscReal,&t->bembed,s,PetscReal,&t->bembedt);CHKERRQ(ierr);
552fe7e6d57SJed Brown     ierr = PetscMemcpy(t->bembed,bembed,s*sizeof(bembed[0]));CHKERRQ(ierr);
553fe7e6d57SJed Brown   }
55461692a83SJed Brown   for (i=0; i<s; i++) {
55561692a83SJed Brown     t->ASum[i] = 0;
55661692a83SJed Brown     t->GammaSum[i] = 0;
55761692a83SJed Brown     for (j=0; j<s; j++) {
55861692a83SJed Brown       t->ASum[i] += A[i*s+j];
559fe7e6d57SJed Brown       t->GammaSum[i] += Gamma[i*s+j];
56061692a83SJed Brown     }
56161692a83SJed Brown   }
56261692a83SJed Brown   ierr = PetscMalloc(s*s*sizeof(PetscScalar),&GammaInv);CHKERRQ(ierr); /* Need to use Scalar for inverse, then convert back to Real */
56361692a83SJed Brown   for (i=0; i<s*s; i++) GammaInv[i] = Gamma[i];
564fd96d5b0SEmil Constantinescu   for (i=0; i<s; i++) {
565fd96d5b0SEmil Constantinescu     if (Gamma[i*s+i] == 0.0) {
566fd96d5b0SEmil Constantinescu       GammaInv[i*s+i] = 1.0;
567c17803e7SJed Brown       t->GammaZeroDiag[i] = PETSC_TRUE;
568fd96d5b0SEmil Constantinescu     } else {
569c17803e7SJed Brown       t->GammaZeroDiag[i] = PETSC_FALSE;
570fd96d5b0SEmil Constantinescu     }
571fd96d5b0SEmil Constantinescu   }
572fd96d5b0SEmil Constantinescu 
57361692a83SJed Brown   switch (s) {
57461692a83SJed Brown   case 1: GammaInv[0] = 1./GammaInv[0]; break;
57561692a83SJed Brown   case 2: ierr = Kernel_A_gets_inverse_A_2(GammaInv,0);CHKERRQ(ierr); break;
57661692a83SJed Brown   case 3: ierr = Kernel_A_gets_inverse_A_3(GammaInv,0);CHKERRQ(ierr); break;
57761692a83SJed Brown   case 4: ierr = Kernel_A_gets_inverse_A_4(GammaInv,0);CHKERRQ(ierr); break;
57861692a83SJed Brown   case 5: {
57961692a83SJed Brown     PetscInt ipvt5[5];
58061692a83SJed Brown     MatScalar work5[5*5];
58161692a83SJed Brown     ierr = Kernel_A_gets_inverse_A_5(GammaInv,ipvt5,work5,0);CHKERRQ(ierr); break;
58261692a83SJed Brown   }
58361692a83SJed Brown   case 6: ierr = Kernel_A_gets_inverse_A_6(GammaInv,0);CHKERRQ(ierr); break;
58461692a83SJed Brown   case 7: ierr = Kernel_A_gets_inverse_A_7(GammaInv,0);CHKERRQ(ierr); break;
58561692a83SJed Brown   default: SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented for %D stages",s);
58661692a83SJed Brown   }
58761692a83SJed Brown   for (i=0; i<s*s; i++) t->GammaInv[i] = PetscRealPart(GammaInv[i]);
58861692a83SJed Brown   ierr = PetscFree(GammaInv);CHKERRQ(ierr);
58943b21953SEmil Constantinescu 
59043b21953SEmil Constantinescu   for (i=0; i<s; i++) {
59143b21953SEmil Constantinescu     for (k=0; k<i+1; k++) {
59243b21953SEmil Constantinescu       t->GammaExplicitCorr[i*s+k]=(t->GammaExplicitCorr[i*s+k])*(t->GammaInv[k*s+k]);
59343b21953SEmil Constantinescu       for (j=k+1; j<i+1; j++) {
59443b21953SEmil Constantinescu         t->GammaExplicitCorr[i*s+k]+=(t->GammaExplicitCorr[i*s+j])*(t->GammaInv[j*s+k]);
59543b21953SEmil Constantinescu       }
59643b21953SEmil Constantinescu     }
59743b21953SEmil Constantinescu   }
59843b21953SEmil Constantinescu 
59961692a83SJed Brown   for (i=0; i<s; i++) {
60061692a83SJed Brown     for (j=0; j<s; j++) {
60161692a83SJed Brown       t->At[i*s+j] = 0;
60261692a83SJed Brown       for (k=0; k<s; k++) {
60361692a83SJed Brown         t->At[i*s+j] += t->A[i*s+k] * t->GammaInv[k*s+j];
60461692a83SJed Brown       }
60561692a83SJed Brown     }
60661692a83SJed Brown     t->bt[i] = 0;
60761692a83SJed Brown     for (j=0; j<s; j++) {
60861692a83SJed Brown       t->bt[i] += t->b[j] * t->GammaInv[j*s+i];
60961692a83SJed Brown     }
610fe7e6d57SJed Brown     if (bembed) {
611fe7e6d57SJed Brown       t->bembedt[i] = 0;
612fe7e6d57SJed Brown       for (j=0; j<s; j++) {
613fe7e6d57SJed Brown         t->bembedt[i] += t->bembed[j] * t->GammaInv[j*s+i];
614fe7e6d57SJed Brown       }
615fe7e6d57SJed Brown     }
61661692a83SJed Brown   }
6178d59e960SJed Brown   t->ccfl = 1.0;                /* Fix this */
6188d59e960SJed Brown 
619f4aed992SEmil Constantinescu   t->pinterp = pinterp;
620f4aed992SEmil Constantinescu   ierr = PetscMalloc(s*pinterp,&t->binterpt);CHKERRQ(ierr);
621f4aed992SEmil Constantinescu 
62261692a83SJed Brown   link->next = RosWTableauList;
62361692a83SJed Brown   RosWTableauList = link;
624e27a552bSJed Brown   PetscFunctionReturn(0);
625e27a552bSJed Brown }
626e27a552bSJed Brown 
627e27a552bSJed Brown #undef __FUNCT__
6281c3436cfSJed Brown #define __FUNCT__ "TSEvaluateStep_RosW"
6291c3436cfSJed Brown /*
6301c3436cfSJed Brown  The step completion formula is
6311c3436cfSJed Brown 
6321c3436cfSJed Brown  x1 = x0 + b^T Y
6331c3436cfSJed Brown 
6341c3436cfSJed Brown  where Y is the multi-vector of stages corrections. This function can be called before or after ts->vec_sol has been
6351c3436cfSJed Brown  updated. Suppose we have a completion formula b and an embedded formula be of different order. We can write
6361c3436cfSJed Brown 
6371c3436cfSJed Brown  x1e = x0 + be^T Y
6381c3436cfSJed Brown      = x1 - b^T Y + be^T Y
6391c3436cfSJed Brown      = x1 + (be - b)^T Y
6401c3436cfSJed Brown 
6411c3436cfSJed Brown  so we can evaluate the method of different order even after the step has been optimistically completed.
6421c3436cfSJed Brown */
6431c3436cfSJed Brown static PetscErrorCode TSEvaluateStep_RosW(TS ts,PetscInt order,Vec X,PetscBool *done)
6441c3436cfSJed Brown {
6451c3436cfSJed Brown   TS_RosW        *ros = (TS_RosW*)ts->data;
6461c3436cfSJed Brown   RosWTableau    tab  = ros->tableau;
6471c3436cfSJed Brown   PetscScalar    *w = ros->work;
6481c3436cfSJed Brown   PetscInt       i;
6491c3436cfSJed Brown   PetscErrorCode ierr;
6501c3436cfSJed Brown 
6511c3436cfSJed Brown   PetscFunctionBegin;
6521c3436cfSJed Brown   if (order == tab->order) {
653108c343cSJed Brown     if (ros->status == TS_STEP_INCOMPLETE) { /* Use standard completion formula */
6541c3436cfSJed Brown       ierr = VecCopy(ts->vec_sol,X);CHKERRQ(ierr);
655de19f811SJed Brown       for (i=0; i<tab->s; i++) w[i] = tab->bt[i];
656de19f811SJed Brown       ierr = VecMAXPY(X,tab->s,w,ros->Y);CHKERRQ(ierr);
657108c343cSJed Brown     } else {ierr = VecCopy(ts->vec_sol,X);CHKERRQ(ierr);}
6581c3436cfSJed Brown     if (done) *done = PETSC_TRUE;
6591c3436cfSJed Brown     PetscFunctionReturn(0);
6601c3436cfSJed Brown   } else if (order == tab->order-1) {
6611c3436cfSJed Brown     if (!tab->bembedt) goto unavailable;
662108c343cSJed Brown     if (ros->status == TS_STEP_INCOMPLETE) { /* Use embedded completion formula */
6631c3436cfSJed Brown       ierr = VecCopy(ts->vec_sol,X);CHKERRQ(ierr);
664de19f811SJed Brown       for (i=0; i<tab->s; i++) w[i] = tab->bembedt[i];
665de19f811SJed Brown       ierr = VecMAXPY(X,tab->s,w,ros->Y);CHKERRQ(ierr);
666108c343cSJed Brown     } else {                    /* Use rollback-and-recomplete formula (bembedt - bt) */
667108c343cSJed Brown       for (i=0; i<tab->s; i++) w[i] = tab->bembedt[i] - tab->bt[i];
668108c343cSJed Brown       ierr = VecCopy(ts->vec_sol,X);CHKERRQ(ierr);
669108c343cSJed Brown       ierr = VecMAXPY(X,tab->s,w,ros->Y);CHKERRQ(ierr);
6701c3436cfSJed Brown     }
6711c3436cfSJed Brown     if (done) *done = PETSC_TRUE;
6721c3436cfSJed Brown     PetscFunctionReturn(0);
6731c3436cfSJed Brown   }
6741c3436cfSJed Brown   unavailable:
6751c3436cfSJed Brown   if (done) *done = PETSC_FALSE;
6761c3436cfSJed Brown   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);
6771c3436cfSJed Brown   PetscFunctionReturn(0);
6781c3436cfSJed Brown }
6791c3436cfSJed Brown 
6801c3436cfSJed Brown #undef __FUNCT__
681e27a552bSJed Brown #define __FUNCT__ "TSStep_RosW"
682e27a552bSJed Brown static PetscErrorCode TSStep_RosW(TS ts)
683e27a552bSJed Brown {
68461692a83SJed Brown   TS_RosW         *ros = (TS_RosW*)ts->data;
68561692a83SJed Brown   RosWTableau     tab  = ros->tableau;
686e27a552bSJed Brown   const PetscInt  s    = tab->s;
6871c3436cfSJed Brown   const PetscReal *At  = tab->At,*Gamma = tab->Gamma,*ASum = tab->ASum,*GammaInv = tab->GammaInv;
6880feba352SEmil Constantinescu   const PetscReal *GammaExplicitCorr = tab->GammaExplicitCorr;
689c17803e7SJed Brown   const PetscBool *GammaZeroDiag = tab->GammaZeroDiag;
69061692a83SJed Brown   PetscScalar     *w   = ros->work;
6917d4bf2deSEmil Constantinescu   Vec             *Y   = ros->Y,Ydot = ros->Ydot,Zdot = ros->Zdot,Zstage = ros->Zstage;
692e27a552bSJed Brown   SNES            snes;
6931c3436cfSJed Brown   TSAdapt         adapt;
6941c3436cfSJed Brown   PetscInt        i,j,its,lits,reject,next_scheme;
695cdbf8f93SLisandro Dalcin   PetscReal       next_time_step;
6961c3436cfSJed Brown   PetscBool       accept;
697e27a552bSJed Brown   PetscErrorCode  ierr;
6980feba352SEmil Constantinescu   MatStructure    str;
699e27a552bSJed Brown 
700e27a552bSJed Brown   PetscFunctionBegin;
701e27a552bSJed Brown   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
702cdbf8f93SLisandro Dalcin   next_time_step = ts->time_step;
7031c3436cfSJed Brown   accept = PETSC_TRUE;
704108c343cSJed Brown   ros->status = TS_STEP_INCOMPLETE;
705e27a552bSJed Brown 
70697335746SJed Brown   for (reject=0; reject<ts->max_reject && !ts->reason; reject++,ts->reject++) {
7071c3436cfSJed Brown     const PetscReal h = ts->time_step;
708e27a552bSJed Brown     for (i=0; i<s; i++) {
7091c3436cfSJed Brown       ros->stage_time = ts->ptime + h*ASum[i];
710c17803e7SJed Brown       if (GammaZeroDiag[i]) {
711c17803e7SJed Brown         ros->stage_explicit = PETSC_TRUE;
712fd96d5b0SEmil Constantinescu         ros->shift = 1./h;
713c17803e7SJed Brown       } else {
714c17803e7SJed Brown         ros->stage_explicit = PETSC_FALSE;
71561692a83SJed Brown         ros->shift = 1./(h*Gamma[i*s+i]);
716fd96d5b0SEmil Constantinescu       }
71761692a83SJed Brown 
71861692a83SJed Brown       ierr = VecCopy(ts->vec_sol,Zstage);CHKERRQ(ierr);
719de19f811SJed Brown       for (j=0; j<i; j++) w[j] = At[i*s+j];
720de19f811SJed Brown       ierr = VecMAXPY(Zstage,i,w,Y);CHKERRQ(ierr);
72161692a83SJed Brown 
72261692a83SJed Brown       for (j=0; j<i; j++) w[j] = 1./h * GammaInv[i*s+j];
72361692a83SJed Brown       ierr = VecZeroEntries(Zdot);CHKERRQ(ierr);
72461692a83SJed Brown       ierr = VecMAXPY(Zdot,i,w,Y);CHKERRQ(ierr);
72561692a83SJed Brown 
726e27a552bSJed Brown       /* Initial guess taken from last stage */
72761692a83SJed Brown       ierr = VecZeroEntries(Y[i]);CHKERRQ(ierr);
72861692a83SJed Brown 
7297d4bf2deSEmil Constantinescu       if (!ros->stage_explicit) {
73061692a83SJed Brown         if (!ros->recompute_jacobian && !i) {
73161692a83SJed Brown           ierr = SNESSetLagJacobian(snes,-2);CHKERRQ(ierr); /* Recompute the Jacobian on this solve, but not again */
73261692a83SJed Brown         }
73361692a83SJed Brown         ierr = SNESSolve(snes,PETSC_NULL,Y[i]);CHKERRQ(ierr);
734e27a552bSJed Brown         ierr = SNESGetIterationNumber(snes,&its);CHKERRQ(ierr);
735e27a552bSJed Brown         ierr = SNESGetLinearSolveIterations(snes,&lits);CHKERRQ(ierr);
736e27a552bSJed Brown         ts->nonlinear_its += its; ts->linear_its += lits;
73797335746SJed Brown         ierr = TSGetAdapt(ts,&adapt);CHKERRQ(ierr);
73897335746SJed Brown         ierr = TSAdaptCheckStage(adapt,ts,&accept);CHKERRQ(ierr);
73997335746SJed Brown         if (!accept) goto reject_step;
7407d4bf2deSEmil Constantinescu       } else {
7411ce71dffSSatish Balay         Mat J,Jp;
7420feba352SEmil Constantinescu         ierr = VecZeroEntries(Ydot);CHKERRQ(ierr); /* Evaluate Y[i]=G(t,Ydot=0,Zstage) */
7430feba352SEmil Constantinescu         ierr = TSComputeIFunction(ts,ros->stage_time,Zstage,Ydot,Y[i],PETSC_FALSE);CHKERRQ(ierr);
7440feba352SEmil Constantinescu         ierr = VecScale(Y[i],-1.0);
7450feba352SEmil Constantinescu         ierr = VecAXPY(Y[i],-1.0,Zdot);CHKERRQ(ierr); /*Y[i]=F(Zstage)-Zdot[=GammaInv*Y]*/
7460feba352SEmil Constantinescu 
7470feba352SEmil Constantinescu         ierr = VecZeroEntries(Zstage);CHKERRQ(ierr); /* Zstage = GammaExplicitCorr[i,j] * Y[j] */
7480feba352SEmil Constantinescu         for (j=0; j<i; j++) w[j] = GammaExplicitCorr[i*s+j];
7490feba352SEmil Constantinescu         ierr = VecMAXPY(Zstage,i,w,Y);CHKERRQ(ierr);
7500feba352SEmil Constantinescu         /*Y[i] += Y[i] + Jac*Zstage[=Jac*GammaExplicitCorr[i,j] * Y[j]] */
7510feba352SEmil Constantinescu         str = SAME_NONZERO_PATTERN;
7520feba352SEmil Constantinescu         ierr = TSGetIJacobian(ts,&J,&Jp,PETSC_NULL,PETSC_NULL);
7530feba352SEmil Constantinescu         ierr = TSComputeIJacobian(ts,ros->stage_time,ts->vec_sol,Ydot,0,&J,&Jp,&str,PETSC_FALSE);CHKERRQ(ierr);
7540feba352SEmil Constantinescu         ierr = MatMult(J,Zstage,Zdot);
7550feba352SEmil Constantinescu 
7560feba352SEmil Constantinescu         ierr = VecAXPY(Y[i],-1.0,Zdot);CHKERRQ(ierr);
7570feba352SEmil Constantinescu         ierr = VecScale(Y[i],h);
7587d4bf2deSEmil Constantinescu         ts->linear_its += 1;
7597d4bf2deSEmil Constantinescu       }
760e27a552bSJed Brown     }
7611c3436cfSJed Brown     ierr = TSEvaluateStep(ts,tab->order,ts->vec_sol,PETSC_NULL);CHKERRQ(ierr);
762108c343cSJed Brown     ros->status = TS_STEP_PENDING;
763e27a552bSJed Brown 
7641c3436cfSJed Brown     /* Register only the current method as a candidate because we're not supporting multiple candidates yet. */
7651c3436cfSJed Brown     ierr = TSGetAdapt(ts,&adapt);CHKERRQ(ierr);
7661c3436cfSJed Brown     ierr = TSAdaptCandidatesClear(adapt);CHKERRQ(ierr);
7678d59e960SJed Brown     ierr = TSAdaptCandidateAdd(adapt,tab->name,tab->order,1,tab->ccfl,1.*tab->s,PETSC_TRUE);CHKERRQ(ierr);
7681c3436cfSJed Brown     ierr = TSAdaptChoose(adapt,ts,ts->time_step,&next_scheme,&next_time_step,&accept);CHKERRQ(ierr);
7691c3436cfSJed Brown     if (accept) {
7701c3436cfSJed Brown       /* ignore next_scheme for now */
771e27a552bSJed Brown       ts->ptime += ts->time_step;
772cdbf8f93SLisandro Dalcin       ts->time_step = next_time_step;
773e27a552bSJed Brown       ts->steps++;
774108c343cSJed Brown       ros->status = TS_STEP_COMPLETE;
7751c3436cfSJed Brown       break;
7761c3436cfSJed Brown     } else {                    /* Roll back the current step */
7771c3436cfSJed Brown       for (i=0; i<s; i++) w[i] = -tab->bt[i];
7781c3436cfSJed Brown       ierr = VecMAXPY(ts->vec_sol,s,w,Y);CHKERRQ(ierr);
7791c3436cfSJed Brown       ts->time_step = next_time_step;
780108c343cSJed Brown       ros->status = TS_STEP_INCOMPLETE;
7811c3436cfSJed Brown     }
782476b6736SJed Brown     reject_step: continue;
7831c3436cfSJed Brown   }
784b2ce242eSJed Brown   if (ros->status != TS_STEP_COMPLETE && !ts->reason) ts->reason = TS_DIVERGED_STEP_REJECTED;
785e27a552bSJed Brown   PetscFunctionReturn(0);
786e27a552bSJed Brown }
787e27a552bSJed Brown 
788e27a552bSJed Brown #undef __FUNCT__
789e27a552bSJed Brown #define __FUNCT__ "TSInterpolate_RosW"
790e27a552bSJed Brown static PetscErrorCode TSInterpolate_RosW(TS ts,PetscReal itime,Vec X)
791e27a552bSJed Brown {
79261692a83SJed Brown   TS_RosW        *ros = (TS_RosW*)ts->data;
793f4aed992SEmil Constantinescu   PetscInt s = ros->tableau->s,pinterp = ros->tableau->pinterp,i,j;
794f4aed992SEmil Constantinescu   PetscReal h;
795f4aed992SEmil Constantinescu   PetscReal tt,t;
796f4aed992SEmil Constantinescu   PetscScalar *bt;
797f4aed992SEmil Constantinescu   const PetscReal *Bt = ros->tableau->binterpt;
798f4aed992SEmil Constantinescu   PetscErrorCode ierr;
799f4aed992SEmil Constantinescu   const PetscReal *GammaInv = ros->tableau->GammaInv;
800f4aed992SEmil Constantinescu   PetscScalar     *w   = ros->work;
801f4aed992SEmil Constantinescu   Vec             *Y   = ros->Y;
802e27a552bSJed Brown 
803e27a552bSJed Brown   PetscFunctionBegin;
804f4aed992SEmil Constantinescu   if (!Bt) SETERRQ1(((PetscObject)ts)->comm,PETSC_ERR_SUP,"TSRosW %s does not have an interpolation formula",ros->tableau->name);
805f4aed992SEmil Constantinescu 
806f4aed992SEmil Constantinescu   switch (ros->status) {
807f4aed992SEmil Constantinescu   case TS_STEP_INCOMPLETE:
808f4aed992SEmil Constantinescu   case TS_STEP_PENDING:
809f4aed992SEmil Constantinescu     h = ts->time_step;
810f4aed992SEmil Constantinescu     t = (itime - ts->ptime)/h;
811f4aed992SEmil Constantinescu     break;
812f4aed992SEmil Constantinescu   case TS_STEP_COMPLETE:
813f4aed992SEmil Constantinescu     h = ts->time_step_prev;
814f4aed992SEmil Constantinescu     t = (itime - ts->ptime)/h + 1; /* In the interval [0,1] */
815f4aed992SEmil Constantinescu     break;
816f4aed992SEmil Constantinescu   default: SETERRQ(((PetscObject)ts)->comm,PETSC_ERR_PLIB,"Invalid TSStepStatus");
817f4aed992SEmil Constantinescu   }
818f4aed992SEmil Constantinescu   ierr = PetscMalloc(s,&bt);CHKERRQ(ierr);
819f4aed992SEmil Constantinescu   for (i=0; i<s; i++) bt[i] = 0;
820f4aed992SEmil Constantinescu   for (j=0,tt=t; j<pinterp; j++,tt*=t) {
821f4aed992SEmil Constantinescu     for (i=0; i<s; i++) {
822f4aed992SEmil Constantinescu       bt[i] += h * Bt[i*pinterp+j] * tt;
823f4aed992SEmil Constantinescu     }
824f4aed992SEmil Constantinescu   }
825f4aed992SEmil Constantinescu 
826f4aed992SEmil Constantinescu   /* y(t+tt*h) = y(t) + Sum bt(tt) * GammaInv * Ydot */
827f4aed992SEmil Constantinescu   /*X<-0*/
828f4aed992SEmil Constantinescu   ierr = VecZeroEntries(X);CHKERRQ(ierr);
829f4aed992SEmil Constantinescu 
830f4aed992SEmil Constantinescu   /*X<- Sum bt_i * GammaInv(i,1:i) * Y(1:i) */
831f4aed992SEmil Constantinescu   for (i=0; i<s; i++) {
832f4aed992SEmil Constantinescu     for (j=0; j<=i; j++) w[j] =  bt[i]*GammaInv[i*s+j];
833f4aed992SEmil Constantinescu     ierr = VecMAXPY(X,i,w,Y);CHKERRQ(ierr);
834f4aed992SEmil Constantinescu   }
835f4aed992SEmil Constantinescu 
836f4aed992SEmil Constantinescu   /*X<-y(t) + X*/
837f4aed992SEmil Constantinescu   ierr = VecAXPY(X,1.0,ts->vec_sol);CHKERRQ(ierr);
838f4aed992SEmil Constantinescu 
839f4aed992SEmil Constantinescu   ierr = PetscFree(bt);CHKERRQ(ierr);
840f4aed992SEmil Constantinescu 
841e27a552bSJed Brown   PetscFunctionReturn(0);
842e27a552bSJed Brown }
843e27a552bSJed Brown 
844e27a552bSJed Brown /*------------------------------------------------------------*/
845e27a552bSJed Brown #undef __FUNCT__
846e27a552bSJed Brown #define __FUNCT__ "TSReset_RosW"
847e27a552bSJed Brown static PetscErrorCode TSReset_RosW(TS ts)
848e27a552bSJed Brown {
84961692a83SJed Brown   TS_RosW        *ros = (TS_RosW*)ts->data;
850e27a552bSJed Brown   PetscInt       s;
851e27a552bSJed Brown   PetscErrorCode ierr;
852e27a552bSJed Brown 
853e27a552bSJed Brown   PetscFunctionBegin;
85461692a83SJed Brown   if (!ros->tableau) PetscFunctionReturn(0);
85561692a83SJed Brown    s = ros->tableau->s;
85661692a83SJed Brown   ierr = VecDestroyVecs(s,&ros->Y);CHKERRQ(ierr);
85761692a83SJed Brown   ierr = VecDestroy(&ros->Ydot);CHKERRQ(ierr);
85861692a83SJed Brown   ierr = VecDestroy(&ros->Ystage);CHKERRQ(ierr);
85961692a83SJed Brown   ierr = VecDestroy(&ros->Zdot);CHKERRQ(ierr);
86061692a83SJed Brown   ierr = VecDestroy(&ros->Zstage);CHKERRQ(ierr);
86161692a83SJed Brown   ierr = PetscFree(ros->work);CHKERRQ(ierr);
862e27a552bSJed Brown   PetscFunctionReturn(0);
863e27a552bSJed Brown }
864e27a552bSJed Brown 
865e27a552bSJed Brown #undef __FUNCT__
866e27a552bSJed Brown #define __FUNCT__ "TSDestroy_RosW"
867e27a552bSJed Brown static PetscErrorCode TSDestroy_RosW(TS ts)
868e27a552bSJed Brown {
869e27a552bSJed Brown   PetscErrorCode  ierr;
870e27a552bSJed Brown 
871e27a552bSJed Brown   PetscFunctionBegin;
872e27a552bSJed Brown   ierr = TSReset_RosW(ts);CHKERRQ(ierr);
873e27a552bSJed Brown   ierr = PetscFree(ts->data);CHKERRQ(ierr);
874e27a552bSJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSRosWGetType_C","",PETSC_NULL);CHKERRQ(ierr);
875e27a552bSJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSRosWSetType_C","",PETSC_NULL);CHKERRQ(ierr);
87661692a83SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSRosWSetRecomputeJacobian_C","",PETSC_NULL);CHKERRQ(ierr);
877e27a552bSJed Brown   PetscFunctionReturn(0);
878e27a552bSJed Brown }
879e27a552bSJed Brown 
880e27a552bSJed Brown /*
881e27a552bSJed Brown   This defines the nonlinear equation that is to be solved with SNES
882e27a552bSJed Brown   G(U) = F[t0+Theta*dt, U, (U-U0)*shift] = 0
883e27a552bSJed Brown */
884e27a552bSJed Brown #undef __FUNCT__
885e27a552bSJed Brown #define __FUNCT__ "SNESTSFormFunction_RosW"
886e27a552bSJed Brown static PetscErrorCode SNESTSFormFunction_RosW(SNES snes,Vec X,Vec F,TS ts)
887e27a552bSJed Brown {
88861692a83SJed Brown   TS_RosW        *ros = (TS_RosW*)ts->data;
889e27a552bSJed Brown   PetscErrorCode ierr;
890e27a552bSJed Brown 
891e27a552bSJed Brown   PetscFunctionBegin;
89261692a83SJed Brown   ierr = VecWAXPY(ros->Ydot,ros->shift,X,ros->Zdot);CHKERRQ(ierr); /* Ydot = shift*X + Zdot */
89361692a83SJed Brown   ierr = VecWAXPY(ros->Ystage,1.0,X,ros->Zstage);CHKERRQ(ierr);    /* Ystage = X + Zstage */
89461692a83SJed Brown   ierr = TSComputeIFunction(ts,ros->stage_time,ros->Ystage,ros->Ydot,F,PETSC_FALSE);CHKERRQ(ierr);
895e27a552bSJed Brown   PetscFunctionReturn(0);
896e27a552bSJed Brown }
897e27a552bSJed Brown 
898e27a552bSJed Brown #undef __FUNCT__
899e27a552bSJed Brown #define __FUNCT__ "SNESTSFormJacobian_RosW"
900e27a552bSJed Brown static PetscErrorCode SNESTSFormJacobian_RosW(SNES snes,Vec X,Mat *A,Mat *B,MatStructure *str,TS ts)
901e27a552bSJed Brown {
90261692a83SJed Brown   TS_RosW        *ros = (TS_RosW*)ts->data;
903e27a552bSJed Brown   PetscErrorCode ierr;
904e27a552bSJed Brown 
905e27a552bSJed Brown   PetscFunctionBegin;
90661692a83SJed Brown   /* ros->Ydot and ros->Ystage have already been computed in SNESTSFormFunction_RosW (SNES guarantees this) */
90761692a83SJed Brown   ierr = TSComputeIJacobian(ts,ros->stage_time,ros->Ystage,ros->Ydot,ros->shift,A,B,str,PETSC_TRUE);CHKERRQ(ierr);
908e27a552bSJed Brown   PetscFunctionReturn(0);
909e27a552bSJed Brown }
910e27a552bSJed Brown 
911e27a552bSJed Brown #undef __FUNCT__
912e27a552bSJed Brown #define __FUNCT__ "TSSetUp_RosW"
913e27a552bSJed Brown static PetscErrorCode TSSetUp_RosW(TS ts)
914e27a552bSJed Brown {
91561692a83SJed Brown   TS_RosW        *ros = (TS_RosW*)ts->data;
91661692a83SJed Brown   RosWTableau    tab  = ros->tableau;
917e27a552bSJed Brown   PetscInt       s    = tab->s;
918e27a552bSJed Brown   PetscErrorCode ierr;
919e27a552bSJed Brown 
920e27a552bSJed Brown   PetscFunctionBegin;
92161692a83SJed Brown   if (!ros->tableau) {
922e27a552bSJed Brown     ierr = TSRosWSetType(ts,TSRosWDefault);CHKERRQ(ierr);
923e27a552bSJed Brown   }
92461692a83SJed Brown   ierr = VecDuplicateVecs(ts->vec_sol,s,&ros->Y);CHKERRQ(ierr);
92561692a83SJed Brown   ierr = VecDuplicate(ts->vec_sol,&ros->Ydot);CHKERRQ(ierr);
92661692a83SJed Brown   ierr = VecDuplicate(ts->vec_sol,&ros->Ystage);CHKERRQ(ierr);
92761692a83SJed Brown   ierr = VecDuplicate(ts->vec_sol,&ros->Zdot);CHKERRQ(ierr);
92861692a83SJed Brown   ierr = VecDuplicate(ts->vec_sol,&ros->Zstage);CHKERRQ(ierr);
92961692a83SJed Brown   ierr = PetscMalloc(s*sizeof(ros->work[0]),&ros->work);CHKERRQ(ierr);
930e27a552bSJed Brown   PetscFunctionReturn(0);
931e27a552bSJed Brown }
932e27a552bSJed Brown /*------------------------------------------------------------*/
933e27a552bSJed Brown 
934e27a552bSJed Brown #undef __FUNCT__
935e27a552bSJed Brown #define __FUNCT__ "TSSetFromOptions_RosW"
936e27a552bSJed Brown static PetscErrorCode TSSetFromOptions_RosW(TS ts)
937e27a552bSJed Brown {
93861692a83SJed Brown   TS_RosW        *ros = (TS_RosW*)ts->data;
939e27a552bSJed Brown   PetscErrorCode ierr;
94061692a83SJed Brown   char           rostype[256];
941e27a552bSJed Brown 
942e27a552bSJed Brown   PetscFunctionBegin;
943e27a552bSJed Brown   ierr = PetscOptionsHead("RosW ODE solver options");CHKERRQ(ierr);
944e27a552bSJed Brown   {
94561692a83SJed Brown     RosWTableauLink link;
946e27a552bSJed Brown     PetscInt count,choice;
947e27a552bSJed Brown     PetscBool flg;
948e27a552bSJed Brown     const char **namelist;
94961692a83SJed Brown     SNES snes;
95061692a83SJed Brown 
95161692a83SJed Brown     ierr = PetscStrncpy(rostype,TSRosWDefault,sizeof rostype);CHKERRQ(ierr);
95261692a83SJed Brown     for (link=RosWTableauList,count=0; link; link=link->next,count++) ;
953e27a552bSJed Brown     ierr = PetscMalloc(count*sizeof(char*),&namelist);CHKERRQ(ierr);
95461692a83SJed Brown     for (link=RosWTableauList,count=0; link; link=link->next,count++) namelist[count] = link->tab.name;
95561692a83SJed Brown     ierr = PetscOptionsEList("-ts_rosw_type","Family of Rosenbrock-W method","TSRosWSetType",(const char*const*)namelist,count,rostype,&choice,&flg);CHKERRQ(ierr);
95661692a83SJed Brown     ierr = TSRosWSetType(ts,flg ? namelist[choice] : rostype);CHKERRQ(ierr);
957e27a552bSJed Brown     ierr = PetscFree(namelist);CHKERRQ(ierr);
95861692a83SJed Brown 
95961692a83SJed Brown     ierr = PetscOptionsBool("-ts_rosw_recompute_jacobian","Recompute the Jacobian at each stage","TSRosWSetRecomputeJacobian",ros->recompute_jacobian,&ros->recompute_jacobian,PETSC_NULL);CHKERRQ(ierr);
96061692a83SJed Brown 
96161692a83SJed Brown     /* Rosenbrock methods are linearly implicit, so set that unless the user has specifically asked for something else */
96261692a83SJed Brown     ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
96361692a83SJed Brown     if (!((PetscObject)snes)->type_name) {
96461692a83SJed Brown       ierr = SNESSetType(snes,SNESKSPONLY);CHKERRQ(ierr);
96561692a83SJed Brown     }
96661692a83SJed Brown     ierr = SNESSetFromOptions(snes);CHKERRQ(ierr);
967e27a552bSJed Brown   }
968e27a552bSJed Brown   ierr = PetscOptionsTail();CHKERRQ(ierr);
969e27a552bSJed Brown   PetscFunctionReturn(0);
970e27a552bSJed Brown }
971e27a552bSJed Brown 
972e27a552bSJed Brown #undef __FUNCT__
973e27a552bSJed Brown #define __FUNCT__ "PetscFormatRealArray"
974e27a552bSJed Brown static PetscErrorCode PetscFormatRealArray(char buf[],size_t len,const char *fmt,PetscInt n,const PetscReal x[])
975e27a552bSJed Brown {
976e27a552bSJed Brown   PetscErrorCode ierr;
977e408995aSJed Brown   PetscInt i;
978e408995aSJed Brown   size_t left,count;
979e27a552bSJed Brown   char *p;
980e27a552bSJed Brown 
981e27a552bSJed Brown   PetscFunctionBegin;
982e408995aSJed Brown   for (i=0,p=buf,left=len; i<n; i++) {
983e408995aSJed Brown     ierr = PetscSNPrintfCount(p,left,fmt,&count,x[i]);CHKERRQ(ierr);
984e27a552bSJed Brown     if (count >= left) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Insufficient space in buffer");
985e27a552bSJed Brown     left -= count;
986e27a552bSJed Brown     p += count;
987e27a552bSJed Brown     *p++ = ' ';
988e27a552bSJed Brown   }
989e27a552bSJed Brown   p[i ? 0 : -1] = 0;
990e27a552bSJed Brown   PetscFunctionReturn(0);
991e27a552bSJed Brown }
992e27a552bSJed Brown 
993e27a552bSJed Brown #undef __FUNCT__
994e27a552bSJed Brown #define __FUNCT__ "TSView_RosW"
995e27a552bSJed Brown static PetscErrorCode TSView_RosW(TS ts,PetscViewer viewer)
996e27a552bSJed Brown {
99761692a83SJed Brown   TS_RosW        *ros = (TS_RosW*)ts->data;
99861692a83SJed Brown   RosWTableau    tab  = ros->tableau;
999e27a552bSJed Brown   PetscBool      iascii;
1000e27a552bSJed Brown   PetscErrorCode ierr;
1001e27a552bSJed Brown 
1002e27a552bSJed Brown   PetscFunctionBegin;
1003e27a552bSJed Brown   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
1004e27a552bSJed Brown   if (iascii) {
100561692a83SJed Brown     const TSRosWType rostype;
1006e408995aSJed Brown     PetscInt i;
1007e408995aSJed Brown     PetscReal abscissa[512];
1008e27a552bSJed Brown     char buf[512];
100961692a83SJed Brown     ierr = TSRosWGetType(ts,&rostype);CHKERRQ(ierr);
101061692a83SJed Brown     ierr = PetscViewerASCIIPrintf(viewer,"  Rosenbrock-W %s\n",rostype);CHKERRQ(ierr);
1011e408995aSJed Brown     ierr = PetscFormatRealArray(buf,sizeof buf,"% 8.6f",tab->s,tab->ASum);CHKERRQ(ierr);
101261692a83SJed Brown     ierr = PetscViewerASCIIPrintf(viewer,"  Abscissa of A       = %s\n",buf);CHKERRQ(ierr);
1013e408995aSJed Brown     for (i=0; i<tab->s; i++) abscissa[i] = tab->ASum[i] + tab->Gamma[i];
1014e408995aSJed Brown     ierr = PetscFormatRealArray(buf,sizeof buf,"% 8.6f",tab->s,abscissa);CHKERRQ(ierr);
1015e408995aSJed Brown     ierr = PetscViewerASCIIPrintf(viewer,"  Abscissa of A+Gamma = %s\n",buf);CHKERRQ(ierr);
1016e27a552bSJed Brown   }
1017e27a552bSJed Brown   ierr = SNESView(ts->snes,viewer);CHKERRQ(ierr);
1018e27a552bSJed Brown   PetscFunctionReturn(0);
1019e27a552bSJed Brown }
1020e27a552bSJed Brown 
1021e27a552bSJed Brown #undef __FUNCT__
1022e27a552bSJed Brown #define __FUNCT__ "TSRosWSetType"
1023e27a552bSJed Brown /*@C
102461692a83SJed Brown   TSRosWSetType - Set the type of Rosenbrock-W scheme
1025e27a552bSJed Brown 
1026e27a552bSJed Brown   Logically collective
1027e27a552bSJed Brown 
1028e27a552bSJed Brown   Input Parameter:
1029e27a552bSJed Brown +  ts - timestepping context
103061692a83SJed Brown -  rostype - type of Rosenbrock-W scheme
1031e27a552bSJed Brown 
1032020d8f30SJed Brown   Level: beginner
1033e27a552bSJed Brown 
1034020d8f30SJed Brown .seealso: TSRosWGetType(), TSROSW, TSROSW2M, TSROSW2P, TSROSWRA3PW, TSROSWRA34PW2, TSROSWRODAS3, TSROSWSANDU3, TSROSWASSP3P3S1C, TSROSWLASSP3P4S2C, TSROSWLLSSP3P4S2C, TSROSWARK3
1035e27a552bSJed Brown @*/
103661692a83SJed Brown PetscErrorCode TSRosWSetType(TS ts,const TSRosWType rostype)
1037e27a552bSJed Brown {
1038e27a552bSJed Brown   PetscErrorCode ierr;
1039e27a552bSJed Brown 
1040e27a552bSJed Brown   PetscFunctionBegin;
1041e27a552bSJed Brown   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
104261692a83SJed Brown   ierr = PetscTryMethod(ts,"TSRosWSetType_C",(TS,const TSRosWType),(ts,rostype));CHKERRQ(ierr);
1043e27a552bSJed Brown   PetscFunctionReturn(0);
1044e27a552bSJed Brown }
1045e27a552bSJed Brown 
1046e27a552bSJed Brown #undef __FUNCT__
1047e27a552bSJed Brown #define __FUNCT__ "TSRosWGetType"
1048e27a552bSJed Brown /*@C
104961692a83SJed Brown   TSRosWGetType - Get the type of Rosenbrock-W scheme
1050e27a552bSJed Brown 
1051e27a552bSJed Brown   Logically collective
1052e27a552bSJed Brown 
1053e27a552bSJed Brown   Input Parameter:
1054e27a552bSJed Brown .  ts - timestepping context
1055e27a552bSJed Brown 
1056e27a552bSJed Brown   Output Parameter:
105761692a83SJed Brown .  rostype - type of Rosenbrock-W scheme
1058e27a552bSJed Brown 
1059e27a552bSJed Brown   Level: intermediate
1060e27a552bSJed Brown 
1061e27a552bSJed Brown .seealso: TSRosWGetType()
1062e27a552bSJed Brown @*/
106361692a83SJed Brown PetscErrorCode TSRosWGetType(TS ts,const TSRosWType *rostype)
1064e27a552bSJed Brown {
1065e27a552bSJed Brown   PetscErrorCode ierr;
1066e27a552bSJed Brown 
1067e27a552bSJed Brown   PetscFunctionBegin;
1068e27a552bSJed Brown   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
106961692a83SJed Brown   ierr = PetscUseMethod(ts,"TSRosWGetType_C",(TS,const TSRosWType*),(ts,rostype));CHKERRQ(ierr);
1070e27a552bSJed Brown   PetscFunctionReturn(0);
1071e27a552bSJed Brown }
1072e27a552bSJed Brown 
1073e27a552bSJed Brown #undef __FUNCT__
107461692a83SJed Brown #define __FUNCT__ "TSRosWSetRecomputeJacobian"
1075e27a552bSJed Brown /*@C
107661692a83SJed Brown   TSRosWSetRecomputeJacobian - Set whether to recompute the Jacobian at each stage. The default is to update the Jacobian once per step.
1077e27a552bSJed Brown 
1078e27a552bSJed Brown   Logically collective
1079e27a552bSJed Brown 
1080e27a552bSJed Brown   Input Parameter:
1081e27a552bSJed Brown +  ts - timestepping context
108261692a83SJed Brown -  flg - PETSC_TRUE to recompute the Jacobian at each stage
1083e27a552bSJed Brown 
1084e27a552bSJed Brown   Level: intermediate
1085e27a552bSJed Brown 
1086e27a552bSJed Brown .seealso: TSRosWGetType()
1087e27a552bSJed Brown @*/
108861692a83SJed Brown PetscErrorCode TSRosWSetRecomputeJacobian(TS ts,PetscBool flg)
1089e27a552bSJed Brown {
1090e27a552bSJed Brown   PetscErrorCode ierr;
1091e27a552bSJed Brown 
1092e27a552bSJed Brown   PetscFunctionBegin;
1093e27a552bSJed Brown   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
109461692a83SJed Brown   ierr = PetscTryMethod(ts,"TSRosWSetRecomputeJacobian_C",(TS,PetscBool),(ts,flg));CHKERRQ(ierr);
1095e27a552bSJed Brown   PetscFunctionReturn(0);
1096e27a552bSJed Brown }
1097e27a552bSJed Brown 
1098e27a552bSJed Brown EXTERN_C_BEGIN
1099e27a552bSJed Brown #undef __FUNCT__
1100e27a552bSJed Brown #define __FUNCT__ "TSRosWGetType_RosW"
110161692a83SJed Brown PetscErrorCode  TSRosWGetType_RosW(TS ts,const TSRosWType *rostype)
1102e27a552bSJed Brown {
110361692a83SJed Brown   TS_RosW        *ros = (TS_RosW*)ts->data;
1104e27a552bSJed Brown   PetscErrorCode ierr;
1105e27a552bSJed Brown 
1106e27a552bSJed Brown   PetscFunctionBegin;
110761692a83SJed Brown   if (!ros->tableau) {ierr = TSRosWSetType(ts,TSRosWDefault);CHKERRQ(ierr);}
110861692a83SJed Brown   *rostype = ros->tableau->name;
1109e27a552bSJed Brown   PetscFunctionReturn(0);
1110e27a552bSJed Brown }
1111e27a552bSJed Brown #undef __FUNCT__
1112e27a552bSJed Brown #define __FUNCT__ "TSRosWSetType_RosW"
111361692a83SJed Brown PetscErrorCode  TSRosWSetType_RosW(TS ts,const TSRosWType rostype)
1114e27a552bSJed Brown {
111561692a83SJed Brown   TS_RosW         *ros = (TS_RosW*)ts->data;
1116e27a552bSJed Brown   PetscErrorCode  ierr;
1117e27a552bSJed Brown   PetscBool       match;
111861692a83SJed Brown   RosWTableauLink link;
1119e27a552bSJed Brown 
1120e27a552bSJed Brown   PetscFunctionBegin;
112161692a83SJed Brown   if (ros->tableau) {
112261692a83SJed Brown     ierr = PetscStrcmp(ros->tableau->name,rostype,&match);CHKERRQ(ierr);
1123e27a552bSJed Brown     if (match) PetscFunctionReturn(0);
1124e27a552bSJed Brown   }
112561692a83SJed Brown   for (link = RosWTableauList; link; link=link->next) {
112661692a83SJed Brown     ierr = PetscStrcmp(link->tab.name,rostype,&match);CHKERRQ(ierr);
1127e27a552bSJed Brown     if (match) {
1128e27a552bSJed Brown       ierr = TSReset_RosW(ts);CHKERRQ(ierr);
112961692a83SJed Brown       ros->tableau = &link->tab;
1130e27a552bSJed Brown       PetscFunctionReturn(0);
1131e27a552bSJed Brown     }
1132e27a552bSJed Brown   }
113361692a83SJed Brown   SETERRQ1(((PetscObject)ts)->comm,PETSC_ERR_ARG_UNKNOWN_TYPE,"Could not find '%s'",rostype);
1134e27a552bSJed Brown   PetscFunctionReturn(0);
1135e27a552bSJed Brown }
113661692a83SJed Brown 
1137e27a552bSJed Brown #undef __FUNCT__
113861692a83SJed Brown #define __FUNCT__ "TSRosWSetRecomputeJacobian_RosW"
113961692a83SJed Brown PetscErrorCode  TSRosWSetRecomputeJacobian_RosW(TS ts,PetscBool flg)
1140e27a552bSJed Brown {
114161692a83SJed Brown   TS_RosW *ros = (TS_RosW*)ts->data;
1142e27a552bSJed Brown 
1143e27a552bSJed Brown   PetscFunctionBegin;
114461692a83SJed Brown   ros->recompute_jacobian = flg;
1145e27a552bSJed Brown   PetscFunctionReturn(0);
1146e27a552bSJed Brown }
1147e27a552bSJed Brown EXTERN_C_END
1148e27a552bSJed Brown 
1149e27a552bSJed Brown /* ------------------------------------------------------------ */
1150e27a552bSJed Brown /*MC
1151020d8f30SJed Brown       TSROSW - ODE solver using Rosenbrock-W schemes
1152e27a552bSJed Brown 
1153e27a552bSJed Brown   These methods are intended for problems with well-separated time scales, especially when a slow scale is strongly
1154e27a552bSJed Brown   nonlinear such that it is expensive to solve with a fully implicit method. The user should provide the stiff part
1155e27a552bSJed Brown   of the equation using TSSetIFunction() and the non-stiff part with TSSetRHSFunction().
1156e27a552bSJed Brown 
1157e27a552bSJed Brown   Notes:
115861692a83SJed Brown   This method currently only works with autonomous ODE and DAE.
115961692a83SJed Brown 
116061692a83SJed Brown   Developer notes:
116161692a83SJed Brown   Rosenbrock-W methods are typically specified for autonomous ODE
116261692a83SJed Brown 
116361692a83SJed Brown $  xdot = f(x)
116461692a83SJed Brown 
116561692a83SJed Brown   by the stage equations
116661692a83SJed Brown 
116761692a83SJed Brown $  k_i = h f(x_0 + sum_j alpha_ij k_j) + h J sum_j gamma_ij k_j
116861692a83SJed Brown 
116961692a83SJed Brown   and step completion formula
117061692a83SJed Brown 
117161692a83SJed Brown $  x_1 = x_0 + sum_j b_j k_j
117261692a83SJed Brown 
117361692a83SJed Brown   with step size h and coefficients alpha_ij, gamma_ij, and b_i. Implementing the method in this form would require f(x)
117461692a83SJed Brown   and the Jacobian J to be available, in addition to the shifted matrix I - h gamma_ii J. Following Hairer and Wanner,
117561692a83SJed Brown   we define new variables for the stage equations
117661692a83SJed Brown 
117761692a83SJed Brown $  y_i = gamma_ij k_j
117861692a83SJed Brown 
117961692a83SJed Brown   The k_j can be recovered because Gamma is invertible. Let C be the lower triangular part of Gamma^{-1} and define
118061692a83SJed Brown 
118161692a83SJed Brown $  A = Alpha Gamma^{-1}, bt^T = b^T Gamma^{-i}
118261692a83SJed Brown 
118361692a83SJed Brown   to rewrite the method as
118461692a83SJed Brown 
118561692a83SJed Brown $  [M/(h gamma_ii) - J] y_i = f(x_0 + sum_j a_ij y_j) + M sum_j (c_ij/h) y_j
118661692a83SJed Brown $  x_1 = x_0 + sum_j bt_j y_j
118761692a83SJed Brown 
118861692a83SJed Brown    where we have introduced the mass matrix M. Continue by defining
118961692a83SJed Brown 
119061692a83SJed Brown $  ydot_i = 1/(h gamma_ii) y_i - sum_j (c_ij/h) y_j
119161692a83SJed Brown 
119261692a83SJed Brown    or, more compactly in tensor notation
119361692a83SJed Brown 
119461692a83SJed Brown $  Ydot = 1/h (Gamma^{-1} \otimes I) Y .
119561692a83SJed Brown 
119661692a83SJed Brown    Note that Gamma^{-1} is lower triangular. With this definition of Ydot in terms of known quantities and the current
119761692a83SJed Brown    stage y_i, the stage equations reduce to performing one Newton step (typically with a lagged Jacobian) on the
119861692a83SJed Brown    equation
119961692a83SJed Brown 
120061692a83SJed Brown $  g(x_0 + sum_j a_ij y_j + y_i, ydot_i) = 0
120161692a83SJed Brown 
120261692a83SJed Brown    with initial guess y_i = 0.
1203e27a552bSJed Brown 
1204e27a552bSJed Brown   Level: beginner
1205e27a552bSJed Brown 
1206020d8f30SJed Brown .seealso:  TSCreate(), TS, TSSetType(), TSRosWSetType(), TSRosWRegister()
1207e27a552bSJed Brown 
1208e27a552bSJed Brown M*/
1209e27a552bSJed Brown EXTERN_C_BEGIN
1210e27a552bSJed Brown #undef __FUNCT__
1211e27a552bSJed Brown #define __FUNCT__ "TSCreate_RosW"
1212e27a552bSJed Brown PetscErrorCode  TSCreate_RosW(TS ts)
1213e27a552bSJed Brown {
121461692a83SJed Brown   TS_RosW        *ros;
1215e27a552bSJed Brown   PetscErrorCode ierr;
1216e27a552bSJed Brown 
1217e27a552bSJed Brown   PetscFunctionBegin;
1218e27a552bSJed Brown #if !defined(PETSC_USE_DYNAMIC_LIBRARIES)
1219e27a552bSJed Brown   ierr = TSRosWInitializePackage(PETSC_NULL);CHKERRQ(ierr);
1220e27a552bSJed Brown #endif
1221e27a552bSJed Brown 
1222e27a552bSJed Brown   ts->ops->reset          = TSReset_RosW;
1223e27a552bSJed Brown   ts->ops->destroy        = TSDestroy_RosW;
1224e27a552bSJed Brown   ts->ops->view           = TSView_RosW;
1225e27a552bSJed Brown   ts->ops->setup          = TSSetUp_RosW;
1226e27a552bSJed Brown   ts->ops->step           = TSStep_RosW;
1227e27a552bSJed Brown   ts->ops->interpolate    = TSInterpolate_RosW;
12281c3436cfSJed Brown   ts->ops->evaluatestep   = TSEvaluateStep_RosW;
1229e27a552bSJed Brown   ts->ops->setfromoptions = TSSetFromOptions_RosW;
1230e27a552bSJed Brown   ts->ops->snesfunction   = SNESTSFormFunction_RosW;
1231e27a552bSJed Brown   ts->ops->snesjacobian   = SNESTSFormJacobian_RosW;
1232e27a552bSJed Brown 
123361692a83SJed Brown   ierr = PetscNewLog(ts,TS_RosW,&ros);CHKERRQ(ierr);
123461692a83SJed Brown   ts->data = (void*)ros;
1235e27a552bSJed Brown 
1236e27a552bSJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSRosWGetType_C","TSRosWGetType_RosW",TSRosWGetType_RosW);CHKERRQ(ierr);
1237e27a552bSJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSRosWSetType_C","TSRosWSetType_RosW",TSRosWSetType_RosW);CHKERRQ(ierr);
123861692a83SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSRosWSetRecomputeJacobian_C","TSRosWSetRecomputeJacobian_RosW",TSRosWSetRecomputeJacobian_RosW);CHKERRQ(ierr);
1239e27a552bSJed Brown   PetscFunctionReturn(0);
1240e27a552bSJed Brown }
1241e27a552bSJed Brown EXTERN_C_END
1242