Actual source code: ex56.c

  1: #include <petscdmplex.h>
  2: #include <petscviewerhdf5.h>
  3: #include <petscsf.h>

  5: static const char help[] = "Test DMLabel I/O with PETSc native HDF5 mesh format\n\n";
  6: static const char EX[]   = "ex56.c";
  7: typedef struct {
  8:   MPI_Comm    comm;
  9:   const char *meshname;                    /* Mesh name */
 10:   PetscInt    num_labels;                  /* Asserted number of labels in loaded mesh */
 11:   PetscBool   compare;                     /* Compare the meshes using DMPlexEqual() and DMCompareLabels() */
 12:   PetscBool   compare_labels;              /* Compare labels in the meshes using DMCompareLabels() */
 13:   PetscBool   compare_boundary;            /* Check label I/O via boundary vertex coordinates */
 14:   PetscBool   compare_pre_post;            /* Compare labels loaded before distribution with those loaded after distribution */
 15:   char        outfile[PETSC_MAX_PATH_LEN]; /* Output file */
 16:   PetscBool   use_low_level_functions;     /* Use low level functions for viewing and loading */
 17:   //TODO This is meant as temporary option; can be removed once we have full parallel loading in place
 18:   PetscBool distribute_after_topo_load; /* Distribute topology right after DMPlexTopologyLoad(), if use_low_level_functions=true */
 19:   PetscInt  verbose;
 20: } AppCtx;

 22: static PetscErrorCode ProcessOptions(MPI_Comm comm, AppCtx *options)
 23: {
 24:   PetscFunctionBeginUser;
 25:   options->comm                       = comm;
 26:   options->num_labels                 = -1;
 27:   options->compare                    = PETSC_FALSE;
 28:   options->compare_labels             = PETSC_FALSE;
 29:   options->compare_boundary           = PETSC_FALSE;
 30:   options->compare_pre_post           = PETSC_FALSE;
 31:   options->outfile[0]                 = '\0';
 32:   options->use_low_level_functions    = PETSC_FALSE;
 33:   options->distribute_after_topo_load = PETSC_FALSE;
 34:   options->verbose                    = 0;

 36:   PetscOptionsBegin(comm, "", "Meshing Problem Options", "DMPLEX");
 37:   PetscCall(PetscOptionsInt("-num_labels", "Asserted number of labels in meshfile; don't count depth and celltype; -1 to deactivate", EX, options->num_labels, &options->num_labels, NULL));
 38:   PetscCall(PetscOptionsBool("-compare", "Compare the meshes using DMPlexEqual() and DMCompareLabels()", EX, options->compare, &options->compare, NULL));
 39:   PetscCall(PetscOptionsBool("-compare_labels", "Compare labels in the meshes using DMCompareLabels()", "ex55.c", options->compare_labels, &options->compare_labels, NULL));
 40:   PetscCall(PetscOptionsBool("-compare_boundary", "Check label I/O via boundary vertex coordinates", "ex55.c", options->compare_boundary, &options->compare_boundary, NULL));
 41:   PetscCall(PetscOptionsBool("-compare_pre_post", "Compare labels loaded before distribution with those loaded after distribution", "ex55.c", options->compare_pre_post, &options->compare_pre_post, NULL));
 42:   PetscCall(PetscOptionsString("-outfile", "Output mesh file", EX, options->outfile, options->outfile, sizeof(options->outfile), NULL));
 43:   PetscCall(PetscOptionsBool("-use_low_level_functions", "Use low level functions for viewing and loading", EX, options->use_low_level_functions, &options->use_low_level_functions, NULL));
 44:   PetscCall(PetscOptionsBool("-distribute_after_topo_load", "Distribute topology right after DMPlexTopologyLoad(), if use_low_level_functions=true", EX, options->distribute_after_topo_load, &options->distribute_after_topo_load, NULL));
 45:   PetscCall(PetscOptionsInt("-verbose", "Verbosity level", EX, options->verbose, &options->verbose, NULL));
 46:   PetscOptionsEnd();
 47:   PetscFunctionReturn(PETSC_SUCCESS);
 48: }

 50: static PetscErrorCode CreateMesh(AppCtx *options, DM *newdm)
 51: {
 52:   DM dm;

 54:   PetscFunctionBeginUser;
 55:   PetscCall(DMCreate(options->comm, &dm));
 56:   PetscCall(DMSetType(dm, DMPLEX));
 57:   PetscCall(DMSetFromOptions(dm));
 58:   PetscCall(PetscObjectGetName((PetscObject)dm, &options->meshname));
 59:   PetscCall(DMViewFromOptions(dm, NULL, "-dm_view"));
 60:   *newdm = dm;
 61:   PetscFunctionReturn(PETSC_SUCCESS);
 62: }

 64: static PetscErrorCode SaveMesh(AppCtx *options, DM dm)
 65: {
 66:   PetscViewer v;

 68:   PetscFunctionBeginUser;
 69:   PetscCall(PetscViewerHDF5Open(PetscObjectComm((PetscObject)dm), options->outfile, FILE_MODE_WRITE, &v));
 70:   if (options->use_low_level_functions) {
 71:     PetscCall(DMPlexTopologyView(dm, v));
 72:     PetscCall(DMPlexCoordinatesView(dm, v));
 73:     PetscCall(DMPlexLabelsView(dm, v));
 74:   } else {
 75:     PetscCall(DMView(dm, v));
 76:   }
 77:   PetscCall(PetscViewerDestroy(&v));
 78:   PetscFunctionReturn(PETSC_SUCCESS);
 79: }

 81: typedef enum {
 82:   NONE      = 0,
 83:   PRE_DIST  = 1,
 84:   POST_DIST = 2
 85: } AuxObjLoadMode;

 87: static PetscErrorCode LoadMeshLowLevel(AppCtx *options, PetscViewer v, PetscBool explicitDistribute, AuxObjLoadMode mode, DM *newdm)
 88: {
 89:   DM      dm;
 90:   PetscSF sfXC;

 92:   PetscFunctionBeginUser;
 93:   PetscCall(DMCreate(options->comm, &dm));
 94:   PetscCall(DMSetType(dm, DMPLEX));
 95:   PetscCall(PetscObjectSetName((PetscObject)dm, options->meshname));
 96:   PetscCall(DMPlexTopologyLoad(dm, v, &sfXC));
 97:   if (mode == PRE_DIST) {
 98:     PetscCall(DMPlexCoordinatesLoad(dm, v, sfXC));
 99:     PetscCall(DMPlexLabelsLoad(dm, v, sfXC));
100:   }
101:   if (explicitDistribute) {
102:     DM               dmdist;
103:     PetscSF          sfXB = sfXC, sfBC;
104:     PetscPartitioner part;

106:     PetscCall(DMPlexGetPartitioner(dm, &part));
107:     PetscCall(PetscPartitionerSetFromOptions(part));
108:     PetscCall(DMPlexDistribute(dm, 0, &sfBC, &dmdist));
109:     if (dmdist) {
110:       const char *name;

112:       PetscCall(PetscObjectGetName((PetscObject)dm, &name));
113:       PetscCall(PetscObjectSetName((PetscObject)dmdist, name));
114:       PetscCall(PetscSFCompose(sfXB, sfBC, &sfXC));
115:       PetscCall(PetscSFDestroy(&sfXB));
116:       PetscCall(PetscSFDestroy(&sfBC));
117:       PetscCall(DMDestroy(&dm));
118:       dm = dmdist;
119:     }
120:   }
121:   if (mode == POST_DIST) {
122:     PetscCall(DMPlexLabelsLoad(dm, v, sfXC));
123:     PetscCall(DMPlexCoordinatesLoad(dm, v, sfXC));
124:   }
125:   PetscCall(PetscSFDestroy(&sfXC));
126:   *newdm = dm;
127:   PetscFunctionReturn(PETSC_SUCCESS);
128: }

