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: 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, void *ctx)
67: {
68: bc_func_ctx *bcCtx;
70: bcCtx = (bc_func_ctx *)ctx;
71: (bcCtx->func)(bcCtx->dim, time, c, bcCtx->Nf, xG, bcCtx->ctx);
72: return 0;
73: }
75: static PetscErrorCode IdentifyBadPoints(DM dm, Vec vec, PetscReal tol)
76: {
77: DM dmplex;
78: PetscInt p, pStart, pEnd, maxDof;
79: Vec vecLocal;
80: DMLabel depthLabel;
81: PetscSection section;
83: DMCreateLocalVector(dm, &vecLocal);
84: DMGlobalToLocalBegin(dm, vec, INSERT_VALUES, vecLocal);
85: DMGlobalToLocalEnd(dm, vec, INSERT_VALUES, vecLocal);
86: DMConvert(dm, DMPLEX, &dmplex);
87: DMPlexGetChart(dmplex, &pStart, &pEnd);
88: DMPlexGetDepthLabel(dmplex, &depthLabel);
89: DMGetLocalSection(dmplex, §ion);
90: PetscSectionGetMaxDof(section, &maxDof);
91: for (p = pStart; p < pEnd; p++) {
92: PetscInt s, c, cSize, parent, childID, numChildren;
93: PetscInt cl, closureSize, *closure = NULL;
94: PetscScalar *values = NULL;
95: PetscBool bad = PETSC_FALSE;
97: VecGetValuesSection(vecLocal, section, p, &values);
98: PetscSectionGetDof(section, p, &cSize);
99: for (c = 0; c < cSize; c++) {
100: PetscReal absDiff = PetscAbsScalar(values[c]);
101: if (absDiff > tol) {
102: bad = PETSC_TRUE;
103: break;
104: }
105: }
106: if (!bad) continue;
107: PetscPrintf(PETSC_COMM_SELF, "Bad point %" PetscInt_FMT "\n", p);
108: DMLabelGetValue(depthLabel, p, &s);
109: PetscPrintf(PETSC_COMM_SELF, " Depth %" PetscInt_FMT "\n", s);
110: DMPlexGetTransitiveClosure(dmplex, p, PETSC_TRUE, &closureSize, &closure);
111: for (cl = 0; cl < closureSize; cl++) {
112: PetscInt cp = closure[2 * cl];
113: DMPlexGetTreeParent(dmplex, cp, &parent, &childID);
114: if (parent != cp) PetscPrintf(PETSC_COMM_SELF, " Closure point %" PetscInt_FMT " (%" PetscInt_FMT ") child of %" PetscInt_FMT " (ID %" PetscInt_FMT ")\n", cl, cp, parent, childID);
115: DMPlexGetTreeChildren(dmplex, cp, &numChildren, NULL);
116: if (numChildren) PetscPrintf(PETSC_COMM_SELF, " Closure point %" PetscInt_FMT " (%" PetscInt_FMT ") is parent\n", cl, cp);
117: }
118: DMPlexRestoreTransitiveClosure(dmplex, p, PETSC_TRUE, &closureSize, &closure);
119: for (c = 0; c < cSize; c++) {
120: PetscReal absDiff = PetscAbsScalar(values[c]);
121: if (absDiff > tol) PetscPrintf(PETSC_COMM_SELF, " Bad dof %" PetscInt_FMT "\n", c);
122: }
123: }
124: DMDestroy(&dmplex);
125: VecDestroy(&vecLocal);
126: return 0;
127: }
129: int main(int argc, char **argv)
130: {
131: MPI_Comm comm;
132: DM base, preForest, postForest;
133: PetscInt dim, Nf = 1;
134: PetscInt step, adaptSteps = 1;
135: PetscInt preCount, postCount;
136: Vec preVec, postVecTransfer, postVecExact;
137: PetscErrorCode (*funcs[1])(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *) = {MultiaffineFunction};
138: void *ctxs[1] = {NULL};
139: PetscReal diff, tol = PETSC_SMALL;
140: PetscBool linear = PETSC_FALSE;
141: PetscBool coords = PETSC_FALSE;
142: PetscBool useFV = PETSC_FALSE;
143: PetscBool conv = PETSC_FALSE;
144: PetscBool transfer_from_base[2] = {PETSC_TRUE, PETSC_FALSE};
145: PetscBool use_bcs = PETSC_TRUE;
146: bc_func_ctx bcCtx;
147: DMLabel adaptLabel;
150: PetscInitialize(&argc, &argv, NULL, help);
151: comm = PETSC_COMM_WORLD;
152: PetscOptionsBegin(comm, "", "DMForestTransferVec() Test Options", "DMFOREST");
153: PetscOptionsBool("-linear", "Transfer a simple linear function", "ex2.c", linear, &linear, NULL);
154: PetscOptionsBool("-coords", "Transfer a simple coordinate function", "ex2.c", coords, &coords, NULL);
155: PetscOptionsBool("-use_fv", "Use a finite volume approximation", "ex2.c", useFV, &useFV, NULL);
156: PetscOptionsBool("-test_convert", "Test conversion to DMPLEX", NULL, conv, &conv, NULL);
157: PetscOptionsBool("-transfer_from_base", "Transfer a vector from base DM to DMForest", "ex2.c", transfer_from_base[0], &transfer_from_base[0], NULL);
158: transfer_from_base[1] = transfer_from_base[0];
159: 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);
160: PetscOptionsBool("-use_bcs", "Use dirichlet boundary conditions", "ex2.c", use_bcs, &use_bcs, NULL);
161: PetscOptionsBoundedInt("-adapt_steps", "Number of adaptivity steps", "ex2.c", adaptSteps, &adaptSteps, NULL, 0);
162: PetscOptionsEnd();
164: tol = PetscMax(1.e-10, tol); /* XXX fix for quadruple precision -> why do I need to do this? */
166: /* the base mesh */
167: DMCreate(comm, &base);
168: DMSetType(base, DMPLEX);
169: DMSetFromOptions(base);
171: AddIdentityLabel(base);
172: DMGetDimension(base, &dim);
174: if (linear) funcs[0] = LinearFunction;
175: if (coords) {
176: funcs[0] = CoordsFunction;
177: Nf = dim;
178: }
180: bcCtx.func = funcs[0];
181: bcCtx.dim = dim;
182: bcCtx.Nf = Nf;
183: bcCtx.ctx = NULL;
185: if (useFV) {
186: PetscFV fv;
187: PetscLimiter limiter;
188: DM baseFV;
190: DMPlexConstructGhostCells(base, NULL, NULL, &baseFV);
191: DMViewFromOptions(baseFV, NULL, "-fv_dm_view");
192: DMDestroy(&base);
193: base = baseFV;
194: PetscFVCreate(PETSC_COMM_SELF, &fv);
195: PetscFVSetSpatialDimension(fv, dim);
196: PetscFVSetType(fv, PETSCFVLEASTSQUARES);
197: PetscFVSetNumComponents(fv, Nf);
198: PetscLimiterCreate(comm, &limiter);
199: PetscLimiterSetType(limiter, PETSCLIMITERNONE);
200: PetscFVSetLimiter(fv, limiter);
201: PetscLimiterDestroy(&limiter);
202: PetscFVSetFromOptions(fv);
203: DMSetField(base, 0, NULL, (PetscObject)fv);
204: PetscFVDestroy(&fv);
205: } else {
206: PetscFE fe;
208: PetscFECreateDefault(comm, dim, Nf, PETSC_FALSE, NULL, PETSC_DEFAULT, &fe);
209: DMSetField(base, 0, NULL, (PetscObject)fe);
210: PetscFEDestroy(&fe);
211: }
212: DMCreateDS(base);
214: if (use_bcs) {
215: PetscInt ids[] = {1, 2, 3, 4, 5, 6};
216: DMLabel label;
218: DMGetLabel(base, "marker", &label);
219: 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);
220: }
221: DMViewFromOptions(base, NULL, "-dm_base_view");
223: /* the pre adaptivity forest */
224: DMCreate(comm, &preForest);
225: DMSetType(preForest, (dim == 2) ? DMP4EST : DMP8EST);
226: DMCopyDisc(base, preForest);
227: DMForestSetBaseDM(preForest, base);
228: DMForestSetMinimumRefinement(preForest, 0);
229: DMForestSetInitialRefinement(preForest, 1);
230: DMSetFromOptions(preForest);
231: DMSetUp(preForest);
232: DMViewFromOptions(preForest, NULL, "-dm_pre_view");
234: /* the pre adaptivity field */
235: DMCreateGlobalVector(preForest, &preVec);
236: DMProjectFunction(preForest, 0., funcs, ctxs, INSERT_VALUES, preVec);
237: VecViewFromOptions(preVec, NULL, "-vec_pre_view");
239: /* communicate between base and pre adaptivity forest */
240: if (transfer_from_base[0]) {
241: Vec baseVec, baseVecMapped;
243: DMGetGlobalVector(base, &baseVec);
244: DMProjectFunction(base, 0., funcs, ctxs, INSERT_VALUES, baseVec);
245: PetscObjectSetName((PetscObject)baseVec, "Function Base");
246: VecViewFromOptions(baseVec, NULL, "-vec_base_view");
248: DMGetGlobalVector(preForest, &baseVecMapped);
249: DMForestTransferVecFromBase(preForest, baseVec, baseVecMapped);
250: VecViewFromOptions(baseVecMapped, NULL, "-vec_map_base_view");
252: /* compare */
253: VecAXPY(baseVecMapped, -1., preVec);
254: VecViewFromOptions(baseVecMapped, NULL, "-vec_map_diff_view");
255: VecNorm(baseVecMapped, NORM_2, &diff);
257: /* output */
258: if (diff < tol) {
259: PetscPrintf(comm, "DMForestTransferVecFromBase() passes.\n");
260: } else {
261: PetscPrintf(comm, "DMForestTransferVecFromBase() fails with error %g and tolerance %g\n", (double)diff, (double)tol);
262: }
264: DMRestoreGlobalVector(base, &baseVec);
265: DMRestoreGlobalVector(preForest, &baseVecMapped);
266: }
268: for (step = 0; step < adaptSteps; ++step) {
269: if (!transfer_from_base[1]) PetscObjectGetReference((PetscObject)preForest, &preCount);
271: /* adapt */
272: CreateAdaptivityLabel(preForest, &adaptLabel);
273: DMForestTemplate(preForest, comm, &postForest);
274: if (step) DMForestSetAdaptivityLabel(postForest, adaptLabel);
275: DMLabelDestroy(&adaptLabel);
276: DMSetUp(postForest);
277: DMViewFromOptions(postForest, NULL, "-dm_post_view");
279: /* transfer */
280: DMCreateGlobalVector(postForest, &postVecTransfer);
281: DMForestTransferVec(preForest, preVec, postForest, postVecTransfer, PETSC_TRUE, 0.0);
282: VecViewFromOptions(postVecTransfer, NULL, "-vec_post_transfer_view");
284: /* the exact post adaptivity field */
285: DMCreateGlobalVector(postForest, &postVecExact);
286: DMProjectFunction(postForest, 0., funcs, ctxs, INSERT_VALUES, postVecExact);
287: VecViewFromOptions(postVecExact, NULL, "-vec_post_exact_view");
289: /* compare */
290: VecAXPY(postVecExact, -1., postVecTransfer);
291: VecViewFromOptions(postVecExact, NULL, "-vec_diff_view");
292: VecNorm(postVecExact, NORM_2, &diff);
294: /* output */
295: if (diff < tol) {
296: PetscPrintf(comm, "DMForestTransferVec() passes.\n");
297: } else {
298: PetscPrintf(comm, "DMForestTransferVec() fails with error %g and tolerance %g\n", (double)diff, (double)tol);
299: IdentifyBadPoints(postForest, postVecExact, tol);
300: }
301: VecDestroy(&postVecExact);
303: /* disconnect preForest from postForest if we don't test the transfer throughout the entire refinement process */
304: if (!transfer_from_base[1]) {
305: DMForestSetAdaptivityForest(postForest, NULL);
306: PetscObjectGetReference((PetscObject)preForest, &postCount);
308: }
310: if (conv) {
311: DM dmConv;
313: DMConvert(postForest, DMPLEX, &dmConv);
314: DMViewFromOptions(dmConv, NULL, "-dm_conv_view");
315: DMPlexCheckCellShape(dmConv, PETSC_TRUE, PETSC_DETERMINE);
316: DMDestroy(&dmConv);
317: }
319: VecDestroy(&preVec);
320: DMDestroy(&preForest);
322: preVec = postVecTransfer;
323: preForest = postForest;
324: }
326: if (transfer_from_base[1]) {
327: Vec baseVec, baseVecMapped;
329: /* communicate between base and last adapted forest */
330: DMGetGlobalVector(base, &baseVec);
331: DMProjectFunction(base, 0., funcs, ctxs, INSERT_VALUES, baseVec);
332: PetscObjectSetName((PetscObject)baseVec, "Function Base");
333: VecViewFromOptions(baseVec, NULL, "-vec_base_view");
335: DMGetGlobalVector(preForest, &baseVecMapped);
336: DMForestTransferVecFromBase(preForest, baseVec, baseVecMapped);
337: VecViewFromOptions(baseVecMapped, NULL, "-vec_map_base_view");
339: /* compare */
340: VecAXPY(baseVecMapped, -1., preVec);
341: VecViewFromOptions(baseVecMapped, NULL, "-vec_map_diff_view");
342: VecNorm(baseVecMapped, NORM_2, &diff);
344: /* output */
345: if (diff < tol) {
346: PetscPrintf(comm, "DMForestTransferVecFromBase() passes.\n");
347: } else {
348: PetscPrintf(comm, "DMForestTransferVecFromBase() fails with error %g and tolerance %g\n", (double)diff, (double)tol);
349: }
351: DMRestoreGlobalVector(base, &baseVec);
352: DMRestoreGlobalVector(preForest, &baseVecMapped);
353: }
355: /* cleanup */
356: VecDestroy(&preVec);
357: DMDestroy(&preForest);
358: DMDestroy(&base);
359: PetscFinalize();
360: return 0;
361: }
363: /*TEST
364: testset:
365: args: -dm_plex_simplex 0 -dm_plex_box_faces 3,3,3 -petscspace_type tensor
367: test:
368: output_file: output/ex2_2d.out
369: suffix: p4est_2d
370: args: -petscspace_degree 2
371: nsize: 3
372: requires: p4est !single
374: test:
375: output_file: output/ex2_2d.out
376: suffix: p4est_2d_deg4
377: args: -petscspace_degree 4
378: requires: p4est !single
380: test:
381: output_file: output/ex2_2d.out
382: suffix: p4est_2d_deg8
383: args: -petscspace_degree 8
384: requires: p4est !single
386: test:
387: output_file: output/ex2_steps2.out
388: suffix: p4est_2d_deg2_steps2
389: args: -petscspace_degree 2 -coords -adapt_steps 2
390: nsize: 3
391: requires: p4est !single
393: test:
394: output_file: output/ex2_steps3.out
395: suffix: p4est_2d_deg3_steps3
396: args: -petscspace_degree 3 -coords -adapt_steps 3 -petscdualspace_lagrange_node_type equispaced -petscdualspace_lagrange_node_endpoints 1
397: nsize: 3
398: requires: p4est !single
400: test:
401: output_file: output/ex2_steps3.out
402: suffix: p4est_2d_deg3_steps3_L2_periodic
403: 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
404: nsize: 3
405: requires: p4est !single
407: test:
408: output_file: output/ex2_steps3.out
409: suffix: p4est_3d_deg2_steps3_L2_periodic
410: 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
411: nsize: 3
412: requires: p4est !single
414: test:
415: output_file: output/ex2_steps2.out
416: suffix: p4est_3d_deg2_steps2
417: args: -dm_plex_dim 3 -petscspace_degree 2 -coords -adapt_steps 2
418: nsize: 3
419: requires: p4est !single
421: test:
422: output_file: output/ex2_steps3.out
423: suffix: p4est_3d_deg3_steps3
424: args: -dm_plex_dim 3 -petscspace_degree 3 -coords -adapt_steps 3 -petscdualspace_lagrange_node_type equispaced -petscdualspace_lagrange_node_endpoints 1
425: nsize: 3
426: requires: p4est !single
428: test:
429: output_file: output/ex2_3d.out
430: suffix: p4est_3d
431: args: -dm_plex_dim 3 -petscspace_degree 1
432: nsize: 3
433: requires: p4est !single
435: test:
436: output_file: output/ex2_3d.out
437: suffix: p4est_3d_deg3
438: args: -dm_plex_dim 3 -petscspace_degree 3
439: nsize: 3
440: requires: p4est !single
442: test:
443: output_file: output/ex2_2d.out
444: suffix: p4est_2d_deg2_coords
445: args: -petscspace_degree 2 -coords
446: nsize: 3
447: requires: p4est !single
449: test:
450: output_file: output/ex2_3d.out
451: suffix: p4est_3d_deg2_coords
452: args: -dm_plex_dim 3 -petscspace_degree 2 -coords
453: nsize: 3
454: requires: p4est !single
456: test:
457: suffix: p4est_3d_nans
458: args: -dm_plex_dim 3 -dm_forest_partition_overlap 1 -test_convert -petscspace_degree 1
459: nsize: 2
460: requires: p4est !single
462: test:
463: TODO: not broken, but the 3D case below is broken, so I do not trust this one
464: output_file: output/ex2_steps2.out
465: suffix: p4est_2d_tfb_distributed_nc
466: 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
467: nsize: 3
468: requires: p4est !single
470: test:
471: TODO: broken
472: output_file: output/ex2_steps2.out
473: suffix: p4est_3d_tfb_distributed_nc
474: 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
475: nsize: 3
476: requires: p4est !single
478: testset:
479: args: -petscspace_type tensor -dm_coord_space 0 -dm_plex_transform_type refine_tobox
481: test:
482: TODO: broken
483: output_file: output/ex2_3d.out
484: suffix: p4est_3d_transfer_fails
485: 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
486: requires: p4est !single
488: test:
489: TODO: broken
490: output_file: output/ex2_steps2_notfb.out
491: suffix: p4est_3d_transfer_fails_2
492: 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
493: requires: p4est !single
495: test:
496: output_file: output/ex2_steps2.out
497: suffix: p4est_3d_multi_transfer_s2t
498: 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
499: requires: p4est !single
501: test:
502: output_file: output/ex2_steps2.out
503: suffix: p4est_3d_coords_transfer_s2t
504: 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
505: requires: p4est !single
507: testset:
508: args: -dm_plex_simplex 0 -dm_plex_box_faces 3,3,3
510: test:
511: output_file: output/ex2_2d_fv.out
512: suffix: p4est_2d_fv
513: args: -transfer_from_base 0 -use_fv -linear -dm_forest_partition_overlap 1
514: nsize: 3
515: requires: p4est !single
517: test:
518: TODO: broken (codimension adjacency)
519: output_file: output/ex2_2d_fv.out
520: suffix: p4est_2d_fv_adjcodim
521: args: -transfer_from_base 0 -use_fv -linear -dm_forest_partition_overlap 1 -dm_forest_adjacency_codimension 1
522: nsize: 2
523: requires: p4est !single
525: test:
526: TODO: broken (dimension adjacency)
527: output_file: output/ex2_2d_fv.out
528: suffix: p4est_2d_fv_adjdim
529: args: -transfer_from_base 0 -use_fv -linear -dm_forest_partition_overlap 1 -dm_forest_adjacency_dimension 1
530: nsize: 2
531: requires: p4est !single
533: test:
534: output_file: output/ex2_2d_fv.out
535: suffix: p4est_2d_fv_zerocells
536: args: -transfer_from_base 0 -use_fv -linear -dm_forest_partition_overlap 1
537: nsize: 10
538: requires: p4est !single
540: test:
541: output_file: output/ex2_3d_fv.out
542: suffix: p4est_3d_fv
543: args: -dm_plex_dim 3 -transfer_from_base 0 -use_fv -linear -dm_forest_partition_overlap 1
544: nsize: 3
545: requires: p4est !single
547: TEST*/