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|dot}_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 283 #undef __FUNCT__ 284 #define __FUNCT__ "TSRollBack_Alpha" 285 static PetscErrorCode TSRollBack_Alpha(TS ts) 286 { 287 TS_Alpha *th = (TS_Alpha*)ts->data; 288 PetscErrorCode ierr; 289 290 PetscFunctionBegin; 291 ierr = VecCopy(th->X0,ts->vec_sol);CHKERRQ(ierr); 292 PetscFunctionReturn(0); 293 } 294 295 #undef __FUNCT__ 296 #define __FUNCT__ "TSInterpolate_Alpha" 297 static PetscErrorCode TSInterpolate_Alpha(TS ts,PetscReal t,Vec X) 298 { 299 TS_Alpha *th = (TS_Alpha*)ts->data; 300 PetscReal dt = t - ts->ptime; 301 PetscErrorCode ierr; 302 303 PetscFunctionBegin; 304 ierr = VecCopy(ts->vec_sol,X);CHKERRQ(ierr); 305 ierr = VecAXPY(X,th->Gamma*dt,th->V1);CHKERRQ(ierr); 306 ierr = VecAXPY(X,(1-th->Gamma)*dt,th->V0);CHKERRQ(ierr); 307 PetscFunctionReturn(0); 308 } 309 310 #undef __FUNCT__ 311 #define __FUNCT__ "SNESTSFormFunction_Alpha" 312 static PetscErrorCode SNESTSFormFunction_Alpha(PETSC_UNUSED SNES snes,Vec X,Vec F,TS ts) 313 { 314 TS_Alpha *th = (TS_Alpha*)ts->data; 315 PetscReal ta = th->stage_time; 316 Vec Xa = th->Xa, Va = th->Va; 317 PetscErrorCode ierr; 318 319 PetscFunctionBegin; 320 ierr = TSAlpha_StageVecs(ts,X);CHKERRQ(ierr); 321 /* F = Function(ta,Xa,Va) */ 322 ierr = TSComputeIFunction(ts,ta,Xa,Va,F,PETSC_FALSE);CHKERRQ(ierr); 323 ierr = VecScale(F,th->scale_F);CHKERRQ(ierr); 324 PetscFunctionReturn(0); 325 } 326 327 #undef __FUNCT__ 328 #define __FUNCT__ "SNESTSFormJacobian_Alpha" 329 static PetscErrorCode SNESTSFormJacobian_Alpha(PETSC_UNUSED SNES snes,PETSC_UNUSED Vec X,Mat J,Mat P,TS ts) 330 { 331 TS_Alpha *th = (TS_Alpha*)ts->data; 332 PetscReal ta = th->stage_time; 333 Vec Xa = th->Xa, Va = th->Va; 334 PetscReal dVdX = th->shift_V; 335 PetscErrorCode ierr; 336 337 PetscFunctionBegin; 338 /* J,P = Jacobian(ta,Xa,Va) */ 339 ierr = TSComputeIJacobian(ts,ta,Xa,Va,dVdX,J,P,PETSC_FALSE);CHKERRQ(ierr); 340 PetscFunctionReturn(0); 341 } 342 343 #undef __FUNCT__ 344 #define __FUNCT__ "TSReset_Alpha" 345 static PetscErrorCode TSReset_Alpha(TS ts) 346 { 347 TS_Alpha *th = (TS_Alpha*)ts->data; 348 PetscErrorCode ierr; 349 350 PetscFunctionBegin; 351 ierr = VecDestroy(&th->X0);CHKERRQ(ierr); 352 ierr = VecDestroy(&th->Xa);CHKERRQ(ierr); 353 ierr = VecDestroy(&th->X1);CHKERRQ(ierr); 354 ierr = VecDestroy(&th->V0);CHKERRQ(ierr); 355 ierr = VecDestroy(&th->Va);CHKERRQ(ierr); 356 ierr = VecDestroy(&th->V1);CHKERRQ(ierr); 357 ierr = VecDestroy(&th->vec_sol_prev);CHKERRQ(ierr); 358 ierr = VecDestroy(&th->vec_work);CHKERRQ(ierr); 359 PetscFunctionReturn(0); 360 } 361 362 #undef __FUNCT__ 363 #define __FUNCT__ "TSDestroy_Alpha" 364 static PetscErrorCode TSDestroy_Alpha(TS ts) 365 { 366 PetscErrorCode ierr; 367 368 PetscFunctionBegin; 369 ierr = TSReset_Alpha(ts);CHKERRQ(ierr); 370 ierr = PetscFree(ts->data);CHKERRQ(ierr); 371 372 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSAlphaUseAdapt_C",NULL);CHKERRQ(ierr); 373 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSAlphaSetRadius_C",NULL);CHKERRQ(ierr); 374 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSAlphaSetParams_C",NULL);CHKERRQ(ierr); 375 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSAlphaGetParams_C",NULL);CHKERRQ(ierr); 376 PetscFunctionReturn(0); 377 } 378 379 #undef __FUNCT__ 380 #define __FUNCT__ "TSSetUp_Alpha" 381 static PetscErrorCode TSSetUp_Alpha(TS ts) 382 { 383 TS_Alpha *th = (TS_Alpha*)ts->data; 384 PetscErrorCode ierr; 385 386 PetscFunctionBegin; 387 ierr = VecDuplicate(ts->vec_sol,&th->X0);CHKERRQ(ierr); 388 ierr = VecDuplicate(ts->vec_sol,&th->Xa);CHKERRQ(ierr); 389 ierr = VecDuplicate(ts->vec_sol,&th->X1);CHKERRQ(ierr); 390 ierr = VecDuplicate(ts->vec_sol,&th->V0);CHKERRQ(ierr); 391 ierr = VecDuplicate(ts->vec_sol,&th->Va);CHKERRQ(ierr); 392 ierr = VecDuplicate(ts->vec_sol,&th->V1);CHKERRQ(ierr); 393 if (!th->adapt) { 394 ierr = TSAdaptDestroy(&ts->adapt);CHKERRQ(ierr); 395 ierr = TSGetAdapt(ts,&ts->adapt);CHKERRQ(ierr); 396 ierr = TSAdaptSetType(ts->adapt,TSADAPTNONE);CHKERRQ(ierr); 397 } else { 398 ierr = TSGetAdapt(ts,&ts->adapt);CHKERRQ(ierr); 399 ierr = VecDuplicate(ts->vec_sol,&th->vec_sol_prev);CHKERRQ(ierr); 400 ierr = VecDuplicate(ts->vec_sol,&th->vec_work);CHKERRQ(ierr); 401 if (ts->exact_final_time == TS_EXACTFINALTIME_UNSPECIFIED) 402 ts->exact_final_time = TS_EXACTFINALTIME_MATCHSTEP; 403 } 404 ierr = TSGetSNES(ts,&ts->snes);CHKERRQ(ierr); 405 PetscFunctionReturn(0); 406 } 407 408 #undef __FUNCT__ 409 #define __FUNCT__ "TSSetFromOptions_Alpha" 410 static PetscErrorCode TSSetFromOptions_Alpha(PetscOptionItems *PetscOptionsObject,TS ts) 411 { 412 TS_Alpha *th = (TS_Alpha*)ts->data; 413 PetscErrorCode ierr; 414 415 PetscFunctionBegin; 416 ierr = PetscOptionsHead(PetscOptionsObject,"Generalized-Alpha ODE solver options");CHKERRQ(ierr); 417 { 418 PetscBool flg; 419 PetscReal radius = 1; 420 PetscBool adapt = th->adapt; 421 ierr = PetscOptionsReal("-ts_alpha_radius","Spectral radius (high-frequency dissipation)","TSAlphaSetRadius",radius,&radius,&flg);CHKERRQ(ierr); 422 if (flg) {ierr = TSAlphaSetRadius(ts,radius);CHKERRQ(ierr);} 423 ierr = PetscOptionsReal("-ts_alpha_alpha_m","Algoritmic parameter alpha_m","TSAlphaSetParams",th->Alpha_m,&th->Alpha_m,NULL);CHKERRQ(ierr); 424 ierr = PetscOptionsReal("-ts_alpha_alpha_f","Algoritmic parameter alpha_f","TSAlphaSetParams",th->Alpha_f,&th->Alpha_f,NULL);CHKERRQ(ierr); 425 ierr = PetscOptionsReal("-ts_alpha_gamma","Algoritmic parameter gamma","TSAlphaSetParams",th->Gamma,&th->Gamma,NULL);CHKERRQ(ierr); 426 ierr = TSAlphaSetParams(ts,th->Alpha_m,th->Alpha_f,th->Gamma);CHKERRQ(ierr); 427 ierr = PetscOptionsBool("-ts_alpha_adapt","Use time-step adaptivity with the Alpha method","TSAlpha2UseAdapt",adapt,&adapt,&flg);CHKERRQ(ierr); 428 if (flg) {ierr = TSAlphaUseAdapt(ts,adapt);CHKERRQ(ierr);} 429 } 430 ierr = PetscOptionsTail();CHKERRQ(ierr); 431 PetscFunctionReturn(0); 432 } 433 434 #undef __FUNCT__ 435 #define __FUNCT__ "TSView_Alpha" 436 static PetscErrorCode TSView_Alpha(TS ts,PetscViewer viewer) 437 { 438 TS_Alpha *th = (TS_Alpha*)ts->data; 439 PetscBool ascii; 440 PetscErrorCode ierr; 441 442 PetscFunctionBegin; 443 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&ascii);CHKERRQ(ierr); 444 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);} 445 if (ts->snes) {ierr = SNESView(ts->snes,viewer);CHKERRQ(ierr);} 446 PetscFunctionReturn(0); 447 } 448 449 #undef __FUNCT__ 450 #define __FUNCT__ "TSAlphaUseAdapt_Alpha" 451 static PetscErrorCode TSAlphaUseAdapt_Alpha(TS ts,PetscBool use) 452 { 453 TS_Alpha *th = (TS_Alpha*)ts->data; 454 455 PetscFunctionBegin; 456 if (use == th->adapt) PetscFunctionReturn(0); 457 if (ts->setupcalled) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ORDER,"Cannot change adaptivity after TSSetUp()"); 458 th->adapt = use; 459 PetscFunctionReturn(0); 460 } 461 462 #undef __FUNCT__ 463 #define __FUNCT__ "TSAlphaSetRadius_Alpha" 464 static PetscErrorCode TSAlphaSetRadius_Alpha(TS ts,PetscReal radius) 465 { 466 PetscReal alpha_m,alpha_f,gamma; 467 PetscErrorCode ierr; 468 469 PetscFunctionBegin; 470 if (radius < 0 || radius > 1) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Radius %g not in range [0,1]",(double)radius); 471 alpha_m = (PetscReal)0.5*(3-radius)/(1+radius); 472 alpha_f = 1/(1+radius); 473 gamma = (PetscReal)0.5 + alpha_m - alpha_f; 474 ierr = TSAlphaSetParams(ts,alpha_m,alpha_f,gamma);CHKERRQ(ierr); 475 PetscFunctionReturn(0); 476 } 477 478 #undef __FUNCT__ 479 #define __FUNCT__ "TSAlphaSetParams_Alpha" 480 static PetscErrorCode TSAlphaSetParams_Alpha(TS ts,PetscReal alpha_m,PetscReal alpha_f,PetscReal gamma) 481 { 482 TS_Alpha *th = (TS_Alpha*)ts->data; 483 PetscReal tol = 100*PETSC_MACHINE_EPSILON; 484 PetscReal res = ((PetscReal)0.5 + alpha_m - alpha_f) - gamma; 485 486 PetscFunctionBegin; 487 th->Alpha_m = alpha_m; 488 th->Alpha_f = alpha_f; 489 th->Gamma = gamma; 490 th->order = (PetscAbsReal(res) < tol) ? 2 : 1; 491 PetscFunctionReturn(0); 492 } 493 494 #undef __FUNCT__ 495 #define __FUNCT__ "TSAlphaGetParams_Alpha" 496 static PetscErrorCode TSAlphaGetParams_Alpha(TS ts,PetscReal *alpha_m,PetscReal *alpha_f,PetscReal *gamma) 497 { 498 TS_Alpha *th = (TS_Alpha*)ts->data; 499 500 PetscFunctionBegin; 501 if (alpha_m) *alpha_m = th->Alpha_m; 502 if (alpha_f) *alpha_f = th->Alpha_f; 503 if (gamma) *gamma = th->Gamma; 504 PetscFunctionReturn(0); 505 } 506 507 /*MC 508 TSALPHA - ODE/DAE solver using the implicit Generalized-Alpha method 509 for first-order systems 510 511 Level: beginner 512 513 References: 514 K.E. Jansen, C.H. Whiting, G.M. Hulber, "A generalized-alpha 515 method for integrating the filtered Navier-Stokes equations with a 516 stabilized finite element method", Computer Methods in Applied 517 Mechanics and Engineering, 190, 305-319, 2000. 518 DOI: 10.1016/S0045-7825(00)00203-6. 519 520 J. Chung, G.M.Hubert. "A Time Integration Algorithm for Structural 521 Dynamics with Improved Numerical Dissipation: The Generalized-alpha 522 Method" ASME Journal of Applied Mechanics, 60, 371:375, 1993. 523 524 .seealso: TS, TSCreate(), TSSetType(), TSAlphaSetRadius(), TSAlphaSetParams() 525 M*/ 526 #undef __FUNCT__ 527 #define __FUNCT__ "TSCreate_Alpha" 528 PETSC_EXTERN PetscErrorCode TSCreate_Alpha(TS ts) 529 { 530 TS_Alpha *th; 531 PetscErrorCode ierr; 532 533 PetscFunctionBegin; 534 ts->ops->reset = TSReset_Alpha; 535 ts->ops->destroy = TSDestroy_Alpha; 536 ts->ops->view = TSView_Alpha; 537 ts->ops->setup = TSSetUp_Alpha; 538 ts->ops->setfromoptions = TSSetFromOptions_Alpha; 539 ts->ops->step = TSStep_Alpha; 540 ts->ops->evaluatewlte = TSEvaluateWLTE_Alpha; 541 ts->ops->rollback = TSRollBack_Alpha; 542 ts->ops->interpolate = TSInterpolate_Alpha; 543 ts->ops->snesfunction = SNESTSFormFunction_Alpha; 544 ts->ops->snesjacobian = SNESTSFormJacobian_Alpha; 545 546 ierr = PetscNewLog(ts,&th);CHKERRQ(ierr); 547 ts->data = (void*)th; 548 549 th->Alpha_m = 0.5; 550 th->Alpha_f = 0.5; 551 th->Gamma = 0.5; 552 th->order = 2; 553 554 th->adapt = PETSC_FALSE; 555 556 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSAlphaUseAdapt_C",TSAlphaUseAdapt_Alpha);CHKERRQ(ierr); 557 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSAlphaSetRadius_C",TSAlphaSetRadius_Alpha);CHKERRQ(ierr); 558 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSAlphaSetParams_C",TSAlphaSetParams_Alpha);CHKERRQ(ierr); 559 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSAlphaGetParams_C",TSAlphaGetParams_Alpha);CHKERRQ(ierr); 560 PetscFunctionReturn(0); 561 } 562 563 #undef __FUNCT__ 564 #define __FUNCT__ "TSAlphaUseAdapt" 565 /*@ 566 TSAlphaUseAdapt - Use time-step adaptivity with the Alpha method 567 568 Logically Collective on TS 569 570 Input Parameter: 571 + ts - timestepping context 572 - use - flag to use adaptivity 573 574 Options Database: 575 . -ts_alpha_adapt 576 577 Level: intermediate 578 579 .seealso: TSAdapt, TSADAPTBASIC 580 @*/ 581 PetscErrorCode TSAlphaUseAdapt(TS ts,PetscBool use) 582 { 583 PetscErrorCode ierr; 584 585 PetscFunctionBegin; 586 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 587 PetscValidLogicalCollectiveBool(ts,use,2); 588 ierr = PetscTryMethod(ts,"TSAlphaUseAdapt_C",(TS,PetscBool),(ts,use));CHKERRQ(ierr); 589 PetscFunctionReturn(0); 590 } 591 592 #undef __FUNCT__ 593 #define __FUNCT__ "TSAlphaSetRadius" 594 /*@ 595 TSAlphaSetRadius - sets the desired spectral radius of the method 596 (i.e. high-frequency numerical damping) 597 598 Logically Collective on TS 599 600 The algorithmic parameters \alpha_m and \alpha_f of the 601 generalized-\alpha method can be computed in terms of a specified 602 spectral radius \rho in [0,1] for infinite time step in order to 603 control high-frequency numerical damping: 604 \alpha_m = 0.5*(3-\rho)/(1+\rho) 605 \alpha_f = 1/(1+\rho) 606 607 Input Parameter: 608 + ts - timestepping context 609 - radius - the desired spectral radius 610 611 Options Database: 612 . -ts_alpha_radius <radius> 613 614 Level: intermediate 615 616 .seealso: TSAlphaSetParams(), TSAlphaGetParams() 617 @*/ 618 PetscErrorCode TSAlphaSetRadius(TS ts,PetscReal radius) 619 { 620 PetscErrorCode ierr; 621 622 PetscFunctionBegin; 623 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 624 PetscValidLogicalCollectiveReal(ts,radius,2); 625 if (radius < 0 || radius > 1) SETERRQ1(((PetscObject)ts)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Radius %g not in range [0,1]",(double)radius); 626 ierr = PetscTryMethod(ts,"TSAlphaSetRadius_C",(TS,PetscReal),(ts,radius));CHKERRQ(ierr); 627 PetscFunctionReturn(0); 628 } 629 630 #undef __FUNCT__ 631 #define __FUNCT__ "TSAlphaSetParams" 632 /*@ 633 TSAlphaSetParams - sets the algorithmic parameters for TSALPHA 634 635 Logically Collective on TS 636 637 Second-order accuracy can be obtained so long as: 638 \gamma = 0.5 + alpha_m - alpha_f 639 640 Unconditional stability requires: 641 \alpha_m >= \alpha_f >= 0.5 642 643 Backward Euler method is recovered with: 644 \alpha_m = \alpha_f = gamma = 1 645 646 647 Input Parameter: 648 + ts - timestepping context 649 . \alpha_m - algorithmic paramenter 650 . \alpha_f - algorithmic paramenter 651 - \gamma - algorithmic paramenter 652 653 Options Database: 654 + -ts_alpha_alpha_m <alpha_m> 655 . -ts_alpha_alpha_f <alpha_f> 656 - -ts_alpha_gamma <gamma> 657 658 Note: 659 Use of this function is normally only required to hack TSALPHA to 660 use a modified integration scheme. Users should call 661 TSAlphaSetRadius() to set the desired spectral radius of the methods 662 (i.e. high-frequency damping) in order so select optimal values for 663 these parameters. 664 665 Level: advanced 666 667 .seealso: TSAlphaSetRadius(), TSAlphaGetParams() 668 @*/ 669 PetscErrorCode TSAlphaSetParams(TS ts,PetscReal alpha_m,PetscReal alpha_f,PetscReal gamma) 670 { 671 PetscErrorCode ierr; 672 673 PetscFunctionBegin; 674 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 675 PetscValidLogicalCollectiveReal(ts,alpha_m,2); 676 PetscValidLogicalCollectiveReal(ts,alpha_f,3); 677 PetscValidLogicalCollectiveReal(ts,gamma,4); 678 ierr = PetscTryMethod(ts,"TSAlphaSetParams_C",(TS,PetscReal,PetscReal,PetscReal),(ts,alpha_m,alpha_f,gamma));CHKERRQ(ierr); 679 PetscFunctionReturn(0); 680 } 681 682 #undef __FUNCT__ 683 #define __FUNCT__ "TSAlphaGetParams" 684 /*@ 685 TSAlphaGetParams - gets the algorithmic parameters for TSALPHA 686 687 Not Collective 688 689 Input Parameter: 690 . ts - timestepping context 691 692 Output Parameters: 693 + \alpha_m - algorithmic parameter 694 . \alpha_f - algorithmic parameter 695 - \gamma - algorithmic parameter 696 697 Note: 698 Use of this function is normally only required to hack TSALPHA to 699 use a modified integration scheme. Users should call 700 TSAlphaSetRadius() to set the high-frequency damping (i.e. spectral 701 radius of the method) in order so select optimal values for these 702 parameters. 703 704 Level: advanced 705 706 .seealso: TSAlphaSetRadius(), TSAlphaSetParams() 707 @*/ 708 PetscErrorCode TSAlphaGetParams(TS ts,PetscReal *alpha_m,PetscReal *alpha_f,PetscReal *gamma) 709 { 710 PetscErrorCode ierr; 711 712 PetscFunctionBegin; 713 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 714 if (alpha_m) PetscValidRealPointer(alpha_m,2); 715 if (alpha_f) PetscValidRealPointer(alpha_f,3); 716 if (gamma) PetscValidRealPointer(gamma,4); 717 ierr = PetscUseMethod(ts,"TSAlphaGetParams_C",(TS,PetscReal*,PetscReal*,PetscReal*),(ts,alpha_m,alpha_f,gamma));CHKERRQ(ierr); 718 PetscFunctionReturn(0); 719 } 720