xref: /petsc/src/ts/utils/tsconvest.c (revision f2ed2dc71a2ab9ffda85eae8afa0cbea9ed570de)
1900f6b5bSMatthew G. Knepley #include <petscconvest.h>            /*I "petscconvest.h" I*/
2900f6b5bSMatthew G. Knepley #include <petscts.h>
3*f2ed2dc7SMatthew G. Knepley #include <petscdmplex.h>
4900f6b5bSMatthew G. Knepley 
5900f6b5bSMatthew G. Knepley #include <petsc/private/petscconvestimpl.h>
6900f6b5bSMatthew G. Knepley 
7900f6b5bSMatthew G. Knepley static PetscErrorCode PetscConvEstSetTS_Private(PetscConvEst ce, PetscObject solver)
8900f6b5bSMatthew G. Knepley {
9900f6b5bSMatthew G. Knepley   PetscClassId   id;
10900f6b5bSMatthew G. Knepley   PetscErrorCode ierr;
11900f6b5bSMatthew G. Knepley 
12900f6b5bSMatthew G. Knepley   PetscFunctionBegin;
13900f6b5bSMatthew G. Knepley   ierr = PetscObjectGetClassId(ce->solver, &id);CHKERRQ(ierr);
14900f6b5bSMatthew G. Knepley   if (id != TS_CLASSID) SETERRQ(PetscObjectComm((PetscObject) ce), PETSC_ERR_ARG_WRONG, "Solver was not a TS");
15900f6b5bSMatthew G. Knepley   ierr = TSGetDM((TS) ce->solver, &ce->idm);CHKERRQ(ierr);
16900f6b5bSMatthew G. Knepley   PetscFunctionReturn(0);
17900f6b5bSMatthew G. Knepley }
18900f6b5bSMatthew G. Knepley 
19900f6b5bSMatthew G. Knepley static PetscErrorCode PetscConvEstInitGuessTS_Private(PetscConvEst ce, PetscInt r, DM dm, Vec u)
20900f6b5bSMatthew G. Knepley {
21900f6b5bSMatthew G. Knepley   PetscErrorCode ierr;
22900f6b5bSMatthew G. Knepley 
23900f6b5bSMatthew G. Knepley   PetscFunctionBegin;
242e61be88SMatthew G. Knepley   ierr = TSComputeInitialCondition((TS) ce->solver, u);CHKERRQ(ierr);
25900f6b5bSMatthew G. Knepley   PetscFunctionReturn(0);
26900f6b5bSMatthew G. Knepley }
27900f6b5bSMatthew G. Knepley 
28900f6b5bSMatthew G. Knepley static PetscErrorCode PetscConvEstComputeErrorTS_Private(PetscConvEst ce, PetscInt r, DM dm, Vec u, PetscReal errors[])
29900f6b5bSMatthew G. Knepley {
30f2cacb80SMatthew G. Knepley   TS               ts = (TS) ce->solver;
31f2cacb80SMatthew G. Knepley   PetscErrorCode (*exactError)(TS, Vec, Vec);
32900f6b5bSMatthew G. Knepley   PetscErrorCode   ierr;
33900f6b5bSMatthew G. Knepley 
34900f6b5bSMatthew G. Knepley   PetscFunctionBegin;
35f2cacb80SMatthew G. Knepley   ierr = TSGetComputeExactError(ts, &exactError);CHKERRQ(ierr);
36f2cacb80SMatthew G. Knepley   if (exactError) {
37f2cacb80SMatthew G. Knepley     Vec      e;
38f2cacb80SMatthew G. Knepley     PetscInt f;
39f2cacb80SMatthew G. Knepley 
40900f6b5bSMatthew G. Knepley     ierr = VecDuplicate(u, &e);CHKERRQ(ierr);
41f2cacb80SMatthew G. Knepley     ierr = TSComputeExactError(ts, u, e);CHKERRQ(ierr);
42900f6b5bSMatthew G. Knepley     ierr = VecNorm(e, NORM_2, errors);CHKERRQ(ierr);
43f2cacb80SMatthew G. Knepley     for (f = 1; f < ce->Nf; ++f) errors[f] = errors[0];
44900f6b5bSMatthew G. Knepley     ierr = VecDestroy(&e);CHKERRQ(ierr);
45f2cacb80SMatthew G. Knepley   } else {
46f2cacb80SMatthew G. Knepley     PetscReal t;
47f2cacb80SMatthew G. Knepley 
48f2cacb80SMatthew G. Knepley     ierr = TSGetSolveTime(ts, &t);CHKERRQ(ierr);
49f2cacb80SMatthew G. Knepley     ierr = DMComputeL2FieldDiff(dm, t, ce->exactSol, ce->ctxs, u, errors);CHKERRQ(ierr);
50f2cacb80SMatthew G. Knepley   }
51900f6b5bSMatthew G. Knepley   PetscFunctionReturn(0);
52900f6b5bSMatthew G. Knepley }
53900f6b5bSMatthew G. Knepley 
54*f2ed2dc7SMatthew G. Knepley static PetscErrorCode PetscConvEstGetConvRateTS_Temporal_Private(PetscConvEst ce, PetscReal alpha[])
55900f6b5bSMatthew G. Knepley {
56900f6b5bSMatthew G. Knepley   TS             ts = (TS) ce->solver;
57900f6b5bSMatthew G. Knepley   Vec            u;
58900f6b5bSMatthew G. Knepley   PetscReal     *dt, *x, *y, slope, intercept;
59900f6b5bSMatthew G. Knepley   PetscInt       Ns, oNs, Nf = ce->Nf, f, Nr = ce->Nr, r;
60900f6b5bSMatthew G. Knepley   PetscErrorCode ierr;
61900f6b5bSMatthew G. Knepley 
62900f6b5bSMatthew G. Knepley   PetscFunctionBegin;
63900f6b5bSMatthew G. Knepley   ierr = TSGetSolution(ts, &u);CHKERRQ(ierr);
64900f6b5bSMatthew G. Knepley   ierr = PetscMalloc1(Nr+1, &dt);CHKERRQ(ierr);
65900f6b5bSMatthew G. Knepley   ierr = TSGetTimeStep(ts, &dt[0]);CHKERRQ(ierr);
66900f6b5bSMatthew G. Knepley   ierr = TSGetMaxSteps(ts, &oNs);CHKERRQ(ierr);
67900f6b5bSMatthew G. Knepley   Ns   = oNs;
68900f6b5bSMatthew G. Knepley   for (r = 0; r <= Nr; ++r) {
69900f6b5bSMatthew G. Knepley     if (r > 0) {
702e61be88SMatthew G. Knepley       dt[r] = dt[r-1]/ce->r;
712e61be88SMatthew G. Knepley       Ns    = PetscCeilReal(Ns*ce->r);
72900f6b5bSMatthew G. Knepley     }
73900f6b5bSMatthew G. Knepley     ierr = TSSetTime(ts, 0.0);CHKERRQ(ierr);
74900f6b5bSMatthew G. Knepley     ierr = TSSetStepNumber(ts, 0);CHKERRQ(ierr);
75900f6b5bSMatthew G. Knepley     ierr = TSSetTimeStep(ts, dt[r]);CHKERRQ(ierr);
76900f6b5bSMatthew G. Knepley     ierr = TSSetMaxSteps(ts, Ns);CHKERRQ(ierr);
77900f6b5bSMatthew G. Knepley     ierr = PetscConvEstComputeInitialGuess(ce, r, NULL, u);CHKERRQ(ierr);
78900f6b5bSMatthew G. Knepley     ierr = TSSolve(ts, u);CHKERRQ(ierr);
79900f6b5bSMatthew G. Knepley     ierr = PetscLogEventBegin(ce->event, ce, 0, 0, 0);CHKERRQ(ierr);
80f2cacb80SMatthew G. Knepley     ierr = PetscConvEstComputeError(ce, r, ce->idm, u, &ce->errors[r*Nf]);CHKERRQ(ierr);
81900f6b5bSMatthew G. Knepley     ierr = PetscLogEventEnd(ce->event, ce, 0, 0, 0);CHKERRQ(ierr);
82*f2ed2dc7SMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
83900f6b5bSMatthew G. Knepley       ierr = PetscLogEventSetDof(ce->event, f, 1.0/dt[r]);CHKERRQ(ierr);
84900f6b5bSMatthew G. Knepley       ierr = PetscLogEventSetError(ce->event, f, ce->errors[r*Nf+f]);CHKERRQ(ierr);
85900f6b5bSMatthew G. Knepley     }
86f2cacb80SMatthew G. Knepley     /* Monitor */
87f2cacb80SMatthew G. Knepley     ierr = PetscConvEstMonitorDefault(ce, r);CHKERRQ(ierr);
88900f6b5bSMatthew G. Knepley   }
89900f6b5bSMatthew G. Knepley   /* Fit convergence rate */
90900f6b5bSMatthew G. Knepley   if (Nr) {
91900f6b5bSMatthew G. Knepley     ierr = PetscMalloc2(Nr+1, &x, Nr+1, &y);CHKERRQ(ierr);
92900f6b5bSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
93900f6b5bSMatthew G. Knepley       for (r = 0; r <= Nr; ++r) {
94f2cacb80SMatthew G. Knepley         x[r] = PetscLog10Real(dt[r]);
95900f6b5bSMatthew G. Knepley         y[r] = PetscLog10Real(ce->errors[r*Nf+f]);
96900f6b5bSMatthew G. Knepley       }
97900f6b5bSMatthew G. Knepley       ierr = PetscLinearRegression(Nr+1, x, y, &slope, &intercept);CHKERRQ(ierr);
98900f6b5bSMatthew G. Knepley       /* Since lg err = s lg dt + b */
99900f6b5bSMatthew G. Knepley       alpha[f] = slope;
100900f6b5bSMatthew G. Knepley     }
101900f6b5bSMatthew G. Knepley     ierr = PetscFree2(x, y);CHKERRQ(ierr);
102900f6b5bSMatthew G. Knepley   }
103900f6b5bSMatthew G. Knepley   /* Reset solver */
104900f6b5bSMatthew G. Knepley   ierr = TSSetConvergedReason(ts, TS_CONVERGED_ITERATING);CHKERRQ(ierr);
105900f6b5bSMatthew G. Knepley   ierr = TSSetTime(ts, 0.0);CHKERRQ(ierr);
106900f6b5bSMatthew G. Knepley   ierr = TSSetStepNumber(ts, 0);CHKERRQ(ierr);
107900f6b5bSMatthew G. Knepley   ierr = TSSetTimeStep(ts, dt[0]);CHKERRQ(ierr);
108900f6b5bSMatthew G. Knepley   ierr = TSSetMaxSteps(ts, oNs);CHKERRQ(ierr);
109900f6b5bSMatthew G. Knepley   ierr = PetscConvEstComputeInitialGuess(ce, 0, NULL, u);CHKERRQ(ierr);
110900f6b5bSMatthew G. Knepley   ierr = PetscFree(dt);CHKERRQ(ierr);
111900f6b5bSMatthew G. Knepley   PetscFunctionReturn(0);
112900f6b5bSMatthew G. Knepley }
113900f6b5bSMatthew G. Knepley 
114*f2ed2dc7SMatthew G. Knepley static PetscErrorCode PetscConvEstGetConvRateTS_Spatial_Private(PetscConvEst ce, PetscReal alpha[])
115*f2ed2dc7SMatthew G. Knepley {
116*f2ed2dc7SMatthew G. Knepley   TS             ts = (TS) ce->solver;
117*f2ed2dc7SMatthew G. Knepley   Vec            uInitial;
118*f2ed2dc7SMatthew G. Knepley   DM            *dm;
119*f2ed2dc7SMatthew G. Knepley   PetscObject    disc;
120*f2ed2dc7SMatthew G. Knepley   PetscReal     *x, *y, slope, intercept;
121*f2ed2dc7SMatthew G. Knepley   PetscInt      *dof, Nr = ce->Nr, r, Nf = ce->Nf, f, dim, oldlevel, oldnlev;
122*f2ed2dc7SMatthew G. Knepley   void          *ctx;
123*f2ed2dc7SMatthew G. Knepley   PetscErrorCode ierr;
124*f2ed2dc7SMatthew G. Knepley 
125*f2ed2dc7SMatthew G. Knepley   PetscFunctionBegin;
126*f2ed2dc7SMatthew G. Knepley   if (ce->r != 2.0) SETERRQ1(PetscObjectComm((PetscObject) ce), PETSC_ERR_SUP, "Only refinement factor 2 is currently supported (not %g)", (double) ce->r);
127*f2ed2dc7SMatthew G. Knepley   ierr = DMGetDimension(ce->idm, &dim);CHKERRQ(ierr);
128*f2ed2dc7SMatthew G. Knepley   ierr = DMGetApplicationContext(ce->idm, &ctx);CHKERRQ(ierr);
129*f2ed2dc7SMatthew G. Knepley   ierr = DMPlexSetRefinementUniform(ce->idm, PETSC_TRUE);CHKERRQ(ierr);
130*f2ed2dc7SMatthew G. Knepley   ierr = DMGetRefineLevel(ce->idm, &oldlevel);CHKERRQ(ierr);
131*f2ed2dc7SMatthew G. Knepley   ierr = PetscMalloc2((Nr+1), &dm, (Nr+1)*Nf, &dof);CHKERRQ(ierr);
132*f2ed2dc7SMatthew G. Knepley   ierr = TSGetSolution(ts, &uInitial);CHKERRQ(ierr);
133*f2ed2dc7SMatthew G. Knepley   /* Loop over meshes */
134*f2ed2dc7SMatthew G. Knepley   dm[0] = ce->idm;
135*f2ed2dc7SMatthew G. Knepley   for (r = 0; r <= Nr; ++r) {
136*f2ed2dc7SMatthew G. Knepley     Vec           u;
137*f2ed2dc7SMatthew G. Knepley #if defined(PETSC_USE_LOG)
138*f2ed2dc7SMatthew G. Knepley     PetscLogStage stage;
139*f2ed2dc7SMatthew G. Knepley #endif
140*f2ed2dc7SMatthew G. Knepley     char          stageName[PETSC_MAX_PATH_LEN];
141*f2ed2dc7SMatthew G. Knepley     const char   *dmname, *uname;
142*f2ed2dc7SMatthew G. Knepley 
143*f2ed2dc7SMatthew G. Knepley     ierr = PetscSNPrintf(stageName, PETSC_MAX_PATH_LEN-1, "ConvEst Refinement Level %D", r);CHKERRQ(ierr);
144*f2ed2dc7SMatthew G. Knepley     ierr = PetscLogStageRegister(stageName, &stage);CHKERRQ(ierr);
145*f2ed2dc7SMatthew G. Knepley     ierr = PetscLogStagePush(stage);CHKERRQ(ierr);
146*f2ed2dc7SMatthew G. Knepley     if (r > 0) {
147*f2ed2dc7SMatthew G. Knepley       ierr = DMRefine(dm[r-1], MPI_COMM_NULL, &dm[r]);CHKERRQ(ierr);
148*f2ed2dc7SMatthew G. Knepley       ierr = DMSetCoarseDM(dm[r], dm[r-1]);CHKERRQ(ierr);
149*f2ed2dc7SMatthew G. Knepley       ierr = DMCopyTransform(ce->idm, dm[r]);CHKERRQ(ierr);
150*f2ed2dc7SMatthew G. Knepley       ierr = PetscObjectGetName((PetscObject) dm[r-1], &dmname);CHKERRQ(ierr);
151*f2ed2dc7SMatthew G. Knepley       ierr = PetscObjectSetName((PetscObject) dm[r], dmname);CHKERRQ(ierr);
152*f2ed2dc7SMatthew G. Knepley       for (f = 0; f <= Nf; ++f) {
153*f2ed2dc7SMatthew G. Knepley         PetscErrorCode (*nspconstr)(DM, PetscInt, MatNullSpace *);
154*f2ed2dc7SMatthew G. Knepley 
155*f2ed2dc7SMatthew G. Knepley         ierr = DMGetNullSpaceConstructor(dm[r-1], f, &nspconstr);CHKERRQ(ierr);
156*f2ed2dc7SMatthew G. Knepley         ierr = DMSetNullSpaceConstructor(dm[r],   f,  nspconstr);CHKERRQ(ierr);
157*f2ed2dc7SMatthew G. Knepley       }
158*f2ed2dc7SMatthew G. Knepley     }
159*f2ed2dc7SMatthew G. Knepley     ierr = DMViewFromOptions(dm[r], NULL, "-conv_dm_view");CHKERRQ(ierr);
160*f2ed2dc7SMatthew G. Knepley     /* Create solution */
161*f2ed2dc7SMatthew G. Knepley     ierr = DMCreateGlobalVector(dm[r], &u);CHKERRQ(ierr);
162*f2ed2dc7SMatthew G. Knepley     ierr = DMGetField(dm[r], 0, NULL, &disc);CHKERRQ(ierr);
163*f2ed2dc7SMatthew G. Knepley     ierr = PetscObjectGetName(disc, &uname);CHKERRQ(ierr);
164*f2ed2dc7SMatthew G. Knepley     ierr = PetscObjectSetName((PetscObject) u, uname);CHKERRQ(ierr);
165*f2ed2dc7SMatthew G. Knepley     /* Setup solver */
166*f2ed2dc7SMatthew G. Knepley     ierr = TSReset(ts);CHKERRQ(ierr);
167*f2ed2dc7SMatthew G. Knepley     ierr = TSSetDM(ts, dm[r]);CHKERRQ(ierr);
168*f2ed2dc7SMatthew G. Knepley     ierr = DMTSSetBoundaryLocal(dm[r], DMPlexTSComputeBoundary, ctx);CHKERRQ(ierr);
169*f2ed2dc7SMatthew G. Knepley     ierr = DMTSSetIFunctionLocal(dm[r], DMPlexTSComputeIFunctionFEM, ctx);CHKERRQ(ierr);
170*f2ed2dc7SMatthew G. Knepley     ierr = DMTSSetIJacobianLocal(dm[r], DMPlexTSComputeIJacobianFEM, ctx);CHKERRQ(ierr);
171*f2ed2dc7SMatthew G. Knepley     ierr = TSSetTime(ts, 0.0);CHKERRQ(ierr);
172*f2ed2dc7SMatthew G. Knepley     ierr = TSSetStepNumber(ts, 0);CHKERRQ(ierr);
173*f2ed2dc7SMatthew G. Knepley     ierr = TSSetFromOptions(ts);CHKERRQ(ierr);
174*f2ed2dc7SMatthew G. Knepley     /* Create initial guess */
175*f2ed2dc7SMatthew G. Knepley     ierr = PetscConvEstComputeInitialGuess(ce, r, dm[r], u);CHKERRQ(ierr);
176*f2ed2dc7SMatthew G. Knepley     ierr = TSSolve(ts, u);CHKERRQ(ierr);
177*f2ed2dc7SMatthew G. Knepley     ierr = PetscLogEventBegin(ce->event, ce, 0, 0, 0);CHKERRQ(ierr);
178*f2ed2dc7SMatthew G. Knepley     ierr = PetscConvEstComputeError(ce, r, dm[r], u, &ce->errors[r*Nf]);CHKERRQ(ierr);
179*f2ed2dc7SMatthew G. Knepley     ierr = PetscLogEventEnd(ce->event, ce, 0, 0, 0);CHKERRQ(ierr);
180*f2ed2dc7SMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
181*f2ed2dc7SMatthew G. Knepley       PetscSection s, fs;
182*f2ed2dc7SMatthew G. Knepley       PetscInt     lsize;
183*f2ed2dc7SMatthew G. Knepley 
184*f2ed2dc7SMatthew G. Knepley       /* Could use DMGetOutputDM() to add in Dirichlet dofs */
185*f2ed2dc7SMatthew G. Knepley       ierr = DMGetLocalSection(dm[r], &s);CHKERRQ(ierr);
186*f2ed2dc7SMatthew G. Knepley       ierr = PetscSectionGetField(s, f, &fs);CHKERRQ(ierr);
187*f2ed2dc7SMatthew G. Knepley       ierr = PetscSectionGetConstrainedStorageSize(fs, &lsize);CHKERRQ(ierr);
188*f2ed2dc7SMatthew G. Knepley       ierr = MPI_Allreduce(&lsize, &dof[r*Nf+f], 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject) ts));CHKERRQ(ierr);
189*f2ed2dc7SMatthew G. Knepley       ierr = PetscLogEventSetDof(ce->event, f, dof[r*Nf+f]);CHKERRQ(ierr);
190*f2ed2dc7SMatthew G. Knepley       ierr = PetscLogEventSetError(ce->event, f, ce->errors[r*Nf+f]);CHKERRQ(ierr);
191*f2ed2dc7SMatthew G. Knepley     }
192*f2ed2dc7SMatthew G. Knepley     /* Monitor */
193*f2ed2dc7SMatthew G. Knepley     ierr = PetscConvEstMonitorDefault(ce, r);CHKERRQ(ierr);
194*f2ed2dc7SMatthew G. Knepley     if (!r) {
195*f2ed2dc7SMatthew G. Knepley       /* PCReset() does not wipe out the level structure */
196*f2ed2dc7SMatthew G. Knepley       SNES snes;
197*f2ed2dc7SMatthew G. Knepley       KSP  ksp;
198*f2ed2dc7SMatthew G. Knepley       PC   pc;
199*f2ed2dc7SMatthew G. Knepley 
200*f2ed2dc7SMatthew G. Knepley       ierr = TSGetSNES(ts, &snes);CHKERRQ(ierr);
201*f2ed2dc7SMatthew G. Knepley       ierr = SNESGetKSP(snes, &ksp);CHKERRQ(ierr);
202*f2ed2dc7SMatthew G. Knepley       ierr = KSPGetPC(ksp, &pc);CHKERRQ(ierr);
203*f2ed2dc7SMatthew G. Knepley       ierr = PCMGGetLevels(pc, &oldnlev);CHKERRQ(ierr);
204*f2ed2dc7SMatthew G. Knepley     }
205*f2ed2dc7SMatthew G. Knepley     /* Cleanup */
206*f2ed2dc7SMatthew G. Knepley     ierr = VecDestroy(&u);CHKERRQ(ierr);
207*f2ed2dc7SMatthew G. Knepley     ierr = PetscLogStagePop();CHKERRQ(ierr);
208*f2ed2dc7SMatthew G. Knepley   }
209*f2ed2dc7SMatthew G. Knepley   for (r = 1; r <= Nr; ++r) {
210*f2ed2dc7SMatthew G. Knepley     ierr = DMDestroy(&dm[r]);CHKERRQ(ierr);
211*f2ed2dc7SMatthew G. Knepley   }
212*f2ed2dc7SMatthew G. Knepley   /* Fit convergence rate */
213*f2ed2dc7SMatthew G. Knepley   ierr = PetscMalloc2(Nr+1, &x, Nr+1, &y);CHKERRQ(ierr);
214*f2ed2dc7SMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
215*f2ed2dc7SMatthew G. Knepley     for (r = 0; r <= Nr; ++r) {
216*f2ed2dc7SMatthew G. Knepley       x[r] = PetscLog10Real(dof[r*Nf+f]);
217*f2ed2dc7SMatthew G. Knepley       y[r] = PetscLog10Real(ce->errors[r*Nf+f]);
218*f2ed2dc7SMatthew G. Knepley     }
219*f2ed2dc7SMatthew G. Knepley     ierr = PetscLinearRegression(Nr+1, x, y, &slope, &intercept);CHKERRQ(ierr);
220*f2ed2dc7SMatthew G. Knepley     /* Since h^{-dim} = N, lg err = s lg N + b = -s dim lg h + b */
221*f2ed2dc7SMatthew G. Knepley     alpha[f] = -slope * dim;
222*f2ed2dc7SMatthew G. Knepley   }
223*f2ed2dc7SMatthew G. Knepley   ierr = PetscFree2(x, y);CHKERRQ(ierr);
224*f2ed2dc7SMatthew G. Knepley   ierr = PetscFree2(dm, dof);CHKERRQ(ierr);
225*f2ed2dc7SMatthew G. Knepley   /* Restore solver */
226*f2ed2dc7SMatthew G. Knepley   ierr = TSReset(ts);CHKERRQ(ierr);
227*f2ed2dc7SMatthew G. Knepley   {
228*f2ed2dc7SMatthew G. Knepley     /* PCReset() does not wipe out the level structure */
229*f2ed2dc7SMatthew G. Knepley     SNES snes;
230*f2ed2dc7SMatthew G. Knepley     KSP  ksp;
231*f2ed2dc7SMatthew G. Knepley     PC   pc;
232*f2ed2dc7SMatthew G. Knepley 
233*f2ed2dc7SMatthew G. Knepley     ierr = TSGetSNES(ts, &snes);CHKERRQ(ierr);
234*f2ed2dc7SMatthew G. Knepley     ierr = SNESGetKSP(snes, &ksp);CHKERRQ(ierr);
235*f2ed2dc7SMatthew G. Knepley     ierr = KSPGetPC(ksp, &pc);CHKERRQ(ierr);
236*f2ed2dc7SMatthew G. Knepley     ierr = PCMGSetLevels(pc, oldnlev, NULL);CHKERRQ(ierr);
237*f2ed2dc7SMatthew G. Knepley     ierr = DMSetRefineLevel(ce->idm, oldlevel);CHKERRQ(ierr); /* The damn DMCoarsen() calls in PCMG can reset this */
238*f2ed2dc7SMatthew G. Knepley   }
239*f2ed2dc7SMatthew G. Knepley   ierr = TSSetDM(ts, ce->idm);CHKERRQ(ierr);
240*f2ed2dc7SMatthew G. Knepley   ierr = DMTSSetBoundaryLocal(ce->idm, DMPlexTSComputeBoundary, ctx);CHKERRQ(ierr);
241*f2ed2dc7SMatthew G. Knepley   ierr = DMTSSetIFunctionLocal(ce->idm, DMPlexTSComputeIFunctionFEM, ctx);CHKERRQ(ierr);
242*f2ed2dc7SMatthew G. Knepley   ierr = DMTSSetIJacobianLocal(ce->idm, DMPlexTSComputeIJacobianFEM, ctx);CHKERRQ(ierr);
243*f2ed2dc7SMatthew G. Knepley   ierr = TSSetConvergedReason(ts, TS_CONVERGED_ITERATING);CHKERRQ(ierr);
244*f2ed2dc7SMatthew G. Knepley   ierr = TSSetTime(ts, 0.0);CHKERRQ(ierr);
245*f2ed2dc7SMatthew G. Knepley   ierr = TSSetStepNumber(ts, 0);CHKERRQ(ierr);
246*f2ed2dc7SMatthew G. Knepley   ierr = TSSetFromOptions(ts);CHKERRQ(ierr);
247*f2ed2dc7SMatthew G. Knepley   ierr = TSSetSolution(ts, uInitial);CHKERRQ(ierr);
248*f2ed2dc7SMatthew G. Knepley   ierr = PetscConvEstComputeInitialGuess(ce, 0, NULL, uInitial);CHKERRQ(ierr);
249*f2ed2dc7SMatthew G. Knepley   PetscFunctionReturn(0);
250*f2ed2dc7SMatthew G. Knepley }
251*f2ed2dc7SMatthew G. Knepley 
252*f2ed2dc7SMatthew G. Knepley PetscErrorCode PetscConvEstUseTS(PetscConvEst ce, PetscBool checkTemporal)
253900f6b5bSMatthew G. Knepley {
254900f6b5bSMatthew G. Knepley   PetscFunctionBegin;
255900f6b5bSMatthew G. Knepley   PetscValidHeaderSpecific(ce, PETSC_OBJECT_CLASSID, 1);
256900f6b5bSMatthew G. Knepley   ce->ops->setsolver     = PetscConvEstSetTS_Private;
257900f6b5bSMatthew G. Knepley   ce->ops->initguess     = PetscConvEstInitGuessTS_Private;
258900f6b5bSMatthew G. Knepley   ce->ops->computeerror  = PetscConvEstComputeErrorTS_Private;
259*f2ed2dc7SMatthew G. Knepley   if (checkTemporal) {
260*f2ed2dc7SMatthew G. Knepley     ce->ops->getconvrate = PetscConvEstGetConvRateTS_Temporal_Private;
261*f2ed2dc7SMatthew G. Knepley   } else {
262*f2ed2dc7SMatthew G. Knepley     ce->ops->getconvrate = PetscConvEstGetConvRateTS_Spatial_Private;
263*f2ed2dc7SMatthew G. Knepley   }
264900f6b5bSMatthew G. Knepley   PetscFunctionReturn(0);
265900f6b5bSMatthew G. Knepley }
266