130: static PetscErrorCode LoadMesh(AppCtx *options, DM *dmnew)
131: {
132:   DM          dm;
133:   PetscViewer v;

135:   PetscFunctionBeginUser;
136:   PetscCall(PetscViewerHDF5Open(options->comm, options->outfile, FILE_MODE_READ, &v));
137:   if (options->use_low_level_functions) {
138:     if (options->compare_pre_post) {
139:       DM dm0;

141:       PetscCall(LoadMeshLowLevel(options, v, PETSC_TRUE, PRE_DIST, &dm0));
142:       PetscCall(LoadMeshLowLevel(options, v, PETSC_TRUE, POST_DIST, &dm));
143:       PetscCall(DMCompareLabels(dm0, dm, NULL, NULL));
144:       PetscCall(DMDestroy(&dm0));
145:     } else {
146:       PetscCall(LoadMeshLowLevel(options, v, options->distribute_after_topo_load, POST_DIST, &dm));
147:     }
148:   } else {
149:     PetscCall(DMCreate(options->comm, &dm));
150:     PetscCall(DMSetType(dm, DMPLEX));
151:     PetscCall(PetscObjectSetName((PetscObject)dm, options->meshname));
152:     PetscCall(DMLoad(dm, v));
153:   }
154:   PetscCall(PetscViewerDestroy(&v));
155:   DMLabel celltypes;
156:   PetscCall(DMPlexGetCellTypeLabel(dm, &celltypes));

158:   PetscCall(DMSetOptionsPrefix(dm, "load_"));
159:   PetscCall(DMSetFromOptions(dm));
160:   PetscCall(DMViewFromOptions(dm, NULL, "-dm_view"));
161:   *dmnew = dm;
162:   PetscFunctionReturn(PETSC_SUCCESS);
163: }

