xref: /petsc/src/ts/impls/implicit/irk/irk.c (revision 517f343b9eed35a6084b9f41ad4d1cb8771ed4e7)
1d2567f34SHong Zhang /*
2d2567f34SHong Zhang   Code for timestepping with implicit Runge-Kutta method
3d2567f34SHong Zhang 
4d2567f34SHong Zhang   Notes:
5d2567f34SHong Zhang   The general system is written as
6d2567f34SHong Zhang 
7d2567f34SHong Zhang   F(t,U,Udot) = 0
8d2567f34SHong Zhang 
9d2567f34SHong Zhang */
10d2567f34SHong Zhang #include <petsc/private/tsimpl.h>                /*I   "petscts.h"   I*/
11d2567f34SHong Zhang #include <petscdm.h>
12d2567f34SHong Zhang #include <petscdt.h>
13d2567f34SHong Zhang 
14d2567f34SHong Zhang static TSIRKType         TSIRKDefault = TSIRKGAUSS;
15d2567f34SHong Zhang static PetscBool         TSIRKRegisterAllCalled;
16d2567f34SHong Zhang static PetscBool         TSIRKPackageInitialized;
17d2567f34SHong Zhang static PetscFunctionList TSIRKList;
18d2567f34SHong Zhang 
19d2567f34SHong Zhang struct _IRKTableau{
20d2567f34SHong Zhang   PetscReal   *A,*b,*c;
21d2567f34SHong Zhang   PetscScalar *A_inv,*A_inv_rowsum,*I_s;
22d2567f34SHong Zhang   PetscReal   *binterp;   /* Dense output formula */
23d2567f34SHong Zhang };
24d2567f34SHong Zhang 
25d2567f34SHong Zhang typedef struct _IRKTableau *IRKTableau;
26d2567f34SHong Zhang 
27d2567f34SHong Zhang typedef struct {
28d2567f34SHong Zhang   char         *method_name;
29d2567f34SHong Zhang   PetscInt     order;            /* Classical approximation order of the method */
30d2567f34SHong Zhang   PetscInt     nstages;          /* Number of stages */
31d2567f34SHong Zhang   PetscBool    stiffly_accurate;
32d2567f34SHong Zhang   PetscInt     pinterp;          /* Interpolation order */
33d2567f34SHong Zhang   IRKTableau   tableau;
34d2567f34SHong Zhang   Vec          U0;               /* Backup vector */
35d2567f34SHong Zhang   Vec          Z;                /* Combined stage vector */
36d2567f34SHong Zhang   Vec          *Y;               /* States computed during the step */
37d2567f34SHong Zhang   Vec          Ydot;             /* Work vector holding time derivatives during residual evaluation */
38d2567f34SHong Zhang   Vec          U;                /* U is used to compute Ydot = shift(Y-U) */
39d2567f34SHong Zhang   Vec          *YdotI;           /* Work vectors to hold the residual evaluation */
40d2567f34SHong Zhang   Mat          TJ;               /* KAIJ matrix for the Jacobian of the combined system */
41d2567f34SHong Zhang   PetscScalar  *work;            /* Scalar work */
42d2567f34SHong Zhang   TSStepStatus status;
43d2567f34SHong Zhang   PetscBool    rebuild_completion;
44d2567f34SHong Zhang   PetscReal    ccfl;
45d2567f34SHong Zhang } TS_IRK;
46d2567f34SHong Zhang 
47d2567f34SHong Zhang /*@C
48d2567f34SHong Zhang    TSIRKTableauCreate - create the tableau for TSIRK and provide the entries
49d2567f34SHong Zhang 
50d2567f34SHong Zhang    Not Collective
51d2567f34SHong Zhang 
52d2567f34SHong Zhang    Input Parameters:
53d2567f34SHong Zhang +  ts - timestepping context
54d2567f34SHong Zhang .  nstages - number of stages, this is the dimension of the matrices below
55d2567f34SHong Zhang .  A - stage coefficients (dimension nstages*nstages, row-major)
56d2567f34SHong Zhang .  b - step completion table (dimension nstages)
57d2567f34SHong Zhang .  c - abscissa (dimension nstages)
5802024617SSatish Balay .  binterp - coefficients of the interpolation formula (dimension nstages)
59d2567f34SHong Zhang .  A_inv - inverse of A (dimension nstages*nstages, row-major)
60d2567f34SHong Zhang .  A_inv_rowsum - row sum of the inverse of A (dimension nstages)
6102024617SSatish Balay -  I_s - identity matrix (dimension nstages*nstages)
62d2567f34SHong Zhang 
63d2567f34SHong Zhang    Level: advanced
64d2567f34SHong Zhang 
65d2567f34SHong Zhang .seealso: TSIRK, TSIRKRegister()
66d2567f34SHong Zhang @*/
67d2567f34SHong Zhang PetscErrorCode TSIRKTableauCreate(TS ts,PetscInt nstages,const PetscReal *A,const PetscReal *b,const PetscReal *c,const PetscReal *binterp,const PetscScalar *A_inv,const PetscScalar *A_inv_rowsum,const PetscScalar *I_s)
68d2567f34SHong Zhang {
69d2567f34SHong Zhang   TS_IRK         *irk = (TS_IRK*)ts->data;
70d2567f34SHong Zhang   IRKTableau     tab = irk->tableau;
71d2567f34SHong Zhang   PetscErrorCode ierr;
72d2567f34SHong Zhang 
73d2567f34SHong Zhang   PetscFunctionBegin;
74d2567f34SHong Zhang   irk->order = nstages;
75d2567f34SHong Zhang   ierr = PetscMalloc3(PetscSqr(nstages),&tab->A,PetscSqr(nstages),&tab->A_inv,PetscSqr(nstages),&tab->I_s);CHKERRQ(ierr);
76d2567f34SHong Zhang   ierr = PetscMalloc4(nstages,&tab->b,nstages,&tab->c,nstages,&tab->binterp,nstages,&tab->A_inv_rowsum);CHKERRQ(ierr);
77d2567f34SHong Zhang   ierr = PetscArraycpy(tab->A,A,PetscSqr(nstages));CHKERRQ(ierr);
78d2567f34SHong Zhang   ierr = PetscArraycpy(tab->b,b,nstages);CHKERRQ(ierr);
79d2567f34SHong Zhang   ierr = PetscArraycpy(tab->c,c,nstages);CHKERRQ(ierr);
80d2567f34SHong Zhang   /* optional coefficient arrays */
81d2567f34SHong Zhang   if (binterp) {
82d2567f34SHong Zhang     ierr = PetscArraycpy(tab->binterp,binterp,nstages);CHKERRQ(ierr);
83d2567f34SHong Zhang   }
84d2567f34SHong Zhang   if (A_inv) {
85d2567f34SHong Zhang     ierr = PetscArraycpy(tab->A_inv,A_inv,PetscSqr(nstages));CHKERRQ(ierr);
86d2567f34SHong Zhang   }
87d2567f34SHong Zhang   if (A_inv_rowsum) {
88d2567f34SHong Zhang     ierr = PetscArraycpy(tab->A_inv_rowsum,A_inv_rowsum,nstages);CHKERRQ(ierr);
89d2567f34SHong Zhang   }
90d2567f34SHong Zhang   if (I_s) {
91d2567f34SHong Zhang     ierr = PetscArraycpy(tab->I_s,I_s,PetscSqr(nstages));CHKERRQ(ierr);
92d2567f34SHong Zhang   }
93d2567f34SHong Zhang   PetscFunctionReturn(0);
94d2567f34SHong Zhang }
95d2567f34SHong Zhang 
96d2567f34SHong Zhang /* Arrays should be freed with PetscFree3(A,b,c) */
97d2567f34SHong Zhang static PetscErrorCode TSIRKCreate_Gauss(TS ts)
98d2567f34SHong Zhang {
99d2567f34SHong Zhang   PetscInt       nstages;
100d2567f34SHong Zhang   PetscReal      *gauss_A_real,*gauss_b,*b,*gauss_c;
101d2567f34SHong Zhang   PetscScalar    *gauss_A,*gauss_A_inv,*gauss_A_inv_rowsum,*I_s;
102d2567f34SHong Zhang   PetscScalar    *G0,*G1;
103d2567f34SHong Zhang   PetscInt       i,j;
104d2567f34SHong Zhang   Mat            G0mat,G1mat,Amat;
105d2567f34SHong Zhang   PetscErrorCode ierr;
106d2567f34SHong Zhang 
107d2567f34SHong Zhang   PetscFunctionBegin;
108d2567f34SHong Zhang   ierr = TSIRKGetNumStages(ts,&nstages);CHKERRQ(ierr);
109d2567f34SHong Zhang   ierr = PetscMalloc3(PetscSqr(nstages),&gauss_A_real,nstages,&gauss_b,nstages,&gauss_c);CHKERRQ(ierr);
110d2567f34SHong Zhang   ierr = PetscMalloc4(PetscSqr(nstages),&gauss_A,PetscSqr(nstages),&gauss_A_inv,nstages,&gauss_A_inv_rowsum,PetscSqr(nstages),&I_s);CHKERRQ(ierr);
111d2567f34SHong Zhang   ierr = PetscMalloc3(nstages,&b,PetscSqr(nstages),&G0,PetscSqr(nstages),&G1);CHKERRQ(ierr);
112d2567f34SHong Zhang   ierr = PetscDTGaussQuadrature(nstages,0.,1.,gauss_c,b);CHKERRQ(ierr);
113d2567f34SHong Zhang   for (i=0; i<nstages; i++) gauss_b[i] = b[i]; /* copy to possibly-complex array */
114d2567f34SHong Zhang 
115d2567f34SHong Zhang   /* A^T = G0^{-1} G1 */
116d2567f34SHong Zhang   for (i=0; i<nstages; i++) {
117d2567f34SHong Zhang     for (j=0; j<nstages; j++) {
118d2567f34SHong Zhang       G0[i*nstages+j] = PetscPowRealInt(gauss_c[i],j);
119d2567f34SHong Zhang       G1[i*nstages+j] = PetscPowRealInt(gauss_c[i],j+1)/(j+1);
120d2567f34SHong Zhang     }
121d2567f34SHong Zhang   }
122d2567f34SHong Zhang   /* The arrays above are row-aligned, but we create dense matrices as the transpose */
123d2567f34SHong Zhang   ierr = MatCreateSeqDense(PETSC_COMM_SELF,nstages,nstages,G0,&G0mat);CHKERRQ(ierr);
124d2567f34SHong Zhang   ierr = MatCreateSeqDense(PETSC_COMM_SELF,nstages,nstages,G1,&G1mat);CHKERRQ(ierr);
125d2567f34SHong Zhang   ierr = MatCreateSeqDense(PETSC_COMM_SELF,nstages,nstages,gauss_A,&Amat);CHKERRQ(ierr);
126d2567f34SHong Zhang   ierr = MatLUFactor(G0mat,NULL,NULL,NULL);CHKERRQ(ierr);
127d2567f34SHong Zhang   ierr = MatMatSolve(G0mat,G1mat,Amat);CHKERRQ(ierr);
128d2567f34SHong Zhang   ierr = MatTranspose(Amat,MAT_INPLACE_MATRIX,&Amat);CHKERRQ(ierr);
129d2567f34SHong Zhang   for (i=0; i<nstages; i++)
130d2567f34SHong Zhang     for (j=0; j<nstages; j++)
131d2567f34SHong Zhang       gauss_A_real[i*nstages+j] = PetscRealPart(gauss_A[i*nstages+j]);
132d2567f34SHong Zhang 
133d2567f34SHong Zhang   ierr = MatDestroy(&G0mat);CHKERRQ(ierr);
134d2567f34SHong Zhang   ierr = MatDestroy(&G1mat);CHKERRQ(ierr);
135d2567f34SHong Zhang   ierr = MatDestroy(&Amat);CHKERRQ(ierr);
136d2567f34SHong Zhang   ierr = PetscFree3(b,G0,G1);CHKERRQ(ierr);
137d2567f34SHong Zhang 
138d2567f34SHong Zhang   {/* Invert A */
139d2567f34SHong Zhang     /* PETSc does not provide a routine to calculate the inverse of a general matrix.
140d2567f34SHong Zhang      * To get the inverse of A, we form a sequential BAIJ matrix from it, consisting of a single block with block size
141d2567f34SHong Zhang      * equal to the dimension of A, and then use MatInvertBlockDiagonal(). */
142d2567f34SHong Zhang     Mat               A_baij;
143d2567f34SHong Zhang     PetscInt          idxm[1]={0},idxn[1]={0};
144d2567f34SHong Zhang     const PetscScalar *A_inv;
145d2567f34SHong Zhang 
146d2567f34SHong Zhang     ierr = MatCreateSeqBAIJ(PETSC_COMM_SELF,nstages,nstages,nstages,1,NULL,&A_baij);CHKERRQ(ierr);
147d2567f34SHong Zhang     ierr = MatSetOption(A_baij,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
148d2567f34SHong Zhang     ierr = MatSetValuesBlocked(A_baij,1,idxm,1,idxn,gauss_A,INSERT_VALUES);CHKERRQ(ierr);
149d2567f34SHong Zhang     ierr = MatAssemblyBegin(A_baij,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
150d2567f34SHong Zhang     ierr = MatAssemblyEnd(A_baij,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
151d2567f34SHong Zhang     ierr = MatInvertBlockDiagonal(A_baij,&A_inv);CHKERRQ(ierr);
152d2567f34SHong Zhang     ierr = PetscMemcpy(gauss_A_inv,A_inv,nstages*nstages*sizeof(PetscScalar));CHKERRQ(ierr);
153d2567f34SHong Zhang     ierr = MatDestroy(&A_baij);CHKERRQ(ierr);
154d2567f34SHong Zhang   }
155d2567f34SHong Zhang 
156d2567f34SHong Zhang   /* Compute row sums A_inv_rowsum and identity I_s */
157d2567f34SHong Zhang   for (i=0; i<nstages; i++) {
158d2567f34SHong Zhang     gauss_A_inv_rowsum[i] = 0;
159d2567f34SHong Zhang     for (j=0; j<nstages; j++) {
160d2567f34SHong Zhang       gauss_A_inv_rowsum[i] += gauss_A_inv[i+nstages*j];
161d2567f34SHong Zhang       I_s[i+nstages*j] = 1.*(i == j);
162d2567f34SHong Zhang     }
163d2567f34SHong Zhang   }
164d2567f34SHong Zhang   ierr = TSIRKTableauCreate(ts,nstages,gauss_A_real,gauss_b,gauss_c,NULL,gauss_A_inv,gauss_A_inv_rowsum,I_s);CHKERRQ(ierr);
165d2567f34SHong Zhang   ierr = PetscFree3(gauss_A_real,gauss_b,gauss_c);CHKERRQ(ierr);
166d2567f34SHong Zhang   ierr = PetscFree4(gauss_A,gauss_A_inv,gauss_A_inv_rowsum,I_s);CHKERRQ(ierr);
167d2567f34SHong Zhang   PetscFunctionReturn(0);
168d2567f34SHong Zhang }
169d2567f34SHong Zhang 
170d2567f34SHong Zhang /*@C
171d2567f34SHong Zhang    TSIRKRegister -  adds a TSIRK implementation
172d2567f34SHong Zhang 
173d2567f34SHong Zhang    Not Collective
174d2567f34SHong Zhang 
175d2567f34SHong Zhang    Input Parameters:
176d2567f34SHong Zhang +  sname - name of user-defined IRK scheme
177d2567f34SHong Zhang -  function - function to create method context
178d2567f34SHong Zhang 
179d2567f34SHong Zhang    Notes:
180d2567f34SHong Zhang    TSIRKRegister() may be called multiple times to add several user-defined families.
181d2567f34SHong Zhang 
182d2567f34SHong Zhang    Sample usage:
183d2567f34SHong Zhang .vb
184d2567f34SHong Zhang    TSIRKRegister("my_scheme",MySchemeCreate);
185d2567f34SHong Zhang .ve
186d2567f34SHong Zhang 
187d2567f34SHong Zhang    Then, your scheme can be chosen with the procedural interface via
188d2567f34SHong Zhang $     TSIRKSetType(ts,"my_scheme")
189d2567f34SHong Zhang    or at runtime via the option
190d2567f34SHong Zhang $     -ts_irk_type my_scheme
191d2567f34SHong Zhang 
192d2567f34SHong Zhang    Level: advanced
193d2567f34SHong Zhang 
194d2567f34SHong Zhang .seealso: TSIRKRegisterAll()
195d2567f34SHong Zhang @*/
196d2567f34SHong Zhang PetscErrorCode TSIRKRegister(const char sname[],PetscErrorCode (*function)(TS))
197d2567f34SHong Zhang {
198d2567f34SHong Zhang   PetscErrorCode ierr;
199d2567f34SHong Zhang 
200d2567f34SHong Zhang   PetscFunctionBegin;
201d2567f34SHong Zhang   ierr = TSIRKInitializePackage();CHKERRQ(ierr);
202d2567f34SHong Zhang   ierr = PetscFunctionListAdd(&TSIRKList,sname,function);CHKERRQ(ierr);
203d2567f34SHong Zhang   PetscFunctionReturn(0);
204d2567f34SHong Zhang }
205d2567f34SHong Zhang 
206d2567f34SHong Zhang /*@C
207d2567f34SHong Zhang   TSIRKRegisterAll - Registers all of the implicit Runge-Kutta methods in TSIRK
208d2567f34SHong Zhang 
209d2567f34SHong Zhang   Not Collective, but should be called by all processes which will need the schemes to be registered
210d2567f34SHong Zhang 
211d2567f34SHong Zhang   Level: advanced
212d2567f34SHong Zhang 
213d2567f34SHong Zhang .seealso:  TSIRKRegisterDestroy()
214d2567f34SHong Zhang @*/
215d2567f34SHong Zhang PetscErrorCode TSIRKRegisterAll(void)
216d2567f34SHong Zhang {
217d2567f34SHong Zhang   PetscErrorCode ierr;
218d2567f34SHong Zhang 
219d2567f34SHong Zhang   PetscFunctionBegin;
220d2567f34SHong Zhang   if (TSIRKRegisterAllCalled) PetscFunctionReturn(0);
221d2567f34SHong Zhang   TSIRKRegisterAllCalled = PETSC_TRUE;
222d2567f34SHong Zhang 
223d2567f34SHong Zhang   ierr = TSIRKRegister(TSIRKGAUSS,TSIRKCreate_Gauss);CHKERRQ(ierr);
224d2567f34SHong Zhang   PetscFunctionReturn(0);
225d2567f34SHong Zhang }
226d2567f34SHong Zhang 
227d2567f34SHong Zhang /*@C
228d2567f34SHong Zhang    TSIRKRegisterDestroy - Frees the list of schemes that were registered by TSIRKRegister().
229d2567f34SHong Zhang 
230d2567f34SHong Zhang    Not Collective
231d2567f34SHong Zhang 
232d2567f34SHong Zhang    Level: advanced
233d2567f34SHong Zhang 
234d2567f34SHong Zhang .seealso: TSIRKRegister(), TSIRKRegisterAll()
235d2567f34SHong Zhang @*/
236d2567f34SHong Zhang PetscErrorCode TSIRKRegisterDestroy(void)
237d2567f34SHong Zhang {
238d2567f34SHong Zhang   PetscFunctionBegin;
239d2567f34SHong Zhang   TSIRKRegisterAllCalled = PETSC_FALSE;
240d2567f34SHong Zhang   PetscFunctionReturn(0);
241d2567f34SHong Zhang }
242d2567f34SHong Zhang 
243d2567f34SHong Zhang /*@C
244d2567f34SHong Zhang   TSIRKInitializePackage - This function initializes everything in the TSIRK package. It is called
245d2567f34SHong Zhang   from TSInitializePackage().
246d2567f34SHong Zhang 
247d2567f34SHong Zhang   Level: developer
248d2567f34SHong Zhang 
249d2567f34SHong Zhang .seealso: PetscInitialize()
250d2567f34SHong Zhang @*/
251d2567f34SHong Zhang PetscErrorCode TSIRKInitializePackage(void)
252d2567f34SHong Zhang {
253d2567f34SHong Zhang   PetscErrorCode ierr;
254d2567f34SHong Zhang 
255d2567f34SHong Zhang   PetscFunctionBegin;
256d2567f34SHong Zhang   if (TSIRKPackageInitialized) PetscFunctionReturn(0);
257d2567f34SHong Zhang   TSIRKPackageInitialized = PETSC_TRUE;
258d2567f34SHong Zhang   ierr = TSIRKRegisterAll();CHKERRQ(ierr);
259d2567f34SHong Zhang   ierr = PetscRegisterFinalize(TSIRKFinalizePackage);CHKERRQ(ierr);
260d2567f34SHong Zhang   PetscFunctionReturn(0);
261d2567f34SHong Zhang }
262d2567f34SHong Zhang 
263d2567f34SHong Zhang /*@C
264d2567f34SHong Zhang   TSIRKFinalizePackage - This function destroys everything in the TSIRK package. It is
265d2567f34SHong Zhang   called from PetscFinalize().
266d2567f34SHong Zhang 
267d2567f34SHong Zhang   Level: developer
268d2567f34SHong Zhang 
269d2567f34SHong Zhang .seealso: PetscFinalize()
270d2567f34SHong Zhang @*/
271d2567f34SHong Zhang PetscErrorCode TSIRKFinalizePackage(void)
272d2567f34SHong Zhang {
273d2567f34SHong Zhang   PetscErrorCode ierr;
274d2567f34SHong Zhang 
275d2567f34SHong Zhang   PetscFunctionBegin;
276d2567f34SHong Zhang   ierr = PetscFunctionListDestroy(&TSIRKList);CHKERRQ(ierr);
277d2567f34SHong Zhang   TSIRKPackageInitialized = PETSC_FALSE;
278d2567f34SHong Zhang   PetscFunctionReturn(0);
279d2567f34SHong Zhang }
280d2567f34SHong Zhang 
281d2567f34SHong Zhang /*
282d2567f34SHong Zhang  This function can be called before or after ts->vec_sol has been updated.
283d2567f34SHong Zhang */
284d2567f34SHong Zhang static PetscErrorCode TSEvaluateStep_IRK(TS ts,PetscInt order,Vec U,PetscBool *done)
285d2567f34SHong Zhang {
286d2567f34SHong Zhang   TS_IRK         *irk = (TS_IRK*)ts->data;
287d2567f34SHong Zhang   IRKTableau     tab = irk->tableau;
288d2567f34SHong Zhang   Vec            *YdotI = irk->YdotI;
289d2567f34SHong Zhang   PetscScalar    *w = irk->work;
290d2567f34SHong Zhang   PetscReal      h;
291d2567f34SHong Zhang   PetscInt       j;
292d2567f34SHong Zhang   PetscErrorCode ierr;
293d2567f34SHong Zhang 
294d2567f34SHong Zhang   PetscFunctionBegin;
295d2567f34SHong Zhang   switch (irk->status) {
296d2567f34SHong Zhang   case TS_STEP_INCOMPLETE:
297d2567f34SHong Zhang   case TS_STEP_PENDING:
298d2567f34SHong Zhang     h = ts->time_step; break;
299d2567f34SHong Zhang   case TS_STEP_COMPLETE:
300d2567f34SHong Zhang     h = ts->ptime - ts->ptime_prev; break;
301d2567f34SHong Zhang   default: SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_PLIB,"Invalid TSStepStatus");
302d2567f34SHong Zhang   }
303d2567f34SHong Zhang 
304d2567f34SHong Zhang   ierr = VecCopy(ts->vec_sol,U);CHKERRQ(ierr);
305d2567f34SHong Zhang   for (j=0; j<irk->nstages; j++) w[j] = h*tab->b[j];
306d2567f34SHong Zhang   ierr = VecMAXPY(U,irk->nstages,w,YdotI);CHKERRQ(ierr);
307d2567f34SHong Zhang   PetscFunctionReturn(0);
308d2567f34SHong Zhang }
309d2567f34SHong Zhang 
310d2567f34SHong Zhang static PetscErrorCode TSRollBack_IRK(TS ts)
311d2567f34SHong Zhang {
312d2567f34SHong Zhang   TS_IRK         *irk = (TS_IRK*)ts->data;
313d2567f34SHong Zhang   PetscErrorCode ierr;
314d2567f34SHong Zhang 
315d2567f34SHong Zhang   PetscFunctionBegin;
316d2567f34SHong Zhang   ierr = VecCopy(irk->U0,ts->vec_sol);CHKERRQ(ierr);
317d2567f34SHong Zhang   PetscFunctionReturn(0);
318d2567f34SHong Zhang }
319d2567f34SHong Zhang 
320d2567f34SHong Zhang static PetscErrorCode TSStep_IRK(TS ts)
321d2567f34SHong Zhang {
322d2567f34SHong Zhang   TS_IRK          *irk = (TS_IRK*)ts->data;
323d2567f34SHong Zhang   IRKTableau      tab = irk->tableau;
324d2567f34SHong Zhang   PetscScalar     *A_inv = tab->A_inv,*A_inv_rowsum = tab->A_inv_rowsum;
325d2567f34SHong Zhang   const PetscInt  nstages = irk->nstages;
326d2567f34SHong Zhang   SNES            snes;
327d2567f34SHong Zhang   PetscInt        i,j,its,lits,bs;
328d2567f34SHong Zhang   TSAdapt         adapt;
329d2567f34SHong Zhang   PetscInt        rejections = 0;
330d2567f34SHong Zhang   PetscBool       accept = PETSC_TRUE;
331d2567f34SHong Zhang   PetscReal       next_time_step = ts->time_step;
332d2567f34SHong Zhang   PetscErrorCode  ierr;
333d2567f34SHong Zhang 
334d2567f34SHong Zhang   PetscFunctionBegin;
335d2567f34SHong Zhang   if (!ts->steprollback) {
336d2567f34SHong Zhang     ierr = VecCopy(ts->vec_sol,irk->U0);CHKERRQ(ierr);
337d2567f34SHong Zhang   }
338d2567f34SHong Zhang   ierr = VecGetBlockSize(ts->vec_sol,&bs);CHKERRQ(ierr);
339d2567f34SHong Zhang   for (i=0; i<nstages; i++) {
340d2567f34SHong Zhang     ierr = VecStrideScatter(ts->vec_sol,i*bs,irk->Z,INSERT_VALUES);CHKERRQ(ierr);
341d2567f34SHong Zhang   }
342d2567f34SHong Zhang 
343d2567f34SHong Zhang   irk->status = TS_STEP_INCOMPLETE;
344d2567f34SHong Zhang   while (!ts->reason && irk->status != TS_STEP_COMPLETE) {
345d2567f34SHong Zhang     ierr = VecCopy(ts->vec_sol,irk->U);CHKERRQ(ierr);
346d2567f34SHong Zhang     ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
347d2567f34SHong Zhang     ierr = SNESSolve(snes,NULL,irk->Z);CHKERRQ(ierr);
348d2567f34SHong Zhang     ierr = SNESGetIterationNumber(snes,&its);CHKERRQ(ierr);
349d2567f34SHong Zhang     ierr = SNESGetLinearSolveIterations(snes,&lits);CHKERRQ(ierr);
350d2567f34SHong Zhang     ts->snes_its += its; ts->ksp_its += lits;
351d2567f34SHong Zhang     ierr = VecStrideGatherAll(irk->Z,irk->Y,INSERT_VALUES);CHKERRQ(ierr);
352d2567f34SHong Zhang     for (i=0; i<nstages; i++) {
353d2567f34SHong Zhang       ierr = VecZeroEntries(irk->YdotI[i]);CHKERRQ(ierr);
354d2567f34SHong Zhang       for (j=0; j<nstages; j++) {
355d2567f34SHong Zhang         ierr = VecAXPY(irk->YdotI[i],A_inv[i+j*nstages]/ts->time_step,irk->Y[j]);CHKERRQ(ierr);
356d2567f34SHong Zhang       }
357d2567f34SHong Zhang       ierr = VecAXPY(irk->YdotI[i],-A_inv_rowsum[i]/ts->time_step,irk->U);CHKERRQ(ierr);
358d2567f34SHong Zhang     }
359d2567f34SHong Zhang     irk->status = TS_STEP_INCOMPLETE;
360d2567f34SHong Zhang     ierr = TSEvaluateStep_IRK(ts,irk->order,ts->vec_sol,NULL);CHKERRQ(ierr);
361d2567f34SHong Zhang     irk->status = TS_STEP_PENDING;
362d2567f34SHong Zhang     ierr = TSGetAdapt(ts,&adapt);CHKERRQ(ierr);
363d2567f34SHong Zhang     ierr = TSAdaptChoose(adapt,ts,ts->time_step,NULL,&next_time_step,&accept);CHKERRQ(ierr);
364d2567f34SHong Zhang     irk->status = accept ? TS_STEP_COMPLETE : TS_STEP_INCOMPLETE;
365d2567f34SHong Zhang     if (!accept) {
366d2567f34SHong Zhang       ierr = TSRollBack_IRK(ts);CHKERRQ(ierr);
367d2567f34SHong Zhang       ts->time_step = next_time_step;
368d2567f34SHong Zhang       goto reject_step;
369d2567f34SHong Zhang     }
370d2567f34SHong Zhang 
371d2567f34SHong Zhang     ts->ptime += ts->time_step;
372d2567f34SHong Zhang     ts->time_step = next_time_step;
373d2567f34SHong Zhang     break;
374d2567f34SHong Zhang   reject_step:
375d2567f34SHong Zhang     ts->reject++; accept = PETSC_FALSE;
376d2567f34SHong Zhang     if (!ts->reason && ++rejections > ts->max_reject && ts->max_reject >= 0) {
377d2567f34SHong Zhang       ts->reason = TS_DIVERGED_STEP_REJECTED;
378d2567f34SHong Zhang       ierr = PetscInfo2(ts,"Step=%D, step rejections %D greater than current TS allowed, stopping solve\n",ts->steps,rejections);CHKERRQ(ierr);
379d2567f34SHong Zhang     }
380d2567f34SHong Zhang   }
381d2567f34SHong Zhang   PetscFunctionReturn(0);
382d2567f34SHong Zhang }
383d2567f34SHong Zhang 
384d2567f34SHong Zhang static PetscErrorCode TSInterpolate_IRK(TS ts,PetscReal itime,Vec U)
385d2567f34SHong Zhang {
386d2567f34SHong Zhang   TS_IRK          *irk = (TS_IRK*)ts->data;
387d2567f34SHong Zhang   PetscInt        nstages = irk->nstages,pinterp = irk->pinterp,i,j;
388d2567f34SHong Zhang   PetscReal       h;
389d2567f34SHong Zhang   PetscReal       tt,t;
390d2567f34SHong Zhang   PetscScalar     *bt;
391d2567f34SHong Zhang   const PetscReal *B = irk->tableau->binterp;
392d2567f34SHong Zhang   PetscErrorCode  ierr;
393d2567f34SHong Zhang 
394d2567f34SHong Zhang   PetscFunctionBegin;
395d2567f34SHong Zhang   if (!B) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSIRK %s does not have an interpolation formula",irk->method_name);
396d2567f34SHong Zhang   switch (irk->status) {
397d2567f34SHong Zhang   case TS_STEP_INCOMPLETE:
398d2567f34SHong Zhang   case TS_STEP_PENDING:
399d2567f34SHong Zhang     h = ts->time_step;
400d2567f34SHong Zhang     t = (itime - ts->ptime)/h;
401d2567f34SHong Zhang     break;
402d2567f34SHong Zhang   case TS_STEP_COMPLETE:
403d2567f34SHong Zhang     h = ts->ptime - ts->ptime_prev;
404d2567f34SHong Zhang     t = (itime - ts->ptime)/h + 1; /* In the interval [0,1] */
405d2567f34SHong Zhang     break;
406d2567f34SHong Zhang   default: SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_PLIB,"Invalid TSStepStatus");
407d2567f34SHong Zhang   }
408d2567f34SHong Zhang   ierr = PetscMalloc1(nstages,&bt);CHKERRQ(ierr);
409d2567f34SHong Zhang   for (i=0; i<nstages; i++) bt[i] = 0;
410d2567f34SHong Zhang   for (j=0,tt=t; j<pinterp; j++,tt*=t) {
411d2567f34SHong Zhang     for (i=0; i<nstages; i++) {
412d2567f34SHong Zhang       bt[i] += h * B[i*pinterp+j] * tt;
413d2567f34SHong Zhang     }
414d2567f34SHong Zhang   }
415d2567f34SHong Zhang   ierr = VecMAXPY(U,nstages,bt,irk->YdotI);CHKERRQ(ierr);
416d2567f34SHong Zhang   PetscFunctionReturn(0);
417d2567f34SHong Zhang }
418d2567f34SHong Zhang 
419d2567f34SHong Zhang static PetscErrorCode TSIRKTableauReset(TS ts)
420d2567f34SHong Zhang {
421d2567f34SHong Zhang   TS_IRK         *irk = (TS_IRK*)ts->data;
422d2567f34SHong Zhang   IRKTableau     tab = irk->tableau;
423d2567f34SHong Zhang   PetscErrorCode ierr;
424d2567f34SHong Zhang 
425d2567f34SHong Zhang   PetscFunctionBegin;
426d2567f34SHong Zhang   if (!tab) PetscFunctionReturn(0);
427d2567f34SHong Zhang   ierr = PetscFree3(tab->A,tab->A_inv,tab->I_s);CHKERRQ(ierr);
428d2567f34SHong Zhang   ierr = PetscFree4(tab->b,tab->c,tab->binterp,tab->A_inv_rowsum);CHKERRQ(ierr);
429d2567f34SHong Zhang   PetscFunctionReturn(0);
430d2567f34SHong Zhang }
431d2567f34SHong Zhang 
432d2567f34SHong Zhang static PetscErrorCode TSReset_IRK(TS ts)
433d2567f34SHong Zhang {
434d2567f34SHong Zhang   TS_IRK         *irk = (TS_IRK*)ts->data;
435d2567f34SHong Zhang   PetscErrorCode ierr;
436d2567f34SHong Zhang 
437d2567f34SHong Zhang   PetscFunctionBegin;
438d2567f34SHong Zhang   ierr = TSIRKTableauReset(ts);CHKERRQ(ierr);
439d2567f34SHong Zhang   if (irk->tableau) {
440d2567f34SHong Zhang     ierr = PetscFree(irk->tableau);CHKERRQ(ierr);
441d2567f34SHong Zhang   }
442d2567f34SHong Zhang   if (irk->method_name) {
443d2567f34SHong Zhang     ierr = PetscFree(irk->method_name);CHKERRQ(ierr);
444d2567f34SHong Zhang   }
445d2567f34SHong Zhang   if (irk->work) {
446d2567f34SHong Zhang     ierr = PetscFree(irk->work);CHKERRQ(ierr);
447d2567f34SHong Zhang   }
448d2567f34SHong Zhang   ierr = VecDestroyVecs(irk->nstages,&irk->Y);CHKERRQ(ierr);
449d2567f34SHong Zhang   ierr = VecDestroyVecs(irk->nstages,&irk->YdotI);CHKERRQ(ierr);
450d2567f34SHong Zhang   ierr = VecDestroy(&irk->Ydot);CHKERRQ(ierr);
451d2567f34SHong Zhang   ierr = VecDestroy(&irk->Z);CHKERRQ(ierr);
452d2567f34SHong Zhang   ierr = VecDestroy(&irk->U);CHKERRQ(ierr);
453d2567f34SHong Zhang   ierr = VecDestroy(&irk->U0);CHKERRQ(ierr);
454d2567f34SHong Zhang   ierr = MatDestroy(&irk->TJ);CHKERRQ(ierr);
455d2567f34SHong Zhang   PetscFunctionReturn(0);
456d2567f34SHong Zhang }
457d2567f34SHong Zhang 
458d2567f34SHong Zhang static PetscErrorCode TSIRKGetVecs(TS ts,DM dm,Vec *U)
459d2567f34SHong Zhang {
460d2567f34SHong Zhang   TS_IRK         *irk = (TS_IRK*)ts->data;
461d2567f34SHong Zhang   PetscErrorCode ierr;
462d2567f34SHong Zhang 
463d2567f34SHong Zhang   PetscFunctionBegin;
464d2567f34SHong Zhang   if (U) {
465d2567f34SHong Zhang     if (dm && dm != ts->dm) {
466d2567f34SHong Zhang       ierr = DMGetNamedGlobalVector(dm,"TSIRK_U",U);CHKERRQ(ierr);
467d2567f34SHong Zhang     } else *U = irk->U;
468d2567f34SHong Zhang   }
469d2567f34SHong Zhang   PetscFunctionReturn(0);
470d2567f34SHong Zhang }
471d2567f34SHong Zhang 
472d2567f34SHong Zhang static PetscErrorCode TSIRKRestoreVecs(TS ts,DM dm,Vec *U)
473d2567f34SHong Zhang {
474d2567f34SHong Zhang   PetscErrorCode ierr;
475d2567f34SHong Zhang 
476d2567f34SHong Zhang   PetscFunctionBegin;
477d2567f34SHong Zhang   if (U) {
478d2567f34SHong Zhang     if (dm && dm != ts->dm) {
479d2567f34SHong Zhang       ierr = DMRestoreNamedGlobalVector(dm,"TSIRK_U",U);CHKERRQ(ierr);
480d2567f34SHong Zhang     }
481d2567f34SHong Zhang   }
482d2567f34SHong Zhang   PetscFunctionReturn(0);
483d2567f34SHong Zhang }
484d2567f34SHong Zhang 
485d2567f34SHong Zhang /*
486d2567f34SHong Zhang   This defines the nonlinear equations that is to be solved with SNES
487d2567f34SHong Zhang     G[e\otimes t + C*dt, Z, Zdot] = 0
488d2567f34SHong Zhang     Zdot = (In \otimes S)*Z - (In \otimes Se) U
489d2567f34SHong Zhang   where S = 1/(dt*A)
490d2567f34SHong Zhang */
491d2567f34SHong Zhang static PetscErrorCode SNESTSFormFunction_IRK(SNES snes,Vec ZC,Vec FC,TS ts)
492d2567f34SHong Zhang {
493d2567f34SHong Zhang   TS_IRK            *irk = (TS_IRK*)ts->data;
494d2567f34SHong Zhang   IRKTableau        tab  = irk->tableau;
495d2567f34SHong Zhang   const PetscInt    nstages = irk->nstages;
496d2567f34SHong Zhang   const PetscReal   *c = tab->c;
497d2567f34SHong Zhang   const PetscScalar *A_inv = tab->A_inv,*A_inv_rowsum = tab->A_inv_rowsum;
498d2567f34SHong Zhang   DM                dm,dmsave;
499d2567f34SHong Zhang   Vec               U,*YdotI = irk->YdotI,Ydot = irk->Ydot,*Y = irk->Y;
500d2567f34SHong Zhang   PetscReal         h = ts->time_step;
501d2567f34SHong Zhang   PetscInt          i,j;
502d2567f34SHong Zhang   PetscErrorCode    ierr;
503d2567f34SHong Zhang 
504d2567f34SHong Zhang   PetscFunctionBegin;
505d2567f34SHong Zhang   ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr);
506d2567f34SHong Zhang   ierr = TSIRKGetVecs(ts,dm,&U);CHKERRQ(ierr);
507d2567f34SHong Zhang   ierr = VecStrideGatherAll(ZC,Y,INSERT_VALUES);CHKERRQ(ierr);
508d2567f34SHong Zhang   dmsave = ts->dm;
509d2567f34SHong Zhang   ts->dm = dm;
510d2567f34SHong Zhang   for (i=0; i<nstages; i++) {
511d2567f34SHong Zhang     ierr = VecZeroEntries(Ydot);CHKERRQ(ierr);
512d2567f34SHong Zhang     for (j=0; j<nstages; j++) {
513d2567f34SHong Zhang       ierr = VecAXPY(Ydot,A_inv[j*nstages+i]/h,Y[j]);CHKERRQ(ierr);
514d2567f34SHong Zhang     }
515d2567f34SHong Zhang     ierr = VecAXPY(Ydot,-A_inv_rowsum[i]/h,U);CHKERRQ(ierr); /* Ydot = (S \otimes In)*Z - (Se \otimes In) U */
516d2567f34SHong Zhang     ierr = TSComputeIFunction(ts,ts->ptime+ts->time_step*c[i],Y[i],Ydot,YdotI[i],PETSC_FALSE);CHKERRQ(ierr);
517d2567f34SHong Zhang   }
518d2567f34SHong Zhang   ierr = VecStrideScatterAll(YdotI,FC,INSERT_VALUES);CHKERRQ(ierr);
519d2567f34SHong Zhang   ts->dm = dmsave;
520d2567f34SHong Zhang   ierr   = TSIRKRestoreVecs(ts,dm,&U);CHKERRQ(ierr);
521d2567f34SHong Zhang   PetscFunctionReturn(0);
522d2567f34SHong Zhang }
523d2567f34SHong Zhang 
524d2567f34SHong Zhang /*
525d2567f34SHong Zhang    For explicit ODE, the Jacobian is
526d2567f34SHong Zhang      JC = I_n \otimes S - J \otimes I_s
527d2567f34SHong Zhang    For DAE, the Jacobian is
528d2567f34SHong Zhang      JC = M_n \otimes S - J \otimes I_s
529d2567f34SHong Zhang */
530d2567f34SHong Zhang static PetscErrorCode SNESTSFormJacobian_IRK(SNES snes,Vec ZC,Mat JC,Mat JCpre,TS ts)
531d2567f34SHong Zhang {
532d2567f34SHong Zhang   TS_IRK          *irk = (TS_IRK*)ts->data;
533d2567f34SHong Zhang   IRKTableau      tab  = irk->tableau;
534d2567f34SHong Zhang   const PetscInt  nstages = irk->nstages;
535d2567f34SHong Zhang   const PetscReal *c = tab->c;
536d2567f34SHong Zhang   DM              dm,dmsave;
537d2567f34SHong Zhang   Vec             *Y = irk->Y,Ydot = irk->Ydot;
538d2567f34SHong Zhang   Mat             J;
539d2567f34SHong Zhang   PetscScalar     *S;
540d2567f34SHong Zhang   PetscInt        i,j,bs;
541d2567f34SHong Zhang   PetscErrorCode  ierr;
542d2567f34SHong Zhang 
543d2567f34SHong Zhang   PetscFunctionBegin;
544d2567f34SHong Zhang   ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr);
545d2567f34SHong Zhang   /* irk->Ydot has already been computed in SNESTSFormFunction_IRK (SNES guarantees this) */
546d2567f34SHong Zhang   dmsave = ts->dm;
547d2567f34SHong Zhang   ts->dm = dm;
548d2567f34SHong Zhang   ierr = VecGetBlockSize(Y[nstages-1],&bs);CHKERRQ(ierr);
549d2567f34SHong Zhang   if (ts->equation_type <= TS_EQ_ODE_EXPLICIT) { /* Support explicit formulas only */
550d2567f34SHong Zhang     ierr = VecStrideGather(ZC,(nstages-1)*bs,Y[nstages-1],INSERT_VALUES);CHKERRQ(ierr);
551d2567f34SHong Zhang     ierr = MatKAIJGetAIJ(JC,&J);CHKERRQ(ierr);
552d2567f34SHong Zhang     ierr = TSComputeIJacobian(ts,ts->ptime+ts->time_step*c[nstages-1],Y[nstages-1],Ydot,0,J,J,PETSC_FALSE);CHKERRQ(ierr);
553d2567f34SHong Zhang     ierr = MatKAIJGetS(JC,NULL,NULL,&S);CHKERRQ(ierr);
554d2567f34SHong Zhang     for (i=0; i<nstages; i++)
555d2567f34SHong Zhang       for (j=0; j<nstages; j++)
556d2567f34SHong Zhang         S[i+nstages*j] = tab->A_inv[i+nstages*j]/ts->time_step;
557d2567f34SHong Zhang     ierr = MatKAIJRestoreS(JC,&S);CHKERRQ(ierr);
558d2567f34SHong Zhang   } else
559d2567f34SHong Zhang     SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSIRK %s does not support implicit formula",irk->method_name); /* ToDo: need the mass matrix for DAE  */
560d2567f34SHong Zhang   ts->dm = dmsave;
561d2567f34SHong Zhang   PetscFunctionReturn(0);
562d2567f34SHong Zhang }
563d2567f34SHong Zhang 
564d2567f34SHong Zhang static PetscErrorCode DMCoarsenHook_TSIRK(DM fine,DM coarse,void *ctx)
565d2567f34SHong Zhang {
566d2567f34SHong Zhang   PetscFunctionBegin;
567d2567f34SHong Zhang   PetscFunctionReturn(0);
568d2567f34SHong Zhang }
569d2567f34SHong Zhang 
570d2567f34SHong Zhang static PetscErrorCode DMRestrictHook_TSIRK(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse,void *ctx)
571d2567f34SHong Zhang {
572d2567f34SHong Zhang   TS             ts = (TS)ctx;
573d2567f34SHong Zhang   Vec            U,U_c;
574d2567f34SHong Zhang   PetscErrorCode ierr;
575d2567f34SHong Zhang 
576d2567f34SHong Zhang   PetscFunctionBegin;
577d2567f34SHong Zhang   ierr = TSIRKGetVecs(ts,fine,&U);CHKERRQ(ierr);
578d2567f34SHong Zhang   ierr = TSIRKGetVecs(ts,coarse,&U_c);CHKERRQ(ierr);
579d2567f34SHong Zhang   ierr = MatRestrict(restrct,U,U_c);CHKERRQ(ierr);
580d2567f34SHong Zhang   ierr = VecPointwiseMult(U_c,rscale,U_c);CHKERRQ(ierr);
581d2567f34SHong Zhang   ierr = TSIRKRestoreVecs(ts,fine,&U);CHKERRQ(ierr);
582d2567f34SHong Zhang   ierr = TSIRKRestoreVecs(ts,coarse,&U_c);CHKERRQ(ierr);
583d2567f34SHong Zhang   PetscFunctionReturn(0);
584d2567f34SHong Zhang }
585d2567f34SHong Zhang 
586d2567f34SHong Zhang static PetscErrorCode DMSubDomainHook_TSIRK(DM dm,DM subdm,void *ctx)
587d2567f34SHong Zhang {
588d2567f34SHong Zhang   PetscFunctionBegin;
589d2567f34SHong Zhang   PetscFunctionReturn(0);
590d2567f34SHong Zhang }
591d2567f34SHong Zhang 
592d2567f34SHong Zhang static PetscErrorCode DMSubDomainRestrictHook_TSIRK(DM dm,VecScatter gscat,VecScatter lscat,DM subdm,void *ctx)
593d2567f34SHong Zhang {
594d2567f34SHong Zhang   TS             ts = (TS)ctx;
595d2567f34SHong Zhang   Vec            U,U_c;
596d2567f34SHong Zhang   PetscErrorCode ierr;
597d2567f34SHong Zhang 
598d2567f34SHong Zhang   PetscFunctionBegin;
599d2567f34SHong Zhang   ierr = TSIRKGetVecs(ts,dm,&U);CHKERRQ(ierr);
600d2567f34SHong Zhang   ierr = TSIRKGetVecs(ts,subdm,&U_c);CHKERRQ(ierr);
601d2567f34SHong Zhang 
602d2567f34SHong Zhang   ierr = VecScatterBegin(gscat,U,U_c,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
603d2567f34SHong Zhang   ierr = VecScatterEnd(gscat,U,U_c,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
604d2567f34SHong Zhang 
605d2567f34SHong Zhang   ierr = TSIRKRestoreVecs(ts,dm,&U);CHKERRQ(ierr);
606d2567f34SHong Zhang   ierr = TSIRKRestoreVecs(ts,subdm,&U_c);CHKERRQ(ierr);
607d2567f34SHong Zhang   PetscFunctionReturn(0);
608d2567f34SHong Zhang }
609d2567f34SHong Zhang 
610d2567f34SHong Zhang static PetscErrorCode TSSetUp_IRK(TS ts)
611d2567f34SHong Zhang {
612d2567f34SHong Zhang   TS_IRK         *irk = (TS_IRK*)ts->data;
613d2567f34SHong Zhang   IRKTableau     tab = irk->tableau;
614d2567f34SHong Zhang   DM             dm;
615d2567f34SHong Zhang   Mat            J;
616d2567f34SHong Zhang   Vec            R;
617d2567f34SHong Zhang   const PetscInt nstages = irk->nstages;
618d2567f34SHong Zhang   PetscInt       vsize,bs;
619d2567f34SHong Zhang   PetscErrorCode ierr;
620d2567f34SHong Zhang 
621d2567f34SHong Zhang   PetscFunctionBegin;
622d2567f34SHong Zhang   if (!irk->work) {
623d2567f34SHong Zhang     ierr = PetscMalloc1(irk->nstages,&irk->work);CHKERRQ(ierr);
624d2567f34SHong Zhang   }
625d2567f34SHong Zhang   if (!irk->Y) {
626d2567f34SHong Zhang     ierr = VecDuplicateVecs(ts->vec_sol,irk->nstages,&irk->Y);CHKERRQ(ierr);
627d2567f34SHong Zhang   }
628d2567f34SHong Zhang   if (!irk->YdotI) {
629d2567f34SHong Zhang     ierr = VecDuplicateVecs(ts->vec_sol,irk->nstages,&irk->YdotI);CHKERRQ(ierr);
630d2567f34SHong Zhang   }
631d2567f34SHong Zhang   if (!irk->Ydot) {
632d2567f34SHong Zhang     ierr = VecDuplicate(ts->vec_sol,&irk->Ydot);CHKERRQ(ierr);
633d2567f34SHong Zhang   }
634d2567f34SHong Zhang   if (!irk->U) {
635d2567f34SHong Zhang     ierr = VecDuplicate(ts->vec_sol,&irk->U);CHKERRQ(ierr);
636d2567f34SHong Zhang   }
637d2567f34SHong Zhang   if (!irk->U0) {
638d2567f34SHong Zhang     ierr = VecDuplicate(ts->vec_sol,&irk->U0);CHKERRQ(ierr);
639d2567f34SHong Zhang   }
640d2567f34SHong Zhang   if (!irk->Z) {
641d2567f34SHong Zhang     ierr = VecCreate(PetscObjectComm((PetscObject)ts->vec_sol),&irk->Z);CHKERRQ(ierr);
642d2567f34SHong Zhang     ierr = VecGetSize(ts->vec_sol,&vsize);CHKERRQ(ierr);
643d2567f34SHong Zhang     ierr = VecSetSizes(irk->Z,PETSC_DECIDE,vsize*irk->nstages);CHKERRQ(ierr);
644d2567f34SHong Zhang     ierr = VecGetBlockSize(ts->vec_sol,&bs);CHKERRQ(ierr);
645d2567f34SHong Zhang     ierr = VecSetBlockSize(irk->Z,irk->nstages*bs);CHKERRQ(ierr);
646d2567f34SHong Zhang     ierr = VecSetFromOptions(irk->Z);CHKERRQ(ierr);
647d2567f34SHong Zhang   }
648d2567f34SHong Zhang   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
649d2567f34SHong Zhang   ierr = DMCoarsenHookAdd(dm,DMCoarsenHook_TSIRK,DMRestrictHook_TSIRK,ts);CHKERRQ(ierr);
650d2567f34SHong Zhang   ierr = DMSubDomainHookAdd(dm,DMSubDomainHook_TSIRK,DMSubDomainRestrictHook_TSIRK,ts);CHKERRQ(ierr);
651d2567f34SHong Zhang 
652d2567f34SHong Zhang   ierr = TSGetSNES(ts,&ts->snes);CHKERRQ(ierr);
653d2567f34SHong Zhang   ierr = VecDuplicate(irk->Z,&R);CHKERRQ(ierr);
654d2567f34SHong Zhang   ierr = SNESSetFunction(ts->snes,R,SNESTSFormFunction,ts);CHKERRQ(ierr);
655d2567f34SHong Zhang   ierr = SNESGetJacobian(ts->snes,&J,NULL,NULL,NULL);CHKERRQ(ierr);
656d2567f34SHong Zhang   if (!irk->TJ) {
657d2567f34SHong Zhang     /* Create the KAIJ matrix for solving the stages */
658d2567f34SHong Zhang     ierr = MatCreateKAIJ(J,nstages,nstages,tab->A_inv,tab->I_s,&irk->TJ);CHKERRQ(ierr);
659d2567f34SHong Zhang   }
660d2567f34SHong Zhang   ierr = SNESSetJacobian(ts->snes,irk->TJ,irk->TJ,SNESTSFormJacobian,ts);CHKERRQ(ierr);
661d2567f34SHong Zhang   ierr = VecDestroy(&R);CHKERRQ(ierr);
662d2567f34SHong Zhang   PetscFunctionReturn(0);
663d2567f34SHong Zhang }
664d2567f34SHong Zhang 
665d2567f34SHong Zhang static PetscErrorCode TSSetFromOptions_IRK(PetscOptionItems *PetscOptionsObject,TS ts)
666d2567f34SHong Zhang {
667d2567f34SHong Zhang   TS_IRK         *irk = (TS_IRK*)ts->data;
668d2567f34SHong Zhang   char           tname[256] = TSIRKGAUSS;
669d2567f34SHong Zhang   PetscErrorCode ierr;
670d2567f34SHong Zhang 
671d2567f34SHong Zhang   PetscFunctionBegin;
672d2567f34SHong Zhang   ierr = PetscOptionsHead(PetscOptionsObject,"IRK ODE solver options");CHKERRQ(ierr);
673d2567f34SHong Zhang   {
674d2567f34SHong Zhang     PetscBool flg1,flg2;
675d2567f34SHong Zhang     ierr = PetscOptionsInt("-ts_irk_nstages","Stages of the IRK method","TSIRKSetNumStages",irk->nstages,&irk->nstages,&flg1);CHKERRQ(ierr);
676d2567f34SHong Zhang     ierr = PetscOptionsFList("-ts_irk_type","Type of IRK method","TSIRKSetType",TSIRKList,irk->method_name[0] ? irk->method_name : tname,tname,sizeof(tname),&flg2);CHKERRQ(ierr);
677d2567f34SHong Zhang     if (flg1 ||flg2 || !irk->method_name[0]) { /* Create the method tableau after nstages or method is set */
678d2567f34SHong Zhang       ierr = TSIRKSetType(ts,tname);CHKERRQ(ierr);
679d2567f34SHong Zhang     }
680d2567f34SHong Zhang   }
681d2567f34SHong Zhang   ierr = PetscOptionsTail();CHKERRQ(ierr);
682d2567f34SHong Zhang   PetscFunctionReturn(0);
683d2567f34SHong Zhang }
684d2567f34SHong Zhang 
685d2567f34SHong Zhang static PetscErrorCode TSView_IRK(TS ts,PetscViewer viewer)
686d2567f34SHong Zhang {
687d2567f34SHong Zhang   TS_IRK         *irk = (TS_IRK*)ts->data;
688d2567f34SHong Zhang   PetscBool      iascii;
689d2567f34SHong Zhang   PetscErrorCode ierr;
690d2567f34SHong Zhang 
691d2567f34SHong Zhang   PetscFunctionBegin;
692d2567f34SHong Zhang   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
693d2567f34SHong Zhang   if (iascii) {
694d2567f34SHong Zhang     IRKTableau    tab = irk->tableau;
695d2567f34SHong Zhang     TSIRKType irktype;
696d2567f34SHong Zhang     char          buf[512];
697d2567f34SHong Zhang 
698d2567f34SHong Zhang     ierr = TSIRKGetType(ts,&irktype);CHKERRQ(ierr);
699d2567f34SHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"  IRK type %s\n",irktype);CHKERRQ(ierr);
700d2567f34SHong Zhang     ierr = PetscFormatRealArray(buf,sizeof(buf),"% 8.6f",irk->nstages,tab->c);CHKERRQ(ierr);
701d2567f34SHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"  Abscissa       c = %s\n",buf);CHKERRQ(ierr);
702d2567f34SHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"Stiffly accurate: %s\n",irk->stiffly_accurate ? "yes" : "no");CHKERRQ(ierr);
703d2567f34SHong Zhang     ierr = PetscFormatRealArray(buf,sizeof(buf),"% 8.6f",PetscSqr(irk->nstages),tab->A);CHKERRQ(ierr);
704d2567f34SHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"  A coefficients       A = %s\n",buf);CHKERRQ(ierr);
705d2567f34SHong Zhang   }
706d2567f34SHong Zhang   PetscFunctionReturn(0);
707d2567f34SHong Zhang }
708d2567f34SHong Zhang 
709d2567f34SHong Zhang static PetscErrorCode TSLoad_IRK(TS ts,PetscViewer viewer)
710d2567f34SHong Zhang {
711d2567f34SHong Zhang   PetscErrorCode ierr;
712d2567f34SHong Zhang   SNES           snes;
713d2567f34SHong Zhang   TSAdapt        adapt;
714d2567f34SHong Zhang 
715d2567f34SHong Zhang   PetscFunctionBegin;
716d2567f34SHong Zhang   ierr = TSGetAdapt(ts,&adapt);CHKERRQ(ierr);
717d2567f34SHong Zhang   ierr = TSAdaptLoad(adapt,viewer);CHKERRQ(ierr);
718d2567f34SHong Zhang   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
719d2567f34SHong Zhang   ierr = SNESLoad(snes,viewer);CHKERRQ(ierr);
720d2567f34SHong Zhang   /* function and Jacobian context for SNES when used with TS is always ts object */
721d2567f34SHong Zhang   ierr = SNESSetFunction(snes,NULL,NULL,ts);CHKERRQ(ierr);
722d2567f34SHong Zhang   ierr = SNESSetJacobian(snes,NULL,NULL,NULL,ts);CHKERRQ(ierr);
723d2567f34SHong Zhang   PetscFunctionReturn(0);
724d2567f34SHong Zhang }
725d2567f34SHong Zhang 
726d2567f34SHong Zhang /*@C
727d2567f34SHong Zhang   TSIRKSetType - Set the type of IRK scheme
728d2567f34SHong Zhang 
729d2567f34SHong Zhang   Logically collective
730d2567f34SHong Zhang 
73102024617SSatish Balay   Input Parameters:
732d2567f34SHong Zhang +  ts - timestepping context
733d2567f34SHong Zhang -  irktype - type of IRK scheme
734d2567f34SHong Zhang 
735d2567f34SHong Zhang   Options Database:
736d2567f34SHong Zhang .  -ts_irk_type <gauss>
737d2567f34SHong Zhang 
738d2567f34SHong Zhang   Level: intermediate
739d2567f34SHong Zhang 
740d2567f34SHong Zhang .seealso: TSIRKGetType(), TSIRK, TSIRKType, TSIRKGAUSS
741d2567f34SHong Zhang @*/
742d2567f34SHong Zhang PetscErrorCode TSIRKSetType(TS ts,TSIRKType irktype)
743d2567f34SHong Zhang {
744d2567f34SHong Zhang   PetscErrorCode ierr;
745d2567f34SHong Zhang 
746d2567f34SHong Zhang   PetscFunctionBegin;
747d2567f34SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
748d2567f34SHong Zhang   PetscValidCharPointer(irktype,2);
749d2567f34SHong Zhang   ierr = PetscTryMethod(ts,"TSIRKSetType_C",(TS,TSIRKType),(ts,irktype));CHKERRQ(ierr);
750d2567f34SHong Zhang   PetscFunctionReturn(0);
751d2567f34SHong Zhang }
752d2567f34SHong Zhang 
753d2567f34SHong Zhang /*@C
754d2567f34SHong Zhang   TSIRKGetType - Get the type of IRK IMEX scheme
755d2567f34SHong Zhang 
756d2567f34SHong Zhang   Logically collective
757d2567f34SHong Zhang 
758d2567f34SHong Zhang   Input Parameter:
759d2567f34SHong Zhang .  ts - timestepping context
760d2567f34SHong Zhang 
761d2567f34SHong Zhang   Output Parameter:
762d2567f34SHong Zhang .  irktype - type of IRK-IMEX scheme
763d2567f34SHong Zhang 
764d2567f34SHong Zhang   Level: intermediate
765d2567f34SHong Zhang 
766d2567f34SHong Zhang .seealso: TSIRKGetType()
767d2567f34SHong Zhang @*/
768d2567f34SHong Zhang PetscErrorCode TSIRKGetType(TS ts,TSIRKType *irktype)
769d2567f34SHong Zhang {
770d2567f34SHong Zhang   PetscErrorCode ierr;
771d2567f34SHong Zhang 
772d2567f34SHong Zhang   PetscFunctionBegin;
773d2567f34SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
774d2567f34SHong Zhang   ierr = PetscUseMethod(ts,"TSIRKGetType_C",(TS,TSIRKType*),(ts,irktype));CHKERRQ(ierr);
775d2567f34SHong Zhang   PetscFunctionReturn(0);
776d2567f34SHong Zhang }
777d2567f34SHong Zhang 
778d2567f34SHong Zhang /*@C
779d2567f34SHong Zhang   TSIRKSetNumStages - Set the number of stages of IRK scheme
780d2567f34SHong Zhang 
781d2567f34SHong Zhang   Logically collective
782d2567f34SHong Zhang 
78302024617SSatish Balay   Input Parameters:
784d2567f34SHong Zhang +  ts - timestepping context
785d2567f34SHong Zhang -  nstages - number of stages of IRK scheme
786d2567f34SHong Zhang 
787d2567f34SHong Zhang   Options Database:
788d2567f34SHong Zhang .  -ts_irk_nstages <int>: Number of stages
789d2567f34SHong Zhang 
790d2567f34SHong Zhang   Level: intermediate
791d2567f34SHong Zhang 
792d2567f34SHong Zhang .seealso: TSIRKGetNumStages(), TSIRK
793d2567f34SHong Zhang @*/
794d2567f34SHong Zhang PetscErrorCode TSIRKSetNumStages(TS ts,PetscInt nstages)
795d2567f34SHong Zhang {
796d2567f34SHong Zhang   PetscErrorCode ierr;
797d2567f34SHong Zhang 
798d2567f34SHong Zhang   PetscFunctionBegin;
799d2567f34SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
800d2567f34SHong Zhang   ierr = PetscTryMethod(ts,"TSIRKSetNumStages_C",(TS,PetscInt),(ts,nstages));CHKERRQ(ierr);
801d2567f34SHong Zhang   PetscFunctionReturn(0);
802d2567f34SHong Zhang }
803d2567f34SHong Zhang 
804d2567f34SHong Zhang /*@C
805d2567f34SHong Zhang   TSIRKGetNumStages - Get the number of stages of IRK scheme
806d2567f34SHong Zhang 
807d2567f34SHong Zhang   Logically collective
808d2567f34SHong Zhang 
80902024617SSatish Balay   Input Parameters:
810d2567f34SHong Zhang +  ts - timestepping context
811d2567f34SHong Zhang -  nstages - number of stages of IRK scheme
812d2567f34SHong Zhang 
813d2567f34SHong Zhang   Level: intermediate
814d2567f34SHong Zhang 
815d2567f34SHong Zhang .seealso: TSIRKSetNumStages(), TSIRK
816d2567f34SHong Zhang @*/
817d2567f34SHong Zhang PetscErrorCode TSIRKGetNumStages(TS ts,PetscInt *nstages)
818d2567f34SHong Zhang {
819d2567f34SHong Zhang   PetscErrorCode ierr;
820d2567f34SHong Zhang 
821d2567f34SHong Zhang   PetscFunctionBegin;
822d2567f34SHong Zhang   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
823d2567f34SHong Zhang   PetscValidIntPointer(nstages,2);
824d2567f34SHong Zhang   ierr = PetscTryMethod(ts,"TSIRKGetNumStages_C",(TS,PetscInt*),(ts,nstages));CHKERRQ(ierr);
825d2567f34SHong Zhang   PetscFunctionReturn(0);
826d2567f34SHong Zhang }
827d2567f34SHong Zhang 
828d2567f34SHong Zhang static PetscErrorCode TSIRKGetType_IRK(TS ts,TSIRKType *irktype)
829d2567f34SHong Zhang {
830d2567f34SHong Zhang   TS_IRK *irk = (TS_IRK*)ts->data;
831d2567f34SHong Zhang 
832d2567f34SHong Zhang   PetscFunctionBegin;
833d2567f34SHong Zhang   *irktype = irk->method_name;
834d2567f34SHong Zhang   PetscFunctionReturn(0);
835d2567f34SHong Zhang }
836d2567f34SHong Zhang 
837d2567f34SHong Zhang static PetscErrorCode TSIRKSetType_IRK(TS ts,TSIRKType irktype)
838d2567f34SHong Zhang {
839d2567f34SHong Zhang   TS_IRK         *irk = (TS_IRK*)ts->data;
840d2567f34SHong Zhang   PetscErrorCode ierr,(*irkcreate)(TS);
841d2567f34SHong Zhang 
842d2567f34SHong Zhang   PetscFunctionBegin;
843d2567f34SHong Zhang   if (irk->method_name) {
844d2567f34SHong Zhang     ierr = PetscFree(irk->method_name);CHKERRQ(ierr);
845d2567f34SHong Zhang     ierr = TSIRKTableauReset(ts);CHKERRQ(ierr);
846d2567f34SHong Zhang   }
847d2567f34SHong Zhang   ierr = PetscFunctionListFind(TSIRKList,irktype,&irkcreate);CHKERRQ(ierr);
848d2567f34SHong Zhang   if (!irkcreate) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown TSIRK type \"%s\" given",irktype);
849d2567f34SHong Zhang   ierr = (*irkcreate)(ts);CHKERRQ(ierr);
850d2567f34SHong Zhang   ierr = PetscStrallocpy(irktype,&irk->method_name);CHKERRQ(ierr);
851d2567f34SHong Zhang   PetscFunctionReturn(0);
852d2567f34SHong Zhang }
853d2567f34SHong Zhang 
854d2567f34SHong Zhang static PetscErrorCode TSIRKSetNumStages_IRK(TS ts,PetscInt nstages)
855d2567f34SHong Zhang {
856d2567f34SHong Zhang   TS_IRK *irk = (TS_IRK*)ts->data;
857d2567f34SHong Zhang 
858d2567f34SHong Zhang   PetscFunctionBegin;
859d2567f34SHong Zhang   if (nstages<=0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"input argument, %d, out of range",nstages);
860d2567f34SHong Zhang   irk->nstages = nstages;
861d2567f34SHong Zhang   PetscFunctionReturn(0);
862d2567f34SHong Zhang }
863d2567f34SHong Zhang 
864d2567f34SHong Zhang static PetscErrorCode TSIRKGetNumStages_IRK(TS ts,PetscInt *nstages)
865d2567f34SHong Zhang {
866d2567f34SHong Zhang   TS_IRK *irk = (TS_IRK*)ts->data;
867d2567f34SHong Zhang 
868d2567f34SHong Zhang   PetscFunctionBegin;
869d2567f34SHong Zhang   PetscValidIntPointer(nstages,2);
870d2567f34SHong Zhang   *nstages = irk->nstages;
871d2567f34SHong Zhang   PetscFunctionReturn(0);
872d2567f34SHong Zhang }
873d2567f34SHong Zhang 
874d2567f34SHong Zhang static PetscErrorCode TSDestroy_IRK(TS ts)
875d2567f34SHong Zhang {
876d2567f34SHong Zhang   PetscErrorCode ierr;
877d2567f34SHong Zhang 
878d2567f34SHong Zhang   PetscFunctionBegin;
879d2567f34SHong Zhang   ierr = TSReset_IRK(ts);CHKERRQ(ierr);
880d2567f34SHong Zhang   if (ts->dm) {
881d2567f34SHong Zhang     ierr = DMCoarsenHookRemove(ts->dm,DMCoarsenHook_TSIRK,DMRestrictHook_TSIRK,ts);CHKERRQ(ierr);
882d2567f34SHong Zhang     ierr = DMSubDomainHookRemove(ts->dm,DMSubDomainHook_TSIRK,DMSubDomainRestrictHook_TSIRK,ts);CHKERRQ(ierr);
883d2567f34SHong Zhang   }
884d2567f34SHong Zhang   ierr = PetscFree(ts->data);CHKERRQ(ierr);
885d2567f34SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSIRKSetType_C",NULL);CHKERRQ(ierr);
886d2567f34SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSIRKGetType_C",NULL);CHKERRQ(ierr);
887d2567f34SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSIRKSetNumStages_C",NULL);CHKERRQ(ierr);
888d2567f34SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSIRKGetNumStages_C",NULL);CHKERRQ(ierr);
889d2567f34SHong Zhang   PetscFunctionReturn(0);
890d2567f34SHong Zhang }
891d2567f34SHong Zhang 
892d2567f34SHong Zhang /*MC
893d2567f34SHong Zhang       TSIRK - ODE and DAE solver using Implicit Runge-Kutta schemes
894d2567f34SHong Zhang 
895d2567f34SHong Zhang   Notes:
896d2567f34SHong Zhang 
897d2567f34SHong Zhang   TSIRK uses the sparse Kronecker product matrix implementation of MATKAIJ to achieve good arithmetic intensity.
898d2567f34SHong Zhang 
899*517f343bSHong Zhang   Gauss-Legrendre methods are currently supported. These are A-stable symplectic methods with an arbitrary number of stages. The order of accuracy is 2s when using s stages. The default method uses three stages and thus has an order of six. The number of stages (thus order) can be set with -ts_irk_nstages or TSIRKSetNumStages().
900d2567f34SHong Zhang 
901d2567f34SHong Zhang   Level: beginner
902d2567f34SHong Zhang 
903*517f343bSHong Zhang .seealso:  TSCreate(), TS, TSSetType(), TSIRKSetType(), TSIRKGetType(), TSIRKGAUSS, TSIRKRegister(), TSIRKSetNumStages()
904d2567f34SHong Zhang 
905d2567f34SHong Zhang M*/
906d2567f34SHong Zhang PETSC_EXTERN PetscErrorCode TSCreate_IRK(TS ts)
907d2567f34SHong Zhang {
908d2567f34SHong Zhang   TS_IRK         *irk;
909d2567f34SHong Zhang   PetscErrorCode ierr;
910d2567f34SHong Zhang 
911d2567f34SHong Zhang   PetscFunctionBegin;
912d2567f34SHong Zhang   ierr = TSIRKInitializePackage();CHKERRQ(ierr);
913d2567f34SHong Zhang 
914d2567f34SHong Zhang   ts->ops->reset          = TSReset_IRK;
915d2567f34SHong Zhang   ts->ops->destroy        = TSDestroy_IRK;
916d2567f34SHong Zhang   ts->ops->view           = TSView_IRK;
917d2567f34SHong Zhang   ts->ops->load           = TSLoad_IRK;
918d2567f34SHong Zhang   ts->ops->setup          = TSSetUp_IRK;
919d2567f34SHong Zhang   ts->ops->step           = TSStep_IRK;
920d2567f34SHong Zhang   ts->ops->interpolate    = TSInterpolate_IRK;
921d2567f34SHong Zhang   ts->ops->evaluatestep   = TSEvaluateStep_IRK;
922d2567f34SHong Zhang   ts->ops->rollback       = TSRollBack_IRK;
923d2567f34SHong Zhang   ts->ops->setfromoptions = TSSetFromOptions_IRK;
924d2567f34SHong Zhang   ts->ops->snesfunction   = SNESTSFormFunction_IRK;
925d2567f34SHong Zhang   ts->ops->snesjacobian   = SNESTSFormJacobian_IRK;
926d2567f34SHong Zhang 
927d2567f34SHong Zhang   ts->usessnes = PETSC_TRUE;
928d2567f34SHong Zhang 
929d2567f34SHong Zhang   ierr = PetscNewLog(ts,&irk);CHKERRQ(ierr);
930d2567f34SHong Zhang   ts->data = (void*)irk;
931d2567f34SHong Zhang 
932d2567f34SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSIRKSetType_C",TSIRKSetType_IRK);CHKERRQ(ierr);
933d2567f34SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSIRKGetType_C",TSIRKGetType_IRK);CHKERRQ(ierr);
934d2567f34SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSIRKSetNumStages_C",TSIRKSetNumStages_IRK);CHKERRQ(ierr);
935d2567f34SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSIRKGetNumStages_C",TSIRKGetNumStages_IRK);CHKERRQ(ierr);
936d2567f34SHong Zhang   /* 3-stage IRK_Gauss is the default */
937d2567f34SHong Zhang   ierr = PetscNew(&irk->tableau);CHKERRQ(ierr);
938d2567f34SHong Zhang   irk->nstages = 3;
939d2567f34SHong Zhang   ierr = TSIRKSetType(ts,TSIRKDefault);CHKERRQ(ierr);
940d2567f34SHong Zhang   PetscFunctionReturn(0);
941d2567f34SHong Zhang }
942