1 /* 2 Code for timestepping with implicit Theta method 3 */ 4 #include <petsc/private/tsimpl.h> /*I "petscts.h" I*/ 5 #include <petscsnes.h> 6 #include <petscdm.h> 7 #include <petscmat.h> 8 9 typedef struct { 10 PetscReal stage_time; 11 Vec X0,X,Xdot; /* Storage for stages and time derivative */ 12 Vec affine; /* Affine vector needed for residual at beginning of step in endpoint formulation */ 13 14 PetscReal Theta; 15 PetscInt order; 16 PetscBool endpoint; 17 PetscBool extrapolate; 18 19 Vec *VecsDeltaLam; /* Increment of the adjoint sensitivity w.r.t IC at stage */ 20 Vec *VecsDeltaMu; /* Increment of the adjoint sensitivity w.r.t P at stage */ 21 Vec *VecsSensiTemp; /* Vector to be timed with Jacobian transpose */ 22 Vec VecCostIntegral0; /* Backup for roll-backs due to events */ 23 PetscReal ptime; 24 PetscReal time_step; 25 26 PetscBool adapt; /* Use time-step adaptivity ? */ 27 PetscReal time_step_prev; 28 Vec vec_sol_prev; 29 Vec vec_lte_work; 30 31 TSStepStatus status; 32 } TS_Theta; 33 34 #undef __FUNCT__ 35 #define __FUNCT__ "TSThetaGetX0AndXdot" 36 static PetscErrorCode TSThetaGetX0AndXdot(TS ts,DM dm,Vec *X0,Vec *Xdot) 37 { 38 TS_Theta *th = (TS_Theta*)ts->data; 39 PetscErrorCode ierr; 40 41 PetscFunctionBegin; 42 if (X0) { 43 if (dm && dm != ts->dm) { 44 ierr = DMGetNamedGlobalVector(dm,"TSTheta_X0",X0);CHKERRQ(ierr); 45 } else *X0 = ts->vec_sol; 46 } 47 if (Xdot) { 48 if (dm && dm != ts->dm) { 49 ierr = DMGetNamedGlobalVector(dm,"TSTheta_Xdot",Xdot);CHKERRQ(ierr); 50 } else *Xdot = th->Xdot; 51 } 52 PetscFunctionReturn(0); 53 } 54 55 #undef __FUNCT__ 56 #define __FUNCT__ "TSThetaRestoreX0AndXdot" 57 static PetscErrorCode TSThetaRestoreX0AndXdot(TS ts,DM dm,Vec *X0,Vec *Xdot) 58 { 59 PetscErrorCode ierr; 60 61 PetscFunctionBegin; 62 if (X0) { 63 if (dm && dm != ts->dm) { 64 ierr = DMRestoreNamedGlobalVector(dm,"TSTheta_X0",X0);CHKERRQ(ierr); 65 } 66 } 67 if (Xdot) { 68 if (dm && dm != ts->dm) { 69 ierr = DMRestoreNamedGlobalVector(dm,"TSTheta_Xdot",Xdot);CHKERRQ(ierr); 70 } 71 } 72 PetscFunctionReturn(0); 73 } 74 75 #undef __FUNCT__ 76 #define __FUNCT__ "DMCoarsenHook_TSTheta" 77 static PetscErrorCode DMCoarsenHook_TSTheta(DM fine,DM coarse,void *ctx) 78 { 79 80 PetscFunctionBegin; 81 PetscFunctionReturn(0); 82 } 83 84 #undef __FUNCT__ 85 #define __FUNCT__ "DMRestrictHook_TSTheta" 86 static PetscErrorCode DMRestrictHook_TSTheta(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse,void *ctx) 87 { 88 TS ts = (TS)ctx; 89 PetscErrorCode ierr; 90 Vec X0,Xdot,X0_c,Xdot_c; 91 92 PetscFunctionBegin; 93 ierr = TSThetaGetX0AndXdot(ts,fine,&X0,&Xdot);CHKERRQ(ierr); 94 ierr = TSThetaGetX0AndXdot(ts,coarse,&X0_c,&Xdot_c);CHKERRQ(ierr); 95 ierr = MatRestrict(restrct,X0,X0_c);CHKERRQ(ierr); 96 ierr = MatRestrict(restrct,Xdot,Xdot_c);CHKERRQ(ierr); 97 ierr = VecPointwiseMult(X0_c,rscale,X0_c);CHKERRQ(ierr); 98 ierr = VecPointwiseMult(Xdot_c,rscale,Xdot_c);CHKERRQ(ierr); 99 ierr = TSThetaRestoreX0AndXdot(ts,fine,&X0,&Xdot);CHKERRQ(ierr); 100 ierr = TSThetaRestoreX0AndXdot(ts,coarse,&X0_c,&Xdot_c);CHKERRQ(ierr); 101 PetscFunctionReturn(0); 102 } 103 104 #undef __FUNCT__ 105 #define __FUNCT__ "DMSubDomainHook_TSTheta" 106 static PetscErrorCode DMSubDomainHook_TSTheta(DM dm,DM subdm,void *ctx) 107 { 108 109 PetscFunctionBegin; 110 PetscFunctionReturn(0); 111 } 112 113 #undef __FUNCT__ 114 #define __FUNCT__ "DMSubDomainRestrictHook_TSTheta" 115 static PetscErrorCode DMSubDomainRestrictHook_TSTheta(DM dm,VecScatter gscat,VecScatter lscat,DM subdm,void *ctx) 116 { 117 TS ts = (TS)ctx; 118 PetscErrorCode ierr; 119 Vec X0,Xdot,X0_sub,Xdot_sub; 120 121 PetscFunctionBegin; 122 ierr = TSThetaGetX0AndXdot(ts,dm,&X0,&Xdot);CHKERRQ(ierr); 123 ierr = TSThetaGetX0AndXdot(ts,subdm,&X0_sub,&Xdot_sub);CHKERRQ(ierr); 124 125 ierr = VecScatterBegin(gscat,X0,X0_sub,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 126 ierr = VecScatterEnd(gscat,X0,X0_sub,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 127 128 ierr = VecScatterBegin(gscat,Xdot,Xdot_sub,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 129 ierr = VecScatterEnd(gscat,Xdot,Xdot_sub,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 130 131 ierr = TSThetaRestoreX0AndXdot(ts,dm,&X0,&Xdot);CHKERRQ(ierr); 132 ierr = TSThetaRestoreX0AndXdot(ts,subdm,&X0_sub,&Xdot_sub);CHKERRQ(ierr); 133 PetscFunctionReturn(0); 134 } 135 136 #undef __FUNCT__ 137 #define __FUNCT__ "TSForwardCostIntegral_Theta" 138 static PetscErrorCode TSForwardCostIntegral_Theta(TS ts) 139 { 140 TS_Theta *th = (TS_Theta*)ts->data; 141 PetscErrorCode ierr; 142 143 PetscFunctionBegin; 144 /* backup cost integral */ 145 ierr = VecCopy(ts->vec_costintegral,th->VecCostIntegral0);CHKERRQ(ierr); 146 if (th->endpoint) { 147 ierr = TSAdjointComputeCostIntegrand(ts,th->ptime,th->X0,ts->vec_costintegrand);CHKERRQ(ierr); 148 ierr = VecAXPY(ts->vec_costintegral,th->time_step*(1-th->Theta),ts->vec_costintegrand);CHKERRQ(ierr); 149 } 150 ierr = TSAdjointComputeCostIntegrand(ts,th->stage_time,th->X,ts->vec_costintegrand);CHKERRQ(ierr); 151 if (th->endpoint) { 152 ierr = VecAXPY(ts->vec_costintegral,th->time_step*th->Theta,ts->vec_costintegrand);CHKERRQ(ierr); 153 } else { 154 ierr = VecAXPY(ts->vec_costintegral,th->time_step,ts->vec_costintegrand);CHKERRQ(ierr); 155 } 156 PetscFunctionReturn(0); 157 } 158 159 #undef __FUNCT__ 160 #define __FUNCT__ "TSAdjointCostIntegral_Theta" 161 static PetscErrorCode TSAdjointCostIntegral_Theta(TS ts) 162 { 163 TS_Theta *th = (TS_Theta*)ts->data; 164 PetscErrorCode ierr; 165 166 PetscFunctionBegin; 167 if (th->endpoint) { 168 /* Evolve ts->vec_costintegral to compute integrals */ 169 ierr = TSAdjointComputeCostIntegrand(ts,ts->ptime,ts->vec_sol,ts->vec_costintegrand);CHKERRQ(ierr); 170 ierr = VecAXPY(ts->vec_costintegral,-ts->time_step*th->Theta,ts->vec_costintegrand);CHKERRQ(ierr); 171 if (th->Theta!=1) { 172 ierr = TSAdjointComputeCostIntegrand(ts,th->ptime,th->X0,ts->vec_costintegrand);CHKERRQ(ierr); 173 ierr = VecAXPY(ts->vec_costintegral,ts->time_step*(th->Theta-1),ts->vec_costintegrand);CHKERRQ(ierr); 174 } 175 }else { 176 ierr = TSAdjointComputeCostIntegrand(ts,th->stage_time,th->X,ts->vec_costintegrand);CHKERRQ(ierr); 177 ierr = VecAXPY(ts->vec_costintegral,-ts->time_step,ts->vec_costintegrand);CHKERRQ(ierr); 178 } 179 PetscFunctionReturn(0); 180 } 181 182 #undef __FUNCT__ 183 #define __FUNCT__ "TS_SNESSolve" 184 static PetscErrorCode TS_SNESSolve(TS ts,Vec b,Vec x) 185 { 186 PetscInt nits,lits; 187 PetscErrorCode ierr; 188 189 PetscFunctionBegin; 190 ierr = SNESSolve(ts->snes,b,x);CHKERRQ(ierr); 191 ierr = SNESGetIterationNumber(ts->snes,&nits);CHKERRQ(ierr); 192 ierr = SNESGetLinearSolveIterations(ts->snes,&lits);CHKERRQ(ierr); 193 ts->snes_its += nits; ts->ksp_its += lits; 194 PetscFunctionReturn(0); 195 } 196 197 #undef __FUNCT__ 198 #define __FUNCT__ "TSStep_Theta" 199 static PetscErrorCode TSStep_Theta(TS ts) 200 { 201 TS_Theta *th = (TS_Theta*)ts->data; 202 PetscInt rejections = 0; 203 PetscBool stageok,accept = PETSC_TRUE; 204 PetscReal next_time_step = ts->time_step; 205 PetscErrorCode ierr; 206 207 PetscFunctionBegin; 208 209 if (!ts->steprollback) { 210 if (th->adapt) { th->time_step_prev = ts->time_step_prev; } 211 if (th->adapt) { ierr = VecCopy(th->X0,th->vec_sol_prev);CHKERRQ(ierr); } 212 ierr = VecCopy(ts->vec_sol,th->X0);CHKERRQ(ierr); 213 } 214 215 th->status = TS_STEP_INCOMPLETE; 216 while (!ts->reason && th->status != TS_STEP_COMPLETE) { 217 218 PetscReal shift = 1/(th->Theta*ts->time_step); 219 th->stage_time = ts->ptime + (th->endpoint ? (PetscReal)1 : th->Theta)*ts->time_step; 220 ierr = TSPreStage(ts,th->stage_time);CHKERRQ(ierr); 221 222 if (th->endpoint) { /* This formulation assumes linear time-independent mass matrix */ 223 if (!th->affine) {ierr = VecDuplicate(ts->vec_sol,&th->affine);CHKERRQ(ierr);} 224 ierr = VecZeroEntries(th->Xdot);CHKERRQ(ierr); 225 ierr = TSComputeIFunction(ts,ts->ptime,th->X0,th->Xdot,th->affine,PETSC_FALSE);CHKERRQ(ierr); 226 ierr = VecScale(th->affine,(th->Theta-1)/th->Theta);CHKERRQ(ierr); 227 } else if (th->affine) { /* Just in case th->endpoint is changed between calls to TSStep_Theta() */ 228 ierr = VecZeroEntries(th->affine);CHKERRQ(ierr); 229 } 230 if (th->extrapolate) { 231 ierr = VecWAXPY(th->X,1/shift,th->Xdot,th->X0);CHKERRQ(ierr); 232 } else { 233 ierr = VecCopy(th->X0,th->X);CHKERRQ(ierr); 234 } 235 236 ierr = TS_SNESSolve(ts,th->affine,th->X);CHKERRQ(ierr); 237 ierr = TSPostStage(ts,th->stage_time,0,&(th->X));CHKERRQ(ierr); 238 ierr = TSAdaptCheckStage(ts->adapt,ts,th->stage_time,th->X,&stageok);CHKERRQ(ierr); 239 if (!stageok) {accept = PETSC_FALSE; goto reject_step;} 240 241 th->status = TS_STEP_PENDING; 242 if (th->endpoint) { 243 ierr = VecCopy(th->X,ts->vec_sol);CHKERRQ(ierr); 244 } else { 245 ierr = VecAXPBYPCZ(th->Xdot,-shift,shift,0,th->X0,th->X);CHKERRQ(ierr); 246 ierr = VecAXPY(ts->vec_sol,ts->time_step,th->Xdot);CHKERRQ(ierr); 247 } 248 ierr = TSAdaptChoose(ts->adapt,ts,ts->time_step,NULL,&next_time_step,&accept);CHKERRQ(ierr); 249 th->status = accept ? TS_STEP_COMPLETE : TS_STEP_INCOMPLETE; 250 if (!accept) { 251 ierr = VecCopy(th->X0,ts->vec_sol);CHKERRQ(ierr); 252 ts->time_step = next_time_step; goto reject_step; 253 } 254 255 if (ts->costintegralfwd) { /* Save the info for the later use in cost integral evaluation */ 256 th->ptime = ts->ptime; 257 th->time_step = ts->time_step; 258 } 259 260 ts->ptime += ts->time_step; 261 ts->time_step = next_time_step; 262 ts->steps++; 263 break; 264 265 reject_step: 266 ts->reject++; 267 if (!ts->reason && ++rejections > ts->max_reject && ts->max_reject >= 0) { 268 ts->reason = TS_DIVERGED_STEP_REJECTED; 269 ierr = PetscInfo2(ts,"Step=%D, step rejections %D greater than current TS allowed, stopping solve\n",ts->steps,rejections);CHKERRQ(ierr); 270 } 271 } 272 PetscFunctionReturn(0); 273 } 274 275 #undef __FUNCT__ 276 #define __FUNCT__ "TSAdjointStep_Theta" 277 static PetscErrorCode TSAdjointStep_Theta(TS ts) 278 { 279 TS_Theta *th = (TS_Theta*)ts->data; 280 Vec *VecsDeltaLam = th->VecsDeltaLam,*VecsDeltaMu = th->VecsDeltaMu,*VecsSensiTemp = th->VecsSensiTemp; 281 PetscInt nadj; 282 PetscErrorCode ierr; 283 Mat J,Jp; 284 KSP ksp; 285 PetscReal shift; 286 287 PetscFunctionBegin; 288 289 th->status = TS_STEP_INCOMPLETE; 290 ierr = SNESGetKSP(ts->snes,&ksp);CHKERRQ(ierr); 291 ierr = TSGetIJacobian(ts,&J,&Jp,NULL,NULL);CHKERRQ(ierr); 292 293 /* If endpoint=1, th->ptime and th->X0 will be used; if endpoint=0, th->stage_time and th->X will be used. */ 294 th->stage_time = ts->ptime + (th->endpoint ? ts->time_step : (1.-th->Theta)*ts->time_step); /* time_step is negative*/ 295 th->ptime = ts->ptime + ts->time_step; 296 297 /* Build RHS */ 298 if (ts->vec_costintegral) { /* Cost function has an integral term */ 299 if (th->endpoint) { 300 ierr = TSAdjointComputeDRDYFunction(ts,ts->ptime,ts->vec_sol,ts->vecs_drdy);CHKERRQ(ierr); 301 }else { 302 ierr = TSAdjointComputeDRDYFunction(ts,th->stage_time,th->X,ts->vecs_drdy);CHKERRQ(ierr); 303 } 304 } 305 for (nadj=0; nadj<ts->numcost; nadj++) { 306 ierr = VecCopy(ts->vecs_sensi[nadj],VecsSensiTemp[nadj]);CHKERRQ(ierr); 307 ierr = VecScale(VecsSensiTemp[nadj],-1./(th->Theta*ts->time_step));CHKERRQ(ierr); 308 if (ts->vec_costintegral) { 309 ierr = VecAXPY(VecsSensiTemp[nadj],1.,ts->vecs_drdy[nadj]);CHKERRQ(ierr); 310 } 311 } 312 313 /* Build LHS */ 314 shift = -1./(th->Theta*ts->time_step); 315 if (th->endpoint) { 316 ierr = TSComputeIJacobian(ts,ts->ptime,ts->vec_sol,th->Xdot,shift,J,Jp,PETSC_FALSE);CHKERRQ(ierr); 317 }else { 318 ierr = TSComputeIJacobian(ts,th->stage_time,th->X,th->Xdot,shift,J,Jp,PETSC_FALSE);CHKERRQ(ierr); 319 } 320 ierr = KSPSetOperators(ksp,J,Jp);CHKERRQ(ierr); 321 322 /* Solve LHS X = RHS */ 323 for (nadj=0; nadj<ts->numcost; nadj++) { 324 ierr = KSPSolveTranspose(ksp,VecsSensiTemp[nadj],VecsDeltaLam[nadj]);CHKERRQ(ierr); 325 } 326 327 /* Update sensitivities, and evaluate integrals if there is any */ 328 if(th->endpoint) { /* two-stage case */ 329 if (th->Theta!=1.) { 330 shift = -1./((th->Theta-1.)*ts->time_step); 331 ierr = TSComputeIJacobian(ts,th->ptime,th->X0,th->Xdot,shift,J,Jp,PETSC_FALSE);CHKERRQ(ierr); 332 if (ts->vec_costintegral) { 333 ierr = TSAdjointComputeDRDYFunction(ts,th->ptime,th->X0,ts->vecs_drdy);CHKERRQ(ierr); 334 } 335 for (nadj=0; nadj<ts->numcost; nadj++) { 336 ierr = MatMultTranspose(J,VecsDeltaLam[nadj],ts->vecs_sensi[nadj]);CHKERRQ(ierr); 337 if (ts->vec_costintegral) { 338 ierr = VecAXPY(ts->vecs_sensi[nadj],-1.,ts->vecs_drdy[nadj]);CHKERRQ(ierr); 339 } 340 ierr = VecScale(ts->vecs_sensi[nadj],1./shift);CHKERRQ(ierr); 341 } 342 }else { /* backward Euler */ 343 shift = 0.0; 344 ierr = TSComputeIJacobian(ts,ts->ptime,ts->vec_sol,th->Xdot,shift,J,Jp,PETSC_FALSE);CHKERRQ(ierr); /* get -f_y */ 345 for (nadj=0; nadj<ts->numcost; nadj++) { 346 ierr = MatMultTranspose(J,VecsDeltaLam[nadj],VecsSensiTemp[nadj]);CHKERRQ(ierr); 347 ierr = VecAXPY(ts->vecs_sensi[nadj],ts->time_step,VecsSensiTemp[nadj]);CHKERRQ(ierr); 348 if (ts->vec_costintegral) { 349 ierr = VecAXPY(ts->vecs_sensi[nadj],-ts->time_step,ts->vecs_drdy[nadj]);CHKERRQ(ierr); 350 } 351 } 352 } 353 354 if (ts->vecs_sensip) { /* sensitivities wrt parameters */ 355 ierr = TSAdjointComputeRHSJacobian(ts,ts->ptime,ts->vec_sol,ts->Jacp);CHKERRQ(ierr); 356 for (nadj=0; nadj<ts->numcost; nadj++) { 357 ierr = MatMultTranspose(ts->Jacp,VecsDeltaLam[nadj],VecsDeltaMu[nadj]);CHKERRQ(ierr); 358 ierr = VecAXPY(ts->vecs_sensip[nadj],-ts->time_step*th->Theta,VecsDeltaMu[nadj]);CHKERRQ(ierr); 359 } 360 if (th->Theta!=1.) { 361 ierr = TSAdjointComputeRHSJacobian(ts,th->ptime,th->X0,ts->Jacp);CHKERRQ(ierr); 362 for (nadj=0; nadj<ts->numcost; nadj++) { 363 ierr = MatMultTranspose(ts->Jacp,VecsDeltaLam[nadj],VecsDeltaMu[nadj]);CHKERRQ(ierr); 364 ierr = VecAXPY(ts->vecs_sensip[nadj],-ts->time_step*(1.-th->Theta),VecsDeltaMu[nadj]);CHKERRQ(ierr); 365 } 366 } 367 if (ts->vec_costintegral) { 368 ierr = TSAdjointComputeDRDPFunction(ts,ts->ptime,ts->vec_sol,ts->vecs_drdp);CHKERRQ(ierr); 369 for (nadj=0; nadj<ts->numcost; nadj++) { 370 ierr = VecAXPY(ts->vecs_sensip[nadj],-ts->time_step*th->Theta,ts->vecs_drdp[nadj]);CHKERRQ(ierr); 371 } 372 if (th->Theta!=1.) { 373 ierr = TSAdjointComputeDRDPFunction(ts,th->ptime,th->X0,ts->vecs_drdp);CHKERRQ(ierr); 374 for (nadj=0; nadj<ts->numcost; nadj++) { 375 ierr = VecAXPY(ts->vecs_sensip[nadj],-ts->time_step*(1.-th->Theta),ts->vecs_drdp[nadj]);CHKERRQ(ierr); 376 } 377 } 378 } 379 } 380 }else { /* one-stage case */ 381 shift = 0.0; 382 ierr = TSComputeIJacobian(ts,th->stage_time,th->X,th->Xdot,shift,J,Jp,PETSC_FALSE);CHKERRQ(ierr); /* get -f_y */ 383 if (ts->vec_costintegral) { 384 ierr = TSAdjointComputeDRDYFunction(ts,th->stage_time,th->X,ts->vecs_drdy);CHKERRQ(ierr); 385 } 386 for (nadj=0; nadj<ts->numcost; nadj++) { 387 ierr = MatMultTranspose(J,VecsDeltaLam[nadj],VecsSensiTemp[nadj]);CHKERRQ(ierr); 388 ierr = VecAXPY(ts->vecs_sensi[nadj],ts->time_step,VecsSensiTemp[nadj]);CHKERRQ(ierr); 389 if (ts->vec_costintegral) { 390 ierr = VecAXPY(ts->vecs_sensi[nadj],-ts->time_step,ts->vecs_drdy[nadj]);CHKERRQ(ierr); 391 } 392 } 393 if (ts->vecs_sensip) { 394 ierr = TSAdjointComputeRHSJacobian(ts,th->stage_time,th->X,ts->Jacp);CHKERRQ(ierr); 395 for (nadj=0; nadj<ts->numcost; nadj++) { 396 ierr = MatMultTranspose(ts->Jacp,VecsDeltaLam[nadj],VecsDeltaMu[nadj]);CHKERRQ(ierr); 397 ierr = VecAXPY(ts->vecs_sensip[nadj],-ts->time_step,VecsDeltaMu[nadj]);CHKERRQ(ierr); 398 } 399 if (ts->vec_costintegral) { 400 ierr = TSAdjointComputeDRDPFunction(ts,th->stage_time,th->X,ts->vecs_drdp);CHKERRQ(ierr); 401 for (nadj=0; nadj<ts->numcost; nadj++) { 402 ierr = VecAXPY(ts->vecs_sensip[nadj],-ts->time_step,ts->vecs_drdp[nadj]);CHKERRQ(ierr); 403 } 404 } 405 } 406 } 407 408 ts->steps++; 409 th->status = TS_STEP_COMPLETE; 410 PetscFunctionReturn(0); 411 } 412 413 #undef __FUNCT__ 414 #define __FUNCT__ "TSInterpolate_Theta" 415 static PetscErrorCode TSInterpolate_Theta(TS ts,PetscReal t,Vec X) 416 { 417 TS_Theta *th = (TS_Theta*)ts->data; 418 PetscReal alpha = t - ts->ptime; 419 PetscErrorCode ierr; 420 421 PetscFunctionBegin; 422 ierr = VecCopy(ts->vec_sol,th->X);CHKERRQ(ierr); 423 if (th->endpoint) alpha *= th->Theta; 424 ierr = VecWAXPY(X,alpha,th->Xdot,th->X);CHKERRQ(ierr); 425 PetscFunctionReturn(0); 426 } 427 428 #define TSEvent_Status(ts) (ts->event ? ts->event->status : TSEVENT_NONE) 429 430 #undef __FUNCT__ 431 #define __FUNCT__ "TSEvaluateWLTE_Theta" 432 static PetscErrorCode TSEvaluateWLTE_Theta(TS ts,NormType wnormtype,PetscInt *order,PetscReal *wlte) 433 { 434 TS_Theta *th = (TS_Theta*)ts->data; 435 Vec X = ts->vec_sol; /* X = solution */ 436 Vec Y = th->vec_lte_work; /* Y = X + LTE */ 437 PetscErrorCode ierr; 438 439 PetscFunctionBegin; 440 if (!ts->steps || TSEvent_Status(ts) == TSEVENT_RESET_NEXTSTEP) { 441 /* Cannot compute LTE in first step or in restart after event */ 442 *wlte = -1; 443 } else { 444 /* Compute LTE using backward differences with non-constant time step */ 445 PetscReal a = 1 + th->time_step_prev/ts->time_step; 446 PetscScalar scal[3]; Vec vecs[3]; 447 scal[0] = +1/a; scal[1] = -1/(a-1); scal[2] = +1/(a*(a-1)); 448 vecs[0] = X; vecs[1] = th->X0; vecs[2] = th->vec_sol_prev; 449 ierr = VecCopy(X,Y);CHKERRQ(ierr); 450 ierr = VecMAXPY(Y,3,scal,vecs);CHKERRQ(ierr); 451 ierr = TSErrorWeightedNorm(ts,X,Y,wnormtype,wlte);CHKERRQ(ierr); 452 } 453 if (order) *order = 2; 454 PetscFunctionReturn(0); 455 } 456 457 #undef __FUNCT__ 458 #define __FUNCT__ "TSRollBack_Theta" 459 static PetscErrorCode TSRollBack_Theta(TS ts) 460 { 461 TS_Theta *th = (TS_Theta*)ts->data; 462 PetscErrorCode ierr; 463 464 PetscFunctionBegin; 465 ierr = VecCopy(th->X0,ts->vec_sol);CHKERRQ(ierr); 466 if (ts->vec_costintegral && ts->costintegralfwd) { 467 ierr = VecCopy(th->VecCostIntegral0,ts->vec_costintegral);CHKERRQ(ierr); 468 } 469 PetscFunctionReturn(0); 470 } 471 472 /*------------------------------------------------------------*/ 473 #undef __FUNCT__ 474 #define __FUNCT__ "TSReset_Theta" 475 static PetscErrorCode TSReset_Theta(TS ts) 476 { 477 TS_Theta *th = (TS_Theta*)ts->data; 478 PetscErrorCode ierr; 479 480 PetscFunctionBegin; 481 ierr = VecDestroy(&th->X);CHKERRQ(ierr); 482 ierr = VecDestroy(&th->Xdot);CHKERRQ(ierr); 483 ierr = VecDestroy(&th->X0);CHKERRQ(ierr); 484 ierr = VecDestroy(&th->affine);CHKERRQ(ierr); 485 486 ierr = VecDestroy(&th->vec_sol_prev);CHKERRQ(ierr); 487 ierr = VecDestroy(&th->vec_lte_work);CHKERRQ(ierr); 488 489 ierr = VecDestroy(&th->VecCostIntegral0);CHKERRQ(ierr); 490 ierr = VecDestroyVecs(ts->numcost,&th->VecsDeltaLam);CHKERRQ(ierr); 491 ierr = VecDestroyVecs(ts->numcost,&th->VecsDeltaMu);CHKERRQ(ierr); 492 ierr = VecDestroyVecs(ts->numcost,&th->VecsSensiTemp);CHKERRQ(ierr); 493 PetscFunctionReturn(0); 494 } 495 496 #undef __FUNCT__ 497 #define __FUNCT__ "TSDestroy_Theta" 498 static PetscErrorCode TSDestroy_Theta(TS ts) 499 { 500 PetscErrorCode ierr; 501 502 PetscFunctionBegin; 503 ierr = TSReset_Theta(ts);CHKERRQ(ierr); 504 ierr = PetscFree(ts->data);CHKERRQ(ierr); 505 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSThetaGetTheta_C",NULL);CHKERRQ(ierr); 506 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSThetaSetTheta_C",NULL);CHKERRQ(ierr); 507 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSThetaGetEndpoint_C",NULL);CHKERRQ(ierr); 508 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSThetaSetEndpoint_C",NULL);CHKERRQ(ierr); 509 PetscFunctionReturn(0); 510 } 511 512 /* 513 This defines the nonlinear equation that is to be solved with SNES 514 G(U) = F[t0+Theta*dt, U, (U-U0)*shift] = 0 515 */ 516 #undef __FUNCT__ 517 #define __FUNCT__ "SNESTSFormFunction_Theta" 518 static PetscErrorCode SNESTSFormFunction_Theta(SNES snes,Vec x,Vec y,TS ts) 519 { 520 TS_Theta *th = (TS_Theta*)ts->data; 521 PetscErrorCode ierr; 522 Vec X0,Xdot; 523 DM dm,dmsave; 524 PetscReal shift = 1/(th->Theta*ts->time_step); 525 526 PetscFunctionBegin; 527 ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 528 /* When using the endpoint variant, this is actually 1/Theta * Xdot */ 529 ierr = TSThetaGetX0AndXdot(ts,dm,&X0,&Xdot);CHKERRQ(ierr); 530 ierr = VecAXPBYPCZ(Xdot,-shift,shift,0,X0,x);CHKERRQ(ierr); 531 532 /* DM monkey-business allows user code to call TSGetDM() inside of functions evaluated on levels of FAS */ 533 dmsave = ts->dm; 534 ts->dm = dm; 535 ierr = TSComputeIFunction(ts,th->stage_time,x,Xdot,y,PETSC_FALSE);CHKERRQ(ierr); 536 ts->dm = dmsave; 537 ierr = TSThetaRestoreX0AndXdot(ts,dm,&X0,&Xdot);CHKERRQ(ierr); 538 PetscFunctionReturn(0); 539 } 540 541 #undef __FUNCT__ 542 #define __FUNCT__ "SNESTSFormJacobian_Theta" 543 static PetscErrorCode SNESTSFormJacobian_Theta(SNES snes,Vec x,Mat A,Mat B,TS ts) 544 { 545 TS_Theta *th = (TS_Theta*)ts->data; 546 PetscErrorCode ierr; 547 Vec Xdot; 548 DM dm,dmsave; 549 PetscReal shift = 1/(th->Theta*ts->time_step); 550 551 PetscFunctionBegin; 552 ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 553 554 /* th->Xdot has already been computed in SNESTSFormFunction_Theta (SNES guarantees this) */ 555 ierr = TSThetaGetX0AndXdot(ts,dm,NULL,&Xdot);CHKERRQ(ierr); 556 557 dmsave = ts->dm; 558 ts->dm = dm; 559 ierr = TSComputeIJacobian(ts,th->stage_time,x,Xdot,shift,A,B,PETSC_FALSE);CHKERRQ(ierr); 560 ts->dm = dmsave; 561 ierr = TSThetaRestoreX0AndXdot(ts,dm,NULL,&Xdot);CHKERRQ(ierr); 562 PetscFunctionReturn(0); 563 } 564 565 #undef __FUNCT__ 566 #define __FUNCT__ "TSSetUp_Theta" 567 static PetscErrorCode TSSetUp_Theta(TS ts) 568 { 569 TS_Theta *th = (TS_Theta*)ts->data; 570 PetscErrorCode ierr; 571 572 PetscFunctionBegin; 573 if (!th->VecCostIntegral0 && ts->vec_costintegral && ts->costintegralfwd) { /* back up cost integral */ 574 ierr = VecDuplicate(ts->vec_costintegral,&th->VecCostIntegral0);CHKERRQ(ierr); 575 } 576 if (!th->X) { 577 ierr = VecDuplicate(ts->vec_sol,&th->X);CHKERRQ(ierr); 578 } 579 if (!th->Xdot) { 580 ierr = VecDuplicate(ts->vec_sol,&th->Xdot);CHKERRQ(ierr); 581 } 582 if (!th->X0) { 583 ierr = VecDuplicate(ts->vec_sol,&th->X0);CHKERRQ(ierr); 584 } 585 if (th->endpoint) { 586 ierr = VecDuplicate(ts->vec_sol,&th->affine);CHKERRQ(ierr); 587 } 588 589 th->order = (th->Theta == 0.5) ? 2 : 1; 590 591 ierr = TSGetDM(ts,&ts->dm);CHKERRQ(ierr); 592 ierr = DMCoarsenHookAdd(ts->dm,DMCoarsenHook_TSTheta,DMRestrictHook_TSTheta,ts);CHKERRQ(ierr); 593 ierr = DMSubDomainHookAdd(ts->dm,DMSubDomainHook_TSTheta,DMSubDomainRestrictHook_TSTheta,ts);CHKERRQ(ierr); 594 595 ierr = TSGetAdapt(ts,&ts->adapt);CHKERRQ(ierr); 596 ierr = TSAdaptCandidatesClear(ts->adapt);CHKERRQ(ierr); 597 if (!th->adapt) { 598 ierr = TSAdaptSetType(ts->adapt,TSADAPTNONE);CHKERRQ(ierr); 599 } else { 600 ierr = VecDuplicate(ts->vec_sol,&th->vec_sol_prev);CHKERRQ(ierr); 601 ierr = VecDuplicate(ts->vec_sol,&th->vec_lte_work);CHKERRQ(ierr); 602 if (ts->exact_final_time == TS_EXACTFINALTIME_UNSPECIFIED) 603 ts->exact_final_time = TS_EXACTFINALTIME_MATCHSTEP; 604 } 605 606 ierr = TSGetSNES(ts,&ts->snes);CHKERRQ(ierr); 607 PetscFunctionReturn(0); 608 } 609 610 /*------------------------------------------------------------*/ 611 612 #undef __FUNCT__ 613 #define __FUNCT__ "TSAdjointSetUp_Theta" 614 static PetscErrorCode TSAdjointSetUp_Theta(TS ts) 615 { 616 TS_Theta *th = (TS_Theta*)ts->data; 617 PetscErrorCode ierr; 618 619 PetscFunctionBegin; 620 ierr = VecDuplicateVecs(ts->vecs_sensi[0],ts->numcost,&th->VecsDeltaLam);CHKERRQ(ierr); 621 if(ts->vecs_sensip) { 622 ierr = VecDuplicateVecs(ts->vecs_sensip[0],ts->numcost,&th->VecsDeltaMu);CHKERRQ(ierr); 623 } 624 ierr = VecDuplicateVecs(ts->vecs_sensi[0],ts->numcost,&th->VecsSensiTemp);CHKERRQ(ierr); 625 PetscFunctionReturn(0); 626 } 627 /*------------------------------------------------------------*/ 628 629 #undef __FUNCT__ 630 #define __FUNCT__ "TSSetFromOptions_Theta" 631 static PetscErrorCode TSSetFromOptions_Theta(PetscOptionItems *PetscOptionsObject,TS ts) 632 { 633 TS_Theta *th = (TS_Theta*)ts->data; 634 PetscErrorCode ierr; 635 636 PetscFunctionBegin; 637 ierr = PetscOptionsHead(PetscOptionsObject,"Theta ODE solver options");CHKERRQ(ierr); 638 { 639 ierr = PetscOptionsReal("-ts_theta_theta","Location of stage (0<Theta<=1)","TSThetaSetTheta",th->Theta,&th->Theta,NULL);CHKERRQ(ierr); 640 ierr = PetscOptionsBool("-ts_theta_extrapolate","Extrapolate stage solution from previous solution (sometimes unstable)","TSThetaSetExtrapolate",th->extrapolate,&th->extrapolate,NULL);CHKERRQ(ierr); 641 ierr = PetscOptionsBool("-ts_theta_endpoint","Use the endpoint instead of midpoint form of the Theta method","TSThetaSetEndpoint",th->endpoint,&th->endpoint,NULL);CHKERRQ(ierr); 642 ierr = PetscOptionsBool("-ts_theta_adapt","Use time-step adaptivity with the Theta method","",th->adapt,&th->adapt,NULL);CHKERRQ(ierr); 643 } 644 ierr = PetscOptionsTail();CHKERRQ(ierr); 645 PetscFunctionReturn(0); 646 } 647 648 #undef __FUNCT__ 649 #define __FUNCT__ "TSView_Theta" 650 static PetscErrorCode TSView_Theta(TS ts,PetscViewer viewer) 651 { 652 TS_Theta *th = (TS_Theta*)ts->data; 653 PetscBool iascii; 654 PetscErrorCode ierr; 655 656 PetscFunctionBegin; 657 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 658 if (iascii) { 659 ierr = PetscViewerASCIIPrintf(viewer," Theta=%g\n",(double)th->Theta);CHKERRQ(ierr); 660 ierr = PetscViewerASCIIPrintf(viewer," Extrapolation=%s\n",th->extrapolate ? "yes" : "no");CHKERRQ(ierr); 661 } 662 if (ts->adapt) {ierr = TSAdaptView(ts->adapt,viewer);CHKERRQ(ierr);} 663 if (ts->snes) {ierr = SNESView(ts->snes,viewer);CHKERRQ(ierr);} 664 PetscFunctionReturn(0); 665 } 666 667 #undef __FUNCT__ 668 #define __FUNCT__ "TSThetaGetTheta_Theta" 669 static PetscErrorCode TSThetaGetTheta_Theta(TS ts,PetscReal *theta) 670 { 671 TS_Theta *th = (TS_Theta*)ts->data; 672 673 PetscFunctionBegin; 674 *theta = th->Theta; 675 PetscFunctionReturn(0); 676 } 677 678 #undef __FUNCT__ 679 #define __FUNCT__ "TSThetaSetTheta_Theta" 680 static PetscErrorCode TSThetaSetTheta_Theta(TS ts,PetscReal theta) 681 { 682 TS_Theta *th = (TS_Theta*)ts->data; 683 684 PetscFunctionBegin; 685 if (theta <= 0 || 1 < theta) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Theta %g not in range (0,1]",(double)theta); 686 th->Theta = theta; 687 th->order = (th->Theta == 0.5) ? 2 : 1; 688 PetscFunctionReturn(0); 689 } 690 691 #undef __FUNCT__ 692 #define __FUNCT__ "TSThetaGetEndpoint_Theta" 693 static PetscErrorCode TSThetaGetEndpoint_Theta(TS ts,PetscBool *endpoint) 694 { 695 TS_Theta *th = (TS_Theta*)ts->data; 696 697 PetscFunctionBegin; 698 *endpoint = th->endpoint; 699 PetscFunctionReturn(0); 700 } 701 702 #undef __FUNCT__ 703 #define __FUNCT__ "TSThetaSetEndpoint_Theta" 704 static PetscErrorCode TSThetaSetEndpoint_Theta(TS ts,PetscBool flg) 705 { 706 TS_Theta *th = (TS_Theta*)ts->data; 707 708 PetscFunctionBegin; 709 th->endpoint = flg; 710 PetscFunctionReturn(0); 711 } 712 713 #if defined(PETSC_HAVE_COMPLEX) 714 #undef __FUNCT__ 715 #define __FUNCT__ "TSComputeLinearStability_Theta" 716 static PetscErrorCode TSComputeLinearStability_Theta(TS ts,PetscReal xr,PetscReal xi,PetscReal *yr,PetscReal *yi) 717 { 718 PetscComplex z = xr + xi*PETSC_i,f; 719 TS_Theta *th = (TS_Theta*)ts->data; 720 const PetscReal one = 1.0; 721 722 PetscFunctionBegin; 723 f = (one + (one - th->Theta)*z)/(one - th->Theta*z); 724 *yr = PetscRealPartComplex(f); 725 *yi = PetscImaginaryPartComplex(f); 726 PetscFunctionReturn(0); 727 } 728 #endif 729 730 #undef __FUNCT__ 731 #define __FUNCT__ "TSGetStages_Theta" 732 static PetscErrorCode TSGetStages_Theta(TS ts,PetscInt *ns,Vec **Y) 733 { 734 TS_Theta *th = (TS_Theta*)ts->data; 735 736 PetscFunctionBegin; 737 if (ns) *ns = 1; 738 if (Y) *Y = th->endpoint ? &(th->X0) : &(th->X); 739 PetscFunctionReturn(0); 740 } 741 742 /* ------------------------------------------------------------ */ 743 /*MC 744 TSTHETA - DAE solver using the implicit Theta method 745 746 Level: beginner 747 748 Options Database: 749 + -ts_theta_theta <Theta> - Location of stage (0<Theta<=1) 750 . -ts_theta_extrapolate <flg> - Extrapolate stage solution from previous solution (sometimes unstable) 751 . -ts_theta_endpoint <flag> - Use the endpoint (like Crank-Nicholson) instead of midpoint form of the Theta method 752 - -ts_theta_adapt <flg> - Use time-step adaptivity with the Theta method 753 754 Notes: 755 $ -ts_type theta -ts_theta_theta 1.0 corresponds to backward Euler (TSBEULER) 756 $ -ts_type theta -ts_theta_theta 0.5 corresponds to the implicit midpoint rule 757 $ -ts_type theta -ts_theta_theta 0.5 -ts_theta_endpoint corresponds to Crank-Nicholson (TSCN) 758 759 This method can be applied to DAE. 760 761 This method is cast as a 1-stage implicit Runge-Kutta method. 762 763 .vb 764 Theta | Theta 765 ------------- 766 | 1 767 .ve 768 769 For the default Theta=0.5, this is also known as the implicit midpoint rule. 770 771 When the endpoint variant is chosen, the method becomes a 2-stage method with first stage explicit: 772 773 .vb 774 0 | 0 0 775 1 | 1-Theta Theta 776 ------------------- 777 | 1-Theta Theta 778 .ve 779 780 For the default Theta=0.5, this is the trapezoid rule (also known as Crank-Nicolson, see TSCN). 781 782 To apply a diagonally implicit RK method to DAE, the stage formula 783 784 $ Y_i = X + h sum_j a_ij Y'_j 785 786 is interpreted as a formula for Y'_i in terms of Y_i and known values (Y'_j, j<i) 787 788 .seealso: TSCreate(), TS, TSSetType(), TSCN, TSBEULER, TSThetaSetTheta(), TSThetaSetEndpoint() 789 790 M*/ 791 #undef __FUNCT__ 792 #define __FUNCT__ "TSCreate_Theta" 793 PETSC_EXTERN PetscErrorCode TSCreate_Theta(TS ts) 794 { 795 TS_Theta *th; 796 PetscErrorCode ierr; 797 798 PetscFunctionBegin; 799 ts->ops->reset = TSReset_Theta; 800 ts->ops->destroy = TSDestroy_Theta; 801 ts->ops->view = TSView_Theta; 802 ts->ops->setup = TSSetUp_Theta; 803 ts->ops->adjointsetup = TSAdjointSetUp_Theta; 804 ts->ops->step = TSStep_Theta; 805 ts->ops->interpolate = TSInterpolate_Theta; 806 ts->ops->evaluatewlte = TSEvaluateWLTE_Theta; 807 ts->ops->rollback = TSRollBack_Theta; 808 ts->ops->setfromoptions = TSSetFromOptions_Theta; 809 ts->ops->snesfunction = SNESTSFormFunction_Theta; 810 ts->ops->snesjacobian = SNESTSFormJacobian_Theta; 811 #if defined(PETSC_HAVE_COMPLEX) 812 ts->ops->linearstability = TSComputeLinearStability_Theta; 813 #endif 814 ts->ops->getstages = TSGetStages_Theta; 815 ts->ops->adjointstep = TSAdjointStep_Theta; 816 ts->ops->adjointintegral = TSAdjointCostIntegral_Theta; 817 ts->ops->forwardintegral = TSForwardCostIntegral_Theta; 818 819 ierr = PetscNewLog(ts,&th);CHKERRQ(ierr); 820 ts->data = (void*)th; 821 822 th->extrapolate = PETSC_FALSE; 823 th->Theta = 0.5; 824 th->order = 2; 825 th->adapt = PETSC_FALSE; 826 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSThetaGetTheta_C",TSThetaGetTheta_Theta);CHKERRQ(ierr); 827 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSThetaSetTheta_C",TSThetaSetTheta_Theta);CHKERRQ(ierr); 828 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSThetaGetEndpoint_C",TSThetaGetEndpoint_Theta);CHKERRQ(ierr); 829 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSThetaSetEndpoint_C",TSThetaSetEndpoint_Theta);CHKERRQ(ierr); 830 PetscFunctionReturn(0); 831 } 832 833 #undef __FUNCT__ 834 #define __FUNCT__ "TSThetaGetTheta" 835 /*@ 836 TSThetaGetTheta - Get the abscissa of the stage in (0,1]. 837 838 Not Collective 839 840 Input Parameter: 841 . ts - timestepping context 842 843 Output Parameter: 844 . theta - stage abscissa 845 846 Note: 847 Use of this function is normally only required to hack TSTHETA to use a modified integration scheme. 848 849 Level: Advanced 850 851 .seealso: TSThetaSetTheta() 852 @*/ 853 PetscErrorCode TSThetaGetTheta(TS ts,PetscReal *theta) 854 { 855 PetscErrorCode ierr; 856 857 PetscFunctionBegin; 858 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 859 PetscValidPointer(theta,2); 860 ierr = PetscUseMethod(ts,"TSThetaGetTheta_C",(TS,PetscReal*),(ts,theta));CHKERRQ(ierr); 861 PetscFunctionReturn(0); 862 } 863 864 #undef __FUNCT__ 865 #define __FUNCT__ "TSThetaSetTheta" 866 /*@ 867 TSThetaSetTheta - Set the abscissa of the stage in (0,1]. 868 869 Not Collective 870 871 Input Parameter: 872 + ts - timestepping context 873 - theta - stage abscissa 874 875 Options Database: 876 . -ts_theta_theta <theta> 877 878 Level: Intermediate 879 880 .seealso: TSThetaGetTheta() 881 @*/ 882 PetscErrorCode TSThetaSetTheta(TS ts,PetscReal theta) 883 { 884 PetscErrorCode ierr; 885 886 PetscFunctionBegin; 887 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 888 ierr = PetscTryMethod(ts,"TSThetaSetTheta_C",(TS,PetscReal),(ts,theta));CHKERRQ(ierr); 889 PetscFunctionReturn(0); 890 } 891 892 #undef __FUNCT__ 893 #define __FUNCT__ "TSThetaGetEndpoint" 894 /*@ 895 TSThetaGetEndpoint - Gets whether to use the endpoint variant of the method (e.g. trapezoid/Crank-Nicolson instead of midpoint rule). 896 897 Not Collective 898 899 Input Parameter: 900 . ts - timestepping context 901 902 Output Parameter: 903 . endpoint - PETSC_TRUE when using the endpoint variant 904 905 Level: Advanced 906 907 .seealso: TSThetaSetEndpoint(), TSTHETA, TSCN 908 @*/ 909 PetscErrorCode TSThetaGetEndpoint(TS ts,PetscBool *endpoint) 910 { 911 PetscErrorCode ierr; 912 913 PetscFunctionBegin; 914 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 915 PetscValidPointer(endpoint,2); 916 ierr = PetscUseMethod(ts,"TSThetaGetEndpoint_C",(TS,PetscBool*),(ts,endpoint));CHKERRQ(ierr); 917 PetscFunctionReturn(0); 918 } 919 920 #undef __FUNCT__ 921 #define __FUNCT__ "TSThetaSetEndpoint" 922 /*@ 923 TSThetaSetEndpoint - Sets whether to use the endpoint variant of the method (e.g. trapezoid/Crank-Nicolson instead of midpoint rule). 924 925 Not Collective 926 927 Input Parameter: 928 + ts - timestepping context 929 - flg - PETSC_TRUE to use the endpoint variant 930 931 Options Database: 932 . -ts_theta_endpoint <flg> 933 934 Level: Intermediate 935 936 .seealso: TSTHETA, TSCN 937 @*/ 938 PetscErrorCode TSThetaSetEndpoint(TS ts,PetscBool flg) 939 { 940 PetscErrorCode ierr; 941 942 PetscFunctionBegin; 943 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 944 ierr = PetscTryMethod(ts,"TSThetaSetEndpoint_C",(TS,PetscBool),(ts,flg));CHKERRQ(ierr); 945 PetscFunctionReturn(0); 946 } 947 948 /* 949 * TSBEULER and TSCN are straightforward specializations of TSTHETA. 950 * The creation functions for these specializations are below. 951 */ 952 953 #undef __FUNCT__ 954 #define __FUNCT__ "TSSetUp_BEuler" 955 static PetscErrorCode TSSetUp_BEuler(TS ts) 956 { 957 TS_Theta *th = (TS_Theta*)ts->data; 958 PetscErrorCode ierr; 959 960 PetscFunctionBegin; 961 if (th->Theta != 1.0) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_OPT_OVERWRITE,"Can not change the default value (1) of theta when using backward Euler\n"); 962 if (th->endpoint) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_OPT_OVERWRITE,"Can not change to the endpoint form of the Theta methods when using backward Euler\n"); 963 ierr = TSSetUp_Theta(ts);CHKERRQ(ierr); 964 PetscFunctionReturn(0); 965 } 966 967 #undef __FUNCT__ 968 #define __FUNCT__ "TSView_BEuler" 969 static PetscErrorCode TSView_BEuler(TS ts,PetscViewer viewer) 970 { 971 PetscErrorCode ierr; 972 973 PetscFunctionBegin; 974 if (ts->adapt) {ierr = TSAdaptView(ts->adapt,viewer);CHKERRQ(ierr);} 975 if (ts->snes) {ierr = SNESView(ts->snes,viewer);CHKERRQ(ierr);} 976 PetscFunctionReturn(0); 977 } 978 979 /*MC 980 TSBEULER - ODE solver using the implicit backward Euler method 981 982 Level: beginner 983 984 Notes: 985 TSBEULER is equivalent to TSTHETA with Theta=1.0 986 987 $ -ts_type theta -ts_theta_theta 1.0 988 989 .seealso: TSCreate(), TS, TSSetType(), TSEULER, TSCN, TSTHETA 990 991 M*/ 992 #undef __FUNCT__ 993 #define __FUNCT__ "TSCreate_BEuler" 994 PETSC_EXTERN PetscErrorCode TSCreate_BEuler(TS ts) 995 { 996 PetscErrorCode ierr; 997 998 PetscFunctionBegin; 999 ierr = TSCreate_Theta(ts);CHKERRQ(ierr); 1000 ierr = TSThetaSetTheta(ts,1.0);CHKERRQ(ierr); 1001 ierr = TSThetaSetEndpoint(ts,PETSC_FALSE);CHKERRQ(ierr); 1002 ts->ops->setup = TSSetUp_BEuler; 1003 ts->ops->view = TSView_BEuler; 1004 PetscFunctionReturn(0); 1005 } 1006 1007 #undef __FUNCT__ 1008 #define __FUNCT__ "TSSetUp_CN" 1009 static PetscErrorCode TSSetUp_CN(TS ts) 1010 { 1011 TS_Theta *th = (TS_Theta*)ts->data; 1012 PetscErrorCode ierr; 1013 1014 PetscFunctionBegin; 1015 if (th->Theta != 0.5) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_OPT_OVERWRITE,"Can not change the default value (0.5) of theta when using Crank-Nicolson\n"); 1016 if (!th->endpoint) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_OPT_OVERWRITE,"Can not change to the midpoint form of the Theta methods when using Crank-Nicolson\n"); 1017 ierr = TSSetUp_Theta(ts);CHKERRQ(ierr); 1018 PetscFunctionReturn(0); 1019 } 1020 1021 #undef __FUNCT__ 1022 #define __FUNCT__ "TSView_CN" 1023 static PetscErrorCode TSView_CN(TS ts,PetscViewer viewer) 1024 { 1025 PetscErrorCode ierr; 1026 1027 PetscFunctionBegin; 1028 if (ts->adapt) {ierr = TSAdaptView(ts->adapt,viewer);CHKERRQ(ierr);} 1029 if (ts->snes) {ierr = SNESView(ts->snes,viewer);CHKERRQ(ierr);} 1030 PetscFunctionReturn(0); 1031 } 1032 1033 /*MC 1034 TSCN - ODE solver using the implicit Crank-Nicolson method. 1035 1036 Level: beginner 1037 1038 Notes: 1039 TSCN is equivalent to TSTHETA with Theta=0.5 and the "endpoint" option set. I.e. 1040 1041 $ -ts_type theta -ts_theta_theta 0.5 -ts_theta_endpoint 1042 1043 .seealso: TSCreate(), TS, TSSetType(), TSBEULER, TSTHETA 1044 1045 M*/ 1046 #undef __FUNCT__ 1047 #define __FUNCT__ "TSCreate_CN" 1048 PETSC_EXTERN PetscErrorCode TSCreate_CN(TS ts) 1049 { 1050 PetscErrorCode ierr; 1051 1052 PetscFunctionBegin; 1053 ierr = TSCreate_Theta(ts);CHKERRQ(ierr); 1054 ierr = TSThetaSetTheta(ts,0.5);CHKERRQ(ierr); 1055 ierr = TSThetaSetEndpoint(ts,PETSC_TRUE);CHKERRQ(ierr); 1056 ts->ops->setup = TSSetUp_CN; 1057 ts->ops->view = TSView_CN; 1058 PetscFunctionReturn(0); 1059 } 1060