xref: /petsc/src/snes/utils/convest.c (revision a56d3bf6b488a55c659ea87da9b5ad62abfd4515)
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:
273*a56d3bf6SMatthew G. Knepley . alpha - The convergence rate for each field
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;
300*a56d3bf6SMatthew G. Knepley   PetscInt      *dof, dim, Nf, f, Nr = ce->Nr, r;
3015d68e14cSMatthew G. Knepley   PetscLogEvent  event;
3026af0ca60SMatthew G. Knepley   PetscErrorCode ierr;
3036af0ca60SMatthew G. Knepley 
3046af0ca60SMatthew G. Knepley   PetscFunctionBegin;
3056af0ca60SMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject) ce, &comm);CHKERRQ(ierr);
3066af0ca60SMatthew G. Knepley   ierr = DMGetDimension(ce->idm, &dim);CHKERRQ(ierr);
3076af0ca60SMatthew G. Knepley   ierr = DMGetApplicationContext(ce->idm, &ctx);CHKERRQ(ierr);
3086af0ca60SMatthew G. Knepley   ierr = DMGetDS(ce->idm, &prob);CHKERRQ(ierr);
309*a56d3bf6SMatthew G. Knepley   ierr = PetscDSGetNumFields(prob, &Nf);CHKERRQ(ierr);
3106af0ca60SMatthew G. Knepley   ierr = DMPlexSetRefinementUniform(ce->idm, PETSC_TRUE);CHKERRQ(ierr);
311*a56d3bf6SMatthew G. Knepley   ierr = PetscMalloc2((Nr+1), &dm, (Nr+1)*Nf, &dof);CHKERRQ(ierr);
3126af0ca60SMatthew G. Knepley   dm[0]  = ce->idm;
3136af0ca60SMatthew G. Knepley   *alpha = 0.0;
3146af0ca60SMatthew G. Knepley   /* Loop over meshes */
3155d68e14cSMatthew G. Knepley   ierr = PetscLogEventRegister("ConvEst Error", PETSC_OBJECT_CLASSID, &event);CHKERRQ(ierr);
3166af0ca60SMatthew G. Knepley   for (r = 0; r <= Nr; ++r) {
3175d68e14cSMatthew G. Knepley     PetscLogStage stage;
3185d68e14cSMatthew G. Knepley     char          stageName[PETSC_MAX_PATH_LEN];
3195d68e14cSMatthew G. Knepley     PetscInt      f;
3205d68e14cSMatthew G. Knepley 
3215d68e14cSMatthew G. Knepley     ierr = PetscSNPrintf(stageName, PETSC_MAX_PATH_LEN-1, "ConvEst Refinement Level %D", r);CHKERRQ(ierr);
3225d68e14cSMatthew G. Knepley     ierr = PetscLogStageRegister(stageName, &stage);CHKERRQ(ierr);
3235d68e14cSMatthew G. Knepley     ierr = PetscLogStagePush(stage);CHKERRQ(ierr);
3246af0ca60SMatthew G. Knepley     if (r > 0) {
3256af0ca60SMatthew G. Knepley       ierr = DMRefine(dm[r-1], MPI_COMM_NULL, &dm[r]);CHKERRQ(ierr);
3266af0ca60SMatthew G. Knepley       ierr = DMSetCoarseDM(dm[r], dm[r-1]);CHKERRQ(ierr);
3276af0ca60SMatthew G. Knepley       ierr = DMSetDS(dm[r], prob);CHKERRQ(ierr);
3286af0ca60SMatthew G. Knepley       ierr = PetscObjectGetName((PetscObject) dm[r-1], &dmname);CHKERRQ(ierr);
3296af0ca60SMatthew G. Knepley       ierr = PetscObjectSetName((PetscObject) dm[r], dmname);CHKERRQ(ierr);
3306af0ca60SMatthew G. Knepley     }
3316af0ca60SMatthew G. Knepley     ierr = DMViewFromOptions(dm[r], NULL, "-conv_dm_view");CHKERRQ(ierr);
3326af0ca60SMatthew G. Knepley     /* Create solution */
3336af0ca60SMatthew G. Knepley     ierr = DMCreateGlobalVector(dm[r], &u);CHKERRQ(ierr);
334239a0881SMatthew G. Knepley     ierr = PetscDSGetDiscretization(prob, 0, &disc);CHKERRQ(ierr);
335239a0881SMatthew G. Knepley     ierr = PetscObjectGetName(disc, &uname);CHKERRQ(ierr);
3366af0ca60SMatthew G. Knepley     ierr = PetscObjectSetName((PetscObject) u, uname);CHKERRQ(ierr);
3376af0ca60SMatthew G. Knepley     /* Setup solver */
3386af0ca60SMatthew G. Knepley     ierr = SNESReset(ce->snes);CHKERRQ(ierr);
3396af0ca60SMatthew G. Knepley     ierr = SNESSetDM(ce->snes, dm[r]);CHKERRQ(ierr);
3406af0ca60SMatthew G. Knepley     ierr = DMPlexSetSNESLocalFEM(dm[r], ctx, ctx, ctx);CHKERRQ(ierr);
3416af0ca60SMatthew G. Knepley     ierr = SNESSetFromOptions(ce->snes);CHKERRQ(ierr);
3426af0ca60SMatthew G. Knepley     /* Create initial guess */
3436af0ca60SMatthew G. Knepley     ierr = DMProjectFunction(dm[r], t, ce->initGuess, NULL, INSERT_VALUES, u);CHKERRQ(ierr);
3446af0ca60SMatthew G. Knepley     ierr = SNESSolve(ce->snes, NULL, u);CHKERRQ(ierr);
3455d68e14cSMatthew G. Knepley     ierr = PetscLogEventBegin(event, ce, 0, 0, 0);CHKERRQ(ierr);
3466af0ca60SMatthew G. Knepley     ierr = DMComputeL2FieldDiff(dm[r], t, ce->exactSol, NULL, u, &ce->errors[r*ce->Nf]);CHKERRQ(ierr);
3475d68e14cSMatthew G. Knepley     ierr = PetscLogEventEnd(event, ce, 0, 0, 0);CHKERRQ(ierr);
348*a56d3bf6SMatthew G. Knepley     for (f = 0; f < ce->Nf; ++f) {
349*a56d3bf6SMatthew G. Knepley       PetscSection s, fs;
350*a56d3bf6SMatthew G. Knepley       PetscInt     lsize;
351*a56d3bf6SMatthew G. Knepley 
352*a56d3bf6SMatthew G. Knepley       /* Could use DMGetOutputDM() to add in Dirichlet dofs */
353*a56d3bf6SMatthew G. Knepley       ierr = DMGetSection(dm[r], &s);CHKERRQ(ierr);
354*a56d3bf6SMatthew G. Knepley       ierr = PetscSectionGetField(s, f, &fs);CHKERRQ(ierr);
355*a56d3bf6SMatthew G. Knepley       ierr = PetscSectionGetConstrainedStorageSize(fs, &lsize);CHKERRQ(ierr);
356*a56d3bf6SMatthew G. Knepley       ierr = MPI_Allreduce(&lsize, &dof[r*ce->Nf+f], 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject) ce->snes));CHKERRQ(ierr);
357*a56d3bf6SMatthew G. Knepley       ierr = PetscLogEventSetDof(event, f, dof[r*ce->Nf+f]);CHKERRQ(ierr);
358*a56d3bf6SMatthew G. Knepley       ierr = PetscLogEventSetError(event, f, ce->errors[r*ce->Nf+f]);CHKERRQ(ierr);
359*a56d3bf6SMatthew G. Knepley     }
3606af0ca60SMatthew G. Knepley     /* Monitor */
3616af0ca60SMatthew G. Knepley     if (ce->monitor) {
3626af0ca60SMatthew G. Knepley       PetscReal *errors = &ce->errors[r*ce->Nf];
3636af0ca60SMatthew G. Knepley 
3646af0ca60SMatthew G. Knepley       ierr = PetscPrintf(comm, "L_2 Error: [");CHKERRQ(ierr);
3656af0ca60SMatthew G. Knepley       for (f = 0; f < ce->Nf; ++f) {
3666af0ca60SMatthew G. Knepley         if (f > 0) {ierr = PetscPrintf(comm, ", ");CHKERRQ(ierr);}
3676af0ca60SMatthew G. Knepley         if (errors[f] < 1.0e-11) {ierr = PetscPrintf(comm, "< 1e-11");CHKERRQ(ierr);}
3688dfade3bSBarry Smith         else                     {ierr = PetscPrintf(comm, "%g", (double)errors[f]);CHKERRQ(ierr);}
3696af0ca60SMatthew G. Knepley       }
3706af0ca60SMatthew G. Knepley       ierr = PetscPrintf(comm, "]\n");CHKERRQ(ierr);
3716af0ca60SMatthew G. Knepley     }
3726af0ca60SMatthew G. Knepley     /* Cleanup */
3736af0ca60SMatthew G. Knepley     ierr = VecDestroy(&u);CHKERRQ(ierr);
3745d68e14cSMatthew G. Knepley     ierr = PetscLogStagePop();CHKERRQ(ierr);
3756af0ca60SMatthew G. Knepley   }
3766af0ca60SMatthew G. Knepley   for (r = 1; r <= Nr; ++r) {
3776af0ca60SMatthew G. Knepley     ierr = DMDestroy(&dm[r]);CHKERRQ(ierr);
3786af0ca60SMatthew G. Knepley   }
3796af0ca60SMatthew G. Knepley   /* Fit convergence rate */
3806af0ca60SMatthew G. Knepley   ierr = PetscMalloc2(Nr+1, &x, Nr+1, &y);CHKERRQ(ierr);
381*a56d3bf6SMatthew G. Knepley   for (f = 0; f < ce->Nf; ++f) {
3826af0ca60SMatthew G. Knepley     for (r = 0; r <= Nr; ++r) {
383*a56d3bf6SMatthew G. Knepley       x[r] = PetscLog10Real(dof[r*ce->Nf+f]);
384*a56d3bf6SMatthew G. Knepley       y[r] = PetscLog10Real(ce->errors[r*ce->Nf+f]);
3856af0ca60SMatthew G. Knepley     }
3866af0ca60SMatthew G. Knepley     ierr = PetscConvEstLinearRegression_Private(ce, Nr+1, x, y, &slope, &intercept);CHKERRQ(ierr);
3876af0ca60SMatthew G. Knepley     /* Since h^{-dim} = N, lg err = s lg N + b = -s dim lg h + b */
388*a56d3bf6SMatthew G. Knepley     alpha[f] = -slope * dim;
389*a56d3bf6SMatthew G. Knepley   }
390*a56d3bf6SMatthew G. Knepley   ierr = PetscFree2(x, y);CHKERRQ(ierr);
3916af0ca60SMatthew G. Knepley   ierr = PetscFree2(dm, dof);CHKERRQ(ierr);
3922cae373cSMatthew G. Knepley   /* Restore solver */
3932cae373cSMatthew G. Knepley   ierr = SNESReset(ce->snes);CHKERRQ(ierr);
3942cae373cSMatthew G. Knepley   ierr = SNESSetDM(ce->snes, ce->idm);CHKERRQ(ierr);
3952cae373cSMatthew G. Knepley   ierr = DMPlexSetSNESLocalFEM(ce->idm, ctx, ctx, ctx);CHKERRQ(ierr);
3962cae373cSMatthew G. Knepley   ierr = SNESSetFromOptions(ce->snes);CHKERRQ(ierr);
3976af0ca60SMatthew G. Knepley   PetscFunctionReturn(0);
3986af0ca60SMatthew G. Knepley }
3996af0ca60SMatthew G. Knepley 
4006af0ca60SMatthew G. Knepley /*@
4016af0ca60SMatthew G. Knepley   PetscConvEstRateView - Displays the convergence rate to a viewer
4026af0ca60SMatthew G. Knepley 
4036af0ca60SMatthew G. Knepley    Collective on SNES
4046af0ca60SMatthew G. Knepley 
4056af0ca60SMatthew G. Knepley    Parameter:
4066af0ca60SMatthew G. Knepley +  snes - iterative context obtained from SNESCreate()
407*a56d3bf6SMatthew G. Knepley .  alpha - the convergence rate for each field
4086af0ca60SMatthew G. Knepley -  viewer - the viewer to display the reason
4096af0ca60SMatthew G. Knepley 
4106af0ca60SMatthew G. Knepley    Options Database Keys:
4116af0ca60SMatthew G. Knepley .  -snes_convergence_estimate - print the convergence rate
4126af0ca60SMatthew G. Knepley 
4136af0ca60SMatthew G. Knepley    Level: developer
4146af0ca60SMatthew G. Knepley 
4156af0ca60SMatthew G. Knepley .seealso: PetscConvEstGetRate()
4166af0ca60SMatthew G. Knepley @*/
417*a56d3bf6SMatthew G. Knepley PetscErrorCode PetscConvEstRateView(PetscConvEst ce, const PetscReal alpha[], PetscViewer viewer)
4186af0ca60SMatthew G. Knepley {
4196af0ca60SMatthew G. Knepley   PetscBool      isAscii;
4206af0ca60SMatthew G. Knepley   PetscErrorCode ierr;
4216af0ca60SMatthew G. Knepley 
4226af0ca60SMatthew G. Knepley   PetscFunctionBegin;
4236af0ca60SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &isAscii);CHKERRQ(ierr);
4246af0ca60SMatthew G. Knepley   if (isAscii) {
425*a56d3bf6SMatthew G. Knepley     DM       dm;
426*a56d3bf6SMatthew G. Knepley     PetscInt Nf, f;
427*a56d3bf6SMatthew G. Knepley 
428*a56d3bf6SMatthew G. Knepley     ierr = SNESGetDM(ce->snes, &dm);CHKERRQ(ierr);
429*a56d3bf6SMatthew G. Knepley     ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr);
4306af0ca60SMatthew G. Knepley     ierr = PetscViewerASCIIAddTab(viewer, ((PetscObject) ce)->tablevel);CHKERRQ(ierr);
431*a56d3bf6SMatthew G. Knepley     ierr = PetscViewerASCIIPrintf(viewer, "L_2 convergence rate: ");CHKERRQ(ierr);
432*a56d3bf6SMatthew G. Knepley     if (Nf > 1) {ierr = PetscViewerASCIIPrintf(viewer, "[");CHKERRQ(ierr);}
433*a56d3bf6SMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
434*a56d3bf6SMatthew G. Knepley       if (f > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);}
435*a56d3bf6SMatthew G. Knepley       ierr = PetscViewerASCIIPrintf(viewer, "%.2g", (double) alpha[f]);CHKERRQ(ierr);
436*a56d3bf6SMatthew G. Knepley     }
437*a56d3bf6SMatthew G. Knepley     if (Nf > 1) {ierr = PetscViewerASCIIPrintf(viewer, "]");CHKERRQ(ierr);}
438*a56d3bf6SMatthew G. Knepley     ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr);
4396af0ca60SMatthew G. Knepley     ierr = PetscViewerASCIISubtractTab(viewer, ((PetscObject) ce)->tablevel);CHKERRQ(ierr);
4406af0ca60SMatthew G. Knepley   }
4416af0ca60SMatthew G. Knepley   PetscFunctionReturn(0);
4426af0ca60SMatthew G. Knepley }
443