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:   DMCreateLabel(dm, "identity");
 13:   DMPlexGetChart(dm, &pStart, &pEnd);
 14:   for (p = pStart; p < pEnd; p++) DMSetLabelValue(dm, "identity", p, p);
 15:   return 0;
 16: }

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

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

 30:     DMLabelGetValue(identLabel,c,&basePoint);
 31:     if (!basePoint) DMLabelSetValue(*adaptLabel,c,DM_ADAPT_REFINE);
 32:   }
 33:   return 0;
 34: }

 36: static PetscErrorCode LinearFunction(PetscInt dim,PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx)
 37: {
 39:   u[0] = (x[0] * 2.0 + 1.) + (x[1] * 20.0 + 10.) + ((dim == 3) ? (x[2] * 200.0 + 100.) : 0.);
 40:   return 0;
 41: }

 43: static PetscErrorCode MultiaffineFunction(PetscInt dim,PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx)
 44: {
 46:   u[0] = (x[0] * 1.0 + 2.0) * (x[1] * 3.0 - 4.0) * ((dim == 3) ? (x[2] * 5.0 + 6.0) : 1.);
 47:   return 0;
 48: }

 50: static PetscErrorCode CoordsFunction(PetscInt dim,PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx)
 51: {
 52:   PetscInt f;

 55:   for (f=0;f<Nf;f++) u[f] = x[f];
 56:   return 0;
 57: }

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

 68: static PetscErrorCode bc_func_fv (PetscReal time, const PetscReal *c, const PetscReal *n, const PetscScalar *xI, PetscScalar *xG, void *ctx)
 69: {
 70:   bc_func_ctx    *bcCtx;

 72:   bcCtx = (bc_func_ctx *) ctx;
 73:   (bcCtx->func)(bcCtx->dim,time,c,bcCtx->Nf,xG,bcCtx->ctx);
 74:   return 0;
 75: }

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

 85:   DMCreateLocalVector(dm, &vecLocal);
 86:   DMGlobalToLocalBegin(dm, vec, INSERT_VALUES, vecLocal);
 87:   DMGlobalToLocalEnd(dm, vec, INSERT_VALUES, vecLocal);
 88:   DMConvert(dm ,DMPLEX, &dmplex);
 89:   DMPlexGetChart(dmplex, &pStart, &pEnd);
 90:   DMPlexGetDepthLabel(dmplex, &depthLabel);
 91:   DMGetLocalSection(dmplex, &section);
 92:   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:     VecGetValuesSection(vecLocal, section, p, &values);
100:     PetscSectionGetDof(section, p, &cSize);
101:     for (c = 0; c < cSize; c++) {
102:       PetscReal absDiff = PetscAbsScalar(values[c]);
103:       if (absDiff > tol) {bad = PETSC_TRUE; break;}
104:     }
105:     if (!bad) continue;
106:     PetscPrintf(PETSC_COMM_SELF, "Bad point %D\n", p);
107:     DMLabelGetValue(depthLabel, p, &s);
108:     PetscPrintf(PETSC_COMM_SELF, "  Depth %D\n", s);
109:     DMPlexGetTransitiveClosure(dmplex, p, PETSC_TRUE, &closureSize, &closure);
110:     for (cl = 0; cl < closureSize; cl++) {
111:       PetscInt cp = closure[2 * cl];
112:       DMPlexGetTreeParent(dmplex, cp, &parent, &childID);
113:       if (parent != cp) {
114:         PetscPrintf(PETSC_COMM_SELF, "  Closure point %D (%D) child of %D (ID %D)\n", cl, cp, parent, childID);
115:       }
116:       DMPlexGetTreeChildren(dmplex, cp, &numChildren, NULL);
117:       if (numChildren) {
118:         PetscPrintf(PETSC_COMM_SELF, "  Closure point %D (%D) is parent\n", cl, cp);
119:       }
120:     }
121:     DMPlexRestoreTransitiveClosure(dmplex, p, PETSC_TRUE, &closureSize, &closure);
122:     for (c = 0; c < cSize; c++) {
123:       PetscReal absDiff = PetscAbsScalar(values[c]);
124:       if (absDiff > tol) {
125:         PetscPrintf(PETSC_COMM_SELF, "  Bad dof %D\n", c);
126:       }
127:     }
128:   }
129:   DMDestroy(&dmplex);
130:   VecDestroy(&vecLocal);
131:   return 0;
132: }

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