165: static PetscErrorCode CompareMeshes(AppCtx *options, DM dm0, DM dm1)
166: {
167:   PetscBool flg;

169:   PetscFunctionBeginUser;
170:   if (options->compare) {
171:     PetscCall(DMPlexEqual(dm0, dm1, &flg));
172:     PetscCheck(flg, options->comm, PETSC_ERR_ARG_INCOMP, "DMs are not equal");
173:     PetscCall(PetscPrintf(options->comm, "DMs equal\n"));
174:   }
175:   if (options->compare_labels) {
176:     PetscCall(DMCompareLabels(dm0, dm1, NULL, NULL));
177:     PetscCall(PetscPrintf(options->comm, "DMLabels equal\n"));
178:   }
179:   PetscFunctionReturn(PETSC_SUCCESS);
180: }

182: static PetscErrorCode MarkBoundary(DM dm, const char name[], PetscInt value, PetscBool verticesOnly, DMLabel *label)
183: {
184:   DMLabel l;

186:   PetscFunctionBeginUser;
187:   PetscCall(DMLabelCreate(PetscObjectComm((PetscObject)dm), name, &l));
188:   PetscCall(DMAddLabel(dm, l));
189:   PetscCall(DMPlexMarkBoundaryFaces(dm, value, l));
190:   PetscCall(DMPlexLabelComplete(dm, l));
191:   if (verticesOnly) {
192:     IS              points;
193:     const PetscInt *idx;
194:     PetscInt        i, n = 0;

196:     PetscCall(DMLabelGetStratumIS(l, value, &points));
197:     if (points) {
198:       PetscCall(ISGetLocalSize(points, &n));
199:       PetscCall(ISGetIndices(points, &idx));
200:     }
201:     for (i = 0; i < n; i++) {
202:       const PetscInt p = idx[i];
203:       PetscInt       d;

205:       PetscCall(DMPlexGetPointDepth(dm, p, &d));
206:       if (d != 0) PetscCall(DMLabelClearValue(l, p, value));
207:     }
208:     if (points) PetscCall(ISRestoreIndices(points, &idx));
209:     PetscCall(ISDestroy(&points));
210:   }
211:   if (label) *label = l;
212:   else PetscCall(DMLabelDestroy(&l));
213:   PetscFunctionReturn(PETSC_SUCCESS);
214: }

