xref: /petsc/src/ts/impls/implicit/alpha/alpha2.c (revision 4e8208cbcbc709572b8abe32f33c78b69c819375)
1818efac9SLisandro Dalcin /*
2818efac9SLisandro Dalcin   Code for timestepping with implicit generalized-\alpha method
3818efac9SLisandro Dalcin   for second order systems.
4818efac9SLisandro Dalcin */
5818efac9SLisandro Dalcin #include <petsc/private/tsimpl.h> /*I   "petscts.h"   I*/
6818efac9SLisandro Dalcin 
7818efac9SLisandro Dalcin static PetscBool  cited      = PETSC_FALSE;
89371c9d4SSatish Balay static const char citation[] = "@article{Chung1993,\n"
9818efac9SLisandro Dalcin                                "  title   = {A Time Integration Algorithm for Structural Dynamics with Improved Numerical Dissipation: The Generalized-$\\alpha$ Method},\n"
10818efac9SLisandro Dalcin                                "  author  = {J. Chung, G. M. Hubert},\n"
11818efac9SLisandro Dalcin                                "  journal = {ASME Journal of Applied Mechanics},\n"
12818efac9SLisandro Dalcin                                "  volume  = {60},\n"
13818efac9SLisandro Dalcin                                "  number  = {2},\n"
14818efac9SLisandro Dalcin                                "  pages   = {371--375},\n"
15818efac9SLisandro Dalcin                                "  year    = {1993},\n"
16818efac9SLisandro Dalcin                                "  issn    = {0021-8936},\n"
17818efac9SLisandro Dalcin                                "  doi     = {http://dx.doi.org/10.1115/1.2900803}\n}\n";
18818efac9SLisandro Dalcin 
19818efac9SLisandro Dalcin typedef struct {
20818efac9SLisandro Dalcin   PetscReal stage_time;
21818efac9SLisandro Dalcin   PetscReal shift_V;
22818efac9SLisandro Dalcin   PetscReal shift_A;
23818efac9SLisandro Dalcin   PetscReal scale_F;
24818efac9SLisandro Dalcin   Vec       X0, Xa, X1;
25818efac9SLisandro Dalcin   Vec       V0, Va, V1;
26818efac9SLisandro Dalcin   Vec       A0, Aa, A1;
27818efac9SLisandro Dalcin 
28818efac9SLisandro Dalcin   Vec vec_dot;
29818efac9SLisandro Dalcin 
30818efac9SLisandro Dalcin   PetscReal Alpha_m;
31818efac9SLisandro Dalcin   PetscReal Alpha_f;
32818efac9SLisandro Dalcin   PetscReal Gamma;
33818efac9SLisandro Dalcin   PetscReal Beta;
34818efac9SLisandro Dalcin   PetscInt  order;
35818efac9SLisandro Dalcin 
36818efac9SLisandro Dalcin   Vec vec_sol_prev;
37818efac9SLisandro Dalcin   Vec vec_dot_prev;
38818efac9SLisandro Dalcin   Vec vec_lte_work[2];
39818efac9SLisandro Dalcin 
40818efac9SLisandro Dalcin   TSStepStatus status;
41220f924aSDavid Kamensky 
428434afd1SBarry Smith   TSAlpha2PredictorFn *predictor;
43220f924aSDavid Kamensky   void                *predictor_ctx;
44818efac9SLisandro Dalcin } TS_Alpha;
45818efac9SLisandro Dalcin 
46220f924aSDavid Kamensky /*@C
47220f924aSDavid Kamensky   TSAlpha2SetPredictor - sets the callback for computing a predictor (i.e., initial guess
48220f924aSDavid Kamensky   for the nonlinear solver).
49220f924aSDavid Kamensky 
50220f924aSDavid Kamensky   Input Parameters:
51220f924aSDavid Kamensky + ts        - timestepping context
52220f924aSDavid Kamensky . predictor - callback to set the predictor in each step
53220f924aSDavid Kamensky - ctx       - the application context, which may be set to `NULL` if not used
54220f924aSDavid Kamensky 
55220f924aSDavid Kamensky   Level: intermediate
56220f924aSDavid Kamensky 
57220f924aSDavid Kamensky   Notes:
58220f924aSDavid Kamensky 
59220f924aSDavid Kamensky   If this function is never called, a same-state-vector predictor will be used, i.e.,
60220f924aSDavid Kamensky   the initial guess will be the converged solution from the previous time step, without regard
61220f924aSDavid Kamensky   for the previous velocity or acceleration.
62220f924aSDavid Kamensky 
638434afd1SBarry Smith .seealso: [](ch_ts), `TS`, `TSALPHA2`, `TSAlpha2PredictorFn`
64220f924aSDavid Kamensky @*/
TSAlpha2SetPredictor(TS ts,TSAlpha2PredictorFn * predictor,PetscCtx ctx)65*2a8381b2SBarry Smith PetscErrorCode TSAlpha2SetPredictor(TS ts, TSAlpha2PredictorFn *predictor, PetscCtx ctx)
66220f924aSDavid Kamensky {
67f4f49eeaSPierre Jolivet   TS_Alpha *th = (TS_Alpha *)ts->data;
68220f924aSDavid Kamensky 
69220f924aSDavid Kamensky   PetscFunctionBegin;
70220f924aSDavid Kamensky   th->predictor     = predictor;
71220f924aSDavid Kamensky   th->predictor_ctx = ctx;
72220f924aSDavid Kamensky   PetscFunctionReturn(PETSC_SUCCESS);
73220f924aSDavid Kamensky }
74220f924aSDavid Kamensky 
TSAlpha_ApplyPredictor(TS ts,Vec X1)75220f924aSDavid Kamensky static PetscErrorCode TSAlpha_ApplyPredictor(TS ts, Vec X1)
76220f924aSDavid Kamensky {
77220f924aSDavid Kamensky   /* Apply a custom predictor if set, or default to same-displacement. */
78f4f49eeaSPierre Jolivet   TS_Alpha *th = (TS_Alpha *)ts->data;
79220f924aSDavid Kamensky 
80220f924aSDavid Kamensky   PetscFunctionBegin;
81220f924aSDavid Kamensky   if (th->predictor) PetscCall(th->predictor(ts, th->X0, th->V0, th->A0, X1, th->predictor_ctx));
82220f924aSDavid Kamensky   else PetscCall(VecCopy(th->X0, X1));
83220f924aSDavid Kamensky   PetscFunctionReturn(PETSC_SUCCESS);
84220f924aSDavid Kamensky }
85220f924aSDavid Kamensky 
TSAlpha_StageTime(TS ts)86d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSAlpha_StageTime(TS ts)
87d71ae5a4SJacob Faibussowitsch {
88818efac9SLisandro Dalcin   TS_Alpha *th      = (TS_Alpha *)ts->data;
89818efac9SLisandro Dalcin   PetscReal t       = ts->ptime;
90818efac9SLisandro Dalcin   PetscReal dt      = ts->time_step;
91818efac9SLisandro Dalcin   PetscReal Alpha_m = th->Alpha_m;
92818efac9SLisandro Dalcin   PetscReal Alpha_f = th->Alpha_f;
93818efac9SLisandro Dalcin   PetscReal Gamma   = th->Gamma;
94818efac9SLisandro Dalcin   PetscReal Beta    = th->Beta;
95818efac9SLisandro Dalcin 
96818efac9SLisandro Dalcin   PetscFunctionBegin;
97818efac9SLisandro Dalcin   th->stage_time = t + Alpha_f * dt;
98818efac9SLisandro Dalcin   th->shift_V    = Gamma / (dt * Beta);
99818efac9SLisandro Dalcin   th->shift_A    = Alpha_m / (Alpha_f * dt * dt * Beta);
100818efac9SLisandro Dalcin   th->scale_F    = 1 / Alpha_f;
1013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
102818efac9SLisandro Dalcin }
103818efac9SLisandro Dalcin 
TSAlpha_StageVecs(TS ts,Vec X)104d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSAlpha_StageVecs(TS ts, Vec X)
105d71ae5a4SJacob Faibussowitsch {
106818efac9SLisandro Dalcin   TS_Alpha *th = (TS_Alpha *)ts->data;
107818efac9SLisandro Dalcin   Vec       X1 = X, V1 = th->V1, A1 = th->A1;
108818efac9SLisandro Dalcin   Vec       Xa = th->Xa, Va = th->Va, Aa = th->Aa;
109818efac9SLisandro Dalcin   Vec       X0 = th->X0, V0 = th->V0, A0 = th->A0;
110818efac9SLisandro Dalcin   PetscReal dt      = ts->time_step;
111818efac9SLisandro Dalcin   PetscReal Alpha_m = th->Alpha_m;
112818efac9SLisandro Dalcin   PetscReal Alpha_f = th->Alpha_f;
113818efac9SLisandro Dalcin   PetscReal Gamma   = th->Gamma;
114818efac9SLisandro Dalcin   PetscReal Beta    = th->Beta;
115818efac9SLisandro Dalcin 
116818efac9SLisandro Dalcin   PetscFunctionBegin;
117818efac9SLisandro Dalcin   /* A1 = ... */
1189566063dSJacob Faibussowitsch   PetscCall(VecWAXPY(A1, -1.0, X0, X1));
1199566063dSJacob Faibussowitsch   PetscCall(VecAXPY(A1, -dt, V0));
1209566063dSJacob Faibussowitsch   PetscCall(VecAXPBY(A1, -(1 - 2 * Beta) / (2 * Beta), 1 / (dt * dt * Beta), A0));
121818efac9SLisandro Dalcin   /* V1 = ... */
1229566063dSJacob Faibussowitsch   PetscCall(VecWAXPY(V1, (1.0 - Gamma) / Gamma, A0, A1));
1239566063dSJacob Faibussowitsch   PetscCall(VecAYPX(V1, dt * Gamma, V0));
124818efac9SLisandro Dalcin   /* Xa = X0 + Alpha_f*(X1-X0) */
1259566063dSJacob Faibussowitsch   PetscCall(VecWAXPY(Xa, -1.0, X0, X1));
1269566063dSJacob Faibussowitsch   PetscCall(VecAYPX(Xa, Alpha_f, X0));
127818efac9SLisandro Dalcin   /* Va = V0 + Alpha_f*(V1-V0) */
1289566063dSJacob Faibussowitsch   PetscCall(VecWAXPY(Va, -1.0, V0, V1));
1299566063dSJacob Faibussowitsch   PetscCall(VecAYPX(Va, Alpha_f, V0));
130818efac9SLisandro Dalcin   /* Aa = A0 + Alpha_m*(A1-A0) */
1319566063dSJacob Faibussowitsch   PetscCall(VecWAXPY(Aa, -1.0, A0, A1));
1329566063dSJacob Faibussowitsch   PetscCall(VecAYPX(Aa, Alpha_m, A0));
1333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
134818efac9SLisandro Dalcin }
135818efac9SLisandro Dalcin 
TSAlpha_SNESSolve(TS ts,Vec b,Vec x)136d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSAlpha_SNESSolve(TS ts, Vec b, Vec x)
137d71ae5a4SJacob Faibussowitsch {
138818efac9SLisandro Dalcin   PetscInt nits, lits;
139818efac9SLisandro Dalcin 
140818efac9SLisandro Dalcin   PetscFunctionBegin;
1419566063dSJacob Faibussowitsch   PetscCall(SNESSolve(ts->snes, b, x));
1429566063dSJacob Faibussowitsch   PetscCall(SNESGetIterationNumber(ts->snes, &nits));
1439566063dSJacob Faibussowitsch   PetscCall(SNESGetLinearSolveIterations(ts->snes, &lits));
1449371c9d4SSatish Balay   ts->snes_its += nits;
1459371c9d4SSatish Balay   ts->ksp_its += lits;
1463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
147818efac9SLisandro Dalcin }
148818efac9SLisandro Dalcin 
149818efac9SLisandro Dalcin /*
150818efac9SLisandro Dalcin   Compute a consistent initial state for the generalized-alpha method.
151070f04f8SDavid Kamensky   - Solve two successive first-order-accurate steps with halved time step.
152818efac9SLisandro Dalcin   - Compute the initial second time derivative using backward differences.
153818efac9SLisandro Dalcin   - If using adaptivity, estimate the LTE of the initial step.
154818efac9SLisandro Dalcin */
TSAlpha_Restart(TS ts,PetscBool * initok)155d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSAlpha_Restart(TS ts, PetscBool *initok)
156d71ae5a4SJacob Faibussowitsch {
157818efac9SLisandro Dalcin   TS_Alpha *th = (TS_Alpha *)ts->data;
158818efac9SLisandro Dalcin   PetscReal time_step;
159818efac9SLisandro Dalcin   PetscReal alpha_m, alpha_f, gamma, beta;
160818efac9SLisandro Dalcin   Vec       X0 = ts->vec_sol, X1, X2 = th->X1;
161818efac9SLisandro Dalcin   Vec       V0 = ts->vec_dot, V1, V2 = th->V1;
162818efac9SLisandro Dalcin   PetscBool stageok;
163818efac9SLisandro Dalcin 
164818efac9SLisandro Dalcin   PetscFunctionBegin;
1659566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(X0, &X1));
1669566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(V0, &V1));
167818efac9SLisandro Dalcin 
168070f04f8SDavid Kamensky   /* Setup first-order-accurate method with halved time step */
1699566063dSJacob Faibussowitsch   PetscCall(TSAlpha2GetParams(ts, &alpha_m, &alpha_f, &gamma, &beta));
1709566063dSJacob Faibussowitsch   PetscCall(TSAlpha2SetParams(ts, 1, 1, 1, 0.5));
1719566063dSJacob Faibussowitsch   PetscCall(TSGetTimeStep(ts, &time_step));
172818efac9SLisandro Dalcin   ts->time_step = time_step / 2;
1739566063dSJacob Faibussowitsch   PetscCall(TSAlpha_StageTime(ts));
174818efac9SLisandro Dalcin   th->stage_time = ts->ptime;
1759566063dSJacob Faibussowitsch   PetscCall(VecZeroEntries(th->A0));
176818efac9SLisandro Dalcin 
177070f04f8SDavid Kamensky   /* First half step, (t0,X0,V0) -> (t1,X1,V1) */
178818efac9SLisandro Dalcin   th->stage_time += ts->time_step;
1799566063dSJacob Faibussowitsch   PetscCall(VecCopy(X0, th->X0));
1809566063dSJacob Faibussowitsch   PetscCall(VecCopy(V0, th->V0));
1819566063dSJacob Faibussowitsch   PetscCall(TSPreStage(ts, th->stage_time));
182220f924aSDavid Kamensky   PetscCall(TSAlpha_ApplyPredictor(ts, X1));
1839566063dSJacob Faibussowitsch   PetscCall(TSAlpha_SNESSolve(ts, NULL, X1));
1849566063dSJacob Faibussowitsch   PetscCall(VecCopy(th->V1, V1));
1859566063dSJacob Faibussowitsch   PetscCall(TSPostStage(ts, th->stage_time, 0, &X1));
1869566063dSJacob Faibussowitsch   PetscCall(TSAdaptCheckStage(ts->adapt, ts, th->stage_time, X1, &stageok));
187818efac9SLisandro Dalcin   if (!stageok) goto finally;
188818efac9SLisandro Dalcin 
189070f04f8SDavid Kamensky   /* Second half step, (t1,X1,V1) -> (t2,X2,V2) */
190818efac9SLisandro Dalcin   th->stage_time += ts->time_step;
1919566063dSJacob Faibussowitsch   PetscCall(VecCopy(X1, th->X0));
1929566063dSJacob Faibussowitsch   PetscCall(VecCopy(V1, th->V0));
1939566063dSJacob Faibussowitsch   PetscCall(TSPreStage(ts, th->stage_time));
194220f924aSDavid Kamensky   PetscCall(TSAlpha_ApplyPredictor(ts, X2));
1959566063dSJacob Faibussowitsch   PetscCall(TSAlpha_SNESSolve(ts, NULL, X2));
1969566063dSJacob Faibussowitsch   PetscCall(VecCopy(th->V1, V2));
1979566063dSJacob Faibussowitsch   PetscCall(TSPostStage(ts, th->stage_time, 0, &X2));
198070f04f8SDavid Kamensky   PetscCall(TSAdaptCheckStage(ts->adapt, ts, th->stage_time, X2, &stageok));
199818efac9SLisandro Dalcin   if (!stageok) goto finally;
200818efac9SLisandro Dalcin 
201818efac9SLisandro Dalcin   /* Compute A0 ~ dV/dt at t0 with backward differences */
2029566063dSJacob Faibussowitsch   PetscCall(VecZeroEntries(th->A0));
203070f04f8SDavid Kamensky   PetscCall(VecAXPY(th->A0, -3 / time_step, V0));
204070f04f8SDavid Kamensky   PetscCall(VecAXPY(th->A0, +4 / time_step, V1));
205070f04f8SDavid Kamensky   PetscCall(VecAXPY(th->A0, -1 / time_step, V2));
206818efac9SLisandro Dalcin 
207818efac9SLisandro Dalcin   /* Rough, lower-order estimate LTE of the initial step */
2082ffb9264SLisandro Dalcin   if (th->vec_lte_work[0]) {
2099566063dSJacob Faibussowitsch     PetscCall(VecZeroEntries(th->vec_lte_work[0]));
2109566063dSJacob Faibussowitsch     PetscCall(VecAXPY(th->vec_lte_work[0], +2, X2));
2119566063dSJacob Faibussowitsch     PetscCall(VecAXPY(th->vec_lte_work[0], -4, X1));
2129566063dSJacob Faibussowitsch     PetscCall(VecAXPY(th->vec_lte_work[0], +2, X0));
213818efac9SLisandro Dalcin   }
2142ffb9264SLisandro Dalcin   if (th->vec_lte_work[1]) {
2159566063dSJacob Faibussowitsch     PetscCall(VecZeroEntries(th->vec_lte_work[1]));
2169566063dSJacob Faibussowitsch     PetscCall(VecAXPY(th->vec_lte_work[1], +2, V2));
2179566063dSJacob Faibussowitsch     PetscCall(VecAXPY(th->vec_lte_work[1], -4, V1));
2189566063dSJacob Faibussowitsch     PetscCall(VecAXPY(th->vec_lte_work[1], +2, V0));
219818efac9SLisandro Dalcin   }
220818efac9SLisandro Dalcin 
221818efac9SLisandro Dalcin finally:
222123b1737SDavid Kamensky   /* Revert TSAlpha to the initial state (t0,X0,V0), but retain
223123b1737SDavid Kamensky      potential time step reduction by factor after failed solve. */
224818efac9SLisandro Dalcin   if (initok) *initok = stageok;
225123b1737SDavid Kamensky   PetscCall(TSSetTimeStep(ts, 2 * ts->time_step));
2269566063dSJacob Faibussowitsch   PetscCall(TSAlpha2SetParams(ts, alpha_m, alpha_f, gamma, beta));
2279566063dSJacob Faibussowitsch   PetscCall(VecCopy(ts->vec_sol, th->X0));
2289566063dSJacob Faibussowitsch   PetscCall(VecCopy(ts->vec_dot, th->V0));
229818efac9SLisandro Dalcin 
2309566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&X1));
2319566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&V1));
2323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
233818efac9SLisandro Dalcin }
234818efac9SLisandro Dalcin 
TSStep_Alpha(TS ts)235d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSStep_Alpha(TS ts)
236d71ae5a4SJacob Faibussowitsch {
237818efac9SLisandro Dalcin   TS_Alpha *th         = (TS_Alpha *)ts->data;
238818efac9SLisandro Dalcin   PetscInt  rejections = 0;
239818efac9SLisandro Dalcin   PetscBool stageok, accept = PETSC_TRUE;
240818efac9SLisandro Dalcin   PetscReal next_time_step = ts->time_step;
241818efac9SLisandro Dalcin 
242818efac9SLisandro Dalcin   PetscFunctionBegin;
2439566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(citation, &cited));
244818efac9SLisandro Dalcin 
245818efac9SLisandro Dalcin   if (!ts->steprollback) {
2469566063dSJacob Faibussowitsch     if (th->vec_sol_prev) PetscCall(VecCopy(th->X0, th->vec_sol_prev));
2479566063dSJacob Faibussowitsch     if (th->vec_dot_prev) PetscCall(VecCopy(th->V0, th->vec_dot_prev));
2489566063dSJacob Faibussowitsch     PetscCall(VecCopy(ts->vec_sol, th->X0));
2499566063dSJacob Faibussowitsch     PetscCall(VecCopy(ts->vec_dot, th->V0));
2509566063dSJacob Faibussowitsch     PetscCall(VecCopy(th->A1, th->A0));
251818efac9SLisandro Dalcin   }
252818efac9SLisandro Dalcin 
253818efac9SLisandro Dalcin   th->status = TS_STEP_INCOMPLETE;
254818efac9SLisandro Dalcin   while (!ts->reason && th->status != TS_STEP_COMPLETE) {
255818efac9SLisandro Dalcin     if (ts->steprestart) {
2569566063dSJacob Faibussowitsch       PetscCall(TSAlpha_Restart(ts, &stageok));
257818efac9SLisandro Dalcin       if (!stageok) goto reject_step;
258818efac9SLisandro Dalcin     }
259818efac9SLisandro Dalcin 
2609566063dSJacob Faibussowitsch     PetscCall(TSAlpha_StageTime(ts));
261220f924aSDavid Kamensky     PetscCall(TSAlpha_ApplyPredictor(ts, th->X1));
2629566063dSJacob Faibussowitsch     PetscCall(TSPreStage(ts, th->stage_time));
2639566063dSJacob Faibussowitsch     PetscCall(TSAlpha_SNESSolve(ts, NULL, th->X1));
2649566063dSJacob Faibussowitsch     PetscCall(TSPostStage(ts, th->stage_time, 0, &th->Xa));
2659566063dSJacob Faibussowitsch     PetscCall(TSAdaptCheckStage(ts->adapt, ts, th->stage_time, th->Xa, &stageok));
266818efac9SLisandro Dalcin     if (!stageok) goto reject_step;
267818efac9SLisandro Dalcin 
268818efac9SLisandro Dalcin     th->status = TS_STEP_PENDING;
2699566063dSJacob Faibussowitsch     PetscCall(VecCopy(th->X1, ts->vec_sol));
2709566063dSJacob Faibussowitsch     PetscCall(VecCopy(th->V1, ts->vec_dot));
2719566063dSJacob Faibussowitsch     PetscCall(TSAdaptChoose(ts->adapt, ts, ts->time_step, NULL, &next_time_step, &accept));
272818efac9SLisandro Dalcin     th->status = accept ? TS_STEP_COMPLETE : TS_STEP_INCOMPLETE;
273818efac9SLisandro Dalcin     if (!accept) {
2749566063dSJacob Faibussowitsch       PetscCall(VecCopy(th->X0, ts->vec_sol));
2759566063dSJacob Faibussowitsch       PetscCall(VecCopy(th->V0, ts->vec_dot));
276818efac9SLisandro Dalcin       ts->time_step = next_time_step;
277818efac9SLisandro Dalcin       goto reject_step;
278818efac9SLisandro Dalcin     }
279818efac9SLisandro Dalcin 
280818efac9SLisandro Dalcin     ts->ptime += ts->time_step;
281818efac9SLisandro Dalcin     ts->time_step = next_time_step;
282818efac9SLisandro Dalcin     break;
283818efac9SLisandro Dalcin 
284818efac9SLisandro Dalcin   reject_step:
2859371c9d4SSatish Balay     ts->reject++;
2869371c9d4SSatish Balay     accept = PETSC_FALSE;
287818efac9SLisandro Dalcin     if (!ts->reason && ++rejections > ts->max_reject && ts->max_reject >= 0) {
288818efac9SLisandro Dalcin       ts->reason = TS_DIVERGED_STEP_REJECTED;
28963a3b9bcSJacob Faibussowitsch       PetscCall(PetscInfo(ts, "Step=%" PetscInt_FMT ", step rejections %" PetscInt_FMT " greater than current TS allowed, stopping solve\n", ts->steps, rejections));
290818efac9SLisandro Dalcin     }
291818efac9SLisandro Dalcin   }
2923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
293818efac9SLisandro Dalcin }
294818efac9SLisandro Dalcin 
TSEvaluateWLTE_Alpha(TS ts,NormType wnormtype,PetscInt * order,PetscReal * wlte)295d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSEvaluateWLTE_Alpha(TS ts, NormType wnormtype, PetscInt *order, PetscReal *wlte)
296d71ae5a4SJacob Faibussowitsch {
297818efac9SLisandro Dalcin   TS_Alpha *th = (TS_Alpha *)ts->data;
298818efac9SLisandro Dalcin   Vec       X  = th->X1;              /* X = solution */
299818efac9SLisandro Dalcin   Vec       V  = th->V1;              /* V = solution */
300818efac9SLisandro Dalcin   Vec       Y  = th->vec_lte_work[0]; /* Y = X + LTE  */
301818efac9SLisandro Dalcin   Vec       Z  = th->vec_lte_work[1]; /* Z = V + LTE  */
3027453f775SEmil Constantinescu   PetscReal enormX, enormV, enormXa, enormVa, enormXr, enormVr;
303818efac9SLisandro Dalcin 
304818efac9SLisandro Dalcin   PetscFunctionBegin;
3059371c9d4SSatish Balay   if (!th->vec_sol_prev) {
3069371c9d4SSatish Balay     *wlte = -1;
3073ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
3089371c9d4SSatish Balay   }
3099371c9d4SSatish Balay   if (!th->vec_dot_prev) {
3109371c9d4SSatish Balay     *wlte = -1;
3113ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
3129371c9d4SSatish Balay   }
3139371c9d4SSatish Balay   if (!th->vec_lte_work[0]) {
3149371c9d4SSatish Balay     *wlte = -1;
3153ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
3169371c9d4SSatish Balay   }
3179371c9d4SSatish Balay   if (!th->vec_lte_work[1]) {
3189371c9d4SSatish Balay     *wlte = -1;
3193ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
3209371c9d4SSatish Balay   }
321818efac9SLisandro Dalcin   if (ts->steprestart) {
3222ffb9264SLisandro Dalcin     /* th->vec_lte_prev is set to the LTE in TSAlpha_Restart() */
3239566063dSJacob Faibussowitsch     PetscCall(VecAXPY(Y, 1, X));
3249566063dSJacob Faibussowitsch     PetscCall(VecAXPY(Z, 1, V));
325818efac9SLisandro Dalcin   } else {
326818efac9SLisandro Dalcin     /* Compute LTE using backward differences with non-constant time step */
327818efac9SLisandro Dalcin     PetscReal   h = ts->time_step, h_prev = ts->ptime - ts->ptime_prev;
328818efac9SLisandro Dalcin     PetscReal   a = 1 + h_prev / h;
3299371c9d4SSatish Balay     PetscScalar scal[3];
3309371c9d4SSatish Balay     Vec         vecX[3], vecV[3];
3319371c9d4SSatish Balay     scal[0] = +1 / a;
3329371c9d4SSatish Balay     scal[1] = -1 / (a - 1);
3339371c9d4SSatish Balay     scal[2] = +1 / (a * (a - 1));
3349371c9d4SSatish Balay     vecX[0] = th->X1;
3359371c9d4SSatish Balay     vecX[1] = th->X0;
3369371c9d4SSatish Balay     vecX[2] = th->vec_sol_prev;
3379371c9d4SSatish Balay     vecV[0] = th->V1;
3389371c9d4SSatish Balay     vecV[1] = th->V0;
3399371c9d4SSatish Balay     vecV[2] = th->vec_dot_prev;
3409566063dSJacob Faibussowitsch     PetscCall(VecCopy(X, Y));
3419566063dSJacob Faibussowitsch     PetscCall(VecMAXPY(Y, 3, scal, vecX));
3429566063dSJacob Faibussowitsch     PetscCall(VecCopy(V, Z));
3439566063dSJacob Faibussowitsch     PetscCall(VecMAXPY(Z, 3, scal, vecV));
344818efac9SLisandro Dalcin   }
345818efac9SLisandro Dalcin   /* XXX ts->atol and ts->vatol are not appropriate for computing enormV */
3469566063dSJacob Faibussowitsch   PetscCall(TSErrorWeightedNorm(ts, X, Y, wnormtype, &enormX, &enormXa, &enormXr));
3479566063dSJacob Faibussowitsch   PetscCall(TSErrorWeightedNorm(ts, V, Z, wnormtype, &enormV, &enormVa, &enormVr));
3489371c9d4SSatish Balay   if (wnormtype == NORM_2) *wlte = PetscSqrtReal(PetscSqr(enormX) / 2 + PetscSqr(enormV) / 2);
3499371c9d4SSatish Balay   else *wlte = PetscMax(enormX, enormV);
350818efac9SLisandro Dalcin   if (order) *order = 2;
3513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
352818efac9SLisandro Dalcin }
353818efac9SLisandro Dalcin 
TSRollBack_Alpha(TS ts)354d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSRollBack_Alpha(TS ts)
355d71ae5a4SJacob Faibussowitsch {
356818efac9SLisandro Dalcin   TS_Alpha *th = (TS_Alpha *)ts->data;
357818efac9SLisandro Dalcin 
358818efac9SLisandro Dalcin   PetscFunctionBegin;
3599566063dSJacob Faibussowitsch   PetscCall(VecCopy(th->X0, ts->vec_sol));
3609566063dSJacob Faibussowitsch   PetscCall(VecCopy(th->V0, ts->vec_dot));
3613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
362818efac9SLisandro Dalcin }
363818efac9SLisandro Dalcin 
364818efac9SLisandro Dalcin /*
365818efac9SLisandro Dalcin static PetscErrorCode TSInterpolate_Alpha(TS ts,PetscReal t,Vec X,Vec V)
366818efac9SLisandro Dalcin {
367818efac9SLisandro Dalcin   TS_Alpha       *th = (TS_Alpha*)ts->data;
368818efac9SLisandro Dalcin   PetscReal      dt  = t - ts->ptime;
369818efac9SLisandro Dalcin 
370818efac9SLisandro Dalcin   PetscFunctionBegin;
3719566063dSJacob Faibussowitsch   PetscCall(VecCopy(ts->vec_dot,V));
3729566063dSJacob Faibussowitsch   PetscCall(VecAXPY(V,dt*(1-th->Gamma),th->A0));
3739566063dSJacob Faibussowitsch   PetscCall(VecAXPY(V,dt*th->Gamma,th->A1));
3749566063dSJacob Faibussowitsch   PetscCall(VecCopy(ts->vec_sol,X));
3759566063dSJacob Faibussowitsch   PetscCall(VecAXPY(X,dt,V));
3769566063dSJacob Faibussowitsch   PetscCall(VecAXPY(X,dt*dt*((PetscReal)0.5-th->Beta),th->A0));
3779566063dSJacob Faibussowitsch   PetscCall(VecAXPY(X,dt*dt*th->Beta,th->A1));
3783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
379818efac9SLisandro Dalcin }
380818efac9SLisandro Dalcin */
381818efac9SLisandro Dalcin 
SNESTSFormFunction_Alpha(PETSC_UNUSED SNES snes,Vec X,Vec F,TS ts)382d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESTSFormFunction_Alpha(PETSC_UNUSED SNES snes, Vec X, Vec F, TS ts)
383d71ae5a4SJacob Faibussowitsch {
384818efac9SLisandro Dalcin   TS_Alpha *th = (TS_Alpha *)ts->data;
385818efac9SLisandro Dalcin   PetscReal ta = th->stage_time;
386818efac9SLisandro Dalcin   Vec       Xa = th->Xa, Va = th->Va, Aa = th->Aa;
387818efac9SLisandro Dalcin 
388818efac9SLisandro Dalcin   PetscFunctionBegin;
3899566063dSJacob Faibussowitsch   PetscCall(TSAlpha_StageVecs(ts, X));
390818efac9SLisandro Dalcin   /* F = Function(ta,Xa,Va,Aa) */
3919566063dSJacob Faibussowitsch   PetscCall(TSComputeI2Function(ts, ta, Xa, Va, Aa, F));
3929566063dSJacob Faibussowitsch   PetscCall(VecScale(F, th->scale_F));
3933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
394818efac9SLisandro Dalcin }
395818efac9SLisandro Dalcin 
SNESTSFormJacobian_Alpha(PETSC_UNUSED SNES snes,PETSC_UNUSED Vec X,Mat J,Mat P,TS ts)396d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESTSFormJacobian_Alpha(PETSC_UNUSED SNES snes, PETSC_UNUSED Vec X, Mat J, Mat P, TS ts)
397d71ae5a4SJacob Faibussowitsch {
398818efac9SLisandro Dalcin   TS_Alpha *th = (TS_Alpha *)ts->data;
399818efac9SLisandro Dalcin   PetscReal ta = th->stage_time;
400818efac9SLisandro Dalcin   Vec       Xa = th->Xa, Va = th->Va, Aa = th->Aa;
401818efac9SLisandro Dalcin   PetscReal dVdX = th->shift_V, dAdX = th->shift_A;
402818efac9SLisandro Dalcin 
403818efac9SLisandro Dalcin   PetscFunctionBegin;
404818efac9SLisandro Dalcin   /* J,P = Jacobian(ta,Xa,Va,Aa) */
4059566063dSJacob Faibussowitsch   PetscCall(TSComputeI2Jacobian(ts, ta, Xa, Va, Aa, dVdX, dAdX, J, P));
4063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
407818efac9SLisandro Dalcin }
408818efac9SLisandro Dalcin 
TSReset_Alpha(TS ts)409d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSReset_Alpha(TS ts)
410d71ae5a4SJacob Faibussowitsch {
411818efac9SLisandro Dalcin   TS_Alpha *th = (TS_Alpha *)ts->data;
412818efac9SLisandro Dalcin 
413818efac9SLisandro Dalcin   PetscFunctionBegin;
4149566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&th->X0));
4159566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&th->Xa));
4169566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&th->X1));
4179566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&th->V0));
4189566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&th->Va));
4199566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&th->V1));
4209566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&th->A0));
4219566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&th->Aa));
4229566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&th->A1));
4239566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&th->vec_sol_prev));
4249566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&th->vec_dot_prev));
4259566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&th->vec_lte_work[0]));
4269566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&th->vec_lte_work[1]));
4273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
428818efac9SLisandro Dalcin }
429818efac9SLisandro Dalcin 
TSDestroy_Alpha(TS ts)430d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSDestroy_Alpha(TS ts)
431d71ae5a4SJacob Faibussowitsch {
432818efac9SLisandro Dalcin   PetscFunctionBegin;
4339566063dSJacob Faibussowitsch   PetscCall(TSReset_Alpha(ts));
4349566063dSJacob Faibussowitsch   PetscCall(PetscFree(ts->data));
435818efac9SLisandro Dalcin 
4369566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSAlpha2SetRadius_C", NULL));
4379566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSAlpha2SetParams_C", NULL));
4389566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSAlpha2GetParams_C", NULL));
4393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
440818efac9SLisandro Dalcin }
441818efac9SLisandro Dalcin 
TSSetUp_Alpha(TS ts)442d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSSetUp_Alpha(TS ts)
443d71ae5a4SJacob Faibussowitsch {
444818efac9SLisandro Dalcin   TS_Alpha *th = (TS_Alpha *)ts->data;
4452ffb9264SLisandro Dalcin   PetscBool match;
446818efac9SLisandro Dalcin 
447818efac9SLisandro Dalcin   PetscFunctionBegin;
4489566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(ts->vec_sol, &th->X0));
4499566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(ts->vec_sol, &th->Xa));
4509566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(ts->vec_sol, &th->X1));
4519566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(ts->vec_sol, &th->V0));
4529566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(ts->vec_sol, &th->Va));
4539566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(ts->vec_sol, &th->V1));
4549566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(ts->vec_sol, &th->A0));
4559566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(ts->vec_sol, &th->Aa));
4569566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(ts->vec_sol, &th->A1));
457818efac9SLisandro Dalcin 
4589566063dSJacob Faibussowitsch   PetscCall(TSGetAdapt(ts, &ts->adapt));
4599566063dSJacob Faibussowitsch   PetscCall(TSAdaptCandidatesClear(ts->adapt));
4609566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)ts->adapt, TSADAPTNONE, &match));
4612ffb9264SLisandro Dalcin   if (!match) {
4629566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(ts->vec_sol, &th->vec_sol_prev));
4639566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(ts->vec_sol, &th->vec_dot_prev));
4649566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(ts->vec_sol, &th->vec_lte_work[0]));
4659566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(ts->vec_sol, &th->vec_lte_work[1]));
466818efac9SLisandro Dalcin   }
467818efac9SLisandro Dalcin 
4689566063dSJacob Faibussowitsch   PetscCall(TSGetSNES(ts, &ts->snes));
4693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
470818efac9SLisandro Dalcin }
471818efac9SLisandro Dalcin 
TSSetFromOptions_Alpha(TS ts,PetscOptionItems PetscOptionsObject)472ce78bad3SBarry Smith static PetscErrorCode TSSetFromOptions_Alpha(TS ts, PetscOptionItems PetscOptionsObject)
473d71ae5a4SJacob Faibussowitsch {
474818efac9SLisandro Dalcin   TS_Alpha *th = (TS_Alpha *)ts->data;
475818efac9SLisandro Dalcin 
476818efac9SLisandro Dalcin   PetscFunctionBegin;
477d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "Generalized-Alpha ODE solver options");
478818efac9SLisandro Dalcin   {
479818efac9SLisandro Dalcin     PetscBool flg;
480818efac9SLisandro Dalcin     PetscReal radius = 1;
4819566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-ts_alpha_radius", "Spectral radius (high-frequency dissipation)", "TSAlpha2SetRadius", radius, &radius, &flg));
4829566063dSJacob Faibussowitsch     if (flg) PetscCall(TSAlpha2SetRadius(ts, radius));
4839566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-ts_alpha_alpha_m", "Algorithmic parameter alpha_m", "TSAlpha2SetParams", th->Alpha_m, &th->Alpha_m, NULL));
4849566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-ts_alpha_alpha_f", "Algorithmic parameter alpha_f", "TSAlpha2SetParams", th->Alpha_f, &th->Alpha_f, NULL));
4859566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-ts_alpha_gamma", "Algorithmic parameter gamma", "TSAlpha2SetParams", th->Gamma, &th->Gamma, NULL));
4869566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-ts_alpha_beta", "Algorithmic parameter beta", "TSAlpha2SetParams", th->Beta, &th->Beta, NULL));
4879566063dSJacob Faibussowitsch     PetscCall(TSAlpha2SetParams(ts, th->Alpha_m, th->Alpha_f, th->Gamma, th->Beta));
488818efac9SLisandro Dalcin   }
489d0609cedSBarry Smith   PetscOptionsHeadEnd();
4903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
491818efac9SLisandro Dalcin }
492818efac9SLisandro Dalcin 
TSView_Alpha(TS ts,PetscViewer viewer)493d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSView_Alpha(TS ts, PetscViewer viewer)
494d71ae5a4SJacob Faibussowitsch {
495818efac9SLisandro Dalcin   TS_Alpha *th = (TS_Alpha *)ts->data;
4969f196a02SMartin Diehl   PetscBool isascii;
497818efac9SLisandro Dalcin 
498818efac9SLisandro Dalcin   PetscFunctionBegin;
4999f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
5009f196a02SMartin Diehl   if (isascii) PetscCall(PetscViewerASCIIPrintf(viewer, "  Alpha_m=%g, Alpha_f=%g, Gamma=%g, Beta=%g\n", (double)th->Alpha_m, (double)th->Alpha_f, (double)th->Gamma, (double)th->Beta));
5013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
502818efac9SLisandro Dalcin }
503818efac9SLisandro Dalcin 
TSAlpha2SetRadius_Alpha(TS ts,PetscReal radius)504d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSAlpha2SetRadius_Alpha(TS ts, PetscReal radius)
505d71ae5a4SJacob Faibussowitsch {
506818efac9SLisandro Dalcin   PetscReal alpha_m, alpha_f, gamma, beta;
507818efac9SLisandro Dalcin 
508818efac9SLisandro Dalcin   PetscFunctionBegin;
509cad9d221SBarry Smith   PetscCheck(radius >= 0 && radius <= 1, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Radius %g not in range [0,1]", (double)radius);
510818efac9SLisandro Dalcin   alpha_m = (2 - radius) / (1 + radius);
511818efac9SLisandro Dalcin   alpha_f = 1 / (1 + radius);
512818efac9SLisandro Dalcin   gamma   = (PetscReal)0.5 + alpha_m - alpha_f;
5139371c9d4SSatish Balay   beta    = (PetscReal)0.5 * (1 + alpha_m - alpha_f);
5149371c9d4SSatish Balay   beta *= beta;
5159566063dSJacob Faibussowitsch   PetscCall(TSAlpha2SetParams(ts, alpha_m, alpha_f, gamma, beta));
5163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
517818efac9SLisandro Dalcin }
518818efac9SLisandro Dalcin 
TSAlpha2SetParams_Alpha(TS ts,PetscReal alpha_m,PetscReal alpha_f,PetscReal gamma,PetscReal beta)519d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSAlpha2SetParams_Alpha(TS ts, PetscReal alpha_m, PetscReal alpha_f, PetscReal gamma, PetscReal beta)
520d71ae5a4SJacob Faibussowitsch {
521818efac9SLisandro Dalcin   TS_Alpha *th  = (TS_Alpha *)ts->data;
522818efac9SLisandro Dalcin   PetscReal tol = 100 * PETSC_MACHINE_EPSILON;
523818efac9SLisandro Dalcin   PetscReal res = ((PetscReal)0.5 + alpha_m - alpha_f) - gamma;
524818efac9SLisandro Dalcin 
525818efac9SLisandro Dalcin   PetscFunctionBegin;
526818efac9SLisandro Dalcin   th->Alpha_m = alpha_m;
527818efac9SLisandro Dalcin   th->Alpha_f = alpha_f;
528818efac9SLisandro Dalcin   th->Gamma   = gamma;
529818efac9SLisandro Dalcin   th->Beta    = beta;
530818efac9SLisandro Dalcin   th->order   = (PetscAbsReal(res) < tol) ? 2 : 1;
5313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
532818efac9SLisandro Dalcin }
533818efac9SLisandro Dalcin 
TSAlpha2GetParams_Alpha(TS ts,PetscReal * alpha_m,PetscReal * alpha_f,PetscReal * gamma,PetscReal * beta)534d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSAlpha2GetParams_Alpha(TS ts, PetscReal *alpha_m, PetscReal *alpha_f, PetscReal *gamma, PetscReal *beta)
535d71ae5a4SJacob Faibussowitsch {
536818efac9SLisandro Dalcin   TS_Alpha *th = (TS_Alpha *)ts->data;
537818efac9SLisandro Dalcin 
538818efac9SLisandro Dalcin   PetscFunctionBegin;
539818efac9SLisandro Dalcin   if (alpha_m) *alpha_m = th->Alpha_m;
540818efac9SLisandro Dalcin   if (alpha_f) *alpha_f = th->Alpha_f;
541818efac9SLisandro Dalcin   if (gamma) *gamma = th->Gamma;
542818efac9SLisandro Dalcin   if (beta) *beta = th->Beta;
5433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
544818efac9SLisandro Dalcin }
545818efac9SLisandro Dalcin 
546818efac9SLisandro Dalcin /*MC
5471d27aa22SBarry Smith   TSALPHA2 - ODE/DAE solver using the implicit Generalized-Alpha method for second-order systems {cite}`chung1993`
548818efac9SLisandro Dalcin 
549818efac9SLisandro Dalcin   Level: beginner
550818efac9SLisandro Dalcin 
5511cc06b55SBarry Smith .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetType()`, `TSAlpha2SetRadius()`, `TSAlpha2SetParams()`
552818efac9SLisandro Dalcin M*/
TSCreate_Alpha2(TS ts)553d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode TSCreate_Alpha2(TS ts)
554d71ae5a4SJacob Faibussowitsch {
555818efac9SLisandro Dalcin   TS_Alpha *th;
556818efac9SLisandro Dalcin 
557818efac9SLisandro Dalcin   PetscFunctionBegin;
558818efac9SLisandro Dalcin   ts->ops->reset          = TSReset_Alpha;
559818efac9SLisandro Dalcin   ts->ops->destroy        = TSDestroy_Alpha;
560818efac9SLisandro Dalcin   ts->ops->view           = TSView_Alpha;
561818efac9SLisandro Dalcin   ts->ops->setup          = TSSetUp_Alpha;
562818efac9SLisandro Dalcin   ts->ops->setfromoptions = TSSetFromOptions_Alpha;
563818efac9SLisandro Dalcin   ts->ops->step           = TSStep_Alpha;
564818efac9SLisandro Dalcin   ts->ops->evaluatewlte   = TSEvaluateWLTE_Alpha;
565818efac9SLisandro Dalcin   ts->ops->rollback       = TSRollBack_Alpha;
566818efac9SLisandro Dalcin   /*ts->ops->interpolate  = TSInterpolate_Alpha;*/
567818efac9SLisandro Dalcin   ts->ops->snesfunction  = SNESTSFormFunction_Alpha;
568818efac9SLisandro Dalcin   ts->ops->snesjacobian  = SNESTSFormJacobian_Alpha;
5692ffb9264SLisandro Dalcin   ts->default_adapt_type = TSADAPTNONE;
570818efac9SLisandro Dalcin 
571efd4aadfSBarry Smith   ts->usessnes = PETSC_TRUE;
572efd4aadfSBarry Smith 
5734dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&th));
574818efac9SLisandro Dalcin   ts->data = (void *)th;
575818efac9SLisandro Dalcin 
576818efac9SLisandro Dalcin   th->Alpha_m = 0.5;
577818efac9SLisandro Dalcin   th->Alpha_f = 0.5;
578818efac9SLisandro Dalcin   th->Gamma   = 0.5;
579818efac9SLisandro Dalcin   th->Beta    = 0.25;
580818efac9SLisandro Dalcin   th->order   = 2;
581818efac9SLisandro Dalcin 
582220f924aSDavid Kamensky   th->predictor     = NULL;
583220f924aSDavid Kamensky   th->predictor_ctx = NULL;
584220f924aSDavid Kamensky 
5859566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSAlpha2SetRadius_C", TSAlpha2SetRadius_Alpha));
5869566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSAlpha2SetParams_C", TSAlpha2SetParams_Alpha));
5879566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSAlpha2GetParams_C", TSAlpha2GetParams_Alpha));
5883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
589818efac9SLisandro Dalcin }
590818efac9SLisandro Dalcin 
591818efac9SLisandro Dalcin /*@
592bcf0153eSBarry Smith   TSAlpha2SetRadius - sets the desired spectral radius of the method for `TSALPHA2`
593818efac9SLisandro Dalcin   (i.e. high-frequency numerical damping)
594818efac9SLisandro Dalcin 
595c3339decSBarry Smith   Logically Collective
596818efac9SLisandro Dalcin 
597d8d19677SJose E. Roman   Input Parameters:
598818efac9SLisandro Dalcin + ts     - timestepping context
599818efac9SLisandro Dalcin - radius - the desired spectral radius
600818efac9SLisandro Dalcin 
601bcf0153eSBarry Smith   Options Database Key:
60267b8a455SSatish Balay . -ts_alpha_radius <radius> - set the desired spectral radius
603818efac9SLisandro Dalcin 
604818efac9SLisandro Dalcin   Level: intermediate
605818efac9SLisandro Dalcin 
60614d0ab18SJacob Faibussowitsch   Notes:
60714d0ab18SJacob Faibussowitsch 
60814d0ab18SJacob Faibussowitsch   The algorithmic parameters $\alpha_m$ and $\alpha_f$ of the generalized-$\alpha$ method can
60914d0ab18SJacob Faibussowitsch   be computed in terms of a specified spectral radius $\rho$ in `[0, 1]` for infinite time step
61014d0ab18SJacob Faibussowitsch   in order to control high-frequency numerical damping\:
611562efe2eSBarry Smith 
61214d0ab18SJacob Faibussowitsch   $$
613562efe2eSBarry Smith   \begin{align*}
614562efe2eSBarry Smith   \alpha_m = (2-\rho)/(1+\rho) \\
61514d0ab18SJacob Faibussowitsch   \alpha_f = 1/(1+\rho)
616562efe2eSBarry Smith   \end{align*}
61714d0ab18SJacob Faibussowitsch   $$
61814d0ab18SJacob Faibussowitsch 
6191cc06b55SBarry Smith .seealso: [](ch_ts), `TS`, `TSALPHA2`, `TSAlpha2SetParams()`, `TSAlpha2GetParams()`
620818efac9SLisandro Dalcin @*/
TSAlpha2SetRadius(TS ts,PetscReal radius)621d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAlpha2SetRadius(TS ts, PetscReal radius)
622d71ae5a4SJacob Faibussowitsch {
623818efac9SLisandro Dalcin   PetscFunctionBegin;
624818efac9SLisandro Dalcin   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
625818efac9SLisandro Dalcin   PetscValidLogicalCollectiveReal(ts, radius, 2);
626cad9d221SBarry Smith   PetscCheck(radius >= 0 && radius <= 1, ((PetscObject)ts)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Radius %g not in range [0,1]", (double)radius);
627cac4c232SBarry Smith   PetscTryMethod(ts, "TSAlpha2SetRadius_C", (TS, PetscReal), (ts, radius));
6283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
629818efac9SLisandro Dalcin }
630818efac9SLisandro Dalcin 
631818efac9SLisandro Dalcin /*@
632bcf0153eSBarry Smith   TSAlpha2SetParams - sets the algorithmic parameters for `TSALPHA2`
633818efac9SLisandro Dalcin 
634c3339decSBarry Smith   Logically Collective
635818efac9SLisandro Dalcin 
636d8d19677SJose E. Roman   Input Parameters:
637818efac9SLisandro Dalcin + ts      - timestepping context
6382fe279fdSBarry Smith . alpha_m - algorithmic parameter
6392fe279fdSBarry Smith . alpha_f - algorithmic parameter
6402fe279fdSBarry Smith . gamma   - algorithmic parameter
6412fe279fdSBarry Smith - beta    - algorithmic parameter
642818efac9SLisandro Dalcin 
643bcf0153eSBarry Smith   Options Database Keys:
64467b8a455SSatish Balay + -ts_alpha_alpha_m <alpha_m> - set alpha_m
64567b8a455SSatish Balay . -ts_alpha_alpha_f <alpha_f> - set alpha_f
64667b8a455SSatish Balay . -ts_alpha_gamma   <gamma>   - set gamma
64767b8a455SSatish Balay - -ts_alpha_beta    <beta>    - set beta
648818efac9SLisandro Dalcin 
649bcf0153eSBarry Smith   Level: advanced
650bcf0153eSBarry Smith 
65114d0ab18SJacob Faibussowitsch   Notes:
65214d0ab18SJacob Faibussowitsch   Second-order accuracy can be obtained so long as\:
653562efe2eSBarry Smith 
65414d0ab18SJacob Faibussowitsch   $$
655562efe2eSBarry Smith   \begin{align*}
656562efe2eSBarry Smith   \gamma = 1/2 + \alpha_m - \alpha_f \\
657562efe2eSBarry Smith   \beta  = 1/4 (1 + \alpha_m - \alpha_f)^2.
658562efe2eSBarry Smith   \end{align*}
65914d0ab18SJacob Faibussowitsch   $$
66014d0ab18SJacob Faibussowitsch 
66114d0ab18SJacob Faibussowitsch   Unconditional stability requires\:
66214d0ab18SJacob Faibussowitsch   $$
663562efe2eSBarry Smith   \alpha_m >= \alpha_f >= 1/2.
66414d0ab18SJacob Faibussowitsch   $$
66514d0ab18SJacob Faibussowitsch 
66614d0ab18SJacob Faibussowitsch   Use of this function is normally only required to hack `TSALPHA2` to use a modified
66714d0ab18SJacob Faibussowitsch   integration scheme. Users should call `TSAlpha2SetRadius()` to set the desired spectral
66814d0ab18SJacob Faibussowitsch   radius of the methods (i.e. high-frequency damping) in order so select optimal values for
669818efac9SLisandro Dalcin   these parameters.
670818efac9SLisandro Dalcin 
6711cc06b55SBarry Smith .seealso: [](ch_ts), `TS`, `TSALPHA2`, `TSAlpha2SetRadius()`, `TSAlpha2GetParams()`
672818efac9SLisandro Dalcin @*/
TSAlpha2SetParams(TS ts,PetscReal alpha_m,PetscReal alpha_f,PetscReal gamma,PetscReal beta)673d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAlpha2SetParams(TS ts, PetscReal alpha_m, PetscReal alpha_f, PetscReal gamma, PetscReal beta)
674d71ae5a4SJacob Faibussowitsch {
675818efac9SLisandro Dalcin   PetscFunctionBegin;
676818efac9SLisandro Dalcin   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
677818efac9SLisandro Dalcin   PetscValidLogicalCollectiveReal(ts, alpha_m, 2);
678818efac9SLisandro Dalcin   PetscValidLogicalCollectiveReal(ts, alpha_f, 3);
679818efac9SLisandro Dalcin   PetscValidLogicalCollectiveReal(ts, gamma, 4);
680818efac9SLisandro Dalcin   PetscValidLogicalCollectiveReal(ts, beta, 5);
681cac4c232SBarry Smith   PetscTryMethod(ts, "TSAlpha2SetParams_C", (TS, PetscReal, PetscReal, PetscReal, PetscReal), (ts, alpha_m, alpha_f, gamma, beta));
6823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
683818efac9SLisandro Dalcin }
684818efac9SLisandro Dalcin 
685818efac9SLisandro Dalcin /*@
686bcf0153eSBarry Smith   TSAlpha2GetParams - gets the algorithmic parameters for `TSALPHA2`
687818efac9SLisandro Dalcin 
688818efac9SLisandro Dalcin   Not Collective
689818efac9SLisandro Dalcin 
690818efac9SLisandro Dalcin   Input Parameter:
691818efac9SLisandro Dalcin . ts - timestepping context
692818efac9SLisandro Dalcin 
693818efac9SLisandro Dalcin   Output Parameters:
6942fe279fdSBarry Smith + alpha_m - algorithmic parameter
6952fe279fdSBarry Smith . alpha_f - algorithmic parameter
6962fe279fdSBarry Smith . gamma   - algorithmic parameter
6972fe279fdSBarry Smith - beta    - algorithmic parameter
698818efac9SLisandro Dalcin 
699bcf0153eSBarry Smith   Level: advanced
700bcf0153eSBarry Smith 
701818efac9SLisandro Dalcin   Note:
70214d0ab18SJacob Faibussowitsch   Use of this function is normally only required to hack `TSALPHA2` to use a modified
70314d0ab18SJacob Faibussowitsch   integration scheme. Users should call `TSAlpha2SetRadius()` to set the high-frequency damping
70414d0ab18SJacob Faibussowitsch   (i.e. spectral radius of the method) in order so select optimal values for these parameters.
705818efac9SLisandro Dalcin 
7061cc06b55SBarry Smith .seealso: [](ch_ts), `TS`, `TSALPHA2`, `TSAlpha2SetRadius()`, `TSAlpha2SetParams()`
707818efac9SLisandro Dalcin @*/
TSAlpha2GetParams(TS ts,PetscReal * alpha_m,PetscReal * alpha_f,PetscReal * gamma,PetscReal * beta)708d71ae5a4SJacob Faibussowitsch PetscErrorCode TSAlpha2GetParams(TS ts, PetscReal *alpha_m, PetscReal *alpha_f, PetscReal *gamma, PetscReal *beta)
709d71ae5a4SJacob Faibussowitsch {
710818efac9SLisandro Dalcin   PetscFunctionBegin;
711818efac9SLisandro Dalcin   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
7124f572ea9SToby Isaac   if (alpha_m) PetscAssertPointer(alpha_m, 2);
7134f572ea9SToby Isaac   if (alpha_f) PetscAssertPointer(alpha_f, 3);
7144f572ea9SToby Isaac   if (gamma) PetscAssertPointer(gamma, 4);
7154f572ea9SToby Isaac   if (beta) PetscAssertPointer(beta, 5);
716cac4c232SBarry Smith   PetscUseMethod(ts, "TSAlpha2GetParams_C", (TS, PetscReal *, PetscReal *, PetscReal *, PetscReal *), (ts, alpha_m, alpha_f, gamma, beta));
7173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
718818efac9SLisandro Dalcin }
719