xref: /petsc/src/ts/impls/mimex/mimex.c (revision 4dfa11a44d5adf2389f1d3acbc8f3c1116dc6c3a)
1abadfa0fSMatthew G. Knepley /*
2abadfa0fSMatthew G. Knepley        Code for Timestepping with my makeshift IMEX.
3abadfa0fSMatthew G. Knepley */
4af0996ceSBarry Smith #include <petsc/private/tsimpl.h> /*I   "petscts.h"   I*/
5abadfa0fSMatthew G. Knepley #include <petscds.h>
6ea844a1aSMatthew Knepley #include <petscsection.h>
7abadfa0fSMatthew G. Knepley #include <petscdmplex.h>
8abadfa0fSMatthew G. Knepley 
9abadfa0fSMatthew G. Knepley typedef struct {
10010837a9SMatthew G. Knepley   Vec       Xdot, update;
11abadfa0fSMatthew G. Knepley   PetscReal stage_time;
1218c55e3fSMatthew G. Knepley   PetscInt  version;
13abadfa0fSMatthew G. Knepley } TS_Mimex;
14abadfa0fSMatthew G. Knepley 
159371c9d4SSatish Balay static PetscErrorCode TSMimexGetX0AndXdot(TS ts, DM dm, Vec *X0, Vec *Xdot) {
16abadfa0fSMatthew G. Knepley   TS_Mimex *mimex = (TS_Mimex *)ts->data;
17abadfa0fSMatthew G. Knepley 
18abadfa0fSMatthew G. Knepley   PetscFunctionBegin;
19abadfa0fSMatthew G. Knepley   if (X0) {
209566063dSJacob Faibussowitsch     if (dm && dm != ts->dm) PetscCall(DMGetNamedGlobalVector(dm, "TSMimex_X0", X0));
21ad540459SPierre Jolivet     else *X0 = ts->vec_sol;
22abadfa0fSMatthew G. Knepley   }
23abadfa0fSMatthew G. Knepley   if (Xdot) {
249566063dSJacob Faibussowitsch     if (dm && dm != ts->dm) PetscCall(DMGetNamedGlobalVector(dm, "TSMimex_Xdot", Xdot));
25ad540459SPierre Jolivet     else *Xdot = mimex->Xdot;
26abadfa0fSMatthew G. Knepley   }
27abadfa0fSMatthew G. Knepley   PetscFunctionReturn(0);
28abadfa0fSMatthew G. Knepley }
29abadfa0fSMatthew G. Knepley 
309371c9d4SSatish Balay static PetscErrorCode TSMimexRestoreX0AndXdot(TS ts, DM dm, Vec *X0, Vec *Xdot) {
31abadfa0fSMatthew G. Knepley   PetscFunctionBegin;
329371c9d4SSatish Balay   if (X0)
339371c9d4SSatish Balay     if (dm && dm != ts->dm) PetscCall(DMRestoreNamedGlobalVector(dm, "TSMimex_X0", X0));
349371c9d4SSatish Balay   if (Xdot)
359371c9d4SSatish Balay     if (dm && dm != ts->dm) PetscCall(DMRestoreNamedGlobalVector(dm, "TSMimex_Xdot", Xdot));
36abadfa0fSMatthew G. Knepley   PetscFunctionReturn(0);
37abadfa0fSMatthew G. Knepley }
38abadfa0fSMatthew G. Knepley 
399371c9d4SSatish Balay static PetscErrorCode TSMimexGetXstarAndG(TS ts, DM dm, Vec *Xstar, Vec *G) {
4018c55e3fSMatthew G. Knepley   PetscFunctionBegin;
419566063dSJacob Faibussowitsch   PetscCall(DMGetNamedGlobalVector(dm, "TSMimex_Xstar", Xstar));
429566063dSJacob Faibussowitsch   PetscCall(DMGetNamedGlobalVector(dm, "TSMimex_G", G));
4318c55e3fSMatthew G. Knepley   PetscFunctionReturn(0);
4418c55e3fSMatthew G. Knepley }
4518c55e3fSMatthew G. Knepley 
469371c9d4SSatish Balay static PetscErrorCode TSMimexRestoreXstarAndG(TS ts, DM dm, Vec *Xstar, Vec *G) {
4718c55e3fSMatthew G. Knepley   PetscFunctionBegin;
489566063dSJacob Faibussowitsch   PetscCall(DMRestoreNamedGlobalVector(dm, "TSMimex_Xstar", Xstar));
499566063dSJacob Faibussowitsch   PetscCall(DMRestoreNamedGlobalVector(dm, "TSMimex_G", G));
5018c55e3fSMatthew G. Knepley   PetscFunctionReturn(0);
5118c55e3fSMatthew G. Knepley }
5218c55e3fSMatthew G. Knepley 
53abadfa0fSMatthew G. Knepley /*
54abadfa0fSMatthew G. Knepley   This defines the nonlinear equation that is to be solved with SNES
55abadfa0fSMatthew G. Knepley   G(U) = F[t0+dt, U, (U-U0)*shift] = 0
56abadfa0fSMatthew G. Knepley */
579371c9d4SSatish Balay static PetscErrorCode SNESTSFormFunction_Mimex(SNES snes, Vec x, Vec y, TS ts) {
58abadfa0fSMatthew G. Knepley   TS_Mimex *mimex = (TS_Mimex *)ts->data;
59abadfa0fSMatthew G. Knepley   DM        dm, dmsave;
60abadfa0fSMatthew G. Knepley   Vec       X0, Xdot;
61abadfa0fSMatthew G. Knepley   PetscReal shift = 1. / ts->time_step;
62abadfa0fSMatthew G. Knepley 
63abadfa0fSMatthew G. Knepley   PetscFunctionBegin;
649566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
659566063dSJacob Faibussowitsch   PetscCall(TSMimexGetX0AndXdot(ts, dm, &X0, &Xdot));
669566063dSJacob Faibussowitsch   PetscCall(VecAXPBYPCZ(Xdot, -shift, shift, 0, X0, x));
67abadfa0fSMatthew G. Knepley 
68abadfa0fSMatthew G. Knepley   /* DM monkey-business allows user code to call TSGetDM() inside of functions evaluated on levels of FAS */
69abadfa0fSMatthew G. Knepley   dmsave = ts->dm;
70abadfa0fSMatthew G. Knepley   ts->dm = dm;
719566063dSJacob Faibussowitsch   PetscCall(TSComputeIFunction(ts, mimex->stage_time, x, Xdot, y, PETSC_TRUE));
7218c55e3fSMatthew G. Knepley   if (mimex->version == 1) {
7318c55e3fSMatthew G. Knepley     DM                 dm;
7418c55e3fSMatthew G. Knepley     PetscDS            prob;
7518c55e3fSMatthew G. Knepley     PetscSection       s;
767e01ee02SMatthew G. Knepley     Vec                Xstar = NULL, G = NULL;
7718c55e3fSMatthew G. Knepley     const PetscScalar *ax;
7818c55e3fSMatthew G. Knepley     PetscScalar       *axstar;
7918c55e3fSMatthew G. Knepley     PetscInt           Nf, f, pStart, pEnd, p;
8018c55e3fSMatthew G. Knepley 
819566063dSJacob Faibussowitsch     PetscCall(TSGetDM(ts, &dm));
829566063dSJacob Faibussowitsch     PetscCall(DMGetDS(dm, &prob));
839566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &s));
849566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumFields(prob, &Nf));
859566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(s, &pStart, &pEnd));
869566063dSJacob Faibussowitsch     PetscCall(TSMimexGetXstarAndG(ts, dm, &Xstar, &G));
879566063dSJacob Faibussowitsch     PetscCall(VecCopy(X0, Xstar));
889566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &ax));
899566063dSJacob Faibussowitsch     PetscCall(VecGetArray(Xstar, &axstar));
9018c55e3fSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
9118c55e3fSMatthew G. Knepley       PetscBool implicit;
9218c55e3fSMatthew G. Knepley 
939566063dSJacob Faibussowitsch       PetscCall(PetscDSGetImplicit(prob, f, &implicit));
9418c55e3fSMatthew G. Knepley       if (!implicit) continue;
9518c55e3fSMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
9618c55e3fSMatthew G. Knepley         PetscScalar *a, *axs;
9718c55e3fSMatthew G. Knepley         PetscInt     fdof, fcdof, d;
9818c55e3fSMatthew G. Knepley 
999566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(s, p, f, &fdof));
1009566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldConstraintDof(s, p, f, &fcdof));
1019566063dSJacob Faibussowitsch         PetscCall(DMPlexPointGlobalFieldRead(dm, p, f, ax, &a));
1029566063dSJacob Faibussowitsch         PetscCall(DMPlexPointGlobalFieldRef(dm, p, f, axstar, &axs));
10318c55e3fSMatthew G. Knepley         for (d = 0; d < fdof - fcdof; ++d) axs[d] = a[d];
10418c55e3fSMatthew G. Knepley       }
10518c55e3fSMatthew G. Knepley     }
1069566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &ax));
1079566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(Xstar, &axstar));
1089566063dSJacob Faibussowitsch     PetscCall(TSComputeRHSFunction(ts, ts->ptime, Xstar, G));
1099566063dSJacob Faibussowitsch     PetscCall(VecAXPY(y, -1.0, G));
1109566063dSJacob Faibussowitsch     PetscCall(TSMimexRestoreXstarAndG(ts, dm, &Xstar, &G));
11118c55e3fSMatthew G. Knepley   }
112abadfa0fSMatthew G. Knepley   ts->dm = dmsave;
1139566063dSJacob Faibussowitsch   PetscCall(TSMimexRestoreX0AndXdot(ts, dm, &X0, &Xdot));
114abadfa0fSMatthew G. Knepley   PetscFunctionReturn(0);
115abadfa0fSMatthew G. Knepley }
116abadfa0fSMatthew G. Knepley 
1179371c9d4SSatish Balay static PetscErrorCode SNESTSFormJacobian_Mimex(SNES snes, Vec x, Mat A, Mat B, TS ts) {
118abadfa0fSMatthew G. Knepley   TS_Mimex *mimex = (TS_Mimex *)ts->data;
119abadfa0fSMatthew G. Knepley   DM        dm, dmsave;
120abadfa0fSMatthew G. Knepley   Vec       Xdot;
121abadfa0fSMatthew G. Knepley   PetscReal shift = 1. / ts->time_step;
122abadfa0fSMatthew G. Knepley 
123abadfa0fSMatthew G. Knepley   PetscFunctionBegin;
124abadfa0fSMatthew G. Knepley   /* th->Xdot has already been computed in SNESTSFormFunction_Mimex (SNES guarantees this) */
1259566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
1269566063dSJacob Faibussowitsch   PetscCall(TSMimexGetX0AndXdot(ts, dm, NULL, &Xdot));
127abadfa0fSMatthew G. Knepley 
128abadfa0fSMatthew G. Knepley   /* DM monkey-business allows user code to call TSGetDM() inside of functions evaluated on levels of FAS */
129abadfa0fSMatthew G. Knepley   dmsave = ts->dm;
130abadfa0fSMatthew G. Knepley   ts->dm = dm;
1319566063dSJacob Faibussowitsch   PetscCall(TSComputeIJacobian(ts, mimex->stage_time, x, Xdot, shift, A, B, PETSC_TRUE));
132abadfa0fSMatthew G. Knepley   ts->dm = dmsave;
1339566063dSJacob Faibussowitsch   PetscCall(TSMimexRestoreX0AndXdot(ts, dm, NULL, &Xdot));
134abadfa0fSMatthew G. Knepley   PetscFunctionReturn(0);
135abadfa0fSMatthew G. Knepley }
136abadfa0fSMatthew G. Knepley 
1379371c9d4SSatish Balay static PetscErrorCode TSStep_Mimex_Split(TS ts) {
138abadfa0fSMatthew G. Knepley   TS_Mimex          *mimex = (TS_Mimex *)ts->data;
139abadfa0fSMatthew G. Knepley   DM                 dm;
140abadfa0fSMatthew G. Knepley   PetscDS            prob;
141abadfa0fSMatthew G. Knepley   PetscSection       s;
142abadfa0fSMatthew G. Knepley   Vec                sol = ts->vec_sol, update = mimex->update;
143abadfa0fSMatthew G. Knepley   const PetscScalar *aupdate;
144abadfa0fSMatthew G. Knepley   PetscScalar       *asol, dt = ts->time_step;
145abadfa0fSMatthew G. Knepley   PetscInt           Nf, f, pStart, pEnd, p;
146abadfa0fSMatthew G. Knepley 
147abadfa0fSMatthew G. Knepley   PetscFunctionBegin;
1489566063dSJacob Faibussowitsch   PetscCall(TSGetDM(ts, &dm));
1499566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dm, &prob));
1509566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &s));
1519566063dSJacob Faibussowitsch   PetscCall(PetscDSGetNumFields(prob, &Nf));
1529566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(s, &pStart, &pEnd));
1539566063dSJacob Faibussowitsch   PetscCall(TSPreStage(ts, ts->ptime));
154abadfa0fSMatthew G. Knepley   /* Compute implicit update */
155abadfa0fSMatthew G. Knepley   mimex->stage_time = ts->ptime + ts->time_step;
1569566063dSJacob Faibussowitsch   PetscCall(VecCopy(sol, update));
1579566063dSJacob Faibussowitsch   PetscCall(SNESSolve(ts->snes, NULL, update));
1589566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(update, &aupdate));
1599566063dSJacob Faibussowitsch   PetscCall(VecGetArray(sol, &asol));
160abadfa0fSMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
16118c55e3fSMatthew G. Knepley     PetscBool implicit;
162abadfa0fSMatthew G. Knepley 
1639566063dSJacob Faibussowitsch     PetscCall(PetscDSGetImplicit(prob, f, &implicit));
16418c55e3fSMatthew G. Knepley     if (!implicit) continue;
165abadfa0fSMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
166abadfa0fSMatthew G. Knepley       PetscScalar *au, *as;
167abadfa0fSMatthew G. Knepley       PetscInt     fdof, fcdof, d;
168abadfa0fSMatthew G. Knepley 
1699566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(s, p, f, &fdof));
1709566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldConstraintDof(s, p, f, &fcdof));
1719566063dSJacob Faibussowitsch       PetscCall(DMPlexPointGlobalFieldRead(dm, p, f, aupdate, &au));
1729566063dSJacob Faibussowitsch       PetscCall(DMPlexPointGlobalFieldRef(dm, p, f, asol, &as));
173abadfa0fSMatthew G. Knepley       for (d = 0; d < fdof - fcdof; ++d) as[d] = au[d];
174abadfa0fSMatthew G. Knepley     }
175abadfa0fSMatthew G. Knepley   }
1769566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(update, &aupdate));
1779566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(sol, &asol));
178abadfa0fSMatthew G. Knepley   /* Compute explicit update */
1799566063dSJacob Faibussowitsch   PetscCall(TSComputeRHSFunction(ts, ts->ptime, sol, update));
1809566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(update, &aupdate));
1819566063dSJacob Faibussowitsch   PetscCall(VecGetArray(sol, &asol));
182abadfa0fSMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
18318c55e3fSMatthew G. Knepley     PetscBool implicit;
184abadfa0fSMatthew G. Knepley 
1859566063dSJacob Faibussowitsch     PetscCall(PetscDSGetImplicit(prob, f, &implicit));
18618c55e3fSMatthew G. Knepley     if (implicit) continue;
187abadfa0fSMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
188abadfa0fSMatthew G. Knepley       PetscScalar *au, *as;
189abadfa0fSMatthew G. Knepley       PetscInt     fdof, fcdof, d;
190abadfa0fSMatthew G. Knepley 
1919566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(s, p, f, &fdof));
1929566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldConstraintDof(s, p, f, &fcdof));
1939566063dSJacob Faibussowitsch       PetscCall(DMPlexPointGlobalFieldRead(dm, p, f, aupdate, &au));
1949566063dSJacob Faibussowitsch       PetscCall(DMPlexPointGlobalFieldRef(dm, p, f, asol, &as));
195abadfa0fSMatthew G. Knepley       for (d = 0; d < fdof - fcdof; ++d) as[d] += dt * au[d];
196abadfa0fSMatthew G. Knepley     }
197abadfa0fSMatthew G. Knepley   }
1989566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(update, &aupdate));
1999566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(sol, &asol));
2009566063dSJacob Faibussowitsch   PetscCall(TSPostStage(ts, ts->ptime, 0, &sol));
201abadfa0fSMatthew G. Knepley   ts->ptime += ts->time_step;
202abadfa0fSMatthew G. Knepley   PetscFunctionReturn(0);
203abadfa0fSMatthew G. Knepley }
204abadfa0fSMatthew G. Knepley 
20518c55e3fSMatthew G. Knepley /* Evalute F at U and G at U0 for explicit fields and U for implicit fields */
2069371c9d4SSatish Balay static PetscErrorCode TSStep_Mimex_Implicit(TS ts) {
20718c55e3fSMatthew G. Knepley   TS_Mimex *mimex  = (TS_Mimex *)ts->data;
20818c55e3fSMatthew G. Knepley   Vec       sol    = ts->vec_sol;
20918c55e3fSMatthew G. Knepley   Vec       update = mimex->update;
21018c55e3fSMatthew G. Knepley 
21118c55e3fSMatthew G. Knepley   PetscFunctionBegin;
2129566063dSJacob Faibussowitsch   PetscCall(TSPreStage(ts, ts->ptime));
21318c55e3fSMatthew G. Knepley   /* Compute implicit update */
21418c55e3fSMatthew G. Knepley   mimex->stage_time = ts->ptime + ts->time_step;
21518c55e3fSMatthew G. Knepley   ts->ptime += ts->time_step;
2169566063dSJacob Faibussowitsch   PetscCall(VecCopy(sol, update));
2179566063dSJacob Faibussowitsch   PetscCall(SNESSolve(ts->snes, NULL, update));
2189566063dSJacob Faibussowitsch   PetscCall(VecCopy(update, sol));
2199566063dSJacob Faibussowitsch   PetscCall(TSPostStage(ts, ts->ptime, 0, &sol));
22018c55e3fSMatthew G. Knepley   PetscFunctionReturn(0);
22118c55e3fSMatthew G. Knepley }
22218c55e3fSMatthew G. Knepley 
2239371c9d4SSatish Balay static PetscErrorCode TSStep_Mimex(TS ts) {
22418c55e3fSMatthew G. Knepley   TS_Mimex *mimex = (TS_Mimex *)ts->data;
22518c55e3fSMatthew G. Knepley 
22618c55e3fSMatthew G. Knepley   PetscFunctionBegin;
22718c55e3fSMatthew G. Knepley   switch (mimex->version) {
2289371c9d4SSatish Balay   case 0: PetscCall(TSStep_Mimex_Split(ts)); break;
2299371c9d4SSatish Balay   case 1: PetscCall(TSStep_Mimex_Implicit(ts)); break;
2309371c9d4SSatish Balay   default: SETERRQ(PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Unknown MIMEX version %" PetscInt_FMT, mimex->version);
23118c55e3fSMatthew G. Knepley   }
23218c55e3fSMatthew G. Knepley   PetscFunctionReturn(0);
23318c55e3fSMatthew G. Knepley }
23418c55e3fSMatthew G. Knepley 
235abadfa0fSMatthew G. Knepley /*------------------------------------------------------------*/
236abadfa0fSMatthew G. Knepley 
2379371c9d4SSatish Balay static PetscErrorCode TSSetUp_Mimex(TS ts) {
238abadfa0fSMatthew G. Knepley   TS_Mimex *mimex = (TS_Mimex *)ts->data;
239abadfa0fSMatthew G. Knepley 
240abadfa0fSMatthew G. Knepley   PetscFunctionBegin;
2419566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(ts->vec_sol, &mimex->update));
2429566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(ts->vec_sol, &mimex->Xdot));
243abadfa0fSMatthew G. Knepley   PetscFunctionReturn(0);
244abadfa0fSMatthew G. Knepley }
245abadfa0fSMatthew G. Knepley 
2469371c9d4SSatish Balay static PetscErrorCode TSReset_Mimex(TS ts) {
247abadfa0fSMatthew G. Knepley   TS_Mimex *mimex = (TS_Mimex *)ts->data;
248abadfa0fSMatthew G. Knepley 
249abadfa0fSMatthew G. Knepley   PetscFunctionBegin;
2509566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&mimex->update));
2519566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&mimex->Xdot));
252abadfa0fSMatthew G. Knepley   PetscFunctionReturn(0);
253abadfa0fSMatthew G. Knepley }
254abadfa0fSMatthew G. Knepley 
2559371c9d4SSatish Balay static PetscErrorCode TSDestroy_Mimex(TS ts) {
256abadfa0fSMatthew G. Knepley   PetscFunctionBegin;
2579566063dSJacob Faibussowitsch   PetscCall(TSReset_Mimex(ts));
2589566063dSJacob Faibussowitsch   PetscCall(PetscFree(ts->data));
259abadfa0fSMatthew G. Knepley   PetscFunctionReturn(0);
260abadfa0fSMatthew G. Knepley }
261abadfa0fSMatthew G. Knepley /*------------------------------------------------------------*/
262abadfa0fSMatthew G. Knepley 
2639371c9d4SSatish Balay static PetscErrorCode TSSetFromOptions_Mimex(TS ts, PetscOptionItems *PetscOptionsObject) {
26418c55e3fSMatthew G. Knepley   TS_Mimex *mimex = (TS_Mimex *)ts->data;
26518c55e3fSMatthew G. Knepley 
266abadfa0fSMatthew G. Knepley   PetscFunctionBegin;
267d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "MIMEX ODE solver options");
2689371c9d4SSatish Balay   { PetscCall(PetscOptionsInt("-ts_mimex_version", "Algorithm version", "TSMimexSetVersion", mimex->version, &mimex->version, NULL)); }
269d0609cedSBarry Smith   PetscOptionsHeadEnd();
270abadfa0fSMatthew G. Knepley   PetscFunctionReturn(0);
271abadfa0fSMatthew G. Knepley }
272abadfa0fSMatthew G. Knepley 
2739371c9d4SSatish Balay static PetscErrorCode TSView_Mimex(TS ts, PetscViewer viewer) {
2745bf398f3SMatthew G. Knepley   TS_Mimex *mimex = (TS_Mimex *)ts->data;
2755bf398f3SMatthew G. Knepley   PetscBool iascii;
2765bf398f3SMatthew G. Knepley 
277abadfa0fSMatthew G. Knepley   PetscFunctionBegin;
2789566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
27948a46eb9SPierre Jolivet   if (iascii) PetscCall(PetscViewerASCIIPrintf(viewer, "  Version = %" PetscInt_FMT "\n", mimex->version));
280abadfa0fSMatthew G. Knepley   PetscFunctionReturn(0);
281abadfa0fSMatthew G. Knepley }
282abadfa0fSMatthew G. Knepley 
2839371c9d4SSatish Balay static PetscErrorCode TSInterpolate_Mimex(TS ts, PetscReal t, Vec X) {
284abadfa0fSMatthew G. Knepley   PetscReal alpha = (ts->ptime - t) / ts->time_step;
285abadfa0fSMatthew G. Knepley 
286abadfa0fSMatthew G. Knepley   PetscFunctionBegin;
2879566063dSJacob Faibussowitsch   PetscCall(VecAXPBY(ts->vec_sol, 1.0 - alpha, alpha, X));
288abadfa0fSMatthew G. Knepley   PetscFunctionReturn(0);
289abadfa0fSMatthew G. Knepley }
290abadfa0fSMatthew G. Knepley 
2919371c9d4SSatish Balay static PetscErrorCode TSComputeLinearStability_Mimex(TS ts, PetscReal xr, PetscReal xi, PetscReal *yr, PetscReal *yi) {
292abadfa0fSMatthew G. Knepley   PetscFunctionBegin;
293abadfa0fSMatthew G. Knepley   *yr = 1.0 + xr;
294abadfa0fSMatthew G. Knepley   *yi = xi;
295abadfa0fSMatthew G. Knepley   PetscFunctionReturn(0);
296abadfa0fSMatthew G. Knepley }
297abadfa0fSMatthew G. Knepley /* ------------------------------------------------------------ */
298abadfa0fSMatthew G. Knepley 
299abadfa0fSMatthew G. Knepley /*MC
300abadfa0fSMatthew G. Knepley       TSMIMEX - ODE solver using the explicit forward Mimex method
301abadfa0fSMatthew G. Knepley 
302abadfa0fSMatthew G. Knepley   Level: beginner
303abadfa0fSMatthew G. Knepley 
304db781477SPatrick Sanan .seealso: `TSCreate()`, `TS`, `TSSetType()`, `TSBEULER`
305abadfa0fSMatthew G. Knepley 
306abadfa0fSMatthew G. Knepley M*/
3079371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode TSCreate_Mimex(TS ts) {
308abadfa0fSMatthew G. Knepley   TS_Mimex *mimex;
309abadfa0fSMatthew G. Knepley 
310abadfa0fSMatthew G. Knepley   PetscFunctionBegin;
311abadfa0fSMatthew G. Knepley   ts->ops->setup           = TSSetUp_Mimex;
312abadfa0fSMatthew G. Knepley   ts->ops->step            = TSStep_Mimex;
313abadfa0fSMatthew G. Knepley   ts->ops->reset           = TSReset_Mimex;
314abadfa0fSMatthew G. Knepley   ts->ops->destroy         = TSDestroy_Mimex;
315abadfa0fSMatthew G. Knepley   ts->ops->setfromoptions  = TSSetFromOptions_Mimex;
316abadfa0fSMatthew G. Knepley   ts->ops->view            = TSView_Mimex;
317abadfa0fSMatthew G. Knepley   ts->ops->interpolate     = TSInterpolate_Mimex;
318abadfa0fSMatthew G. Knepley   ts->ops->linearstability = TSComputeLinearStability_Mimex;
319abadfa0fSMatthew G. Knepley   ts->ops->snesfunction    = SNESTSFormFunction_Mimex;
320abadfa0fSMatthew G. Knepley   ts->ops->snesjacobian    = SNESTSFormJacobian_Mimex;
3212ffb9264SLisandro Dalcin   ts->default_adapt_type   = TSADAPTNONE;
322abadfa0fSMatthew G. Knepley 
323*4dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&mimex));
324abadfa0fSMatthew G. Knepley   ts->data = (void *)mimex;
325fdc0a3ceSMatthew G. Knepley 
326fdc0a3ceSMatthew G. Knepley   mimex->version = 1;
327abadfa0fSMatthew G. Knepley   PetscFunctionReturn(0);
328abadfa0fSMatthew G. Knepley }
329