216: static PetscErrorCode VertexCoordinatesToAll(DM dm, IS vertices, Vec *allCoords)
217: {
218:   Vec        coords, allCoords_;
219:   VecScatter sc;
220:   MPI_Comm   comm;

222:   PetscFunctionBeginUser;
223:   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
224:   PetscCall(DMGetCoordinatesLocalSetUp(dm));
225:   if (vertices) {
226:     PetscCall(DMGetCoordinatesLocalTuple(dm, vertices, NULL, &coords));
227:   } else {
228:     PetscCall(VecCreateFromOptions(PETSC_COMM_SELF, NULL, 1, 0, 0, &coords));
229:   }
230:   {
231:     PetscInt n;
232:     Vec      mpivec;

234:     PetscCall(VecGetLocalSize(coords, &n));
235:     PetscCall(VecCreateFromOptions(comm, NULL, 1, n, PETSC_DECIDE, &mpivec));
236:     PetscCall(VecCopy(coords, mpivec));
237:     PetscCall(VecDestroy(&coords));
238:     coords = mpivec;
239:   }

241:   PetscCall(VecScatterCreateToAll(coords, &sc, &allCoords_));
242:   PetscCall(VecScatterBegin(sc, coords, allCoords_, INSERT_VALUES, SCATTER_FORWARD));
243:   PetscCall(VecScatterEnd(sc, coords, allCoords_, INSERT_VALUES, SCATTER_FORWARD));
244:   PetscCall(VecScatterDestroy(&sc));
245:   PetscCall(VecDestroy(&coords));
246:   *allCoords = allCoords_;
247:   PetscFunctionReturn(PETSC_SUCCESS);
248: }

250: static PetscErrorCode DMLabelGetCoordinateRepresentation(DM dm, DMLabel label, PetscInt value, Vec *allCoords)
251: {
252:   IS vertices;

254:   PetscFunctionBeginUser;
255:   PetscCall(DMLabelGetStratumIS(label, value, &vertices));
256:   PetscCall(VertexCoordinatesToAll(dm, vertices, allCoords));
257:   PetscCall(ISDestroy(&vertices));
258:   PetscFunctionReturn(PETSC_SUCCESS);
259: }

261: static PetscErrorCode DMLabelCompareWithCoordinateRepresentation(DM dm, DMLabel label, PetscInt value, Vec allCoords, PetscInt verbose)
262: {
263:   const char     *labelName;
264:   IS              pointsIS;
265:   const PetscInt *points;
266:   PetscInt        n;
267:   PetscBool       fail = PETSC_FALSE;
268:   MPI_Comm        comm;
269:   PetscMPIInt     rank;

271:   PetscFunctionBeginUser;
272:   PetscCheck(label, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Label not loaded");
273:   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
274:   PetscCall(PetscObjectGetName((PetscObject)label, &labelName));
275:   PetscCallMPI(MPI_Comm_rank(comm, &rank));
276:   {
277:     PetscInt pStart, pEnd;

279:     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
280:     PetscCall(DMLabelCreateIndex(label, pStart, pEnd));
281:   }
282:   PetscCall(DMPlexFindVertices(dm, allCoords, 0.0, &pointsIS));
283:   PetscCall(ISGetIndices(pointsIS, &points));
284:   PetscCall(ISGetLocalSize(pointsIS, &n));
285:   if (verbose > 1) PetscCall(DMLabelView(label, PETSC_VIEWER_STDOUT_(comm)));
286:   for (PetscInt i = 0; i < n; i++) {
287:     const PetscInt p = points[i];
288:     PetscBool      has;
289:     PetscInt       v;

291:     if (p < 0) continue;
292:     PetscCall(DMLabelHasPoint(label, p, &has));
293:     if (!has) {
294:       if (verbose) PetscCall(PetscSynchronizedFPrintf(comm, PETSC_STDERR, "[%d] Label \"%s\" does not have point %" PetscInt_FMT "\n", rank, labelName, p));
295:       fail = PETSC_TRUE;
296:       continue;
297:     }
298:     PetscCall(DMLabelGetValue(label, p, &v));
299:     if (v != value) {
300:       if (verbose) PetscCall(PetscSynchronizedFPrintf(comm, PETSC_STDERR, "Point %" PetscInt_FMT " has bad value %" PetscInt_FMT " in label \"%s\"", p, v, labelName));
301:       fail = PETSC_TRUE;
302:       continue;
303:     }
304:     if (verbose > 1) PetscCall(PetscSynchronizedPrintf(comm, "[%d] OK point %" PetscInt_FMT "\n", rank, p));
305:   }
306:   PetscCall(PetscSynchronizedFlush(comm, PETSC_STDOUT));
307:   PetscCall(PetscSynchronizedFlush(comm, PETSC_STDERR));
308:   PetscCall(ISRestoreIndices(pointsIS, &points));
309:   PetscCall(ISDestroy(&pointsIS));
310:   PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &fail, 1, MPI_C_BOOL, MPI_LOR, comm));
311:   PetscCheck(!fail, comm, PETSC_ERR_PLIB, "Label \"%s\" was not loaded correctly%s", labelName, verbose ? " - see details above" : "");
312:   PetscFunctionReturn(PETSC_SUCCESS);
313: }