155:   PetscInitialize(&argc, &argv, NULL,help);
156:   comm = PETSC_COMM_WORLD;
157:   PetscOptionsBegin(comm, "", "DMForestTransferVec() Test Options", "DMFOREST");
158:   PetscOptionsBool("-linear","Transfer a simple linear function", "ex2.c", linear, &linear, NULL);
159:   PetscOptionsBool("-coords","Transfer a simple coordinate function", "ex2.c", coords, &coords, NULL);
160:   PetscOptionsBool("-use_fv","Use a finite volume approximation", "ex2.c", useFV, &useFV, NULL);
161:   PetscOptionsBool("-test_convert","Test conversion to DMPLEX",NULL,conv,&conv,NULL);
162:   PetscOptionsBool("-transfer_from_base","Transfer a vector from base DM to DMForest", "ex2.c", transfer_from_base[0], &transfer_from_base[0], NULL);
163:   transfer_from_base[1] = transfer_from_base[0];
164:   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);
165:   PetscOptionsBool("-use_bcs","Use dirichlet boundary conditions", "ex2.c", use_bcs, &use_bcs, NULL);
166:   PetscOptionsBoundedInt("-adapt_steps","Number of adaptivity steps", "ex2.c", adaptSteps, &adaptSteps, NULL,0);
167:   PetscOptionsEnd();

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

171:   /* the base mesh */
172:   DMCreate(comm, &base);
173:   DMSetType(base, DMPLEX);
174:   DMSetFromOptions(base);

176:   AddIdentityLabel(base);
177:   DMGetDimension(base, &dim);

179:   if (linear) {
180:     funcs[0] = LinearFunction;
181:   }
182:   if (coords) {
183:     funcs[0] = CoordsFunction;
184:     Nf = dim;
185:   }

187:   bcCtx.func = funcs[0];
188:   bcCtx.dim  = dim;
189:   bcCtx.Nf   = Nf;
190:   bcCtx.ctx  = NULL;

192:   if (useFV) {
193:     PetscFV      fv;
194:     PetscLimiter limiter;
195:     DM           baseFV;

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

215:     PetscFECreateDefault(comm,dim,Nf,PETSC_FALSE,NULL,PETSC_DEFAULT,&fe);
216:     DMSetField(base,0,NULL,(PetscObject)fe);
217:     PetscFEDestroy(&fe);
218:   }
219:   DMCreateDS(base);

221:   if (use_bcs) {
222:     PetscInt ids[] = {1, 2, 3, 4, 5, 6};
223:     DMLabel  label;

225:     DMGetLabel(base, "marker", &label);
226:     DMAddBoundary(base,DM_BC_ESSENTIAL, "bc", label, 2 * dim, ids, 0, 0, NULL, useFV ? (void(*)(void)) bc_func_fv : (void(*)(void)) funcs[0], NULL, useFV ? (void *) &bcCtx : NULL, NULL);
227:   }
228:   DMViewFromOptions(base,NULL,"-dm_base_view");

230:   /* the pre adaptivity forest */
231:   DMCreate(comm,&preForest);
232:   DMSetType(preForest,(dim == 2) ? DMP4EST : DMP8EST);
233:   DMCopyDisc(base,preForest);
234:   DMForestSetBaseDM(preForest,base);
235:   DMForestSetMinimumRefinement(preForest,0);
236:   DMForestSetInitialRefinement(preForest,1);
237:   DMSetFromOptions(preForest);
238:   DMSetUp(preForest);
239:   DMViewFromOptions(preForest,NULL,"-dm_pre_view");

