xref: /petsc/src/ts/impls/implicit/theta/theta.c (revision 277b19d07ec08e548e5816b82c213278d45c3326)
1316643e7SJed Brown 
2316643e7SJed Brown /*
3316643e7SJed Brown   Code for timestepping with implicit Theta method
4316643e7SJed Brown 
5316643e7SJed Brown   Notes:
6316643e7SJed Brown   This method can be applied to DAE.
7316643e7SJed Brown 
8316643e7SJed Brown   This method is cast as a 1-stage implicit Runge-Kutta method.
9316643e7SJed Brown 
10316643e7SJed Brown   Theta | Theta
11316643e7SJed Brown   -------------
12316643e7SJed Brown         |  1
13316643e7SJed Brown 
14316643e7SJed Brown   To apply a diagonally implicit RK method to DAE, the stage formula
15316643e7SJed Brown 
16316643e7SJed Brown   X_i = x + h sum_j a_ij X'_j
17316643e7SJed Brown 
18316643e7SJed Brown   is interpreted as a formula for X'_i in terms of X_i and known stuff (X'_j, j<i)
19316643e7SJed Brown */
20c6db04a5SJed Brown #include <private/tsimpl.h>                /*I   "petscts.h"   I*/
21316643e7SJed Brown 
22316643e7SJed Brown typedef struct {
23316643e7SJed Brown   Vec X,Xdot;                   /* Storage for one stage */
24ace3abfcSBarry Smith   PetscBool extrapolate;
25316643e7SJed Brown   PetscReal Theta;
26316643e7SJed Brown   PetscReal shift;
27316643e7SJed Brown   PetscReal stage_time;
28316643e7SJed Brown } TS_Theta;
29316643e7SJed Brown 
30316643e7SJed Brown #undef __FUNCT__
31316643e7SJed Brown #define __FUNCT__ "TSStep_Theta"
32316643e7SJed Brown static PetscErrorCode TSStep_Theta(TS ts,PetscInt *steps,PetscReal *ptime)
33316643e7SJed Brown {
34316643e7SJed Brown   TS_Theta       *th = (TS_Theta*)ts->data;
352b5a38e1SLisandro Dalcin   PetscInt       i,max_steps = ts->max_steps,its,lits;
362b5a38e1SLisandro Dalcin   PetscErrorCode ierr;
37316643e7SJed Brown 
38316643e7SJed Brown   PetscFunctionBegin;
39316643e7SJed Brown   *steps = -ts->steps;
402b5a38e1SLisandro Dalcin   *ptime = ts->ptime;
412b5a38e1SLisandro Dalcin 
422b5a38e1SLisandro Dalcin   ierr = TSMonitor(ts,ts->steps,ts->ptime,ts->vec_sol);CHKERRQ(ierr);
43316643e7SJed Brown 
44316643e7SJed Brown   for (i=0; i<max_steps; i++) {
45316643e7SJed Brown     if (ts->ptime + ts->time_step > ts->max_time) break;
463f2090d5SJed Brown     ierr = TSPreStep(ts);CHKERRQ(ierr);
472b5a38e1SLisandro Dalcin 
48316643e7SJed Brown     th->stage_time = ts->ptime + th->Theta*ts->time_step;
49316643e7SJed Brown     th->shift = 1./(th->Theta*ts->time_step);
50316643e7SJed Brown 
51ace68cafSJed Brown     if (th->extrapolate) {
522b5a38e1SLisandro Dalcin       ierr = VecWAXPY(th->X,1./th->shift,th->Xdot,ts->vec_sol);CHKERRQ(ierr);
53ace68cafSJed Brown     } else {
542b5a38e1SLisandro Dalcin       ierr = VecCopy(ts->vec_sol,th->X);CHKERRQ(ierr);
55ace68cafSJed Brown     }
56316643e7SJed Brown     ierr = SNESSolve(ts->snes,PETSC_NULL,th->X);CHKERRQ(ierr);
57316643e7SJed Brown     ierr = SNESGetIterationNumber(ts->snes,&its);CHKERRQ(ierr);
58316643e7SJed Brown     ierr = SNESGetLinearSolveIterations(ts->snes,&lits);CHKERRQ(ierr);
59316643e7SJed Brown     ts->nonlinear_its += its; ts->linear_its += lits;
602b5a38e1SLisandro Dalcin 
612b5a38e1SLisandro Dalcin     ierr = VecAXPBYPCZ(th->Xdot,-th->shift,th->shift,0,ts->vec_sol,th->X);CHKERRQ(ierr);
622b5a38e1SLisandro Dalcin     ierr = VecAXPY(ts->vec_sol,ts->time_step,th->Xdot);CHKERRQ(ierr);
632b5a38e1SLisandro Dalcin     ts->ptime += ts->time_step;
64316643e7SJed Brown     ts->steps++;
652b5a38e1SLisandro Dalcin 
663f2090d5SJed Brown     ierr = TSPostStep(ts);CHKERRQ(ierr);
672b5a38e1SLisandro Dalcin     ierr = TSMonitor(ts,ts->steps,ts->ptime,ts->vec_sol);CHKERRQ(ierr);
68316643e7SJed Brown   }
69316643e7SJed Brown 
70316643e7SJed Brown   *steps += ts->steps;
71316643e7SJed Brown   *ptime  = ts->ptime;
72316643e7SJed Brown   PetscFunctionReturn(0);
73316643e7SJed Brown }
74316643e7SJed Brown 
75316643e7SJed Brown /*------------------------------------------------------------*/
76316643e7SJed Brown #undef __FUNCT__
77*277b19d0SLisandro Dalcin #define __FUNCT__ "TSReset_Theta"
78*277b19d0SLisandro Dalcin static PetscErrorCode TSReset_Theta(TS ts)
79316643e7SJed Brown {
80316643e7SJed Brown   TS_Theta       *th = (TS_Theta*)ts->data;
81316643e7SJed Brown   PetscErrorCode  ierr;
82316643e7SJed Brown 
83316643e7SJed Brown   PetscFunctionBegin;
84a5cbb462SJed Brown   if (th->X)    {ierr = VecDestroy(th->X);CHKERRQ(ierr);}
85a5cbb462SJed Brown   if (th->Xdot) {ierr = VecDestroy(th->Xdot);CHKERRQ(ierr);}
86*277b19d0SLisandro Dalcin   PetscFunctionReturn(0);
87*277b19d0SLisandro Dalcin }
88*277b19d0SLisandro Dalcin 
89*277b19d0SLisandro Dalcin #undef __FUNCT__
90*277b19d0SLisandro Dalcin #define __FUNCT__ "TSDestroy_Theta"
91*277b19d0SLisandro Dalcin static PetscErrorCode TSDestroy_Theta(TS ts)
92*277b19d0SLisandro Dalcin {
93*277b19d0SLisandro Dalcin   PetscErrorCode  ierr;
94*277b19d0SLisandro Dalcin 
95*277b19d0SLisandro Dalcin   PetscFunctionBegin;
96*277b19d0SLisandro Dalcin   ierr = TSReset_Theta(ts);CHKERRQ(ierr);
97*277b19d0SLisandro Dalcin   ierr = PetscFree(ts->data);CHKERRQ(ierr);
98316643e7SJed Brown   PetscFunctionReturn(0);
99316643e7SJed Brown }
100316643e7SJed Brown 
101316643e7SJed Brown /*
102316643e7SJed Brown   This defines the nonlinear equation that is to be solved with SNES
1032b5a38e1SLisandro Dalcin   G(U) = F[t0+Theta*dt, U, (U-U0)*shift] = 0
104316643e7SJed Brown */
105316643e7SJed Brown #undef __FUNCT__
1060f5c6efeSJed Brown #define __FUNCT__ "SNESTSFormFunction_Theta"
1070f5c6efeSJed Brown static PetscErrorCode SNESTSFormFunction_Theta(SNES snes,Vec x,Vec y,TS ts)
108316643e7SJed Brown {
109316643e7SJed Brown   TS_Theta *th = (TS_Theta*)ts->data;
110316643e7SJed Brown   PetscErrorCode ierr;
111316643e7SJed Brown 
112316643e7SJed Brown   PetscFunctionBegin;
1132b5a38e1SLisandro Dalcin   ierr = VecAXPBYPCZ(th->Xdot,-th->shift,th->shift,0,ts->vec_sol,x);CHKERRQ(ierr);
114316643e7SJed Brown   ierr = TSComputeIFunction(ts,th->stage_time,x,th->Xdot,y);CHKERRQ(ierr);
115316643e7SJed Brown   PetscFunctionReturn(0);
116316643e7SJed Brown }
117316643e7SJed Brown 
118316643e7SJed Brown #undef __FUNCT__
1190f5c6efeSJed Brown #define __FUNCT__ "SNESTSFormJacobian_Theta"
1200f5c6efeSJed Brown static PetscErrorCode SNESTSFormJacobian_Theta(SNES snes,Vec x,Mat *A,Mat *B,MatStructure *str,TS ts)
121316643e7SJed Brown {
122316643e7SJed Brown   TS_Theta *th = (TS_Theta*)ts->data;
123316643e7SJed Brown   PetscErrorCode ierr;
124316643e7SJed Brown 
125316643e7SJed Brown   PetscFunctionBegin;
1260f5c6efeSJed Brown   /* th->Xdot has already been computed in SNESTSFormFunction_Theta (SNES guarantees this) */
127316643e7SJed Brown   ierr = TSComputeIJacobian(ts,th->stage_time,x,th->Xdot,th->shift,A,B,str);CHKERRQ(ierr);
128316643e7SJed Brown   PetscFunctionReturn(0);
129316643e7SJed Brown }
130316643e7SJed Brown 
131316643e7SJed Brown 
132316643e7SJed Brown #undef __FUNCT__
133316643e7SJed Brown #define __FUNCT__ "TSSetUp_Theta"
134316643e7SJed Brown static PetscErrorCode TSSetUp_Theta(TS ts)
135316643e7SJed Brown {
136316643e7SJed Brown   TS_Theta *th = (TS_Theta*)ts->data;
137316643e7SJed Brown   PetscErrorCode ierr;
138a6e0575dSJed Brown   Vec            res;
139316643e7SJed Brown 
140316643e7SJed Brown   PetscFunctionBegin;
14117186662SBarry Smith   if (ts->problem_type == TS_LINEAR) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Only for nonlinear problems");
142316643e7SJed Brown   ierr = VecDuplicate(ts->vec_sol,&th->X);CHKERRQ(ierr);
143316643e7SJed Brown   ierr = VecDuplicate(ts->vec_sol,&th->Xdot);CHKERRQ(ierr);
144a6e0575dSJed Brown   ierr = VecDuplicate(ts->vec_sol,&res);CHKERRQ(ierr);
145a6e0575dSJed Brown   ierr = SNESSetFunction(ts->snes,res,SNESTSFormFunction,ts);CHKERRQ(ierr);
146a6e0575dSJed Brown   ierr = VecDestroy(res);CHKERRQ(ierr);
1477c0b301bSJed Brown   /* This is nasty.  SNESSetFromOptions() is usually called in TSSetFromOptions().  With -snes_mf_operator, it will
1487c0b301bSJed Brown   replace A and we don't want to mess with that.  With -snes_mf, A and B will be replaced as well as the function and
1497c0b301bSJed Brown   context.  Note that SNESSetFunction() normally has not been called before SNESSetFromOptions(), so when -snes_mf sets
1507c0b301bSJed Brown   the Jacobian user context to snes->funP, it will actually be NULL.  This is not a problem because both snes->funP and
1517c0b301bSJed Brown   snes->jacP should be the TS. */
1527c0b301bSJed Brown   {
1537c0b301bSJed Brown     Mat A,B;
1547c0b301bSJed Brown     PetscErrorCode (*func)(SNES,Vec,Mat*,Mat*,MatStructure*,void*);
1557c0b301bSJed Brown     void *ctx;
1567c0b301bSJed Brown     ierr = SNESGetJacobian(ts->snes,&A,&B,&func,&ctx);CHKERRQ(ierr);
1570f5c6efeSJed Brown     ierr = SNESSetJacobian(ts->snes,A?A:ts->A,B?B:ts->B,func?func:&SNESTSFormJacobian,ctx?ctx:ts);CHKERRQ(ierr);
1587c0b301bSJed Brown   }
159316643e7SJed Brown   PetscFunctionReturn(0);
160316643e7SJed Brown }
161316643e7SJed Brown /*------------------------------------------------------------*/
162316643e7SJed Brown 
163316643e7SJed Brown #undef __FUNCT__
164316643e7SJed Brown #define __FUNCT__ "TSSetFromOptions_Theta"
165316643e7SJed Brown static PetscErrorCode TSSetFromOptions_Theta(TS ts)
166316643e7SJed Brown {
167316643e7SJed Brown   TS_Theta *th = (TS_Theta*)ts->data;
168316643e7SJed Brown   PetscErrorCode ierr;
169316643e7SJed Brown 
170316643e7SJed Brown   PetscFunctionBegin;
171d73342a9SJed Brown   ierr = PetscOptionsHead("Theta ODE solver options");CHKERRQ(ierr);
172316643e7SJed Brown   {
173316643e7SJed Brown     ierr = PetscOptionsReal("-ts_theta_theta","Location of stage (0<Theta<=1)","TSThetaSetTheta",th->Theta,&th->Theta,PETSC_NULL);CHKERRQ(ierr);
174acfcf0e5SJed Brown     ierr = PetscOptionsBool("-ts_theta_extrapolate","Extrapolate stage solution from previous solution (sometimes unstable)","TSThetaSetExtrapolate",th->extrapolate,&th->extrapolate,PETSC_NULL);CHKERRQ(ierr);
175316643e7SJed Brown   }
176316643e7SJed Brown   ierr = PetscOptionsTail();CHKERRQ(ierr);
177316643e7SJed Brown   PetscFunctionReturn(0);
178316643e7SJed Brown }
179316643e7SJed Brown 
180316643e7SJed Brown #undef __FUNCT__
181316643e7SJed Brown #define __FUNCT__ "TSView_Theta"
182316643e7SJed Brown static PetscErrorCode TSView_Theta(TS ts,PetscViewer viewer)
183316643e7SJed Brown {
184316643e7SJed Brown   TS_Theta       *th = (TS_Theta*)ts->data;
185ace3abfcSBarry Smith   PetscBool       iascii;
186316643e7SJed Brown   PetscErrorCode  ierr;
187316643e7SJed Brown 
188316643e7SJed Brown   PetscFunctionBegin;
1892692d6eeSBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
190316643e7SJed Brown   if (iascii) {
191316643e7SJed Brown     ierr = PetscViewerASCIIPrintf(viewer,"  Theta=%G\n",th->Theta);CHKERRQ(ierr);
192ace68cafSJed Brown     ierr = PetscViewerASCIIPrintf(viewer,"  Extrapolation=%s\n",th->extrapolate?"yes":"no");CHKERRQ(ierr);
193316643e7SJed Brown   } else {
194e32f2f54SBarry Smith     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported for TS_Theta",((PetscObject)viewer)->type_name);
195316643e7SJed Brown   }
196316643e7SJed Brown   PetscFunctionReturn(0);
197316643e7SJed Brown }
198316643e7SJed Brown 
1990de4c49aSJed Brown EXTERN_C_BEGIN
2000de4c49aSJed Brown #undef __FUNCT__
2010de4c49aSJed Brown #define __FUNCT__ "TSThetaGetTheta_Theta"
2027087cfbeSBarry Smith PetscErrorCode  TSThetaGetTheta_Theta(TS ts,PetscReal *theta)
2030de4c49aSJed Brown {
2040de4c49aSJed Brown   TS_Theta *th = (TS_Theta*)ts->data;
2050de4c49aSJed Brown 
2060de4c49aSJed Brown   PetscFunctionBegin;
2070de4c49aSJed Brown   *theta = th->Theta;
2080de4c49aSJed Brown   PetscFunctionReturn(0);
2090de4c49aSJed Brown }
2100de4c49aSJed Brown 
2110de4c49aSJed Brown #undef __FUNCT__
2120de4c49aSJed Brown #define __FUNCT__ "TSThetaSetTheta_Theta"
2137087cfbeSBarry Smith PetscErrorCode  TSThetaSetTheta_Theta(TS ts,PetscReal theta)
2140de4c49aSJed Brown {
2150de4c49aSJed Brown   TS_Theta *th = (TS_Theta*)ts->data;
2160de4c49aSJed Brown 
2170de4c49aSJed Brown   PetscFunctionBegin;
218e7be1afaSJed Brown   if (theta <= 0 || 1 < theta) SETERRQ1(((PetscObject)ts)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Theta %G not in range (0,1]",theta);
2190de4c49aSJed Brown   th->Theta = theta;
2200de4c49aSJed Brown   PetscFunctionReturn(0);
2210de4c49aSJed Brown }
2220de4c49aSJed Brown EXTERN_C_END
2230de4c49aSJed Brown 
224316643e7SJed Brown /* ------------------------------------------------------------ */
225316643e7SJed Brown /*MC
22696f5712cSJed Brown       TSTHETA - DAE solver using the implicit Theta method
227316643e7SJed Brown 
228316643e7SJed Brown   Level: beginner
229316643e7SJed Brown 
230316643e7SJed Brown .seealso:  TSCreate(), TS, TSSetType()
231316643e7SJed Brown 
232316643e7SJed Brown M*/
233316643e7SJed Brown EXTERN_C_BEGIN
234316643e7SJed Brown #undef __FUNCT__
235316643e7SJed Brown #define __FUNCT__ "TSCreate_Theta"
2367087cfbeSBarry Smith PetscErrorCode  TSCreate_Theta(TS ts)
237316643e7SJed Brown {
238316643e7SJed Brown   TS_Theta       *th;
239316643e7SJed Brown   PetscErrorCode ierr;
240316643e7SJed Brown 
241316643e7SJed Brown   PetscFunctionBegin;
242*277b19d0SLisandro Dalcin   ts->ops->reset          = TSReset_Theta;
243316643e7SJed Brown   ts->ops->destroy        = TSDestroy_Theta;
244316643e7SJed Brown   ts->ops->view           = TSView_Theta;
245316643e7SJed Brown   ts->ops->setup          = TSSetUp_Theta;
246316643e7SJed Brown   ts->ops->step           = TSStep_Theta;
247316643e7SJed Brown   ts->ops->setfromoptions = TSSetFromOptions_Theta;
2480f5c6efeSJed Brown   ts->ops->snesfunction   = SNESTSFormFunction_Theta;
2490f5c6efeSJed Brown   ts->ops->snesjacobian   = SNESTSFormJacobian_Theta;
250316643e7SJed Brown 
2512b5a38e1SLisandro Dalcin   ts->problem_type = TS_NONLINEAR;
252316643e7SJed Brown   ierr = SNESCreate(((PetscObject)ts)->comm,&ts->snes);CHKERRQ(ierr);
253316643e7SJed Brown   ierr = PetscObjectIncrementTabLevel((PetscObject)ts->snes,(PetscObject)ts,1);CHKERRQ(ierr);
254316643e7SJed Brown 
255316643e7SJed Brown   ierr = PetscNewLog(ts,TS_Theta,&th);CHKERRQ(ierr);
256316643e7SJed Brown   ts->data = (void*)th;
257316643e7SJed Brown 
2586f700aefSJed Brown   th->extrapolate = PETSC_FALSE;
259316643e7SJed Brown   th->Theta       = 0.5;
260316643e7SJed Brown 
2610de4c49aSJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSThetaGetTheta_C","TSThetaGetTheta_Theta",TSThetaGetTheta_Theta);CHKERRQ(ierr);
2620de4c49aSJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSThetaSetTheta_C","TSThetaSetTheta_Theta",TSThetaSetTheta_Theta);CHKERRQ(ierr);
263316643e7SJed Brown   PetscFunctionReturn(0);
264316643e7SJed Brown }
265316643e7SJed Brown EXTERN_C_END
2660de4c49aSJed Brown 
2670de4c49aSJed Brown #undef __FUNCT__
2680de4c49aSJed Brown #define __FUNCT__ "TSThetaGetTheta"
2690de4c49aSJed Brown /*@
2700de4c49aSJed Brown   TSThetaGetTheta - Get the abscissa of the stage in (0,1].
2710de4c49aSJed Brown 
2720de4c49aSJed Brown   Not Collective
2730de4c49aSJed Brown 
2740de4c49aSJed Brown   Input Parameter:
2750de4c49aSJed Brown .  ts - timestepping context
2760de4c49aSJed Brown 
2770de4c49aSJed Brown   Output Parameter:
2780de4c49aSJed Brown .  theta - stage abscissa
2790de4c49aSJed Brown 
2800de4c49aSJed Brown   Note:
2810de4c49aSJed Brown   Use of this function is normally only required to hack TSTHETA to use a modified integration scheme.
2820de4c49aSJed Brown 
2830de4c49aSJed Brown   Level: Advanced
2840de4c49aSJed Brown 
2850de4c49aSJed Brown .seealso: TSThetaSetTheta()
2860de4c49aSJed Brown @*/
2877087cfbeSBarry Smith PetscErrorCode  TSThetaGetTheta(TS ts,PetscReal *theta)
2880de4c49aSJed Brown {
2894ac538c5SBarry Smith   PetscErrorCode ierr;
2900de4c49aSJed Brown 
2910de4c49aSJed Brown   PetscFunctionBegin;
292afb20b64SJed Brown   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2930de4c49aSJed Brown   PetscValidPointer(theta,2);
2944ac538c5SBarry Smith   ierr = PetscUseMethod(ts,"TSThetaGetTheta_C",(TS,PetscReal*),(ts,theta));CHKERRQ(ierr);
2950de4c49aSJed Brown   PetscFunctionReturn(0);
2960de4c49aSJed Brown }
2970de4c49aSJed Brown 
2980de4c49aSJed Brown #undef __FUNCT__
2990de4c49aSJed Brown #define __FUNCT__ "TSThetaSetTheta"
3000de4c49aSJed Brown /*@
3010de4c49aSJed Brown   TSThetaSetTheta - Set the abscissa of the stage in (0,1].
3020de4c49aSJed Brown 
3030de4c49aSJed Brown   Not Collective
3040de4c49aSJed Brown 
3050de4c49aSJed Brown   Input Parameter:
3060de4c49aSJed Brown +  ts - timestepping context
3070de4c49aSJed Brown -  theta - stage abscissa
3080de4c49aSJed Brown 
3090de4c49aSJed Brown   Options Database:
3100de4c49aSJed Brown .  -ts_theta_theta <theta>
3110de4c49aSJed Brown 
3120de4c49aSJed Brown   Level: Intermediate
3130de4c49aSJed Brown 
3140de4c49aSJed Brown .seealso: TSThetaGetTheta()
3150de4c49aSJed Brown @*/
3167087cfbeSBarry Smith PetscErrorCode  TSThetaSetTheta(TS ts,PetscReal theta)
3170de4c49aSJed Brown {
3184ac538c5SBarry Smith   PetscErrorCode ierr;
3190de4c49aSJed Brown 
3200de4c49aSJed Brown   PetscFunctionBegin;
321afb20b64SJed Brown   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3224ac538c5SBarry Smith   ierr = PetscTryMethod(ts,"TSThetaSetTheta_C",(TS,PetscReal),(ts,theta));CHKERRQ(ierr);
3230de4c49aSJed Brown   PetscFunctionReturn(0);
3240de4c49aSJed Brown }
325