1 /* 2 Code for timestepping with implicit generalized-\alpha method 3 for first order systems. 4 */ 5 #include <petsc/private/tsimpl.h> /*I "petscts.h" I*/ 6 7 static PetscBool cited = PETSC_FALSE; 8 static const char citation[] = 9 "@article{Jansen2000,\n" 10 " title = {A generalized-$\\alpha$ method for integrating the filtered {N}avier--{S}tokes equations with a stabilized finite element method},\n" 11 " author = {Kenneth E. Jansen and Christian H. Whiting and Gregory M. Hulbert},\n" 12 " journal = {Computer Methods in Applied Mechanics and Engineering},\n" 13 " volume = {190},\n" 14 " number = {3--4},\n" 15 " pages = {305--319},\n" 16 " year = {2000},\n" 17 " issn = {0045-7825},\n" 18 " doi = {http://dx.doi.org/10.1016/S0045-7825(00)00203-6}\n}\n"; 19 20 typedef struct { 21 PetscReal stage_time; 22 PetscReal shift_V; 23 PetscReal scale_F; 24 Vec X0,Xa,X1; 25 Vec V0,Va,V1; 26 27 PetscReal Alpha_m; 28 PetscReal Alpha_f; 29 PetscReal Gamma; 30 PetscInt order; 31 32 PetscBool adapt; 33 PetscReal time_step_prev; 34 Vec vec_sol_prev; 35 Vec vec_work; 36 37 TSStepStatus status; 38 } TS_Alpha; 39 40 #undef __FUNCT__ 41 #define __FUNCT__ "TSAlpha_StageTime" 42 static PetscErrorCode TSAlpha_StageTime(TS ts) 43 { 44 TS_Alpha *th = (TS_Alpha*)ts->data; 45 PetscReal t = ts->ptime; 46 PetscReal dt = ts->time_step; 47 PetscReal Alpha_m = th->Alpha_m; 48 PetscReal Alpha_f = th->Alpha_f; 49 PetscReal Gamma = th->Gamma; 50 51 PetscFunctionBegin; 52 th->stage_time = t + Alpha_f*dt; 53 th->shift_V = Alpha_m/(Alpha_f*Gamma*dt); 54 th->scale_F = 1/Alpha_f; 55 PetscFunctionReturn(0); 56 } 57 58 #undef __FUNCT__ 59 #define __FUNCT__ "TSAlpha_StageVecs" 60 static PetscErrorCode TSAlpha_StageVecs(TS ts,Vec X) 61 { 62 TS_Alpha *th = (TS_Alpha*)ts->data; 63 Vec X1 = X, V1 = th->V1; 64 Vec Xa = th->Xa, Va = th->Va; 65 Vec X0 = th->X0, V0 = th->V0; 66 PetscReal dt = ts->time_step; 67 PetscReal Alpha_m = th->Alpha_m; 68 PetscReal Alpha_f = th->Alpha_f; 69 PetscReal Gamma = th->Gamma; 70 PetscErrorCode ierr; 71 72 PetscFunctionBegin; 73 /* V1 = 1/(Gamma*dT)*(X1-X0) + (1-1/Gamma)*V0 */ 74 ierr = VecWAXPY(V1,-1.0,X0,X1);CHKERRQ(ierr); 75 ierr = VecAXPBY(V1,1-1/Gamma,1/(Gamma*dt),V0);CHKERRQ(ierr); 76 /* Xa = X0 + Alpha_f*(X1-X0) */ 77 ierr = VecWAXPY(Xa,-1.0,X0,X1);CHKERRQ(ierr); 78 ierr = VecAYPX(Xa,Alpha_f,X0);CHKERRQ(ierr); 79 /* Va = V0 + Alpha_m*(V1-V0) */ 80 ierr = VecWAXPY(Va,-1.0,V0,V1);CHKERRQ(ierr); 81 ierr = VecAYPX(Va,Alpha_m,V0);CHKERRQ(ierr); 82 PetscFunctionReturn(0); 83 } 84 85 #undef __FUNCT__ 86 #define __FUNCT__ "TS_SNESSolve" 87 static PetscErrorCode TS_SNESSolve(TS ts,Vec b,Vec x) 88 { 89 PetscInt nits,lits; 90 PetscErrorCode ierr; 91 92 PetscFunctionBegin; 93 ierr = SNESSolve(ts->snes,b,x);CHKERRQ(ierr); 94 ierr = SNESGetIterationNumber(ts->snes,&nits);CHKERRQ(ierr); 95 ierr = SNESGetLinearSolveIterations(ts->snes,&lits);CHKERRQ(ierr); 96 ts->snes_its += nits; ts->ksp_its += lits; 97 PetscFunctionReturn(0); 98 } 99 100 /* 101 Compute a consistent initial state for the generalized-alpha method. 102 - Solve two successive backward Euler steps with halved time step. 103 - Compute the initial time derivative using backward differences. 104 - If using adaptivity, estimate the LTE of the initial step. 105 */ 106 #undef __FUNCT__ 107 #define __FUNCT__ "TSAlpha_ResetStep" 108 static PetscErrorCode TSAlpha_ResetStep(TS ts,PetscBool *initok) 109 { 110 TS_Alpha *th = (TS_Alpha*)ts->data; 111 PetscReal time_step; 112 PetscReal alpha_m,alpha_f,gamma; 113 Vec X0 = ts->vec_sol, X1, X2 = th->X1; 114 PetscBool stageok; 115 PetscErrorCode ierr; 116 117 PetscFunctionBegin; 118 ierr = VecDuplicate(X0,&X1);CHKERRQ(ierr); 119 120 /* Setup backward Euler with halved time step */ 121 ierr = TSAlphaGetParams(ts,&alpha_m,&alpha_f,&gamma);CHKERRQ(ierr); 122 ierr = TSAlphaSetParams(ts,1,1,1);CHKERRQ(ierr); 123 ierr = TSGetTimeStep(ts,&time_step);CHKERRQ(ierr); 124 ts->time_step = time_step/2; 125 ierr = TSAlpha_StageTime(ts);CHKERRQ(ierr); 126 th->stage_time = ts->ptime; 127 ierr = VecZeroEntries(th->V0);CHKERRQ(ierr); 128 129 /* First BE step, (t0,X0) -> (t1,X1)*/ 130 th->stage_time += ts->time_step; 131 ierr = VecCopy(X0,th->X0);CHKERRQ(ierr); 132 ierr = TSPreStage(ts,th->stage_time);CHKERRQ(ierr); 133 ierr = VecCopy(th->X0,X1);CHKERRQ(ierr); 134 ierr = TS_SNESSolve(ts,NULL,X1);CHKERRQ(ierr); 135 ierr = TSPostStage(ts,th->stage_time,0,&X1);CHKERRQ(ierr); 136 ierr = TSAdaptCheckStage(ts->adapt,ts,th->stage_time,X1,&stageok);CHKERRQ(ierr); 137 if (!stageok) goto finally; 138 139 /* Second BE step, (t1,X1) -> (t2,X2)*/ 140 th->stage_time += ts->time_step; 141 ierr = VecCopy(X1,th->X0);CHKERRQ(ierr); 142 ierr = TSPreStage(ts,th->stage_time);CHKERRQ(ierr); 143 ierr = VecCopy(th->X0,X2);CHKERRQ(ierr); 144 ierr = TS_SNESSolve(ts,NULL,X2);CHKERRQ(ierr); 145 ierr = TSPostStage(ts,th->stage_time,0,&X2);CHKERRQ(ierr); 146 ierr = TSAdaptCheckStage(ts->adapt,ts,th->stage_time,X2,&stageok);CHKERRQ(ierr); 147 if (!stageok) goto finally; 148 149 /* Compute V0 ~ dX/dt at t0 with backward differences */ 150 ierr = VecZeroEntries(th->V0);CHKERRQ(ierr); 151 ierr = VecAXPY(th->V0,-3/ts->time_step,X0);CHKERRQ(ierr); 152 ierr = VecAXPY(th->V0,+4/ts->time_step,X1);CHKERRQ(ierr); 153 ierr = VecAXPY(th->V0,-1/ts->time_step,X2);CHKERRQ(ierr); 154 155 /* Rough, lower-order estimate LTE of the initial step */ 156 if (th->adapt) { 157 ierr = VecZeroEntries(th->vec_sol_prev);CHKERRQ(ierr); 158 ierr = VecAXPY(th->vec_sol_prev,+2,X2);CHKERRQ(ierr); 159 ierr = VecAXPY(th->vec_sol_prev,-4,X1);CHKERRQ(ierr); 160 ierr = VecAXPY(th->vec_sol_prev,+2,X0);CHKERRQ(ierr); 161 } 162 163 finally: 164 /* Revert TSAlpha to the initial state (t0,X0) */ 165 if (initok) *initok = stageok; 166 ierr = TSSetTimeStep(ts,time_step);CHKERRQ(ierr); 167 ierr = TSAlphaSetParams(ts,alpha_m,alpha_f,gamma);CHKERRQ(ierr); 168 ierr = VecCopy(ts->vec_sol,th->X0);CHKERRQ(ierr); 169 170 ierr = VecDestroy(&X1);CHKERRQ(ierr); 171 PetscFunctionReturn(0); 172 } 173 174 #undef __FUNCT__ 175 #define __FUNCT__ "TSAlpha_AdaptStep" 176 static PetscErrorCode TSAlpha_AdaptStep(TS ts,PetscReal *next_h,PetscBool *accept) 177 { 178 TS_Alpha *th = (TS_Alpha*)ts->data; 179 PetscInt scheme; 180 PetscErrorCode ierr; 181 182 PetscFunctionBegin; 183 th->status = TS_STEP_PENDING; 184 ierr = TSAdaptCandidatesClear(ts->adapt);CHKERRQ(ierr); 185 ierr = TSAdaptCandidateAdd(ts->adapt,"",/*order=*/2,1,1.0,1.0,PETSC_TRUE);CHKERRQ(ierr); 186 ierr = TSAdaptChoose(ts->adapt,ts,ts->time_step,&scheme,next_h,accept);CHKERRQ(ierr); 187 th->status = *accept ? TS_STEP_COMPLETE : TS_STEP_INCOMPLETE; 188 PetscFunctionReturn(0); 189 } 190 191 #define TSEvent_Status(ts) (ts->event ? ts->event->status : TSEVENT_NONE) 192 193 #undef __FUNCT__ 194 #define __FUNCT__ "TSStep_Alpha" 195 static PetscErrorCode TSStep_Alpha(TS ts) 196 { 197 TS_Alpha *th = (TS_Alpha*)ts->data; 198 PetscInt rejections = 0; 199 PetscBool stageok,accept = PETSC_TRUE; 200 PetscReal next_time_step = ts->time_step; 201 PetscErrorCode ierr; 202 203 PetscFunctionBegin; 204 ierr = PetscCitationsRegister(citation,&cited);CHKERRQ(ierr); 205 206 ierr = TSPreStep(ts);CHKERRQ(ierr); 207 208 th->status = TS_STEP_INCOMPLETE; 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 ierr = VecCopy(th->V1,th->V0);CHKERRQ(ierr); 214 } 215 216 while (!ts->reason && th->status != TS_STEP_COMPLETE) { 217 218 if (!ts->steps || TSEvent_Status(ts) == TSEVENT_RESET_NEXTSTEP) { 219 ierr = TSAlpha_ResetStep(ts,&stageok);CHKERRQ(ierr); 220 if (!stageok) {accept = PETSC_FALSE; goto reject_step;} 221 } 222 223 ierr = TSAlpha_StageTime(ts);CHKERRQ(ierr); 224 ierr = VecCopy(th->X0,th->X1);CHKERRQ(ierr); 225 ierr = TSPreStage(ts,th->stage_time);CHKERRQ(ierr); 226 ierr = TS_SNESSolve(ts,NULL,th->X1);CHKERRQ(ierr); 227 ierr = TSPostStage(ts,th->stage_time,0,&th->X1);CHKERRQ(ierr); 228 ierr = TSAdaptCheckStage(ts->adapt,ts,th->stage_time,th->X1,&stageok);CHKERRQ(ierr); 229 if (!stageok) {accept = PETSC_FALSE; goto reject_step;} 230 231 ierr = VecCopy(th->X1,ts->vec_sol);CHKERRQ(ierr); 232 if (TSEvent_Status(ts) == TSEVENT_NONE) { 233 ierr = TSAlpha_AdaptStep(ts,&next_time_step,&accept);CHKERRQ(ierr); 234 if (!accept) { 235 ierr = VecCopy(th->X0,ts->vec_sol);CHKERRQ(ierr); 236 ts->time_step = next_time_step; goto reject_step; 237 } 238 } 239 240 ts->ptime += ts->time_step; 241 ts->time_step = next_time_step; 242 ts->steps++; 243 break; 244 245 reject_step: 246 ts->reject++; 247 if (!ts->reason && ++rejections > ts->max_reject && ts->max_reject >= 0) { 248 ts->reason = TS_DIVERGED_STEP_REJECTED; 249 ierr = PetscInfo2(ts,"Step=%D, step rejections %D greater than current TS allowed, stopping solve\n",ts->steps,rejections);CHKERRQ(ierr); 250 } 251 } 252 PetscFunctionReturn(0); 253 } 254 255 #undef __FUNCT__ 256 #define __FUNCT__ "TSEvaluateWLTE_Alpha" 257 static PetscErrorCode TSEvaluateWLTE_Alpha(TS ts,NormType wnormtype,PetscInt *order,PetscReal *wlte) 258 { 259 TS_Alpha *th = (TS_Alpha*)ts->data; 260 Vec X = th->X1; /* X = solution */ 261 Vec Y = th->vec_work; /* Y = X + LTE */ 262 PetscErrorCode ierr; 263 264 PetscFunctionBegin; 265 if (!ts->steps || TSEvent_Status(ts) == TSEVENT_RESET_NEXTSTEP) { 266 /* th->vec_sol_prev is set to the LTE in TSAlpha_ResetStep() */ 267 ierr = VecWAXPY(Y,1.0,th->vec_sol_prev,X);CHKERRQ(ierr); 268 } else { 269 /* Compute LTE using backward differences with non-constant time step */ 270 PetscReal a = 1 + th->time_step_prev/ts->time_step; 271 PetscScalar scal[3]; Vec vecs[3]; 272 scal[0] = +1/a; scal[1] = -1/(a-1); scal[2] = +1/(a*(a-1)); 273 vecs[0] = th->X1; vecs[1] = th->X0; vecs[2] = th->vec_sol_prev; 274 ierr = VecCopy(X,Y);CHKERRQ(ierr); 275 ierr = VecMAXPY(Y,3,scal,vecs);CHKERRQ(ierr); 276 } 277 ierr = TSErrorWeightedNorm(ts,X,Y,wnormtype,wlte);CHKERRQ(ierr); 278 if (order) *order = 2; 279 PetscFunctionReturn(0); 280 } 281 282 #undef __FUNCT__ 283 #define __FUNCT__ "TSRollBack_Alpha" 284 static PetscErrorCode TSRollBack_Alpha(TS ts) 285 { 286 TS_Alpha *th = (TS_Alpha*)ts->data; 287 PetscErrorCode ierr; 288 289 PetscFunctionBegin; 290 ierr = VecCopy(th->X0,ts->vec_sol);CHKERRQ(ierr); 291 PetscFunctionReturn(0); 292 } 293 294 #undef __FUNCT__ 295 #define __FUNCT__ "TSInterpolate_Alpha" 296 static PetscErrorCode TSInterpolate_Alpha(TS ts,PetscReal t,Vec X) 297 { 298 TS_Alpha *th = (TS_Alpha*)ts->data; 299 PetscReal dt = t - ts->ptime; 300 PetscErrorCode ierr; 301 302 PetscFunctionBegin; 303 ierr = VecCopy(ts->vec_sol,X);CHKERRQ(ierr); 304 ierr = VecAXPY(X,th->Gamma*dt,th->V1);CHKERRQ(ierr); 305 ierr = VecAXPY(X,(1-th->Gamma)*dt,th->V0);CHKERRQ(ierr); 306 PetscFunctionReturn(0); 307 } 308 309 #undef __FUNCT__ 310 #define __FUNCT__ "SNESTSFormFunction_Alpha" 311 static PetscErrorCode SNESTSFormFunction_Alpha(PETSC_UNUSED SNES snes,Vec X,Vec F,TS ts) 312 { 313 TS_Alpha *th = (TS_Alpha*)ts->data; 314 PetscReal ta = th->stage_time; 315 Vec Xa = th->Xa, Va = th->Va; 316 PetscErrorCode ierr; 317 318 PetscFunctionBegin; 319 ierr = TSAlpha_StageVecs(ts,X);CHKERRQ(ierr); 320 /* F = Function(ta,Xa,Va) */ 321 ierr = TSComputeIFunction(ts,ta,Xa,Va,F,PETSC_FALSE);CHKERRQ(ierr); 322 ierr = VecScale(F,th->scale_F);CHKERRQ(ierr); 323 PetscFunctionReturn(0); 324 } 325 326 #undef __FUNCT__ 327 #define __FUNCT__ "SNESTSFormJacobian_Alpha" 328 static PetscErrorCode SNESTSFormJacobian_Alpha(PETSC_UNUSED SNES snes,PETSC_UNUSED Vec X,Mat J,Mat P,TS ts) 329 { 330 TS_Alpha *th = (TS_Alpha*)ts->data; 331 PetscReal ta = th->stage_time; 332 Vec Xa = th->Xa, Va = th->Va; 333 PetscReal dVdX = th->shift_V; 334 PetscErrorCode ierr; 335 336 PetscFunctionBegin; 337 /* J,P = Jacobian(ta,Xa,Va) */ 338 ierr = TSComputeIJacobian(ts,ta,Xa,Va,dVdX,J,P,PETSC_FALSE);CHKERRQ(ierr); 339 PetscFunctionReturn(0); 340 } 341 342 #undef __FUNCT__ 343 #define __FUNCT__ "TSReset_Alpha" 344 static PetscErrorCode TSReset_Alpha(TS ts) 345 { 346 TS_Alpha *th = (TS_Alpha*)ts->data; 347 PetscErrorCode ierr; 348 349 PetscFunctionBegin; 350 ierr = VecDestroy(&th->X0);CHKERRQ(ierr); 351 ierr = VecDestroy(&th->Xa);CHKERRQ(ierr); 352 ierr = VecDestroy(&th->X1);CHKERRQ(ierr); 353 ierr = VecDestroy(&th->V0);CHKERRQ(ierr); 354 ierr = VecDestroy(&th->Va);CHKERRQ(ierr); 355 ierr = VecDestroy(&th->V1);CHKERRQ(ierr); 356 ierr = VecDestroy(&th->vec_sol_prev);CHKERRQ(ierr); 357 ierr = VecDestroy(&th->vec_work);CHKERRQ(ierr); 358 PetscFunctionReturn(0); 359 } 360 361 #undef __FUNCT__ 362 #define __FUNCT__ "TSDestroy_Alpha" 363 static PetscErrorCode TSDestroy_Alpha(TS ts) 364 { 365 PetscErrorCode ierr; 366 367 PetscFunctionBegin; 368 ierr = TSReset_Alpha(ts);CHKERRQ(ierr); 369 ierr = PetscFree(ts->data);CHKERRQ(ierr); 370 371 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSAlphaUseAdapt_C",NULL);CHKERRQ(ierr); 372 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSAlphaSetRadius_C",NULL);CHKERRQ(ierr); 373 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSAlphaSetParams_C",NULL);CHKERRQ(ierr); 374 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSAlphaGetParams_C",NULL);CHKERRQ(ierr); 375 PetscFunctionReturn(0); 376 } 377 378 #undef __FUNCT__ 379 #define __FUNCT__ "TSSetUp_Alpha" 380 static PetscErrorCode TSSetUp_Alpha(TS ts) 381 { 382 TS_Alpha *th = (TS_Alpha*)ts->data; 383 PetscErrorCode ierr; 384 385 PetscFunctionBegin; 386 ierr = VecDuplicate(ts->vec_sol,&th->X0);CHKERRQ(ierr); 387 ierr = VecDuplicate(ts->vec_sol,&th->Xa);CHKERRQ(ierr); 388 ierr = VecDuplicate(ts->vec_sol,&th->X1);CHKERRQ(ierr); 389 ierr = VecDuplicate(ts->vec_sol,&th->V0);CHKERRQ(ierr); 390 ierr = VecDuplicate(ts->vec_sol,&th->Va);CHKERRQ(ierr); 391 ierr = VecDuplicate(ts->vec_sol,&th->V1);CHKERRQ(ierr); 392 if (!th->adapt) { 393 ierr = TSAdaptDestroy(&ts->adapt);CHKERRQ(ierr); 394 ierr = TSGetAdapt(ts,&ts->adapt);CHKERRQ(ierr); 395 ierr = TSAdaptSetType(ts->adapt,TSADAPTNONE);CHKERRQ(ierr); 396 } else { 397 ierr = TSGetAdapt(ts,&ts->adapt);CHKERRQ(ierr); 398 ierr = VecDuplicate(ts->vec_sol,&th->vec_sol_prev);CHKERRQ(ierr); 399 ierr = VecDuplicate(ts->vec_sol,&th->vec_work);CHKERRQ(ierr); 400 if (ts->exact_final_time == TS_EXACTFINALTIME_UNSPECIFIED) 401 ts->exact_final_time = TS_EXACTFINALTIME_MATCHSTEP; 402 } 403 ierr = TSGetSNES(ts,&ts->snes);CHKERRQ(ierr); 404 PetscFunctionReturn(0); 405 } 406 407 #undef __FUNCT__ 408 #define __FUNCT__ "TSSetFromOptions_Alpha" 409 static PetscErrorCode TSSetFromOptions_Alpha(PetscOptionItems *PetscOptionsObject,TS ts) 410 { 411 TS_Alpha *th = (TS_Alpha*)ts->data; 412 PetscErrorCode ierr; 413 414 PetscFunctionBegin; 415 ierr = PetscOptionsHead(PetscOptionsObject,"Generalized-Alpha ODE solver options");CHKERRQ(ierr); 416 { 417 PetscBool flg; 418 PetscReal radius = 1; 419 PetscBool adapt = th->adapt; 420 ierr = PetscOptionsReal("-ts_alpha_radius","Spectral radius (high-frequency dissipation)","TSAlphaSetRadius",radius,&radius,&flg);CHKERRQ(ierr); 421 if (flg) {ierr = TSAlphaSetRadius(ts,radius);CHKERRQ(ierr);} 422 ierr = PetscOptionsReal("-ts_alpha_alpha_m","Algoritmic parameter alpha_m","TSAlphaSetParams",th->Alpha_m,&th->Alpha_m,NULL);CHKERRQ(ierr); 423 ierr = PetscOptionsReal("-ts_alpha_alpha_f","Algoritmic parameter alpha_f","TSAlphaSetParams",th->Alpha_f,&th->Alpha_f,NULL);CHKERRQ(ierr); 424 ierr = PetscOptionsReal("-ts_alpha_gamma","Algoritmic parameter gamma","TSAlphaSetParams",th->Gamma,&th->Gamma,NULL);CHKERRQ(ierr); 425 ierr = TSAlphaSetParams(ts,th->Alpha_m,th->Alpha_f,th->Gamma);CHKERRQ(ierr); 426 ierr = PetscOptionsBool("-ts_alpha_adapt","Use time-step adaptivity with the Alpha method","TSAlpha2UseAdapt",adapt,&adapt,&flg);CHKERRQ(ierr); 427 if (flg) {ierr = TSAlphaUseAdapt(ts,adapt);CHKERRQ(ierr);} 428 } 429 ierr = PetscOptionsTail();CHKERRQ(ierr); 430 PetscFunctionReturn(0); 431 } 432 433 #undef __FUNCT__ 434 #define __FUNCT__ "TSView_Alpha" 435 static PetscErrorCode TSView_Alpha(TS ts,PetscViewer viewer) 436 { 437 TS_Alpha *th = (TS_Alpha*)ts->data; 438 PetscBool ascii; 439 PetscErrorCode ierr; 440 441 PetscFunctionBegin; 442 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&ascii);CHKERRQ(ierr); 443 if (ascii) {ierr = PetscViewerASCIIPrintf(viewer," Alpha_m=%g, Alpha_f=%g, Gamma=%g\n",(double)th->Alpha_m,(double)th->Alpha_f,(double)th->Gamma);CHKERRQ(ierr);} 444 if (ts->snes) {ierr = SNESView(ts->snes,viewer);CHKERRQ(ierr);} 445 PetscFunctionReturn(0); 446 } 447 448 #undef __FUNCT__ 449 #define __FUNCT__ "TSAlphaUseAdapt_Alpha" 450 static PetscErrorCode TSAlphaUseAdapt_Alpha(TS ts,PetscBool use) 451 { 452 TS_Alpha *th = (TS_Alpha*)ts->data; 453 454 PetscFunctionBegin; 455 if (use == th->adapt) PetscFunctionReturn(0); 456 if (ts->setupcalled) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ORDER,"Cannot change adaptivity after TSSetUp()"); 457 th->adapt = use; 458 PetscFunctionReturn(0); 459 } 460 461 #undef __FUNCT__ 462 #define __FUNCT__ "TSAlphaSetRadius_Alpha" 463 static PetscErrorCode TSAlphaSetRadius_Alpha(TS ts,PetscReal radius) 464 { 465 PetscReal alpha_m,alpha_f,gamma; 466 PetscErrorCode ierr; 467 468 PetscFunctionBegin; 469 if (radius < 0 || radius > 1) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Radius %g not in range [0,1]",(double)radius); 470 alpha_m = (PetscReal)0.5*(3-radius)/(1+radius); 471 alpha_f = 1/(1+radius); 472 gamma = (PetscReal)0.5 + alpha_m - alpha_f; 473 ierr = TSAlphaSetParams(ts,alpha_m,alpha_f,gamma);CHKERRQ(ierr); 474 PetscFunctionReturn(0); 475 } 476 477 #undef __FUNCT__ 478 #define __FUNCT__ "TSAlphaSetParams_Alpha" 479 static PetscErrorCode TSAlphaSetParams_Alpha(TS ts,PetscReal alpha_m,PetscReal alpha_f,PetscReal gamma) 480 { 481 TS_Alpha *th = (TS_Alpha*)ts->data; 482 PetscReal tol = 100*PETSC_MACHINE_EPSILON; 483 PetscReal res = ((PetscReal)0.5 + alpha_m - alpha_f) - gamma; 484 485 PetscFunctionBegin; 486 th->Alpha_m = alpha_m; 487 th->Alpha_f = alpha_f; 488 th->Gamma = gamma; 489 th->order = (PetscAbsReal(res) < tol) ? 2 : 1; 490 PetscFunctionReturn(0); 491 } 492 493 #undef __FUNCT__ 494 #define __FUNCT__ "TSAlphaGetParams_Alpha" 495 static PetscErrorCode TSAlphaGetParams_Alpha(TS ts,PetscReal *alpha_m,PetscReal *alpha_f,PetscReal *gamma) 496 { 497 TS_Alpha *th = (TS_Alpha*)ts->data; 498 499 PetscFunctionBegin; 500 if (alpha_m) *alpha_m = th->Alpha_m; 501 if (alpha_f) *alpha_f = th->Alpha_f; 502 if (gamma) *gamma = th->Gamma; 503 PetscFunctionReturn(0); 504 } 505 506 /*MC 507 TSALPHA - ODE/DAE solver using the implicit Generalized-Alpha method 508 for first-order systems 509 510 Level: beginner 511 512 References: 513 K.E. Jansen, C.H. Whiting, G.M. Hulber, "A generalized-alpha 514 method for integrating the filtered Navier-Stokes equations with a 515 stabilized finite element method", Computer Methods in Applied 516 Mechanics and Engineering, 190, 305-319, 2000. 517 DOI: 10.1016/S0045-7825(00)00203-6. 518 519 J. Chung, G.M.Hubert. "A Time Integration Algorithm for Structural 520 Dynamics with Improved Numerical Dissipation: The Generalized-alpha 521 Method" ASME Journal of Applied Mechanics, 60, 371:375, 1993. 522 523 .seealso: TS, TSCreate(), TSSetType(), TSAlphaSetRadius(), TSAlphaSetParams() 524 M*/ 525 #undef __FUNCT__ 526 #define __FUNCT__ "TSCreate_Alpha" 527 PETSC_EXTERN PetscErrorCode TSCreate_Alpha(TS ts) 528 { 529 TS_Alpha *th; 530 PetscErrorCode ierr; 531 532 PetscFunctionBegin; 533 ts->ops->reset = TSReset_Alpha; 534 ts->ops->destroy = TSDestroy_Alpha; 535 ts->ops->view = TSView_Alpha; 536 ts->ops->setup = TSSetUp_Alpha; 537 ts->ops->setfromoptions = TSSetFromOptions_Alpha; 538 ts->ops->step = TSStep_Alpha; 539 ts->ops->evaluatewlte = TSEvaluateWLTE_Alpha; 540 ts->ops->rollback = TSRollBack_Alpha; 541 ts->ops->interpolate = TSInterpolate_Alpha; 542 ts->ops->snesfunction = SNESTSFormFunction_Alpha; 543 ts->ops->snesjacobian = SNESTSFormJacobian_Alpha; 544 545 ierr = PetscNewLog(ts,&th);CHKERRQ(ierr); 546 ts->data = (void*)th; 547 548 th->Alpha_m = 0.5; 549 th->Alpha_f = 0.5; 550 th->Gamma = 0.5; 551 th->order = 2; 552 553 th->adapt = PETSC_FALSE; 554 555 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSAlphaUseAdapt_C",TSAlphaUseAdapt_Alpha);CHKERRQ(ierr); 556 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSAlphaSetRadius_C",TSAlphaSetRadius_Alpha);CHKERRQ(ierr); 557 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSAlphaSetParams_C",TSAlphaSetParams_Alpha);CHKERRQ(ierr); 558 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSAlphaGetParams_C",TSAlphaGetParams_Alpha);CHKERRQ(ierr); 559 PetscFunctionReturn(0); 560 } 561 562 #undef __FUNCT__ 563 #define __FUNCT__ "TSAlphaUseAdapt" 564 /*@ 565 TSAlphaUseAdapt - Use time-step adaptivity with the Alpha method 566 567 Logically Collective on TS 568 569 Input Parameter: 570 + ts - timestepping context 571 - use - flag to use adaptivity 572 573 Options Database: 574 . -ts_alpha_adapt 575 576 Level: intermediate 577 578 .seealso: TSAdapt, TSADAPTBASIC 579 @*/ 580 PetscErrorCode TSAlphaUseAdapt(TS ts,PetscBool use) 581 { 582 PetscErrorCode ierr; 583 584 PetscFunctionBegin; 585 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 586 PetscValidLogicalCollectiveBool(ts,use,2); 587 ierr = PetscTryMethod(ts,"TSAlphaUseAdapt_C",(TS,PetscBool),(ts,use));CHKERRQ(ierr); 588 PetscFunctionReturn(0); 589 } 590 591 #undef __FUNCT__ 592 #define __FUNCT__ "TSAlphaSetRadius" 593 /*@ 594 TSAlphaSetRadius - sets the desired spectral radius of the method 595 (i.e. high-frequency numerical damping) 596 597 Logically Collective on TS 598 599 The algorithmic parameters \alpha_m and \alpha_f of the 600 generalized-\alpha method can be computed in terms of a specified 601 spectral radius \rho in [0,1] for infinite time step in order to 602 control high-frequency numerical damping: 603 \alpha_m = 0.5*(3-\rho)/(1+\rho) 604 \alpha_f = 1/(1+\rho) 605 606 Input Parameter: 607 + ts - timestepping context 608 - radius - the desired spectral radius 609 610 Options Database: 611 . -ts_alpha_radius <radius> 612 613 Level: intermediate 614 615 .seealso: TSAlphaSetParams(), TSAlphaGetParams() 616 @*/ 617 PetscErrorCode TSAlphaSetRadius(TS ts,PetscReal radius) 618 { 619 PetscErrorCode ierr; 620 621 PetscFunctionBegin; 622 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 623 PetscValidLogicalCollectiveReal(ts,radius,2); 624 if (radius < 0 || radius > 1) SETERRQ1(((PetscObject)ts)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Radius %g not in range [0,1]",(double)radius); 625 ierr = PetscTryMethod(ts,"TSAlphaSetRadius_C",(TS,PetscReal),(ts,radius));CHKERRQ(ierr); 626 PetscFunctionReturn(0); 627 } 628 629 #undef __FUNCT__ 630 #define __FUNCT__ "TSAlphaSetParams" 631 /*@ 632 TSAlphaSetParams - sets the algorithmic parameters for TSALPHA 633 634 Logically Collective on TS 635 636 Second-order accuracy can be obtained so long as: 637 \gamma = 0.5 + alpha_m - alpha_f 638 639 Unconditional stability requires: 640 \alpha_m >= \alpha_f >= 0.5 641 642 Backward Euler method is recovered with: 643 \alpha_m = \alpha_f = gamma = 1 644 645 Input Parameter: 646 + ts - timestepping context 647 . \alpha_m - algorithmic paramenter 648 . \alpha_f - algorithmic paramenter 649 - \gamma - algorithmic paramenter 650 651 Options Database: 652 + -ts_alpha_alpha_m <alpha_m> 653 . -ts_alpha_alpha_f <alpha_f> 654 - -ts_alpha_gamma <gamma> 655 656 Note: 657 Use of this function is normally only required to hack TSALPHA to 658 use a modified integration scheme. Users should call 659 TSAlphaSetRadius() to set the desired spectral radius of the methods 660 (i.e. high-frequency damping) in order so select optimal values for 661 these parameters. 662 663 Level: advanced 664 665 .seealso: TSAlphaSetRadius(), TSAlphaGetParams() 666 @*/ 667 PetscErrorCode TSAlphaSetParams(TS ts,PetscReal alpha_m,PetscReal alpha_f,PetscReal gamma) 668 { 669 PetscErrorCode ierr; 670 671 PetscFunctionBegin; 672 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 673 PetscValidLogicalCollectiveReal(ts,alpha_m,2); 674 PetscValidLogicalCollectiveReal(ts,alpha_f,3); 675 PetscValidLogicalCollectiveReal(ts,gamma,4); 676 ierr = PetscTryMethod(ts,"TSAlphaSetParams_C",(TS,PetscReal,PetscReal,PetscReal),(ts,alpha_m,alpha_f,gamma));CHKERRQ(ierr); 677 PetscFunctionReturn(0); 678 } 679 680 #undef __FUNCT__ 681 #define __FUNCT__ "TSAlphaGetParams" 682 /*@ 683 TSAlphaGetParams - gets the algorithmic parameters for TSALPHA 684 685 Not Collective 686 687 Input Parameter: 688 . ts - timestepping context 689 690 Output Parameters: 691 + \alpha_m - algorithmic parameter 692 . \alpha_f - algorithmic parameter 693 - \gamma - algorithmic parameter 694 695 Note: 696 Use of this function is normally only required to hack TSALPHA to 697 use a modified integration scheme. Users should call 698 TSAlphaSetRadius() to set the high-frequency damping (i.e. spectral 699 radius of the method) in order so select optimal values for these 700 parameters. 701 702 Level: advanced 703 704 .seealso: TSAlphaSetRadius(), TSAlphaSetParams() 705 @*/ 706 PetscErrorCode TSAlphaGetParams(TS ts,PetscReal *alpha_m,PetscReal *alpha_f,PetscReal *gamma) 707 { 708 PetscErrorCode ierr; 709 710 PetscFunctionBegin; 711 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 712 if (alpha_m) PetscValidRealPointer(alpha_m,2); 713 if (alpha_f) PetscValidRealPointer(alpha_f,3); 714 if (gamma) PetscValidRealPointer(gamma,4); 715 ierr = PetscUseMethod(ts,"TSAlphaGetParams_C",(TS,PetscReal*,PetscReal*,PetscReal*),(ts,alpha_m,alpha_f,gamma));CHKERRQ(ierr); 716 PetscFunctionReturn(0); 717 } 718