xref: /petsc/src/ts/impls/eimex/eimex.c (revision 0bb9014ae32410f4e29595948e3740bc8123d71c)
1*0bb9014aSEmil Constantinescu /*
2*0bb9014aSEmil Constantinescu  * eimex.c
3*0bb9014aSEmil Constantinescu  *
4*0bb9014aSEmil Constantinescu  *  Created on: Jun 21, 2012
5*0bb9014aSEmil Constantinescu  *      Written by Hong Zhang (zhang@vt.edu), Virginia Tech
6*0bb9014aSEmil Constantinescu  *                 Emil Constantinescu (emconsta@mcs.anl.gov), Argonne National Laboratory
7*0bb9014aSEmil Constantinescu  */
8*0bb9014aSEmil Constantinescu /*
9*0bb9014aSEmil Constantinescu   Code for timestepping with Extrapolated IMEX methods
10*0bb9014aSEmil Constantinescu 
11*0bb9014aSEmil Constantinescu   Notes:
12*0bb9014aSEmil Constantinescu   The general system is written as
13*0bb9014aSEmil Constantinescu 
14*0bb9014aSEmil Constantinescu   G(t,X,Xdot) = F(t,X)
15*0bb9014aSEmil Constantinescu 
16*0bb9014aSEmil Constantinescu   where G represents the stiff part of the physics and F represents the non-stiff part.
17*0bb9014aSEmil Constantinescu   This method is designed to be linearly implicit on G and can use an approximate and lagged Jacobian.
18*0bb9014aSEmil Constantinescu 
19*0bb9014aSEmil Constantinescu   Another common form for the system is
20*0bb9014aSEmil Constantinescu 
21*0bb9014aSEmil Constantinescu   y'=f(x)+g(x)
22*0bb9014aSEmil Constantinescu 
23*0bb9014aSEmil Constantinescu   The relationship between F,G and f,g is
24*0bb9014aSEmil Constantinescu 
25*0bb9014aSEmil Constantinescu   G = y'-g(x), F = f(x)
26*0bb9014aSEmil Constantinescu 
27*0bb9014aSEmil Constantinescu  References
28*0bb9014aSEmil Constantinescu   E. Constantinescu and A. Sandu, Extrapolated implicit-explicit time stepping, SIAM Journal on Scientific
29*0bb9014aSEmil Constantinescu Computing, 31 (2010), pp. 4452–4477.
30*0bb9014aSEmil Constantinescu 
31*0bb9014aSEmil Constantinescu */
32*0bb9014aSEmil Constantinescu #include <petsc-private/tsimpl.h>                /*I   "petscts.h"   I*/
33*0bb9014aSEmil Constantinescu 
34*0bb9014aSEmil Constantinescu static const PetscInt TSEIMEXDefault = 3;
35*0bb9014aSEmil Constantinescu 
36*0bb9014aSEmil Constantinescu typedef struct {
37*0bb9014aSEmil Constantinescu   PetscInt     row_ind;         /* Return the term T[row_ind][col_ind]*/
38*0bb9014aSEmil Constantinescu   PetscInt     col_ind;         /* Return the term T[row_ind][col_ind]*/
39*0bb9014aSEmil Constantinescu   PetscInt     nstages;         /* Numbers of stages in current scheme*/
40*0bb9014aSEmil Constantinescu   PetscInt     max_rows;        /* Maximum number of rows */
41*0bb9014aSEmil Constantinescu   PetscInt     *N;              /* Harmonic sequence N[max_rows] */
42*0bb9014aSEmil Constantinescu   Vec          Y;               /* States computed during the step, used to complete the step */
43*0bb9014aSEmil Constantinescu   Vec          Z;               /* For shift*(Y-Z) */
44*0bb9014aSEmil Constantinescu   Vec          *T;              /* Working table, size determined by nstages */
45*0bb9014aSEmil Constantinescu   Vec          YdotRHS;         /* f(x) Work vector holding YdotRHS during residual evaluation */
46*0bb9014aSEmil Constantinescu   Vec          YdotI;           /* xdot-g(x) Work vector holding YdotI = G(t,x,xdot) when xdot =0 */
47*0bb9014aSEmil Constantinescu   Vec          Ydot;            /* f(x)+g(x) Work vector*/
48*0bb9014aSEmil Constantinescu   Vec          VecSolPrev;      /* Work vector holding the solution from the previous step (used for interpolation)*/
49*0bb9014aSEmil Constantinescu //  PetscScalar  *work;            /* Scalar work space of length number of stages, used to prepare VecMAXPY() */
50*0bb9014aSEmil Constantinescu   PetscReal    shift;
51*0bb9014aSEmil Constantinescu   PetscReal    ctime;
52*0bb9014aSEmil Constantinescu   PetscBool    recompute_jacobian; /* Recompute the Jacobian at each stage, default is to freeze the Jacobian at the start of each step */
53*0bb9014aSEmil Constantinescu   PetscBool    ord_adapt;       /*order adapativity*/
54*0bb9014aSEmil Constantinescu   TSStepStatus status;
55*0bb9014aSEmil Constantinescu } TS_EIMEX;
56*0bb9014aSEmil Constantinescu 
57*0bb9014aSEmil Constantinescu /* This function is pure */
58*0bb9014aSEmil Constantinescu static PetscInt Map(PetscInt i, PetscInt j, PetscInt s)
59*0bb9014aSEmil Constantinescu {
60*0bb9014aSEmil Constantinescu   return ((2*s-j+1)*j/2+i-j);
61*0bb9014aSEmil Constantinescu }
62*0bb9014aSEmil Constantinescu 
63*0bb9014aSEmil Constantinescu 
64*0bb9014aSEmil Constantinescu #undef __FUNCT__
65*0bb9014aSEmil Constantinescu #define __FUNCT__ "TSEvaluateStep_EIMEX"
66*0bb9014aSEmil Constantinescu static PetscErrorCode TSEvaluateStep_EIMEX(TS ts,PetscInt order,Vec X,PetscBool *done)
67*0bb9014aSEmil Constantinescu {
68*0bb9014aSEmil Constantinescu   TS_EIMEX        *ext = (TS_EIMEX*)ts->data;
69*0bb9014aSEmil Constantinescu   const PetscInt  ns = ext->nstages;
70*0bb9014aSEmil Constantinescu   PetscErrorCode ierr;
71*0bb9014aSEmil Constantinescu   PetscFunctionBegin;
72*0bb9014aSEmil Constantinescu   ierr = VecCopy(ext->T[Map(ext->row_ind,ext->col_ind,ns)],X);CHKERRQ(ierr);
73*0bb9014aSEmil Constantinescu   PetscFunctionReturn(0);
74*0bb9014aSEmil Constantinescu }
75*0bb9014aSEmil Constantinescu 
76*0bb9014aSEmil Constantinescu 
77*0bb9014aSEmil Constantinescu #undef __FUNCT__
78*0bb9014aSEmil Constantinescu #define __FUNCT__ "TSStage_EIMEX"
79*0bb9014aSEmil Constantinescu static PetscErrorCode TSStage_EIMEX(TS ts,PetscInt istage)
80*0bb9014aSEmil Constantinescu {
81*0bb9014aSEmil Constantinescu   TS_EIMEX        *ext = (TS_EIMEX*)ts->data;
82*0bb9014aSEmil Constantinescu   PetscReal       h;
83*0bb9014aSEmil Constantinescu   Vec             Y=ext->Y, Z=ext->Z;
84*0bb9014aSEmil Constantinescu   SNES            snes;
85*0bb9014aSEmil Constantinescu   TSAdapt         adapt;
86*0bb9014aSEmil Constantinescu   PetscInt        i,its,lits;
87*0bb9014aSEmil Constantinescu   PetscBool       accept;
88*0bb9014aSEmil Constantinescu   PetscErrorCode  ierr;
89*0bb9014aSEmil Constantinescu 
90*0bb9014aSEmil Constantinescu   PetscFunctionBegin;
91*0bb9014aSEmil Constantinescu   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
92*0bb9014aSEmil Constantinescu   h = ts->time_step/ext->N[istage];/*step size for the istage-th stage*/
93*0bb9014aSEmil Constantinescu   ext->shift = 1./h;
94*0bb9014aSEmil Constantinescu   ierr = SNESSetLagJacobian(snes,-2);CHKERRQ(ierr); /* Recompute the Jacobian on this solve, but not again */
95*0bb9014aSEmil Constantinescu   ierr = VecCopy(ext->VecSolPrev,Y);CHKERRQ(ierr); /*Take the previous solution as intial step*/
96*0bb9014aSEmil Constantinescu 
97*0bb9014aSEmil Constantinescu   for(i=0; i<ext->N[istage]; i++){
98*0bb9014aSEmil Constantinescu     ext->ctime = ts->ptime + h*i;
99*0bb9014aSEmil Constantinescu     ierr = VecCopy(Y,Z);CHKERRQ(ierr);/*Save the solution of the previous substep*/
100*0bb9014aSEmil Constantinescu     ierr = SNESSolve(snes,PETSC_NULL,Y);CHKERRQ(ierr);
101*0bb9014aSEmil Constantinescu     ierr = SNESGetIterationNumber(snes,&its);CHKERRQ(ierr);
102*0bb9014aSEmil Constantinescu     ierr = SNESGetLinearSolveIterations(snes,&lits);CHKERRQ(ierr);
103*0bb9014aSEmil Constantinescu     ts->snes_its += its; ts->ksp_its += lits;
104*0bb9014aSEmil Constantinescu     ierr = TSGetAdapt(ts,&adapt);CHKERRQ(ierr);
105*0bb9014aSEmil Constantinescu     ierr = TSAdaptCheckStage(adapt,ts,&accept);CHKERRQ(ierr);
106*0bb9014aSEmil Constantinescu   }
107*0bb9014aSEmil Constantinescu 
108*0bb9014aSEmil Constantinescu   PetscFunctionReturn(0);
109*0bb9014aSEmil Constantinescu }
110*0bb9014aSEmil Constantinescu 
111*0bb9014aSEmil Constantinescu 
112*0bb9014aSEmil Constantinescu #undef __FUNCT__
113*0bb9014aSEmil Constantinescu #define __FUNCT__ "TSStep_EIMEX"
114*0bb9014aSEmil Constantinescu static PetscErrorCode TSStep_EIMEX(TS ts)
115*0bb9014aSEmil Constantinescu {
116*0bb9014aSEmil Constantinescu   TS_EIMEX        *ext = (TS_EIMEX*)ts->data;
117*0bb9014aSEmil Constantinescu   const PetscInt  ns = ext->nstages;
118*0bb9014aSEmil Constantinescu   Vec             *T=ext->T, Y=ext->Y;
119*0bb9014aSEmil Constantinescu 
120*0bb9014aSEmil Constantinescu   SNES            snes;
121*0bb9014aSEmil Constantinescu   PetscInt        i,j;
122*0bb9014aSEmil Constantinescu   PetscBool       accept = PETSC_FALSE;
123*0bb9014aSEmil Constantinescu   PetscErrorCode  ierr;
124*0bb9014aSEmil Constantinescu   PetscReal       alpha,local_error;
125*0bb9014aSEmil Constantinescu   PetscFunctionBegin;
126*0bb9014aSEmil Constantinescu 
127*0bb9014aSEmil Constantinescu   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
128*0bb9014aSEmil Constantinescu   ierr = SNESSetType(snes,"ksponly"); CHKERRQ(ierr);
129*0bb9014aSEmil Constantinescu   ext->status = TS_STEP_INCOMPLETE;
130*0bb9014aSEmil Constantinescu 
131*0bb9014aSEmil Constantinescu   ierr = VecCopy(ts->vec_sol,ext->VecSolPrev);CHKERRQ(ierr);
132*0bb9014aSEmil Constantinescu 
133*0bb9014aSEmil Constantinescu   /* Apply n_j steps of the base method to obtain solutions of T(j,1),1<=j<=s*/
134*0bb9014aSEmil Constantinescu   for(j=0; j<ns; j++){
135*0bb9014aSEmil Constantinescu 	ierr = TSStage_EIMEX(ts,j);CHKERRQ(ierr);
136*0bb9014aSEmil Constantinescu 	ierr = VecCopy(Y,T[j]); CHKERRQ(ierr);
137*0bb9014aSEmil Constantinescu   }
138*0bb9014aSEmil Constantinescu 
139*0bb9014aSEmil Constantinescu   for(i=1;i<ns;i++){
140*0bb9014aSEmil Constantinescu     for(j=i;j<ns;j++){
141*0bb9014aSEmil Constantinescu       alpha = -(PetscReal)ext->N[j]/ext->N[j-i];
142*0bb9014aSEmil Constantinescu       ierr  = VecAXPBYPCZ(T[Map(j,i,ns)],alpha,1.0,0,T[Map(j,i-1,ns)],
143*0bb9014aSEmil Constantinescu     		  T[Map(j-1,i-1,ns)]);/*T[j][i]=alpha*T[j][i-1]+T[j-1][i-1]*/
144*0bb9014aSEmil Constantinescu       alpha = 1.0/(1.0 + alpha);
145*0bb9014aSEmil Constantinescu       ierr  = VecScale(T[Map(j,i,ns)],alpha);CHKERRQ(ierr);
146*0bb9014aSEmil Constantinescu     }
147*0bb9014aSEmil Constantinescu   }
148*0bb9014aSEmil Constantinescu 
149*0bb9014aSEmil Constantinescu   ierr = TSEvaluateStep(ts,ns,ts->vec_sol,PETSC_NULL);CHKERRQ(ierr);/*update ts solution */
150*0bb9014aSEmil Constantinescu 
151*0bb9014aSEmil Constantinescu   if(ext->ord_adapt && ext->nstages < ext->max_rows){
152*0bb9014aSEmil Constantinescu 	accept = PETSC_FALSE;
153*0bb9014aSEmil Constantinescu 	while(!accept && ext->nstages < ext->max_rows){
154*0bb9014aSEmil Constantinescu 	  ierr = TSErrorNormWRMS(ts,T[Map(ext->nstages-1,ext->nstages-2,ext->nstages)],&local_error);CHKERRQ(ierr);
155*0bb9014aSEmil Constantinescu 	  accept = (local_error < 1.0)? PETSC_TRUE : PETSC_FALSE;
156*0bb9014aSEmil Constantinescu 
157*0bb9014aSEmil Constantinescu 	  if(!accept){/* add one more stage*/
158*0bb9014aSEmil Constantinescu 	    ierr = TSStage_EIMEX(ts,ext->nstages);CHKERRQ(ierr);
159*0bb9014aSEmil Constantinescu 	    ext->nstages++; ext->row_ind++; ext->col_ind++;
160*0bb9014aSEmil Constantinescu 	    /*T table need to be recycled*/
161*0bb9014aSEmil Constantinescu 	    ierr = VecDuplicateVecs(ts->vec_sol,(1+ext->nstages)*ext->nstages/2,&ext->T);CHKERRQ(ierr);
162*0bb9014aSEmil Constantinescu 	    for(i=0; i<ext->nstages-1; i++){
163*0bb9014aSEmil Constantinescu 	      for(j=0; j<=i; j++){
164*0bb9014aSEmil Constantinescu 	        ierr = VecCopy(T[Map(i,j,ext->nstages-1)],ext->T[Map(i,j,ext->nstages)]);CHKERRQ(ierr);
165*0bb9014aSEmil Constantinescu 	      }
166*0bb9014aSEmil Constantinescu 	    }
167*0bb9014aSEmil Constantinescu 	    ierr = VecDestroyVecs(ext->nstages*(ext->nstages-1)/2,&T);CHKERRQ(ierr);
168*0bb9014aSEmil Constantinescu 	    T = ext->T; /*reset the pointer*/
169*0bb9014aSEmil Constantinescu 	    /*recycling finished, store the new solution*/
170*0bb9014aSEmil Constantinescu 	    ierr = VecCopy(Y,T[ext->nstages-1]); CHKERRQ(ierr);
171*0bb9014aSEmil Constantinescu 	    /*extrapolation for the newly added stage*/
172*0bb9014aSEmil Constantinescu 	    for(i=1;i<ext->nstages;i++){
173*0bb9014aSEmil Constantinescu 	      alpha = -(PetscReal)ext->N[ext->nstages-1]/ext->N[ext->nstages-1-i];
174*0bb9014aSEmil Constantinescu 	      ierr  = VecAXPBYPCZ(T[Map(ext->nstages-1,i,ext->nstages)],alpha,1.0,0,T[Map(ext->nstages-1,i-1,ext->nstages)],T[Map(ext->nstages-1-1,i-1,ext->nstages)]);/*T[ext->nstages-1][i]=alpha*T[ext->nstages-1][i-1]+T[ext->nstages-1-1][i-1]*/
175*0bb9014aSEmil Constantinescu 	      alpha = 1.0/(1.0 + alpha);
176*0bb9014aSEmil Constantinescu 	      ierr  = VecScale(T[Map(ext->nstages-1,i,ext->nstages)],alpha);CHKERRQ(ierr);
177*0bb9014aSEmil Constantinescu 	    }
178*0bb9014aSEmil Constantinescu 	    /*update ts solution */
179*0bb9014aSEmil Constantinescu 	    ierr = TSEvaluateStep(ts,ext->nstages,ts->vec_sol,PETSC_NULL);CHKERRQ(ierr);
180*0bb9014aSEmil Constantinescu 	  }/*end if !accept*/
181*0bb9014aSEmil Constantinescu 	}/*end while*/
182*0bb9014aSEmil Constantinescu 
183*0bb9014aSEmil Constantinescu 	if(ext->nstages == ext->max_rows){
184*0bb9014aSEmil Constantinescu 		ierr = PetscInfo(ts,"Max number of rows has been used\n");CHKERRQ(ierr);
185*0bb9014aSEmil Constantinescu 	}
186*0bb9014aSEmil Constantinescu   }/*end if ext->ord_adapt*/
187*0bb9014aSEmil Constantinescu 
188*0bb9014aSEmil Constantinescu   ts->ptime += ts->time_step;
189*0bb9014aSEmil Constantinescu   ts->steps++;
190*0bb9014aSEmil Constantinescu   ext->status = TS_STEP_COMPLETE;
191*0bb9014aSEmil Constantinescu 
192*0bb9014aSEmil Constantinescu   if (ext->status != TS_STEP_COMPLETE && !ts->reason) ts->reason = TS_DIVERGED_STEP_REJECTED;
193*0bb9014aSEmil Constantinescu   PetscFunctionReturn(0);
194*0bb9014aSEmil Constantinescu }
195*0bb9014aSEmil Constantinescu 
196*0bb9014aSEmil Constantinescu 
197*0bb9014aSEmil Constantinescu /*cubic Hermit spline*/
198*0bb9014aSEmil Constantinescu #undef __FUNCT__
199*0bb9014aSEmil Constantinescu #define __FUNCT__ "TSInterpolate_EIMEX"
200*0bb9014aSEmil Constantinescu static PetscErrorCode TSInterpolate_EIMEX(TS ts,PetscReal itime,Vec X)
201*0bb9014aSEmil Constantinescu {
202*0bb9014aSEmil Constantinescu   TS_EIMEX       *ext = (TS_EIMEX*)ts->data;
203*0bb9014aSEmil Constantinescu   PetscReal      t,a,b;
204*0bb9014aSEmil Constantinescu   Vec            Y0=ext->VecSolPrev,Y1=ext->Y,
205*0bb9014aSEmil Constantinescu 		         Ydot=ext->Ydot,YdotI=ext->YdotI;
206*0bb9014aSEmil Constantinescu   const PetscReal h = ts->time_step_prev;
207*0bb9014aSEmil Constantinescu   PetscErrorCode ierr;
208*0bb9014aSEmil Constantinescu   PetscScalar *x;
209*0bb9014aSEmil Constantinescu   PetscFunctionBegin;
210*0bb9014aSEmil Constantinescu   t = (itime -ts->ptime + h)/h;
211*0bb9014aSEmil Constantinescu   /*YdotI = -f(x)-g(x)*/
212*0bb9014aSEmil Constantinescu 
213*0bb9014aSEmil Constantinescu   ierr = VecZeroEntries(Ydot);CHKERRQ(ierr);
214*0bb9014aSEmil Constantinescu   ierr = TSComputeIFunction(ts,ts->ptime-h,Y0,Ydot,YdotI,PETSC_FALSE);CHKERRQ(ierr);
215*0bb9014aSEmil Constantinescu 
216*0bb9014aSEmil Constantinescu   a    = 2.0*pow(t,3) - 3.0*t*t + 1.0;
217*0bb9014aSEmil Constantinescu   b    = -(pow(t,3) - 2.0*t*t + t)*h;
218*0bb9014aSEmil Constantinescu   ierr = VecAXPBYPCZ(X,a,b,0.0,Y0,YdotI);CHKERRQ(ierr);
219*0bb9014aSEmil Constantinescu 
220*0bb9014aSEmil Constantinescu   ierr = TSComputeIFunction(ts,ts->ptime,Y1,Ydot,YdotI,PETSC_FALSE);CHKERRQ(ierr);
221*0bb9014aSEmil Constantinescu   a    = -2.0*pow(t,3)+3.0*t*t;
222*0bb9014aSEmil Constantinescu   b    = -(pow(t,3) - t*t)*h;
223*0bb9014aSEmil Constantinescu   ierr = VecAXPBYPCZ(X,a,b,1.0,Y1,YdotI);CHKERRQ(ierr);
224*0bb9014aSEmil Constantinescu 
225*0bb9014aSEmil Constantinescu   PetscFunctionReturn(0);
226*0bb9014aSEmil Constantinescu }
227*0bb9014aSEmil Constantinescu 
228*0bb9014aSEmil Constantinescu 
229*0bb9014aSEmil Constantinescu #undef __FUNCT__
230*0bb9014aSEmil Constantinescu #define __FUNCT__ "TSReset_EIMEX"
231*0bb9014aSEmil Constantinescu static PetscErrorCode TSReset_EIMEX(TS ts)
232*0bb9014aSEmil Constantinescu {
233*0bb9014aSEmil Constantinescu   TS_EIMEX        *ext = (TS_EIMEX*)ts->data;
234*0bb9014aSEmil Constantinescu   PetscInt        ns;
235*0bb9014aSEmil Constantinescu   PetscErrorCode  ierr;
236*0bb9014aSEmil Constantinescu 
237*0bb9014aSEmil Constantinescu   PetscFunctionBegin;
238*0bb9014aSEmil Constantinescu   ns = ext->nstages;
239*0bb9014aSEmil Constantinescu   ierr = VecDestroyVecs((1+ns)*ns/2,&ext->T);CHKERRQ(ierr);
240*0bb9014aSEmil Constantinescu   ierr = VecDestroy(&ext->Y);CHKERRQ(ierr);
241*0bb9014aSEmil Constantinescu   ierr = VecDestroy(&ext->Z);CHKERRQ(ierr);
242*0bb9014aSEmil Constantinescu   ierr = VecDestroy(&ext->YdotRHS);CHKERRQ(ierr);
243*0bb9014aSEmil Constantinescu   ierr = VecDestroy(&ext->YdotI);CHKERRQ(ierr);
244*0bb9014aSEmil Constantinescu   ierr = VecDestroy(&ext->Ydot);CHKERRQ(ierr);
245*0bb9014aSEmil Constantinescu   ierr = VecDestroy(&ext->VecSolPrev);CHKERRQ(ierr);
246*0bb9014aSEmil Constantinescu   ierr = PetscFree(ext->N);CHKERRQ(ierr);
247*0bb9014aSEmil Constantinescu   PetscFunctionReturn(0);
248*0bb9014aSEmil Constantinescu }
249*0bb9014aSEmil Constantinescu 
250*0bb9014aSEmil Constantinescu #undef __FUNCT__
251*0bb9014aSEmil Constantinescu #define __FUNCT__ "TSDestroy_EIMEX"
252*0bb9014aSEmil Constantinescu static PetscErrorCode TSDestroy_EIMEX(TS ts)
253*0bb9014aSEmil Constantinescu {
254*0bb9014aSEmil Constantinescu   PetscErrorCode  ierr;
255*0bb9014aSEmil Constantinescu 
256*0bb9014aSEmil Constantinescu   PetscFunctionBegin;
257*0bb9014aSEmil Constantinescu   ierr = TSReset_EIMEX(ts);CHKERRQ(ierr);
258*0bb9014aSEmil Constantinescu   ierr = PetscFree(ts->data);CHKERRQ(ierr);
259*0bb9014aSEmil Constantinescu   ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSEIMEXSetMaxRows_C","",PETSC_NULL);CHKERRQ(ierr);
260*0bb9014aSEmil Constantinescu   ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSEIMEXSetRowCol_C","",PETSC_NULL);CHKERRQ(ierr);
261*0bb9014aSEmil Constantinescu   ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSEIMEXSetOrdAdapt_C","",PETSC_NULL);CHKERRQ(ierr);
262*0bb9014aSEmil Constantinescu 
263*0bb9014aSEmil Constantinescu   PetscFunctionReturn(0);
264*0bb9014aSEmil Constantinescu }
265*0bb9014aSEmil Constantinescu 
266*0bb9014aSEmil Constantinescu 
267*0bb9014aSEmil Constantinescu #undef __FUNCT__
268*0bb9014aSEmil Constantinescu #define __FUNCT__ "TSEIMEXGetVecs"
269*0bb9014aSEmil Constantinescu static PetscErrorCode TSEIMEXGetVecs(TS ts,DM dm,Vec *Z,Vec *Ydot,Vec *YdotI, Vec *YdotRHS)
270*0bb9014aSEmil Constantinescu {
271*0bb9014aSEmil Constantinescu   TS_EIMEX       *ext = (TS_EIMEX*)ts->data;
272*0bb9014aSEmil Constantinescu   PetscErrorCode ierr;
273*0bb9014aSEmil Constantinescu 
274*0bb9014aSEmil Constantinescu   PetscFunctionBegin;
275*0bb9014aSEmil Constantinescu   if (Z) {
276*0bb9014aSEmil Constantinescu     if (dm && dm != ts->dm) {
277*0bb9014aSEmil Constantinescu       ierr = DMGetNamedGlobalVector(dm,"TSEIMEX_Z",Z);CHKERRQ(ierr);
278*0bb9014aSEmil Constantinescu     } else *Z = ext->Z;
279*0bb9014aSEmil Constantinescu   }
280*0bb9014aSEmil Constantinescu   if (Ydot) {
281*0bb9014aSEmil Constantinescu     if (dm && dm != ts->dm) {
282*0bb9014aSEmil Constantinescu       ierr = DMGetNamedGlobalVector(dm,"TSEIMEX_Ydot",Ydot);CHKERRQ(ierr);
283*0bb9014aSEmil Constantinescu     } else *Ydot = ext->Ydot;
284*0bb9014aSEmil Constantinescu   }
285*0bb9014aSEmil Constantinescu   if (YdotI) {
286*0bb9014aSEmil Constantinescu     if (dm && dm != ts->dm) {
287*0bb9014aSEmil Constantinescu       ierr = DMGetNamedGlobalVector(dm,"TSEIMEX_YdotI",YdotI);CHKERRQ(ierr);
288*0bb9014aSEmil Constantinescu     } else *YdotI = ext->YdotI;
289*0bb9014aSEmil Constantinescu   }
290*0bb9014aSEmil Constantinescu   if (YdotRHS) {
291*0bb9014aSEmil Constantinescu     if (dm && dm != ts->dm) {
292*0bb9014aSEmil Constantinescu       ierr = DMGetNamedGlobalVector(dm,"TSEIMEX_YdotRHS",YdotRHS);CHKERRQ(ierr);
293*0bb9014aSEmil Constantinescu     } else *YdotRHS = ext->YdotRHS;
294*0bb9014aSEmil Constantinescu   }
295*0bb9014aSEmil Constantinescu   PetscFunctionReturn(0);
296*0bb9014aSEmil Constantinescu }
297*0bb9014aSEmil Constantinescu 
298*0bb9014aSEmil Constantinescu 
299*0bb9014aSEmil Constantinescu #undef __FUNCT__
300*0bb9014aSEmil Constantinescu #define __FUNCT__ "TSEIMEXRestoreVecs"
301*0bb9014aSEmil Constantinescu static PetscErrorCode TSEIMEXRestoreVecs(TS ts,DM dm,Vec *Z,Vec *Ydot,Vec *YdotI,Vec *YdotRHS)
302*0bb9014aSEmil Constantinescu {
303*0bb9014aSEmil Constantinescu   PetscErrorCode ierr;
304*0bb9014aSEmil Constantinescu 
305*0bb9014aSEmil Constantinescu   PetscFunctionBegin;
306*0bb9014aSEmil Constantinescu   if (Z) {
307*0bb9014aSEmil Constantinescu     if (dm && dm != ts->dm) {
308*0bb9014aSEmil Constantinescu       ierr = DMRestoreNamedGlobalVector(dm,"TSEIMEX_Z",Z);CHKERRQ(ierr);
309*0bb9014aSEmil Constantinescu     }
310*0bb9014aSEmil Constantinescu   }
311*0bb9014aSEmil Constantinescu   if (Ydot) {
312*0bb9014aSEmil Constantinescu     if (dm && dm != ts->dm) {
313*0bb9014aSEmil Constantinescu       ierr = DMRestoreNamedGlobalVector(dm,"TSEIMEX_Ydot",Ydot);CHKERRQ(ierr);
314*0bb9014aSEmil Constantinescu     }
315*0bb9014aSEmil Constantinescu   }
316*0bb9014aSEmil Constantinescu   if (YdotI) {
317*0bb9014aSEmil Constantinescu     if (dm && dm != ts->dm) {
318*0bb9014aSEmil Constantinescu       ierr = DMRestoreNamedGlobalVector(dm,"TSEIMEX_YdotI",YdotI);CHKERRQ(ierr);
319*0bb9014aSEmil Constantinescu     }
320*0bb9014aSEmil Constantinescu   }
321*0bb9014aSEmil Constantinescu   if (YdotRHS) {
322*0bb9014aSEmil Constantinescu     if (dm && dm != ts->dm) {
323*0bb9014aSEmil Constantinescu       ierr = DMRestoreNamedGlobalVector(dm,"TSEIMEX_YdotRHS",YdotRHS);CHKERRQ(ierr);
324*0bb9014aSEmil Constantinescu     }
325*0bb9014aSEmil Constantinescu   }
326*0bb9014aSEmil Constantinescu   PetscFunctionReturn(0);
327*0bb9014aSEmil Constantinescu }
328*0bb9014aSEmil Constantinescu 
329*0bb9014aSEmil Constantinescu 
330*0bb9014aSEmil Constantinescu /*
331*0bb9014aSEmil Constantinescu   This defines the nonlinear equation that is to be solved with SNES
332*0bb9014aSEmil Constantinescu   Fn[t0+Theta*dt, U, (U-U0)*shift] = 0
333*0bb9014aSEmil Constantinescu   In the case of Backward Euler, Fn = (U-U0)/h-g(t1,U))
334*0bb9014aSEmil Constantinescu   Since FormIFunction calculates G = ydot - g(t,y), ydot will be set to (U-U0)/h
335*0bb9014aSEmil Constantinescu */
336*0bb9014aSEmil Constantinescu #undef __FUNCT__
337*0bb9014aSEmil Constantinescu #define __FUNCT__ "SNESTSFormFunction_EIMEX"
338*0bb9014aSEmil Constantinescu static PetscErrorCode SNESTSFormFunction_EIMEX(SNES snes,Vec X,Vec G,TS ts)
339*0bb9014aSEmil Constantinescu {
340*0bb9014aSEmil Constantinescu   TS_EIMEX        *ext = (TS_EIMEX*)ts->data;
341*0bb9014aSEmil Constantinescu   PetscErrorCode  ierr;
342*0bb9014aSEmil Constantinescu   Vec             Ydot,Z;
343*0bb9014aSEmil Constantinescu   DM              dm,dmsave;
344*0bb9014aSEmil Constantinescu 
345*0bb9014aSEmil Constantinescu   PetscFunctionBegin;
346*0bb9014aSEmil Constantinescu   ierr = VecZeroEntries(G);CHKERRQ(ierr);
347*0bb9014aSEmil Constantinescu 
348*0bb9014aSEmil Constantinescu   ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr);
349*0bb9014aSEmil Constantinescu   ierr = TSEIMEXGetVecs(ts,dm,&Z,&Ydot,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
350*0bb9014aSEmil Constantinescu   ierr = VecZeroEntries(Ydot);CHKERRQ(ierr);
351*0bb9014aSEmil Constantinescu   dmsave = ts->dm;
352*0bb9014aSEmil Constantinescu   ts->dm = dm;
353*0bb9014aSEmil Constantinescu   ierr = TSComputeIFunction(ts,ext->ctime,X,Ydot,G,PETSC_FALSE);CHKERRQ(ierr);
354*0bb9014aSEmil Constantinescu   /* PETSC_FALSE indicates non-imex, adding explicit RHS to the implicit I function.  */
355*0bb9014aSEmil Constantinescu   ierr = VecCopy(G,Ydot);CHKERRQ(ierr);
356*0bb9014aSEmil Constantinescu   ts->dm = dmsave;
357*0bb9014aSEmil Constantinescu   ierr = TSEIMEXRestoreVecs(ts,dm,&Z,&Ydot,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
358*0bb9014aSEmil Constantinescu 
359*0bb9014aSEmil Constantinescu   PetscFunctionReturn(0);
360*0bb9014aSEmil Constantinescu }
361*0bb9014aSEmil Constantinescu 
362*0bb9014aSEmil Constantinescu /*
363*0bb9014aSEmil Constantinescu  This defined the Jacobian matrix for SNES. Jn = (I/h-g'(t,y))
364*0bb9014aSEmil Constantinescu  */
365*0bb9014aSEmil Constantinescu #undef __FUNCT__
366*0bb9014aSEmil Constantinescu #define __FUNCT__ "SNESTSFormJacobian_EIMEX"
367*0bb9014aSEmil Constantinescu static PetscErrorCode SNESTSFormJacobian_EIMEX(SNES snes,Vec X,Mat *A,Mat *B,MatStructure *str,TS ts)
368*0bb9014aSEmil Constantinescu {
369*0bb9014aSEmil Constantinescu   TS_EIMEX        *ext = (TS_EIMEX*)ts->data;
370*0bb9014aSEmil Constantinescu   Vec             Ydot;
371*0bb9014aSEmil Constantinescu   PetscErrorCode  ierr;
372*0bb9014aSEmil Constantinescu   DM              dm,dmsave;
373*0bb9014aSEmil Constantinescu   PetscFunctionBegin;
374*0bb9014aSEmil Constantinescu   ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr);
375*0bb9014aSEmil Constantinescu   ierr = TSEIMEXGetVecs(ts,dm,PETSC_NULL,&Ydot,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
376*0bb9014aSEmil Constantinescu   /*  ierr = VecZeroEntries(Ydot);CHKERRQ(ierr);*/
377*0bb9014aSEmil Constantinescu   /* ext->Ydot have already been computed in SNESTSFormFunction_EIMEX (SNES guarantees this) */
378*0bb9014aSEmil Constantinescu   dmsave = ts->dm;
379*0bb9014aSEmil Constantinescu   ts->dm = dm;
380*0bb9014aSEmil Constantinescu   ierr = TSComputeIJacobian(ts,ts->ptime,X,Ydot,ext->shift,A,B,str,PETSC_TRUE);CHKERRQ(ierr);
381*0bb9014aSEmil Constantinescu   ts->dm = dmsave;
382*0bb9014aSEmil Constantinescu   ierr = TSEIMEXRestoreVecs(ts,dm,PETSC_NULL,&Ydot,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
383*0bb9014aSEmil Constantinescu   PetscFunctionReturn(0);
384*0bb9014aSEmil Constantinescu }
385*0bb9014aSEmil Constantinescu 
386*0bb9014aSEmil Constantinescu #undef __FUNCT__
387*0bb9014aSEmil Constantinescu #define __FUNCT__ "DMCoarsenHook_TSEIMEX"
388*0bb9014aSEmil Constantinescu static PetscErrorCode DMCoarsenHook_TSEIMEX(DM fine,DM coarse,void *ctx)
389*0bb9014aSEmil Constantinescu {
390*0bb9014aSEmil Constantinescu 
391*0bb9014aSEmil Constantinescu   PetscFunctionBegin;
392*0bb9014aSEmil Constantinescu   PetscFunctionReturn(0);
393*0bb9014aSEmil Constantinescu }
394*0bb9014aSEmil Constantinescu 
395*0bb9014aSEmil Constantinescu #undef __FUNCT__
396*0bb9014aSEmil Constantinescu #define __FUNCT__ "DMRestrictHook_TSEIMEX"
397*0bb9014aSEmil Constantinescu static PetscErrorCode DMRestrictHook_TSEIMEX(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse,void *ctx)
398*0bb9014aSEmil Constantinescu {
399*0bb9014aSEmil Constantinescu   TS ts = (TS)ctx;
400*0bb9014aSEmil Constantinescu   PetscErrorCode ierr;
401*0bb9014aSEmil Constantinescu   Vec Z,Z_c;
402*0bb9014aSEmil Constantinescu 
403*0bb9014aSEmil Constantinescu   PetscFunctionBegin;
404*0bb9014aSEmil Constantinescu   ierr = TSEIMEXGetVecs(ts,fine,&Z,PETSC_NULL,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
405*0bb9014aSEmil Constantinescu   ierr = TSEIMEXGetVecs(ts,coarse,&Z_c,PETSC_NULL,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
406*0bb9014aSEmil Constantinescu   ierr = MatRestrict(restrct,Z,Z_c);CHKERRQ(ierr);
407*0bb9014aSEmil Constantinescu   ierr = VecPointwiseMult(Z_c,rscale,Z_c);CHKERRQ(ierr);
408*0bb9014aSEmil Constantinescu   ierr = TSEIMEXRestoreVecs(ts,fine,&Z,PETSC_NULL,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
409*0bb9014aSEmil Constantinescu   ierr = TSEIMEXRestoreVecs(ts,coarse,&Z_c,PETSC_NULL,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
410*0bb9014aSEmil Constantinescu   PetscFunctionReturn(0);
411*0bb9014aSEmil Constantinescu }
412*0bb9014aSEmil Constantinescu 
413*0bb9014aSEmil Constantinescu 
414*0bb9014aSEmil Constantinescu #undef __FUNCT__
415*0bb9014aSEmil Constantinescu #define __FUNCT__ "TSSetUp_EIMEX"
416*0bb9014aSEmil Constantinescu static PetscErrorCode TSSetUp_EIMEX(TS ts)
417*0bb9014aSEmil Constantinescu {
418*0bb9014aSEmil Constantinescu   TS_EIMEX       *ext = (TS_EIMEX*)ts->data;
419*0bb9014aSEmil Constantinescu   PetscErrorCode ierr;
420*0bb9014aSEmil Constantinescu   DM             dm;
421*0bb9014aSEmil Constantinescu   PetscFunctionBegin;
422*0bb9014aSEmil Constantinescu 
423*0bb9014aSEmil Constantinescu   if (!ext->N){ /*ext->max_rows not set*/
424*0bb9014aSEmil Constantinescu     ierr = TSEIMEXSetMaxRows(ts,TSEIMEXDefault);CHKERRQ(ierr);
425*0bb9014aSEmil Constantinescu   }
426*0bb9014aSEmil Constantinescu   if(-1 == ext->row_ind && -1 == ext->col_ind){
427*0bb9014aSEmil Constantinescu 	ierr = TSEIMEXSetRowCol(ts,ext->max_rows,ext->max_rows);CHKERRQ(ierr);
428*0bb9014aSEmil Constantinescu   }else{/*ext->row_ind and col_ind already set*/
429*0bb9014aSEmil Constantinescu     if(ext->ord_adapt){
430*0bb9014aSEmil Constantinescu       ierr = PetscInfo(ts,"Order adaptivity is enabled and TSEIMEXSetRowCol or -ts_eimex_row_col option will take no effect\n");CHKERRQ(ierr);
431*0bb9014aSEmil Constantinescu 	}
432*0bb9014aSEmil Constantinescu   }
433*0bb9014aSEmil Constantinescu 
434*0bb9014aSEmil Constantinescu   if(ext->ord_adapt){
435*0bb9014aSEmil Constantinescu     ext->nstages = 2; /*Start with the 2-stage scheme*/
436*0bb9014aSEmil Constantinescu 	ierr = TSEIMEXSetRowCol(ts,ext->nstages,ext->nstages);CHKERRQ(ierr);
437*0bb9014aSEmil Constantinescu   }else{
438*0bb9014aSEmil Constantinescu 	ext->nstages = ext->max_rows; /*by default nstages is the same as max_rows, this can be changed by setting order adaptivity */
439*0bb9014aSEmil Constantinescu   }
440*0bb9014aSEmil Constantinescu 
441*0bb9014aSEmil Constantinescu   ierr = VecDuplicateVecs(ts->vec_sol,(1+ext->nstages)*ext->nstages/2,&ext->T);CHKERRQ(ierr);/*full T table*/
442*0bb9014aSEmil Constantinescu   ierr = VecDuplicate(ts->vec_sol,&ext->YdotI);CHKERRQ(ierr);
443*0bb9014aSEmil Constantinescu   ierr = VecDuplicate(ts->vec_sol,&ext->YdotRHS);CHKERRQ(ierr);
444*0bb9014aSEmil Constantinescu   ierr = VecDuplicate(ts->vec_sol,&ext->Ydot);CHKERRQ(ierr);
445*0bb9014aSEmil Constantinescu   ierr = VecDuplicate(ts->vec_sol,&ext->VecSolPrev);CHKERRQ(ierr);
446*0bb9014aSEmil Constantinescu   ierr = VecDuplicate(ts->vec_sol,&ext->Y);CHKERRQ(ierr);
447*0bb9014aSEmil Constantinescu   ierr = VecDuplicate(ts->vec_sol,&ext->Z);CHKERRQ(ierr);
448*0bb9014aSEmil Constantinescu   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
449*0bb9014aSEmil Constantinescu   if (dm) {
450*0bb9014aSEmil Constantinescu     ierr = DMCoarsenHookAdd(dm,DMCoarsenHook_TSEIMEX,DMRestrictHook_TSEIMEX,ts);CHKERRQ(ierr);
451*0bb9014aSEmil Constantinescu   }
452*0bb9014aSEmil Constantinescu   PetscFunctionReturn(0);
453*0bb9014aSEmil Constantinescu }
454*0bb9014aSEmil Constantinescu 
455*0bb9014aSEmil Constantinescu #undef __FUNCT__
456*0bb9014aSEmil Constantinescu #define __FUNCT__ "TSSetFromOptions_EIMEX"
457*0bb9014aSEmil Constantinescu static PetscErrorCode TSSetFromOptions_EIMEX(TS ts)
458*0bb9014aSEmil Constantinescu {
459*0bb9014aSEmil Constantinescu   TS_EIMEX       *ext = (TS_EIMEX*)ts->data;
460*0bb9014aSEmil Constantinescu   PetscErrorCode ierr;
461*0bb9014aSEmil Constantinescu   PetscInt       tindex[2]={TSEIMEXDefault,TSEIMEXDefault};
462*0bb9014aSEmil Constantinescu   PetscInt       np = 2, nrows=TSEIMEXDefault;
463*0bb9014aSEmil Constantinescu   PetscFunctionBegin;
464*0bb9014aSEmil Constantinescu   ierr = PetscOptionsHead("EIMEX ODE solver options");CHKERRQ(ierr);
465*0bb9014aSEmil Constantinescu   {
466*0bb9014aSEmil Constantinescu     PetscBool flg;
467*0bb9014aSEmil Constantinescu     flg  = PETSC_FALSE;
468*0bb9014aSEmil Constantinescu     ierr = PetscOptionsInt("-ts_eimex_max_rows","Define the maximum number of rows used","TSEIMEXSetMaxRows",nrows,&nrows,&flg);CHKERRQ(ierr); /*default value 3*/
469*0bb9014aSEmil Constantinescu     if(flg){
470*0bb9014aSEmil Constantinescu       ierr = TSEIMEXSetMaxRows(ts,nrows);CHKERRQ(ierr);
471*0bb9014aSEmil Constantinescu     }
472*0bb9014aSEmil Constantinescu     ierr = PetscOptionsIntArray("-ts_eimex_row_col","Return the specific term in the T table","TSEIMEXSetRowCol",tindex,&np,&flg);CHKERRQ(ierr);
473*0bb9014aSEmil Constantinescu     if(flg){
474*0bb9014aSEmil Constantinescu       ierr = TSEIMEXSetRowCol(ts,tindex[0],tindex[1]);CHKERRQ(ierr);
475*0bb9014aSEmil Constantinescu     }
476*0bb9014aSEmil Constantinescu     ierr = PetscOptionsBool("-ts_eimex_order_adapt","Solve the problem with adaptive order","TSEIMEXSetOrdAdapt",ext->ord_adapt,&ext->ord_adapt,PETSC_NULL);CHKERRQ(ierr);
477*0bb9014aSEmil Constantinescu     ierr = SNESSetFromOptions(ts->snes);CHKERRQ(ierr);
478*0bb9014aSEmil Constantinescu 
479*0bb9014aSEmil Constantinescu     /*prevent users from changing SNESType*/
480*0bb9014aSEmil Constantinescu   }
481*0bb9014aSEmil Constantinescu   ierr = PetscOptionsTail();CHKERRQ(ierr);
482*0bb9014aSEmil Constantinescu   PetscFunctionReturn(0);
483*0bb9014aSEmil Constantinescu }
484*0bb9014aSEmil Constantinescu 
485*0bb9014aSEmil Constantinescu #undef __FUNCT__
486*0bb9014aSEmil Constantinescu #define __FUNCT__ "TSView_EIMEX"
487*0bb9014aSEmil Constantinescu static PetscErrorCode TSView_EIMEX(TS ts,PetscViewer viewer)
488*0bb9014aSEmil Constantinescu {
489*0bb9014aSEmil Constantinescu   /*  TS_EIMEX         *ext = (TS_EIMEX*)ts->data;*/
490*0bb9014aSEmil Constantinescu   PetscBool        iascii;
491*0bb9014aSEmil Constantinescu   PetscErrorCode   ierr;
492*0bb9014aSEmil Constantinescu 
493*0bb9014aSEmil Constantinescu   PetscFunctionBegin;
494*0bb9014aSEmil Constantinescu   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
495*0bb9014aSEmil Constantinescu   if (iascii) {
496*0bb9014aSEmil Constantinescu     ierr = PetscViewerASCIIPrintf(viewer,"  EIMEX\n");CHKERRQ(ierr);
497*0bb9014aSEmil Constantinescu   }
498*0bb9014aSEmil Constantinescu   ierr = SNESView(ts->snes,viewer);CHKERRQ(ierr);
499*0bb9014aSEmil Constantinescu   PetscFunctionReturn(0);
500*0bb9014aSEmil Constantinescu }
501*0bb9014aSEmil Constantinescu 
502*0bb9014aSEmil Constantinescu 
503*0bb9014aSEmil Constantinescu #undef __FUNCT__
504*0bb9014aSEmil Constantinescu #define __FUNCT__ "TSEIMEXSetMaxRows"
505*0bb9014aSEmil Constantinescu /*@C
506*0bb9014aSEmil Constantinescu   TSEIMEXSetMaxRows - Set the maximum number of rows for EIMEX schemes
507*0bb9014aSEmil Constantinescu 
508*0bb9014aSEmil Constantinescu   Logically collective
509*0bb9014aSEmil Constantinescu 
510*0bb9014aSEmil Constantinescu   Input Parameter:
511*0bb9014aSEmil Constantinescu +  ts - timestepping context
512*0bb9014aSEmil Constantinescu -  nrows - maximum number of rows
513*0bb9014aSEmil Constantinescu 
514*0bb9014aSEmil Constantinescu   Level: intermediate
515*0bb9014aSEmil Constantinescu 
516*0bb9014aSEmil Constantinescu .seealso: TSEIMEXSetRowCol(), TSEIMEXSetOrdAdapt(), TSEIMEX
517*0bb9014aSEmil Constantinescu @*/
518*0bb9014aSEmil Constantinescu PetscErrorCode TSEIMEXSetMaxRows(TS ts, PetscInt nrows)
519*0bb9014aSEmil Constantinescu {
520*0bb9014aSEmil Constantinescu   PetscErrorCode ierr;
521*0bb9014aSEmil Constantinescu   PetscFunctionBegin;
522*0bb9014aSEmil Constantinescu   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
523*0bb9014aSEmil Constantinescu   ierr = PetscTryMethod(ts,"TSEIMEXSetMaxRows_C",(TS,PetscInt),(ts,nrows));CHKERRQ(ierr);
524*0bb9014aSEmil Constantinescu   PetscFunctionReturn(0);
525*0bb9014aSEmil Constantinescu }
526*0bb9014aSEmil Constantinescu 
527*0bb9014aSEmil Constantinescu 
528*0bb9014aSEmil Constantinescu #undef __FUNCT__
529*0bb9014aSEmil Constantinescu #define __FUNCT__ "TSEIMEXSetRowCol"
530*0bb9014aSEmil Constantinescu /*@C
531*0bb9014aSEmil Constantinescu   TSEIMEXSetRowCol - Set the type index in the T table for the return value
532*0bb9014aSEmil Constantinescu 
533*0bb9014aSEmil Constantinescu   Logically collective
534*0bb9014aSEmil Constantinescu 
535*0bb9014aSEmil Constantinescu   Input Parameter:
536*0bb9014aSEmil Constantinescu +  ts - timestepping context
537*0bb9014aSEmil Constantinescu -  tindex - index in the T table
538*0bb9014aSEmil Constantinescu 
539*0bb9014aSEmil Constantinescu   Level: intermediate
540*0bb9014aSEmil Constantinescu 
541*0bb9014aSEmil Constantinescu .seealso: TSEIMEXSetMaxRows(), TSEIMEXSetOrdAdapt(), TSEIMEX
542*0bb9014aSEmil Constantinescu @*/
543*0bb9014aSEmil Constantinescu PetscErrorCode TSEIMEXSetRowCol(TS ts, PetscInt row, PetscInt col)
544*0bb9014aSEmil Constantinescu {
545*0bb9014aSEmil Constantinescu   PetscErrorCode ierr;
546*0bb9014aSEmil Constantinescu   PetscFunctionBegin;
547*0bb9014aSEmil Constantinescu   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
548*0bb9014aSEmil Constantinescu   ierr = PetscTryMethod(ts,"TSEIMEXSetRowCol_C",(TS,PetscInt, PetscInt),(ts,row,col));CHKERRQ(ierr);
549*0bb9014aSEmil Constantinescu   PetscFunctionReturn(0);
550*0bb9014aSEmil Constantinescu }
551*0bb9014aSEmil Constantinescu 
552*0bb9014aSEmil Constantinescu 
553*0bb9014aSEmil Constantinescu #undef __FUNCT__
554*0bb9014aSEmil Constantinescu #define __FUNCT__ "TSEIMEXSetOrdAdapt"
555*0bb9014aSEmil Constantinescu /*@C
556*0bb9014aSEmil Constantinescu   TSEIMEXSetOrdAdapt - Set the order adaptativity
557*0bb9014aSEmil Constantinescu 
558*0bb9014aSEmil Constantinescu   Logically collective
559*0bb9014aSEmil Constantinescu 
560*0bb9014aSEmil Constantinescu   Input Parameter:
561*0bb9014aSEmil Constantinescu +  ts - timestepping context
562*0bb9014aSEmil Constantinescu -  tindex - index in the T table
563*0bb9014aSEmil Constantinescu 
564*0bb9014aSEmil Constantinescu   Level: intermediate
565*0bb9014aSEmil Constantinescu 
566*0bb9014aSEmil Constantinescu .seealso: TSEIMEXSetRowCol(), TSEIMEXSetOrdAdapt(), TSEIMEX
567*0bb9014aSEmil Constantinescu @*/
568*0bb9014aSEmil Constantinescu PetscErrorCode TSEIMEXSetOrdAdapt(TS ts, PetscBool flg)
569*0bb9014aSEmil Constantinescu {
570*0bb9014aSEmil Constantinescu   PetscErrorCode ierr;
571*0bb9014aSEmil Constantinescu   PetscFunctionBegin;
572*0bb9014aSEmil Constantinescu   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
573*0bb9014aSEmil Constantinescu   ierr = PetscTryMethod(ts,"TSEIMEXSetOrdAdapt_C",(TS,PetscBool),(ts,flg));CHKERRQ(ierr);
574*0bb9014aSEmil Constantinescu   PetscFunctionReturn(0);
575*0bb9014aSEmil Constantinescu }
576*0bb9014aSEmil Constantinescu 
577*0bb9014aSEmil Constantinescu 
578*0bb9014aSEmil Constantinescu EXTERN_C_BEGIN
579*0bb9014aSEmil Constantinescu #undef __FUNCT__
580*0bb9014aSEmil Constantinescu #define __FUNCT__ "TSEIMEXSetMaxRows_EIMEX"
581*0bb9014aSEmil Constantinescu PetscErrorCode  TSEIMEXSetMaxRows_EIMEX(TS ts,PetscInt nrows)
582*0bb9014aSEmil Constantinescu {
583*0bb9014aSEmil Constantinescu   TS_EIMEX *ext = (TS_EIMEX*)ts->data;
584*0bb9014aSEmil Constantinescu   PetscErrorCode ierr;
585*0bb9014aSEmil Constantinescu   PetscInt       i;
586*0bb9014aSEmil Constantinescu 
587*0bb9014aSEmil Constantinescu   PetscFunctionBegin;
588*0bb9014aSEmil Constantinescu   if (nrows < 0 || nrows > 100) SETERRQ1(((PetscObject)ts)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Max number of rows (current value %D) should be an integer number between 1 and 100\n",nrows);
589*0bb9014aSEmil Constantinescu   if(ext->N){
590*0bb9014aSEmil Constantinescu 	ierr = PetscFree(ext->N);CHKERRQ(ierr);
591*0bb9014aSEmil Constantinescu   }
592*0bb9014aSEmil Constantinescu   ext->max_rows = nrows;
593*0bb9014aSEmil Constantinescu   ierr = PetscMalloc(nrows*sizeof(PetscInt),&ext->N);CHKERRQ(ierr);
594*0bb9014aSEmil Constantinescu   for(i=0;i<nrows;i++) ext->N[i]=i+1;
595*0bb9014aSEmil Constantinescu   PetscFunctionReturn(0);
596*0bb9014aSEmil Constantinescu }
597*0bb9014aSEmil Constantinescu 
598*0bb9014aSEmil Constantinescu #undef __FUNCT__
599*0bb9014aSEmil Constantinescu #define __FUNCT__ "TSEIMEXSetRowCol_EIMEX"
600*0bb9014aSEmil Constantinescu PetscErrorCode  TSEIMEXSetRowCol_EIMEX(TS ts,PetscInt row,PetscInt col)
601*0bb9014aSEmil Constantinescu {
602*0bb9014aSEmil Constantinescu   TS_EIMEX *ext = (TS_EIMEX*)ts->data;
603*0bb9014aSEmil Constantinescu 
604*0bb9014aSEmil Constantinescu   PetscFunctionBegin;
605*0bb9014aSEmil Constantinescu   if (row < 1 || col < 1) SETERRQ2(((PetscObject)ts)->comm,PETSC_ERR_ARG_OUTOFRANGE,"The row or column index (current value %d,%d) should not be less than 1 \n",row,col);
606*0bb9014aSEmil Constantinescu   if (row > ext->max_rows || col > ext->max_rows) SETERRQ3(((PetscObject)ts)->comm,PETSC_ERR_ARG_OUTOFRANGE,"The row or column index (current value %d,%d) exceeds the maximum number of rows %d\n",row,col,ext->max_rows);
607*0bb9014aSEmil Constantinescu   if (col > row) SETERRQ2(((PetscObject)ts)->comm,PETSC_ERR_ARG_OUTOFRANGE,"The column index (%d) exceeds the row index (%d)\n",col,row);
608*0bb9014aSEmil Constantinescu 
609*0bb9014aSEmil Constantinescu   ext->row_ind = row - 1;
610*0bb9014aSEmil Constantinescu   ext->col_ind = col - 1; /*Array index in C starts from 0*/
611*0bb9014aSEmil Constantinescu   PetscFunctionReturn(0);
612*0bb9014aSEmil Constantinescu }
613*0bb9014aSEmil Constantinescu 
614*0bb9014aSEmil Constantinescu #undef __FUNCT__
615*0bb9014aSEmil Constantinescu #define __FUNCT__ "TSEIMEXSetOrdAdapt_EIMEX"
616*0bb9014aSEmil Constantinescu PetscErrorCode  TSEIMEXSetOrdAdapt_EIMEX(TS ts,PetscBool flg)
617*0bb9014aSEmil Constantinescu {
618*0bb9014aSEmil Constantinescu   TS_EIMEX *ext = (TS_EIMEX*)ts->data;
619*0bb9014aSEmil Constantinescu   PetscFunctionBegin;
620*0bb9014aSEmil Constantinescu   ext->ord_adapt = flg;
621*0bb9014aSEmil Constantinescu   PetscFunctionReturn(0);
622*0bb9014aSEmil Constantinescu }
623*0bb9014aSEmil Constantinescu EXTERN_C_END
624*0bb9014aSEmil Constantinescu 
625*0bb9014aSEmil Constantinescu /* ------------------------------------------------------------ */
626*0bb9014aSEmil Constantinescu /*MC
627*0bb9014aSEmil Constantinescu       TSEIMEX - ODE solver using extrapolated IMEX schemes
628*0bb9014aSEmil Constantinescu   These methods are intended for problems with well-separated time scales, especially when a slow scale is strongly nonlinear such that it is expensive to solve with a fully implicit method. The user should provide the stiff part of the equation using TSSetIFunction() and the non-stiff part with TSSetRHSFunction().
629*0bb9014aSEmil Constantinescu 
630*0bb9014aSEmil Constantinescu    Notes:
631*0bb9014aSEmil Constantinescu   The default is a 3-stage scheme, it can be changed with TSEIMEXSetMaxRows() or -ts_eimex_max_rows
632*0bb9014aSEmil Constantinescu 
633*0bb9014aSEmil Constantinescu   This method currently only works with ODE, for which the stiff part G(t,X,Xdot) has the form Xdot + Ghat(t,X).
634*0bb9014aSEmil Constantinescu 
635*0bb9014aSEmil Constantinescu   Level: beginner
636*0bb9014aSEmil Constantinescu 
637*0bb9014aSEmil Constantinescu .seealso:  TSCreate(), TS
638*0bb9014aSEmil Constantinescu M*/
639*0bb9014aSEmil Constantinescu EXTERN_C_BEGIN
640*0bb9014aSEmil Constantinescu #undef __FUNCT__
641*0bb9014aSEmil Constantinescu #define __FUNCT__ "TSCreate_EIMEX"
642*0bb9014aSEmil Constantinescu PetscErrorCode  TSCreate_EIMEX(TS ts)
643*0bb9014aSEmil Constantinescu {
644*0bb9014aSEmil Constantinescu   TS_EIMEX       *ext;
645*0bb9014aSEmil Constantinescu   PetscErrorCode ierr;
646*0bb9014aSEmil Constantinescu 
647*0bb9014aSEmil Constantinescu   PetscFunctionBegin;
648*0bb9014aSEmil Constantinescu 
649*0bb9014aSEmil Constantinescu   ts->ops->reset          = TSReset_EIMEX;
650*0bb9014aSEmil Constantinescu   ts->ops->destroy        = TSDestroy_EIMEX;
651*0bb9014aSEmil Constantinescu   ts->ops->view           = TSView_EIMEX;
652*0bb9014aSEmil Constantinescu   ts->ops->setup          = TSSetUp_EIMEX;
653*0bb9014aSEmil Constantinescu   ts->ops->step           = TSStep_EIMEX;
654*0bb9014aSEmil Constantinescu   ts->ops->interpolate    = TSInterpolate_EIMEX;
655*0bb9014aSEmil Constantinescu   ts->ops->evaluatestep   = TSEvaluateStep_EIMEX;
656*0bb9014aSEmil Constantinescu   ts->ops->setfromoptions = TSSetFromOptions_EIMEX;
657*0bb9014aSEmil Constantinescu   ts->ops->snesfunction   = SNESTSFormFunction_EIMEX;
658*0bb9014aSEmil Constantinescu   ts->ops->snesjacobian   = SNESTSFormJacobian_EIMEX;
659*0bb9014aSEmil Constantinescu 
660*0bb9014aSEmil Constantinescu   ierr = PetscNewLog(ts,TS_EIMEX,&ext);CHKERRQ(ierr);
661*0bb9014aSEmil Constantinescu   ts->data = (void*)ext;
662*0bb9014aSEmil Constantinescu 
663*0bb9014aSEmil Constantinescu   ext->ord_adapt = PETSC_FALSE; /*By default, no order adapativity*/
664*0bb9014aSEmil Constantinescu   ext->row_ind   = -1;
665*0bb9014aSEmil Constantinescu   ext->col_ind   = -1;
666*0bb9014aSEmil Constantinescu   ext->max_rows  = TSEIMEXDefault;
667*0bb9014aSEmil Constantinescu   ext->nstages   = TSEIMEXDefault;
668*0bb9014aSEmil Constantinescu 
669*0bb9014aSEmil Constantinescu   ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSEIMEXSetMaxRows_C","TSEIMEXSetMaxRows_EIMEX",TSEIMEXSetMaxRows_EIMEX);CHKERRQ(ierr);
670*0bb9014aSEmil Constantinescu   ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSEIMEXSetRowCol_C","TSEIMEXSetRowCol_EIMEX",TSEIMEXSetRowCol_EIMEX);CHKERRQ(ierr);
671*0bb9014aSEmil Constantinescu   ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSEIMEXSetOrdAdapt_C","TSEIMEXSetOrdAdapt_EIMEX",TSEIMEXSetOrdAdapt_EIMEX);CHKERRQ(ierr);
672*0bb9014aSEmil Constantinescu   PetscFunctionReturn(0);
673*0bb9014aSEmil Constantinescu }
674*0bb9014aSEmil Constantinescu EXTERN_C_END
675*0bb9014aSEmil Constantinescu 
676