Actual source code: ex2.c

  1: static char help[] = "Create a mesh, refine and coarsen simultaneously, and transfer a field\n\n";

  3: #include <petscds.h>
  4: #include <petscdmplex.h>
  5: #include <petscdmforest.h>
  6: #include <petscoptions.h>

  8: static PetscErrorCode AddIdentityLabel(DM dm)
  9: {
 10:   PetscInt pStart, pEnd, p;

 12:   PetscFunctionBegin;
 13:   PetscCall(DMCreateLabel(dm, "identity"));
 14:   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
 15:   for (p = pStart; p < pEnd; p++) PetscCall(DMSetLabelValue(dm, "identity", p, p));
 16:   PetscFunctionReturn(PETSC_SUCCESS);
 17: }

 19: static PetscErrorCode CreateAdaptivityLabel(DM forest, DMLabel *adaptLabel)
 20: {
 21:   DMLabel  identLabel;
 22:   PetscInt cStart, cEnd, c;

 24:   PetscFunctionBegin;
 25:   PetscCall(DMLabelCreate(PETSC_COMM_SELF, "adapt", adaptLabel));
 26:   PetscCall(DMLabelSetDefaultValue(*adaptLabel, DM_ADAPT_COARSEN));
 27:   PetscCall(DMGetLabel(forest, "identity", &identLabel));
 28:   PetscCall(DMForestGetCellChart(forest, &cStart, &cEnd));
 29:   for (c = cStart; c < cEnd; c++) {
 30:     PetscInt basePoint;

 32:     PetscCall(DMLabelGetValue(identLabel, c, &basePoint));
 33:     if (!basePoint) PetscCall(DMLabelSetValue(*adaptLabel, c, DM_ADAPT_REFINE));
 34:   }
 35:   PetscFunctionReturn(PETSC_SUCCESS);
 36: }

 38: static PetscErrorCode LinearFunction(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], PetscCtx ctx)
 39: {
 40:   PetscFunctionBeginUser;
 41:   u[0] = (x[0] * 2.0 + 1.) + (x[1] * 20.0 + 10.) + ((dim == 3) ? (x[2] * 200.0 + 100.) : 0.);
 42:   PetscFunctionReturn(PETSC_SUCCESS);
 43: }

 45: static PetscErrorCode MultiaffineFunction(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], PetscCtx ctx)
 46: {
 47:   PetscFunctionBeginUser;
 48:   u[0] = (x[0] * 1.0 + 2.0) * (x[1] * 3.0 - 4.0) * ((dim == 3) ? (x[2] * 5.0 + 6.0) : 1.);
 49:   PetscFunctionReturn(PETSC_SUCCESS);
 50: }

 52: static PetscErrorCode CoordsFunction(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], PetscCtx ctx)
 53: {
 54:   PetscFunctionBeginUser;
 55:   for (PetscInt f = 0; f < Nf; f++) u[f] = x[f];
 56:   PetscFunctionReturn(PETSC_SUCCESS);
 57: }

 59: typedef struct _bc_func_ctx {
 60:   PetscErrorCode (*func)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *);
 61:   PetscInt dim;
 62:   PetscInt Nf;
 63:   void    *ctx;
 64: } bc_func_ctx;

 66: static PetscErrorCode bc_func_fv(PetscReal time, const PetscReal *c, const PetscReal *n, const PetscScalar *xI, PetscScalar *xG, PetscCtx ctx)
 67: {
 68:   bc_func_ctx *bcCtx;

 70:   PetscFunctionBegin;
 71:   bcCtx = (bc_func_ctx *)ctx;
 72:   PetscCall(bcCtx->func(bcCtx->dim, time, c, bcCtx->Nf, xG, bcCtx->ctx));
 73:   PetscFunctionReturn(PETSC_SUCCESS);
 74: }

 76: static PetscErrorCode IdentifyBadPoints(DM dm, Vec vec, PetscReal tol)
 77: {
 78:   DM           dmplex;
 79:   PetscInt     p, pStart, pEnd, maxDof;
 80:   Vec          vecLocal;
 81:   DMLabel      depthLabel;
 82:   PetscSection section;

 84:   PetscFunctionBegin;
 85:   PetscCall(DMCreateLocalVector(dm, &vecLocal));
 86:   PetscCall(DMGlobalToLocalBegin(dm, vec, INSERT_VALUES, vecLocal));
 87:   PetscCall(DMGlobalToLocalEnd(dm, vec, INSERT_VALUES, vecLocal));
 88:   PetscCall(DMConvert(dm, DMPLEX, &dmplex));
 89:   PetscCall(DMPlexGetChart(dmplex, &pStart, &pEnd));
 90:   PetscCall(DMPlexGetDepthLabel(dmplex, &depthLabel));
 91:   PetscCall(DMGetLocalSection(dmplex, &section));
 92:   PetscCall(PetscSectionGetMaxDof(section, &maxDof));
 93:   for (p = pStart; p < pEnd; p++) {
 94:     PetscInt     s, c, cSize, parent, childID, numChildren;
 95:     PetscInt     cl, closureSize, *closure = NULL;
 96:     PetscScalar *values = NULL;
 97:     PetscBool    bad    = PETSC_FALSE;

 99:     PetscCall(VecGetValuesSection(vecLocal, section, p, &values));
100:     PetscCall(PetscSectionGetDof(section, p, &cSize));
101:     for (c = 0; c < cSize; c++) {
102:       PetscReal absDiff = PetscAbsScalar(values[c]);
103:       if (absDiff > tol) {
104:         bad = PETSC_TRUE;
105:         break;
106:       }
107:     }
108:     if (!bad) continue;
109:     PetscCall(PetscPrintf(PETSC_COMM_SELF, "Bad point %" PetscInt_FMT "\n", p));
110:     PetscCall(DMLabelGetValue(depthLabel, p, &s));
111:     PetscCall(PetscPrintf(PETSC_COMM_SELF, "  Depth %" PetscInt_FMT "\n", s));
112:     PetscCall(DMPlexGetTransitiveClosure(dmplex, p, PETSC_TRUE, &closureSize, &closure));
113:     for (cl = 0; cl < closureSize; cl++) {
114:       PetscInt cp = closure[2 * cl];
115:       PetscCall(DMPlexGetTreeParent(dmplex, cp, &parent, &childID));
116:       if (parent != cp) PetscCall(PetscPrintf(PETSC_COMM_SELF, "  Closure point %" PetscInt_FMT " (%" PetscInt_FMT ") child of %" PetscInt_FMT " (ID %" PetscInt_FMT ")\n", cl, cp, parent, childID));
117:       PetscCall(DMPlexGetTreeChildren(dmplex, cp, &numChildren, NULL));
118:       if (numChildren) PetscCall(PetscPrintf(PETSC_COMM_SELF, "  Closure point %" PetscInt_FMT " (%" PetscInt_FMT ") is parent\n", cl, cp));
119:     }
120:     PetscCall(DMPlexRestoreTransitiveClosure(dmplex, p, PETSC_TRUE, &closureSize, &closure));
121:     for (c = 0; c < cSize; c++) {
122:       PetscReal absDiff = PetscAbsScalar(values[c]);
123:       if (absDiff > tol) PetscCall(PetscPrintf(PETSC_COMM_SELF, "  Bad dof %" PetscInt_FMT "\n", c));
124:     }
125:   }
126:   PetscCall(DMDestroy(&dmplex));
127:   PetscCall(VecDestroy(&vecLocal));
128:   PetscFunctionReturn(PETSC_SUCCESS);
129: }

