1 /* 2 Code for timestepping with implicit Theta method 3 4 Notes: 5 This method can be applied to DAE. 6 7 This method is cast as a 1-stage implicit Runge-Kutta method. 8 9 Theta | Theta 10 ------------- 11 | 1 12 13 To apply a diagonally implicit RK method to DAE, the stage formula 14 15 X_i = x + h sum_j a_ij X'_j 16 17 is interpreted as a formula for X'_i in terms of X_i and known stuff (X'_j, j<i) 18 */ 19 #include <private/tsimpl.h> /*I "petscts.h" I*/ 20 21 typedef struct { 22 Vec X,Xdot; /* Storage for one stage */ 23 PetscBool extrapolate; 24 PetscReal Theta; 25 PetscReal shift; 26 PetscReal stage_time; 27 } TS_Theta; 28 29 #undef __FUNCT__ 30 #define __FUNCT__ "TSStep_Theta" 31 static PetscErrorCode TSStep_Theta(TS ts) 32 { 33 TS_Theta *th = (TS_Theta*)ts->data; 34 PetscInt its,lits; 35 PetscErrorCode ierr; 36 37 PetscFunctionBegin; 38 ts->time_step = ts->next_time_step; 39 th->stage_time = ts->ptime + th->Theta*ts->time_step; 40 th->shift = 1./(th->Theta*ts->time_step); 41 42 if (th->extrapolate) { 43 ierr = VecWAXPY(th->X,1./th->shift,th->Xdot,ts->vec_sol);CHKERRQ(ierr); 44 } else { 45 ierr = VecCopy(ts->vec_sol,th->X);CHKERRQ(ierr); 46 } 47 ierr = SNESSolve(ts->snes,PETSC_NULL,th->X);CHKERRQ(ierr); 48 ierr = SNESGetIterationNumber(ts->snes,&its);CHKERRQ(ierr); 49 ierr = SNESGetLinearSolveIterations(ts->snes,&lits);CHKERRQ(ierr); 50 ts->nonlinear_its += its; ts->linear_its += lits; 51 52 ierr = VecAXPBYPCZ(th->Xdot,-th->shift,th->shift,0,ts->vec_sol,th->X);CHKERRQ(ierr); 53 ierr = VecAXPY(ts->vec_sol,ts->time_step,th->Xdot);CHKERRQ(ierr); 54 ts->ptime += ts->time_step; 55 ts->next_time_step = ts->time_step; 56 ts->steps++; 57 PetscFunctionReturn(0); 58 } 59 60 /*------------------------------------------------------------*/ 61 #undef __FUNCT__ 62 #define __FUNCT__ "TSReset_Theta" 63 static PetscErrorCode TSReset_Theta(TS ts) 64 { 65 TS_Theta *th = (TS_Theta*)ts->data; 66 PetscErrorCode ierr; 67 68 PetscFunctionBegin; 69 ierr = VecDestroy(&th->X);CHKERRQ(ierr); 70 ierr = VecDestroy(&th->Xdot);CHKERRQ(ierr); 71 PetscFunctionReturn(0); 72 } 73 74 #undef __FUNCT__ 75 #define __FUNCT__ "TSDestroy_Theta" 76 static PetscErrorCode TSDestroy_Theta(TS ts) 77 { 78 PetscErrorCode ierr; 79 80 PetscFunctionBegin; 81 ierr = TSReset_Theta(ts);CHKERRQ(ierr); 82 ierr = PetscFree(ts->data);CHKERRQ(ierr); 83 PetscFunctionReturn(0); 84 } 85 86 /* 87 This defines the nonlinear equation that is to be solved with SNES 88 G(U) = F[t0+Theta*dt, U, (U-U0)*shift] = 0 89 */ 90 #undef __FUNCT__ 91 #define __FUNCT__ "SNESTSFormFunction_Theta" 92 static PetscErrorCode SNESTSFormFunction_Theta(SNES snes,Vec x,Vec y,TS ts) 93 { 94 TS_Theta *th = (TS_Theta*)ts->data; 95 PetscErrorCode ierr; 96 97 PetscFunctionBegin; 98 ierr = VecAXPBYPCZ(th->Xdot,-th->shift,th->shift,0,ts->vec_sol,x);CHKERRQ(ierr); 99 ierr = TSComputeIFunction(ts,th->stage_time,x,th->Xdot,y,PETSC_FALSE);CHKERRQ(ierr); 100 PetscFunctionReturn(0); 101 } 102 103 #undef __FUNCT__ 104 #define __FUNCT__ "SNESTSFormJacobian_Theta" 105 static PetscErrorCode SNESTSFormJacobian_Theta(SNES snes,Vec x,Mat *A,Mat *B,MatStructure *str,TS ts) 106 { 107 TS_Theta *th = (TS_Theta*)ts->data; 108 PetscErrorCode ierr; 109 110 PetscFunctionBegin; 111 /* th->Xdot has already been computed in SNESTSFormFunction_Theta (SNES guarantees this) */ 112 ierr = TSComputeIJacobian(ts,th->stage_time,x,th->Xdot,th->shift,A,B,str,PETSC_FALSE);CHKERRQ(ierr); 113 PetscFunctionReturn(0); 114 } 115 116 117 #undef __FUNCT__ 118 #define __FUNCT__ "TSSetUp_Theta" 119 static PetscErrorCode TSSetUp_Theta(TS ts) 120 { 121 TS_Theta *th = (TS_Theta*)ts->data; 122 PetscErrorCode ierr; 123 124 PetscFunctionBegin; 125 ierr = VecDuplicate(ts->vec_sol,&th->X);CHKERRQ(ierr); 126 ierr = VecDuplicate(ts->vec_sol,&th->Xdot);CHKERRQ(ierr); 127 PetscFunctionReturn(0); 128 } 129 /*------------------------------------------------------------*/ 130 131 #undef __FUNCT__ 132 #define __FUNCT__ "TSSetFromOptions_Theta" 133 static PetscErrorCode TSSetFromOptions_Theta(TS ts) 134 { 135 TS_Theta *th = (TS_Theta*)ts->data; 136 PetscErrorCode ierr; 137 138 PetscFunctionBegin; 139 ierr = PetscOptionsHead("Theta ODE solver options");CHKERRQ(ierr); 140 { 141 ierr = PetscOptionsReal("-ts_theta_theta","Location of stage (0<Theta<=1)","TSThetaSetTheta",th->Theta,&th->Theta,PETSC_NULL);CHKERRQ(ierr); 142 ierr = PetscOptionsBool("-ts_theta_extrapolate","Extrapolate stage solution from previous solution (sometimes unstable)","TSThetaSetExtrapolate",th->extrapolate,&th->extrapolate,PETSC_NULL);CHKERRQ(ierr); 143 } 144 ierr = PetscOptionsTail();CHKERRQ(ierr); 145 PetscFunctionReturn(0); 146 } 147 148 #undef __FUNCT__ 149 #define __FUNCT__ "TSView_Theta" 150 static PetscErrorCode TSView_Theta(TS ts,PetscViewer viewer) 151 { 152 TS_Theta *th = (TS_Theta*)ts->data; 153 PetscBool iascii; 154 PetscErrorCode ierr; 155 156 PetscFunctionBegin; 157 ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 158 if (iascii) { 159 ierr = PetscViewerASCIIPrintf(viewer," Theta=%G\n",th->Theta);CHKERRQ(ierr); 160 ierr = PetscViewerASCIIPrintf(viewer," Extrapolation=%s\n",th->extrapolate?"yes":"no");CHKERRQ(ierr); 161 } else { 162 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported for TS_Theta",((PetscObject)viewer)->type_name); 163 } 164 PetscFunctionReturn(0); 165 } 166 167 EXTERN_C_BEGIN 168 #undef __FUNCT__ 169 #define __FUNCT__ "TSThetaGetTheta_Theta" 170 PetscErrorCode TSThetaGetTheta_Theta(TS ts,PetscReal *theta) 171 { 172 TS_Theta *th = (TS_Theta*)ts->data; 173 174 PetscFunctionBegin; 175 *theta = th->Theta; 176 PetscFunctionReturn(0); 177 } 178 179 #undef __FUNCT__ 180 #define __FUNCT__ "TSThetaSetTheta_Theta" 181 PetscErrorCode TSThetaSetTheta_Theta(TS ts,PetscReal theta) 182 { 183 TS_Theta *th = (TS_Theta*)ts->data; 184 185 PetscFunctionBegin; 186 if (theta <= 0 || 1 < theta) SETERRQ1(((PetscObject)ts)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Theta %G not in range (0,1]",theta); 187 th->Theta = theta; 188 PetscFunctionReturn(0); 189 } 190 EXTERN_C_END 191 192 /* ------------------------------------------------------------ */ 193 /*MC 194 TSTHETA - DAE solver using the implicit Theta method 195 196 Level: beginner 197 198 .seealso: TSCreate(), TS, TSSetType() 199 200 M*/ 201 EXTERN_C_BEGIN 202 #undef __FUNCT__ 203 #define __FUNCT__ "TSCreate_Theta" 204 PetscErrorCode TSCreate_Theta(TS ts) 205 { 206 TS_Theta *th; 207 PetscErrorCode ierr; 208 209 PetscFunctionBegin; 210 ts->ops->reset = TSReset_Theta; 211 ts->ops->destroy = TSDestroy_Theta; 212 ts->ops->view = TSView_Theta; 213 ts->ops->setup = TSSetUp_Theta; 214 ts->ops->step = TSStep_Theta; 215 ts->ops->setfromoptions = TSSetFromOptions_Theta; 216 ts->ops->snesfunction = SNESTSFormFunction_Theta; 217 ts->ops->snesjacobian = SNESTSFormJacobian_Theta; 218 219 ierr = PetscNewLog(ts,TS_Theta,&th);CHKERRQ(ierr); 220 ts->data = (void*)th; 221 222 th->extrapolate = PETSC_FALSE; 223 th->Theta = 0.5; 224 225 ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSThetaGetTheta_C","TSThetaGetTheta_Theta",TSThetaGetTheta_Theta);CHKERRQ(ierr); 226 ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSThetaSetTheta_C","TSThetaSetTheta_Theta",TSThetaSetTheta_Theta);CHKERRQ(ierr); 227 PetscFunctionReturn(0); 228 } 229 EXTERN_C_END 230 231 #undef __FUNCT__ 232 #define __FUNCT__ "TSThetaGetTheta" 233 /*@ 234 TSThetaGetTheta - Get the abscissa of the stage in (0,1]. 235 236 Not Collective 237 238 Input Parameter: 239 . ts - timestepping context 240 241 Output Parameter: 242 . theta - stage abscissa 243 244 Note: 245 Use of this function is normally only required to hack TSTHETA to use a modified integration scheme. 246 247 Level: Advanced 248 249 .seealso: TSThetaSetTheta() 250 @*/ 251 PetscErrorCode TSThetaGetTheta(TS ts,PetscReal *theta) 252 { 253 PetscErrorCode ierr; 254 255 PetscFunctionBegin; 256 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 257 PetscValidPointer(theta,2); 258 ierr = PetscUseMethod(ts,"TSThetaGetTheta_C",(TS,PetscReal*),(ts,theta));CHKERRQ(ierr); 259 PetscFunctionReturn(0); 260 } 261 262 #undef __FUNCT__ 263 #define __FUNCT__ "TSThetaSetTheta" 264 /*@ 265 TSThetaSetTheta - Set the abscissa of the stage in (0,1]. 266 267 Not Collective 268 269 Input Parameter: 270 + ts - timestepping context 271 - theta - stage abscissa 272 273 Options Database: 274 . -ts_theta_theta <theta> 275 276 Level: Intermediate 277 278 .seealso: TSThetaGetTheta() 279 @*/ 280 PetscErrorCode TSThetaSetTheta(TS ts,PetscReal theta) 281 { 282 PetscErrorCode ierr; 283 284 PetscFunctionBegin; 285 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 286 ierr = PetscTryMethod(ts,"TSThetaSetTheta_C",(TS,PetscReal),(ts,theta));CHKERRQ(ierr); 287 PetscFunctionReturn(0); 288 } 289 290 /* 291 * TSBEULER and TSCN are straightforward specializations of TSTHETA. 292 * The creation functions for these specializations are below. 293 */ 294 295 #undef __FUNCT__ 296 #define __FUNCT__ "TSView_BEuler" 297 static PetscErrorCode TSView_BEuler(TS ts,PetscViewer viewer) 298 { 299 PetscFunctionBegin; 300 PetscFunctionReturn(0); 301 } 302 303 /*MC 304 TSBEULER - ODE solver using the implicit backward Euler method 305 306 Level: beginner 307 308 .seealso: TSCreate(), TS, TSSetType(), TSEULER, TSCN, TSTHETA 309 310 M*/ 311 EXTERN_C_BEGIN 312 #undef __FUNCT__ 313 #define __FUNCT__ "TSCreate_BEuler" 314 PetscErrorCode TSCreate_BEuler(TS ts) 315 { 316 PetscErrorCode ierr; 317 318 PetscFunctionBegin; 319 ierr = TSCreate_Theta(ts);CHKERRQ(ierr); 320 ierr = TSThetaSetTheta(ts,1.0);CHKERRQ(ierr); 321 ts->ops->view = TSView_BEuler; 322 PetscFunctionReturn(0); 323 } 324 EXTERN_C_END 325 326 #undef __FUNCT__ 327 #define __FUNCT__ "TSView_CN" 328 static PetscErrorCode TSView_CN(TS ts,PetscViewer viewer) 329 { 330 PetscFunctionBegin; 331 PetscFunctionReturn(0); 332 } 333 334 /*MC 335 TSCN - ODE solver using the implicit Crank-Nicolson method. 336 337 Level: beginner 338 339 Notes: 340 TSCN is equivalent to TSTHETA with Theta=0.5 341 342 .seealso: TSCreate(), TS, TSSetType(), TSBEULER, TSTHETA 343 344 M*/ 345 EXTERN_C_BEGIN 346 #undef __FUNCT__ 347 #define __FUNCT__ "TSCreate_CN" 348 PetscErrorCode TSCreate_CN(TS ts) 349 { 350 PetscErrorCode ierr; 351 352 PetscFunctionBegin; 353 ierr = TSCreate_Theta(ts);CHKERRQ(ierr); 354 ierr = TSThetaSetTheta(ts,0.5);CHKERRQ(ierr); 355 ts->ops->view = TSView_CN; 356 PetscFunctionReturn(0); 357 } 358 EXTERN_C_END 359