315: static PetscErrorCode CheckNumLabels(DM dm, AppCtx *ctx)
316: {
317:   PetscInt    actualNum;
318:   PetscBool   fail = PETSC_FALSE;
319:   MPI_Comm    comm;
320:   PetscMPIInt rank;

322:   PetscFunctionBeginUser;
323:   if (ctx->num_labels < 0) PetscFunctionReturn(PETSC_SUCCESS);
324:   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
325:   PetscCallMPI(MPI_Comm_rank(comm, &rank));
326:   PetscCall(DMGetNumLabels(dm, &actualNum));
327:   if (ctx->num_labels != actualNum) {
328:     fail = PETSC_TRUE;
329:     if (ctx->verbose) {
330:       PetscCall(PetscSynchronizedFPrintf(comm, PETSC_STDERR, "[%d] Asserted number of labels: %" PetscInt_FMT ", actual: %" PetscInt_FMT "\n", rank, ctx->num_labels, actualNum));
331:       for (PetscInt i = 0; i < actualNum; i++) {
332:         DMLabel     label;
333:         const char *name;

335:         PetscCall(DMGetLabelByNum(dm, i, &label));
336:         PetscCall(PetscObjectGetName((PetscObject)label, &name));
337:         PetscCall(PetscSynchronizedFPrintf(comm, PETSC_STDERR, "[%d] Label %" PetscInt_FMT " \"%s\"\n", rank, i, name));
338:       }
339:       PetscCall(PetscSynchronizedFlush(comm, PETSC_STDERR));
340:     }
341:   }
342:   PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &fail, 1, MPI_C_BOOL, MPI_LOR, comm));
343:   PetscCheck(!fail, comm, PETSC_ERR_PLIB, "Wrong number of labels%s", ctx->verbose ? " - see details above" : "");
344:   PetscFunctionReturn(PETSC_SUCCESS);
345: }

347: static inline PetscErrorCode IncrementNumLabels(AppCtx *ctx)
348: {
349:   PetscFunctionBeginUser;
350:   if (ctx->num_labels >= 0) ctx->num_labels++;
351:   PetscFunctionReturn(PETSC_SUCCESS);
352: }

