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