xref: /petsc/src/ts/impls/implicit/irk/irk.c (revision 3397a780bae4d42ff2f0c2f2a9d9d56e479d9fc7)
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);
655*3397a780SHong Zhang   ierr = TSGetIJacobian(ts,&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 
899d2567f34SHong Zhang   The default is TSIRK3, it can be changed with TSIRKSetType() or -ts_irk_type
900d2567f34SHong Zhang 
901d2567f34SHong Zhang   If the equation is implicit or a DAE, then TSSetEquationType() needs to be set accordingly. Refer to the manual for further information.
902d2567f34SHong Zhang 
903d2567f34SHong Zhang   Consider trying TSROSW if the stiff part is linear or weakly nonlinear.
904d2567f34SHong Zhang 
905d2567f34SHong Zhang   Level: beginner
906d2567f34SHong Zhang 
907d2567f34SHong Zhang .seealso:  TSCreate(), TS, TSSetType(), TSIRKSetType(), TSIRKGetType(),
908d2567f34SHong Zhang            TSIRK1BEE, TSIRK2C, TSIRK2D, TSIRK2E, TSIRK3, TSIRKL2, TSIRKA2, TSIRKARS122,
909d2567f34SHong Zhang            TSIRK4, TSIRK5, TSIRKPRSSP2, TSIRKARS443, TSIRKBPR3, TSIRKType, TSIRKRegister()
910d2567f34SHong Zhang 
911d2567f34SHong Zhang M*/
912d2567f34SHong Zhang PETSC_EXTERN PetscErrorCode TSCreate_IRK(TS ts)
913d2567f34SHong Zhang {
914d2567f34SHong Zhang   TS_IRK         *irk;
915d2567f34SHong Zhang   PetscErrorCode ierr;
916d2567f34SHong Zhang 
917d2567f34SHong Zhang   PetscFunctionBegin;
918d2567f34SHong Zhang   ierr = TSIRKInitializePackage();CHKERRQ(ierr);
919d2567f34SHong Zhang 
920d2567f34SHong Zhang   ts->ops->reset          = TSReset_IRK;
921d2567f34SHong Zhang   ts->ops->destroy        = TSDestroy_IRK;
922d2567f34SHong Zhang   ts->ops->view           = TSView_IRK;
923d2567f34SHong Zhang   ts->ops->load           = TSLoad_IRK;
924d2567f34SHong Zhang   ts->ops->setup          = TSSetUp_IRK;
925d2567f34SHong Zhang   ts->ops->step           = TSStep_IRK;
926d2567f34SHong Zhang   ts->ops->interpolate    = TSInterpolate_IRK;
927d2567f34SHong Zhang   ts->ops->evaluatestep   = TSEvaluateStep_IRK;
928d2567f34SHong Zhang   ts->ops->rollback       = TSRollBack_IRK;
929d2567f34SHong Zhang   ts->ops->setfromoptions = TSSetFromOptions_IRK;
930d2567f34SHong Zhang   ts->ops->snesfunction   = SNESTSFormFunction_IRK;
931d2567f34SHong Zhang   ts->ops->snesjacobian   = SNESTSFormJacobian_IRK;
932d2567f34SHong Zhang 
933d2567f34SHong Zhang   ts->usessnes = PETSC_TRUE;
934d2567f34SHong Zhang 
935d2567f34SHong Zhang   ierr = PetscNewLog(ts,&irk);CHKERRQ(ierr);
936d2567f34SHong Zhang   ts->data = (void*)irk;
937d2567f34SHong Zhang 
938d2567f34SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSIRKSetType_C",TSIRKSetType_IRK);CHKERRQ(ierr);
939d2567f34SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSIRKGetType_C",TSIRKGetType_IRK);CHKERRQ(ierr);
940d2567f34SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSIRKSetNumStages_C",TSIRKSetNumStages_IRK);CHKERRQ(ierr);
941d2567f34SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)ts,"TSIRKGetNumStages_C",TSIRKGetNumStages_IRK);CHKERRQ(ierr);
942d2567f34SHong Zhang   /* 3-stage IRK_Gauss is the default */
943d2567f34SHong Zhang   ierr = PetscNew(&irk->tableau);CHKERRQ(ierr);
944d2567f34SHong Zhang   irk->nstages = 3;
945d2567f34SHong Zhang   ierr = TSIRKSetType(ts,TSIRKDefault);CHKERRQ(ierr);
946d2567f34SHong Zhang   PetscFunctionReturn(0);
947d2567f34SHong Zhang }
948