241:   /* the pre adaptivity field */
242:   DMCreateGlobalVector(preForest,&preVec);
243:   DMProjectFunction(preForest,0.,funcs,ctxs,INSERT_VALUES,preVec);
244:   VecViewFromOptions(preVec,NULL,"-vec_pre_view");

246:   /* communicate between base and pre adaptivity forest */
247:   if (transfer_from_base[0]) {
248:     Vec baseVec, baseVecMapped;

250:     DMGetGlobalVector(base,&baseVec);
251:     DMProjectFunction(base,0.,funcs,ctxs,INSERT_VALUES,baseVec);
252:     PetscObjectSetName((PetscObject)baseVec,"Function Base");
253:     VecViewFromOptions(baseVec,NULL,"-vec_base_view");

255:     DMGetGlobalVector(preForest,&baseVecMapped);
256:     DMForestTransferVecFromBase(preForest,baseVec,baseVecMapped);
257:     VecViewFromOptions(baseVecMapped,NULL,"-vec_map_base_view");

259:     /* compare */
260:     VecAXPY(baseVecMapped,-1.,preVec);
261:     VecViewFromOptions(baseVecMapped,NULL,"-vec_map_diff_view");
262:     VecNorm(baseVecMapped,NORM_2,&diff);

264:     /* output */
265:     if (diff < tol) {
266:       PetscPrintf(comm,"DMForestTransferVecFromBase() passes.\n");
267:     } else {
268:       PetscPrintf(comm,"DMForestTransferVecFromBase() fails with error %g and tolerance %g\n",(double)diff,(double)tol);
269:     }

271:     DMRestoreGlobalVector(base,&baseVec);
272:     DMRestoreGlobalVector(preForest,&baseVecMapped);
273:   }

275:   for (step = 0; step < adaptSteps; ++step) {

277:     if (!transfer_from_base[1]) {
278:       PetscObjectGetReference((PetscObject)preForest,&preCount);
279:     }

281:     /* adapt */
282:     CreateAdaptivityLabel(preForest,&adaptLabel);
283:     DMForestTemplate(preForest,comm,&postForest);
284:     if (step) DMForestSetAdaptivityLabel(postForest,adaptLabel);
285:     DMLabelDestroy(&adaptLabel);
286:     DMSetUp(postForest);
287:     DMViewFromOptions(postForest,NULL,"-dm_post_view");

289:     /* transfer */
290:     DMCreateGlobalVector(postForest,&postVecTransfer);
291:     DMForestTransferVec(preForest,preVec,postForest,postVecTransfer,PETSC_TRUE,0.0);
292:     VecViewFromOptions(postVecTransfer,NULL,"-vec_post_transfer_view");

294:     /* the exact post adaptivity field */
295:     DMCreateGlobalVector(postForest,&postVecExact);
296:     DMProjectFunction(postForest,0.,funcs,ctxs,INSERT_VALUES,postVecExact);
297:     VecViewFromOptions(postVecExact,NULL,"-vec_post_exact_view");

299:     /* compare */
300:     VecAXPY(postVecExact,-1.,postVecTransfer);
301:     VecViewFromOptions(postVecExact,NULL,"-vec_diff_view");
302:     VecNorm(postVecExact,NORM_2,&diff);

304:     /* output */
305:     if (diff < tol) {
306:       PetscPrintf(comm,"DMForestTransferVec() passes.\n");
307:     } else {
308:       PetscPrintf(comm,"DMForestTransferVec() fails with error %g and tolerance %g\n",(double)diff,(double)tol);
309:       IdentifyBadPoints(postForest, postVecExact, tol);
310:     }
311:     VecDestroy(&postVecExact);

313:     /* disconnect preForest from postForest if we don't test the transfer throughout the entire refinement process */
314:     if (!transfer_from_base[1]) {
315:       DMForestSetAdaptivityForest(postForest,NULL);
316:       PetscObjectGetReference((PetscObject)preForest,&postCount);
318:     }

320:     if (conv) {
321:       DM dmConv;

323:       DMConvert(postForest,DMPLEX,&dmConv);
324:       DMViewFromOptions(dmConv,NULL,"-dm_conv_view");
325:       DMPlexCheckCellShape(dmConv,PETSC_TRUE,PETSC_DETERMINE);
326:       DMDestroy(&dmConv);
327:     }

329:     VecDestroy(&preVec);
330:     DMDestroy(&preForest);

332:     preVec    = postVecTransfer;
333:     preForest = postForest;
334:   }

