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