xref: /petsc/src/dm/impls/plex/tests/ex60.c (revision 41473654878cf397846bad00e76167b500a16251)
100d473e3SJoe Wallwork static char help[] = "Test metric utils in the uniform, isotropic case.\n\n";
200d473e3SJoe Wallwork 
300d473e3SJoe Wallwork #include <petscdmplex.h>
400d473e3SJoe Wallwork 
500d473e3SJoe Wallwork static PetscErrorCode bowl(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, void *ctx)
600d473e3SJoe Wallwork {
700d473e3SJoe Wallwork   PetscInt d;
800d473e3SJoe Wallwork 
900d473e3SJoe Wallwork   *u = 0.0;
1000d473e3SJoe Wallwork   for (d = 0; d < dim; d++) *u += 0.5*(x[d] - 0.5)*(x[d] - 0.5);
1100d473e3SJoe Wallwork 
1200d473e3SJoe Wallwork   return 0;
1300d473e3SJoe Wallwork }
1400d473e3SJoe Wallwork 
1500d473e3SJoe Wallwork int main(int argc, char **argv) {
1600d473e3SJoe Wallwork   DM              dm, dmDist, dmAdapt;
1721b3e102SJoe Wallwork   DMLabel         bdLabel = NULL, rgLabel = NULL;
1800d473e3SJoe Wallwork   MPI_Comm        comm;
19*41473654SJoe Wallwork   PetscBool       uniform = PETSC_FALSE, isotropic = PETSC_FALSE, noTagging = PETSC_FALSE;
2000d473e3SJoe Wallwork   PetscErrorCode  ierr;
21f49e87b0SJoe Wallwork   PetscInt       *faces, dim = 3, d;
2200d473e3SJoe Wallwork   PetscReal       scaling = 1.0;
2300d473e3SJoe Wallwork   Vec             metric;
2400d473e3SJoe Wallwork 
2500d473e3SJoe Wallwork   /* Set up */
2600d473e3SJoe Wallwork   ierr = PetscInitialize(&argc, &argv, NULL, help);if (ierr) return ierr;
2700d473e3SJoe Wallwork   comm = PETSC_COMM_WORLD;
2800d473e3SJoe Wallwork   ierr = PetscOptionsBegin(comm, "", "Mesh adaptation options", "DMPLEX");CHKERRQ(ierr);
2900d473e3SJoe Wallwork   ierr = PetscOptionsRangeInt("-dim", "The topological mesh dimension", "ex60.c", dim, &dim, NULL, 2, 3);CHKERRQ(ierr);
3000d473e3SJoe Wallwork   ierr = PetscOptionsBool("-uniform", "Should the metric be assumed uniform?", "ex60.c", uniform, &uniform, NULL);CHKERRQ(ierr);
31e5697243SJoe Wallwork   ierr = PetscOptionsBool("-isotropic", "Should the metric be assumed isotropic, or computed as a recovered Hessian?", "ex60.c", isotropic, &isotropic, NULL);CHKERRQ(ierr);
32*41473654SJoe Wallwork   ierr = PetscOptionsBool("-noTagging", "Should tag preservation testing be turned off?", "ex60.c", noTagging, &noTagging, NULL);CHKERRQ(ierr);
3300d473e3SJoe Wallwork   ierr = PetscOptionsEnd();
3400d473e3SJoe Wallwork 
3500d473e3SJoe Wallwork   /* Create box mesh */
3600d473e3SJoe Wallwork   ierr = PetscMalloc1(dim, &faces);CHKERRQ(ierr);
37f49e87b0SJoe Wallwork   for (d = 0; d < dim; ++d) faces[d] = 4;
3800d473e3SJoe Wallwork   ierr = DMPlexCreateBoxMesh(comm, dim, PETSC_TRUE, faces, NULL, NULL, NULL, PETSC_TRUE, &dm);CHKERRQ(ierr);
3900d473e3SJoe Wallwork   ierr = PetscFree(faces);CHKERRQ(ierr);
40e5697243SJoe Wallwork   ierr = DMSetFromOptions(dm);CHKERRQ(ierr);
4100d473e3SJoe Wallwork 
4200d473e3SJoe Wallwork   /* Distribute mesh over processes */
4300d473e3SJoe Wallwork   ierr = DMPlexDistribute(dm, 0, NULL, &dmDist);CHKERRQ(ierr);
4400d473e3SJoe Wallwork   if (dmDist) {
4500d473e3SJoe Wallwork     ierr = DMDestroy(&dm);CHKERRQ(ierr);
4600d473e3SJoe Wallwork     dm = dmDist;
4700d473e3SJoe Wallwork   }
4800d473e3SJoe Wallwork   ierr = PetscObjectSetName((PetscObject) dm, "DM_init");CHKERRQ(ierr);
4900d473e3SJoe Wallwork   ierr = DMViewFromOptions(dm, NULL, "-initial_mesh_view");CHKERRQ(ierr);
5000d473e3SJoe Wallwork 
51*41473654SJoe Wallwork   /* Set tags to be preserved */
52*41473654SJoe Wallwork   if (!noTagging) {
53*41473654SJoe Wallwork     DM                 cdm;
54*41473654SJoe Wallwork     PetscInt           cStart, cEnd, c, fStart, fEnd, f, vStart, vEnd;
55*41473654SJoe Wallwork     const PetscScalar *coords;
56*41473654SJoe Wallwork     Vec                coordinates;
57*41473654SJoe Wallwork 
58*41473654SJoe Wallwork     /* Cell tags */
59*41473654SJoe Wallwork     ierr = DMCreateLabel(dm, "Cell Sets");CHKERRQ(ierr);
60*41473654SJoe Wallwork     ierr = DMGetLabel(dm, "Cell Sets", &rgLabel);CHKERRQ(ierr);
61*41473654SJoe Wallwork     ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
62*41473654SJoe Wallwork     for (c = cStart; c < cEnd; ++c) {
63*41473654SJoe Wallwork       PetscReal centroid[3], volume, x;
64*41473654SJoe Wallwork 
65*41473654SJoe Wallwork       ierr = DMPlexComputeCellGeometryFVM(dm, c, &volume, centroid, NULL);CHKERRQ(ierr);
66*41473654SJoe Wallwork       x = centroid[0];
67*41473654SJoe Wallwork       if (x < 0.5) { ierr = DMLabelSetValue(rgLabel, c, 3);CHKERRQ(ierr); }
68*41473654SJoe Wallwork       else         { ierr = DMLabelSetValue(rgLabel, c, 4);CHKERRQ(ierr); }
69*41473654SJoe Wallwork     }
70*41473654SJoe Wallwork 
71*41473654SJoe Wallwork     /* Face tags */
72*41473654SJoe Wallwork     ierr = DMCreateLabel(dm, "Face Sets");CHKERRQ(ierr);
73*41473654SJoe Wallwork     ierr = DMGetLabel(dm, "Face Sets", &bdLabel);CHKERRQ(ierr);
74*41473654SJoe Wallwork     ierr = DMPlexMarkBoundaryFaces(dm, 1, bdLabel);CHKERRQ(ierr);
75*41473654SJoe Wallwork     ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
76*41473654SJoe Wallwork     ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
77*41473654SJoe Wallwork     ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
78*41473654SJoe Wallwork     ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr);
79*41473654SJoe Wallwork     ierr = VecGetArrayRead(coordinates, &coords);CHKERRQ(ierr);
80*41473654SJoe Wallwork     for (f = fStart; f < fEnd; ++f) {
81*41473654SJoe Wallwork       PetscBool flg = PETSC_TRUE;
82*41473654SJoe Wallwork       PetscInt *closure = NULL, closureSize, cl;
83*41473654SJoe Wallwork       PetscReal eps = 1.0e-08;
84*41473654SJoe Wallwork 
85*41473654SJoe Wallwork       ierr = DMPlexGetTransitiveClosure(dm, f, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
86*41473654SJoe Wallwork       for (cl = 0; cl < closureSize*2; cl += 2) {
87*41473654SJoe Wallwork         PetscInt   off = closure[cl];
88*41473654SJoe Wallwork         PetscReal *x;
89*41473654SJoe Wallwork 
90*41473654SJoe Wallwork         if ((off < vStart) || (off >= vEnd)) continue;
91*41473654SJoe Wallwork         ierr = DMPlexPointLocalRead(cdm, off, coords, &x);CHKERRQ(ierr);
92*41473654SJoe Wallwork         if ((x[0] < 0.5 - eps) || (x[0] > 0.5 + eps)) flg = PETSC_FALSE;
93*41473654SJoe Wallwork       }
94*41473654SJoe Wallwork       if (flg) { ierr = DMLabelSetValue(bdLabel, f, 2);CHKERRQ(ierr); }
95*41473654SJoe Wallwork       ierr = DMPlexRestoreTransitiveClosure(dm, f, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
96*41473654SJoe Wallwork     }
97*41473654SJoe Wallwork     ierr = VecRestoreArrayRead(coordinates, &coords);CHKERRQ(ierr);
98*41473654SJoe Wallwork   }
99*41473654SJoe Wallwork 
10000d473e3SJoe Wallwork   /* Construct metric */
10100d473e3SJoe Wallwork   if (uniform) {
102e5697243SJoe Wallwork     if (isotropic) { ierr = DMPlexMetricCreateUniform(dm, 0, scaling, &metric);CHKERRQ(ierr); }
10300d473e3SJoe Wallwork     else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Uniform anisotropic metrics not supported.");
10400d473e3SJoe Wallwork   }
10500d473e3SJoe Wallwork   else {
10600d473e3SJoe Wallwork     DM      dmIndi;
10700d473e3SJoe Wallwork     PetscFE fe;
10800d473e3SJoe Wallwork     Vec     indicator;
10900d473e3SJoe Wallwork 
11000d473e3SJoe Wallwork     /* Construct "error indicator" */
11100d473e3SJoe Wallwork     ierr = DMClone(dm, &dmIndi);CHKERRQ(ierr);
11200d473e3SJoe Wallwork     ierr = PetscFECreateLagrange(comm, dim, 1, PETSC_TRUE, 1, PETSC_DETERMINE, &fe);CHKERRQ(ierr);
1135767498bSJoe Wallwork     ierr = DMSetField(dmIndi, 0, NULL, (PetscObject)fe);CHKERRQ(ierr);
11400d473e3SJoe Wallwork     ierr = DMCreateDS(dmIndi);CHKERRQ(ierr);
11500d473e3SJoe Wallwork     ierr = PetscFEDestroy(&fe);CHKERRQ(ierr);
11600d473e3SJoe Wallwork     ierr = DMCreateLocalVector(dmIndi, &indicator);CHKERRQ(ierr);
117e5697243SJoe Wallwork     if (isotropic) {
11800d473e3SJoe Wallwork 
11900d473e3SJoe Wallwork       /* Isotropic case: just specify unity */
12000d473e3SJoe Wallwork       ierr = VecSet(indicator, scaling);CHKERRQ(ierr);
12100d473e3SJoe Wallwork       ierr = DMPlexMetricCreateIsotropic(dm, 0, indicator, &metric);CHKERRQ(ierr);
12200d473e3SJoe Wallwork 
12300d473e3SJoe Wallwork     } else {
12400d473e3SJoe Wallwork 
12500d473e3SJoe Wallwork       /* 'Anisotropic' case: approximate the identity by recovering the Hessian of a parabola */
12600d473e3SJoe Wallwork       DM               dmGrad;
12700d473e3SJoe Wallwork       PetscErrorCode (*funcs[1])(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar*, void*) = {bowl};
12800d473e3SJoe Wallwork       Vec              gradient;
12900d473e3SJoe Wallwork 
13000d473e3SJoe Wallwork       /* Project the parabola into P1 space */
13100d473e3SJoe Wallwork       ierr = DMProjectFunctionLocal(dmIndi, 0.0, funcs, NULL, INSERT_ALL_VALUES, indicator);CHKERRQ(ierr);
13200d473e3SJoe Wallwork 
13300d473e3SJoe Wallwork       /* Approximate the gradient */
13400d473e3SJoe Wallwork       ierr = DMClone(dmIndi, &dmGrad);CHKERRQ(ierr);
13500d473e3SJoe Wallwork       ierr = PetscFECreateLagrange(comm, dim, dim, PETSC_TRUE, 1, PETSC_DETERMINE, &fe);CHKERRQ(ierr);
1365767498bSJoe Wallwork       ierr = DMSetField(dmGrad, 0, NULL, (PetscObject)fe);CHKERRQ(ierr);
13700d473e3SJoe Wallwork       ierr = DMCreateDS(dmGrad);CHKERRQ(ierr);
13800d473e3SJoe Wallwork       ierr = PetscFEDestroy(&fe);CHKERRQ(ierr);
13900d473e3SJoe Wallwork       ierr = DMCreateLocalVector(dmGrad, &gradient);CHKERRQ(ierr);
14000d473e3SJoe Wallwork       ierr = DMPlexComputeGradientClementInterpolant(dmIndi, indicator, gradient);CHKERRQ(ierr);
14100d473e3SJoe Wallwork       ierr = VecViewFromOptions(gradient, NULL, "-adapt_gradient_view");CHKERRQ(ierr);
14200d473e3SJoe Wallwork 
14300d473e3SJoe Wallwork       /* Approximate the Hessian */
1445767498bSJoe Wallwork       ierr = DMPlexMetricCreate(dm, 0, &metric);CHKERRQ(ierr);
14500d473e3SJoe Wallwork       ierr = DMPlexComputeGradientClementInterpolant(dmGrad, gradient, metric);CHKERRQ(ierr);
14600d473e3SJoe Wallwork       ierr = VecViewFromOptions(metric, NULL, "-adapt_hessian_view");CHKERRQ(ierr);
14700d473e3SJoe Wallwork       ierr = VecDestroy(&gradient);CHKERRQ(ierr);
14800d473e3SJoe Wallwork       ierr = DMDestroy(&dmGrad);CHKERRQ(ierr);
14900d473e3SJoe Wallwork     }
15000d473e3SJoe Wallwork     ierr = VecDestroy(&indicator);CHKERRQ(ierr);
15100d473e3SJoe Wallwork     ierr = DMDestroy(&dmIndi);CHKERRQ(ierr);
15200d473e3SJoe Wallwork   }
15300d473e3SJoe Wallwork 
15400d473e3SJoe Wallwork   /* Test metric routines */
15500d473e3SJoe Wallwork   {
156f49e87b0SJoe Wallwork     DM        dmDet;
15700d473e3SJoe Wallwork     PetscReal errornorm, norm, tol = 1.0e-10, weights[2] = {0.8, 0.2};
158f49e87b0SJoe Wallwork     Vec       metric1, metric2, metricComb, determinant;
15900d473e3SJoe Wallwork     Vec       metrics[2];
16000d473e3SJoe Wallwork 
16100d473e3SJoe Wallwork     ierr = VecDuplicate(metric, &metric1);CHKERRQ(ierr);
16200d473e3SJoe Wallwork     ierr = VecSet(metric1, 0);CHKERRQ(ierr);
16300d473e3SJoe Wallwork     ierr = VecAXPY(metric1, 0.625, metric);CHKERRQ(ierr);
16400d473e3SJoe Wallwork     ierr = VecDuplicate(metric, &metric2);CHKERRQ(ierr);
16500d473e3SJoe Wallwork     ierr = VecSet(metric2, 0);CHKERRQ(ierr);
16600d473e3SJoe Wallwork     ierr = VecAXPY(metric2, 2.5, metric);CHKERRQ(ierr);
16700d473e3SJoe Wallwork     metrics[0] = metric1;
16800d473e3SJoe Wallwork     metrics[1] = metric2;
16900d473e3SJoe Wallwork 
17000d473e3SJoe Wallwork     /* Test metric average */
17100d473e3SJoe Wallwork     ierr = DMPlexMetricAverage(dm, 2, weights, metrics, &metricComb);CHKERRQ(ierr);
17200d473e3SJoe Wallwork     ierr = VecAXPY(metricComb, -1, metric);CHKERRQ(ierr);
17300d473e3SJoe Wallwork     ierr = VecNorm(metric, NORM_2, &norm);CHKERRQ(ierr);
17400d473e3SJoe Wallwork     ierr = VecNorm(metricComb, NORM_2, &errornorm);CHKERRQ(ierr);
17500d473e3SJoe Wallwork     errornorm /= norm;
1767cdd5544SJoe Wallwork     ierr = PetscPrintf(comm, "Metric average L2 error: %.4f%%\n", 100*errornorm);CHKERRQ(ierr);
1777cdd5544SJoe Wallwork     if (errornorm > tol) SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Metric average test failed");
17800d473e3SJoe Wallwork     ierr = VecDestroy(&metricComb);CHKERRQ(ierr);
17900d473e3SJoe Wallwork 
18000d473e3SJoe Wallwork     /* Test metric intersection */
181e5697243SJoe Wallwork     if (isotropic) {
18200d473e3SJoe Wallwork       ierr = DMPlexMetricIntersection(dm, 2, metrics, &metricComb);CHKERRQ(ierr);
18300d473e3SJoe Wallwork       ierr = VecAXPY(metricComb, -1, metric1);CHKERRQ(ierr);
18400d473e3SJoe Wallwork       ierr = VecNorm(metricComb, NORM_2, &errornorm);CHKERRQ(ierr);
18500d473e3SJoe Wallwork       errornorm /= norm;
1867cdd5544SJoe Wallwork       ierr = PetscPrintf(comm, "Metric intersection L2 error: %.4f%%\n", 100*errornorm);CHKERRQ(ierr);
1877cdd5544SJoe Wallwork       if (errornorm > tol) SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Metric intersection test failed");
18800d473e3SJoe Wallwork     }
189f49e87b0SJoe Wallwork     ierr = VecDestroy(&metric1);CHKERRQ(ierr);
19000d473e3SJoe Wallwork     ierr = VecDestroy(&metric2);CHKERRQ(ierr);
19100d473e3SJoe Wallwork     ierr = VecDestroy(&metricComb);CHKERRQ(ierr);
19200d473e3SJoe Wallwork 
19300d473e3SJoe Wallwork     /* Test metric SPD enforcement */
194f49e87b0SJoe Wallwork     ierr = DMPlexMetricEnforceSPD(dm, metric, PETSC_TRUE, PETSC_TRUE, &metric1, &determinant);CHKERRQ(ierr);
195e5697243SJoe Wallwork     if (isotropic) {
196f49e87b0SJoe Wallwork       Vec err;
197f49e87b0SJoe Wallwork 
198f49e87b0SJoe Wallwork       ierr = VecDuplicate(determinant, &err);CHKERRQ(ierr);
199f49e87b0SJoe Wallwork       ierr = VecSet(err, 1.0);CHKERRQ(ierr);
200f49e87b0SJoe Wallwork       ierr = VecNorm(err, NORM_2, &norm);CHKERRQ(ierr);
201f49e87b0SJoe Wallwork       ierr = VecAXPY(err, -1, determinant);CHKERRQ(ierr);
202f49e87b0SJoe Wallwork       ierr = VecNorm(err, NORM_2, &errornorm);CHKERRQ(ierr);
203f49e87b0SJoe Wallwork       ierr = VecDestroy(&err);CHKERRQ(ierr);
204f49e87b0SJoe Wallwork       errornorm /= norm;
2057cdd5544SJoe Wallwork       ierr = PetscPrintf(comm, "Metric determinant L2 error: %.4f%%\n", 100*errornorm);CHKERRQ(ierr);
2067cdd5544SJoe Wallwork       if (errornorm > tol) SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Determinant is not unit");
20700d473e3SJoe Wallwork       ierr = VecAXPY(metric1, -1, metric);CHKERRQ(ierr);
20800d473e3SJoe Wallwork       ierr = VecNorm(metric1, NORM_2, &errornorm);CHKERRQ(ierr);
20900d473e3SJoe Wallwork       errornorm /= norm;
2107cdd5544SJoe Wallwork       ierr = PetscPrintf(comm, "Metric SPD enforcement L2 error: %.4f%%\n", 100*errornorm);CHKERRQ(ierr);
2117cdd5544SJoe Wallwork       if (errornorm > tol) SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Metric SPD enforcement test failed");
21200d473e3SJoe Wallwork     }
21300d473e3SJoe Wallwork     ierr = VecDestroy(&metric1);CHKERRQ(ierr);
214f49e87b0SJoe Wallwork     ierr = VecGetDM(determinant, &dmDet);CHKERRQ(ierr);
215f49e87b0SJoe Wallwork     ierr = VecDestroy(&determinant);CHKERRQ(ierr);
216f49e87b0SJoe Wallwork     ierr = DMDestroy(&dmDet);CHKERRQ(ierr);
21700d473e3SJoe Wallwork 
21800d473e3SJoe Wallwork     /* Test metric normalization */
219e5697243SJoe Wallwork     ierr = DMPlexMetricNormalize(dm, metric, PETSC_TRUE, PETSC_TRUE, &metric1);CHKERRQ(ierr);
220e5697243SJoe Wallwork     if (isotropic) {
221e5697243SJoe Wallwork       PetscReal target;
222e5697243SJoe Wallwork 
223e5697243SJoe Wallwork       ierr = DMPlexMetricGetTargetComplexity(dm, &target);CHKERRQ(ierr);
224e5697243SJoe Wallwork       scaling = PetscPowReal(target, 2.0/dim);
22500d473e3SJoe Wallwork       ierr = DMPlexMetricCreateUniform(dm, 0, scaling, &metric2);CHKERRQ(ierr);
22600d473e3SJoe Wallwork       ierr = VecAXPY(metric2, -1, metric1);CHKERRQ(ierr);
22700d473e3SJoe Wallwork       ierr = VecNorm(metric2, NORM_2, &errornorm);CHKERRQ(ierr);
22800d473e3SJoe Wallwork       errornorm /= norm;
2297cdd5544SJoe Wallwork       ierr = PetscPrintf(comm, "Metric normalization L2 error: %.4f%%\n", 100*errornorm);CHKERRQ(ierr);
2307cdd5544SJoe Wallwork       if (errornorm > tol) SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Metric normalization test failed");
23100d473e3SJoe Wallwork     }
23200d473e3SJoe Wallwork     ierr = VecCopy(metric1, metric);CHKERRQ(ierr);
23300d473e3SJoe Wallwork     ierr = VecDestroy(&metric2);CHKERRQ(ierr);
23400d473e3SJoe Wallwork     ierr = VecDestroy(&metric1);CHKERRQ(ierr);
23500d473e3SJoe Wallwork   }
23600d473e3SJoe Wallwork 
23700d473e3SJoe Wallwork   /* Adapt the mesh */
23821b3e102SJoe Wallwork   ierr = DMAdaptMetric(dm, metric, bdLabel, rgLabel, &dmAdapt);CHKERRQ(ierr);
23921b3e102SJoe Wallwork   ierr = DMDestroy(&dm);CHKERRQ(ierr);
24000d473e3SJoe Wallwork   ierr = PetscObjectSetName((PetscObject) dmAdapt, "DM_adapted");CHKERRQ(ierr);
24100d473e3SJoe Wallwork   ierr = VecDestroy(&metric);CHKERRQ(ierr);
24200d473e3SJoe Wallwork   ierr = DMViewFromOptions(dmAdapt, NULL, "-adapted_mesh_view");CHKERRQ(ierr);
24300d473e3SJoe Wallwork 
244*41473654SJoe Wallwork   /* Test tag preservation */
245*41473654SJoe Wallwork   if (!noTagging) {
246*41473654SJoe Wallwork     PetscBool hasTag;
247*41473654SJoe Wallwork     PetscInt  size;
248*41473654SJoe Wallwork 
249*41473654SJoe Wallwork     ierr = DMGetLabel(dmAdapt, "Face Sets", &bdLabel);CHKERRQ(ierr);
250*41473654SJoe Wallwork     ierr = DMLabelHasStratum(bdLabel, 1, &hasTag);CHKERRQ(ierr);
251*41473654SJoe Wallwork     if (!hasTag) SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Adapted mesh does not have face tag 1");
252*41473654SJoe Wallwork     ierr = DMLabelHasStratum(bdLabel, 2, &hasTag);CHKERRQ(ierr);
253*41473654SJoe Wallwork     if (!hasTag) SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Adapted mesh does not have face tag 2");
254*41473654SJoe Wallwork     ierr = DMLabelGetNumValues(bdLabel, &size);CHKERRQ(ierr);
255*41473654SJoe Wallwork     if (size != 2) SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Adapted mesh has the wrong number of face tags (got %d, expected 2)", size);
256*41473654SJoe Wallwork 
257*41473654SJoe Wallwork     ierr = DMGetLabel(dmAdapt, "Cell Sets", &rgLabel);CHKERRQ(ierr);
258*41473654SJoe Wallwork     ierr = DMLabelHasStratum(rgLabel, 3, &hasTag);CHKERRQ(ierr);
259*41473654SJoe Wallwork     if (!hasTag) SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Adapted mesh does not have cell tag 3");
260*41473654SJoe Wallwork     ierr = DMLabelHasStratum(rgLabel, 4, &hasTag);CHKERRQ(ierr);
261*41473654SJoe Wallwork     if (!hasTag) SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Adapted mesh does not have cell tag 4");
262*41473654SJoe Wallwork     ierr = DMLabelGetNumValues(rgLabel, &size);CHKERRQ(ierr);
263*41473654SJoe Wallwork     if (size != 2) SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Adapted mesh has the wrong number of cell tags (got %d, expected 2)", size);
264*41473654SJoe Wallwork   }
265*41473654SJoe Wallwork 
26600d473e3SJoe Wallwork   /* Clean up */
26700d473e3SJoe Wallwork   ierr = DMDestroy(&dmAdapt);CHKERRQ(ierr);
26800d473e3SJoe Wallwork   ierr = PetscFinalize();
26900d473e3SJoe Wallwork   return 0;
27000d473e3SJoe Wallwork }
27100d473e3SJoe Wallwork 
27200d473e3SJoe Wallwork /*TEST
27300d473e3SJoe Wallwork 
274dd0671eeSJoe Wallwork   test:
275dd0671eeSJoe Wallwork     suffix: uniform_2d_pragmatic
27600d473e3SJoe Wallwork     requires: pragmatic
277*41473654SJoe Wallwork     args: -dm_plex_metric_target_complexity 100 -dim 2 -dm_adaptor pragmatic -uniform -isotropic -noTagging
27800d473e3SJoe Wallwork   test:
279dd0671eeSJoe Wallwork     suffix: uniform_3d_pragmatic
280dd0671eeSJoe Wallwork     requires: pragmatic tetgen
281*41473654SJoe Wallwork     args: -dm_plex_metric_target_complexity 100 -dim 3 -dm_adaptor pragmatic -uniform -isotropic -noTagging
28200d473e3SJoe Wallwork   test:
283dd0671eeSJoe Wallwork     suffix: iso_2d_pragmatic
284dd0671eeSJoe Wallwork     requires: pragmatic
285*41473654SJoe Wallwork     args: -dm_plex_metric_target_complexity 100 -dim 2 -dm_adaptor pragmatic -isotropic -noTagging
28600d473e3SJoe Wallwork   test:
287dd0671eeSJoe Wallwork     suffix: iso_3d_pragmatic
288dd0671eeSJoe Wallwork     requires: pragmatic tetgen
289*41473654SJoe Wallwork     args: -dm_plex_metric_target_complexity 100 -dim 3 -dm_adaptor pragmatic -isotropic -noTagging
29000d473e3SJoe Wallwork   test:
291dd0671eeSJoe Wallwork     suffix: hessian_2d_pragmatic
292dd0671eeSJoe Wallwork     requires: pragmatic
293*41473654SJoe Wallwork     args: -dm_plex_metric_target_complexity 100 -dim 2 -dm_adaptor pragmatic -noTagging
29400d473e3SJoe Wallwork   test:
295dd0671eeSJoe Wallwork     suffix: hessian_3d_pragmatic
296dd0671eeSJoe Wallwork     requires: pragmatic tetgen
297*41473654SJoe Wallwork     args: -dm_plex_metric_target_complexity 100 -dim 3 -dm_adaptor pragmatic -noTagging
29800d473e3SJoe Wallwork   test:
299dd0671eeSJoe Wallwork     suffix: uniform_2d_mmg
300dd0671eeSJoe Wallwork     requires: mmg
301dd0671eeSJoe Wallwork     args: -dm_plex_metric_target_complexity 100 -dim 2 -dm_adaptor mmg -uniform -isotropic
302dd0671eeSJoe Wallwork   test:
303dd0671eeSJoe Wallwork     suffix: uniform_3d_mmg
304dd0671eeSJoe Wallwork     requires: mmg tetgen
305dd0671eeSJoe Wallwork     args: -dm_plex_metric_target_complexity 100 -dim 3 -dm_adaptor mmg -uniform -isotropic
306dd0671eeSJoe Wallwork   test:
307dd0671eeSJoe Wallwork     suffix: iso_2d_mmg
308dd0671eeSJoe Wallwork     requires: mmg
309dd0671eeSJoe Wallwork     args: -dm_plex_metric_target_complexity 100 -dim 2 -dm_adaptor mmg -isotropic
310dd0671eeSJoe Wallwork   test:
311dd0671eeSJoe Wallwork     suffix: iso_3d_mmg
312dd0671eeSJoe Wallwork     requires: mmg tetgen
313dd0671eeSJoe Wallwork     args: -dm_plex_metric_target_complexity 100 -dim 3 -dm_adaptor mmg -isotropic
314dd0671eeSJoe Wallwork   test:
315dd0671eeSJoe Wallwork     suffix: hessian_2d_mmg
316dd0671eeSJoe Wallwork     requires: mmg
317dd0671eeSJoe Wallwork     args: -dm_plex_metric_target_complexity 100 -dim 2 -dm_adaptor mmg
318dd0671eeSJoe Wallwork   test:
319dd0671eeSJoe Wallwork     suffix: hessian_3d_mmg
320dd0671eeSJoe Wallwork     requires: mmg tetgen
321dd0671eeSJoe Wallwork     args: -dm_plex_metric_target_complexity 100 -dim 3 -dm_adaptor mmg
322dd0671eeSJoe Wallwork   test:
323dd0671eeSJoe Wallwork     suffix: uniform_3d_parmmg
324dd0671eeSJoe Wallwork     requires: parmmg tetgen
325dd0671eeSJoe Wallwork     nsize: 2
326dd0671eeSJoe Wallwork     args: -dm_plex_metric_target_complexity 100 -dim 3 -dm_adaptor parmmg -uniform -isotropic
327dd0671eeSJoe Wallwork   test:
328dd0671eeSJoe Wallwork     suffix: iso_3d_parmmg
329dd0671eeSJoe Wallwork     requires: parmmg tetgen
330dd0671eeSJoe Wallwork     nsize: 2
331dd0671eeSJoe Wallwork     args: -dm_plex_metric_target_complexity 100 -dim 3 -dm_adaptor parmmg -isotropic
332dd0671eeSJoe Wallwork   test:
333dd0671eeSJoe Wallwork     suffix: hessian_3d_parmmg
334dd0671eeSJoe Wallwork     requires: parmmg tetgen
335dd0671eeSJoe Wallwork     nsize: 2
336dd0671eeSJoe Wallwork     args: -dm_plex_metric_target_complexity 100 -dim 3 -dm_adaptor parmmg
33700d473e3SJoe Wallwork 
33800d473e3SJoe Wallwork TEST*/
339