131: int main(int argc, char **argv)
132: {
133:   MPI_Comm comm;
134:   DM       base, preForest, postForest;
135:   PetscInt dim, Nf          = 1;
136:   PetscInt step, adaptSteps = 1;
137:   PetscInt preCount, postCount;
138:   Vec      preVec, postVecTransfer, postVecExact;
139:   PetscErrorCode (*funcs[1])(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *) = {MultiaffineFunction};
140:   void       *ctxs[1]                                                                                 = {NULL};
141:   PetscReal   diff, tol = PETSC_SMALL;
142:   PetscBool   linear                = PETSC_FALSE;
143:   PetscBool   coords                = PETSC_FALSE;
144:   PetscBool   useFV                 = PETSC_FALSE;
145:   PetscBool   conv                  = PETSC_FALSE;
146:   PetscBool   transfer_from_base[2] = {PETSC_TRUE, PETSC_FALSE};
147:   PetscBool   use_bcs               = PETSC_TRUE;
148:   bc_func_ctx bcCtx;
149:   DMLabel     adaptLabel;

151:   PetscFunctionBeginUser;
152:   PetscCall(PetscInitialize(&argc, &argv, NULL, help));
153:   comm = PETSC_COMM_WORLD;
154:   PetscOptionsBegin(comm, "", "DMForestTransferVec() Test Options", "DMFOREST");
155:   PetscCall(PetscOptionsBool("-linear", "Transfer a simple linear function", "ex2.c", linear, &linear, NULL));
156:   PetscCall(PetscOptionsBool("-coords", "Transfer a simple coordinate function", "ex2.c", coords, &coords, NULL));
157:   PetscCall(PetscOptionsBool("-use_fv", "Use a finite volume approximation", "ex2.c", useFV, &useFV, NULL));
158:   PetscCall(PetscOptionsBool("-test_convert", "Test conversion to DMPLEX", NULL, conv, &conv, NULL));
159:   PetscCall(PetscOptionsBool("-transfer_from_base", "Transfer a vector from base DM to DMForest", "ex2.c", transfer_from_base[0], &transfer_from_base[0], NULL));
160:   transfer_from_base[1] = transfer_from_base[0];
161:   PetscCall(PetscOptionsBool("-transfer_from_base_steps", "Transfer a vector from base DM to the latest DMForest after the adaptivity steps", "ex2.c", transfer_from_base[1], &transfer_from_base[1], NULL));
162:   PetscCall(PetscOptionsBool("-use_bcs", "Use dirichlet boundary conditions", "ex2.c", use_bcs, &use_bcs, NULL));
163:   PetscCall(PetscOptionsBoundedInt("-adapt_steps", "Number of adaptivity steps", "ex2.c", adaptSteps, &adaptSteps, NULL, 0));
164:   PetscOptionsEnd();

166:   tol = PetscMax(1.e-10, tol); /* XXX fix for quadruple precision -> why do I need to do this? */

168:   /* the base mesh */
169:   PetscCall(DMCreate(comm, &base));
170:   PetscCall(DMSetType(base, DMPLEX));
171:   PetscCall(DMSetFromOptions(base));

173:   PetscCall(AddIdentityLabel(base));
174:   PetscCall(DMGetDimension(base, &dim));

176:   if (linear) funcs[0] = LinearFunction;
177:   if (coords) {
178:     funcs[0] = CoordsFunction;
179:     Nf       = dim;
180:   }

182:   bcCtx.func = funcs[0];
183:   bcCtx.dim  = dim;
184:   bcCtx.Nf   = Nf;
185:   bcCtx.ctx  = NULL;

187:   if (useFV) {
188:     PetscFV      fv;
189:     PetscLimiter limiter;
190:     DM           baseFV;

192:     PetscCall(DMPlexConstructGhostCells(base, NULL, NULL, &baseFV));
193:     PetscCall(DMViewFromOptions(baseFV, NULL, "-fv_dm_view"));
194:     PetscCall(DMDestroy(&base));
195:     base = baseFV;
196:     PetscCall(PetscFVCreate(PETSC_COMM_SELF, &fv));
197:     PetscCall(PetscFVSetSpatialDimension(fv, dim));
198:     PetscCall(PetscFVSetType(fv, PETSCFVLEASTSQUARES));
199:     PetscCall(PetscFVSetNumComponents(fv, Nf));
200:     PetscCall(PetscLimiterCreate(comm, &limiter));
201:     PetscCall(PetscLimiterSetType(limiter, PETSCLIMITERNONE));
202:     PetscCall(PetscFVSetLimiter(fv, limiter));
203:     PetscCall(PetscLimiterDestroy(&limiter));
204:     PetscCall(PetscFVSetFromOptions(fv));
205:     PetscCall(DMSetField(base, 0, NULL, (PetscObject)fv));
206:     PetscCall(PetscFVDestroy(&fv));
207:   } else {
208:     PetscFE fe;

210:     PetscCall(PetscFECreateDefault(comm, dim, Nf, PETSC_FALSE, NULL, PETSC_DEFAULT, &fe));
211:     PetscCall(DMSetField(base, 0, NULL, (PetscObject)fe));
212:     PetscCall(PetscFEDestroy(&fe));
213:   }
214:   PetscCall(DMCreateDS(base));

216:   if (use_bcs) {
217:     PetscInt ids[] = {1, 2, 3, 4, 5, 6};
218:     DMLabel  label;

220:     PetscCall(DMGetLabel(base, "marker", &label));
221:     PetscCall(DMAddBoundary(base, DM_BC_ESSENTIAL, "bc", label, 2 * dim, ids, 0, 0, NULL, useFV ? (PetscVoidFn *)bc_func_fv : (PetscVoidFn *)funcs[0], NULL, useFV ? (void *)&bcCtx : NULL, NULL));
222:   }
223:   PetscCall(DMViewFromOptions(base, NULL, "-dm_base_view"));

225:   /* the pre adaptivity forest */
226:   PetscCall(DMCreate(comm, &preForest));
227:   PetscCall(DMSetType(preForest, (dim == 2) ? DMP4EST : DMP8EST));
228:   PetscCall(DMCopyDisc(base, preForest));
229:   PetscCall(DMForestSetBaseDM(preForest, base));
230:   PetscCall(DMForestSetMinimumRefinement(preForest, 0));
231:   PetscCall(DMForestSetInitialRefinement(preForest, 1));
232:   PetscCall(DMSetFromOptions(preForest));
233:   PetscCall(DMSetUp(preForest));
234:   PetscCall(DMViewFromOptions(preForest, NULL, "-dm_pre_view"));

236:   /* the pre adaptivity field */
237:   PetscCall(DMCreateGlobalVector(preForest, &preVec));
238:   PetscCall(DMProjectFunction(preForest, 0., funcs, ctxs, INSERT_VALUES, preVec));
239:   PetscCall(VecViewFromOptions(preVec, NULL, "-vec_pre_view"));

241:   /* communicate between base and pre adaptivity forest */
242:   if (transfer_from_base[0]) {
243:     Vec baseVec, baseVecMapped;

245:     PetscCall(DMGetGlobalVector(base, &baseVec));
246:     PetscCall(DMProjectFunction(base, 0., funcs, ctxs, INSERT_VALUES, baseVec));
247:     PetscCall(PetscObjectSetName((PetscObject)baseVec, "Function Base"));
248:     PetscCall(VecViewFromOptions(baseVec, NULL, "-vec_base_view"));

250:     PetscCall(DMGetGlobalVector(preForest, &baseVecMapped));
251:     PetscCall(DMForestTransferVecFromBase(preForest, baseVec, baseVecMapped));
252:     PetscCall(VecViewFromOptions(baseVecMapped, NULL, "-vec_map_base_view"));

254:     /* compare */
255:     PetscCall(VecAXPY(baseVecMapped, -1., preVec));
256:     PetscCall(VecViewFromOptions(baseVecMapped, NULL, "-vec_map_diff_view"));
257:     PetscCall(VecNorm(baseVecMapped, NORM_2, &diff));

259:     /* output */
260:     if (diff < tol) {
261:       PetscCall(PetscPrintf(comm, "DMForestTransferVecFromBase() passes.\n"));
262:     } else {
263:       PetscCall(PetscPrintf(comm, "DMForestTransferVecFromBase() fails with error %g and tolerance %g\n", (double)diff, (double)tol));
264:     }

266:     PetscCall(DMRestoreGlobalVector(base, &baseVec));
267:     PetscCall(DMRestoreGlobalVector(preForest, &baseVecMapped));
268:   }

270:   for (step = 0; step < adaptSteps; ++step) {
271:     if (!transfer_from_base[1]) PetscCall(PetscObjectGetReference((PetscObject)preForest, &preCount));

273:     /* adapt */
274:     PetscCall(CreateAdaptivityLabel(preForest, &adaptLabel));
275:     PetscCall(DMForestTemplate(preForest, comm, &postForest));
276:     if (step) PetscCall(DMForestSetAdaptivityLabel(postForest, adaptLabel));
277:     PetscCall(DMLabelDestroy(&adaptLabel));
278:     PetscCall(DMSetUp(postForest));
279:     PetscCall(DMViewFromOptions(postForest, NULL, "-dm_post_view"));

281:     /* transfer */
282:     PetscCall(DMCreateGlobalVector(postForest, &postVecTransfer));
283:     PetscCall(DMForestTransferVec(preForest, preVec, postForest, postVecTransfer, PETSC_TRUE, 0.0));
284:     PetscCall(VecViewFromOptions(postVecTransfer, NULL, "-vec_post_transfer_view"));

286:     /* the exact post adaptivity field */
287:     PetscCall(DMCreateGlobalVector(postForest, &postVecExact));
288:     PetscCall(DMProjectFunction(postForest, 0., funcs, ctxs, INSERT_VALUES, postVecExact));
289:     PetscCall(VecViewFromOptions(postVecExact, NULL, "-vec_post_exact_view"));

291:     /* compare */
292:     PetscCall(VecAXPY(postVecExact, -1., postVecTransfer));
293:     PetscCall(VecViewFromOptions(postVecExact, NULL, "-vec_diff_view"));
294:     PetscCall(VecNorm(postVecExact, NORM_2, &diff));

296:     /* output */
297:     if (diff < tol) {
298:       PetscCall(PetscPrintf(comm, "DMForestTransferVec() passes.\n"));
299:     } else {
300:       PetscCall(PetscPrintf(comm, "DMForestTransferVec() fails with error %g and tolerance %g\n", (double)diff, (double)tol));
301:       PetscCall(IdentifyBadPoints(postForest, postVecExact, tol));
302:     }
303:     PetscCall(VecDestroy(&postVecExact));

305:     /* disconnect preForest from postForest if we don't test the transfer throughout the entire refinement process */
306:     if (!transfer_from_base[1]) {
307:       PetscCall(DMForestSetAdaptivityForest(postForest, NULL));
308:       PetscCall(PetscObjectGetReference((PetscObject)preForest, &postCount));
309:       PetscCheck(postCount == preCount, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Adaptation not memory neutral: reference count increase from %" PetscInt_FMT " to %" PetscInt_FMT, preCount, postCount);
310:     }

312:     if (conv) {
313:       DM dmConv;

315:       PetscCall(DMConvert(postForest, DMPLEX, &dmConv));
316:       PetscCall(DMViewFromOptions(dmConv, NULL, "-dm_conv_view"));
317:       PetscCall(DMPlexCheckCellShape(dmConv, PETSC_TRUE, PETSC_DETERMINE));
318:       PetscCall(DMDestroy(&dmConv));
319:     }

321:     PetscCall(VecDestroy(&preVec));
322:     PetscCall(DMDestroy(&preForest));

324:     preVec    = postVecTransfer;
325:     preForest = postForest;
326:   }

328:   if (transfer_from_base[1]) {
329:     Vec baseVec, baseVecMapped;

331:     /* communicate between base and last adapted forest */
332:     PetscCall(DMGetGlobalVector(base, &baseVec));
333:     PetscCall(DMProjectFunction(base, 0., funcs, ctxs, INSERT_VALUES, baseVec));
334:     PetscCall(PetscObjectSetName((PetscObject)baseVec, "Function Base"));
335:     PetscCall(VecViewFromOptions(baseVec, NULL, "-vec_base_view"));

337:     PetscCall(DMGetGlobalVector(preForest, &baseVecMapped));
338:     PetscCall(DMForestTransferVecFromBase(preForest, baseVec, baseVecMapped));
339:     PetscCall(VecViewFromOptions(baseVecMapped, NULL, "-vec_map_base_view"));

341:     /* compare */
342:     PetscCall(VecAXPY(baseVecMapped, -1., preVec));
343:     PetscCall(VecViewFromOptions(baseVecMapped, NULL, "-vec_map_diff_view"));
344:     PetscCall(VecNorm(baseVecMapped, NORM_2, &diff));

346:     /* output */
347:     if (diff < tol) {
348:       PetscCall(PetscPrintf(comm, "DMForestTransferVecFromBase() passes.\n"));
349:     } else {
350:       PetscCall(PetscPrintf(comm, "DMForestTransferVecFromBase() fails with error %g and tolerance %g\n", (double)diff, (double)tol));
351:     }

353:     PetscCall(DMRestoreGlobalVector(base, &baseVec));
354:     PetscCall(DMRestoreGlobalVector(preForest, &baseVecMapped));
355:   }

357:   /* cleanup */
358:   PetscCall(VecDestroy(&preVec));
359:   PetscCall(DMDestroy(&preForest));
360:   PetscCall(DMDestroy(&base));
361:   PetscCall(PetscFinalize());
362:   return 0;
363: }

365: /*TEST
366:   testset:
367:     args: -dm_plex_simplex 0 -dm_plex_box_faces 3,3,3 -petscspace_type tensor

369:     test:
370:       output_file: output/ex2_2d.out
371:       suffix: p4est_2d
372:       args: -petscspace_degree 2
373:       nsize: 3
374:       requires: p4est !single

376:     test:
377:       output_file: output/ex2_2d.out
378:       suffix: p4est_2d_deg4
379:       args: -petscspace_degree 4
380:       requires: p4est !single

382:     test:
383:       output_file: output/ex2_2d.out
384:       suffix: p4est_2d_deg8
385:       args: -petscspace_degree 8
386:       requires: p4est !single

388:     test:
389:       output_file: output/ex2_steps2.out
390:       suffix: p4est_2d_deg2_steps2
391:       args: -petscspace_degree 2 -coords -adapt_steps 2
392:       nsize: 3
393:       requires: p4est !single

395:     test:
396:       output_file: output/ex2_steps3.out
397:       suffix: p4est_2d_deg3_steps3
398:       args: -petscspace_degree 3 -coords -adapt_steps 3 -petscdualspace_lagrange_node_type equispaced -petscdualspace_lagrange_node_endpoints 1
399:       nsize: 3
400:       requires: p4est !single

402:     test:
403:       output_file: output/ex2_steps3.out
404:       suffix: p4est_2d_deg3_steps3_L2_periodic
405:       args: -petscspace_degree 3 -petscdualspace_lagrange_continuity 0 -coords -adapt_steps 3 -dm_plex_box_bd periodic,periodic -use_bcs 0 -petscdualspace_lagrange_node_type equispaced
406:       nsize: 3
407:       requires: p4est !single

409:     test:
410:       output_file: output/ex2_steps3.out
411:       suffix: p4est_3d_deg2_steps3_L2_periodic
412:       args: -dm_plex_dim 3 -petscspace_degree 2 -petscdualspace_lagrange_continuity 0 -coords -adapt_steps 3 -dm_plex_box_bd periodic,periodic,periodic -use_bcs 0
413:       nsize: 3
414:       requires: p4est !single

416:     test:
417:       output_file: output/ex2_steps2.out
418:       suffix: p4est_3d_deg2_steps2
419:       args: -dm_plex_dim 3 -petscspace_degree 2 -coords -adapt_steps 2
420:       nsize: 3
421:       requires: p4est !single

423:     test:
424:       output_file: output/ex2_steps3.out
425:       suffix: p4est_3d_deg3_steps3
426:       args: -dm_plex_dim 3 -petscspace_degree 3 -coords -adapt_steps 3 -petscdualspace_lagrange_node_type equispaced -petscdualspace_lagrange_node_endpoints 1
427:       nsize: 3
428:       requires: p4est !single

430:     test:
431:       output_file: output/ex2_3d.out
432:       suffix: p4est_3d
433:       args: -dm_plex_dim 3 -petscspace_degree 1
434:       nsize: 3
435:       requires: p4est !single

437:     test:
438:       output_file: output/ex2_3d.out
439:       suffix: p4est_3d_deg3
440:       args: -dm_plex_dim 3 -petscspace_degree 3
441:       nsize: 3
442:       requires: p4est !single

444:     test:
445:       output_file: output/ex2_2d.out
446:       suffix: p4est_2d_deg2_coords
447:       args: -petscspace_degree 2 -coords
448:       nsize: 3
449:       requires: p4est !single

451:     test:
452:       output_file: output/ex2_3d.out
453:       suffix: p4est_3d_deg2_coords
454:       args: -dm_plex_dim 3 -petscspace_degree 2 -coords
455:       nsize: 3
456:       requires: p4est !single

458:     test:
459:       suffix: p4est_3d_nans
460:       args: -dm_plex_dim 3 -dm_forest_partition_overlap 1 -test_convert -petscspace_degree 1
461:       nsize: 2
462:       requires: p4est !single

464:     test:
465:       TODO: not broken, but the 3D case below is broken, so I do not trust this one
466:       output_file: output/ex2_steps2.out
467:       suffix: p4est_2d_tfb_distributed_nc
468:       args: -petscspace_degree 3 -dm_forest_maximum_refinement 2 -dm_p4est_refine_pattern hash -use_bcs 0 -coords -adapt_steps 2 -petscpartitioner_type shell -petscpartitioner_shell_random
469:       nsize: 3
470:       requires: p4est !single

472:     test:
473:       TODO: broken
474:       output_file: output/ex2_steps2.out
475:       suffix: p4est_3d_tfb_distributed_nc
476:       args: -dm_plex_dim 3 -petscspace_degree 2 -dm_forest_maximum_refinement 2 -dm_p4est_refine_pattern hash -use_bcs 0 -coords -adapt_steps 2 -petscpartitioner_type shell -petscpartitioner_shell_random
477:       nsize: 3
478:       requires: p4est !single

480:   testset:
481:     args: -petscspace_type tensor -dm_coord_space 0 -dm_plex_transform_type refine_tobox

483:     test:
484:       TODO: broken
485:       output_file: output/ex2_3d.out
486:       suffix: p4est_3d_transfer_fails
487:       args: -petscspace_degree 1 -dm_plex_filename ${wPETSC_DIR}/share/petsc/datafiles/meshes/doublet-tet.msh -adapt_steps 1 -dm_forest_initial_refinement 1 -use_bcs 0 -dm_refine
488:       requires: p4est !single

490:     test:
491:       TODO: broken
492:       output_file: output/ex2_steps2_notfb.out
493:       suffix: p4est_3d_transfer_fails_2
494:       args: -petscspace_degree 1 -dm_plex_filename ${wPETSC_DIR}/share/petsc/datafiles/meshes/doublet-tet.msh -adapt_steps 2 -dm_forest_initial_refinement 0 -transfer_from_base 0 -use_bcs 0 -dm_refine
495:       requires: p4est !single

497:     test:
498:       output_file: output/ex2_steps2.out
499:       suffix: p4est_3d_multi_transfer_s2t
500:       args: -petscspace_degree 3 -dm_plex_filename ${wPETSC_DIR}/share/petsc/datafiles/meshes/doublet-tet.msh -adapt_steps 2 -dm_forest_initial_refinement 1 -petscdualspace_lagrange_continuity 0 -use_bcs 0 -dm_refine 1
501:       requires: p4est !single

503:     test:
504:       output_file: output/ex2_steps2.out
505:       suffix: p4est_3d_coords_transfer_s2t
506:       args: -petscspace_degree 3 -dm_plex_filename ${wPETSC_DIR}/share/petsc/datafiles/meshes/doublet-tet.msh -adapt_steps 2 -dm_forest_initial_refinement 1 -petscdualspace_lagrange_continuity 0 -coords -use_bcs 0 -dm_refine 1
507:       requires: p4est !single

509:   testset:
510:     args: -dm_plex_simplex 0 -dm_plex_box_faces 3,3,3

512:     test:
513:       output_file: output/ex2_2d_fv.out
514:       suffix: p4est_2d_fv
515:       args: -transfer_from_base 0 -use_fv -linear -dm_forest_partition_overlap 1
516:       nsize: 3
517:       requires: p4est !single

519:     test:
520:       TODO: broken (codimension adjacency)
521:       output_file: output/ex2_2d_fv.out
522:       suffix: p4est_2d_fv_adjcodim
523:       args: -transfer_from_base 0 -use_fv -linear -dm_forest_partition_overlap 1 -dm_forest_adjacency_codimension 1
524:       nsize: 2
525:       requires: p4est !single

527:     test:
528:       TODO: broken (dimension adjacency)
529:       output_file: output/ex2_2d_fv.out
530:       suffix: p4est_2d_fv_adjdim
531:       args: -transfer_from_base 0 -use_fv -linear -dm_forest_partition_overlap 1 -dm_forest_adjacency_dimension 1
532:       nsize: 2
533:       requires: p4est !single

535:     test:
536:       output_file: output/ex2_2d_fv.out
537:       suffix: p4est_2d_fv_zerocells
538:       args: -transfer_from_base 0 -use_fv -linear -dm_forest_partition_overlap 1
539:       nsize: 10
540:       requires: p4est !single

542:     test:
543:       output_file: output/ex2_3d_fv.out
544:       suffix: p4est_3d_fv
545:       args: -dm_plex_dim 3 -transfer_from_base 0 -use_fv -linear -dm_forest_partition_overlap 1
546:       nsize: 3
547:       requires: p4est !single

549: TEST*/