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