354: int main(int argc, char **argv)
355: {
356:   const char     BOUNDARY_NAME[]          = "Boundary";
357:   const char     BOUNDARY_VERTICES_NAME[] = "BoundaryVertices";
358:   const PetscInt BOUNDARY_VALUE           = 12345;
359:   const PetscInt BOUNDARY_VERTICES_VALUE  = 6789;
360:   DM             dm, dmnew;
361:   AppCtx         user;
362:   Vec            allCoords = NULL;

364:   PetscFunctionBeginUser;
365:   PetscCall(PetscInitialize(&argc, &argv, NULL, help));
366:   PetscCall(ProcessOptions(PETSC_COMM_WORLD, &user));
367:   PetscCall(CreateMesh(&user, &dm));
368:   PetscCall(MarkBoundary(dm, BOUNDARY_NAME, BOUNDARY_VALUE, PETSC_FALSE, NULL));
369:   PetscCall(IncrementNumLabels(&user));
370:   if (user.compare_boundary) {
371:     DMLabel label;

373:     PetscCall(MarkBoundary(dm, BOUNDARY_VERTICES_NAME, BOUNDARY_VERTICES_VALUE, PETSC_TRUE, &label));
374:     PetscCall(IncrementNumLabels(&user));
375:     PetscCall(DMLabelGetCoordinateRepresentation(dm, label, BOUNDARY_VERTICES_VALUE, &allCoords));
376:     PetscCall(DMLabelDestroy(&label));
377:   }
378:   PetscCall(SaveMesh(&user, dm));

380:   PetscCall(LoadMesh(&user, &dmnew));
381:   PetscCall(IncrementNumLabels(&user)); /* account for depth label */
382:   PetscCall(IncrementNumLabels(&user)); /* account for celltype label */
383:   PetscCall(CheckNumLabels(dm, &user));
384:   PetscCall(CompareMeshes(&user, dm, dmnew));
385:   if (user.compare_boundary) {
386:     DMLabel label;

388:     PetscCall(DMGetLabel(dmnew, BOUNDARY_VERTICES_NAME, &label));
389:     PetscCall(DMLabelCompareWithCoordinateRepresentation(dmnew, label, BOUNDARY_VERTICES_VALUE, allCoords, user.verbose));
390:   }
391:   PetscCall(DMDestroy(&dm));
392:   PetscCall(DMDestroy(&dmnew));
393:   PetscCall(VecDestroy(&allCoords));
394:   PetscCall(PetscFinalize());
395:   return 0;
396: }