336:   if (transfer_from_base[1]) {
337:     Vec baseVec, baseVecMapped;

339:     /* communicate between base and last adapted forest */
340:     DMGetGlobalVector(base,&baseVec);
341:     DMProjectFunction(base,0.,funcs,ctxs,INSERT_VALUES,baseVec);
342:     PetscObjectSetName((PetscObject)baseVec,"Function Base");
343:     VecViewFromOptions(baseVec,NULL,"-vec_base_view");

345:     DMGetGlobalVector(preForest,&baseVecMapped);
346:     DMForestTransferVecFromBase(preForest,baseVec,baseVecMapped);
347:     VecViewFromOptions(baseVecMapped,NULL,"-vec_map_base_view");

349:     /* compare */
350:     VecAXPY(baseVecMapped,-1.,preVec);
351:     VecViewFromOptions(baseVecMapped,NULL,"-vec_map_diff_view");
352:     VecNorm(baseVecMapped,NORM_2,&diff);

354:     /* output */
355:     if (diff < tol) {
356:       PetscPrintf(comm,"DMForestTransferVecFromBase() passes.\n");
357:     } else {
358:       PetscPrintf(comm,"DMForestTransferVecFromBase() fails with error %g and tolerance %g\n",(double)diff,(double)tol);
359:     }

361:     DMRestoreGlobalVector(base,&baseVec);
362:     DMRestoreGlobalVector(preForest,&baseVecMapped);
363:   }

365:   /* cleanup */
366:   VecDestroy(&preVec);
367:   DMDestroy(&preForest);
368:   DMDestroy(&base);
369:   PetscFinalize();
370:   return 0;
371: }

