xref: /petsc/src/ts/impls/implicit/alpha/alpha1.c (revision 9808bdc15d219b421217c709a9bd042805b02bc0)
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