xref: /petsc/src/snes/utils/convest.c (revision 2cae373cf2fea36bded87db9c8283e10aa2afe9c)
16af0ca60SMatthew G. Knepley #include <petscconvest.h>            /*I "petscconvest.h" I*/
26af0ca60SMatthew G. Knepley #include <petscdmplex.h>
36af0ca60SMatthew G. Knepley #include <petscds.h>
46af0ca60SMatthew G. Knepley #include <petscblaslapack.h>
56af0ca60SMatthew G. Knepley 
66af0ca60SMatthew G. Knepley #include <petsc/private/petscconvestimpl.h>
76af0ca60SMatthew G. Knepley 
86af0ca60SMatthew G. Knepley static PetscErrorCode zero_private(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, void *ctx)
96af0ca60SMatthew G. Knepley {
106af0ca60SMatthew G. Knepley   PetscInt c;
116af0ca60SMatthew G. Knepley   for (c = 0; c < Nc; ++c) u[c] = 0.0;
126af0ca60SMatthew G. Knepley   return 0;
136af0ca60SMatthew G. Knepley }
146af0ca60SMatthew G. Knepley 
156af0ca60SMatthew G. Knepley 
166af0ca60SMatthew G. Knepley /*@
176af0ca60SMatthew G. Knepley   PetscConvEstCreate - Create a PetscConvEst object
186af0ca60SMatthew G. Knepley 
196af0ca60SMatthew G. Knepley   Collective on MPI_Comm
206af0ca60SMatthew G. Knepley 
216af0ca60SMatthew G. Knepley   Input Parameter:
226af0ca60SMatthew G. Knepley . comm - The communicator for the PetscConvEst object
236af0ca60SMatthew G. Knepley 
246af0ca60SMatthew G. Knepley   Output Parameter:
256af0ca60SMatthew G. Knepley . ce   - The PetscConvEst object
266af0ca60SMatthew G. Knepley 
276af0ca60SMatthew G. Knepley   Level: beginner
286af0ca60SMatthew G. Knepley 
296af0ca60SMatthew G. Knepley .keywords: PetscConvEst, convergence, create
306af0ca60SMatthew G. Knepley .seealso: PetscConvEstDestroy(), PetscConvEstGetConvRate()
316af0ca60SMatthew G. Knepley @*/
326af0ca60SMatthew G. Knepley PetscErrorCode PetscConvEstCreate(MPI_Comm comm, PetscConvEst *ce)
336af0ca60SMatthew G. Knepley {
346af0ca60SMatthew G. Knepley   PetscErrorCode ierr;
356af0ca60SMatthew G. Knepley 
366af0ca60SMatthew G. Knepley   PetscFunctionBegin;
376af0ca60SMatthew G. Knepley   PetscValidPointer(ce, 2);
386af0ca60SMatthew G. Knepley   ierr = PetscSysInitializePackage();CHKERRQ(ierr);
396af0ca60SMatthew G. Knepley   ierr = PetscHeaderCreate(*ce, PETSC_OBJECT_CLASSID, "PetscConvEst", "ConvergenceEstimator", "SNES", comm, PetscConvEstDestroy, PetscConvEstView);CHKERRQ(ierr);
406af0ca60SMatthew G. Knepley   (*ce)->monitor = PETSC_FALSE;
416af0ca60SMatthew G. Knepley   (*ce)->Nr      = 4;
426af0ca60SMatthew G. Knepley   PetscFunctionReturn(0);
436af0ca60SMatthew G. Knepley }
446af0ca60SMatthew G. Knepley 
456af0ca60SMatthew G. Knepley /*@
466af0ca60SMatthew G. Knepley   PetscConvEstDestroy - Destroys a PetscConvEst object
476af0ca60SMatthew G. Knepley 
486af0ca60SMatthew G. Knepley   Collective on PetscConvEst
496af0ca60SMatthew G. Knepley 
506af0ca60SMatthew G. Knepley   Input Parameter:
516af0ca60SMatthew G. Knepley . ce - The PetscConvEst object
526af0ca60SMatthew G. Knepley 
536af0ca60SMatthew G. Knepley   Level: beginner
546af0ca60SMatthew G. Knepley 
556af0ca60SMatthew G. Knepley .keywords: PetscConvEst, convergence, destroy
566af0ca60SMatthew G. Knepley .seealso: PetscConvEstCreate(), PetscConvEstGetConvRate()
576af0ca60SMatthew G. Knepley @*/
586af0ca60SMatthew G. Knepley PetscErrorCode PetscConvEstDestroy(PetscConvEst *ce)
596af0ca60SMatthew G. Knepley {
606af0ca60SMatthew G. Knepley   PetscErrorCode ierr;
616af0ca60SMatthew G. Knepley 
626af0ca60SMatthew G. Knepley   PetscFunctionBegin;
636af0ca60SMatthew G. Knepley   if (!*ce) PetscFunctionReturn(0);
646af0ca60SMatthew G. Knepley   PetscValidHeaderSpecific((*ce),PETSC_OBJECT_CLASSID,1);
656af0ca60SMatthew G. Knepley   if (--((PetscObject)(*ce))->refct > 0) {
666af0ca60SMatthew G. Knepley     *ce = NULL;
676af0ca60SMatthew G. Knepley     PetscFunctionReturn(0);
686af0ca60SMatthew G. Knepley   }
696af0ca60SMatthew G. Knepley   ierr = PetscFree2((*ce)->initGuess, (*ce)->exactSol);CHKERRQ(ierr);
706af0ca60SMatthew G. Knepley   ierr = PetscFree((*ce)->errors);CHKERRQ(ierr);
716af0ca60SMatthew G. Knepley   ierr = PetscHeaderDestroy(ce);CHKERRQ(ierr);
726af0ca60SMatthew G. Knepley   PetscFunctionReturn(0);
736af0ca60SMatthew G. Knepley }
746af0ca60SMatthew G. Knepley 
756af0ca60SMatthew G. Knepley /*@
766af0ca60SMatthew G. Knepley   PetscConvEstSetFromOptions - Sets a PetscConvEst object from options
776af0ca60SMatthew G. Knepley 
786af0ca60SMatthew G. Knepley   Collective on PetscConvEst
796af0ca60SMatthew G. Knepley 
806af0ca60SMatthew G. Knepley   Input Parameters:
816af0ca60SMatthew G. Knepley . ce - The PetscConvEst object
826af0ca60SMatthew G. Knepley 
836af0ca60SMatthew G. Knepley   Level: beginner
846af0ca60SMatthew G. Knepley 
856af0ca60SMatthew G. Knepley .keywords: PetscConvEst, convergence, options
866af0ca60SMatthew G. Knepley .seealso: PetscConvEstCreate(), PetscConvEstGetConvRate()
876af0ca60SMatthew G. Knepley @*/
886af0ca60SMatthew G. Knepley PetscErrorCode PetscConvEstSetFromOptions(PetscConvEst ce)
896af0ca60SMatthew G. Knepley {
906af0ca60SMatthew G. Knepley   PetscErrorCode ierr;
916af0ca60SMatthew G. Knepley 
926af0ca60SMatthew G. Knepley   PetscFunctionBegin;
936af0ca60SMatthew G. Knepley   ierr = PetscOptionsBegin(PetscObjectComm((PetscObject) ce), "", "Convergence Estimator Options", "PetscConvEst");CHKERRQ(ierr);
946af0ca60SMatthew G. Knepley   ierr = PetscOptionsInt("-num_refine", "The number of refinements for the convergence check", "PetscConvEst", ce->Nr, &ce->Nr, NULL);CHKERRQ(ierr);
956af0ca60SMatthew G. Knepley   ierr = PetscOptionsEnd();
966af0ca60SMatthew G. Knepley   PetscFunctionReturn(0);
976af0ca60SMatthew G. Knepley }
986af0ca60SMatthew G. Knepley 
996af0ca60SMatthew G. Knepley /*@
1006af0ca60SMatthew G. Knepley   PetscConvEstView - Views a PetscConvEst object
1016af0ca60SMatthew G. Knepley 
1026af0ca60SMatthew G. Knepley   Collective on PetscConvEst
1036af0ca60SMatthew G. Knepley 
1046af0ca60SMatthew G. Knepley   Input Parameters:
1056af0ca60SMatthew G. Knepley + ce     - The PetscConvEst object
1066af0ca60SMatthew G. Knepley - viewer - The PetscViewer object
1076af0ca60SMatthew G. Knepley 
1086af0ca60SMatthew G. Knepley   Level: beginner
1096af0ca60SMatthew G. Knepley 
1106af0ca60SMatthew G. Knepley .keywords: PetscConvEst, convergence, view
1116af0ca60SMatthew G. Knepley .seealso: PetscConvEstCreate(), PetscConvEstGetConvRate()
1126af0ca60SMatthew G. Knepley @*/
1136af0ca60SMatthew G. Knepley PetscErrorCode PetscConvEstView(PetscConvEst ce, PetscViewer viewer)
1146af0ca60SMatthew G. Knepley {
1156af0ca60SMatthew G. Knepley   PetscErrorCode ierr;
1166af0ca60SMatthew G. Knepley 
1176af0ca60SMatthew G. Knepley   PetscFunctionBegin;
1186af0ca60SMatthew G. Knepley   ierr = PetscObjectPrintClassNamePrefixType((PetscObject) ce, viewer);CHKERRQ(ierr);
1196af0ca60SMatthew G. Knepley   ierr = PetscViewerASCIIPrintf(viewer, "ConvEst with %D levels\n", ce->Nr+1);CHKERRQ(ierr);
1206af0ca60SMatthew G. Knepley   PetscFunctionReturn(0);
1216af0ca60SMatthew G. Knepley }
1226af0ca60SMatthew G. Knepley 
1236af0ca60SMatthew G. Knepley /*@
1246af0ca60SMatthew G. Knepley   PetscConvEstGetSolver - Gets the solver used to produce discrete solutions
1256af0ca60SMatthew G. Knepley 
1266af0ca60SMatthew G. Knepley   Not collective
1276af0ca60SMatthew G. Knepley 
1286af0ca60SMatthew G. Knepley   Input Parameter:
1296af0ca60SMatthew G. Knepley . ce   - The PetscConvEst object
1306af0ca60SMatthew G. Knepley 
1316af0ca60SMatthew G. Knepley   Output Parameter:
1326af0ca60SMatthew G. Knepley . snes - The solver
1336af0ca60SMatthew G. Knepley 
1346af0ca60SMatthew G. Knepley   Level: intermediate
1356af0ca60SMatthew G. Knepley 
1366af0ca60SMatthew G. Knepley .keywords: PetscConvEst, convergence
1376af0ca60SMatthew G. Knepley .seealso: PetscConvEstSetSolver(), PetscConvEstCreate(), PetscConvEstGetConvRate()
1386af0ca60SMatthew G. Knepley @*/
1396af0ca60SMatthew G. Knepley PetscErrorCode PetscConvEstGetSolver(PetscConvEst ce, SNES *snes)
1406af0ca60SMatthew G. Knepley {
1416af0ca60SMatthew G. Knepley   PetscFunctionBegin;
1426af0ca60SMatthew G. Knepley   PetscValidHeaderSpecific(ce, PETSC_OBJECT_CLASSID, 1);
1436af0ca60SMatthew G. Knepley   PetscValidPointer(snes, 2);
1446af0ca60SMatthew G. Knepley   *snes = ce->snes;
1456af0ca60SMatthew G. Knepley   PetscFunctionReturn(0);
1466af0ca60SMatthew G. Knepley }
1476af0ca60SMatthew G. Knepley 
1486af0ca60SMatthew G. Knepley /*@
1496af0ca60SMatthew G. Knepley   PetscConvEstSetSolver - Sets the solver used to produce discrete solutions
1506af0ca60SMatthew G. Knepley 
1516af0ca60SMatthew G. Knepley   Not collective
1526af0ca60SMatthew G. Knepley 
1536af0ca60SMatthew G. Knepley   Input Parameters:
1546af0ca60SMatthew G. Knepley + ce   - The PetscConvEst object
1556af0ca60SMatthew G. Knepley - snes - The solver
1566af0ca60SMatthew G. Knepley 
1576af0ca60SMatthew G. Knepley   Level: intermediate
1586af0ca60SMatthew G. Knepley 
1596af0ca60SMatthew G. Knepley   Note: The solver MUST have an attached DM/DS, so that we know the exact solution
1606af0ca60SMatthew G. Knepley 
1616af0ca60SMatthew G. Knepley .keywords: PetscConvEst, convergence
1626af0ca60SMatthew G. Knepley .seealso: PetscConvEstGetSolver(), PetscConvEstCreate(), PetscConvEstGetConvRate()
1636af0ca60SMatthew G. Knepley @*/
1646af0ca60SMatthew G. Knepley PetscErrorCode PetscConvEstSetSolver(PetscConvEst ce, SNES snes)
1656af0ca60SMatthew G. Knepley {
1666af0ca60SMatthew G. Knepley   PetscErrorCode ierr;
1676af0ca60SMatthew G. Knepley 
1686af0ca60SMatthew G. Knepley   PetscFunctionBegin;
1696af0ca60SMatthew G. Knepley   PetscValidHeaderSpecific(ce, PETSC_OBJECT_CLASSID, 1);
1706af0ca60SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 2);
1716af0ca60SMatthew G. Knepley   ce->snes = snes;
1726af0ca60SMatthew G. Knepley   ierr = SNESGetDM(ce->snes, &ce->idm);CHKERRQ(ierr);
1736af0ca60SMatthew G. Knepley   PetscFunctionReturn(0);
1746af0ca60SMatthew G. Knepley }
1756af0ca60SMatthew G. Knepley 
1766af0ca60SMatthew G. Knepley /*@
1776af0ca60SMatthew G. Knepley   PetscConvEstSetUp - After the solver is specified, we create structures for estimating convergence
1786af0ca60SMatthew G. Knepley 
1796af0ca60SMatthew G. Knepley   Collective on PetscConvEst
1806af0ca60SMatthew G. Knepley 
1816af0ca60SMatthew G. Knepley   Input Parameters:
1826af0ca60SMatthew G. Knepley . ce - The PetscConvEst object
1836af0ca60SMatthew G. Knepley 
1846af0ca60SMatthew G. Knepley   Level: beginner
1856af0ca60SMatthew G. Knepley 
1866af0ca60SMatthew G. Knepley .keywords: PetscConvEst, convergence, setup
1876af0ca60SMatthew G. Knepley .seealso: PetscConvEstCreate(), PetscConvEstGetConvRate()
1886af0ca60SMatthew G. Knepley @*/
1890955ed61SMatthew G. Knepley PetscErrorCode PetscConvEstSetUp(PetscConvEst ce)
1906af0ca60SMatthew G. Knepley {
1916af0ca60SMatthew G. Knepley   PetscDS        prob;
1926af0ca60SMatthew G. Knepley   PetscInt       f;
1936af0ca60SMatthew G. Knepley   PetscErrorCode ierr;
1946af0ca60SMatthew G. Knepley 
1956af0ca60SMatthew G. Knepley   PetscFunctionBegin;
1966af0ca60SMatthew G. Knepley   ierr = DMGetDS(ce->idm, &prob);CHKERRQ(ierr);
1976af0ca60SMatthew G. Knepley   ierr = PetscDSGetNumFields(prob, &ce->Nf);CHKERRQ(ierr);
1986af0ca60SMatthew G. Knepley   ierr = PetscMalloc1((ce->Nr+1)*ce->Nf, &ce->errors);CHKERRQ(ierr);
1996af0ca60SMatthew G. Knepley   ierr = PetscMalloc2(ce->Nf, &ce->initGuess, ce->Nf, &ce->exactSol);CHKERRQ(ierr);
2006af0ca60SMatthew G. Knepley   for (f = 0; f < ce->Nf; ++f) ce->initGuess[f] = zero_private;
2016af0ca60SMatthew G. Knepley   for (f = 0; f < ce->Nf; ++f) {
2026af0ca60SMatthew G. Knepley     ierr = PetscDSGetExactSolution(prob, f, &ce->exactSol[f]);CHKERRQ(ierr);
2036af0ca60SMatthew G. Knepley     if (!ce->exactSol[f]) SETERRQ1(PetscObjectComm((PetscObject) ce), PETSC_ERR_ARG_WRONG, "DS must contain exact solution functions in order to estimate convergence, missing for field %D", f);
2046af0ca60SMatthew G. Knepley   }
2056af0ca60SMatthew G. Knepley   PetscFunctionReturn(0);
2066af0ca60SMatthew G. Knepley }
2076af0ca60SMatthew G. Knepley 
2086af0ca60SMatthew G. Knepley static PetscErrorCode PetscConvEstLinearRegression_Private(PetscConvEst ce, PetscInt n, const PetscReal x[], const PetscReal y[], PetscReal *slope, PetscReal *intercept)
2096af0ca60SMatthew G. Knepley {
21028cc7b48SMatthew G. Knepley   PetscScalar    H[4];
21128cc7b48SMatthew G. Knepley   PetscReal     *X, *Y, beta[2];
2126af0ca60SMatthew G. Knepley   PetscInt       i, j, k;
2136af0ca60SMatthew G. Knepley   PetscErrorCode ierr;
2146af0ca60SMatthew G. Knepley 
2156af0ca60SMatthew G. Knepley   PetscFunctionBegin;
2168fa78361SMatthew G. Knepley   *slope = *intercept = 0.0;
2176af0ca60SMatthew G. Knepley   ierr = PetscMalloc2(n*2, &X, n*2, &Y);CHKERRQ(ierr);
2186af0ca60SMatthew G. Knepley   for (k = 0; k < n; ++k) {
2196af0ca60SMatthew G. Knepley     /* X[n,2] = [1, x] */
2206af0ca60SMatthew G. Knepley     X[k*2+0] = 1.0;
2216af0ca60SMatthew G. Knepley     X[k*2+1] = x[k];
2226af0ca60SMatthew G. Knepley   }
2236af0ca60SMatthew G. Knepley   /* H = X^T X */
2246af0ca60SMatthew G. Knepley   for (i = 0; i < 2; ++i) {
2256af0ca60SMatthew G. Knepley     for (j = 0; j < 2; ++j) {
2266af0ca60SMatthew G. Knepley       H[i*2+j] = 0.0;
2276af0ca60SMatthew G. Knepley       for (k = 0; k < n; ++k) {
2286af0ca60SMatthew G. Knepley         H[i*2+j] += X[k*2+i] * X[k*2+j];
2296af0ca60SMatthew G. Knepley       }
2306af0ca60SMatthew G. Knepley     }
2316af0ca60SMatthew G. Knepley   }
2326af0ca60SMatthew G. Knepley   /* H = (X^T X)^{-1} */
2336af0ca60SMatthew G. Knepley   {
2346af0ca60SMatthew G. Knepley     PetscBLASInt two = 2, ipiv[2], info;
2350955ed61SMatthew G. Knepley     PetscScalar  work[2];
2366af0ca60SMatthew G. Knepley 
2376af0ca60SMatthew G. Knepley     ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2386af0ca60SMatthew G. Knepley     PetscStackCallBLAS("LAPACKgetrf", LAPACKgetrf_(&two, &two, H, &two, ipiv, &info));
2396af0ca60SMatthew G. Knepley     PetscStackCallBLAS("LAPACKgetri", LAPACKgetri_(&two, H, &two, ipiv, work, &two, &info));
2406af0ca60SMatthew G. Knepley     ierr = PetscFPTrapPop();CHKERRQ(ierr);
2416af0ca60SMatthew G. Knepley   }
2426af0ca60SMatthew G. Knepley     /* Y = H X^T */
2436af0ca60SMatthew G. Knepley   for (i = 0; i < 2; ++i) {
2446af0ca60SMatthew G. Knepley     for (k = 0; k < n; ++k) {
2456af0ca60SMatthew G. Knepley       Y[i*n+k] = 0.0;
2466af0ca60SMatthew G. Knepley       for (j = 0; j < 2; ++j) {
24728cc7b48SMatthew G. Knepley         Y[i*n+k] += PetscRealPart(H[i*2+j]) * X[k*2+j];
2486af0ca60SMatthew G. Knepley       }
2496af0ca60SMatthew G. Knepley     }
2506af0ca60SMatthew G. Knepley   }
2516af0ca60SMatthew G. Knepley   /* beta = Y error = [y-intercept, slope] */
2526af0ca60SMatthew G. Knepley   for (i = 0; i < 2; ++i) {
2536af0ca60SMatthew G. Knepley     beta[i] = 0.0;
2546af0ca60SMatthew G. Knepley     for (k = 0; k < n; ++k) {
2556af0ca60SMatthew G. Knepley       beta[i] += Y[i*n+k] * y[k];
2566af0ca60SMatthew G. Knepley     }
2576af0ca60SMatthew G. Knepley   }
2586af0ca60SMatthew G. Knepley   ierr = PetscFree2(X, Y);CHKERRQ(ierr);
2596af0ca60SMatthew G. Knepley   *intercept = beta[0];
2606af0ca60SMatthew G. Knepley   *slope     = beta[1];
2616af0ca60SMatthew G. Knepley   PetscFunctionReturn(0);
2626af0ca60SMatthew G. Knepley }
2636af0ca60SMatthew G. Knepley 
2646af0ca60SMatthew G. Knepley /*@
2656af0ca60SMatthew G. Knepley   PetscConvEstGetConvRate - Returns an estimate of the convergence rate for the discretization
2666af0ca60SMatthew G. Knepley 
2676af0ca60SMatthew G. Knepley   Not collective
2686af0ca60SMatthew G. Knepley 
2696af0ca60SMatthew G. Knepley   Input Parameter:
2706af0ca60SMatthew G. Knepley . ce   - The PetscConvEst object
2716af0ca60SMatthew G. Knepley 
2726af0ca60SMatthew G. Knepley   Output Parameter:
2736af0ca60SMatthew G. Knepley . alpha - The convergence rate
2746af0ca60SMatthew G. Knepley 
2756af0ca60SMatthew G. Knepley   Note: The convergence rate alpha is defined by
2766af0ca60SMatthew G. Knepley $ || u_h - u_exact || < C h^alpha
2776af0ca60SMatthew G. Knepley where u_h is the discrete solution, and h is a measure of the discretization size.
2786af0ca60SMatthew G. Knepley 
2796af0ca60SMatthew G. Knepley We solve a series of problems on refined meshes, calculate an error based upon the exact solution in the DS,
2806af0ca60SMatthew G. Knepley and then fit the result to our model above using linear regression.
2816af0ca60SMatthew G. Knepley 
2826af0ca60SMatthew G. Knepley   Options database keys:
2836af0ca60SMatthew G. Knepley . -snes_convergence_estimate : Execute convergence estimation and print out the rate
2846af0ca60SMatthew G. Knepley 
2856af0ca60SMatthew G. Knepley   Level: intermediate
2866af0ca60SMatthew G. Knepley 
2876af0ca60SMatthew G. Knepley .keywords: PetscConvEst, convergence
2886af0ca60SMatthew G. Knepley .seealso: PetscConvEstSetSolver(), PetscConvEstCreate(), PetscConvEstGetConvRate()
2896af0ca60SMatthew G. Knepley @*/
2906af0ca60SMatthew G. Knepley PetscErrorCode PetscConvEstGetConvRate(PetscConvEst ce, PetscReal *alpha)
2916af0ca60SMatthew G. Knepley {
2926af0ca60SMatthew G. Knepley   DM            *dm;
2936af0ca60SMatthew G. Knepley   PetscDS        prob;
2946af0ca60SMatthew G. Knepley   PetscObject    disc;
2956af0ca60SMatthew G. Knepley   MPI_Comm       comm;
2966af0ca60SMatthew G. Knepley   const char    *uname, *dmname;
2976af0ca60SMatthew G. Knepley   void          *ctx;
2986af0ca60SMatthew G. Knepley   Vec            u;
2996af0ca60SMatthew G. Knepley   PetscReal      t = 0.0, *x, *y, slope, intercept;
3006af0ca60SMatthew G. Knepley   PetscInt      *dof, dim, Nr = ce->Nr, r;
3016af0ca60SMatthew G. Knepley   PetscErrorCode ierr;
3026af0ca60SMatthew G. Knepley 
3036af0ca60SMatthew G. Knepley   PetscFunctionBegin;
3046af0ca60SMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject) ce, &comm);CHKERRQ(ierr);
3056af0ca60SMatthew G. Knepley   ierr = DMGetDimension(ce->idm, &dim);CHKERRQ(ierr);
3066af0ca60SMatthew G. Knepley   ierr = DMGetApplicationContext(ce->idm, &ctx);CHKERRQ(ierr);
3076af0ca60SMatthew G. Knepley   ierr = DMGetDS(ce->idm, &prob);CHKERRQ(ierr);
3086af0ca60SMatthew G. Knepley   ierr = DMPlexSetRefinementUniform(ce->idm, PETSC_TRUE);CHKERRQ(ierr);
3096af0ca60SMatthew G. Knepley   ierr = PetscMalloc2((Nr+1), &dm, (Nr+1), &dof);CHKERRQ(ierr);
3106af0ca60SMatthew G. Knepley   dm[0]  = ce->idm;
3116af0ca60SMatthew G. Knepley   *alpha = 0.0;
3126af0ca60SMatthew G. Knepley   /* Loop over meshes */
3136af0ca60SMatthew G. Knepley   for (r = 0; r <= Nr; ++r) {
3146af0ca60SMatthew G. Knepley     if (r > 0) {
3156af0ca60SMatthew G. Knepley       ierr = DMRefine(dm[r-1], MPI_COMM_NULL, &dm[r]);CHKERRQ(ierr);
3166af0ca60SMatthew G. Knepley       ierr = DMSetCoarseDM(dm[r], dm[r-1]);CHKERRQ(ierr);
3176af0ca60SMatthew G. Knepley       ierr = DMSetDS(dm[r], prob);CHKERRQ(ierr);
3186af0ca60SMatthew G. Knepley       ierr = PetscObjectGetName((PetscObject) dm[r-1], &dmname);CHKERRQ(ierr);
3196af0ca60SMatthew G. Knepley       ierr = PetscObjectSetName((PetscObject) dm[r], dmname);CHKERRQ(ierr);
3206af0ca60SMatthew G. Knepley     }
3216af0ca60SMatthew G. Knepley     ierr = DMViewFromOptions(dm[r], NULL, "-conv_dm_view");CHKERRQ(ierr);
3226af0ca60SMatthew G. Knepley     ierr = DMPlexGetHeightStratum(dm[r], 0, NULL, &dof[r]);CHKERRQ(ierr);
3236af0ca60SMatthew G. Knepley     /* Create solution */
3246af0ca60SMatthew G. Knepley     ierr = DMCreateGlobalVector(dm[r], &u);CHKERRQ(ierr);
325239a0881SMatthew G. Knepley     ierr = PetscDSGetDiscretization(prob, 0, &disc);CHKERRQ(ierr);
326239a0881SMatthew G. Knepley     ierr = PetscObjectGetName(disc, &uname);CHKERRQ(ierr);
3276af0ca60SMatthew G. Knepley     ierr = PetscObjectSetName((PetscObject) u, uname);CHKERRQ(ierr);
3286af0ca60SMatthew G. Knepley     /* Setup solver */
3296af0ca60SMatthew G. Knepley     ierr = SNESReset(ce->snes);CHKERRQ(ierr);
3306af0ca60SMatthew G. Knepley     ierr = SNESSetDM(ce->snes, dm[r]);CHKERRQ(ierr);
3316af0ca60SMatthew G. Knepley     ierr = DMPlexSetSNESLocalFEM(dm[r], ctx, ctx, ctx);CHKERRQ(ierr);
3326af0ca60SMatthew G. Knepley     ierr = SNESSetFromOptions(ce->snes);CHKERRQ(ierr);
3336af0ca60SMatthew G. Knepley     /* Create initial guess */
3346af0ca60SMatthew G. Knepley     ierr = DMProjectFunction(dm[r], t, ce->initGuess, NULL, INSERT_VALUES, u);CHKERRQ(ierr);
3356af0ca60SMatthew G. Knepley     ierr = SNESSolve(ce->snes, NULL, u);CHKERRQ(ierr);
3366af0ca60SMatthew G. Knepley     ierr = DMComputeL2FieldDiff(dm[r], t, ce->exactSol, NULL, u, &ce->errors[r*ce->Nf]);CHKERRQ(ierr);
3376af0ca60SMatthew G. Knepley     /* Monitor */
3386af0ca60SMatthew G. Knepley     if (ce->monitor) {
3396af0ca60SMatthew G. Knepley       PetscReal *errors = &ce->errors[r*ce->Nf];
3406af0ca60SMatthew G. Knepley       PetscInt f;
3416af0ca60SMatthew G. Knepley 
3426af0ca60SMatthew G. Knepley       ierr = PetscPrintf(comm, "L_2 Error: [");CHKERRQ(ierr);
3436af0ca60SMatthew G. Knepley       for (f = 0; f < ce->Nf; ++f) {
3446af0ca60SMatthew G. Knepley         if (f > 0) {ierr = PetscPrintf(comm, ", ");CHKERRQ(ierr);}
3456af0ca60SMatthew G. Knepley         if (errors[f] < 1.0e-11) {ierr = PetscPrintf(comm, "< 1e-11");CHKERRQ(ierr);}
3466af0ca60SMatthew G. Knepley         else                     {ierr = PetscPrintf(comm, "%g", errors[f]);CHKERRQ(ierr);}
3476af0ca60SMatthew G. Knepley       }
3486af0ca60SMatthew G. Knepley       ierr = PetscPrintf(comm, "]\n");CHKERRQ(ierr);
3496af0ca60SMatthew G. Knepley     }
3506af0ca60SMatthew G. Knepley     /* Cleanup */
3516af0ca60SMatthew G. Knepley     ierr = VecDestroy(&u);CHKERRQ(ierr);
3526af0ca60SMatthew G. Knepley   }
3536af0ca60SMatthew G. Knepley   for (r = 1; r <= Nr; ++r) {
3546af0ca60SMatthew G. Knepley     ierr = DMDestroy(&dm[r]);CHKERRQ(ierr);
3556af0ca60SMatthew G. Knepley   }
3566af0ca60SMatthew G. Knepley   /* Fit convergence rate */
3576af0ca60SMatthew G. Knepley   ierr = PetscMalloc2(Nr+1, &x, Nr+1, &y);CHKERRQ(ierr);
3586af0ca60SMatthew G. Knepley   for (r = 0; r <= Nr; ++r) {
3596af0ca60SMatthew G. Knepley     x[r] = PetscLog10Real(dof[r]);
3606af0ca60SMatthew G. Knepley     y[r] = PetscLog10Real(ce->errors[r*ce->Nf+0]);
3616af0ca60SMatthew G. Knepley   }
3626af0ca60SMatthew G. Knepley   ierr = PetscConvEstLinearRegression_Private(ce, Nr+1, x, y, &slope, &intercept);CHKERRQ(ierr);
3636af0ca60SMatthew G. Knepley   ierr = PetscFree2(x, y);CHKERRQ(ierr);
3646af0ca60SMatthew G. Knepley   /* Since h^{-dim} = N, lg err = s lg N + b = -s dim lg h + b */
3656af0ca60SMatthew G. Knepley   *alpha = -slope * dim;
3666af0ca60SMatthew G. Knepley   ierr = PetscFree2(dm, dof);CHKERRQ(ierr);
367*2cae373cSMatthew G. Knepley   /* Restore solver */
368*2cae373cSMatthew G. Knepley   ierr = SNESReset(ce->snes);CHKERRQ(ierr);
369*2cae373cSMatthew G. Knepley   ierr = SNESSetDM(ce->snes, ce->idm);CHKERRQ(ierr);
370*2cae373cSMatthew G. Knepley   ierr = DMPlexSetSNESLocalFEM(ce->idm, ctx, ctx, ctx);CHKERRQ(ierr);
371*2cae373cSMatthew G. Knepley   ierr = SNESSetFromOptions(ce->snes);CHKERRQ(ierr);
3726af0ca60SMatthew G. Knepley   PetscFunctionReturn(0);
3736af0ca60SMatthew G. Knepley }
3746af0ca60SMatthew G. Knepley 
3756af0ca60SMatthew G. Knepley /*@
3766af0ca60SMatthew G. Knepley   PetscConvEstRateView - Displays the convergence rate to a viewer
3776af0ca60SMatthew G. Knepley 
3786af0ca60SMatthew G. Knepley    Collective on SNES
3796af0ca60SMatthew G. Knepley 
3806af0ca60SMatthew G. Knepley    Parameter:
3816af0ca60SMatthew G. Knepley +  snes - iterative context obtained from SNESCreate()
3826af0ca60SMatthew G. Knepley .  alpha - the convergence rate
3836af0ca60SMatthew G. Knepley -  viewer - the viewer to display the reason
3846af0ca60SMatthew G. Knepley 
3856af0ca60SMatthew G. Knepley    Options Database Keys:
3866af0ca60SMatthew G. Knepley .  -snes_convergence_estimate - print the convergence rate
3876af0ca60SMatthew G. Knepley 
3886af0ca60SMatthew G. Knepley    Level: developer
3896af0ca60SMatthew G. Knepley 
3906af0ca60SMatthew G. Knepley .seealso: PetscConvEstGetRate()
3916af0ca60SMatthew G. Knepley @*/
3926af0ca60SMatthew G. Knepley PetscErrorCode PetscConvEstRateView(PetscConvEst ce, PetscReal alpha, PetscViewer viewer)
3936af0ca60SMatthew G. Knepley {
3946af0ca60SMatthew G. Knepley   PetscBool      isAscii;
3956af0ca60SMatthew G. Knepley   PetscErrorCode ierr;
3966af0ca60SMatthew G. Knepley 
3976af0ca60SMatthew G. Knepley   PetscFunctionBegin;
3986af0ca60SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &isAscii);CHKERRQ(ierr);
3996af0ca60SMatthew G. Knepley   if (isAscii) {
4006af0ca60SMatthew G. Knepley     ierr = PetscViewerASCIIAddTab(viewer, ((PetscObject) ce)->tablevel);CHKERRQ(ierr);
4016af0ca60SMatthew G. Knepley     ierr = PetscViewerASCIIPrintf(viewer, "L_2 convergence rate: %0.2g\n", (double) alpha);CHKERRQ(ierr);
4026af0ca60SMatthew G. Knepley     ierr = PetscViewerASCIISubtractTab(viewer, ((PetscObject) ce)->tablevel);CHKERRQ(ierr);
4036af0ca60SMatthew G. Knepley   }
4046af0ca60SMatthew G. Knepley   PetscFunctionReturn(0);
4056af0ca60SMatthew G. Knepley }
406