373: /*TEST
374:   testset:
375:     args: -dm_plex_simplex 0 -dm_plex_box_faces 3,3,3 -petscspace_type tensor

377:     test:
378:       output_file: output/ex2_2d.out
379:       suffix: p4est_2d
380:       args: -petscspace_degree 2
381:       nsize: 3
382:       requires: p4est !single

384:     test:
385:       output_file: output/ex2_2d.out
386:       suffix: p4est_2d_deg4
387:       args: -petscspace_degree 4
388:       requires: p4est !single

390:     test:
391:       output_file: output/ex2_2d.out
392:       suffix: p4est_2d_deg8
393:       args: -petscspace_degree 8
394:       requires: p4est !single

396:     test:
397:       output_file: output/ex2_steps2.out
398:       suffix: p4est_2d_deg2_steps2
399:       args: -petscspace_degree 2 -coords -adapt_steps 2
400:       nsize: 3
401:       requires: p4est !single

403:     test:
404:       output_file: output/ex2_steps3.out
405:       suffix: p4est_2d_deg3_steps3
406:       args: -petscspace_degree 3 -coords -adapt_steps 3 -petscdualspace_lagrange_node_type equispaced -petscdualspace_lagrange_node_endpoints 1
407:       nsize: 3
408:       requires: p4est !single

410:     test:
411:       output_file: output/ex2_steps3.out
412:       suffix: p4est_2d_deg3_steps3_L2_periodic
413:       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
414:       nsize: 3
415:       requires: p4est !single

417:     test:
418:       output_file: output/ex2_steps3.out
419:       suffix: p4est_3d_deg2_steps3_L2_periodic
420:       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
421:       nsize: 3
422:       requires: p4est !single

424:     test:
425:       output_file: output/ex2_steps2.out
426:       suffix: p4est_3d_deg2_steps2
427:       args: -dm_plex_dim 3 -petscspace_degree 2 -coords -adapt_steps 2
428:       nsize: 3
429:       requires: p4est !single

431:     test:
432:       output_file: output/ex2_steps3.out
433:       suffix: p4est_3d_deg3_steps3
434:       args: -dm_plex_dim 3 -petscspace_degree 3 -coords -adapt_steps 3 -petscdualspace_lagrange_node_type equispaced -petscdualspace_lagrange_node_endpoints 1
435:       nsize: 3
436:       requires: p4est !single

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

445:     test:
446:       output_file: output/ex2_3d.out
447:       suffix: p4est_3d_deg3
448:       args: -dm_plex_dim 3 -petscspace_degree 3
449:       nsize: 3
450:       requires: p4est !single

452:     test:
453:       output_file: output/ex2_2d.out
454:       suffix: p4est_2d_deg2_coords
455:       args: -petscspace_degree 2 -coords
456:       nsize: 3
457:       requires: p4est !single

459:     test:
460:       output_file: output/ex2_3d.out
461:       suffix: p4est_3d_deg2_coords
462:       args: -dm_plex_dim 3 -petscspace_degree 2 -coords
463:       nsize: 3
464:       requires: p4est !single

466:     test:
467:       suffix: p4est_3d_nans
468:       args: -dm_plex_dim 3 -dm_forest_partition_overlap 1 -test_convert -petscspace_degree 1
469:       nsize: 2
470:       requires: p4est !single

472:     test:
473:       TODO: not broken, but the 3D case below is broken, so I do not trust this one
474:       output_file: output/ex2_steps2.out
475:       suffix: p4est_2d_tfb_distributed_nc
476:       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
477:       nsize: 3
478:       requires: p4est !single

480:     test:
481:       TODO: broken
482:       output_file: output/ex2_steps2.out
483:       suffix: p4est_3d_tfb_distributed_nc
484:       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
485:       nsize: 3
486:       requires: p4est !single

488:   testset:
489:     args: -petscspace_type tensor -dm_coord_space 0 -dm_plex_transform_type refine_tobox

491:     test:
492:       TODO: broken
493:       output_file: output/ex2_3d.out
494:       suffix: p4est_3d_transfer_fails
495:       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
496:       requires: p4est !single

498:     test:
499:       TODO: broken
500:       output_file: output/ex2_steps2_notfb.out
501:       suffix: p4est_3d_transfer_fails_2
502:       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
503:       requires: p4est !single

505:     test:
506:       output_file: output/ex2_steps2.out
507:       suffix: p4est_3d_multi_transfer_s2t
508:       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
509:       requires: p4est !single

511:     test:
512:       output_file: output/ex2_steps2.out
513:       suffix: p4est_3d_coords_transfer_s2t
514:       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
515:       requires: p4est !single

517:   testset:
518:     args: -dm_plex_simplex 0 -dm_plex_box_faces 3,3,3

520:     test:
521:       output_file: output/ex2_2d_fv.out
522:       suffix: p4est_2d_fv
523:       args: -transfer_from_base 0 -use_fv -linear -dm_forest_partition_overlap 1
524:       nsize: 3
525:       requires: p4est !single

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

535:     test:
536:       TODO: broken (dimension adjacency)
537:       output_file: output/ex2_2d_fv.out
538:       suffix: p4est_2d_fv_adjdim
539:       args: -transfer_from_base 0 -use_fv -linear -dm_forest_partition_overlap 1 -dm_forest_adjacency_dimension 1
540:       nsize: 2
541:       requires: p4est !single

543:     test:
544:       output_file: output/ex2_2d_fv.out
545:       suffix: p4est_2d_fv_zerocells
546:       args: -transfer_from_base 0 -use_fv -linear -dm_forest_partition_overlap 1
547:       nsize: 10
548:       requires: p4est !single

550:     test:
551:       output_file: output/ex2_3d_fv.out
552:       suffix: p4est_3d_fv
553:       args: -dm_plex_dim 3 -transfer_from_base 0 -use_fv -linear -dm_forest_partition_overlap 1
554:       nsize: 3
555:       requires: p4est !single

557: TEST*/