398: //TODO we can -compare once the new parallel topology format is in place
399: /*TEST
400:   build:
401:     requires: hdf5

403:   # load old format, save in new format, reload, distribute
404:   testset:
405:     suffix: 1
406:     requires: !complex datafilespath
407:     args: -dm_plex_name plex
408:     args: -dm_plex_check_all -dm_plex_view_hdf5_storage_version 2.0.0
409:     args: -dm_plex_interpolate -petscpartitioner_type simple
410:     args: -load_dm_plex_check_all
411:     args: -use_low_level_functions {{0 1}} -compare_boundary
412:     args: -num_labels 1
413:     args: -outfile ex56_1.h5
414:     nsize: {{1 3}}
415:     output_file: output/empty.out
416:     test:
417:       suffix: a
418:       args: -dm_plex_filename ${DATAFILESPATH}/meshes/hdf5-petsc/petsc-v3.16.0/v1.0.0/annulus-20.h5
419:     test:
420:       suffix: b
421:       TODO: broken
422:       args: -dm_plex_filename ${DATAFILESPATH}/meshes/hdf5-petsc/petsc-v3.16.0/v1.0.0/barycentricallyrefinedcube.h5
423:     test:
424:       suffix: c
425:       args: -dm_plex_filename ${DATAFILESPATH}/meshes/hdf5-petsc/petsc-v3.16.0/v1.0.0/blockcylinder-50.h5
426:     test:
427:       suffix: d
428:       args: -dm_plex_filename ${DATAFILESPATH}/meshes/hdf5-petsc/petsc-v3.16.0/v1.0.0/cube-hexahedra-refined.h5 -num_labels 0
429:     test:
430:       suffix: e
431:       args: -dm_plex_filename ${DATAFILESPATH}/meshes/hdf5-petsc/petsc-v3.16.0/v1.0.0/hybrid_hexwedge.h5
432:     test:
433:       suffix: f
434:       args: -dm_plex_filename ${DATAFILESPATH}/meshes/hdf5-petsc/petsc-v3.16.0/v1.0.0/square.h5

436:   # load old format, save in new format, reload topology, distribute, load geometry and labels
437:   testset:
438:     suffix: 2
439:     requires: !complex datafilespath
440:     args: -dm_plex_name plex
441:     args: -dm_plex_check_all -dm_plex_view_hdf5_storage_version 2.0.0
442:     args: -dm_plex_interpolate -petscpartitioner_type simple
443:     args: -load_dm_plex_check_all
444:     args: -use_low_level_functions -load_dm_distribute 0 -distribute_after_topo_load -compare_boundary
445:     args: -num_labels 1
446:     args: -outfile ex56_2.h5
447:     nsize: 3
448:     output_file: output/empty.out
449:     test:
450:       suffix: a
451:       args: -dm_plex_filename ${DATAFILESPATH}/meshes/hdf5-petsc/petsc-v3.16.0/v1.0.0/annulus-20.h5
452:     test:
453:       suffix: b
454:       TODO: broken
455:       args: -dm_plex_filename ${DATAFILESPATH}/meshes/hdf5-petsc/petsc-v3.16.0/v1.0.0/barycentricallyrefinedcube.h5
456:     test:
457:       suffix: c
458:       args: -dm_plex_filename ${DATAFILESPATH}/meshes/hdf5-petsc/petsc-v3.16.0/v1.0.0/blockcylinder-50.h5
459:     test:
460:       suffix: d
461:       args: -dm_plex_filename ${DATAFILESPATH}/meshes/hdf5-petsc/petsc-v3.16.0/v1.0.0/cube-hexahedra-refined.h5 -num_labels 0
462:     test:
463:       suffix: e
464:       args: -dm_plex_filename ${DATAFILESPATH}/meshes/hdf5-petsc/petsc-v3.16.0/v1.0.0/hybrid_hexwedge.h5
465:     test:
466:       suffix: f
467:       args: -dm_plex_filename ${DATAFILESPATH}/meshes/hdf5-petsc/petsc-v3.16.0/v1.0.0/square.h5

469:   # load old format, save in new format, reload topology, distribute, load geometry and labels
470:   testset:
471:     suffix: 3
472:     requires: !complex datafilespath
473:     args: -dm_plex_name plex
474:     args: -dm_plex_view_hdf5_storage_version 2.0.0
475:     args: -dm_plex_interpolate -load_dm_distribute 0 -petscpartitioner_type simple
476:     args: -use_low_level_functions -compare_pre_post
477:     args: -num_labels 1
478:     args: -outfile ex56_3.h5
479:     nsize: 3
480:     output_file: output/empty.out
481:     test:
482:       suffix: a
483:       args: -dm_plex_filename ${DATAFILESPATH}/meshes/hdf5-petsc/petsc-v3.16.0/v1.0.0/annulus-20.h5
484:     test:
485:       suffix: b
486:       TODO: broken
487:       args: -dm_plex_filename ${DATAFILESPATH}/meshes/hdf5-petsc/petsc-v3.16.0/v1.0.0/barycentricallyrefinedcube.h5
488:     test:
489:       suffix: c
490:       args: -dm_plex_filename ${DATAFILESPATH}/meshes/hdf5-petsc/petsc-v3.16.0/v1.0.0/blockcylinder-50.h5
491:     test:
492:       suffix: d
493:       args: -dm_plex_filename ${DATAFILESPATH}/meshes/hdf5-petsc/petsc-v3.16.0/v1.0.0/cube-hexahedra-refined.h5 -num_labels 0
494:     test:
495:       suffix: e
496:       args: -dm_plex_filename ${DATAFILESPATH}/meshes/hdf5-petsc/petsc-v3.16.0/v1.0.0/hybrid_hexwedge.h5
497:     test:
498:       suffix: f
499:       args: -dm_plex_filename ${DATAFILESPATH}/meshes/hdf5-petsc/petsc-v3.16.0/v1.0.0/square.h5
500: TEST*/