xref: /petsc/src/dm/impls/plex/hdf5/plexhdf5.c (revision ea87367f2c347d0545fd4cb1e9459d95e4df3c32)
12e1d0745SJose E. Roman #include <petsc/private/dmpleximpl.h> /*I      "petscdmplex.h"   I*/
22e1d0745SJose E. Roman #include <petsc/private/isimpl.h>
32e1d0745SJose E. Roman #include <petsc/private/vecimpl.h>
42e1d0745SJose E. Roman #include <petsc/private/viewerhdf5impl.h>
52e1d0745SJose E. Roman #include <petsclayouthdf5.h>
62e1d0745SJose E. Roman 
72e1d0745SJose E. Roman static PetscErrorCode PetscViewerParseVersion_Private(PetscViewer, const char[], DMPlexStorageVersion *);
82e1d0745SJose E. Roman static PetscErrorCode PetscViewerCheckVersion_Private(PetscViewer, DMPlexStorageVersion);
92e1d0745SJose E. Roman static PetscErrorCode PetscViewerAttachVersion_Private(PetscViewer, const char[], DMPlexStorageVersion);
102e1d0745SJose E. Roman static PetscErrorCode PetscViewerGetAttachedVersion_Private(PetscViewer, const char[], DMPlexStorageVersion *);
112e1d0745SJose E. Roman 
122e1d0745SJose E. Roman PETSC_EXTERN PetscErrorCode VecView_MPI(Vec, PetscViewer);
132e1d0745SJose E. Roman 
142e1d0745SJose E. Roman static PetscErrorCode PetscViewerPrintVersion_Private(PetscViewer viewer, DMPlexStorageVersion version, char str[], size_t len)
152e1d0745SJose E. Roman {
162e1d0745SJose E. Roman   PetscFunctionBegin;
172e1d0745SJose E. Roman   PetscCall(PetscViewerCheckVersion_Private(viewer, version));
182e1d0745SJose E. Roman   PetscCall(PetscSNPrintf(str, len, "%d.%d.%d", version->major, version->minor, version->subminor));
192e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
202e1d0745SJose E. Roman }
212e1d0745SJose E. Roman 
222e1d0745SJose E. Roman static PetscErrorCode PetscViewerParseVersion_Private(PetscViewer viewer, const char str[], DMPlexStorageVersion *version)
232e1d0745SJose E. Roman {
242e1d0745SJose E. Roman   PetscToken           t;
25ce78bad3SBarry Smith   const char          *ts;
262e1d0745SJose E. Roman   PetscInt             i;
272e1d0745SJose E. Roman   PetscInt             ti[3];
282e1d0745SJose E. Roman   DMPlexStorageVersion v;
292e1d0745SJose E. Roman 
302e1d0745SJose E. Roman   PetscFunctionBegin;
312e1d0745SJose E. Roman   PetscCall(PetscTokenCreate(str, '.', &t));
322e1d0745SJose E. Roman   for (i = 0; i < 3; i++) {
332e1d0745SJose E. Roman     PetscCall(PetscTokenFind(t, &ts));
342e1d0745SJose E. Roman     PetscCheck(ts, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONG, "Malformed version string %s", str);
352e1d0745SJose E. Roman     PetscCall(PetscOptionsStringToInt(ts, &ti[i]));
362e1d0745SJose E. Roman   }
372e1d0745SJose E. Roman   PetscCall(PetscTokenFind(t, &ts));
382e1d0745SJose E. Roman   PetscCheck(!ts, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONG, "Malformed version string %s", str);
392e1d0745SJose E. Roman   PetscCall(PetscTokenDestroy(&t));
402e1d0745SJose E. Roman   PetscCall(PetscNew(&v));
412e1d0745SJose E. Roman   v->major    = (int)ti[0];
422e1d0745SJose E. Roman   v->minor    = (int)ti[1];
432e1d0745SJose E. Roman   v->subminor = (int)ti[2];
442e1d0745SJose E. Roman   PetscCall(PetscViewerCheckVersion_Private(viewer, v));
452e1d0745SJose E. Roman   *version = v;
462e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
472e1d0745SJose E. Roman }
482e1d0745SJose E. Roman 
492e1d0745SJose E. Roman static PetscErrorCode PetscViewerAttachVersion_Private(PetscViewer viewer, const char key[], DMPlexStorageVersion v)
502e1d0745SJose E. Roman {
512e1d0745SJose E. Roman   PetscFunctionBegin;
525a236de6SSatish Balay   PetscCall(PetscObjectContainerCompose((PetscObject)viewer, key, v, PetscCtxDestroyDefault));
532e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
542e1d0745SJose E. Roman }
552e1d0745SJose E. Roman 
562e1d0745SJose E. Roman static PetscErrorCode PetscViewerGetAttachedVersion_Private(PetscViewer viewer, const char key[], DMPlexStorageVersion *v)
572e1d0745SJose E. Roman {
582e1d0745SJose E. Roman   PetscContainer cont;
592e1d0745SJose E. Roman 
602e1d0745SJose E. Roman   PetscFunctionBegin;
612e1d0745SJose E. Roman   PetscCall(PetscObjectQuery((PetscObject)viewer, key, (PetscObject *)&cont));
622e1d0745SJose E. Roman   *v = NULL;
632e1d0745SJose E. Roman   if (cont) PetscCall(PetscContainerGetPointer(cont, (void **)v));
642e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
652e1d0745SJose E. Roman }
662e1d0745SJose E. Roman 
672e1d0745SJose E. Roman /*
682e1d0745SJose E. Roman   Version log:
692e1d0745SJose E. Roman   1.0.0 legacy version (default if no "dmplex_storage_version" attribute found in file)
702e1d0745SJose E. Roman   1.1.0 legacy version, but output VIZ by default
712e1d0745SJose E. Roman   2.0.0 introduce versioning and multiple topologies
722e1d0745SJose E. Roman   2.1.0 introduce distributions
732e1d0745SJose E. Roman   3.0.0 new checkpointing format in Firedrake paper
742e1d0745SJose E. Roman   3.1.0 new format with IS compression
752e1d0745SJose E. Roman */
762e1d0745SJose E. Roman static PetscErrorCode PetscViewerCheckVersion_Private(PetscViewer viewer, DMPlexStorageVersion version)
772e1d0745SJose E. Roman {
782e1d0745SJose E. Roman   PetscBool valid = PETSC_FALSE;
792e1d0745SJose E. Roman 
802e1d0745SJose E. Roman   PetscFunctionBegin;
812e1d0745SJose E. Roman   switch (version->major) {
822e1d0745SJose E. Roman   case 1:
832e1d0745SJose E. Roman     switch (version->minor) {
842e1d0745SJose E. Roman     case 0:
852e1d0745SJose E. Roman       switch (version->subminor) {
862e1d0745SJose E. Roman       case 0:
872e1d0745SJose E. Roman         valid = PETSC_TRUE;
882e1d0745SJose E. Roman         break;
892e1d0745SJose E. Roman       }
902e1d0745SJose E. Roman       break;
912e1d0745SJose E. Roman     case 1:
922e1d0745SJose E. Roman       switch (version->subminor) {
932e1d0745SJose E. Roman       case 0:
942e1d0745SJose E. Roman         valid = PETSC_TRUE;
952e1d0745SJose E. Roman         break;
962e1d0745SJose E. Roman       }
972e1d0745SJose E. Roman       break;
982e1d0745SJose E. Roman     }
992e1d0745SJose E. Roman     break;
1002e1d0745SJose E. Roman   case 2:
1012e1d0745SJose E. Roman     switch (version->minor) {
1022e1d0745SJose E. Roman     case 0:
1032e1d0745SJose E. Roman       switch (version->subminor) {
1042e1d0745SJose E. Roman       case 0:
1052e1d0745SJose E. Roman         valid = PETSC_TRUE;
1062e1d0745SJose E. Roman         break;
1072e1d0745SJose E. Roman       }
1082e1d0745SJose E. Roman       break;
1092e1d0745SJose E. Roman     case 1:
1102e1d0745SJose E. Roman       switch (version->subminor) {
1112e1d0745SJose E. Roman       case 0:
1122e1d0745SJose E. Roman         valid = PETSC_TRUE;
1132e1d0745SJose E. Roman         break;
1142e1d0745SJose E. Roman       }
1152e1d0745SJose E. Roman       break;
1162e1d0745SJose E. Roman     }
1172e1d0745SJose E. Roman     break;
1182e1d0745SJose E. Roman   case 3:
1192e1d0745SJose E. Roman     switch (version->minor) {
1202e1d0745SJose E. Roman     case 0:
1212e1d0745SJose E. Roman       switch (version->subminor) {
1222e1d0745SJose E. Roman       case 0:
1232e1d0745SJose E. Roman         valid = PETSC_TRUE;
1242e1d0745SJose E. Roman         break;
1252e1d0745SJose E. Roman       }
1262e1d0745SJose E. Roman       break;
1272e1d0745SJose E. Roman     case 1:
1282e1d0745SJose E. Roman       switch (version->subminor) {
1292e1d0745SJose E. Roman       case 0:
1302e1d0745SJose E. Roman         valid = PETSC_TRUE;
1312e1d0745SJose E. Roman         break;
1322e1d0745SJose E. Roman       }
1332e1d0745SJose E. Roman       break;
1342e1d0745SJose E. Roman     }
1352e1d0745SJose E. Roman     break;
1362e1d0745SJose E. Roman   }
1372e1d0745SJose E. Roman   PetscCheck(valid, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "DMPlexStorageVersion %d.%d.%d not supported", version->major, version->minor, version->subminor);
1382e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
1392e1d0745SJose E. Roman }
1402e1d0745SJose E. Roman 
1412e1d0745SJose E. Roman static inline PetscBool DMPlexStorageVersionEQ(DMPlexStorageVersion version, int major, int minor, int subminor)
1422e1d0745SJose E. Roman {
1432e1d0745SJose E. Roman   return (PetscBool)(version->major == major && version->minor == minor && version->subminor == subminor);
1442e1d0745SJose E. Roman }
1452e1d0745SJose E. Roman 
1462e1d0745SJose E. Roman static inline PetscBool DMPlexStorageVersionGE(DMPlexStorageVersion version, int major, int minor, int subminor)
1472e1d0745SJose E. Roman {
1482e1d0745SJose E. Roman   return (PetscBool)((version->major == major && version->minor == minor && version->subminor >= subminor) || (version->major == major && version->minor > minor) || (version->major > major));
1492e1d0745SJose E. Roman }
1502e1d0745SJose E. Roman 
1512e1d0745SJose E. Roman /*@C
1522e1d0745SJose E. Roman   PetscViewerHDF5SetDMPlexStorageVersionWriting - Set the storage version for writing
1532e1d0745SJose E. Roman 
1542e1d0745SJose E. Roman   Logically collective
1552e1d0745SJose E. Roman 
1562e1d0745SJose E. Roman   Input Parameters:
1572e1d0745SJose E. Roman + viewer  - The `PetscViewer`
1582e1d0745SJose E. Roman - version - The storage format version
1592e1d0745SJose E. Roman 
1602e1d0745SJose E. Roman   Level: advanced
1612e1d0745SJose E. Roman 
1622e1d0745SJose E. Roman   Note:
1632e1d0745SJose E. Roman   The version has major, minor, and subminor integers. Parallel operations are only available for version 3.0.0.
1642e1d0745SJose E. Roman 
1652e1d0745SJose E. Roman .seealso: [](ch_dmbase), `DM`, `PetscViewerHDF5GetDMPlexStorageVersionWriting()`, `PetscViewerHDF5GetDMPlexStorageVersionReading()`, `PetscViewerHDF5SetDMPlexStorageVersionReading()`
1662e1d0745SJose E. Roman @*/
1672e1d0745SJose E. Roman PetscErrorCode PetscViewerHDF5SetDMPlexStorageVersionWriting(PetscViewer viewer, DMPlexStorageVersion version)
1682e1d0745SJose E. Roman {
1692e1d0745SJose E. Roman   const char           ATTR_NAME[] = "dmplex_storage_version";
1702e1d0745SJose E. Roman   DMPlexStorageVersion viewerVersion;
1712e1d0745SJose E. Roman   PetscBool            fileHasVersion;
1722e1d0745SJose E. Roman   char                 fileVersion[16], versionStr[16], viewerVersionStr[16];
1732e1d0745SJose E. Roman 
1742e1d0745SJose E. Roman   PetscFunctionBegin;
1752e1d0745SJose E. Roman   PetscValidHeaderSpecificType(viewer, PETSC_VIEWER_CLASSID, 1, PETSCVIEWERHDF5);
1762e1d0745SJose E. Roman   PetscAssertPointer(version, 2);
1772e1d0745SJose E. Roman   PetscCall(PetscViewerPrintVersion_Private(viewer, version, versionStr, 16));
1782e1d0745SJose E. Roman   PetscCall(PetscViewerGetAttachedVersion_Private(viewer, DMPLEX_STORAGE_VERSION_WRITING_KEY, &viewerVersion));
1792e1d0745SJose E. Roman   if (viewerVersion) {
1802e1d0745SJose E. Roman     PetscBool flg;
1812e1d0745SJose E. Roman 
1822e1d0745SJose E. Roman     PetscCall(PetscViewerPrintVersion_Private(viewer, viewerVersion, viewerVersionStr, 16));
1832e1d0745SJose E. Roman     PetscCall(PetscStrcmp(versionStr, viewerVersionStr, &flg));
1842e1d0745SJose E. Roman     PetscCheck(flg, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "User requested DMPlex storage version %s but viewer already has version %s - cannot mix versions", versionStr, viewerVersionStr);
1852e1d0745SJose E. Roman   }
1862e1d0745SJose E. Roman 
1872e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5HasAttribute(viewer, NULL, ATTR_NAME, &fileHasVersion));
1882e1d0745SJose E. Roman   if (fileHasVersion) {
1892e1d0745SJose E. Roman     PetscBool flg;
1902e1d0745SJose E. Roman     char     *tmp;
1912e1d0745SJose E. Roman 
1922e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5ReadAttribute(viewer, "/", ATTR_NAME, PETSC_STRING, NULL, &tmp));
1932e1d0745SJose E. Roman     PetscCall(PetscStrncpy(fileVersion, tmp, sizeof(fileVersion)));
1942e1d0745SJose E. Roman     PetscCall(PetscFree(tmp));
1952e1d0745SJose E. Roman     PetscCall(PetscStrcmp(fileVersion, versionStr, &flg));
1962e1d0745SJose E. Roman     PetscCheck(flg, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "User requested DMPlex storage version %s but file already has version %s - cannot mix versions", versionStr, fileVersion);
1972e1d0745SJose E. Roman   } else {
1982e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5WriteAttribute(viewer, "/", ATTR_NAME, PETSC_STRING, versionStr));
1992e1d0745SJose E. Roman   }
2002e1d0745SJose E. Roman   PetscCall(PetscNew(&viewerVersion));
2012e1d0745SJose E. Roman   viewerVersion->major    = version->major;
2022e1d0745SJose E. Roman   viewerVersion->minor    = version->minor;
2032e1d0745SJose E. Roman   viewerVersion->subminor = version->subminor;
2042e1d0745SJose E. Roman   PetscCall(PetscViewerAttachVersion_Private(viewer, DMPLEX_STORAGE_VERSION_WRITING_KEY, viewerVersion));
2052e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
2062e1d0745SJose E. Roman }
2072e1d0745SJose E. Roman 
2082e1d0745SJose E. Roman /*@C
2092e1d0745SJose E. Roman   PetscViewerHDF5GetDMPlexStorageVersionWriting - Get the storage version for writing
2102e1d0745SJose E. Roman 
2112e1d0745SJose E. Roman   Logically collective
2122e1d0745SJose E. Roman 
2132e1d0745SJose E. Roman   Input Parameter:
2142e1d0745SJose E. Roman . viewer - The `PetscViewer`
2152e1d0745SJose E. Roman 
2162e1d0745SJose E. Roman   Output Parameter:
2172e1d0745SJose E. Roman . version - The storage format version
2182e1d0745SJose E. Roman 
2192e1d0745SJose E. Roman   Options Database Keys:
2202e1d0745SJose E. Roman . -dm_plex_view_hdf5_storage_version <num> - Overrides the storage format version
2212e1d0745SJose E. Roman 
2222e1d0745SJose E. Roman   Level: advanced
2232e1d0745SJose E. Roman 
2242e1d0745SJose E. Roman   Note:
2252e1d0745SJose E. Roman   The version has major, minor, and subminor integers. Parallel operations are only available for version 3.0.0.
2262e1d0745SJose E. Roman 
2272e1d0745SJose E. Roman .seealso: [](ch_dmbase), `DM`, `PetscViewerHDF5SetDMPlexStorageVersionWriting()`, `PetscViewerHDF5GetDMPlexStorageVersionReading()`, `PetscViewerHDF5SetDMPlexStorageVersionReading()`
2282e1d0745SJose E. Roman @*/
2292e1d0745SJose E. Roman PetscErrorCode PetscViewerHDF5GetDMPlexStorageVersionWriting(PetscViewer viewer, DMPlexStorageVersion *version)
2302e1d0745SJose E. Roman {
2312e1d0745SJose E. Roman   const char ATTR_NAME[] = "dmplex_storage_version";
2322e1d0745SJose E. Roman   PetscBool  fileHasVersion;
2332e1d0745SJose E. Roman   char       optVersion[16], fileVersion[16];
2342e1d0745SJose E. Roman 
2352e1d0745SJose E. Roman   PetscFunctionBegin;
2362e1d0745SJose E. Roman   PetscValidHeaderSpecificType(viewer, PETSC_VIEWER_CLASSID, 1, PETSCVIEWERHDF5);
2372e1d0745SJose E. Roman   PetscAssertPointer(version, 2);
2382e1d0745SJose E. Roman   PetscCall(PetscViewerGetAttachedVersion_Private(viewer, DMPLEX_STORAGE_VERSION_WRITING_KEY, version));
2392e1d0745SJose E. Roman   if (*version) PetscFunctionReturn(PETSC_SUCCESS);
2402e1d0745SJose E. Roman 
2412e1d0745SJose E. Roman   PetscCall(PetscStrncpy(fileVersion, DMPLEX_STORAGE_VERSION_STABLE, sizeof(fileVersion)));
2422e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5HasAttribute(viewer, NULL, ATTR_NAME, &fileHasVersion));
2432e1d0745SJose E. Roman   if (fileHasVersion) {
2442e1d0745SJose E. Roman     char *tmp;
2452e1d0745SJose E. Roman 
2462e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5ReadAttribute(viewer, "/", ATTR_NAME, PETSC_STRING, NULL, &tmp));
2472e1d0745SJose E. Roman     PetscCall(PetscStrncpy(fileVersion, tmp, sizeof(fileVersion)));
2482e1d0745SJose E. Roman     PetscCall(PetscFree(tmp));
2492e1d0745SJose E. Roman   }
2502e1d0745SJose E. Roman   PetscCall(PetscStrncpy(optVersion, fileVersion, sizeof(optVersion)));
2512e1d0745SJose E. Roman   PetscObjectOptionsBegin((PetscObject)viewer);
2522e1d0745SJose E. Roman   PetscCall(PetscOptionsString("-dm_plex_view_hdf5_storage_version", "DMPlex HDF5 viewer storage version", NULL, optVersion, optVersion, sizeof(optVersion), NULL));
2532e1d0745SJose E. Roman   PetscOptionsEnd();
2542e1d0745SJose E. Roman   if (!fileHasVersion) {
2552e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5WriteAttribute(viewer, "/", ATTR_NAME, PETSC_STRING, optVersion));
2562e1d0745SJose E. Roman   } else {
2572e1d0745SJose E. Roman     PetscBool flg;
2582e1d0745SJose E. Roman 
2592e1d0745SJose E. Roman     PetscCall(PetscStrcmp(fileVersion, optVersion, &flg));
2602e1d0745SJose E. Roman     PetscCheck(flg, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "User requested DMPlex storage version %s but file already has version %s - cannot mix versions", optVersion, fileVersion);
2612e1d0745SJose E. Roman   }
2622e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5WriteAttribute(viewer, NULL, "petsc_version_git", PETSC_STRING, PETSC_VERSION_GIT));
2632e1d0745SJose E. Roman   PetscCall(PetscViewerParseVersion_Private(viewer, optVersion, version));
2642e1d0745SJose E. Roman   PetscCall(PetscViewerAttachVersion_Private(viewer, DMPLEX_STORAGE_VERSION_WRITING_KEY, *version));
2652e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
2662e1d0745SJose E. Roman }
2672e1d0745SJose E. Roman 
2682e1d0745SJose E. Roman /*@C
2692e1d0745SJose E. Roman   PetscViewerHDF5SetDMPlexStorageVersionReading - Set the storage version for reading
2702e1d0745SJose E. Roman 
2712e1d0745SJose E. Roman   Logically collective
2722e1d0745SJose E. Roman 
2732e1d0745SJose E. Roman   Input Parameters:
2742e1d0745SJose E. Roman + viewer  - The `PetscViewer`
2752e1d0745SJose E. Roman - version - The storage format version
2762e1d0745SJose E. Roman 
2772e1d0745SJose E. Roman   Level: advanced
2782e1d0745SJose E. Roman 
2792e1d0745SJose E. Roman   Note:
2802e1d0745SJose E. Roman   The version has major, minor, and subminor integers. Parallel operations are only available for version 3.0.0.
2812e1d0745SJose E. Roman 
2822e1d0745SJose E. Roman .seealso: [](ch_dmbase), `DM`, `PetscViewerHDF5GetDMPlexStorageVersionReading()`, `PetscViewerHDF5GetDMPlexStorageVersionWriting()`, `PetscViewerHDF5SetDMPlexStorageVersionWriting()`
2832e1d0745SJose E. Roman @*/
2842e1d0745SJose E. Roman PetscErrorCode PetscViewerHDF5SetDMPlexStorageVersionReading(PetscViewer viewer, DMPlexStorageVersion version)
2852e1d0745SJose E. Roman {
2862e1d0745SJose E. Roman   const char           ATTR_NAME[] = "dmplex_storage_version";
2872e1d0745SJose E. Roman   DMPlexStorageVersion viewerVersion;
2882e1d0745SJose E. Roman   PetscBool            fileHasVersion;
2892e1d0745SJose E. Roman   char                 versionStr[16], viewerVersionStr[16];
2902e1d0745SJose E. Roman 
2912e1d0745SJose E. Roman   PetscFunctionBegin;
2922e1d0745SJose E. Roman   PetscValidHeaderSpecificType(viewer, PETSC_VIEWER_CLASSID, 1, PETSCVIEWERHDF5);
2932e1d0745SJose E. Roman   PetscAssertPointer(version, 2);
2942e1d0745SJose E. Roman   PetscCall(PetscViewerPrintVersion_Private(viewer, version, versionStr, 16));
2952e1d0745SJose E. Roman   PetscCall(PetscViewerGetAttachedVersion_Private(viewer, DMPLEX_STORAGE_VERSION_READING_KEY, &viewerVersion));
2962e1d0745SJose E. Roman   if (viewerVersion) {
2972e1d0745SJose E. Roman     PetscBool flg;
2982e1d0745SJose E. Roman 
2992e1d0745SJose E. Roman     PetscCall(PetscViewerPrintVersion_Private(viewer, viewerVersion, viewerVersionStr, 16));
3002e1d0745SJose E. Roman     PetscCall(PetscStrcmp(versionStr, viewerVersionStr, &flg));
3012e1d0745SJose E. Roman     PetscCheck(flg, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "User requested DMPlex storage version %s but viewer already has version %s - cannot mix versions", versionStr, viewerVersionStr);
3022e1d0745SJose E. Roman   }
3032e1d0745SJose E. Roman 
3042e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5HasAttribute(viewer, NULL, ATTR_NAME, &fileHasVersion));
3052e1d0745SJose E. Roman   if (fileHasVersion) {
3062e1d0745SJose E. Roman     char     *fileVersion;
3072e1d0745SJose E. Roman     PetscBool flg;
3082e1d0745SJose E. Roman 
3092e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5ReadAttribute(viewer, "/", ATTR_NAME, PETSC_STRING, NULL, &fileVersion));
3102e1d0745SJose E. Roman     PetscCall(PetscStrcmp(fileVersion, versionStr, &flg));
3112e1d0745SJose E. Roman     PetscCheck(flg, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "User requested DMPlex storage version %s but file already has version %s - cannot mix versions", versionStr, fileVersion);
3122e1d0745SJose E. Roman     PetscCall(PetscFree(fileVersion));
3132e1d0745SJose E. Roman   }
3142e1d0745SJose E. Roman   PetscCall(PetscNew(&viewerVersion));
3152e1d0745SJose E. Roman   viewerVersion->major    = version->major;
3162e1d0745SJose E. Roman   viewerVersion->minor    = version->minor;
3172e1d0745SJose E. Roman   viewerVersion->subminor = version->subminor;
3182e1d0745SJose E. Roman   PetscCall(PetscViewerAttachVersion_Private(viewer, DMPLEX_STORAGE_VERSION_READING_KEY, viewerVersion));
3192e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
3202e1d0745SJose E. Roman }
3212e1d0745SJose E. Roman 
3222e1d0745SJose E. Roman /*@C
3232e1d0745SJose E. Roman   PetscViewerHDF5GetDMPlexStorageVersionReading - Get the storage version for reading
3242e1d0745SJose E. Roman 
3252e1d0745SJose E. Roman   Logically collective
3262e1d0745SJose E. Roman 
3272e1d0745SJose E. Roman   Input Parameter:
3282e1d0745SJose E. Roman . viewer - The `PetscViewer`
3292e1d0745SJose E. Roman 
3302e1d0745SJose E. Roman   Output Parameter:
3312e1d0745SJose E. Roman . version - The storage format version
3322e1d0745SJose E. Roman 
3332e1d0745SJose E. Roman   Options Database Keys:
3342e1d0745SJose E. Roman . -dm_plex_view_hdf5_storage_version <num> - Overrides the storage format version
3352e1d0745SJose E. Roman 
3362e1d0745SJose E. Roman   Level: advanced
3372e1d0745SJose E. Roman 
3382e1d0745SJose E. Roman   Note:
3392e1d0745SJose E. Roman   The version has major, minor, and subminor integers. Parallel operations are only available for version 3.0.0.
3402e1d0745SJose E. Roman 
3412e1d0745SJose E. Roman .seealso: [](ch_dmbase), `DM`, `PetscViewerHDF5SetDMPlexStorageVersionReading()`, `PetscViewerHDF5GetDMPlexStorageVersionWriting()`, `PetscViewerHDF5SetDMPlexStorageVersionWriting()`
3422e1d0745SJose E. Roman @*/
3432e1d0745SJose E. Roman PetscErrorCode PetscViewerHDF5GetDMPlexStorageVersionReading(PetscViewer viewer, DMPlexStorageVersion *version)
3442e1d0745SJose E. Roman {
3452e1d0745SJose E. Roman   const char ATTR_NAME[] = "dmplex_storage_version";
3462e1d0745SJose E. Roman   char      *defaultVersion;
3472e1d0745SJose E. Roman   char      *versionString;
3482e1d0745SJose E. Roman 
3492e1d0745SJose E. Roman   PetscFunctionBegin;
3502e1d0745SJose E. Roman   PetscValidHeaderSpecificType(viewer, PETSC_VIEWER_CLASSID, 1, PETSCVIEWERHDF5);
3512e1d0745SJose E. Roman   PetscAssertPointer(version, 2);
3522e1d0745SJose E. Roman   PetscCall(PetscViewerGetAttachedVersion_Private(viewer, DMPLEX_STORAGE_VERSION_READING_KEY, version));
3532e1d0745SJose E. Roman   if (*version) PetscFunctionReturn(PETSC_SUCCESS);
3542e1d0745SJose E. Roman 
3552e1d0745SJose E. Roman   //TODO string HDF5 attribute handling is terrible and should be redesigned
3562e1d0745SJose E. Roman   PetscCall(PetscStrallocpy(DMPLEX_STORAGE_VERSION_FIRST, &defaultVersion));
3572e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5ReadAttribute(viewer, "/", ATTR_NAME, PETSC_STRING, &defaultVersion, &versionString));
3582e1d0745SJose E. Roman   PetscCall(PetscViewerParseVersion_Private(viewer, versionString, version));
3592e1d0745SJose E. Roman   PetscCall(PetscViewerAttachVersion_Private(viewer, DMPLEX_STORAGE_VERSION_READING_KEY, *version));
3602e1d0745SJose E. Roman   PetscCall(PetscFree(versionString));
3612e1d0745SJose E. Roman   PetscCall(PetscFree(defaultVersion));
3622e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
3632e1d0745SJose E. Roman }
3642e1d0745SJose E. Roman 
3652e1d0745SJose E. Roman static PetscErrorCode DMPlexGetHDF5Name_Private(DM dm, const char *name[])
3662e1d0745SJose E. Roman {
3672e1d0745SJose E. Roman   PetscFunctionBegin;
3682e1d0745SJose E. Roman   if (((PetscObject)dm)->name) {
3692e1d0745SJose E. Roman     PetscCall(PetscObjectGetName((PetscObject)dm, name));
3702e1d0745SJose E. Roman   } else {
3712e1d0745SJose E. Roman     *name = "plex";
3722e1d0745SJose E. Roman   }
3732e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
3742e1d0745SJose E. Roman }
3752e1d0745SJose E. Roman 
3762e1d0745SJose E. Roman PetscErrorCode DMSequenceGetLength_HDF5_Internal(DM dm, const char seqname[], PetscInt *seqlen, PetscViewer viewer)
3772e1d0745SJose E. Roman {
3782e1d0745SJose E. Roman   hid_t       file, group, dset, dspace;
3792e1d0745SJose E. Roman   hsize_t     rdim, *dims;
380ce78bad3SBarry Smith   const char *groupname;
3812e1d0745SJose E. Roman   PetscBool   has;
3822e1d0745SJose E. Roman 
3832e1d0745SJose E. Roman   PetscFunctionBegin;
3842e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5GetGroup(viewer, NULL, &groupname));
3852e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5HasDataset(viewer, seqname, &has));
3862e1d0745SJose E. Roman   PetscCheck(has, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Object (dataset) \"%s\" not stored in group %s", seqname, groupname);
3872e1d0745SJose E. Roman 
3882e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5OpenGroup(viewer, NULL, &file, &group));
3892e1d0745SJose E. Roman   PetscCallHDF5Return(dset, H5Dopen2, (group, seqname, H5P_DEFAULT));
3902e1d0745SJose E. Roman   PetscCallHDF5Return(dspace, H5Dget_space, (dset));
3912e1d0745SJose E. Roman   PetscCallHDF5ReturnNoCheck(rdim, H5Sget_simple_extent_dims, (dspace, NULL, NULL));
3922e1d0745SJose E. Roman   PetscCall(PetscMalloc1(rdim, &dims));
3932e1d0745SJose E. Roman   PetscCallHDF5ReturnNoCheck(rdim, H5Sget_simple_extent_dims, (dspace, dims, NULL));
3942e1d0745SJose E. Roman   *seqlen = (PetscInt)dims[0];
3952e1d0745SJose E. Roman   PetscCall(PetscFree(dims));
3962e1d0745SJose E. Roman   PetscCallHDF5(H5Dclose, (dset));
3972e1d0745SJose E. Roman   PetscCallHDF5(H5Gclose, (group));
3982e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
3992e1d0745SJose E. Roman }
4002e1d0745SJose E. Roman 
4012e1d0745SJose E. Roman static PetscErrorCode DMSequenceView_HDF5(DM dm, const char seqname[], PetscInt seqnum, PetscScalar value, PetscViewer viewer)
4022e1d0745SJose E. Roman {
4032e1d0745SJose E. Roman   Vec         stamp;
4042e1d0745SJose E. Roman   PetscMPIInt rank;
4052e1d0745SJose E. Roman 
4062e1d0745SJose E. Roman   PetscFunctionBegin;
4072e1d0745SJose E. Roman   if (seqnum < 0) PetscFunctionReturn(PETSC_SUCCESS);
4082e1d0745SJose E. Roman   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
4092e1d0745SJose E. Roman   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)viewer), rank ? 0 : 1, 1, &stamp));
4102e1d0745SJose E. Roman   PetscCall(VecSetBlockSize(stamp, 1));
4112e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)stamp, seqname));
4122e1d0745SJose E. Roman   if (rank == 0) {
4132e1d0745SJose E. Roman     PetscReal timeScale;
4142e1d0745SJose E. Roman     PetscBool istime;
4152e1d0745SJose E. Roman 
4162e1d0745SJose E. Roman     PetscCall(PetscStrncmp(seqname, "time", 5, &istime));
4172e1d0745SJose E. Roman     if (istime) {
4182e1d0745SJose E. Roman       PetscCall(DMPlexGetScale(dm, PETSC_UNIT_TIME, &timeScale));
4192e1d0745SJose E. Roman       value *= timeScale;
4202e1d0745SJose E. Roman     }
4212e1d0745SJose E. Roman     PetscCall(VecSetValue(stamp, 0, value, INSERT_VALUES));
4222e1d0745SJose E. Roman   }
4232e1d0745SJose E. Roman   PetscCall(VecAssemblyBegin(stamp));
4242e1d0745SJose E. Roman   PetscCall(VecAssemblyEnd(stamp));
4252e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "/"));
4262e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushTimestepping(viewer));
4272e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5SetTimestep(viewer, seqnum)); /* seqnum < 0 jumps out above */
4282e1d0745SJose E. Roman   PetscCall(VecView(stamp, viewer));
4292e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopTimestepping(viewer));
4302e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
4312e1d0745SJose E. Roman   PetscCall(VecDestroy(&stamp));
4322e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
4332e1d0745SJose E. Roman }
4342e1d0745SJose E. Roman 
4352e1d0745SJose E. Roman PetscErrorCode DMSequenceLoad_HDF5_Internal(DM dm, const char seqname[], PetscInt seqnum, PetscScalar *value, PetscViewer viewer)
4362e1d0745SJose E. Roman {
4372e1d0745SJose E. Roman   Vec         stamp;
4382e1d0745SJose E. Roman   PetscMPIInt rank;
4392e1d0745SJose E. Roman 
4402e1d0745SJose E. Roman   PetscFunctionBegin;
4412e1d0745SJose E. Roman   if (seqnum < 0) PetscFunctionReturn(PETSC_SUCCESS);
4422e1d0745SJose E. Roman   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
4432e1d0745SJose E. Roman   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)viewer), rank ? 0 : 1, 1, &stamp));
4442e1d0745SJose E. Roman   PetscCall(VecSetBlockSize(stamp, 1));
4452e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)stamp, seqname));
4462e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "/"));
4472e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushTimestepping(viewer));
4482e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5SetTimestep(viewer, seqnum)); /* seqnum < 0 jumps out above */
4492e1d0745SJose E. Roman   PetscCall(VecLoad(stamp, viewer));
4502e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopTimestepping(viewer));
4512e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
4522e1d0745SJose E. Roman   if (rank == 0) {
4532e1d0745SJose E. Roman     const PetscScalar *a;
4542e1d0745SJose E. Roman     PetscReal          timeScale;
4552e1d0745SJose E. Roman     PetscBool          istime;
4562e1d0745SJose E. Roman 
4572e1d0745SJose E. Roman     PetscCall(VecGetArrayRead(stamp, &a));
4582e1d0745SJose E. Roman     *value = a[0];
4592e1d0745SJose E. Roman     PetscCall(VecRestoreArrayRead(stamp, &a));
4602e1d0745SJose E. Roman     PetscCall(PetscStrncmp(seqname, "time", 5, &istime));
4612e1d0745SJose E. Roman     if (istime) {
4622e1d0745SJose E. Roman       PetscCall(DMPlexGetScale(dm, PETSC_UNIT_TIME, &timeScale));
4632e1d0745SJose E. Roman       *value /= timeScale;
4642e1d0745SJose E. Roman     }
4652e1d0745SJose E. Roman   }
4662e1d0745SJose E. Roman   PetscCall(VecDestroy(&stamp));
4672e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
4682e1d0745SJose E. Roman }
4692e1d0745SJose E. Roman 
4702e1d0745SJose E. Roman static PetscErrorCode DMPlexCreateCutVertexLabel_Private(DM dm, DMLabel cutLabel, DMLabel *cutVertexLabel)
4712e1d0745SJose E. Roman {
4722e1d0745SJose E. Roman   IS              cutcells = NULL;
4732e1d0745SJose E. Roman   const PetscInt *cutc;
4742e1d0745SJose E. Roman   PetscInt        cellHeight, vStart, vEnd, cStart, cEnd, c;
4752e1d0745SJose E. Roman 
4762e1d0745SJose E. Roman   PetscFunctionBegin;
4772e1d0745SJose E. Roman   if (!cutLabel) PetscFunctionReturn(PETSC_SUCCESS);
4782e1d0745SJose E. Roman   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
4792e1d0745SJose E. Roman   PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
4802e1d0745SJose E. Roman   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
4812e1d0745SJose E. Roman   /* Label vertices that should be duplicated */
4822e1d0745SJose E. Roman   PetscCall(DMLabelCreate(PETSC_COMM_SELF, "Cut Vertices", cutVertexLabel));
4832e1d0745SJose E. Roman   PetscCall(DMLabelGetStratumIS(cutLabel, 2, &cutcells));
4842e1d0745SJose E. Roman   if (cutcells) {
4852e1d0745SJose E. Roman     PetscInt n;
4862e1d0745SJose E. Roman 
4872e1d0745SJose E. Roman     PetscCall(ISGetIndices(cutcells, &cutc));
4882e1d0745SJose E. Roman     PetscCall(ISGetLocalSize(cutcells, &n));
4892e1d0745SJose E. Roman     for (c = 0; c < n; ++c) {
4902e1d0745SJose E. Roman       if ((cutc[c] >= cStart) && (cutc[c] < cEnd)) {
4912e1d0745SJose E. Roman         PetscInt *closure = NULL;
4922e1d0745SJose E. Roman         PetscInt  closureSize, cl, value;
4932e1d0745SJose E. Roman 
4942e1d0745SJose E. Roman         PetscCall(DMPlexGetTransitiveClosure(dm, cutc[c], PETSC_TRUE, &closureSize, &closure));
4952e1d0745SJose E. Roman         for (cl = 0; cl < closureSize * 2; cl += 2) {
4962e1d0745SJose E. Roman           if ((closure[cl] >= vStart) && (closure[cl] < vEnd)) {
4972e1d0745SJose E. Roman             PetscCall(DMLabelGetValue(cutLabel, closure[cl], &value));
4982e1d0745SJose E. Roman             if (value == 1) PetscCall(DMLabelSetValue(*cutVertexLabel, closure[cl], 1));
4992e1d0745SJose E. Roman           }
5002e1d0745SJose E. Roman         }
5012e1d0745SJose E. Roman         PetscCall(DMPlexRestoreTransitiveClosure(dm, cutc[c], PETSC_TRUE, &closureSize, &closure));
5022e1d0745SJose E. Roman       }
5032e1d0745SJose E. Roman     }
5042e1d0745SJose E. Roman     PetscCall(ISRestoreIndices(cutcells, &cutc));
5052e1d0745SJose E. Roman   }
5062e1d0745SJose E. Roman   PetscCall(ISDestroy(&cutcells));
5072e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
5082e1d0745SJose E. Roman }
5092e1d0745SJose E. Roman 
5102e1d0745SJose E. Roman PetscErrorCode VecView_Plex_Local_HDF5_Internal(Vec v, PetscViewer viewer)
5112e1d0745SJose E. Roman {
5125a236de6SSatish Balay   DMPlexStorageVersion version;
5132e1d0745SJose E. Roman   DM                   dm;
5142e1d0745SJose E. Roman   DM                   dmBC;
5152e1d0745SJose E. Roman   PetscSection         section, sectionGlobal;
5162e1d0745SJose E. Roman   Vec                  gv;
5172e1d0745SJose E. Roman   const char          *name;
5182e1d0745SJose E. Roman   PetscViewerFormat    format;
5192e1d0745SJose E. Roman   PetscInt             seqnum;
5202e1d0745SJose E. Roman   PetscReal            seqval;
5212e1d0745SJose E. Roman   PetscBool            isseq;
5222e1d0745SJose E. Roman 
5232e1d0745SJose E. Roman   PetscFunctionBegin;
5245a236de6SSatish Balay   PetscCall(PetscViewerHDF5GetDMPlexStorageVersionWriting(viewer, &version));
5252e1d0745SJose E. Roman   PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq));
5262e1d0745SJose E. Roman   PetscCall(VecGetDM(v, &dm));
5272e1d0745SJose E. Roman   PetscCall(DMGetLocalSection(dm, &section));
5282e1d0745SJose E. Roman   PetscCall(DMGetOutputSequenceNumber(dm, &seqnum, &seqval));
5292e1d0745SJose E. Roman   PetscCall(DMSequenceView_HDF5(dm, "time", seqnum, (PetscScalar)seqval, viewer));
5302e1d0745SJose E. Roman   if (seqnum >= 0) {
5312e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5PushTimestepping(viewer));
5322e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5SetTimestep(viewer, seqnum));
5332e1d0745SJose E. Roman   }
5342e1d0745SJose E. Roman   PetscCall(PetscViewerGetFormat(viewer, &format));
5352e1d0745SJose E. Roman   PetscCall(DMGetOutputDM(dm, &dmBC));
5362e1d0745SJose E. Roman   PetscCall(DMGetGlobalSection(dmBC, &sectionGlobal));
5372e1d0745SJose E. Roman   PetscCall(DMGetGlobalVector(dmBC, &gv));
5382e1d0745SJose E. Roman   PetscCall(PetscObjectGetName((PetscObject)v, &name));
5392e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)gv, name));
5402e1d0745SJose E. Roman   PetscCall(DMLocalToGlobalBegin(dmBC, v, INSERT_VALUES, gv));
5412e1d0745SJose E. Roman   PetscCall(DMLocalToGlobalEnd(dmBC, v, INSERT_VALUES, gv));
5422e1d0745SJose E. Roman   PetscCall(PetscObjectTypeCompare((PetscObject)gv, VECSEQ, &isseq));
5432e1d0745SJose E. Roman   if (format == PETSC_VIEWER_HDF5_VIZ) {
5442e1d0745SJose E. Roman     /* Output visualization representation */
5452e1d0745SJose E. Roman     PetscInt numFields, f;
5462e1d0745SJose E. Roman     DMLabel  cutLabel, cutVertexLabel = NULL;
5472e1d0745SJose E. Roman 
5482e1d0745SJose E. Roman     PetscCall(PetscSectionGetNumFields(section, &numFields));
5492e1d0745SJose E. Roman     PetscCall(DMGetLabel(dm, "periodic_cut", &cutLabel));
5502e1d0745SJose E. Roman     for (f = 0; f < numFields; ++f) {
5512e1d0745SJose E. Roman       Vec                      subv;
5522e1d0745SJose E. Roman       IS                       is;
5532e1d0745SJose E. Roman       const char              *fname, *fgroup, *componentName, *fname_def = "unnamed";
5542e1d0745SJose E. Roman       char                     subname[PETSC_MAX_PATH_LEN];
5555a236de6SSatish Balay       PetscInt                 Nc, Nt = 1;
5565a236de6SSatish Balay       PetscInt                *pStart, *pEnd;
5575a236de6SSatish Balay       PetscViewerVTKFieldType *ft;
5582e1d0745SJose E. Roman 
5595a236de6SSatish Balay       if (DMPlexStorageVersionEQ(version, 1, 1, 0)) PetscCall(DMPlexGetFieldTypes_Internal(dm, section, f, &Nt, &pStart, &pEnd, &ft));
5605a236de6SSatish Balay       else {
5615a236de6SSatish Balay         PetscCall(PetscMalloc3(Nt, &pStart, Nt, &pEnd, Nt, &ft));
5625a236de6SSatish Balay         PetscCall(DMPlexGetFieldType_Internal(dm, section, f, &pStart[0], &pEnd[0], &ft[0]));
5635a236de6SSatish Balay       }
5645a236de6SSatish Balay       for (PetscInt t = 0; t < Nt; ++t) {
5655a236de6SSatish Balay         if (ft[t] == PETSC_VTK_INVALID) continue;
5665a236de6SSatish Balay         fgroup = (ft[t] == PETSC_VTK_POINT_VECTOR_FIELD) || (ft[t] == PETSC_VTK_POINT_FIELD) ? "/vertex_fields" : "/cell_fields";
5672e1d0745SJose E. Roman         PetscCall(PetscSectionGetFieldName(section, f, &fname));
5682e1d0745SJose E. Roman         if (!fname) fname = fname_def;
5692e1d0745SJose E. Roman 
5705a236de6SSatish Balay         if (!t) {
5712e1d0745SJose E. Roman           PetscCall(PetscViewerHDF5PushGroup(viewer, fgroup));
5725a236de6SSatish Balay         } else {
5735a236de6SSatish Balay           char group[PETSC_MAX_PATH_LEN];
5745a236de6SSatish Balay 
5755a236de6SSatish Balay           PetscCall(PetscSNPrintf(group, PETSC_MAX_PATH_LEN, "%s_%" PetscInt_FMT, fgroup, t));
5765a236de6SSatish Balay           PetscCall(PetscViewerHDF5PushGroup(viewer, group));
5775a236de6SSatish Balay         }
5782e1d0745SJose E. Roman 
5792e1d0745SJose E. Roman         if (cutLabel) {
5802e1d0745SJose E. Roman           const PetscScalar *ga;
5812e1d0745SJose E. Roman           PetscScalar       *suba;
5825a236de6SSatish Balay           PetscInt           gstart, subSize = 0, extSize = 0, subOff = 0, newOff = 0;
5832e1d0745SJose E. Roman 
5842e1d0745SJose E. Roman           PetscCall(DMPlexCreateCutVertexLabel_Private(dm, cutLabel, &cutVertexLabel));
5852e1d0745SJose E. Roman           PetscCall(PetscSectionGetFieldComponents(section, f, &Nc));
5865a236de6SSatish Balay           for (PetscInt p = pStart[t]; p < pEnd[t]; ++p) {
5872e1d0745SJose E. Roman             PetscInt gdof, fdof = 0, val;
5882e1d0745SJose E. Roman 
5892e1d0745SJose E. Roman             PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof));
5902e1d0745SJose E. Roman             if (gdof > 0) PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof));
5912e1d0745SJose E. Roman             subSize += fdof;
5922e1d0745SJose E. Roman             PetscCall(DMLabelGetValue(cutVertexLabel, p, &val));
5932e1d0745SJose E. Roman             if (val == 1) extSize += fdof;
5942e1d0745SJose E. Roman           }
5952e1d0745SJose E. Roman           PetscCall(VecCreate(PetscObjectComm((PetscObject)gv), &subv));
5962e1d0745SJose E. Roman           PetscCall(VecSetSizes(subv, subSize + extSize, PETSC_DETERMINE));
5972e1d0745SJose E. Roman           PetscCall(VecSetBlockSize(subv, Nc));
5982e1d0745SJose E. Roman           PetscCall(VecSetType(subv, VECSTANDARD));
5992e1d0745SJose E. Roman           PetscCall(VecGetOwnershipRange(gv, &gstart, NULL));
6002e1d0745SJose E. Roman           PetscCall(VecGetArrayRead(gv, &ga));
6012e1d0745SJose E. Roman           PetscCall(VecGetArray(subv, &suba));
6025a236de6SSatish Balay           for (PetscInt p = pStart[t]; p < pEnd[t]; ++p) {
6032e1d0745SJose E. Roman             PetscInt gdof, goff, val;
6042e1d0745SJose E. Roman 
6052e1d0745SJose E. Roman             PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof));
6062e1d0745SJose E. Roman             if (gdof > 0) {
6072e1d0745SJose E. Roman               PetscInt fdof, fc, f2, poff = 0;
6082e1d0745SJose E. Roman 
6092e1d0745SJose E. Roman               PetscCall(PetscSectionGetOffset(sectionGlobal, p, &goff));
6102e1d0745SJose E. Roman               /* Can get rid of this loop by storing field information in the global section */
6112e1d0745SJose E. Roman               for (f2 = 0; f2 < f; ++f2) {
6122e1d0745SJose E. Roman                 PetscCall(PetscSectionGetFieldDof(section, p, f2, &fdof));
6132e1d0745SJose E. Roman                 poff += fdof;
6142e1d0745SJose E. Roman               }
6152e1d0745SJose E. Roman               PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof));
6162e1d0745SJose E. Roman               for (fc = 0; fc < fdof; ++fc, ++subOff) suba[subOff] = ga[goff + poff + fc - gstart];
6172e1d0745SJose E. Roman               PetscCall(DMLabelGetValue(cutVertexLabel, p, &val));
6182e1d0745SJose E. Roman               if (val == 1) {
6192e1d0745SJose E. Roman                 for (fc = 0; fc < fdof; ++fc, ++newOff) suba[subSize + newOff] = ga[goff + poff + fc - gstart];
6202e1d0745SJose E. Roman               }
6212e1d0745SJose E. Roman             }
6222e1d0745SJose E. Roman           }
6232e1d0745SJose E. Roman           PetscCall(VecRestoreArrayRead(gv, &ga));
6242e1d0745SJose E. Roman           PetscCall(VecRestoreArray(subv, &suba));
6252e1d0745SJose E. Roman           PetscCall(DMLabelDestroy(&cutVertexLabel));
6262e1d0745SJose E. Roman         } else {
6275a236de6SSatish Balay           PetscCall(PetscSectionGetField_Internal(section, sectionGlobal, gv, f, pStart[t], pEnd[t], &is, &subv));
6282e1d0745SJose E. Roman         }
6292e1d0745SJose E. Roman         PetscCall(PetscStrncpy(subname, name, sizeof(subname)));
6302e1d0745SJose E. Roman         PetscCall(PetscStrlcat(subname, "_", sizeof(subname)));
6312e1d0745SJose E. Roman         PetscCall(PetscStrlcat(subname, fname, sizeof(subname)));
6322e1d0745SJose E. Roman         PetscCall(PetscObjectSetName((PetscObject)subv, subname));
6332e1d0745SJose E. Roman         if (isseq) PetscCall(VecView_Seq(subv, viewer));
6342e1d0745SJose E. Roman         else PetscCall(VecView_MPI(subv, viewer));
6355a236de6SSatish Balay         if (ft[t] == PETSC_VTK_POINT_VECTOR_FIELD || ft[t] == PETSC_VTK_CELL_VECTOR_FIELD) {
6362e1d0745SJose E. Roman           PetscCall(PetscViewerHDF5WriteObjectAttribute(viewer, (PetscObject)subv, "vector_field_type", PETSC_STRING, "vector"));
6372e1d0745SJose E. Roman         } else {
6382e1d0745SJose E. Roman           PetscCall(PetscViewerHDF5WriteObjectAttribute(viewer, (PetscObject)subv, "vector_field_type", PETSC_STRING, "scalar"));
6392e1d0745SJose E. Roman         }
6402e1d0745SJose E. Roman 
6412e1d0745SJose E. Roman         /* Output the component names in the field if available */
6422e1d0745SJose E. Roman         PetscCall(PetscSectionGetFieldComponents(section, f, &Nc));
6435a236de6SSatish Balay         for (PetscInt c = 0; c < Nc; ++c) {
6442e1d0745SJose E. Roman           char componentNameLabel[PETSC_MAX_PATH_LEN];
6452e1d0745SJose E. Roman           PetscCall(PetscSectionGetComponentName(section, f, c, &componentName));
6462e1d0745SJose E. Roman           PetscCall(PetscSNPrintf(componentNameLabel, sizeof(componentNameLabel), "componentName%" PetscInt_FMT, c));
6472e1d0745SJose E. Roman           PetscCall(PetscViewerHDF5WriteObjectAttribute(viewer, (PetscObject)subv, componentNameLabel, PETSC_STRING, componentName));
6482e1d0745SJose E. Roman         }
6492e1d0745SJose E. Roman 
6502e1d0745SJose E. Roman         if (cutLabel) PetscCall(VecDestroy(&subv));
6515a236de6SSatish Balay         else PetscCall(PetscSectionRestoreField_Internal(section, sectionGlobal, gv, f, pStart[t], pEnd[t], &is, &subv));
6522e1d0745SJose E. Roman         PetscCall(PetscViewerHDF5PopGroup(viewer));
6532e1d0745SJose E. Roman       }
654c935b23eSStefano Zampini       if (!DMPlexStorageVersionEQ(version, 1, 1, 0)) PetscCall(PetscFree3(pStart, pEnd, ft));
6555a236de6SSatish Balay     }
6562e1d0745SJose E. Roman   } else {
6572e1d0745SJose E. Roman     /* Output full vector */
6582e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5PushGroup(viewer, "/fields"));
6592e1d0745SJose E. Roman     if (isseq) PetscCall(VecView_Seq(gv, viewer));
6602e1d0745SJose E. Roman     else PetscCall(VecView_MPI(gv, viewer));
6612e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5PopGroup(viewer));
6622e1d0745SJose E. Roman   }
6632e1d0745SJose E. Roman   if (seqnum >= 0) PetscCall(PetscViewerHDF5PopTimestepping(viewer));
6642e1d0745SJose E. Roman   PetscCall(DMRestoreGlobalVector(dmBC, &gv));
6652e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
6662e1d0745SJose E. Roman }
6672e1d0745SJose E. Roman 
6682e1d0745SJose E. Roman PetscErrorCode VecView_Plex_HDF5_Internal(Vec v, PetscViewer viewer)
6692e1d0745SJose E. Roman {
6702e1d0745SJose E. Roman   DMPlexStorageVersion version;
6712e1d0745SJose E. Roman   DM                   dm;
6722e1d0745SJose E. Roman   Vec                  locv;
6732e1d0745SJose E. Roman   PetscObject          isZero;
6742e1d0745SJose E. Roman   const char          *name;
6752e1d0745SJose E. Roman   PetscReal            time;
6762e1d0745SJose E. Roman 
6772e1d0745SJose E. Roman   PetscFunctionBegin;
6782e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5GetDMPlexStorageVersionWriting(viewer, &version));
6792e1d0745SJose E. Roman   PetscCall(PetscInfo(v, "Writing Vec %s storage version %d.%d.%d\n", v->hdr.name, version->major, version->minor, version->subminor));
6802e1d0745SJose E. Roman 
6812e1d0745SJose E. Roman   PetscCall(VecGetDM(v, &dm));
6822e1d0745SJose E. Roman   PetscCall(DMGetLocalVector(dm, &locv));
6832e1d0745SJose E. Roman   PetscCall(PetscObjectGetName((PetscObject)v, &name));
6842e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)locv, name));
6852e1d0745SJose E. Roman   PetscCall(PetscObjectQuery((PetscObject)v, "__Vec_bc_zero__", &isZero));
6862e1d0745SJose E. Roman   PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", isZero));
6872e1d0745SJose E. Roman   PetscCall(DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv));
6882e1d0745SJose E. Roman   PetscCall(DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv));
6892e1d0745SJose E. Roman   PetscCall(DMGetOutputSequenceNumber(dm, NULL, &time));
6902e1d0745SJose E. Roman   PetscCall(DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locv, time, NULL, NULL, NULL));
6912e1d0745SJose E. Roman   PetscCall(VecView_Plex_Local_HDF5_Internal(locv, viewer));
6922e1d0745SJose E. Roman   if (DMPlexStorageVersionEQ(version, 1, 1, 0)) {
6932e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5PushGroup(viewer, "/fields"));
6942e1d0745SJose E. Roman     PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_HDF5_VIZ));
6952e1d0745SJose E. Roman     PetscCall(VecView_Plex_Local_HDF5_Internal(locv, viewer));
6962e1d0745SJose E. Roman     PetscCall(PetscViewerPopFormat(viewer));
6972e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5PopGroup(viewer));
6982e1d0745SJose E. Roman   }
6992e1d0745SJose E. Roman   PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", NULL));
7002e1d0745SJose E. Roman   PetscCall(DMRestoreLocalVector(dm, &locv));
7012e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
7022e1d0745SJose E. Roman }
7032e1d0745SJose E. Roman 
7042e1d0745SJose E. Roman PetscErrorCode VecView_Plex_HDF5_Native_Internal(Vec v, PetscViewer viewer)
7052e1d0745SJose E. Roman {
7062e1d0745SJose E. Roman   PetscBool isseq;
7072e1d0745SJose E. Roman 
7082e1d0745SJose E. Roman   PetscFunctionBegin;
7092e1d0745SJose E. Roman   PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq));
7102e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "/fields"));
7112e1d0745SJose E. Roman   if (isseq) PetscCall(VecView_Seq(v, viewer));
7122e1d0745SJose E. Roman   else PetscCall(VecView_MPI(v, viewer));
7132e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
7142e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
7152e1d0745SJose E. Roman }
7162e1d0745SJose E. Roman 
7172e1d0745SJose E. Roman PetscErrorCode VecLoad_Plex_HDF5_Internal(Vec v, PetscViewer viewer)
7182e1d0745SJose E. Roman {
7192e1d0745SJose E. Roman   DM          dm;
7202e1d0745SJose E. Roman   Vec         locv;
7212e1d0745SJose E. Roman   const char *name;
7222e1d0745SJose E. Roman   PetscInt    seqnum;
7232e1d0745SJose E. Roman 
7242e1d0745SJose E. Roman   PetscFunctionBegin;
7252e1d0745SJose E. Roman   PetscCall(VecGetDM(v, &dm));
7262e1d0745SJose E. Roman   PetscCall(DMGetLocalVector(dm, &locv));
7272e1d0745SJose E. Roman   PetscCall(PetscObjectGetName((PetscObject)v, &name));
7282e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)locv, name));
7292e1d0745SJose E. Roman   PetscCall(DMGetOutputSequenceNumber(dm, &seqnum, NULL));
7302e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "/fields"));
7312e1d0745SJose E. Roman   if (seqnum >= 0) {
7322e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5PushTimestepping(viewer));
7332e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5SetTimestep(viewer, seqnum));
7342e1d0745SJose E. Roman   }
7352e1d0745SJose E. Roman   PetscCall(VecLoad_Plex_Local(locv, viewer));
7362e1d0745SJose E. Roman   if (seqnum >= 0) PetscCall(PetscViewerHDF5PopTimestepping(viewer));
7372e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
7382e1d0745SJose E. Roman   PetscCall(DMLocalToGlobalBegin(dm, locv, INSERT_VALUES, v));
7392e1d0745SJose E. Roman   PetscCall(DMLocalToGlobalEnd(dm, locv, INSERT_VALUES, v));
7402e1d0745SJose E. Roman   PetscCall(DMRestoreLocalVector(dm, &locv));
7412e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
7422e1d0745SJose E. Roman }
7432e1d0745SJose E. Roman 
7442e1d0745SJose E. Roman PetscErrorCode VecLoad_Plex_HDF5_Native_Internal(Vec v, PetscViewer viewer)
7452e1d0745SJose E. Roman {
7462e1d0745SJose E. Roman   DM       dm;
7472e1d0745SJose E. Roman   PetscInt seqnum;
7482e1d0745SJose E. Roman 
7492e1d0745SJose E. Roman   PetscFunctionBegin;
7502e1d0745SJose E. Roman   PetscCall(VecGetDM(v, &dm));
7512e1d0745SJose E. Roman   PetscCall(DMGetOutputSequenceNumber(dm, &seqnum, NULL));
7522e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "/fields"));
7532e1d0745SJose E. Roman   if (seqnum >= 0) {
7542e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5PushTimestepping(viewer));
7552e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5SetTimestep(viewer, seqnum));
7562e1d0745SJose E. Roman   }
7572e1d0745SJose E. Roman   PetscCall(VecLoad_Default(v, viewer));
7582e1d0745SJose E. Roman   if (seqnum >= 0) PetscCall(PetscViewerHDF5PopTimestepping(viewer));
7592e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
7602e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
7612e1d0745SJose E. Roman }
7622e1d0745SJose E. Roman 
7632e1d0745SJose E. Roman static PetscErrorCode DMPlexDistributionView_HDF5_Private(DM dm, IS globalPointNumbers, PetscViewer viewer)
7642e1d0745SJose E. Roman {
7655a236de6SSatish Balay   DMPlexStorageVersion version;
7662e1d0745SJose E. Roman   MPI_Comm             comm;
7672e1d0745SJose E. Roman   PetscMPIInt          size, rank;
7682e1d0745SJose E. Roman   PetscInt             size_petsc_int;
7692e1d0745SJose E. Roman   const char          *topologydm_name, *distribution_name;
7702e1d0745SJose E. Roman   const PetscInt      *gpoint;
7712e1d0745SJose E. Roman   PetscInt             pStart, pEnd, p;
7722e1d0745SJose E. Roman   PetscSF              pointSF;
7732e1d0745SJose E. Roman   PetscInt             nroots, nleaves;
7742e1d0745SJose E. Roman   const PetscInt      *ilocal;
7752e1d0745SJose E. Roman   const PetscSFNode   *iremote;
7762e1d0745SJose E. Roman   IS                   chartSizesIS, ownersIS, gpointsIS;
7772e1d0745SJose E. Roman   PetscInt            *chartSize, *owners, *gpoints;
778*ea87367fSMatthew G. Knepley   PetscBool            ocompress;
7792e1d0745SJose E. Roman 
7802e1d0745SJose E. Roman   PetscFunctionBegin;
7815a236de6SSatish Balay   PetscCall(PetscViewerHDF5GetDMPlexStorageVersionWriting(viewer, &version));
7822e1d0745SJose E. Roman   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
7832e1d0745SJose E. Roman   PetscCallMPI(MPI_Comm_size(comm, &size));
7842e1d0745SJose E. Roman   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7852e1d0745SJose E. Roman   PetscCall(DMPlexGetHDF5Name_Private(dm, &topologydm_name));
7862e1d0745SJose E. Roman   PetscCall(DMPlexDistributionGetName(dm, &distribution_name));
7872e1d0745SJose E. Roman   if (!distribution_name) PetscFunctionReturn(PETSC_SUCCESS);
7882e1d0745SJose E. Roman   PetscCall(PetscLogEventBegin(DMPLEX_DistributionView, viewer, 0, 0, 0));
7892e1d0745SJose E. Roman   size_petsc_int = (PetscInt)size;
7902e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5WriteAttribute(viewer, NULL, "comm_size", PETSC_INT, (void *)&size_petsc_int));
7912e1d0745SJose E. Roman   PetscCall(ISGetIndices(globalPointNumbers, &gpoint));
7922e1d0745SJose E. Roman   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
7932e1d0745SJose E. Roman   PetscCall(PetscMalloc1(1, &chartSize));
7942e1d0745SJose E. Roman   *chartSize = pEnd - pStart;
7952e1d0745SJose E. Roman   PetscCall(PetscMalloc1(*chartSize, &owners));
7962e1d0745SJose E. Roman   PetscCall(PetscMalloc1(*chartSize, &gpoints));
7972e1d0745SJose E. Roman   PetscCall(DMGetPointSF(dm, &pointSF));
7982e1d0745SJose E. Roman   PetscCall(PetscSFGetGraph(pointSF, &nroots, &nleaves, &ilocal, &iremote));
7992e1d0745SJose E. Roman   for (p = pStart; p < pEnd; ++p) {
8002e1d0745SJose E. Roman     PetscInt gp = gpoint[p - pStart];
8012e1d0745SJose E. Roman 
8022e1d0745SJose E. Roman     owners[p - pStart]  = rank;
8032e1d0745SJose E. Roman     gpoints[p - pStart] = (gp < 0 ? -(gp + 1) : gp);
8042e1d0745SJose E. Roman   }
8052e1d0745SJose E. Roman   for (p = 0; p < nleaves; ++p) {
8062e1d0745SJose E. Roman     PetscInt ilocalp = (ilocal ? ilocal[p] : p);
8072e1d0745SJose E. Roman 
8082e1d0745SJose E. Roman     owners[ilocalp] = iremote[p].rank;
8092e1d0745SJose E. Roman   }
8102e1d0745SJose E. Roman   PetscCall(ISCreateGeneral(comm, 1, chartSize, PETSC_OWN_POINTER, &chartSizesIS));
8112e1d0745SJose E. Roman   PetscCall(ISCreateGeneral(comm, *chartSize, owners, PETSC_OWN_POINTER, &ownersIS));
8122e1d0745SJose E. Roman   PetscCall(ISCreateGeneral(comm, *chartSize, gpoints, PETSC_OWN_POINTER, &gpointsIS));
8135a236de6SSatish Balay   if (DMPlexStorageVersionGE(version, 3, 1, 0)) {
814*ea87367fSMatthew G. Knepley     PetscCall(PetscViewerHDF5GetCompress(viewer, &ocompress));
815*ea87367fSMatthew G. Knepley     PetscCall(PetscViewerHDF5SetCompress(viewer, PETSC_TRUE));
8165a236de6SSatish Balay   }
8172e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)chartSizesIS, "chart_sizes"));
8182e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)ownersIS, "owners"));
8192e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)gpointsIS, "global_point_numbers"));
8202e1d0745SJose E. Roman   PetscCall(ISView(chartSizesIS, viewer));
8212e1d0745SJose E. Roman   PetscCall(ISView(ownersIS, viewer));
8222e1d0745SJose E. Roman   PetscCall(ISView(gpointsIS, viewer));
8232e1d0745SJose E. Roman   PetscCall(ISDestroy(&chartSizesIS));
8242e1d0745SJose E. Roman   PetscCall(ISDestroy(&ownersIS));
8252e1d0745SJose E. Roman   PetscCall(ISDestroy(&gpointsIS));
8262e1d0745SJose E. Roman   PetscCall(ISRestoreIndices(globalPointNumbers, &gpoint));
827*ea87367fSMatthew G. Knepley   if (DMPlexStorageVersionGE(version, 3, 1, 0)) PetscCall(PetscViewerHDF5SetCompress(viewer, ocompress));
8282e1d0745SJose E. Roman   PetscCall(PetscLogEventEnd(DMPLEX_DistributionView, viewer, 0, 0, 0));
8292e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
8302e1d0745SJose E. Roman }
8312e1d0745SJose E. Roman 
8322e1d0745SJose E. Roman static PetscErrorCode DMPlexTopologyView_HDF5_Inner_Private(DM dm, IS globalPointNumbers, PetscViewer viewer, PetscInt pStart, PetscInt pEnd, const char pointsName[], const char coneSizesName[], const char conesName[], const char orientationsName[])
8332e1d0745SJose E. Roman {
8345a236de6SSatish Balay   DMPlexStorageVersion version;
8352e1d0745SJose E. Roman   IS                   coneSizesIS, conesIS, orientationsIS;
8362e1d0745SJose E. Roman   PetscInt            *coneSizes, *cones, *orientations;
8372e1d0745SJose E. Roman   const PetscInt      *gpoint;
8382e1d0745SJose E. Roman   PetscInt             nPoints = 0, conesSize = 0;
8392e1d0745SJose E. Roman   PetscInt             p, c, s;
840*ea87367fSMatthew G. Knepley   PetscBool            ocompress;
8412e1d0745SJose E. Roman   MPI_Comm             comm;
8422e1d0745SJose E. Roman 
8432e1d0745SJose E. Roman   PetscFunctionBegin;
8445a236de6SSatish Balay   PetscCall(PetscViewerHDF5GetDMPlexStorageVersionWriting(viewer, &version));
8452e1d0745SJose E. Roman   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
8462e1d0745SJose E. Roman   PetscCall(ISGetIndices(globalPointNumbers, &gpoint));
8472e1d0745SJose E. Roman   for (p = pStart; p < pEnd; ++p) {
8482e1d0745SJose E. Roman     if (gpoint[p] >= 0) {
8492e1d0745SJose E. Roman       PetscInt coneSize;
8502e1d0745SJose E. Roman 
8512e1d0745SJose E. Roman       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
8522e1d0745SJose E. Roman       nPoints += 1;
8532e1d0745SJose E. Roman       conesSize += coneSize;
8542e1d0745SJose E. Roman     }
8552e1d0745SJose E. Roman   }
8562e1d0745SJose E. Roman   PetscCall(PetscMalloc1(nPoints, &coneSizes));
8572e1d0745SJose E. Roman   PetscCall(PetscMalloc1(conesSize, &cones));
8582e1d0745SJose E. Roman   PetscCall(PetscMalloc1(conesSize, &orientations));
8592e1d0745SJose E. Roman   for (p = pStart, c = 0, s = 0; p < pEnd; ++p) {
8602e1d0745SJose E. Roman     if (gpoint[p] >= 0) {
8612e1d0745SJose E. Roman       const PetscInt *cone, *ornt;
8622e1d0745SJose E. Roman       PetscInt        coneSize, cp;
8632e1d0745SJose E. Roman 
8642e1d0745SJose E. Roman       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
8652e1d0745SJose E. Roman       PetscCall(DMPlexGetCone(dm, p, &cone));
8662e1d0745SJose E. Roman       PetscCall(DMPlexGetConeOrientation(dm, p, &ornt));
8672e1d0745SJose E. Roman       coneSizes[s] = coneSize;
8682e1d0745SJose E. Roman       for (cp = 0; cp < coneSize; ++cp, ++c) {
8692e1d0745SJose E. Roman         cones[c]        = gpoint[cone[cp]] < 0 ? -(gpoint[cone[cp]] + 1) : gpoint[cone[cp]];
8702e1d0745SJose E. Roman         orientations[c] = ornt[cp];
8712e1d0745SJose E. Roman       }
8722e1d0745SJose E. Roman       ++s;
8732e1d0745SJose E. Roman     }
8742e1d0745SJose E. Roman   }
8752e1d0745SJose E. Roman   PetscCheck(s == nPoints, PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of points %" PetscInt_FMT " != %" PetscInt_FMT, s, nPoints);
8762e1d0745SJose E. Roman   PetscCheck(c == conesSize, PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of cone points %" PetscInt_FMT " != %" PetscInt_FMT, c, conesSize);
8772e1d0745SJose E. Roman   PetscCall(ISCreateGeneral(comm, nPoints, coneSizes, PETSC_OWN_POINTER, &coneSizesIS));
8782e1d0745SJose E. Roman   PetscCall(ISCreateGeneral(comm, conesSize, cones, PETSC_OWN_POINTER, &conesIS));
8792e1d0745SJose E. Roman   PetscCall(ISCreateGeneral(comm, conesSize, orientations, PETSC_OWN_POINTER, &orientationsIS));
8802e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)coneSizesIS, coneSizesName));
8812e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)conesIS, conesName));
8822e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)orientationsIS, orientationsName));
8835a236de6SSatish Balay   if (DMPlexStorageVersionGE(version, 3, 1, 0)) {
884*ea87367fSMatthew G. Knepley     PetscCall(PetscViewerHDF5GetCompress(viewer, &ocompress));
885*ea87367fSMatthew G. Knepley     PetscCall(PetscViewerHDF5SetCompress(viewer, PETSC_TRUE));
8865a236de6SSatish Balay   }
8872e1d0745SJose E. Roman   PetscCall(ISView(coneSizesIS, viewer));
8882e1d0745SJose E. Roman   PetscCall(ISView(conesIS, viewer));
8892e1d0745SJose E. Roman   PetscCall(ISView(orientationsIS, viewer));
8902e1d0745SJose E. Roman   PetscCall(ISDestroy(&coneSizesIS));
8912e1d0745SJose E. Roman   PetscCall(ISDestroy(&conesIS));
8922e1d0745SJose E. Roman   PetscCall(ISDestroy(&orientationsIS));
8932e1d0745SJose E. Roman   if (pointsName) {
8942e1d0745SJose E. Roman     IS        pointsIS;
8952e1d0745SJose E. Roman     PetscInt *points;
8962e1d0745SJose E. Roman 
8972e1d0745SJose E. Roman     PetscCall(PetscMalloc1(nPoints, &points));
8982e1d0745SJose E. Roman     for (p = pStart, c = 0, s = 0; p < pEnd; ++p) {
8992e1d0745SJose E. Roman       if (gpoint[p] >= 0) {
9002e1d0745SJose E. Roman         points[s] = gpoint[p];
9012e1d0745SJose E. Roman         ++s;
9022e1d0745SJose E. Roman       }
9032e1d0745SJose E. Roman     }
9042e1d0745SJose E. Roman     PetscCall(ISCreateGeneral(comm, nPoints, points, PETSC_OWN_POINTER, &pointsIS));
9052e1d0745SJose E. Roman     PetscCall(PetscObjectSetName((PetscObject)pointsIS, pointsName));
9062e1d0745SJose E. Roman     PetscCall(ISView(pointsIS, viewer));
9072e1d0745SJose E. Roman     PetscCall(ISDestroy(&pointsIS));
9082e1d0745SJose E. Roman   }
9092e1d0745SJose E. Roman   PetscCall(ISRestoreIndices(globalPointNumbers, &gpoint));
910*ea87367fSMatthew G. Knepley   if (DMPlexStorageVersionGE(version, 3, 1, 0)) PetscCall(PetscViewerHDF5SetCompress(viewer, ocompress));
9112e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
9122e1d0745SJose E. Roman }
9132e1d0745SJose E. Roman 
9142e1d0745SJose E. Roman static PetscErrorCode DMPlexTopologyView_HDF5_Legacy_Private(DM dm, IS globalPointNumbers, PetscViewer viewer)
9152e1d0745SJose E. Roman {
9162e1d0745SJose E. Roman   const char *pointsName, *coneSizesName, *conesName, *orientationsName;
9172e1d0745SJose E. Roman   PetscInt    pStart, pEnd, dim;
9182e1d0745SJose E. Roman 
9192e1d0745SJose E. Roman   PetscFunctionBegin;
9202e1d0745SJose E. Roman   pointsName       = "order";
9212e1d0745SJose E. Roman   coneSizesName    = "cones";
9222e1d0745SJose E. Roman   conesName        = "cells";
9232e1d0745SJose E. Roman   orientationsName = "orientation";
9242e1d0745SJose E. Roman   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
9252e1d0745SJose E. Roman   PetscCall(DMPlexTopologyView_HDF5_Inner_Private(dm, globalPointNumbers, viewer, pStart, pEnd, pointsName, coneSizesName, conesName, orientationsName));
9262e1d0745SJose E. Roman   PetscCall(DMGetDimension(dm, &dim));
9272e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5WriteAttribute(viewer, conesName, "cell_dim", PETSC_INT, (void *)&dim));
9282e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
9292e1d0745SJose E. Roman }
9302e1d0745SJose E. Roman 
9312e1d0745SJose E. Roman //TODO get this numbering right away without needing this function
9322e1d0745SJose E. Roman /* Renumber global point numbers so that they are 0-based per stratum */
9332e1d0745SJose E. Roman static PetscErrorCode RenumberGlobalPointNumbersPerStratum_Private(DM dm, IS globalPointNumbers, IS *newGlobalPointNumbers, IS *strataPermutation)
9342e1d0745SJose E. Roman {
9352e1d0745SJose E. Roman   PetscInt        d, depth, p, n;
9362e1d0745SJose E. Roman   PetscInt       *offsets;
9372e1d0745SJose E. Roman   const PetscInt *gpn;
9382e1d0745SJose E. Roman   PetscInt       *ngpn;
9392e1d0745SJose E. Roman   MPI_Comm        comm;
9402e1d0745SJose E. Roman 
9412e1d0745SJose E. Roman   PetscFunctionBegin;
9422e1d0745SJose E. Roman   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
9432e1d0745SJose E. Roman   PetscCall(ISGetLocalSize(globalPointNumbers, &n));
9442e1d0745SJose E. Roman   PetscCall(ISGetIndices(globalPointNumbers, &gpn));
9452e1d0745SJose E. Roman   PetscCall(PetscMalloc1(n, &ngpn));
9462e1d0745SJose E. Roman   PetscCall(DMPlexGetDepth(dm, &depth));
9472e1d0745SJose E. Roman   PetscCall(PetscMalloc1(depth + 1, &offsets));
9482e1d0745SJose E. Roman   for (d = 0; d <= depth; d++) {
9492e1d0745SJose E. Roman     PetscInt pStart, pEnd;
9502e1d0745SJose E. Roman 
9512e1d0745SJose E. Roman     PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
9522e1d0745SJose E. Roman     offsets[d] = PETSC_INT_MAX;
9532e1d0745SJose E. Roman     for (p = pStart; p < pEnd; p++) {
9542e1d0745SJose E. Roman       if (gpn[p] >= 0 && gpn[p] < offsets[d]) offsets[d] = gpn[p];
9552e1d0745SJose E. Roman     }
9562e1d0745SJose E. Roman   }
9572e1d0745SJose E. Roman   PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, offsets, depth + 1, MPIU_INT, MPI_MIN, comm));
9582e1d0745SJose E. Roman   for (d = 0; d <= depth; d++) {
9592e1d0745SJose E. Roman     PetscInt pStart, pEnd;
9602e1d0745SJose E. Roman 
9612e1d0745SJose E. Roman     PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
9622e1d0745SJose E. Roman     for (p = pStart; p < pEnd; p++) ngpn[p] = gpn[p] - PetscSign(gpn[p]) * offsets[d];
9632e1d0745SJose E. Roman   }
9642e1d0745SJose E. Roman   PetscCall(ISRestoreIndices(globalPointNumbers, &gpn));
9652e1d0745SJose E. Roman   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)globalPointNumbers), n, ngpn, PETSC_OWN_POINTER, newGlobalPointNumbers));
9662e1d0745SJose E. Roman   {
9672e1d0745SJose E. Roman     PetscInt *perm;
9682e1d0745SJose E. Roman 
9692e1d0745SJose E. Roman     PetscCall(PetscMalloc1(depth + 1, &perm));
9702e1d0745SJose E. Roman     for (d = 0; d <= depth; d++) perm[d] = d;
9712e1d0745SJose E. Roman     PetscCall(PetscSortIntWithPermutation(depth + 1, offsets, perm));
9722e1d0745SJose E. Roman     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, depth + 1, perm, PETSC_OWN_POINTER, strataPermutation));
9732e1d0745SJose E. Roman   }
9742e1d0745SJose E. Roman   PetscCall(PetscFree(offsets));
9752e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
9762e1d0745SJose E. Roman }
9772e1d0745SJose E. Roman 
9782e1d0745SJose E. Roman static PetscErrorCode DMPlexTopologyView_HDF5_Private(DM dm, IS globalPointNumbers, PetscViewer viewer)
9792e1d0745SJose E. Roman {
9802e1d0745SJose E. Roman   IS          globalPointNumbers0, strataPermutation;
9812e1d0745SJose E. Roman   const char *coneSizesName, *conesName, *orientationsName;
9822e1d0745SJose E. Roman   PetscInt    depth, d;
9832e1d0745SJose E. Roman   MPI_Comm    comm;
9842e1d0745SJose E. Roman 
9852e1d0745SJose E. Roman   PetscFunctionBegin;
9862e1d0745SJose E. Roman   coneSizesName    = "cone_sizes";
9872e1d0745SJose E. Roman   conesName        = "cones";
9882e1d0745SJose E. Roman   orientationsName = "orientations";
9892e1d0745SJose E. Roman   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
9902e1d0745SJose E. Roman   PetscCall(DMPlexGetDepth(dm, &depth));
9912e1d0745SJose E. Roman   {
9922e1d0745SJose E. Roman     PetscInt dim;
9932e1d0745SJose E. Roman 
9942e1d0745SJose E. Roman     PetscCall(DMGetDimension(dm, &dim));
9952e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5WriteAttribute(viewer, NULL, "cell_dim", PETSC_INT, &dim));
9962e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5WriteAttribute(viewer, NULL, "depth", PETSC_INT, &depth));
9972e1d0745SJose E. Roman   }
9982e1d0745SJose E. Roman 
9992e1d0745SJose E. Roman   PetscCall(RenumberGlobalPointNumbersPerStratum_Private(dm, globalPointNumbers, &globalPointNumbers0, &strataPermutation));
10002e1d0745SJose E. Roman   /* TODO dirty trick to save serial IS using the same parallel viewer */
10012e1d0745SJose E. Roman   {
10022e1d0745SJose E. Roman     IS              spOnComm;
10032e1d0745SJose E. Roman     PetscInt        n   = 0, N;
10042e1d0745SJose E. Roman     const PetscInt *idx = NULL;
10052e1d0745SJose E. Roman     const PetscInt *old;
10062e1d0745SJose E. Roman     PetscMPIInt     rank;
10072e1d0745SJose E. Roman 
10082e1d0745SJose E. Roman     PetscCallMPI(MPI_Comm_rank(comm, &rank));
10092e1d0745SJose E. Roman     PetscCall(ISGetLocalSize(strataPermutation, &N));
10102e1d0745SJose E. Roman     PetscCall(ISGetIndices(strataPermutation, &old));
10112e1d0745SJose E. Roman     if (!rank) {
10122e1d0745SJose E. Roman       n   = N;
10132e1d0745SJose E. Roman       idx = old;
10142e1d0745SJose E. Roman     }
10152e1d0745SJose E. Roman     PetscCall(ISCreateGeneral(comm, n, idx, PETSC_COPY_VALUES, &spOnComm));
10162e1d0745SJose E. Roman     PetscCall(ISRestoreIndices(strataPermutation, &old));
10172e1d0745SJose E. Roman     PetscCall(ISDestroy(&strataPermutation));
10182e1d0745SJose E. Roman     strataPermutation = spOnComm;
10192e1d0745SJose E. Roman   }
10202e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)strataPermutation, "permutation"));
10212e1d0745SJose E. Roman   PetscCall(ISView(strataPermutation, viewer));
10222e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "strata"));
10232e1d0745SJose E. Roman   for (d = 0; d <= depth; d++) {
10242e1d0745SJose E. Roman     PetscInt pStart, pEnd;
10252e1d0745SJose E. Roman     char     group[128];
10262e1d0745SJose E. Roman 
10272e1d0745SJose E. Roman     PetscCall(PetscSNPrintf(group, sizeof(group), "%" PetscInt_FMT, d));
10282e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5PushGroup(viewer, group));
10292e1d0745SJose E. Roman     PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
10302e1d0745SJose E. Roman     PetscCall(DMPlexTopologyView_HDF5_Inner_Private(dm, globalPointNumbers0, viewer, pStart, pEnd, NULL, coneSizesName, conesName, orientationsName));
10312e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5PopGroup(viewer));
10322e1d0745SJose E. Roman   }
10332e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer)); /* strata */
10342e1d0745SJose E. Roman   PetscCall(ISDestroy(&globalPointNumbers0));
10352e1d0745SJose E. Roman   PetscCall(ISDestroy(&strataPermutation));
10362e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
10372e1d0745SJose E. Roman }
10382e1d0745SJose E. Roman 
10392e1d0745SJose E. Roman PetscErrorCode DMPlexTopologyView_HDF5_Internal(DM dm, IS globalPointNumbers, PetscViewer viewer)
10402e1d0745SJose E. Roman {
10412e1d0745SJose E. Roman   DMPlexStorageVersion version;
10422e1d0745SJose E. Roman   const char          *topologydm_name;
10432e1d0745SJose E. Roman   char                 group[PETSC_MAX_PATH_LEN];
10442e1d0745SJose E. Roman 
10452e1d0745SJose E. Roman   PetscFunctionBegin;
10462e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5GetDMPlexStorageVersionWriting(viewer, &version));
10472e1d0745SJose E. Roman   PetscCall(PetscInfo(dm, "Writing DM %s storage version %d.%d.%d\n", dm->hdr.name, version->major, version->minor, version->subminor));
10482e1d0745SJose E. Roman   PetscCall(DMPlexGetHDF5Name_Private(dm, &topologydm_name));
10492e1d0745SJose E. Roman   if (DMPlexStorageVersionGE(version, 2, 0, 0)) {
10502e1d0745SJose E. Roman     PetscCall(PetscSNPrintf(group, sizeof(group), "topologies/%s", topologydm_name));
10512e1d0745SJose E. Roman   } else {
10522e1d0745SJose E. Roman     PetscCall(PetscStrncpy(group, "/", sizeof(group)));
10532e1d0745SJose E. Roman   }
10542e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, group));
10552e1d0745SJose E. Roman 
10562e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "topology"));
10572e1d0745SJose E. Roman   if (version->major < 3) {
10582e1d0745SJose E. Roman     PetscCall(DMPlexTopologyView_HDF5_Legacy_Private(dm, globalPointNumbers, viewer));
10592e1d0745SJose E. Roman   } else {
10602e1d0745SJose E. Roman     /* since DMPlexStorageVersion 3.0.0 */
10612e1d0745SJose E. Roman     PetscCall(DMPlexTopologyView_HDF5_Private(dm, globalPointNumbers, viewer));
10622e1d0745SJose E. Roman   }
10632e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer)); /* "topology" */
10642e1d0745SJose E. Roman 
10652e1d0745SJose E. Roman   if (DMPlexStorageVersionGE(version, 2, 1, 0)) {
10662e1d0745SJose E. Roman     const char *distribution_name;
10672e1d0745SJose E. Roman 
10682e1d0745SJose E. Roman     PetscCall(DMPlexDistributionGetName(dm, &distribution_name));
10692e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5PushGroup(viewer, "distributions"));
10702e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5WriteGroup(viewer, NULL));
10712e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5PushGroup(viewer, distribution_name));
10722e1d0745SJose E. Roman     PetscCall(DMPlexDistributionView_HDF5_Private(dm, globalPointNumbers, viewer));
10732e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5PopGroup(viewer)); /* distribution_name */
10742e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5PopGroup(viewer)); /* "distributions" */
10752e1d0745SJose E. Roman   }
10762e1d0745SJose E. Roman 
10772e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
10782e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
10792e1d0745SJose E. Roman }
10802e1d0745SJose E. Roman 
10812e1d0745SJose E. Roman static PetscErrorCode CreateConesIS_Private(DM dm, PetscInt cStart, PetscInt cEnd, IS globalCellNumbers, PetscInt *numCorners, IS *cellIS)
10822e1d0745SJose E. Roman {
10832e1d0745SJose E. Roman   PetscSF         sfPoint;
10842e1d0745SJose E. Roman   DMLabel         cutLabel, cutVertexLabel         = NULL;
10852e1d0745SJose E. Roman   IS              globalVertexNumbers, cutvertices = NULL;
10862e1d0745SJose E. Roman   const PetscInt *gcell, *gvertex, *cutverts = NULL;
10872e1d0745SJose E. Roman   PetscInt       *vertices;
10882e1d0745SJose E. Roman   PetscInt        conesSize = 0;
10892e1d0745SJose E. Roman   PetscInt        dim, numCornersLocal = 0, cell, vStart, vEnd, vExtra = 0, v;
10902e1d0745SJose E. Roman 
10912e1d0745SJose E. Roman   PetscFunctionBegin;
10922e1d0745SJose E. Roman   *numCorners = 0;
10932e1d0745SJose E. Roman   PetscCall(DMGetDimension(dm, &dim));
10942e1d0745SJose E. Roman   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
10952e1d0745SJose E. Roman   PetscCall(ISGetIndices(globalCellNumbers, &gcell));
10962e1d0745SJose E. Roman 
10972e1d0745SJose E. Roman   for (cell = cStart; cell < cEnd; ++cell) {
10982e1d0745SJose E. Roman     PetscInt *closure = NULL;
10992e1d0745SJose E. Roman     PetscInt  closureSize, v, Nc = 0;
11002e1d0745SJose E. Roman 
11012e1d0745SJose E. Roman     if (gcell[cell] < 0) continue;
11022e1d0745SJose E. Roman     PetscCall(DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure));
11032e1d0745SJose E. Roman     for (v = 0; v < closureSize * 2; v += 2) {
11042e1d0745SJose E. Roman       if ((closure[v] >= vStart) && (closure[v] < vEnd)) ++Nc;
11052e1d0745SJose E. Roman     }
11062e1d0745SJose E. Roman     PetscCall(DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure));
11072e1d0745SJose E. Roman     conesSize += Nc;
11082e1d0745SJose E. Roman     if (!numCornersLocal) numCornersLocal = Nc;
11092e1d0745SJose E. Roman     else if (numCornersLocal != Nc) numCornersLocal = 1;
11102e1d0745SJose E. Roman   }
11112e1d0745SJose E. Roman   PetscCallMPI(MPIU_Allreduce(&numCornersLocal, numCorners, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
11122e1d0745SJose E. Roman   PetscCheck(!numCornersLocal || !(numCornersLocal != *numCorners || *numCorners == 0), PETSC_COMM_SELF, PETSC_ERR_SUP, "Visualization topology currently only supports identical cell shapes");
11132e1d0745SJose E. Roman   /* Handle periodic cuts by identifying vertices which should be duplicated */
11142e1d0745SJose E. Roman   PetscCall(DMGetLabel(dm, "periodic_cut", &cutLabel));
11152e1d0745SJose E. Roman   PetscCall(DMPlexCreateCutVertexLabel_Private(dm, cutLabel, &cutVertexLabel));
11162e1d0745SJose E. Roman   if (cutVertexLabel) PetscCall(DMLabelGetStratumIS(cutVertexLabel, 1, &cutvertices));
11172e1d0745SJose E. Roman   if (cutvertices) {
11182e1d0745SJose E. Roman     PetscCall(ISGetIndices(cutvertices, &cutverts));
11192e1d0745SJose E. Roman     PetscCall(ISGetLocalSize(cutvertices, &vExtra));
11202e1d0745SJose E. Roman   }
11212e1d0745SJose E. Roman   PetscCall(DMGetPointSF(dm, &sfPoint));
11222e1d0745SJose E. Roman   if (cutLabel) {
11232e1d0745SJose E. Roman     const PetscInt    *ilocal;
11242e1d0745SJose E. Roman     const PetscSFNode *iremote;
11252e1d0745SJose E. Roman     PetscInt           nroots, nleaves;
11262e1d0745SJose E. Roman 
11272e1d0745SJose E. Roman     PetscCall(PetscSFGetGraph(sfPoint, &nroots, &nleaves, &ilocal, &iremote));
11282e1d0745SJose E. Roman     if (nleaves < 0) {
11292e1d0745SJose E. Roman       PetscCall(PetscObjectReference((PetscObject)sfPoint));
11302e1d0745SJose E. Roman     } else {
11312e1d0745SJose E. Roman       PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)sfPoint), &sfPoint));
11322e1d0745SJose E. Roman       PetscCall(PetscSFSetGraph(sfPoint, nroots + vExtra, nleaves, (PetscInt *)ilocal, PETSC_COPY_VALUES, (PetscSFNode *)iremote, PETSC_COPY_VALUES));
11332e1d0745SJose E. Roman     }
11342e1d0745SJose E. Roman   } else {
11352e1d0745SJose E. Roman     PetscCall(PetscObjectReference((PetscObject)sfPoint));
11362e1d0745SJose E. Roman   }
11372e1d0745SJose E. Roman   /* Number all vertices */
11382e1d0745SJose E. Roman   PetscCall(DMPlexCreateNumbering_Plex(dm, vStart, vEnd + vExtra, 0, NULL, sfPoint, &globalVertexNumbers));
11392e1d0745SJose E. Roman   PetscCall(PetscSFDestroy(&sfPoint));
11402e1d0745SJose E. Roman   /* Create cones */
11412e1d0745SJose E. Roman   PetscCall(ISGetIndices(globalVertexNumbers, &gvertex));
11422e1d0745SJose E. Roman   PetscCall(PetscMalloc1(conesSize, &vertices));
11432e1d0745SJose E. Roman   for (cell = cStart, v = 0; cell < cEnd; ++cell) {
11442e1d0745SJose E. Roman     PetscInt *closure = NULL;
11452e1d0745SJose E. Roman     PetscInt  closureSize, Nc = 0, p, value = -1;
11462e1d0745SJose E. Roman     PetscBool replace;
11472e1d0745SJose E. Roman 
11482e1d0745SJose E. Roman     if (gcell[cell] < 0) continue;
11492e1d0745SJose E. Roman     if (cutLabel) PetscCall(DMLabelGetValue(cutLabel, cell, &value));
11502e1d0745SJose E. Roman     replace = (value == 2) ? PETSC_TRUE : PETSC_FALSE;
11512e1d0745SJose E. Roman     PetscCall(DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure));
11522e1d0745SJose E. Roman     for (p = 0; p < closureSize * 2; p += 2) {
11532e1d0745SJose E. Roman       if ((closure[p] >= vStart) && (closure[p] < vEnd)) closure[Nc++] = closure[p];
11542e1d0745SJose E. Roman     }
11552e1d0745SJose E. Roman     PetscCall(DMPlexReorderCell(dm, cell, closure));
11562e1d0745SJose E. Roman     for (p = 0; p < Nc; ++p) {
11572e1d0745SJose E. Roman       PetscInt nv, gv = gvertex[closure[p] - vStart];
11582e1d0745SJose E. Roman 
11592e1d0745SJose E. Roman       if (replace) {
11602e1d0745SJose E. Roman         PetscCall(PetscFindInt(closure[p], vExtra, cutverts, &nv));
11612e1d0745SJose E. Roman         if (nv >= 0) gv = gvertex[vEnd - vStart + nv];
11622e1d0745SJose E. Roman       }
11632e1d0745SJose E. Roman       vertices[v++] = gv < 0 ? -(gv + 1) : gv;
11642e1d0745SJose E. Roman     }
11652e1d0745SJose E. Roman     PetscCall(DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure));
11662e1d0745SJose E. Roman   }
11672e1d0745SJose E. Roman   PetscCall(ISRestoreIndices(globalVertexNumbers, &gvertex));
11682e1d0745SJose E. Roman   PetscCall(ISDestroy(&globalVertexNumbers));
11692e1d0745SJose E. Roman   PetscCall(ISRestoreIndices(globalCellNumbers, &gcell));
11702e1d0745SJose E. Roman   if (cutvertices) PetscCall(ISRestoreIndices(cutvertices, &cutverts));
11712e1d0745SJose E. Roman   PetscCall(ISDestroy(&cutvertices));
11722e1d0745SJose E. Roman   PetscCall(DMLabelDestroy(&cutVertexLabel));
11732e1d0745SJose E. Roman   PetscCheck(v == conesSize, PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of cell vertices %" PetscInt_FMT " != %" PetscInt_FMT, v, conesSize);
11742e1d0745SJose E. Roman   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), conesSize, vertices, PETSC_OWN_POINTER, cellIS));
11752e1d0745SJose E. Roman   PetscCall(PetscLayoutSetBlockSize((*cellIS)->map, *numCorners));
11762e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)*cellIS, "cells"));
11772e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
11782e1d0745SJose E. Roman }
11792e1d0745SJose E. Roman 
11802e1d0745SJose E. Roman static PetscErrorCode DMPlexTopologyView_HDF5_XDMF_Private(DM dm, IS globalCellNumbers, PetscViewer viewer)
11812e1d0745SJose E. Roman {
11822e1d0745SJose E. Roman   DM       cdm;
11832e1d0745SJose E. Roman   DMLabel  depthLabel, ctLabel;
11842e1d0745SJose E. Roman   IS       cellIS;
11852e1d0745SJose E. Roman   PetscInt dim, depth, cellHeight, c, n = 0;
11862e1d0745SJose E. Roman 
11872e1d0745SJose E. Roman   PetscFunctionBegin;
11882e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "/viz"));
11892e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5WriteGroup(viewer, NULL));
11902e1d0745SJose E. Roman 
11912e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
11922e1d0745SJose E. Roman   PetscCall(DMGetDimension(dm, &dim));
11932e1d0745SJose E. Roman   PetscCall(DMPlexGetDepth(dm, &depth));
11942e1d0745SJose E. Roman   PetscCall(DMGetCoordinateDM(dm, &cdm));
11952e1d0745SJose E. Roman   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
11962e1d0745SJose E. Roman   PetscCall(DMPlexGetDepthLabel(dm, &depthLabel));
11972e1d0745SJose E. Roman   PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel));
11982e1d0745SJose E. Roman   for (c = 0; c < DM_NUM_POLYTOPES; ++c) {
11992e1d0745SJose E. Roman     const DMPolytopeType ict = (DMPolytopeType)c;
12002e1d0745SJose E. Roman     PetscInt             pStart, pEnd, dep, numCorners;
12012e1d0745SJose E. Roman     PetscBool            output = PETSC_FALSE, doOutput;
12022e1d0745SJose E. Roman 
12032e1d0745SJose E. Roman     if (ict == DM_POLYTOPE_FV_GHOST) continue;
12042e1d0745SJose E. Roman     PetscCall(DMLabelGetStratumBounds(ctLabel, ict, &pStart, &pEnd));
12052e1d0745SJose E. Roman     if (pStart >= 0) {
12062e1d0745SJose E. Roman       PetscCall(DMLabelGetValue(depthLabel, pStart, &dep));
12072e1d0745SJose E. Roman       if (dep == depth - cellHeight) output = PETSC_TRUE;
12082e1d0745SJose E. Roman     }
12092e1d0745SJose E. Roman     PetscCallMPI(MPIU_Allreduce(&output, &doOutput, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)dm)));
12102e1d0745SJose E. Roman     if (!doOutput) continue;
12112e1d0745SJose E. Roman     PetscCall(CreateConesIS_Private(dm, pStart, pEnd, globalCellNumbers, &numCorners, &cellIS));
12122e1d0745SJose E. Roman     if (!n) {
12132e1d0745SJose E. Roman       PetscCall(PetscViewerHDF5PushGroup(viewer, "/viz/topology"));
12142e1d0745SJose E. Roman     } else {
12152e1d0745SJose E. Roman       char group[PETSC_MAX_PATH_LEN];
12162e1d0745SJose E. Roman 
12172e1d0745SJose E. Roman       PetscCall(PetscSNPrintf(group, PETSC_MAX_PATH_LEN, "/viz/topology_%" PetscInt_FMT, n));
12182e1d0745SJose E. Roman       PetscCall(PetscViewerHDF5PushGroup(viewer, group));
12192e1d0745SJose E. Roman     }
12202e1d0745SJose E. Roman     PetscCall(ISView(cellIS, viewer));
12212e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5WriteObjectAttribute(viewer, (PetscObject)cellIS, "cell_corners", PETSC_INT, (void *)&numCorners));
12222e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5WriteObjectAttribute(viewer, (PetscObject)cellIS, "cell_dim", PETSC_INT, (void *)&dim));
12232e1d0745SJose E. Roman     PetscCall(ISDestroy(&cellIS));
12242e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5PopGroup(viewer));
12252e1d0745SJose E. Roman     ++n;
12262e1d0745SJose E. Roman   }
12272e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
12282e1d0745SJose E. Roman }
12292e1d0745SJose E. Roman 
12302e1d0745SJose E. Roman static PetscErrorCode DMPlexCoordinatesView_HDF5_Legacy_Private(DM dm, PetscViewer viewer)
12312e1d0745SJose E. Roman {
12322e1d0745SJose E. Roman   DM        cdm;
12332e1d0745SJose E. Roman   Vec       coordinates, newcoords;
12342e1d0745SJose E. Roman   PetscReal lengthScale;
12352e1d0745SJose E. Roman   PetscInt  m, M, bs;
12362e1d0745SJose E. Roman 
12372e1d0745SJose E. Roman   PetscFunctionBegin;
12382e1d0745SJose E. Roman   PetscCall(DMPlexGetScale(dm, PETSC_UNIT_LENGTH, &lengthScale));
12392e1d0745SJose E. Roman   PetscCall(DMGetCoordinateDM(dm, &cdm));
12402e1d0745SJose E. Roman   PetscCall(DMGetCoordinates(dm, &coordinates));
12412e1d0745SJose E. Roman   PetscCall(VecCreate(PetscObjectComm((PetscObject)coordinates), &newcoords));
12422e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)newcoords, "vertices"));
12432e1d0745SJose E. Roman   PetscCall(VecGetSize(coordinates, &M));
12442e1d0745SJose E. Roman   PetscCall(VecGetLocalSize(coordinates, &m));
12452e1d0745SJose E. Roman   PetscCall(VecSetSizes(newcoords, m, M));
12462e1d0745SJose E. Roman   PetscCall(VecGetBlockSize(coordinates, &bs));
12472e1d0745SJose E. Roman   PetscCall(VecSetBlockSize(newcoords, bs));
12482e1d0745SJose E. Roman   PetscCall(VecSetType(newcoords, VECSTANDARD));
12492e1d0745SJose E. Roman   PetscCall(VecCopy(coordinates, newcoords));
12502e1d0745SJose E. Roman   PetscCall(VecScale(newcoords, lengthScale));
12512e1d0745SJose E. Roman   /* Did not use DMGetGlobalVector() in order to bypass default group assignment */
12522e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "/geometry"));
12532e1d0745SJose E. Roman   PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_NATIVE));
12542e1d0745SJose E. Roman   PetscCall(VecView(newcoords, viewer));
12552e1d0745SJose E. Roman   PetscCall(PetscViewerPopFormat(viewer));
12562e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
12572e1d0745SJose E. Roman   PetscCall(VecDestroy(&newcoords));
12582e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
12592e1d0745SJose E. Roman }
12602e1d0745SJose E. Roman 
12612e1d0745SJose E. Roman PetscErrorCode DMPlexCoordinatesView_HDF5_Internal(DM dm, PetscViewer viewer)
12622e1d0745SJose E. Roman {
12632e1d0745SJose E. Roman   DM                   cdm;
12642e1d0745SJose E. Roman   Vec                  coords, newcoords;
12652e1d0745SJose E. Roman   PetscInt             m, M, bs;
12662e1d0745SJose E. Roman   PetscReal            lengthScale;
1267*ea87367fSMatthew G. Knepley   PetscBool            viewSection = PETSC_TRUE, ocompress;
12682e1d0745SJose E. Roman   const char          *topologydm_name, *coordinatedm_name, *coordinates_name;
12692e1d0745SJose E. Roman   PetscViewerFormat    format;
12702e1d0745SJose E. Roman   DMPlexStorageVersion version;
12712e1d0745SJose E. Roman 
1272*ea87367fSMatthew G. Knepley   PetscFunctionBegin;
12732e1d0745SJose E. Roman   PetscCall(PetscViewerGetFormat(viewer, &format));
12742e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5GetDMPlexStorageVersionWriting(viewer, &version));
12752e1d0745SJose E. Roman   if (!DMPlexStorageVersionGE(version, 2, 0, 0) || format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) {
12762e1d0745SJose E. Roman     PetscCall(DMPlexCoordinatesView_HDF5_Legacy_Private(dm, viewer));
12772e1d0745SJose E. Roman     PetscFunctionReturn(PETSC_SUCCESS);
12782e1d0745SJose E. Roman   }
12792e1d0745SJose E. Roman   /* since 2.0.0 */
1280*ea87367fSMatthew G. Knepley   if (DMPlexStorageVersionGE(version, 3, 1, 0)) {
1281*ea87367fSMatthew G. Knepley     PetscCall(PetscViewerHDF5GetCompress(viewer, &ocompress));
1282*ea87367fSMatthew G. Knepley     PetscCall(PetscViewerHDF5SetCompress(viewer, PETSC_TRUE));
1283*ea87367fSMatthew G. Knepley   }
12842e1d0745SJose E. Roman   PetscCall(PetscOptionsGetBool(NULL, dm->hdr.prefix, "-dm_plex_view_coordinate_section", &viewSection, NULL));
12852e1d0745SJose E. Roman   PetscCall(DMGetCoordinateDM(dm, &cdm));
12862e1d0745SJose E. Roman   PetscCall(DMGetCoordinates(dm, &coords));
12872e1d0745SJose E. Roman   PetscCall(PetscObjectGetName((PetscObject)cdm, &coordinatedm_name));
12882e1d0745SJose E. Roman   PetscCall(PetscObjectGetName((PetscObject)coords, &coordinates_name));
12892e1d0745SJose E. Roman   PetscCall(DMPlexGetHDF5Name_Private(dm, &topologydm_name));
12902e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "topologies"));
12912e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, topologydm_name));
12922e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5WriteAttribute(viewer, NULL, "coordinateDMName", PETSC_STRING, coordinatedm_name));
12932e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5WriteAttribute(viewer, NULL, "coordinatesName", PETSC_STRING, coordinates_name));
12942e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
12952e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
12962e1d0745SJose E. Roman   if (viewSection) PetscCall(DMPlexSectionView(dm, viewer, cdm));
12972e1d0745SJose E. Roman   PetscCall(VecCreate(PetscObjectComm((PetscObject)coords), &newcoords));
12982e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)newcoords, coordinates_name));
12992e1d0745SJose E. Roman   PetscCall(VecGetSize(coords, &M));
13002e1d0745SJose E. Roman   PetscCall(VecGetLocalSize(coords, &m));
13012e1d0745SJose E. Roman   PetscCall(VecSetSizes(newcoords, m, M));
13022e1d0745SJose E. Roman   PetscCall(VecGetBlockSize(coords, &bs));
13032e1d0745SJose E. Roman   PetscCall(VecSetBlockSize(newcoords, bs));
13042e1d0745SJose E. Roman   PetscCall(VecSetType(newcoords, VECSTANDARD));
13052e1d0745SJose E. Roman   PetscCall(VecCopy(coords, newcoords));
13062e1d0745SJose E. Roman   PetscCall(DMPlexGetScale(dm, PETSC_UNIT_LENGTH, &lengthScale));
13072e1d0745SJose E. Roman   PetscCall(VecScale(newcoords, lengthScale));
13082e1d0745SJose E. Roman   PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_NATIVE));
13092e1d0745SJose E. Roman   PetscCall(DMPlexGlobalVectorView(dm, viewer, cdm, newcoords));
13102e1d0745SJose E. Roman   PetscCall(PetscViewerPopFormat(viewer));
13112e1d0745SJose E. Roman   PetscCall(VecDestroy(&newcoords));
1312*ea87367fSMatthew G. Knepley   if (DMPlexStorageVersionGE(version, 3, 1, 0)) PetscCall(PetscViewerHDF5SetCompress(viewer, ocompress));
13132e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
13142e1d0745SJose E. Roman }
13152e1d0745SJose E. Roman 
13162e1d0745SJose E. Roman static PetscErrorCode DMPlexCoordinatesView_HDF5_XDMF_Private(DM dm, PetscViewer viewer)
13172e1d0745SJose E. Roman {
13182e1d0745SJose E. Roman   DM               cdm;
13192e1d0745SJose E. Roman   Vec              coordinatesLocal, newcoords;
13202e1d0745SJose E. Roman   PetscSection     cSection, cGlobalSection;
13212e1d0745SJose E. Roman   PetscScalar     *coords, *ncoords;
13222e1d0745SJose E. Roman   DMLabel          cutLabel, cutVertexLabel = NULL;
13232e1d0745SJose E. Roman   const PetscReal *L;
13242e1d0745SJose E. Roman   PetscReal        lengthScale;
13252e1d0745SJose E. Roman   PetscInt         vStart, vEnd, v, bs, N, coordSize, dof, off, d;
13262e1d0745SJose E. Roman   PetscBool        localized, embedded;
13272e1d0745SJose E. Roman 
13282e1d0745SJose E. Roman   PetscFunctionBegin;
13292e1d0745SJose E. Roman   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
13302e1d0745SJose E. Roman   PetscCall(DMPlexGetScale(dm, PETSC_UNIT_LENGTH, &lengthScale));
13312e1d0745SJose E. Roman   PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal));
13322e1d0745SJose E. Roman   PetscCall(VecGetBlockSize(coordinatesLocal, &bs));
13332e1d0745SJose E. Roman   PetscCall(DMGetCoordinatesLocalized(dm, &localized));
13342e1d0745SJose E. Roman   if (localized == PETSC_FALSE) PetscFunctionReturn(PETSC_SUCCESS);
13352e1d0745SJose E. Roman   PetscCall(DMGetPeriodicity(dm, NULL, NULL, &L));
13362e1d0745SJose E. Roman   PetscCall(DMGetCoordinateDM(dm, &cdm));
13372e1d0745SJose E. Roman   PetscCall(DMGetLocalSection(cdm, &cSection));
13382e1d0745SJose E. Roman   PetscCall(DMGetGlobalSection(cdm, &cGlobalSection));
13392e1d0745SJose E. Roman   PetscCall(DMGetLabel(dm, "periodic_cut", &cutLabel));
13402e1d0745SJose E. Roman   N = 0;
13412e1d0745SJose E. Roman 
13422e1d0745SJose E. Roman   PetscCall(DMPlexCreateCutVertexLabel_Private(dm, cutLabel, &cutVertexLabel));
13432e1d0745SJose E. Roman   PetscCall(VecCreate(PetscObjectComm((PetscObject)dm), &newcoords));
13442e1d0745SJose E. Roman   PetscCall(PetscSectionGetDof(cSection, vStart, &dof));
13452e1d0745SJose E. Roman   PetscCall(PetscPrintf(PETSC_COMM_SELF, "DOF: %" PetscInt_FMT "\n", dof));
13462e1d0745SJose E. Roman   embedded = (PetscBool)(L && dof == 2 && !cutLabel);
13472e1d0745SJose E. Roman   if (cutVertexLabel) {
13482e1d0745SJose E. Roman     PetscCall(DMLabelGetStratumSize(cutVertexLabel, 1, &v));
13492e1d0745SJose E. Roman     N += dof * v;
13502e1d0745SJose E. Roman   }
13512e1d0745SJose E. Roman   for (v = vStart; v < vEnd; ++v) {
13522e1d0745SJose E. Roman     PetscCall(PetscSectionGetDof(cGlobalSection, v, &dof));
13532e1d0745SJose E. Roman     if (dof < 0) continue;
13542e1d0745SJose E. Roman     if (embedded) N += dof + 1;
13552e1d0745SJose E. Roman     else N += dof;
13562e1d0745SJose E. Roman   }
13572e1d0745SJose E. Roman   if (embedded) PetscCall(VecSetBlockSize(newcoords, bs + 1));
13582e1d0745SJose E. Roman   else PetscCall(VecSetBlockSize(newcoords, bs));
13592e1d0745SJose E. Roman   PetscCall(VecSetSizes(newcoords, N, PETSC_DETERMINE));
13602e1d0745SJose E. Roman   PetscCall(VecSetType(newcoords, VECSTANDARD));
13612e1d0745SJose E. Roman   PetscCall(VecGetArray(coordinatesLocal, &coords));
13622e1d0745SJose E. Roman   PetscCall(VecGetArray(newcoords, &ncoords));
13632e1d0745SJose E. Roman   coordSize = 0;
13642e1d0745SJose E. Roman   for (v = vStart; v < vEnd; ++v) {
13652e1d0745SJose E. Roman     PetscCall(PetscSectionGetDof(cGlobalSection, v, &dof));
13662e1d0745SJose E. Roman     PetscCall(PetscSectionGetOffset(cSection, v, &off));
13672e1d0745SJose E. Roman     if (dof < 0) continue;
13682e1d0745SJose E. Roman     if (embedded) {
13692e1d0745SJose E. Roman       if (L && (L[0] > 0.0) && (L[1] > 0.0)) {
13702e1d0745SJose E. Roman         PetscReal theta, phi, r, R;
13712e1d0745SJose E. Roman         /* XY-periodic */
13722e1d0745SJose E. Roman         /* Suppose its an y-z circle, then
13732e1d0745SJose E. Roman              \hat r = (0, cos(th), sin(th)) \hat x = (1, 0, 0)
13742e1d0745SJose E. Roman            and the circle in that plane is
13752e1d0745SJose E. Roman              \hat r cos(phi) + \hat x sin(phi) */
13762e1d0745SJose E. Roman         theta                = 2.0 * PETSC_PI * PetscRealPart(coords[off + 1]) / L[1];
13772e1d0745SJose E. Roman         phi                  = 2.0 * PETSC_PI * PetscRealPart(coords[off + 0]) / L[0];
13782e1d0745SJose E. Roman         r                    = L[0] / (2.0 * PETSC_PI * 2.0 * L[1]);
13792e1d0745SJose E. Roman         R                    = L[1] / (2.0 * PETSC_PI);
13802e1d0745SJose E. Roman         ncoords[coordSize++] = PetscSinReal(phi) * r;
13812e1d0745SJose E. Roman         ncoords[coordSize++] = -PetscCosReal(theta) * (R + r * PetscCosReal(phi));
13822e1d0745SJose E. Roman         ncoords[coordSize++] = PetscSinReal(theta) * (R + r * PetscCosReal(phi));
13832e1d0745SJose E. Roman       } else if (L && (L[0] > 0.0)) {
13842e1d0745SJose E. Roman         /* X-periodic */
13852e1d0745SJose E. Roman         ncoords[coordSize++] = -PetscCosReal(2.0 * PETSC_PI * PetscRealPart(coords[off + 0]) / L[0]) * (L[0] / (2.0 * PETSC_PI));
13862e1d0745SJose E. Roman         ncoords[coordSize++] = coords[off + 1];
13872e1d0745SJose E. Roman         ncoords[coordSize++] = PetscSinReal(2.0 * PETSC_PI * PetscRealPart(coords[off + 0]) / L[0]) * (L[0] / (2.0 * PETSC_PI));
13882e1d0745SJose E. Roman       } else if (L && (L[1] > 0.0)) {
13892e1d0745SJose E. Roman         /* Y-periodic */
13902e1d0745SJose E. Roman         ncoords[coordSize++] = coords[off + 0];
13912e1d0745SJose E. Roman         ncoords[coordSize++] = PetscSinReal(2.0 * PETSC_PI * PetscRealPart(coords[off + 1]) / L[1]) * (L[1] / (2.0 * PETSC_PI));
13922e1d0745SJose E. Roman         ncoords[coordSize++] = -PetscCosReal(2.0 * PETSC_PI * PetscRealPart(coords[off + 1]) / L[1]) * (L[1] / (2.0 * PETSC_PI));
13932e1d0745SJose E. Roman #if 0
13942e1d0745SJose E. Roman       } else if ((bd[0] == DM_BOUNDARY_TWIST)) {
13952e1d0745SJose E. Roman         PetscReal phi, r, R;
13962e1d0745SJose E. Roman         /* Mobius strip */
13972e1d0745SJose E. Roman         /* Suppose its an x-z circle, then
13982e1d0745SJose E. Roman              \hat r = (-cos(phi), 0, sin(phi)) \hat y = (0, 1, 0)
13992e1d0745SJose E. Roman            and in that plane we rotate by pi as we go around the circle
14002e1d0745SJose E. Roman              \hat r cos(phi/2) + \hat y sin(phi/2) */
14012e1d0745SJose E. Roman         phi   = 2.0*PETSC_PI*PetscRealPart(coords[off+0])/L[0];
14022e1d0745SJose E. Roman         R     = L[0];
14032e1d0745SJose E. Roman         r     = PetscRealPart(coords[off+1]) - L[1]/2.0;
14042e1d0745SJose E. Roman         ncoords[coordSize++] = -PetscCosReal(phi) * (R + r * PetscCosReal(phi/2.0));
14052e1d0745SJose E. Roman         ncoords[coordSize++] =  PetscSinReal(phi/2.0) * r;
14062e1d0745SJose E. Roman         ncoords[coordSize++] =  PetscSinReal(phi) * (R + r * PetscCosReal(phi/2.0));
14072e1d0745SJose E. Roman #endif
14082e1d0745SJose E. Roman       } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Cannot handle periodicity in this domain");
14092e1d0745SJose E. Roman     } else {
14102e1d0745SJose E. Roman       for (d = 0; d < dof; ++d, ++coordSize) ncoords[coordSize] = coords[off + d];
14112e1d0745SJose E. Roman     }
14122e1d0745SJose E. Roman   }
14132e1d0745SJose E. Roman   if (cutVertexLabel) {
14142e1d0745SJose E. Roman     IS              vertices;
14152e1d0745SJose E. Roman     const PetscInt *verts;
14162e1d0745SJose E. Roman     PetscInt        n;
14172e1d0745SJose E. Roman 
14182e1d0745SJose E. Roman     PetscCall(DMLabelGetStratumIS(cutVertexLabel, 1, &vertices));
14192e1d0745SJose E. Roman     if (vertices) {
14202e1d0745SJose E. Roman       PetscCall(ISGetIndices(vertices, &verts));
14212e1d0745SJose E. Roman       PetscCall(ISGetLocalSize(vertices, &n));
14222e1d0745SJose E. Roman       for (v = 0; v < n; ++v) {
14232e1d0745SJose E. Roman         PetscCall(PetscSectionGetDof(cSection, verts[v], &dof));
14242e1d0745SJose E. Roman         PetscCall(PetscSectionGetOffset(cSection, verts[v], &off));
14252e1d0745SJose E. Roman         for (d = 0; d < dof; ++d) ncoords[coordSize++] = coords[off + d] + ((L[d] > 0.) ? L[d] : 0.0);
14262e1d0745SJose E. Roman       }
14272e1d0745SJose E. Roman       PetscCall(ISRestoreIndices(vertices, &verts));
14282e1d0745SJose E. Roman       PetscCall(ISDestroy(&vertices));
14292e1d0745SJose E. Roman     }
14302e1d0745SJose E. Roman   }
14312e1d0745SJose E. Roman   PetscCheck(coordSize == N, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched sizes: %" PetscInt_FMT " != %" PetscInt_FMT, coordSize, N);
14322e1d0745SJose E. Roman   PetscCall(DMLabelDestroy(&cutVertexLabel));
14332e1d0745SJose E. Roman   PetscCall(VecRestoreArray(coordinatesLocal, &coords));
14342e1d0745SJose E. Roman   PetscCall(VecRestoreArray(newcoords, &ncoords));
14352e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)newcoords, "vertices"));
14362e1d0745SJose E. Roman   PetscCall(VecScale(newcoords, lengthScale));
14372e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "/viz"));
14382e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5WriteGroup(viewer, NULL));
14392e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
14402e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "/viz/geometry"));
14412e1d0745SJose E. Roman   PetscCall(VecView(newcoords, viewer));
14422e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
14432e1d0745SJose E. Roman   PetscCall(VecDestroy(&newcoords));
14442e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
14452e1d0745SJose E. Roman }
14462e1d0745SJose E. Roman 
14472e1d0745SJose E. Roman PetscErrorCode DMPlexLabelsView_HDF5_Internal(DM dm, IS globalPointNumbers, PetscViewer viewer)
14482e1d0745SJose E. Roman {
14492e1d0745SJose E. Roman   const char          *topologydm_name;
14502e1d0745SJose E. Roman   const PetscInt      *gpoint;
14512e1d0745SJose E. Roman   PetscInt             numLabels;
1452*ea87367fSMatthew G. Knepley   PetscBool            omitCelltypes = PETSC_FALSE, ocompress;
14532e1d0745SJose E. Roman   DMPlexStorageVersion version;
14542e1d0745SJose E. Roman   char                 group[PETSC_MAX_PATH_LEN];
14552e1d0745SJose E. Roman 
14562e1d0745SJose E. Roman   PetscFunctionBegin;
14572e1d0745SJose E. Roman   PetscCall(PetscOptionsGetBool(NULL, dm->hdr.prefix, "-dm_plex_omit_celltypes", &omitCelltypes, NULL));
14582e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5GetDMPlexStorageVersionWriting(viewer, &version));
1459*ea87367fSMatthew G. Knepley   if (DMPlexStorageVersionGE(version, 3, 1, 0)) {
1460*ea87367fSMatthew G. Knepley     PetscCall(PetscViewerHDF5GetCompress(viewer, &ocompress));
1461*ea87367fSMatthew G. Knepley     PetscCall(PetscViewerHDF5SetCompress(viewer, PETSC_TRUE));
1462*ea87367fSMatthew G. Knepley   }
14632e1d0745SJose E. Roman   PetscCall(ISGetIndices(globalPointNumbers, &gpoint));
14642e1d0745SJose E. Roman   PetscCall(DMPlexGetHDF5Name_Private(dm, &topologydm_name));
14652e1d0745SJose E. Roman   if (DMPlexStorageVersionGE(version, 2, 0, 0)) {
14662e1d0745SJose E. Roman     PetscCall(PetscSNPrintf(group, sizeof(group), "topologies/%s/labels", topologydm_name));
14672e1d0745SJose E. Roman   } else {
14682e1d0745SJose E. Roman     PetscCall(PetscStrncpy(group, "/labels", sizeof(group)));
14692e1d0745SJose E. Roman   }
14702e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, group));
14712e1d0745SJose E. Roman   PetscCall(DMGetNumLabels(dm, &numLabels));
14722e1d0745SJose E. Roman   for (PetscInt l = 0; l < numLabels; ++l) {
14732e1d0745SJose E. Roman     DMLabel         label;
14742e1d0745SJose E. Roman     const char     *name;
14752e1d0745SJose E. Roman     IS              valueIS, pvalueIS, globalValueIS;
14762e1d0745SJose E. Roman     const PetscInt *values;
14772e1d0745SJose E. Roman     PetscInt        numValues, v;
14782e1d0745SJose E. Roman     PetscBool       isDepth, isCelltype, output;
14792e1d0745SJose E. Roman 
14802e1d0745SJose E. Roman     PetscCall(DMGetLabelByNum(dm, l, &label));
14812e1d0745SJose E. Roman     PetscCall(PetscObjectGetName((PetscObject)label, &name));
14822e1d0745SJose E. Roman     PetscCall(DMGetLabelOutput(dm, name, &output));
14832e1d0745SJose E. Roman     PetscCall(PetscStrncmp(name, "depth", 10, &isDepth));
14842e1d0745SJose E. Roman     PetscCall(PetscStrncmp(name, "celltype", 10, &isCelltype));
14852e1d0745SJose E. Roman     // TODO Should only filter out celltype if it can be calculated
14862e1d0745SJose E. Roman     if (isDepth || (isCelltype && omitCelltypes) || !output) continue;
14872e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5PushGroup(viewer, name));
14882e1d0745SJose E. Roman     PetscCall(DMLabelGetValueIS(label, &valueIS));
14892e1d0745SJose E. Roman     /* Must copy to a new IS on the global comm */
14902e1d0745SJose E. Roman     PetscCall(ISGetLocalSize(valueIS, &numValues));
14912e1d0745SJose E. Roman     PetscCall(ISGetIndices(valueIS, &values));
14922e1d0745SJose E. Roman     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), numValues, values, PETSC_COPY_VALUES, &pvalueIS));
14932e1d0745SJose E. Roman     PetscCall(ISRestoreIndices(valueIS, &values));
14942e1d0745SJose E. Roman     PetscCall(ISAllGather(pvalueIS, &globalValueIS));
14952e1d0745SJose E. Roman     PetscCall(ISDestroy(&pvalueIS));
14962e1d0745SJose E. Roman     PetscCall(ISSortRemoveDups(globalValueIS));
14972e1d0745SJose E. Roman     PetscCall(ISGetLocalSize(globalValueIS, &numValues));
14982e1d0745SJose E. Roman     PetscCall(ISGetIndices(globalValueIS, &values));
14992e1d0745SJose E. Roman     for (v = 0; v < numValues; ++v) {
15002e1d0745SJose E. Roman       IS              stratumIS, globalStratumIS;
15012e1d0745SJose E. Roman       const PetscInt *spoints = NULL;
15022e1d0745SJose E. Roman       PetscInt       *gspoints, n = 0, gn, p;
15032e1d0745SJose E. Roman       const char     *iname = "indices";
15042e1d0745SJose E. Roman       char            group[PETSC_MAX_PATH_LEN];
15052e1d0745SJose E. Roman 
15062e1d0745SJose E. Roman       PetscCall(PetscSNPrintf(group, sizeof(group), "%" PetscInt_FMT, values[v]));
15072e1d0745SJose E. Roman       PetscCall(PetscViewerHDF5PushGroup(viewer, group));
15082e1d0745SJose E. Roman       PetscCall(DMLabelGetStratumIS(label, values[v], &stratumIS));
15092e1d0745SJose E. Roman 
15102e1d0745SJose E. Roman       if (stratumIS) PetscCall(ISGetLocalSize(stratumIS, &n));
15112e1d0745SJose E. Roman       if (stratumIS) PetscCall(ISGetIndices(stratumIS, &spoints));
15122e1d0745SJose E. Roman       for (gn = 0, p = 0; p < n; ++p)
15132e1d0745SJose E. Roman         if (gpoint[spoints[p]] >= 0) ++gn;
15142e1d0745SJose E. Roman       PetscCall(PetscMalloc1(gn, &gspoints));
15152e1d0745SJose E. Roman       for (gn = 0, p = 0; p < n; ++p)
15162e1d0745SJose E. Roman         if (gpoint[spoints[p]] >= 0) gspoints[gn++] = gpoint[spoints[p]];
15172e1d0745SJose E. Roman       if (stratumIS) PetscCall(ISRestoreIndices(stratumIS, &spoints));
15182e1d0745SJose E. Roman       PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), gn, gspoints, PETSC_OWN_POINTER, &globalStratumIS));
15192e1d0745SJose E. Roman       PetscCall(PetscObjectSetName((PetscObject)globalStratumIS, iname));
15202e1d0745SJose E. Roman       PetscCall(ISView(globalStratumIS, viewer));
15212e1d0745SJose E. Roman       PetscCall(ISDestroy(&globalStratumIS));
15222e1d0745SJose E. Roman       PetscCall(ISDestroy(&stratumIS));
15232e1d0745SJose E. Roman       PetscCall(PetscViewerHDF5PopGroup(viewer));
15242e1d0745SJose E. Roman     }
15252e1d0745SJose E. Roman     PetscCall(ISRestoreIndices(globalValueIS, &values));
15262e1d0745SJose E. Roman     PetscCall(ISDestroy(&globalValueIS));
15272e1d0745SJose E. Roman     PetscCall(ISDestroy(&valueIS));
15282e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5PopGroup(viewer));
15292e1d0745SJose E. Roman   }
15302e1d0745SJose E. Roman   PetscCall(ISRestoreIndices(globalPointNumbers, &gpoint));
15312e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
1532*ea87367fSMatthew G. Knepley   if (DMPlexStorageVersionGE(version, 3, 1, 0)) PetscCall(PetscViewerHDF5SetCompress(viewer, ocompress));
15332e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
15342e1d0745SJose E. Roman }
15352e1d0745SJose E. Roman 
15362e1d0745SJose E. Roman /* We only write cells and vertices. Does this screw up parallel reading? */
15372e1d0745SJose E. Roman PetscErrorCode DMPlexView_HDF5_Internal(DM dm, PetscViewer viewer)
15382e1d0745SJose E. Roman {
15392e1d0745SJose E. Roman   IS                globalPointNumbers;
15402e1d0745SJose E. Roman   PetscViewerFormat format;
15412e1d0745SJose E. Roman   PetscBool         viz_geom = PETSC_FALSE, xdmf_topo = PETSC_FALSE, petsc_topo = PETSC_FALSE;
15422e1d0745SJose E. Roman 
15432e1d0745SJose E. Roman   PetscFunctionBegin;
15442e1d0745SJose E. Roman   PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbers));
15452e1d0745SJose E. Roman   PetscCall(DMPlexCoordinatesView_HDF5_Internal(dm, viewer));
15462e1d0745SJose E. Roman 
15472e1d0745SJose E. Roman   PetscCall(PetscViewerGetFormat(viewer, &format));
15482e1d0745SJose E. Roman   switch (format) {
15492e1d0745SJose E. Roman   case PETSC_VIEWER_HDF5_VIZ:
15502e1d0745SJose E. Roman     viz_geom  = PETSC_TRUE;
15512e1d0745SJose E. Roman     xdmf_topo = PETSC_TRUE;
15522e1d0745SJose E. Roman     break;
15532e1d0745SJose E. Roman   case PETSC_VIEWER_HDF5_XDMF:
15542e1d0745SJose E. Roman     xdmf_topo = PETSC_TRUE;
15552e1d0745SJose E. Roman     break;
15562e1d0745SJose E. Roman   case PETSC_VIEWER_HDF5_PETSC:
15572e1d0745SJose E. Roman     petsc_topo = PETSC_TRUE;
15582e1d0745SJose E. Roman     break;
15592e1d0745SJose E. Roman   case PETSC_VIEWER_DEFAULT:
15602e1d0745SJose E. Roman   case PETSC_VIEWER_NATIVE:
15612e1d0745SJose E. Roman     viz_geom   = PETSC_TRUE;
15622e1d0745SJose E. Roman     xdmf_topo  = PETSC_TRUE;
15632e1d0745SJose E. Roman     petsc_topo = PETSC_TRUE;
15642e1d0745SJose E. Roman     break;
15652e1d0745SJose E. Roman   default:
15662e1d0745SJose E. Roman     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]);
15672e1d0745SJose E. Roman   }
15682e1d0745SJose E. Roman 
15692e1d0745SJose E. Roman   if (viz_geom) PetscCall(DMPlexCoordinatesView_HDF5_XDMF_Private(dm, viewer));
15702e1d0745SJose E. Roman   if (xdmf_topo) PetscCall(DMPlexTopologyView_HDF5_XDMF_Private(dm, globalPointNumbers, viewer));
15712e1d0745SJose E. Roman   if (petsc_topo) {
15722e1d0745SJose E. Roman     PetscBool viewLabels = PETSC_TRUE;
15732e1d0745SJose E. Roman 
15742e1d0745SJose E. Roman     PetscCall(DMPlexTopologyView_HDF5_Internal(dm, globalPointNumbers, viewer));
15752e1d0745SJose E. Roman     PetscCall(PetscOptionsGetBool(NULL, dm->hdr.prefix, "-dm_plex_view_labels", &viewLabels, NULL));
15762e1d0745SJose E. Roman     if (viewLabels) PetscCall(DMPlexLabelsView_HDF5_Internal(dm, globalPointNumbers, viewer));
15772e1d0745SJose E. Roman   }
15782e1d0745SJose E. Roman 
15792e1d0745SJose E. Roman   PetscCall(ISDestroy(&globalPointNumbers));
15802e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
15812e1d0745SJose E. Roman }
15822e1d0745SJose E. Roman 
15832e1d0745SJose E. Roman PetscErrorCode DMPlexSectionView_HDF5_Internal(DM dm, PetscViewer viewer, DM sectiondm)
15842e1d0745SJose E. Roman {
15855a236de6SSatish Balay   DMPlexStorageVersion version;
15862e1d0745SJose E. Roman   MPI_Comm             comm;
15872e1d0745SJose E. Roman   const char          *topologydm_name;
15882e1d0745SJose E. Roman   const char          *sectiondm_name;
15892e1d0745SJose E. Roman   PetscSection         gsection;
1590*ea87367fSMatthew G. Knepley   PetscBool            ocompress;
15912e1d0745SJose E. Roman 
15922e1d0745SJose E. Roman   PetscFunctionBegin;
15935a236de6SSatish Balay   PetscCall(PetscViewerHDF5GetDMPlexStorageVersionWriting(viewer, &version));
1594*ea87367fSMatthew G. Knepley   if (DMPlexStorageVersionGE(version, 3, 1, 0)) {
1595*ea87367fSMatthew G. Knepley     PetscCall(PetscViewerHDF5GetCompress(viewer, &ocompress));
1596*ea87367fSMatthew G. Knepley     PetscCall(PetscViewerHDF5SetCompress(viewer, PETSC_TRUE));
1597*ea87367fSMatthew G. Knepley   }
15982e1d0745SJose E. Roman   PetscCall(PetscObjectGetComm((PetscObject)sectiondm, &comm));
15992e1d0745SJose E. Roman   PetscCall(DMPlexGetHDF5Name_Private(dm, &topologydm_name));
16002e1d0745SJose E. Roman   PetscCall(PetscObjectGetName((PetscObject)sectiondm, &sectiondm_name));
16012e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "topologies"));
16022e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, topologydm_name));
16032e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "dms"));
16042e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, sectiondm_name));
16052e1d0745SJose E. Roman   PetscCall(DMGetGlobalSection(sectiondm, &gsection));
16062e1d0745SJose E. Roman   /* Save raw section */
16072e1d0745SJose E. Roman   PetscCall(PetscSectionView(gsection, viewer));
16082e1d0745SJose E. Roman   /* Save plex wrapper */
16092e1d0745SJose E. Roman   {
16102e1d0745SJose E. Roman     PetscInt        pStart, pEnd, p, n;
16112e1d0745SJose E. Roman     IS              globalPointNumbers;
16122e1d0745SJose E. Roman     const PetscInt *gpoints;
16132e1d0745SJose E. Roman     IS              orderIS;
16142e1d0745SJose E. Roman     PetscInt       *order;
16152e1d0745SJose E. Roman 
16162e1d0745SJose E. Roman     PetscCall(PetscSectionGetChart(gsection, &pStart, &pEnd));
16172e1d0745SJose E. Roman     PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbers));
16182e1d0745SJose E. Roman     PetscCall(ISGetIndices(globalPointNumbers, &gpoints));
16192e1d0745SJose E. Roman     for (p = pStart, n = 0; p < pEnd; ++p)
16202e1d0745SJose E. Roman       if (gpoints[p] >= 0) n++;
16212e1d0745SJose E. Roman     /* "order" is an array of global point numbers.
16222e1d0745SJose E. Roman        When loading, it is used with topology/order array
16232e1d0745SJose E. Roman        to match section points with plex topology points. */
16242e1d0745SJose E. Roman     PetscCall(PetscMalloc1(n, &order));
16252e1d0745SJose E. Roman     for (p = pStart, n = 0; p < pEnd; ++p)
16262e1d0745SJose E. Roman       if (gpoints[p] >= 0) order[n++] = gpoints[p];
16272e1d0745SJose E. Roman     PetscCall(ISRestoreIndices(globalPointNumbers, &gpoints));
16282e1d0745SJose E. Roman     PetscCall(ISDestroy(&globalPointNumbers));
16292e1d0745SJose E. Roman     PetscCall(ISCreateGeneral(comm, n, order, PETSC_OWN_POINTER, &orderIS));
16302e1d0745SJose E. Roman     PetscCall(PetscObjectSetName((PetscObject)orderIS, "order"));
16312e1d0745SJose E. Roman     PetscCall(ISView(orderIS, viewer));
16322e1d0745SJose E. Roman     PetscCall(ISDestroy(&orderIS));
16332e1d0745SJose E. Roman   }
16342e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
16352e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
16362e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
16372e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
1638*ea87367fSMatthew G. Knepley   if (DMPlexStorageVersionGE(version, 3, 1, 0)) PetscCall(PetscViewerHDF5SetCompress(viewer, ocompress));
16392e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
16402e1d0745SJose E. Roman }
16412e1d0745SJose E. Roman 
16422e1d0745SJose E. Roman PetscErrorCode DMPlexGlobalVectorView_HDF5_Internal(DM dm, PetscViewer viewer, DM sectiondm, Vec vec)
16432e1d0745SJose E. Roman {
16442e1d0745SJose E. Roman   const char *topologydm_name;
16452e1d0745SJose E. Roman   const char *sectiondm_name;
16462e1d0745SJose E. Roman   const char *vec_name;
16472e1d0745SJose E. Roman   PetscInt    bs;
16482e1d0745SJose E. Roman 
16492e1d0745SJose E. Roman   PetscFunctionBegin;
16502e1d0745SJose E. Roman   /* Check consistency */
16512e1d0745SJose E. Roman   {
16522e1d0745SJose E. Roman     PetscSF pointsf, pointsf1;
16532e1d0745SJose E. Roman 
16542e1d0745SJose E. Roman     PetscCall(DMGetPointSF(dm, &pointsf));
16552e1d0745SJose E. Roman     PetscCall(DMGetPointSF(sectiondm, &pointsf1));
16562e1d0745SJose E. Roman     PetscCheck(pointsf1 == pointsf, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatching point SFs for dm and sectiondm");
16572e1d0745SJose E. Roman   }
16582e1d0745SJose E. Roman   PetscCall(DMPlexGetHDF5Name_Private(dm, &topologydm_name));
16592e1d0745SJose E. Roman   PetscCall(PetscObjectGetName((PetscObject)sectiondm, &sectiondm_name));
16602e1d0745SJose E. Roman   PetscCall(PetscObjectGetName((PetscObject)vec, &vec_name));
16612e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "topologies"));
16622e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, topologydm_name));
16632e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "dms"));
16642e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, sectiondm_name));
16652e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "vecs"));
16662e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, vec_name));
16672e1d0745SJose E. Roman   PetscCall(VecGetBlockSize(vec, &bs));
16682e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5WriteAttribute(viewer, NULL, "blockSize", PETSC_INT, (void *)&bs));
16692e1d0745SJose E. Roman   PetscCall(VecSetBlockSize(vec, 1));
16702e1d0745SJose E. Roman   /* VecView(vec, viewer) would call (*vec->opt->view)(vec, viewer), but,    */
16712e1d0745SJose E. Roman   /* if vec was created with DMGet{Global, Local}Vector(), vec->opt->view    */
16722e1d0745SJose E. Roman   /* is set to VecView_Plex, which would save vec in a predefined location.  */
16732e1d0745SJose E. Roman   /* To save vec in where we want, we create a new Vec (temp) with           */
16742e1d0745SJose E. Roman   /* VecCreate(), wrap the vec data in temp, and call VecView(temp, viewer). */
16752e1d0745SJose E. Roman   {
16762e1d0745SJose E. Roman     Vec                temp;
16772e1d0745SJose E. Roman     const PetscScalar *array;
16782e1d0745SJose E. Roman     PetscLayout        map;
16792e1d0745SJose E. Roman 
16802e1d0745SJose E. Roman     PetscCall(VecCreate(PetscObjectComm((PetscObject)vec), &temp));
16812e1d0745SJose E. Roman     PetscCall(PetscObjectSetName((PetscObject)temp, vec_name));
16822e1d0745SJose E. Roman     PetscCall(VecGetLayout(vec, &map));
16832e1d0745SJose E. Roman     PetscCall(VecSetLayout(temp, map));
16842e1d0745SJose E. Roman     PetscCall(VecSetUp(temp));
16852e1d0745SJose E. Roman     PetscCall(VecGetArrayRead(vec, &array));
16862e1d0745SJose E. Roman     PetscCall(VecPlaceArray(temp, array));
16872e1d0745SJose E. Roman     PetscCall(VecView(temp, viewer));
16882e1d0745SJose E. Roman     PetscCall(VecResetArray(temp));
16892e1d0745SJose E. Roman     PetscCall(VecRestoreArrayRead(vec, &array));
16902e1d0745SJose E. Roman     PetscCall(VecDestroy(&temp));
16912e1d0745SJose E. Roman   }
16922e1d0745SJose E. Roman   PetscCall(VecSetBlockSize(vec, bs));
16932e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
16942e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
16952e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
16962e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
16972e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
16982e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
16992e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
17002e1d0745SJose E. Roman }
17012e1d0745SJose E. Roman 
17022e1d0745SJose E. Roman PetscErrorCode DMPlexLocalVectorView_HDF5_Internal(DM dm, PetscViewer viewer, DM sectiondm, Vec vec)
17032e1d0745SJose E. Roman {
17042e1d0745SJose E. Roman   MPI_Comm     comm;
17052e1d0745SJose E. Roman   const char  *topologydm_name;
17062e1d0745SJose E. Roman   const char  *sectiondm_name;
17072e1d0745SJose E. Roman   const char  *vec_name;
17082e1d0745SJose E. Roman   PetscSection section;
17092e1d0745SJose E. Roman   PetscBool    includesConstraints;
17102e1d0745SJose E. Roman   Vec          gvec;
17112e1d0745SJose E. Roman   PetscInt     m, bs;
17122e1d0745SJose E. Roman 
17132e1d0745SJose E. Roman   PetscFunctionBegin;
17142e1d0745SJose E. Roman   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
17152e1d0745SJose E. Roman   /* Check consistency */
17162e1d0745SJose E. Roman   {
17172e1d0745SJose E. Roman     PetscSF pointsf, pointsf1;
17182e1d0745SJose E. Roman 
17192e1d0745SJose E. Roman     PetscCall(DMGetPointSF(dm, &pointsf));
17202e1d0745SJose E. Roman     PetscCall(DMGetPointSF(sectiondm, &pointsf1));
17212e1d0745SJose E. Roman     PetscCheck(pointsf1 == pointsf, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatching point SFs for dm and sectiondm");
17222e1d0745SJose E. Roman   }
17232e1d0745SJose E. Roman   PetscCall(DMPlexGetHDF5Name_Private(dm, &topologydm_name));
17242e1d0745SJose E. Roman   PetscCall(PetscObjectGetName((PetscObject)sectiondm, &sectiondm_name));
17252e1d0745SJose E. Roman   PetscCall(PetscObjectGetName((PetscObject)vec, &vec_name));
17262e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "topologies"));
17272e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, topologydm_name));
17282e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "dms"));
17292e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, sectiondm_name));
17302e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "vecs"));
17312e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, vec_name));
17322e1d0745SJose E. Roman   PetscCall(VecGetBlockSize(vec, &bs));
17332e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5WriteAttribute(viewer, NULL, "blockSize", PETSC_INT, (void *)&bs));
17342e1d0745SJose E. Roman   PetscCall(VecCreate(comm, &gvec));
17352e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)gvec, vec_name));
17362e1d0745SJose E. Roman   PetscCall(DMGetGlobalSection(sectiondm, &section));
17372e1d0745SJose E. Roman   PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
17382e1d0745SJose E. Roman   if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
17392e1d0745SJose E. Roman   else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
17402e1d0745SJose E. Roman   PetscCall(VecSetSizes(gvec, m, PETSC_DECIDE));
17412e1d0745SJose E. Roman   PetscCall(VecSetUp(gvec));
17422e1d0745SJose E. Roman   PetscCall(DMLocalToGlobalBegin(sectiondm, vec, INSERT_VALUES, gvec));
17432e1d0745SJose E. Roman   PetscCall(DMLocalToGlobalEnd(sectiondm, vec, INSERT_VALUES, gvec));
17442e1d0745SJose E. Roman   PetscCall(VecView(gvec, viewer));
17452e1d0745SJose E. Roman   PetscCall(VecDestroy(&gvec));
17462e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
17472e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
17482e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
17492e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
17502e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
17512e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
17522e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
17532e1d0745SJose E. Roman }
17542e1d0745SJose E. Roman 
17552e1d0745SJose E. Roman struct _n_LoadLabelsCtx {
17562e1d0745SJose E. Roman   MPI_Comm    comm;
17572e1d0745SJose E. Roman   PetscMPIInt rank;
17582e1d0745SJose E. Roman   DM          dm;
17592e1d0745SJose E. Roman   PetscViewer viewer;
17602e1d0745SJose E. Roman   DMLabel     label;
17612e1d0745SJose E. Roman   PetscSF     sfXC;
17622e1d0745SJose E. Roman   PetscLayout layoutX;
17632e1d0745SJose E. Roman };
17642e1d0745SJose E. Roman typedef struct _n_LoadLabelsCtx *LoadLabelsCtx;
17652e1d0745SJose E. Roman 
17662e1d0745SJose E. Roman static PetscErrorCode LoadLabelsCtxCreate(DM dm, PetscViewer viewer, PetscSF sfXC, LoadLabelsCtx *ctx)
17672e1d0745SJose E. Roman {
17682e1d0745SJose E. Roman   PetscFunctionBegin;
17692e1d0745SJose E. Roman   PetscCall(PetscNew(ctx));
17702e1d0745SJose E. Roman   PetscCall(PetscObjectReference((PetscObject)((*ctx)->dm = dm)));
17712e1d0745SJose E. Roman   PetscCall(PetscObjectReference((PetscObject)((*ctx)->viewer = viewer)));
17722e1d0745SJose E. Roman   PetscCall(PetscObjectGetComm((PetscObject)dm, &(*ctx)->comm));
17732e1d0745SJose E. Roman   PetscCallMPI(MPI_Comm_rank((*ctx)->comm, &(*ctx)->rank));
17742e1d0745SJose E. Roman   (*ctx)->sfXC = sfXC;
17752e1d0745SJose E. Roman   if (sfXC) {
17762e1d0745SJose E. Roman     PetscInt nX;
17772e1d0745SJose E. Roman 
17782e1d0745SJose E. Roman     PetscCall(PetscObjectReference((PetscObject)sfXC));
17792e1d0745SJose E. Roman     PetscCall(PetscSFGetGraph(sfXC, &nX, NULL, NULL, NULL));
17802e1d0745SJose E. Roman     PetscCall(PetscLayoutCreateFromSizes((*ctx)->comm, nX, PETSC_DECIDE, 1, &(*ctx)->layoutX));
17812e1d0745SJose E. Roman   }
17822e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
17832e1d0745SJose E. Roman }
17842e1d0745SJose E. Roman 
17852e1d0745SJose E. Roman static PetscErrorCode LoadLabelsCtxDestroy(LoadLabelsCtx *ctx)
17862e1d0745SJose E. Roman {
17872e1d0745SJose E. Roman   PetscFunctionBegin;
17882e1d0745SJose E. Roman   if (!*ctx) PetscFunctionReturn(PETSC_SUCCESS);
17892e1d0745SJose E. Roman   PetscCall(DMDestroy(&(*ctx)->dm));
17902e1d0745SJose E. Roman   PetscCall(PetscViewerDestroy(&(*ctx)->viewer));
17912e1d0745SJose E. Roman   PetscCall(PetscSFDestroy(&(*ctx)->sfXC));
17922e1d0745SJose E. Roman   PetscCall(PetscLayoutDestroy(&(*ctx)->layoutX));
17932e1d0745SJose E. Roman   PetscCall(PetscFree(*ctx));
17942e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
17952e1d0745SJose E. Roman }
17962e1d0745SJose E. Roman 
17972e1d0745SJose E. Roman /*
17982e1d0745SJose E. Roman     A: on-disk points
17992e1d0745SJose E. Roman     X: global points [0, NX)
18002e1d0745SJose E. Roman     C: distributed plex points
18012e1d0745SJose E. Roman */
18022e1d0745SJose E. Roman static herr_t ReadLabelStratumHDF5_Distribute_Private(IS stratumIS, LoadLabelsCtx ctx, IS *newStratumIS)
18032e1d0745SJose E. Roman {
18042e1d0745SJose E. Roman   MPI_Comm        comm    = ctx->comm;
18052e1d0745SJose E. Roman   PetscSF         sfXC    = ctx->sfXC;
18062e1d0745SJose E. Roman   PetscLayout     layoutX = ctx->layoutX;
18072e1d0745SJose E. Roman   PetscSF         sfXA;
18082e1d0745SJose E. Roman   const PetscInt *A_points;
18092e1d0745SJose E. Roman   PetscInt        nX, nC;
18102e1d0745SJose E. Roman   PetscInt        n;
18112e1d0745SJose E. Roman 
18122e1d0745SJose E. Roman   PetscFunctionBegin;
18132e1d0745SJose E. Roman   PetscCall(PetscSFGetGraph(sfXC, &nX, &nC, NULL, NULL));
18142e1d0745SJose E. Roman   PetscCall(ISGetLocalSize(stratumIS, &n));
18152e1d0745SJose E. Roman   PetscCall(ISGetIndices(stratumIS, &A_points));
18162e1d0745SJose E. Roman   PetscCall(PetscSFCreate(comm, &sfXA));
18172e1d0745SJose E. Roman   PetscCall(PetscSFSetGraphLayout(sfXA, layoutX, n, NULL, PETSC_USE_POINTER, A_points));
18182e1d0745SJose E. Roman   PetscCall(ISCreate(comm, newStratumIS));
18192e1d0745SJose E. Roman   PetscCall(ISSetType(*newStratumIS, ISGENERAL));
18202e1d0745SJose E. Roman   {
18212e1d0745SJose E. Roman     PetscInt   i;
18222e1d0745SJose E. Roman     PetscBool *A_mask, *X_mask, *C_mask;
18232e1d0745SJose E. Roman 
18242e1d0745SJose E. Roman     PetscCall(PetscCalloc3(n, &A_mask, nX, &X_mask, nC, &C_mask));
18252e1d0745SJose E. Roman     for (i = 0; i < n; i++) A_mask[i] = PETSC_TRUE;
18262e1d0745SJose E. Roman     PetscCall(PetscSFReduceBegin(sfXA, MPIU_BOOL, A_mask, X_mask, MPI_REPLACE));
18272e1d0745SJose E. Roman     PetscCall(PetscSFReduceEnd(sfXA, MPIU_BOOL, A_mask, X_mask, MPI_REPLACE));
18282e1d0745SJose E. Roman     PetscCall(PetscSFBcastBegin(sfXC, MPIU_BOOL, X_mask, C_mask, MPI_LOR));
18292e1d0745SJose E. Roman     PetscCall(PetscSFBcastEnd(sfXC, MPIU_BOOL, X_mask, C_mask, MPI_LOR));
18302e1d0745SJose E. Roman     PetscCall(ISGeneralSetIndicesFromMask(*newStratumIS, 0, nC, C_mask));
18312e1d0745SJose E. Roman     PetscCall(PetscFree3(A_mask, X_mask, C_mask));
18322e1d0745SJose E. Roman   }
18332e1d0745SJose E. Roman   PetscCall(PetscSFDestroy(&sfXA));
18342e1d0745SJose E. Roman   PetscCall(ISRestoreIndices(stratumIS, &A_points));
18352e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
18362e1d0745SJose E. Roman }
18372e1d0745SJose E. Roman 
18382e1d0745SJose E. Roman static herr_t ReadLabelStratumHDF5_Static(hid_t g_id, const char *vname, const H5L_info_t *info, void *op_data)
18392e1d0745SJose E. Roman {
18402e1d0745SJose E. Roman   LoadLabelsCtx   ctx    = (LoadLabelsCtx)op_data;
18412e1d0745SJose E. Roman   PetscViewer     viewer = ctx->viewer;
18422e1d0745SJose E. Roman   DMLabel         label  = ctx->label;
18432e1d0745SJose E. Roman   MPI_Comm        comm   = ctx->comm;
18442e1d0745SJose E. Roman   IS              stratumIS;
18452e1d0745SJose E. Roman   const PetscInt *ind;
18462e1d0745SJose E. Roman   PetscInt        value, N, i;
18472e1d0745SJose E. Roman 
18482e1d0745SJose E. Roman   PetscCall(PetscOptionsStringToInt(vname, &value));
18492e1d0745SJose E. Roman   PetscCall(ISCreate(comm, &stratumIS));
18502e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)stratumIS, "indices"));
18512e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, vname)); /* labels/<lname>/<vname> */
18522e1d0745SJose E. Roman 
18532e1d0745SJose E. Roman   if (!ctx->sfXC) {
18542e1d0745SJose E. Roman     /* Force serial load */
18552e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5ReadSizes(viewer, "indices", NULL, &N));
18562e1d0745SJose E. Roman     PetscCall(PetscLayoutSetLocalSize(stratumIS->map, !ctx->rank ? N : 0));
18572e1d0745SJose E. Roman     PetscCall(PetscLayoutSetSize(stratumIS->map, N));
18582e1d0745SJose E. Roman   }
18592e1d0745SJose E. Roman   PetscCall(ISLoad(stratumIS, viewer));
18602e1d0745SJose E. Roman 
18612e1d0745SJose E. Roman   if (ctx->sfXC) {
18622e1d0745SJose E. Roman     IS newStratumIS;
18632e1d0745SJose E. Roman 
18642e1d0745SJose E. Roman     PetscCallHDF5(ReadLabelStratumHDF5_Distribute_Private, (stratumIS, ctx, &newStratumIS));
18652e1d0745SJose E. Roman     PetscCall(ISDestroy(&stratumIS));
18662e1d0745SJose E. Roman     stratumIS = newStratumIS;
18672e1d0745SJose E. Roman   }
18682e1d0745SJose E. Roman 
18692e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
18702e1d0745SJose E. Roman   PetscCall(ISGetLocalSize(stratumIS, &N));
18712e1d0745SJose E. Roman   PetscCall(ISGetIndices(stratumIS, &ind));
18722e1d0745SJose E. Roman   for (i = 0; i < N; ++i) PetscCall(DMLabelSetValue(label, ind[i], value));
18732e1d0745SJose E. Roman   PetscCall(ISRestoreIndices(stratumIS, &ind));
18742e1d0745SJose E. Roman   PetscCall(ISDestroy(&stratumIS));
18752e1d0745SJose E. Roman   return 0;
18762e1d0745SJose E. Roman }
18772e1d0745SJose E. Roman 
18782e1d0745SJose E. Roman /* TODO: Fix this code, it is returning PETSc error codes when it should be translating them to herr_t codes */
18792e1d0745SJose E. Roman static herr_t ReadLabelHDF5_Static(hid_t g_id, const char *lname, const H5L_info_t *info, void *op_data)
18802e1d0745SJose E. Roman {
18812e1d0745SJose E. Roman   LoadLabelsCtx  ctx = (LoadLabelsCtx)op_data;
18822e1d0745SJose E. Roman   DM             dm  = ctx->dm;
18832e1d0745SJose E. Roman   hsize_t        idx = 0;
18842e1d0745SJose E. Roman   PetscErrorCode ierr;
18852e1d0745SJose E. Roman   PetscBool      flg;
18862e1d0745SJose E. Roman   herr_t         err;
18872e1d0745SJose E. Roman 
18882e1d0745SJose E. Roman   PetscCall(DMHasLabel(dm, lname, &flg));
18892e1d0745SJose E. Roman   if (flg) PetscCall(DMRemoveLabel(dm, lname, NULL));
18902e1d0745SJose E. Roman   ierr = DMCreateLabel(dm, lname);
18912e1d0745SJose E. Roman   if (ierr) return (herr_t)ierr;
18922e1d0745SJose E. Roman   ierr = DMGetLabel(dm, lname, &ctx->label);
18932e1d0745SJose E. Roman   if (ierr) return (herr_t)ierr;
18942e1d0745SJose E. Roman   ierr = PetscViewerHDF5PushGroup(ctx->viewer, lname);
18952e1d0745SJose E. Roman   if (ierr) return (herr_t)ierr;
18962e1d0745SJose E. Roman   /* Iterate over the label's strata */
18972e1d0745SJose E. Roman   PetscCallHDF5Return(err, H5Literate_by_name, (g_id, lname, H5_INDEX_NAME, H5_ITER_NATIVE, &idx, ReadLabelStratumHDF5_Static, op_data, 0));
18982e1d0745SJose E. Roman   ierr = PetscViewerHDF5PopGroup(ctx->viewer);
18992e1d0745SJose E. Roman   if (ierr) return (herr_t)ierr;
19002e1d0745SJose E. Roman   return err;
19012e1d0745SJose E. Roman }
19022e1d0745SJose E. Roman 
19032e1d0745SJose E. Roman PetscErrorCode DMPlexLabelsLoad_HDF5_Internal(DM dm, PetscViewer viewer, PetscSF sfXC)
19042e1d0745SJose E. Roman {
19052e1d0745SJose E. Roman   const char          *topologydm_name;
19062e1d0745SJose E. Roman   LoadLabelsCtx        ctx;
19072e1d0745SJose E. Roman   hsize_t              idx = 0;
19082e1d0745SJose E. Roman   char                 group[PETSC_MAX_PATH_LEN];
19092e1d0745SJose E. Roman   DMPlexStorageVersion version;
19102e1d0745SJose E. Roman   PetscBool            distributed, hasGroup;
19112e1d0745SJose E. Roman 
19122e1d0745SJose E. Roman   PetscFunctionBegin;
19132e1d0745SJose E. Roman   PetscCall(DMPlexIsDistributed(dm, &distributed));
19142e1d0745SJose E. Roman   if (distributed) PetscCheck(sfXC, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_NULL, "PetscSF must be given for parallel load");
19152e1d0745SJose E. Roman   PetscCall(LoadLabelsCtxCreate(dm, viewer, sfXC, &ctx));
19162e1d0745SJose E. Roman   PetscCall(DMPlexGetHDF5Name_Private(dm, &topologydm_name));
19172e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5GetDMPlexStorageVersionReading(viewer, &version));
19182e1d0745SJose E. Roman   if (DMPlexStorageVersionGE(version, 2, 0, 0)) {
19192e1d0745SJose E. Roman     PetscCall(PetscSNPrintf(group, sizeof(group), "topologies/%s/labels", topologydm_name));
19202e1d0745SJose E. Roman   } else {
19212e1d0745SJose E. Roman     PetscCall(PetscStrncpy(group, "labels", sizeof(group)));
19222e1d0745SJose E. Roman   }
19232e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, group));
19242e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5HasGroup(viewer, NULL, &hasGroup));
19252e1d0745SJose E. Roman   if (hasGroup) {
19262e1d0745SJose E. Roman     hid_t fileId, groupId;
19272e1d0745SJose E. Roman 
19282e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5OpenGroup(viewer, NULL, &fileId, &groupId));
19292e1d0745SJose E. Roman     /* Iterate over labels */
19302e1d0745SJose E. Roman     PetscCallHDF5(H5Literate, (groupId, H5_INDEX_NAME, H5_ITER_NATIVE, &idx, ReadLabelHDF5_Static, ctx));
19312e1d0745SJose E. Roman     PetscCallHDF5(H5Gclose, (groupId));
19322e1d0745SJose E. Roman   }
19332e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
19342e1d0745SJose E. Roman   PetscCall(LoadLabelsCtxDestroy(&ctx));
19352e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
19362e1d0745SJose E. Roman }
19372e1d0745SJose E. Roman 
19382e1d0745SJose E. Roman static PetscErrorCode DMPlexDistributionLoad_HDF5_Private(DM dm, PetscViewer viewer, PetscSF sf, PetscSF *distsf, DM *distdm)
19392e1d0745SJose E. Roman {
19402e1d0745SJose E. Roman   MPI_Comm        comm;
19412e1d0745SJose E. Roman   PetscMPIInt     size, rank;
19422e1d0745SJose E. Roman   PetscInt        dist_size;
19432e1d0745SJose E. Roman   const char     *distribution_name;
19442e1d0745SJose E. Roman   PetscInt        p, lsize;
19452e1d0745SJose E. Roman   IS              chartSizesIS, ownersIS, gpointsIS;
19462e1d0745SJose E. Roman   const PetscInt *chartSize, *owners, *gpoints;
19472e1d0745SJose E. Roman   PetscLayout     layout;
19482e1d0745SJose E. Roman   PetscBool       has;
19492e1d0745SJose E. Roman 
19502e1d0745SJose E. Roman   PetscFunctionBegin;
19512e1d0745SJose E. Roman   *distsf = NULL;
19522e1d0745SJose E. Roman   *distdm = NULL;
19532e1d0745SJose E. Roman   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
19542e1d0745SJose E. Roman   PetscCallMPI(MPI_Comm_size(comm, &size));
19552e1d0745SJose E. Roman   PetscCallMPI(MPI_Comm_rank(comm, &rank));
19562e1d0745SJose E. Roman   PetscCall(DMPlexDistributionGetName(dm, &distribution_name));
19572e1d0745SJose E. Roman   if (!distribution_name) PetscFunctionReturn(PETSC_SUCCESS);
19582e1d0745SJose E. Roman   PetscCall(PetscLogEventBegin(DMPLEX_DistributionLoad, viewer, 0, 0, 0));
19592e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5HasGroup(viewer, NULL, &has));
19602e1d0745SJose E. Roman   if (!has) {
1961ce78bad3SBarry Smith     const char *full_group;
19622e1d0745SJose E. Roman 
19632e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5GetGroup(viewer, NULL, &full_group));
19642e1d0745SJose E. Roman     PetscCheck(has, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Distribution %s cannot be found: HDF5 group %s not found in file", distribution_name, full_group);
19652e1d0745SJose E. Roman   }
19662e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5ReadAttribute(viewer, NULL, "comm_size", PETSC_INT, NULL, (void *)&dist_size));
19672e1d0745SJose E. Roman   PetscCheck(dist_size == (PetscInt)size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mismatching comm sizes: comm size of this session (%d) != comm size used for %s (%" PetscInt_FMT ")", size, distribution_name, dist_size);
19682e1d0745SJose E. Roman   PetscCall(ISCreate(comm, &chartSizesIS));
19692e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)chartSizesIS, "chart_sizes"));
19702e1d0745SJose E. Roman   PetscCall(ISCreate(comm, &ownersIS));
19712e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)ownersIS, "owners"));
19722e1d0745SJose E. Roman   PetscCall(ISCreate(comm, &gpointsIS));
19732e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)gpointsIS, "global_point_numbers"));
19742e1d0745SJose E. Roman   PetscCall(PetscLayoutSetLocalSize(chartSizesIS->map, 1));
19752e1d0745SJose E. Roman   PetscCall(ISLoad(chartSizesIS, viewer));
19762e1d0745SJose E. Roman   PetscCall(ISGetIndices(chartSizesIS, &chartSize));
19772e1d0745SJose E. Roman   PetscCall(PetscLayoutSetLocalSize(ownersIS->map, *chartSize));
19782e1d0745SJose E. Roman   PetscCall(PetscLayoutSetLocalSize(gpointsIS->map, *chartSize));
19792e1d0745SJose E. Roman   PetscCall(ISLoad(ownersIS, viewer));
19802e1d0745SJose E. Roman   PetscCall(ISLoad(gpointsIS, viewer));
19812e1d0745SJose E. Roman   PetscCall(ISGetIndices(ownersIS, &owners));
19822e1d0745SJose E. Roman   PetscCall(ISGetIndices(gpointsIS, &gpoints));
19832e1d0745SJose E. Roman   PetscCall(PetscSFCreate(comm, distsf));
19842e1d0745SJose E. Roman   PetscCall(PetscSFSetFromOptions(*distsf));
19852e1d0745SJose E. Roman   PetscCall(PetscLayoutCreate(comm, &layout));
19862e1d0745SJose E. Roman   PetscCall(PetscSFGetGraph(sf, &lsize, NULL, NULL, NULL));
19872e1d0745SJose E. Roman   PetscCall(PetscLayoutSetLocalSize(layout, lsize));
19882e1d0745SJose E. Roman   PetscCall(PetscLayoutSetBlockSize(layout, 1));
19892e1d0745SJose E. Roman   PetscCall(PetscLayoutSetUp(layout));
19902e1d0745SJose E. Roman   PetscCall(PetscSFSetGraphLayout(*distsf, layout, *chartSize, NULL, PETSC_OWN_POINTER, gpoints));
19912e1d0745SJose E. Roman   PetscCall(PetscLayoutDestroy(&layout));
19922e1d0745SJose E. Roman   /* Migrate DM */
19932e1d0745SJose E. Roman   {
19942e1d0745SJose E. Roman     PetscInt     pStart, pEnd;
19952e1d0745SJose E. Roman     PetscSFNode *buffer0, *buffer1, *buffer2;
19962e1d0745SJose E. Roman 
19972e1d0745SJose E. Roman     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
19982e1d0745SJose E. Roman     PetscCall(PetscMalloc2(pEnd - pStart, &buffer0, lsize, &buffer1));
19992e1d0745SJose E. Roman     PetscCall(PetscMalloc1(*chartSize, &buffer2));
20002e1d0745SJose E. Roman     {
20012e1d0745SJose E. Roman       PetscSF            workPointSF;
20022e1d0745SJose E. Roman       PetscInt           workNroots, workNleaves;
20032e1d0745SJose E. Roman       const PetscInt    *workIlocal;
20042e1d0745SJose E. Roman       const PetscSFNode *workIremote;
20052e1d0745SJose E. Roman 
20062e1d0745SJose E. Roman       for (p = pStart; p < pEnd; ++p) {
20072e1d0745SJose E. Roman         buffer0[p - pStart].rank  = rank;
20082e1d0745SJose E. Roman         buffer0[p - pStart].index = p - pStart;
20092e1d0745SJose E. Roman       }
20102e1d0745SJose E. Roman       PetscCall(DMGetPointSF(dm, &workPointSF));
20112e1d0745SJose E. Roman       PetscCall(PetscSFGetGraph(workPointSF, &workNroots, &workNleaves, &workIlocal, &workIremote));
20122e1d0745SJose E. Roman       for (p = 0; p < workNleaves; ++p) {
20132e1d0745SJose E. Roman         PetscInt workIlocalp = (workIlocal ? workIlocal[p] : p);
20142e1d0745SJose E. Roman 
20152e1d0745SJose E. Roman         buffer0[workIlocalp].rank = -1;
20162e1d0745SJose E. Roman       }
20172e1d0745SJose E. Roman     }
20182e1d0745SJose E. Roman     for (p = 0; p < lsize; ++p) buffer1[p].rank = -1;
20192e1d0745SJose E. Roman     for (p = 0; p < *chartSize; ++p) buffer2[p].rank = -1;
20202e1d0745SJose E. Roman     PetscCall(PetscSFReduceBegin(sf, MPIU_SF_NODE, buffer0, buffer1, MPI_MAXLOC));
20212e1d0745SJose E. Roman     PetscCall(PetscSFReduceEnd(sf, MPIU_SF_NODE, buffer0, buffer1, MPI_MAXLOC));
20222e1d0745SJose E. Roman     PetscCall(PetscSFBcastBegin(*distsf, MPIU_SF_NODE, buffer1, buffer2, MPI_REPLACE));
20232e1d0745SJose E. Roman     PetscCall(PetscSFBcastEnd(*distsf, MPIU_SF_NODE, buffer1, buffer2, MPI_REPLACE));
20242e1d0745SJose E. Roman     if (PetscDefined(USE_DEBUG)) {
20252e1d0745SJose E. Roman       for (p = 0; p < *chartSize; ++p) {
20262e1d0745SJose E. Roman         PetscCheck(buffer2[p].rank >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Found negative root rank %" PetscInt_FMT " at local point %" PetscInt_FMT " on rank %d when making migrationSF", buffer2[p].rank, p, rank);
20272e1d0745SJose E. Roman       }
20282e1d0745SJose E. Roman     }
20292e1d0745SJose E. Roman     PetscCall(PetscFree2(buffer0, buffer1));
20302e1d0745SJose E. Roman     PetscCall(DMCreate(comm, distdm));
20312e1d0745SJose E. Roman     PetscCall(DMSetType(*distdm, DMPLEX));
20322e1d0745SJose E. Roman     PetscCall(PetscObjectSetName((PetscObject)*distdm, ((PetscObject)dm)->name));
20332e1d0745SJose E. Roman     PetscCall(DMPlexDistributionSetName(*distdm, distribution_name));
20342e1d0745SJose E. Roman     {
20352e1d0745SJose E. Roman       PetscSF migrationSF;
20362e1d0745SJose E. Roman 
20372e1d0745SJose E. Roman       PetscCall(PetscSFCreate(comm, &migrationSF));
20382e1d0745SJose E. Roman       PetscCall(PetscSFSetFromOptions(migrationSF));
20392e1d0745SJose E. Roman       PetscCall(PetscSFSetGraph(migrationSF, pEnd - pStart, *chartSize, NULL, PETSC_OWN_POINTER, buffer2, PETSC_OWN_POINTER));
20402e1d0745SJose E. Roman       PetscCall(PetscSFSetUp(migrationSF));
20412e1d0745SJose E. Roman       PetscCall(DMPlexMigrate(dm, migrationSF, *distdm));
20422e1d0745SJose E. Roman       PetscCall(PetscSFDestroy(&migrationSF));
20432e1d0745SJose E. Roman     }
20442e1d0745SJose E. Roman   }
20452e1d0745SJose E. Roman   /* Set pointSF */
20462e1d0745SJose E. Roman   {
20472e1d0745SJose E. Roman     PetscSF      pointSF;
20482e1d0745SJose E. Roman     PetscInt    *ilocal, nleaves, q;
20492e1d0745SJose E. Roman     PetscSFNode *iremote, *buffer0, *buffer1;
20502e1d0745SJose E. Roman 
20512e1d0745SJose E. Roman     PetscCall(PetscMalloc2(*chartSize, &buffer0, lsize, &buffer1));
20522e1d0745SJose E. Roman     for (p = 0, nleaves = 0; p < *chartSize; ++p) {
20532e1d0745SJose E. Roman       if (owners[p] == rank) {
20542e1d0745SJose E. Roman         buffer0[p].rank = rank;
20552e1d0745SJose E. Roman       } else {
20562e1d0745SJose E. Roman         buffer0[p].rank = -1;
20572e1d0745SJose E. Roman         nleaves++;
20582e1d0745SJose E. Roman       }
20592e1d0745SJose E. Roman       buffer0[p].index = p;
20602e1d0745SJose E. Roman     }
20612e1d0745SJose E. Roman     for (p = 0; p < lsize; ++p) buffer1[p].rank = -1;
20622e1d0745SJose E. Roman     PetscCall(PetscSFReduceBegin(*distsf, MPIU_SF_NODE, buffer0, buffer1, MPI_MAXLOC));
20632e1d0745SJose E. Roman     PetscCall(PetscSFReduceEnd(*distsf, MPIU_SF_NODE, buffer0, buffer1, MPI_MAXLOC));
20642e1d0745SJose E. Roman     for (p = 0; p < *chartSize; ++p) buffer0[p].rank = -1;
20652e1d0745SJose E. Roman     PetscCall(PetscSFBcastBegin(*distsf, MPIU_SF_NODE, buffer1, buffer0, MPI_REPLACE));
20662e1d0745SJose E. Roman     PetscCall(PetscSFBcastEnd(*distsf, MPIU_SF_NODE, buffer1, buffer0, MPI_REPLACE));
20672e1d0745SJose E. Roman     if (PetscDefined(USE_DEBUG)) {
20682e1d0745SJose E. Roman       for (p = 0; p < *chartSize; ++p) PetscCheck(buffer0[p].rank >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Found negative root rank %" PetscInt_FMT " at local point %" PetscInt_FMT " on rank %d when making pointSF", buffer0[p].rank, p, rank);
20692e1d0745SJose E. Roman     }
20702e1d0745SJose E. Roman     PetscCall(PetscMalloc1(nleaves, &ilocal));
20712e1d0745SJose E. Roman     PetscCall(PetscMalloc1(nleaves, &iremote));
20722e1d0745SJose E. Roman     for (p = 0, q = 0; p < *chartSize; ++p) {
20732e1d0745SJose E. Roman       if (buffer0[p].rank != rank) {
20742e1d0745SJose E. Roman         ilocal[q]        = p;
20752e1d0745SJose E. Roman         iremote[q].rank  = buffer0[p].rank;
20762e1d0745SJose E. Roman         iremote[q].index = buffer0[p].index;
20772e1d0745SJose E. Roman         q++;
20782e1d0745SJose E. Roman       }
20792e1d0745SJose E. Roman     }
20802e1d0745SJose E. Roman     PetscCheck(q == nleaves, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatching leaf sizes: %" PetscInt_FMT " != %" PetscInt_FMT, q, nleaves);
20812e1d0745SJose E. Roman     PetscCall(PetscFree2(buffer0, buffer1));
20822e1d0745SJose E. Roman     PetscCall(PetscSFCreate(comm, &pointSF));
20832e1d0745SJose E. Roman     PetscCall(PetscSFSetFromOptions(pointSF));
20842e1d0745SJose E. Roman     PetscCall(PetscSFSetGraph(pointSF, *chartSize, nleaves, ilocal, PETSC_OWN_POINTER, iremote, PETSC_OWN_POINTER));
20852e1d0745SJose E. Roman     PetscCall(DMSetPointSF(*distdm, pointSF));
20862e1d0745SJose E. Roman     {
20872e1d0745SJose E. Roman       DM cdm;
20882e1d0745SJose E. Roman 
20892e1d0745SJose E. Roman       PetscCall(DMGetCoordinateDM(*distdm, &cdm));
20902e1d0745SJose E. Roman       PetscCall(DMSetPointSF(cdm, pointSF));
20912e1d0745SJose E. Roman     }
20922e1d0745SJose E. Roman     PetscCall(PetscSFDestroy(&pointSF));
20932e1d0745SJose E. Roman   }
20942e1d0745SJose E. Roman   PetscCall(ISRestoreIndices(chartSizesIS, &chartSize));
20952e1d0745SJose E. Roman   PetscCall(ISRestoreIndices(ownersIS, &owners));
20962e1d0745SJose E. Roman   PetscCall(ISRestoreIndices(gpointsIS, &gpoints));
20972e1d0745SJose E. Roman   PetscCall(ISDestroy(&chartSizesIS));
20982e1d0745SJose E. Roman   PetscCall(ISDestroy(&ownersIS));
20992e1d0745SJose E. Roman   PetscCall(ISDestroy(&gpointsIS));
21002e1d0745SJose E. Roman   /* Record that overlap has been manually created.               */
21012e1d0745SJose E. Roman   /* This is to pass `DMPlexCheckPointSF()`, which checks that    */
21022e1d0745SJose E. Roman   /* pointSF does not contain cells in the leaves if overlap = 0. */
21032e1d0745SJose E. Roman   PetscCall(DMPlexSetOverlap_Plex(*distdm, NULL, DMPLEX_OVERLAP_MANUAL));
21042e1d0745SJose E. Roman   PetscCall(DMPlexDistributeSetDefault(*distdm, PETSC_FALSE));
21052e1d0745SJose E. Roman   PetscCall(DMPlexReorderSetDefault(*distdm, DM_REORDER_DEFAULT_FALSE));
21062e1d0745SJose E. Roman   PetscCall(PetscLogEventEnd(DMPLEX_DistributionLoad, viewer, 0, 0, 0));
21072e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
21082e1d0745SJose E. Roman }
21092e1d0745SJose E. Roman 
21102e1d0745SJose E. Roman // Serial load of topology
21112e1d0745SJose E. Roman static PetscErrorCode DMPlexTopologyLoad_HDF5_Legacy_Private(DM dm, PetscViewer viewer, PetscSF *sf)
21122e1d0745SJose E. Roman {
21132e1d0745SJose E. Roman   MPI_Comm        comm;
21142e1d0745SJose E. Roman   const char     *pointsName, *coneSizesName, *conesName, *orientationsName;
21152e1d0745SJose E. Roman   IS              pointsIS, coneSizesIS, conesIS, orientationsIS;
21162e1d0745SJose E. Roman   const PetscInt *points, *coneSizes, *cones, *orientations;
21172e1d0745SJose E. Roman   PetscInt       *cone, *ornt;
21182e1d0745SJose E. Roman   PetscInt        dim, N, Np, pEnd, p, q, maxConeSize = 0, c;
21192e1d0745SJose E. Roman   PetscMPIInt     size, rank;
21202e1d0745SJose E. Roman 
21212e1d0745SJose E. Roman   PetscFunctionBegin;
21222e1d0745SJose E. Roman   pointsName       = "order";
21232e1d0745SJose E. Roman   coneSizesName    = "cones";
21242e1d0745SJose E. Roman   conesName        = "cells";
21252e1d0745SJose E. Roman   orientationsName = "orientation";
21262e1d0745SJose E. Roman   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
21272e1d0745SJose E. Roman   PetscCallMPI(MPI_Comm_size(comm, &size));
21282e1d0745SJose E. Roman   PetscCallMPI(MPI_Comm_rank(comm, &rank));
21292e1d0745SJose E. Roman   PetscCall(ISCreate(comm, &pointsIS));
21302e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)pointsIS, pointsName));
21312e1d0745SJose E. Roman   PetscCall(ISCreate(comm, &coneSizesIS));
21322e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)coneSizesIS, coneSizesName));
21332e1d0745SJose E. Roman   PetscCall(ISCreate(comm, &conesIS));
21342e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)conesIS, conesName));
21352e1d0745SJose E. Roman   PetscCall(ISCreate(comm, &orientationsIS));
21362e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)orientationsIS, orientationsName));
21372e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5ReadObjectAttribute(viewer, (PetscObject)conesIS, "cell_dim", PETSC_INT, NULL, &dim));
21382e1d0745SJose E. Roman   PetscCall(DMSetDimension(dm, dim));
21392e1d0745SJose E. Roman   {
21402e1d0745SJose E. Roman     /* Force serial load */
21412e1d0745SJose E. Roman     PetscCall(PetscInfo(dm, "Loading DM %s in serial\n", dm->hdr.name));
21422e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5ReadSizes(viewer, pointsName, NULL, &Np));
21432e1d0745SJose E. Roman     PetscCall(PetscLayoutSetLocalSize(pointsIS->map, rank == 0 ? Np : 0));
21442e1d0745SJose E. Roman     PetscCall(PetscLayoutSetSize(pointsIS->map, Np));
21452e1d0745SJose E. Roman     pEnd = rank == 0 ? Np : 0;
21462e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5ReadSizes(viewer, coneSizesName, NULL, &Np));
21472e1d0745SJose E. Roman     PetscCall(PetscLayoutSetLocalSize(coneSizesIS->map, rank == 0 ? Np : 0));
21482e1d0745SJose E. Roman     PetscCall(PetscLayoutSetSize(coneSizesIS->map, Np));
21492e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5ReadSizes(viewer, conesName, NULL, &N));
21502e1d0745SJose E. Roman     PetscCall(PetscLayoutSetLocalSize(conesIS->map, rank == 0 ? N : 0));
21512e1d0745SJose E. Roman     PetscCall(PetscLayoutSetSize(conesIS->map, N));
21522e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5ReadSizes(viewer, orientationsName, NULL, &N));
21532e1d0745SJose E. Roman     PetscCall(PetscLayoutSetLocalSize(orientationsIS->map, rank == 0 ? N : 0));
21542e1d0745SJose E. Roman     PetscCall(PetscLayoutSetSize(orientationsIS->map, N));
21552e1d0745SJose E. Roman   }
21562e1d0745SJose E. Roman   PetscCall(ISLoad(pointsIS, viewer));
21572e1d0745SJose E. Roman   PetscCall(ISLoad(coneSizesIS, viewer));
21582e1d0745SJose E. Roman   PetscCall(ISLoad(conesIS, viewer));
21592e1d0745SJose E. Roman   PetscCall(ISLoad(orientationsIS, viewer));
21602e1d0745SJose E. Roman   /* Create Plex */
21612e1d0745SJose E. Roman   PetscCall(DMPlexSetChart(dm, 0, pEnd));
21622e1d0745SJose E. Roman   PetscCall(ISGetIndices(pointsIS, &points));
21632e1d0745SJose E. Roman   PetscCall(ISGetIndices(coneSizesIS, &coneSizes));
21642e1d0745SJose E. Roman   for (p = 0; p < pEnd; ++p) {
21652e1d0745SJose E. Roman     PetscCall(DMPlexSetConeSize(dm, points[p], coneSizes[p]));
21662e1d0745SJose E. Roman     maxConeSize = PetscMax(maxConeSize, coneSizes[p]);
21672e1d0745SJose E. Roman   }
21682e1d0745SJose E. Roman   PetscCall(DMSetUp(dm));
21692e1d0745SJose E. Roman   PetscCall(ISGetIndices(conesIS, &cones));
21702e1d0745SJose E. Roman   PetscCall(ISGetIndices(orientationsIS, &orientations));
21712e1d0745SJose E. Roman   PetscCall(PetscMalloc2(maxConeSize, &cone, maxConeSize, &ornt));
21722e1d0745SJose E. Roman   for (p = 0, q = 0; p < pEnd; ++p) {
21732e1d0745SJose E. Roman     for (c = 0; c < coneSizes[p]; ++c, ++q) {
21742e1d0745SJose E. Roman       cone[c] = cones[q];
21752e1d0745SJose E. Roman       ornt[c] = orientations[q];
21762e1d0745SJose E. Roman     }
21772e1d0745SJose E. Roman     PetscCall(DMPlexSetCone(dm, points[p], cone));
21782e1d0745SJose E. Roman     PetscCall(DMPlexSetConeOrientation(dm, points[p], ornt));
21792e1d0745SJose E. Roman   }
21802e1d0745SJose E. Roman   PetscCall(PetscFree2(cone, ornt));
21812e1d0745SJose E. Roman   /* Create global section migration SF */
21822e1d0745SJose E. Roman   if (sf) {
21832e1d0745SJose E. Roman     PetscLayout layout;
21842e1d0745SJose E. Roman     PetscInt   *globalIndices;
21852e1d0745SJose E. Roman 
21862e1d0745SJose E. Roman     PetscCall(PetscMalloc1(pEnd, &globalIndices));
21872e1d0745SJose E. Roman     /* plex point == globalPointNumber in this case */
21882e1d0745SJose E. Roman     for (p = 0; p < pEnd; ++p) globalIndices[p] = p;
21892e1d0745SJose E. Roman     PetscCall(PetscLayoutCreate(comm, &layout));
21902e1d0745SJose E. Roman     PetscCall(PetscLayoutSetSize(layout, Np));
21912e1d0745SJose E. Roman     PetscCall(PetscLayoutSetBlockSize(layout, 1));
21922e1d0745SJose E. Roman     PetscCall(PetscLayoutSetUp(layout));
21932e1d0745SJose E. Roman     PetscCall(PetscSFCreate(comm, sf));
21942e1d0745SJose E. Roman     PetscCall(PetscSFSetFromOptions(*sf));
21952e1d0745SJose E. Roman     PetscCall(PetscSFSetGraphLayout(*sf, layout, pEnd, NULL, PETSC_OWN_POINTER, globalIndices));
21962e1d0745SJose E. Roman     PetscCall(PetscLayoutDestroy(&layout));
21972e1d0745SJose E. Roman     PetscCall(PetscFree(globalIndices));
21982e1d0745SJose E. Roman   }
21992e1d0745SJose E. Roman   /* Clean-up */
22002e1d0745SJose E. Roman   PetscCall(ISRestoreIndices(pointsIS, &points));
22012e1d0745SJose E. Roman   PetscCall(ISRestoreIndices(coneSizesIS, &coneSizes));
22022e1d0745SJose E. Roman   PetscCall(ISRestoreIndices(conesIS, &cones));
22032e1d0745SJose E. Roman   PetscCall(ISRestoreIndices(orientationsIS, &orientations));
22042e1d0745SJose E. Roman   PetscCall(ISDestroy(&pointsIS));
22052e1d0745SJose E. Roman   PetscCall(ISDestroy(&coneSizesIS));
22062e1d0745SJose E. Roman   PetscCall(ISDestroy(&conesIS));
22072e1d0745SJose E. Roman   PetscCall(ISDestroy(&orientationsIS));
22082e1d0745SJose E. Roman   /* Fill in the rest of the topology structure */
22092e1d0745SJose E. Roman   PetscCall(DMPlexSymmetrize(dm));
22102e1d0745SJose E. Roman   PetscCall(DMPlexStratify(dm));
22112e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
22122e1d0745SJose E. Roman }
22132e1d0745SJose E. Roman 
22142e1d0745SJose E. Roman /* Representation of two DMPlex strata in 0-based global numbering */
22152e1d0745SJose E. Roman struct _n_PlexLayer {
22162e1d0745SJose E. Roman   PetscInt     d;
22172e1d0745SJose E. Roman   IS           conesIS, orientationsIS;
22182e1d0745SJose E. Roman   PetscSection coneSizesSection;
22192e1d0745SJose E. Roman   PetscLayout  vertexLayout;
22202e1d0745SJose E. Roman   PetscSF      overlapSF, l2gSF; //TODO maybe confusing names (in DMPlex in general)
22212e1d0745SJose E. Roman   PetscInt     offset, conesOffset, leafOffset;
22222e1d0745SJose E. Roman };
22232e1d0745SJose E. Roman typedef struct _n_PlexLayer *PlexLayer;
22242e1d0745SJose E. Roman 
22252e1d0745SJose E. Roman static PetscErrorCode PlexLayerDestroy(PlexLayer *layer)
22262e1d0745SJose E. Roman {
22272e1d0745SJose E. Roman   PetscFunctionBegin;
22282e1d0745SJose E. Roman   if (!*layer) PetscFunctionReturn(PETSC_SUCCESS);
22292e1d0745SJose E. Roman   PetscCall(PetscSectionDestroy(&(*layer)->coneSizesSection));
22302e1d0745SJose E. Roman   PetscCall(ISDestroy(&(*layer)->conesIS));
22312e1d0745SJose E. Roman   PetscCall(ISDestroy(&(*layer)->orientationsIS));
22322e1d0745SJose E. Roman   PetscCall(PetscSFDestroy(&(*layer)->overlapSF));
22332e1d0745SJose E. Roman   PetscCall(PetscSFDestroy(&(*layer)->l2gSF));
22342e1d0745SJose E. Roman   PetscCall(PetscLayoutDestroy(&(*layer)->vertexLayout));
22352e1d0745SJose E. Roman   PetscCall(PetscFree(*layer));
22362e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
22372e1d0745SJose E. Roman }
22382e1d0745SJose E. Roman 
22392e1d0745SJose E. Roman static PetscErrorCode PlexLayerCreate_Private(PlexLayer *layer)
22402e1d0745SJose E. Roman {
22412e1d0745SJose E. Roman   PetscFunctionBegin;
22422e1d0745SJose E. Roman   PetscCall(PetscNew(layer));
22432e1d0745SJose E. Roman   (*layer)->d           = -1;
22442e1d0745SJose E. Roman   (*layer)->offset      = -1;
22452e1d0745SJose E. Roman   (*layer)->conesOffset = -1;
22462e1d0745SJose E. Roman   (*layer)->leafOffset  = -1;
22472e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
22482e1d0745SJose E. Roman }
22492e1d0745SJose E. Roman 
22502e1d0745SJose E. Roman // Parallel load of a depth stratum
22512e1d0745SJose E. Roman static PetscErrorCode PlexLayerLoad_Private(PlexLayer layer, PetscViewer viewer, PetscInt d, PetscLayout pointsLayout)
22522e1d0745SJose E. Roman {
22532e1d0745SJose E. Roman   char         path[128];
22542e1d0745SJose E. Roman   MPI_Comm     comm;
22552e1d0745SJose E. Roman   const char  *coneSizesName, *conesName, *orientationsName;
22562e1d0745SJose E. Roman   IS           coneSizesIS, conesIS, orientationsIS;
22572e1d0745SJose E. Roman   PetscSection coneSizesSection;
22582e1d0745SJose E. Roman   PetscLayout  vertexLayout = NULL;
22592e1d0745SJose E. Roman   PetscInt     s;
22602e1d0745SJose E. Roman 
22612e1d0745SJose E. Roman   PetscFunctionBegin;
22622e1d0745SJose E. Roman   coneSizesName    = "cone_sizes";
22632e1d0745SJose E. Roman   conesName        = "cones";
22642e1d0745SJose E. Roman   orientationsName = "orientations";
22652e1d0745SJose E. Roman   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
22662e1d0745SJose E. Roman 
22672e1d0745SJose E. Roman   /* query size of next lower depth stratum (next lower dimension) */
22682e1d0745SJose E. Roman   if (d > 0) {
22692e1d0745SJose E. Roman     PetscInt NVertices;
22702e1d0745SJose E. Roman 
22712e1d0745SJose E. Roman     PetscCall(PetscSNPrintf(path, sizeof(path), "%" PetscInt_FMT "/%s", d - 1, coneSizesName));
22722e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5ReadSizes(viewer, path, NULL, &NVertices));
22732e1d0745SJose E. Roman     PetscCall(PetscLayoutCreate(comm, &vertexLayout));
22742e1d0745SJose E. Roman     PetscCall(PetscLayoutSetSize(vertexLayout, NVertices));
22752e1d0745SJose E. Roman     PetscCall(PetscLayoutSetUp(vertexLayout));
22762e1d0745SJose E. Roman   }
22772e1d0745SJose E. Roman 
22782e1d0745SJose E. Roman   PetscCall(PetscSNPrintf(path, sizeof(path), "%" PetscInt_FMT, d));
22792e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, path));
22802e1d0745SJose E. Roman 
22812e1d0745SJose E. Roman   /* create coneSizesSection from stored IS coneSizes */
22822e1d0745SJose E. Roman   {
22832e1d0745SJose E. Roman     const PetscInt *coneSizes;
22842e1d0745SJose E. Roman 
22852e1d0745SJose E. Roman     PetscCall(ISCreate(comm, &coneSizesIS));
22862e1d0745SJose E. Roman     PetscCall(PetscObjectSetName((PetscObject)coneSizesIS, coneSizesName));
22872e1d0745SJose E. Roman     if (pointsLayout) PetscCall(ISSetLayout(coneSizesIS, pointsLayout));
22882e1d0745SJose E. Roman     PetscCall(ISLoad(coneSizesIS, viewer));
22892e1d0745SJose E. Roman     if (!pointsLayout) PetscCall(ISGetLayout(coneSizesIS, &pointsLayout));
22902e1d0745SJose E. Roman     PetscCall(ISGetIndices(coneSizesIS, &coneSizes));
22912e1d0745SJose E. Roman     PetscCall(PetscSectionCreate(comm, &coneSizesSection));
22922e1d0745SJose E. Roman     //TODO different start ?
22932e1d0745SJose E. Roman     PetscCall(PetscSectionSetChart(coneSizesSection, 0, pointsLayout->n));
22942e1d0745SJose E. Roman     for (s = 0; s < pointsLayout->n; ++s) PetscCall(PetscSectionSetDof(coneSizesSection, s, coneSizes[s]));
22952e1d0745SJose E. Roman     PetscCall(PetscSectionSetUp(coneSizesSection));
22962e1d0745SJose E. Roman     PetscCall(ISRestoreIndices(coneSizesIS, &coneSizes));
22972e1d0745SJose E. Roman     {
22982e1d0745SJose E. Roman       PetscLayout tmp = NULL;
22992e1d0745SJose E. Roman 
23002e1d0745SJose E. Roman       /* We need to keep the layout until the end of function */
23012e1d0745SJose E. Roman       PetscCall(PetscLayoutReference((PetscLayout)pointsLayout, &tmp));
23022e1d0745SJose E. Roman     }
23032e1d0745SJose E. Roman     PetscCall(ISDestroy(&coneSizesIS));
23042e1d0745SJose E. Roman   }
23052e1d0745SJose E. Roman 
23062e1d0745SJose E. Roman   /* use value layout of coneSizesSection as layout of cones and orientations */
23072e1d0745SJose E. Roman   {
23082e1d0745SJose E. Roman     PetscLayout conesLayout;
23092e1d0745SJose E. Roman 
23102e1d0745SJose E. Roman     PetscCall(PetscSectionGetValueLayout(comm, coneSizesSection, &conesLayout));
23112e1d0745SJose E. Roman     PetscCall(ISCreate(comm, &conesIS));
23122e1d0745SJose E. Roman     PetscCall(ISCreate(comm, &orientationsIS));
23132e1d0745SJose E. Roman     PetscCall(PetscObjectSetName((PetscObject)conesIS, conesName));
23142e1d0745SJose E. Roman     PetscCall(PetscObjectSetName((PetscObject)orientationsIS, orientationsName));
23152e1d0745SJose E. Roman     PetscCall(PetscLayoutDuplicate(conesLayout, &conesIS->map));
23162e1d0745SJose E. Roman     PetscCall(PetscLayoutDuplicate(conesLayout, &orientationsIS->map));
23172e1d0745SJose E. Roman     PetscCall(ISLoad(conesIS, viewer));
23182e1d0745SJose E. Roman     PetscCall(ISLoad(orientationsIS, viewer));
23192e1d0745SJose E. Roman     PetscCall(PetscLayoutDestroy(&conesLayout));
23202e1d0745SJose E. Roman   }
23212e1d0745SJose E. Roman 
23222e1d0745SJose E. Roman   /* check assertion that layout of points is the same as point layout of coneSizesSection */
23232e1d0745SJose E. Roman   {
23242e1d0745SJose E. Roman     PetscLayout pointsLayout0;
23252e1d0745SJose E. Roman     PetscBool   flg;
23262e1d0745SJose E. Roman 
23272e1d0745SJose E. Roman     PetscCall(PetscSectionGetPointLayout(comm, coneSizesSection, &pointsLayout0));
23282e1d0745SJose E. Roman     PetscCall(PetscLayoutCompare(pointsLayout, pointsLayout0, &flg));
23292e1d0745SJose E. Roman     PetscCheck(flg, comm, PETSC_ERR_PLIB, "points layout != coneSizesSection point layout");
23302e1d0745SJose E. Roman     PetscCall(PetscLayoutDestroy(&pointsLayout0));
23312e1d0745SJose E. Roman   }
23322e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
23332e1d0745SJose E. Roman   PetscCall(PetscLayoutDestroy(&pointsLayout));
23342e1d0745SJose E. Roman 
23352e1d0745SJose E. Roman   layer->d                = d;
23362e1d0745SJose E. Roman   layer->conesIS          = conesIS;
23372e1d0745SJose E. Roman   layer->coneSizesSection = coneSizesSection;
23382e1d0745SJose E. Roman   layer->orientationsIS   = orientationsIS;
23392e1d0745SJose E. Roman   layer->vertexLayout     = vertexLayout;
23402e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
23412e1d0745SJose E. Roman }
23422e1d0745SJose E. Roman 
23432e1d0745SJose E. Roman static PetscErrorCode PlexLayerDistribute_Private(PlexLayer layer, PetscSF cellLocalToGlobalSF)
23442e1d0745SJose E. Roman {
23452e1d0745SJose E. Roman   IS           newConesIS, newOrientationsIS;
23462e1d0745SJose E. Roman   PetscSection newConeSizesSection;
23472e1d0745SJose E. Roman   MPI_Comm     comm;
23482e1d0745SJose E. Roman 
23492e1d0745SJose E. Roman   PetscFunctionBegin;
23502e1d0745SJose E. Roman   PetscCall(PetscObjectGetComm((PetscObject)cellLocalToGlobalSF, &comm));
23512e1d0745SJose E. Roman   PetscCall(PetscSectionCreate(comm, &newConeSizesSection));
23522e1d0745SJose E. Roman   //TODO rename to something like ISDistribute() with optional PetscSection argument
23532e1d0745SJose E. Roman   PetscCall(DMPlexDistributeFieldIS(NULL, cellLocalToGlobalSF, layer->coneSizesSection, layer->conesIS, newConeSizesSection, &newConesIS));
23542e1d0745SJose E. Roman   PetscCall(DMPlexDistributeFieldIS(NULL, cellLocalToGlobalSF, layer->coneSizesSection, layer->orientationsIS, newConeSizesSection, &newOrientationsIS));
23552e1d0745SJose E. Roman 
23562e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)newConeSizesSection, ((PetscObject)layer->coneSizesSection)->name));
23572e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)newConesIS, ((PetscObject)layer->conesIS)->name));
23582e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)newOrientationsIS, ((PetscObject)layer->orientationsIS)->name));
23592e1d0745SJose E. Roman   PetscCall(PetscSectionDestroy(&layer->coneSizesSection));
23602e1d0745SJose E. Roman   PetscCall(ISDestroy(&layer->conesIS));
23612e1d0745SJose E. Roman   PetscCall(ISDestroy(&layer->orientationsIS));
23622e1d0745SJose E. Roman   layer->coneSizesSection = newConeSizesSection;
23632e1d0745SJose E. Roman   layer->conesIS          = newConesIS;
23642e1d0745SJose E. Roman   layer->orientationsIS   = newOrientationsIS;
23652e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
23662e1d0745SJose E. Roman }
23672e1d0745SJose E. Roman 
23682e1d0745SJose E. Roman //TODO share code with DMPlexBuildFromCellListParallel()
23692e1d0745SJose E. Roman #include <petsc/private/hashseti.h>
23702e1d0745SJose E. Roman static PetscErrorCode PlexLayerCreateSFs_Private(PlexLayer layer, PetscSF *vertexOverlapSF, PetscSF *sfXC)
23712e1d0745SJose E. Roman {
23722e1d0745SJose E. Roman   PetscLayout     vertexLayout     = layer->vertexLayout;
23732e1d0745SJose E. Roman   PetscSection    coneSection      = layer->coneSizesSection;
23742e1d0745SJose E. Roman   IS              cellVertexData   = layer->conesIS;
23752e1d0745SJose E. Roman   IS              coneOrientations = layer->orientationsIS;
23762e1d0745SJose E. Roman   PetscSF         vl2gSF, vOverlapSF;
23772e1d0745SJose E. Roman   PetscInt       *verticesAdj;
23782e1d0745SJose E. Roman   PetscInt        i, n, numVerticesAdj;
23792e1d0745SJose E. Roman   const PetscInt *cvd, *co = NULL;
23802e1d0745SJose E. Roman   MPI_Comm        comm;
23812e1d0745SJose E. Roman 
23822e1d0745SJose E. Roman   PetscFunctionBegin;
23832e1d0745SJose E. Roman   PetscCall(PetscObjectGetComm((PetscObject)coneSection, &comm));
23842e1d0745SJose E. Roman   PetscCall(PetscSectionGetStorageSize(coneSection, &n));
23852e1d0745SJose E. Roman   {
23862e1d0745SJose E. Roman     PetscInt n0;
23872e1d0745SJose E. Roman 
23882e1d0745SJose E. Roman     PetscCall(ISGetLocalSize(cellVertexData, &n0));
23892e1d0745SJose E. Roman     PetscCheck(n == n0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Local size of IS cellVertexData = %" PetscInt_FMT " != %" PetscInt_FMT " = storage size of PetscSection coneSection", n0, n);
23902e1d0745SJose E. Roman     PetscCall(ISGetIndices(cellVertexData, &cvd));
23912e1d0745SJose E. Roman   }
23922e1d0745SJose E. Roman   if (coneOrientations) {
23932e1d0745SJose E. Roman     PetscInt n0;
23942e1d0745SJose E. Roman 
23952e1d0745SJose E. Roman     PetscCall(ISGetLocalSize(coneOrientations, &n0));
23962e1d0745SJose E. Roman     PetscCheck(n == n0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Local size of IS coneOrientations = %" PetscInt_FMT " != %" PetscInt_FMT " = storage size of PetscSection coneSection", n0, n);
23972e1d0745SJose E. Roman     PetscCall(ISGetIndices(coneOrientations, &co));
23982e1d0745SJose E. Roman   }
23992e1d0745SJose E. Roman   /* Get/check global number of vertices */
24002e1d0745SJose E. Roman   {
24012e1d0745SJose E. Roman     PetscInt NVerticesInCells = PETSC_INT_MIN;
24022e1d0745SJose E. Roman 
24032e1d0745SJose E. Roman     /* NVerticesInCells = max(cellVertexData) + 1 */
24042e1d0745SJose E. Roman     for (i = 0; i < n; i++)
24052e1d0745SJose E. Roman       if (cvd[i] > NVerticesInCells) NVerticesInCells = cvd[i];
24062e1d0745SJose E. Roman     ++NVerticesInCells;
24072e1d0745SJose E. Roman     PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, comm));
24082e1d0745SJose E. Roman 
24092e1d0745SJose E. Roman     if (vertexLayout->n == PETSC_DECIDE && vertexLayout->N == PETSC_DECIDE) vertexLayout->N = NVerticesInCells;
24102e1d0745SJose E. Roman     else
24112e1d0745SJose E. Roman       PetscCheck(vertexLayout->N == PETSC_DECIDE || vertexLayout->N >= NVerticesInCells, comm, PETSC_ERR_ARG_SIZ, "Specified global number of vertices %" PetscInt_FMT " must be greater than or equal to the number of unique vertices in the cell-vertex dataset %" PetscInt_FMT,
24122e1d0745SJose E. Roman                  vertexLayout->N, NVerticesInCells);
24132e1d0745SJose E. Roman     PetscCall(PetscLayoutSetUp(vertexLayout));
24142e1d0745SJose E. Roman   }
24152e1d0745SJose E. Roman   /* Find locally unique vertices in cellVertexData */
24162e1d0745SJose E. Roman   {
24172e1d0745SJose E. Roman     PetscHSetI vhash;
24182e1d0745SJose E. Roman     PetscInt   off = 0;
24192e1d0745SJose E. Roman 
24202e1d0745SJose E. Roman     PetscCall(PetscHSetICreate(&vhash));
24212e1d0745SJose E. Roman     for (i = 0; i < n; ++i) PetscCall(PetscHSetIAdd(vhash, cvd[i]));
24222e1d0745SJose E. Roman     PetscCall(PetscHSetIGetSize(vhash, &numVerticesAdj));
24232e1d0745SJose E. Roman     PetscCall(PetscMalloc1(numVerticesAdj, &verticesAdj));
24242e1d0745SJose E. Roman     PetscCall(PetscHSetIGetElems(vhash, &off, verticesAdj));
24252e1d0745SJose E. Roman     PetscAssert(off == numVerticesAdj, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Assertion failed: off == numVerticesAdj (%" PetscInt_FMT " != %" PetscInt_FMT ")", off, numVerticesAdj);
24262e1d0745SJose E. Roman     PetscCall(PetscHSetIDestroy(&vhash));
24272e1d0745SJose E. Roman   }
24282e1d0745SJose E. Roman   /* We must sort vertices to preserve numbering */
24292e1d0745SJose E. Roman   PetscCall(PetscSortInt(numVerticesAdj, verticesAdj));
24302e1d0745SJose E. Roman   /* Connect locally unique vertices with star forest */
24312e1d0745SJose E. Roman   PetscCall(PetscSFCreateByMatchingIndices(vertexLayout, numVerticesAdj, verticesAdj, NULL, 0, numVerticesAdj, verticesAdj, NULL, 0, &vl2gSF, &vOverlapSF));
24322e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)vOverlapSF, "overlapSF"));
24332e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)vl2gSF, "localToGlobalSF"));
24342e1d0745SJose E. Roman 
24352e1d0745SJose E. Roman   PetscCall(PetscFree(verticesAdj));
24362e1d0745SJose E. Roman   *vertexOverlapSF = vOverlapSF;
24372e1d0745SJose E. Roman   *sfXC            = vl2gSF;
24382e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
24392e1d0745SJose E. Roman }
24402e1d0745SJose E. Roman 
24412e1d0745SJose E. Roman static PetscErrorCode PlexLayerCreateCellSFs_Private(PlexLayer layer, PetscSF *cellOverlapSF, PetscSF *cellLocalToGlobalSF)
24422e1d0745SJose E. Roman {
24432e1d0745SJose E. Roman   PetscSection coneSection = layer->coneSizesSection;
24442e1d0745SJose E. Roman   PetscInt     nCells;
24452e1d0745SJose E. Roman   MPI_Comm     comm;
24462e1d0745SJose E. Roman 
24472e1d0745SJose E. Roman   PetscFunctionBegin;
24482e1d0745SJose E. Roman   PetscCall(PetscObjectGetComm((PetscObject)coneSection, &comm));
24492e1d0745SJose E. Roman   {
24502e1d0745SJose E. Roman     PetscInt cStart;
24512e1d0745SJose E. Roman 
24522e1d0745SJose E. Roman     PetscCall(PetscSectionGetChart(coneSection, &cStart, &nCells));
24532e1d0745SJose E. Roman     PetscCheck(cStart == 0, comm, PETSC_ERR_ARG_OUTOFRANGE, "coneSection must start at 0");
24542e1d0745SJose E. Roman   }
24552e1d0745SJose E. Roman   /* Create overlapSF as empty SF with the right number of roots */
24562e1d0745SJose E. Roman   PetscCall(PetscSFCreate(comm, cellOverlapSF));
24572e1d0745SJose E. Roman   PetscCall(PetscSFSetGraph(*cellOverlapSF, nCells, 0, NULL, PETSC_USE_POINTER, NULL, PETSC_USE_POINTER));
24582e1d0745SJose E. Roman   PetscCall(PetscSFSetUp(*cellOverlapSF));
24592e1d0745SJose E. Roman   /* Create localToGlobalSF as identity mapping */
24602e1d0745SJose E. Roman   {
24612e1d0745SJose E. Roman     PetscLayout map;
24622e1d0745SJose E. Roman 
24632e1d0745SJose E. Roman     PetscCall(PetscLayoutCreateFromSizes(comm, nCells, PETSC_DECIDE, 1, &map));
24642e1d0745SJose E. Roman     PetscCall(PetscSFCreateFromLayouts(map, map, cellLocalToGlobalSF));
24652e1d0745SJose E. Roman     PetscCall(PetscSFSetUp(*cellLocalToGlobalSF));
24662e1d0745SJose E. Roman     PetscCall(PetscLayoutDestroy(&map));
24672e1d0745SJose E. Roman   }
24682e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
24692e1d0745SJose E. Roman }
24702e1d0745SJose E. Roman 
24712e1d0745SJose E. Roman static PetscErrorCode DMPlexTopologyBuildFromLayers_Private(DM dm, PetscInt depth, PlexLayer *layers, IS strataPermutation)
24722e1d0745SJose E. Roman {
24732e1d0745SJose E. Roman   const PetscInt *permArr;
24742e1d0745SJose E. Roman   PetscInt        d, nPoints;
24752e1d0745SJose E. Roman   MPI_Comm        comm;
24762e1d0745SJose E. Roman 
24772e1d0745SJose E. Roman   PetscFunctionBegin;
24782e1d0745SJose E. Roman   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
24792e1d0745SJose E. Roman   PetscCall(ISGetIndices(strataPermutation, &permArr));
24802e1d0745SJose E. Roman 
24812e1d0745SJose E. Roman   /* Count points, strata offsets and cones offsets (taking strataPermutation into account) */
24822e1d0745SJose E. Roman   {
24832e1d0745SJose E. Roman     PetscInt stratumOffset = 0;
24842e1d0745SJose E. Roman     PetscInt conesOffset   = 0;
24852e1d0745SJose E. Roman 
24862e1d0745SJose E. Roman     for (d = 0; d <= depth; d++) {
24872e1d0745SJose E. Roman       const PetscInt  e = permArr[d];
24882e1d0745SJose E. Roman       const PlexLayer l = layers[e];
24892e1d0745SJose E. Roman       PetscInt        lo, n, size;
24902e1d0745SJose E. Roman 
24912e1d0745SJose E. Roman       PetscCall(PetscSectionGetChart(l->coneSizesSection, &lo, &n));
24922e1d0745SJose E. Roman       PetscCall(PetscSectionGetStorageSize(l->coneSizesSection, &size));
24932e1d0745SJose E. Roman       PetscCheck(lo == 0, comm, PETSC_ERR_PLIB, "starting point should be 0 in coneSizesSection %" PetscInt_FMT, d);
24942e1d0745SJose E. Roman       l->offset      = stratumOffset;
24952e1d0745SJose E. Roman       l->conesOffset = conesOffset;
24962e1d0745SJose E. Roman       stratumOffset += n;
24972e1d0745SJose E. Roman       conesOffset += size;
24982e1d0745SJose E. Roman     }
24992e1d0745SJose E. Roman     nPoints = stratumOffset;
25002e1d0745SJose E. Roman   }
25012e1d0745SJose E. Roman 
25022e1d0745SJose E. Roman   /* Set interval for all plex points */
25032e1d0745SJose E. Roman   //TODO we should store starting point of plex
25042e1d0745SJose E. Roman   PetscCall(DMPlexSetChart(dm, 0, nPoints));
25052e1d0745SJose E. Roman 
25062e1d0745SJose E. Roman   /* Set up plex coneSection from layer coneSections */
25072e1d0745SJose E. Roman   {
25082e1d0745SJose E. Roman     PetscSection coneSection;
25092e1d0745SJose E. Roman 
25102e1d0745SJose E. Roman     PetscCall(DMPlexGetConeSection(dm, &coneSection));
25112e1d0745SJose E. Roman     for (d = 0; d <= depth; d++) {
25122e1d0745SJose E. Roman       const PlexLayer l = layers[d];
25132e1d0745SJose E. Roman       PetscInt        n, q;
25142e1d0745SJose E. Roman 
25152e1d0745SJose E. Roman       PetscCall(PetscSectionGetChart(l->coneSizesSection, NULL, &n));
25162e1d0745SJose E. Roman       for (q = 0; q < n; q++) {
25172e1d0745SJose E. Roman         const PetscInt p = l->offset + q;
25182e1d0745SJose E. Roman         PetscInt       coneSize;
25192e1d0745SJose E. Roman 
25202e1d0745SJose E. Roman         PetscCall(PetscSectionGetDof(l->coneSizesSection, q, &coneSize));
25212e1d0745SJose E. Roman         PetscCall(PetscSectionSetDof(coneSection, p, coneSize));
25222e1d0745SJose E. Roman       }
25232e1d0745SJose E. Roman     }
25242e1d0745SJose E. Roman   }
25252e1d0745SJose E. Roman   //TODO this is terrible, DMSetUp_Plex() should be DMPlexSetUpSections() or so
25262e1d0745SJose E. Roman   PetscCall(DMSetUp(dm));
25272e1d0745SJose E. Roman 
25282e1d0745SJose E. Roman   /* Renumber cones points from layer-global numbering to plex-local numbering */
25292e1d0745SJose E. Roman   {
25302e1d0745SJose E. Roman     PetscInt *cones, *ornts;
25312e1d0745SJose E. Roman 
25322e1d0745SJose E. Roman     PetscCall(DMPlexGetCones(dm, &cones));
25332e1d0745SJose E. Roman     PetscCall(DMPlexGetConeOrientations(dm, &ornts));
25342e1d0745SJose E. Roman     for (d = 1; d <= depth; d++) {
25352e1d0745SJose E. Roman       const PlexLayer l = layers[d];
25362e1d0745SJose E. Roman       PetscInt        i, lConesSize;
25372e1d0745SJose E. Roman       PetscInt       *lCones;
25382e1d0745SJose E. Roman       const PetscInt *lOrnts;
25392e1d0745SJose E. Roman       PetscInt       *pCones = &cones[l->conesOffset];
25402e1d0745SJose E. Roman       PetscInt       *pOrnts = &ornts[l->conesOffset];
25412e1d0745SJose E. Roman 
25422e1d0745SJose E. Roman       PetscCall(PetscSectionGetStorageSize(l->coneSizesSection, &lConesSize));
25432e1d0745SJose E. Roman       /* Get cones in local plex numbering */
25442e1d0745SJose E. Roman       {
25452e1d0745SJose E. Roman         ISLocalToGlobalMapping l2g;
25462e1d0745SJose E. Roman         PetscLayout            vertexLayout = l->vertexLayout;
25472e1d0745SJose E. Roman         PetscSF                vertexSF     = layers[d - 1]->l2gSF; /* vertices of this layer are cells of previous layer */
25482e1d0745SJose E. Roman         const PetscInt        *gCones;
25492e1d0745SJose E. Roman         PetscInt               lConesSize0;
25502e1d0745SJose E. Roman 
25512e1d0745SJose E. Roman         PetscCall(ISGetLocalSize(l->conesIS, &lConesSize0));
25522e1d0745SJose E. Roman         PetscCheck(lConesSize0 == lConesSize, comm, PETSC_ERR_PLIB, "layer %" PetscInt_FMT " size(conesIS) = %" PetscInt_FMT " != %" PetscInt_FMT " = storageSize(coneSizesSection)", d, lConesSize0, lConesSize);
25532e1d0745SJose E. Roman         PetscCall(ISGetLocalSize(l->orientationsIS, &lConesSize0));
25542e1d0745SJose E. Roman         PetscCheck(lConesSize0 == lConesSize, comm, PETSC_ERR_PLIB, "layer %" PetscInt_FMT " size(orientationsIS) = %" PetscInt_FMT " != %" PetscInt_FMT " = storageSize(coneSizesSection)", d, lConesSize0, lConesSize);
25552e1d0745SJose E. Roman 
25562e1d0745SJose E. Roman         PetscCall(PetscMalloc1(lConesSize, &lCones));
25572e1d0745SJose E. Roman         PetscCall(ISGetIndices(l->conesIS, &gCones));
25582e1d0745SJose E. Roman         PetscCall(ISLocalToGlobalMappingCreateSF(vertexSF, vertexLayout->rstart, &l2g));
25592e1d0745SJose E. Roman         PetscCall(ISGlobalToLocalMappingApply(l2g, IS_GTOLM_MASK, lConesSize, gCones, &lConesSize0, lCones));
25602e1d0745SJose E. Roman         PetscCheck(lConesSize0 == lConesSize, comm, PETSC_ERR_PLIB, "global to local does not cover all indices (%" PetscInt_FMT " of %" PetscInt_FMT ")", lConesSize0, lConesSize);
25612e1d0745SJose E. Roman         PetscCall(ISLocalToGlobalMappingDestroy(&l2g));
25622e1d0745SJose E. Roman         PetscCall(ISRestoreIndices(l->conesIS, &gCones));
25632e1d0745SJose E. Roman       }
25642e1d0745SJose E. Roman       PetscCall(ISGetIndices(l->orientationsIS, &lOrnts));
25652e1d0745SJose E. Roman       /* Set cones, need to add stratum offset */
25662e1d0745SJose E. Roman       for (i = 0; i < lConesSize; i++) {
25672e1d0745SJose E. Roman         pCones[i] = lCones[i] + layers[d - 1]->offset; /* cone points of current layer are points of previous layer */
25682e1d0745SJose E. Roman         pOrnts[i] = lOrnts[i];
25692e1d0745SJose E. Roman       }
25702e1d0745SJose E. Roman       PetscCall(PetscFree(lCones));
25712e1d0745SJose E. Roman       PetscCall(ISRestoreIndices(l->orientationsIS, &lOrnts));
25722e1d0745SJose E. Roman     }
25732e1d0745SJose E. Roman   }
25742e1d0745SJose E. Roman   PetscCall(DMPlexSymmetrize(dm));
25752e1d0745SJose E. Roman   PetscCall(DMPlexStratify(dm));
25762e1d0745SJose E. Roman   PetscCall(ISRestoreIndices(strataPermutation, &permArr));
25772e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
25782e1d0745SJose E. Roman }
25792e1d0745SJose E. Roman 
25802e1d0745SJose E. Roman static PetscErrorCode PlexLayerConcatenateSFs_Private(MPI_Comm comm, PetscInt depth, PlexLayer layers[], IS strataPermutation, PetscSF *overlapSF, PetscSF *l2gSF)
25812e1d0745SJose E. Roman {
25822e1d0745SJose E. Roman   PetscInt        d;
25832e1d0745SJose E. Roman   PetscSF        *osfs, *lsfs;
25842e1d0745SJose E. Roman   PetscInt       *leafOffsets;
25852e1d0745SJose E. Roman   const PetscInt *permArr;
25862e1d0745SJose E. Roman 
25872e1d0745SJose E. Roman   PetscFunctionBegin;
25882e1d0745SJose E. Roman   PetscCall(ISGetIndices(strataPermutation, &permArr));
25892e1d0745SJose E. Roman   PetscCall(PetscCalloc3(depth + 1, &osfs, depth + 1, &lsfs, depth + 1, &leafOffsets));
25902e1d0745SJose E. Roman   for (d = 0; d <= depth; d++) {
25912e1d0745SJose E. Roman     const PetscInt e = permArr[d];
25922e1d0745SJose E. Roman 
25932e1d0745SJose E. Roman     PetscAssert(e == layers[e]->d, PETSC_COMM_SELF, PETSC_ERR_PLIB, "assertion: e == layers[e]->d");
25942e1d0745SJose E. Roman     osfs[d]        = layers[e]->overlapSF;
25952e1d0745SJose E. Roman     lsfs[d]        = layers[e]->l2gSF;
25962e1d0745SJose E. Roman     leafOffsets[d] = layers[e]->offset;
25972e1d0745SJose E. Roman   }
25982e1d0745SJose E. Roman   PetscCall(PetscSFConcatenate(comm, depth + 1, osfs, PETSCSF_CONCATENATE_ROOTMODE_LOCAL, leafOffsets, overlapSF));
25992e1d0745SJose E. Roman   PetscCall(PetscSFConcatenate(comm, depth + 1, lsfs, PETSCSF_CONCATENATE_ROOTMODE_GLOBAL, leafOffsets, l2gSF));
26002e1d0745SJose E. Roman   PetscCall(PetscFree3(osfs, lsfs, leafOffsets));
26012e1d0745SJose E. Roman   PetscCall(ISRestoreIndices(strataPermutation, &permArr));
26022e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
26032e1d0745SJose E. Roman }
26042e1d0745SJose E. Roman 
26052e1d0745SJose E. Roman // Parallel load of topology
26062e1d0745SJose E. Roman static PetscErrorCode DMPlexTopologyLoad_HDF5_Private(DM dm, PetscViewer viewer, PetscSF *sfXC)
26072e1d0745SJose E. Roman {
26082e1d0745SJose E. Roman   PlexLayer  *layers;
26092e1d0745SJose E. Roman   IS          strataPermutation;
26102e1d0745SJose E. Roman   PetscLayout pointsLayout;
26112e1d0745SJose E. Roman   PetscInt    depth;
26122e1d0745SJose E. Roman   PetscInt    d;
26132e1d0745SJose E. Roman   MPI_Comm    comm;
26142e1d0745SJose E. Roman 
26152e1d0745SJose E. Roman   PetscFunctionBegin;
26162e1d0745SJose E. Roman   {
26172e1d0745SJose E. Roman     PetscInt dim;
26182e1d0745SJose E. Roman 
26192e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5ReadAttribute(viewer, NULL, "depth", PETSC_INT, NULL, &depth));
26202e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5ReadAttribute(viewer, NULL, "cell_dim", PETSC_INT, NULL, &dim));
26212e1d0745SJose E. Roman     PetscCall(DMSetDimension(dm, dim));
26222e1d0745SJose E. Roman   }
26232e1d0745SJose E. Roman   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
26242e1d0745SJose E. Roman 
26252e1d0745SJose E. Roman   PetscCall(PetscInfo(dm, "Loading DM %s in parallel\n", dm->hdr.name));
26262e1d0745SJose E. Roman   {
26272e1d0745SJose E. Roman     IS spOnComm;
26282e1d0745SJose E. Roman 
26292e1d0745SJose E. Roman     PetscCall(ISCreate(comm, &spOnComm));
26302e1d0745SJose E. Roman     PetscCall(PetscObjectSetName((PetscObject)spOnComm, "permutation"));
26312e1d0745SJose E. Roman     PetscCall(ISLoad(spOnComm, viewer));
26322e1d0745SJose E. Roman     /* have the same serial IS on every rank */
26332e1d0745SJose E. Roman     PetscCall(ISAllGather(spOnComm, &strataPermutation));
26342e1d0745SJose E. Roman     PetscCall(PetscObjectSetName((PetscObject)strataPermutation, ((PetscObject)spOnComm)->name));
26352e1d0745SJose E. Roman     PetscCall(ISDestroy(&spOnComm));
26362e1d0745SJose E. Roman   }
26372e1d0745SJose E. Roman 
26382e1d0745SJose E. Roman   /* Create layers, load raw data for each layer */
26392e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "strata"));
26402e1d0745SJose E. Roman   PetscCall(PetscMalloc1(depth + 1, &layers));
26412e1d0745SJose E. Roman   for (d = depth, pointsLayout = NULL; d >= 0; pointsLayout = layers[d]->vertexLayout, d--) {
26422e1d0745SJose E. Roman     PetscCall(PlexLayerCreate_Private(&layers[d]));
26432e1d0745SJose E. Roman     PetscCall(PlexLayerLoad_Private(layers[d], viewer, d, pointsLayout));
26442e1d0745SJose E. Roman   }
26452e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer)); /* strata */
26462e1d0745SJose E. Roman 
26472e1d0745SJose E. Roman   for (d = depth; d >= 0; d--) {
26482e1d0745SJose E. Roman     /* Redistribute cells and vertices for each applicable layer */
26492e1d0745SJose E. Roman     if (d < depth) PetscCall(PlexLayerDistribute_Private(layers[d], layers[d]->l2gSF));
26502e1d0745SJose E. Roman     /* Create vertex overlap SF and vertex localToGlobal SF for each applicable layer */
26512e1d0745SJose E. Roman     if (d > 0) PetscCall(PlexLayerCreateSFs_Private(layers[d], &layers[d - 1]->overlapSF, &layers[d - 1]->l2gSF));
26522e1d0745SJose E. Roman   }
26532e1d0745SJose E. Roman   /* Build trivial SFs for the cell layer as well */
26542e1d0745SJose E. Roman   PetscCall(PlexLayerCreateCellSFs_Private(layers[depth], &layers[depth]->overlapSF, &layers[depth]->l2gSF));
26552e1d0745SJose E. Roman 
26562e1d0745SJose E. Roman   /* Build DMPlex topology from the layers */
26572e1d0745SJose E. Roman   PetscCall(DMPlexTopologyBuildFromLayers_Private(dm, depth, layers, strataPermutation));
26582e1d0745SJose E. Roman 
26592e1d0745SJose E. Roman   /* Build overall point SF alias overlap SF */
26602e1d0745SJose E. Roman   {
26612e1d0745SJose E. Roman     PetscSF overlapSF;
26622e1d0745SJose E. Roman 
26632e1d0745SJose E. Roman     PetscCall(PlexLayerConcatenateSFs_Private(comm, depth, layers, strataPermutation, &overlapSF, sfXC));
26642e1d0745SJose E. Roman     PetscCall(DMSetPointSF(dm, overlapSF));
26652e1d0745SJose E. Roman     PetscCall(PetscSFDestroy(&overlapSF));
26662e1d0745SJose E. Roman   }
26672e1d0745SJose E. Roman 
26682e1d0745SJose E. Roman   for (d = depth; d >= 0; d--) PetscCall(PlexLayerDestroy(&layers[d]));
26692e1d0745SJose E. Roman   PetscCall(PetscFree(layers));
26702e1d0745SJose E. Roman   PetscCall(ISDestroy(&strataPermutation));
26712e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
26722e1d0745SJose E. Roman }
26732e1d0745SJose E. Roman 
26742e1d0745SJose E. Roman PetscErrorCode DMPlexTopologyLoad_HDF5_Internal(DM dm, PetscViewer viewer, PetscSF *sfXC)
26752e1d0745SJose E. Roman {
26762e1d0745SJose E. Roman   DMPlexStorageVersion version;
26772e1d0745SJose E. Roman   const char          *topologydm_name;
26782e1d0745SJose E. Roman   char                 group[PETSC_MAX_PATH_LEN];
26792e1d0745SJose E. Roman   PetscSF              sfwork = NULL;
26802e1d0745SJose E. Roman 
26812e1d0745SJose E. Roman   PetscFunctionBegin;
26822e1d0745SJose E. Roman   PetscCall(DMPlexGetHDF5Name_Private(dm, &topologydm_name));
26832e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5GetDMPlexStorageVersionReading(viewer, &version));
26842e1d0745SJose E. Roman   if (DMPlexStorageVersionGE(version, 2, 0, 0)) {
26852e1d0745SJose E. Roman     PetscCall(PetscSNPrintf(group, sizeof(group), "topologies/%s", topologydm_name));
26862e1d0745SJose E. Roman   } else {
26872e1d0745SJose E. Roman     PetscCall(PetscStrncpy(group, "/", sizeof(group)));
26882e1d0745SJose E. Roman   }
26892e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, group));
26902e1d0745SJose E. Roman 
26912e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "topology"));
26922e1d0745SJose E. Roman   if (version->major < 3) {
26932e1d0745SJose E. Roman     PetscCall(DMPlexTopologyLoad_HDF5_Legacy_Private(dm, viewer, &sfwork));
26942e1d0745SJose E. Roman   } else {
26952e1d0745SJose E. Roman     /* since DMPlexStorageVersion 3.0.0 */
26962e1d0745SJose E. Roman     PetscCall(DMPlexTopologyLoad_HDF5_Private(dm, viewer, &sfwork));
26972e1d0745SJose E. Roman   }
26982e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer)); /* "topology" */
26992e1d0745SJose E. Roman 
27002e1d0745SJose E. Roman   if (DMPlexStorageVersionGE(version, 2, 0, 0)) {
27012e1d0745SJose E. Roman     DM          distdm;
27022e1d0745SJose E. Roman     PetscSF     distsf;
27032e1d0745SJose E. Roman     const char *distribution_name;
27042e1d0745SJose E. Roman     PetscBool   exists;
27052e1d0745SJose E. Roman 
27062e1d0745SJose E. Roman     PetscCall(DMPlexDistributionGetName(dm, &distribution_name));
27072e1d0745SJose E. Roman     /* this group is guaranteed to be present since DMPlexStorageVersion 2.1.0 */
27082e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5PushGroup(viewer, "distributions"));
27092e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5HasGroup(viewer, NULL, &exists));
27102e1d0745SJose E. Roman     if (exists) {
27112e1d0745SJose E. Roman       PetscCall(PetscViewerHDF5PushGroup(viewer, distribution_name));
27122e1d0745SJose E. Roman       PetscCall(DMPlexDistributionLoad_HDF5_Private(dm, viewer, sfwork, &distsf, &distdm));
27132e1d0745SJose E. Roman       if (distdm) {
27142e1d0745SJose E. Roman         PetscCall(DMPlexReplace_Internal(dm, &distdm));
27152e1d0745SJose E. Roman         PetscCall(PetscSFDestroy(&sfwork));
27162e1d0745SJose E. Roman         sfwork = distsf;
27172e1d0745SJose E. Roman       }
27182e1d0745SJose E. Roman       PetscCall(PetscViewerHDF5PopGroup(viewer)); /* distribution_name */
27192e1d0745SJose E. Roman     }
27202e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5PopGroup(viewer)); /* "distributions" */
27212e1d0745SJose E. Roman   }
27222e1d0745SJose E. Roman   if (sfXC) {
27232e1d0745SJose E. Roman     *sfXC = sfwork;
27242e1d0745SJose E. Roman   } else {
27252e1d0745SJose E. Roman     PetscCall(PetscSFDestroy(&sfwork));
27262e1d0745SJose E. Roman   }
27272e1d0745SJose E. Roman 
27282e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
27292e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
27302e1d0745SJose E. Roman }
27312e1d0745SJose E. Roman 
27322e1d0745SJose E. Roman /* If the file is old, it not only has different path to the coordinates, but   */
27332e1d0745SJose E. Roman /* does not contain coordinateDMs, so must fall back to the old implementation. */
27342e1d0745SJose E. Roman static PetscErrorCode DMPlexCoordinatesLoad_HDF5_Legacy_Private(DM dm, PetscViewer viewer)
27352e1d0745SJose E. Roman {
27362e1d0745SJose E. Roman   PetscSection coordSection;
27372e1d0745SJose E. Roman   Vec          coordinates;
27382e1d0745SJose E. Roman   PetscReal    lengthScale;
27392e1d0745SJose E. Roman   PetscInt     spatialDim, N, numVertices, vStart, vEnd, v;
27402e1d0745SJose E. Roman   PetscMPIInt  rank;
27412e1d0745SJose E. Roman 
27422e1d0745SJose E. Roman   PetscFunctionBegin;
27432e1d0745SJose E. Roman   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
27442e1d0745SJose E. Roman   /* Read geometry */
27452e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "/geometry"));
27462e1d0745SJose E. Roman   PetscCall(VecCreate(PetscObjectComm((PetscObject)dm), &coordinates));
27472e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)coordinates, "vertices"));
27482e1d0745SJose E. Roman   {
27492e1d0745SJose E. Roman     /* Force serial load */
27502e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5ReadSizes(viewer, "vertices", &spatialDim, &N));
27512e1d0745SJose E. Roman     PetscCall(VecSetSizes(coordinates, rank == 0 ? N : 0, N));
27522e1d0745SJose E. Roman     PetscCall(VecSetBlockSize(coordinates, spatialDim));
27532e1d0745SJose E. Roman   }
27542e1d0745SJose E. Roman   PetscCall(VecLoad(coordinates, viewer));
27552e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
27562e1d0745SJose E. Roman   PetscCall(DMPlexGetScale(dm, PETSC_UNIT_LENGTH, &lengthScale));
27572e1d0745SJose E. Roman   PetscCall(VecScale(coordinates, 1.0 / lengthScale));
27582e1d0745SJose E. Roman   PetscCall(VecGetLocalSize(coordinates, &numVertices));
27592e1d0745SJose E. Roman   PetscCall(VecGetBlockSize(coordinates, &spatialDim));
27602e1d0745SJose E. Roman   numVertices /= spatialDim;
27612e1d0745SJose E. Roman   /* Create coordinates */
27622e1d0745SJose E. Roman   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
27632e1d0745SJose E. Roman   PetscCheck(numVertices == vEnd - vStart, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of coordinates loaded %" PetscInt_FMT " does not match number of vertices %" PetscInt_FMT, numVertices, vEnd - vStart);
27642e1d0745SJose E. Roman   PetscCall(DMGetCoordinateSection(dm, &coordSection));
27652e1d0745SJose E. Roman   PetscCall(PetscSectionSetNumFields(coordSection, 1));
27662e1d0745SJose E. Roman   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spatialDim));
27672e1d0745SJose E. Roman   PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd));
27682e1d0745SJose E. Roman   for (v = vStart; v < vEnd; ++v) {
27692e1d0745SJose E. Roman     PetscCall(PetscSectionSetDof(coordSection, v, spatialDim));
27702e1d0745SJose E. Roman     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spatialDim));
27712e1d0745SJose E. Roman   }
27722e1d0745SJose E. Roman   PetscCall(PetscSectionSetUp(coordSection));
27732e1d0745SJose E. Roman   PetscCall(DMSetCoordinates(dm, coordinates));
27742e1d0745SJose E. Roman   PetscCall(VecDestroy(&coordinates));
27752e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
27762e1d0745SJose E. Roman }
27772e1d0745SJose E. Roman 
27782e1d0745SJose E. Roman PetscErrorCode DMPlexCoordinatesLoad_HDF5_Internal(DM dm, PetscViewer viewer, PetscSF sfXC)
27792e1d0745SJose E. Roman {
27802e1d0745SJose E. Roman   DMPlexStorageVersion version;
27812e1d0745SJose E. Roman   DM                   cdm;
27822e1d0745SJose E. Roman   Vec                  coords;
27832e1d0745SJose E. Roman   PetscInt             blockSize;
27842e1d0745SJose E. Roman   PetscReal            lengthScale;
27852e1d0745SJose E. Roman   PetscSF              lsf;
27862e1d0745SJose E. Roman   const char          *topologydm_name;
27872e1d0745SJose E. Roman   char                *coordinatedm_name, *coordinates_name;
27882e1d0745SJose E. Roman 
27892e1d0745SJose E. Roman   PetscFunctionBegin;
27902e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5GetDMPlexStorageVersionReading(viewer, &version));
27912e1d0745SJose E. Roman   if (!DMPlexStorageVersionGE(version, 2, 0, 0)) {
27922e1d0745SJose E. Roman     PetscCall(DMPlexCoordinatesLoad_HDF5_Legacy_Private(dm, viewer));
27932e1d0745SJose E. Roman     PetscFunctionReturn(PETSC_SUCCESS);
27942e1d0745SJose E. Roman   }
27952e1d0745SJose E. Roman   /* else: since DMPlexStorageVersion 2.0.0 */
27962e1d0745SJose E. Roman   PetscCheck(sfXC, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_NULL, "PetscSF must be given for parallel load");
27972e1d0745SJose E. Roman   PetscCall(DMPlexGetHDF5Name_Private(dm, &topologydm_name));
27982e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "topologies"));
27992e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, topologydm_name));
28002e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5ReadAttribute(viewer, NULL, "coordinateDMName", PETSC_STRING, NULL, &coordinatedm_name));
28012e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5ReadAttribute(viewer, NULL, "coordinatesName", PETSC_STRING, NULL, &coordinates_name));
28022e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
28032e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
28042e1d0745SJose E. Roman   PetscCall(DMGetCoordinateDM(dm, &cdm));
28052e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)cdm, coordinatedm_name));
28062e1d0745SJose E. Roman   PetscCall(PetscFree(coordinatedm_name));
28072e1d0745SJose E. Roman   /* lsf: on-disk data -> in-memory local vector associated with cdm's local section */
28082e1d0745SJose E. Roman   PetscCall(DMPlexSectionLoad(dm, viewer, cdm, sfXC, NULL, &lsf));
28092e1d0745SJose E. Roman   PetscCall(DMCreateLocalVector(cdm, &coords));
28102e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)coords, coordinates_name));
28112e1d0745SJose E. Roman   PetscCall(PetscFree(coordinates_name));
28122e1d0745SJose E. Roman   PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_NATIVE));
28132e1d0745SJose E. Roman   PetscCall(DMPlexLocalVectorLoad(dm, viewer, cdm, lsf, coords));
28142e1d0745SJose E. Roman   PetscCall(PetscViewerPopFormat(viewer));
28152e1d0745SJose E. Roman   PetscCall(DMPlexGetScale(dm, PETSC_UNIT_LENGTH, &lengthScale));
28162e1d0745SJose E. Roman   PetscCall(VecScale(coords, 1.0 / lengthScale));
28172e1d0745SJose E. Roman   PetscCall(DMSetCoordinatesLocal(dm, coords));
28182e1d0745SJose E. Roman   PetscCall(VecGetBlockSize(coords, &blockSize));
28192e1d0745SJose E. Roman   PetscCall(DMSetCoordinateDim(dm, blockSize));
28202e1d0745SJose E. Roman   PetscCall(VecDestroy(&coords));
28212e1d0745SJose E. Roman   PetscCall(PetscSFDestroy(&lsf));
28222e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
28232e1d0745SJose E. Roman }
28242e1d0745SJose E. Roman 
28252e1d0745SJose E. Roman PetscErrorCode DMPlexLoad_HDF5_Internal(DM dm, PetscViewer viewer)
28262e1d0745SJose E. Roman {
28272e1d0745SJose E. Roman   DMPlexStorageVersion version;
28282e1d0745SJose E. Roman 
28292e1d0745SJose E. Roman   PetscFunctionBegin;
28302e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5GetDMPlexStorageVersionReading(viewer, &version));
28312e1d0745SJose E. Roman   PetscCall(PetscInfo(dm, "Loading DM %s storage version %d.%d.%d\n", dm->hdr.name, version->major, version->minor, version->subminor));
28322e1d0745SJose E. Roman   if (!DMPlexStorageVersionGE(version, 2, 0, 0)) {
28332e1d0745SJose E. Roman     PetscCall(DMPlexTopologyLoad_HDF5_Internal(dm, viewer, NULL));
28342e1d0745SJose E. Roman     PetscCall(DMPlexLabelsLoad_HDF5_Internal(dm, viewer, NULL));
28352e1d0745SJose E. Roman     PetscCall(DMPlexCoordinatesLoad_HDF5_Legacy_Private(dm, viewer));
28362e1d0745SJose E. Roman   } else {
28372e1d0745SJose E. Roman     PetscSF sfXC;
28382e1d0745SJose E. Roman 
28392e1d0745SJose E. Roman     /* since DMPlexStorageVersion 2.0.0 */
28402e1d0745SJose E. Roman     PetscCall(DMPlexTopologyLoad_HDF5_Internal(dm, viewer, &sfXC));
28412e1d0745SJose E. Roman     PetscCall(DMPlexLabelsLoad_HDF5_Internal(dm, viewer, sfXC));
28422e1d0745SJose E. Roman     PetscCall(DMPlexCoordinatesLoad_HDF5_Internal(dm, viewer, sfXC));
28432e1d0745SJose E. Roman     PetscCall(PetscSFDestroy(&sfXC));
28442e1d0745SJose E. Roman   }
28452e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
28462e1d0745SJose E. Roman }
28472e1d0745SJose E. Roman 
28482e1d0745SJose E. Roman static PetscErrorCode DMPlexSectionLoad_HDF5_Internal_CreateDataSF(PetscSection rootSection, PetscLayout layout, PetscInt globalOffsets[], PetscSection leafSection, PetscSF *sectionSF)
28492e1d0745SJose E. Roman {
28502e1d0745SJose E. Roman   MPI_Comm  comm;
28512e1d0745SJose E. Roman   PetscInt  pStart, pEnd, p, m;
28522e1d0745SJose E. Roman   PetscInt *goffs, *ilocal;
28532e1d0745SJose E. Roman   PetscBool rootIncludeConstraints, leafIncludeConstraints;
28542e1d0745SJose E. Roman 
28552e1d0745SJose E. Roman   PetscFunctionBegin;
28562e1d0745SJose E. Roman   PetscCall(PetscObjectGetComm((PetscObject)leafSection, &comm));
28572e1d0745SJose E. Roman   PetscCall(PetscSectionGetChart(leafSection, &pStart, &pEnd));
28582e1d0745SJose E. Roman   PetscCall(PetscSectionGetIncludesConstraints(rootSection, &rootIncludeConstraints));
28592e1d0745SJose E. Roman   PetscCall(PetscSectionGetIncludesConstraints(leafSection, &leafIncludeConstraints));
28602e1d0745SJose E. Roman   if (rootIncludeConstraints && leafIncludeConstraints) PetscCall(PetscSectionGetStorageSize(leafSection, &m));
28612e1d0745SJose E. Roman   else PetscCall(PetscSectionGetConstrainedStorageSize(leafSection, &m));
28622e1d0745SJose E. Roman   PetscCall(PetscMalloc1(m, &ilocal));
28632e1d0745SJose E. Roman   PetscCall(PetscMalloc1(m, &goffs));
28642e1d0745SJose E. Roman   /* Currently, PetscSFDistributeSection() returns globalOffsets[] only */
28652e1d0745SJose E. Roman   /* for the top-level section (not for each field), so one must have   */
28662e1d0745SJose E. Roman   /* rootSection->pointMajor == PETSC_TRUE.                             */
28672e1d0745SJose E. Roman   PetscCheck(rootSection->pointMajor, PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for field major ordering");
28682e1d0745SJose E. Roman   /* Currently, we also assume that leafSection->pointMajor == PETSC_TRUE. */
28692e1d0745SJose E. Roman   PetscCheck(leafSection->pointMajor, PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for field major ordering");
28702e1d0745SJose E. Roman   for (p = pStart, m = 0; p < pEnd; ++p) {
28712e1d0745SJose E. Roman     PetscInt        dof, cdof, i, j, off, goff;
28722e1d0745SJose E. Roman     const PetscInt *cinds;
28732e1d0745SJose E. Roman 
28742e1d0745SJose E. Roman     PetscCall(PetscSectionGetDof(leafSection, p, &dof));
28752e1d0745SJose E. Roman     if (dof < 0) continue;
28762e1d0745SJose E. Roman     goff = globalOffsets[p - pStart];
28772e1d0745SJose E. Roman     PetscCall(PetscSectionGetOffset(leafSection, p, &off));
28782e1d0745SJose E. Roman     PetscCall(PetscSectionGetConstraintDof(leafSection, p, &cdof));
28792e1d0745SJose E. Roman     PetscCall(PetscSectionGetConstraintIndices(leafSection, p, &cinds));
28802e1d0745SJose E. Roman     for (i = 0, j = 0; i < dof; ++i) {
28812e1d0745SJose E. Roman       PetscBool constrained = (PetscBool)(j < cdof && i == cinds[j]);
28822e1d0745SJose E. Roman 
28832e1d0745SJose E. Roman       if (!constrained || (leafIncludeConstraints && rootIncludeConstraints)) {
28842e1d0745SJose E. Roman         ilocal[m]  = off++;
28852e1d0745SJose E. Roman         goffs[m++] = goff++;
28862e1d0745SJose E. Roman       } else if (leafIncludeConstraints && !rootIncludeConstraints) ++off;
28872e1d0745SJose E. Roman       else if (!leafIncludeConstraints && rootIncludeConstraints) ++goff;
28882e1d0745SJose E. Roman       if (constrained) ++j;
28892e1d0745SJose E. Roman     }
28902e1d0745SJose E. Roman   }
28912e1d0745SJose E. Roman   PetscCall(PetscSFCreate(comm, sectionSF));
28922e1d0745SJose E. Roman   PetscCall(PetscSFSetFromOptions(*sectionSF));
28932e1d0745SJose E. Roman   PetscCall(PetscSFSetGraphLayout(*sectionSF, layout, m, ilocal, PETSC_OWN_POINTER, goffs));
28942e1d0745SJose E. Roman   PetscCall(PetscFree(goffs));
28952e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
28962e1d0745SJose E. Roman }
28972e1d0745SJose E. Roman 
28982e1d0745SJose E. Roman PetscErrorCode DMPlexSectionLoad_HDF5_Internal(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sfXB, PetscSF *gsf, PetscSF *lsf)
28992e1d0745SJose E. Roman {
29002e1d0745SJose E. Roman   MPI_Comm     comm;
29012e1d0745SJose E. Roman   PetscMPIInt  size, rank;
29022e1d0745SJose E. Roman   const char  *topologydm_name;
29032e1d0745SJose E. Roman   const char  *sectiondm_name;
29042e1d0745SJose E. Roman   PetscSection sectionA, sectionB;
29052e1d0745SJose E. Roman   PetscBool    has;
29062e1d0745SJose E. Roman   PetscInt     nX, n, i;
29072e1d0745SJose E. Roman   PetscSF      sfAB;
29082e1d0745SJose E. Roman 
29092e1d0745SJose E. Roman   PetscFunctionBegin;
29102e1d0745SJose E. Roman   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
29112e1d0745SJose E. Roman   PetscCallMPI(MPI_Comm_size(comm, &size));
29122e1d0745SJose E. Roman   PetscCallMPI(MPI_Comm_rank(comm, &rank));
29132e1d0745SJose E. Roman   PetscCall(DMPlexGetHDF5Name_Private(dm, &topologydm_name));
29142e1d0745SJose E. Roman   PetscCall(PetscObjectGetName((PetscObject)sectiondm, &sectiondm_name));
29152e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "topologies"));
29162e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, topologydm_name));
29172e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "dms"));
29182e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, sectiondm_name));
29192e1d0745SJose E. Roman   /* A: on-disk points                        */
29202e1d0745SJose E. Roman   /* X: list of global point numbers, [0, NX) */
29212e1d0745SJose E. Roman   /* B: plex points                           */
29222e1d0745SJose E. Roman   /* Load raw section (sectionA)              */
29232e1d0745SJose E. Roman   PetscCall(PetscSectionCreate(comm, &sectionA));
29242e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5HasGroup(viewer, "section", &has));
29252e1d0745SJose E. Roman   if (has) PetscCall(PetscSectionLoad(sectionA, viewer));
29262e1d0745SJose E. Roman   else {
29272e1d0745SJose E. Roman     // TODO If section is missing, create the default affine section with dim dofs on each vertex. Use PetscSplitOwnership() to split vertices.
29282e1d0745SJose E. Roman     //   How do I know the total number of vertices?
29292e1d0745SJose E. Roman     PetscInt dim, Nf = 1, Nv, nv = PETSC_DECIDE;
29302e1d0745SJose E. Roman 
29312e1d0745SJose E. Roman     PetscCall(DMGetDimension(dm, &dim));
29322e1d0745SJose E. Roman     PetscCall(DMPlexGetDepthStratumGlobalSize(dm, 0, &Nv));
29332e1d0745SJose E. Roman     PetscCall(PetscSectionSetNumFields(sectionA, Nf));
29342e1d0745SJose E. Roman     PetscCall(PetscSectionSetFieldName(sectionA, 0, "Cartesian"));
29352e1d0745SJose E. Roman     PetscCall(PetscSectionSetFieldComponents(sectionA, 0, dim));
29362e1d0745SJose E. Roman     for (PetscInt c = 0; c < dim; ++c) {
29372e1d0745SJose E. Roman       char axis = 'X' + (char)c;
29382e1d0745SJose E. Roman 
29392e1d0745SJose E. Roman       PetscCall(PetscSectionSetComponentName(sectionA, 0, c, &axis));
29402e1d0745SJose E. Roman     }
29412e1d0745SJose E. Roman     PetscCall(PetscSplitOwnership(comm, &nv, &Nv));
29422e1d0745SJose E. Roman     PetscCall(PetscSectionSetChart(sectionA, 0, nv));
29432e1d0745SJose E. Roman     for (PetscInt p = 0; p < nv; ++p) {
29442e1d0745SJose E. Roman       PetscCall(PetscSectionSetDof(sectionA, p, dim));
29452e1d0745SJose E. Roman       PetscCall(PetscSectionSetFieldDof(sectionA, p, 0, dim));
29462e1d0745SJose E. Roman     }
29472e1d0745SJose E. Roman     PetscCall(PetscSectionSetUp(sectionA));
29482e1d0745SJose E. Roman   }
29492e1d0745SJose E. Roman   PetscCall(PetscSectionGetChart(sectionA, NULL, &n));
29502e1d0745SJose E. Roman /* Create sfAB: A -> B */
29512e1d0745SJose E. Roman #if defined(PETSC_USE_DEBUG)
29522e1d0745SJose E. Roman   {
29532e1d0745SJose E. Roman     PetscInt N, N1;
29542e1d0745SJose E. Roman 
29552e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5ReadSizes(viewer, "order", NULL, &N1));
29562e1d0745SJose E. Roman     PetscCallMPI(MPIU_Allreduce(&n, &N, 1, MPIU_INT, MPI_SUM, comm));
29572e1d0745SJose E. Roman     PetscCheck(N1 == N, comm, PETSC_ERR_ARG_SIZ, "Mismatching sizes: on-disk order array size (%" PetscInt_FMT ") != number of loaded section points (%" PetscInt_FMT ")", N1, N);
29582e1d0745SJose E. Roman   }
29592e1d0745SJose E. Roman #endif
29602e1d0745SJose E. Roman   {
29612e1d0745SJose E. Roman     IS              orderIS;
29622e1d0745SJose E. Roman     const PetscInt *gpoints;
29632e1d0745SJose E. Roman     PetscSF         sfXA, sfAX;
29642e1d0745SJose E. Roman     PetscLayout     layout;
29652e1d0745SJose E. Roman     PetscSFNode    *owners, *buffer;
29662e1d0745SJose E. Roman     PetscInt        nleaves;
29672e1d0745SJose E. Roman     PetscInt       *ilocal;
29682e1d0745SJose E. Roman     PetscSFNode    *iremote;
29692e1d0745SJose E. Roman 
29702e1d0745SJose E. Roman     /* Create sfAX: A -> X */
29712e1d0745SJose E. Roman     PetscCall(ISCreate(comm, &orderIS));
29722e1d0745SJose E. Roman     PetscCall(PetscObjectSetName((PetscObject)orderIS, "order"));
29732e1d0745SJose E. Roman     PetscCall(PetscLayoutSetLocalSize(orderIS->map, n));
29742e1d0745SJose E. Roman     PetscCall(ISLoad(orderIS, viewer));
29752e1d0745SJose E. Roman     PetscCall(PetscLayoutCreate(comm, &layout));
29762e1d0745SJose E. Roman     PetscCall(PetscSFGetGraph(sfXB, &nX, NULL, NULL, NULL));
29772e1d0745SJose E. Roman     PetscCall(PetscLayoutSetLocalSize(layout, nX));
29782e1d0745SJose E. Roman     PetscCall(PetscLayoutSetBlockSize(layout, 1));
29792e1d0745SJose E. Roman     PetscCall(PetscLayoutSetUp(layout));
29802e1d0745SJose E. Roman     PetscCall(PetscSFCreate(comm, &sfXA));
29812e1d0745SJose E. Roman     PetscCall(ISGetIndices(orderIS, &gpoints));
29822e1d0745SJose E. Roman     PetscCall(PetscSFSetGraphLayout(sfXA, layout, n, NULL, PETSC_OWN_POINTER, gpoints));
29832e1d0745SJose E. Roman     PetscCall(ISRestoreIndices(orderIS, &gpoints));
29842e1d0745SJose E. Roman     PetscCall(ISDestroy(&orderIS));
29852e1d0745SJose E. Roman     PetscCall(PetscLayoutDestroy(&layout));
29862e1d0745SJose E. Roman     PetscCall(PetscMalloc1(n, &owners));
29872e1d0745SJose E. Roman     PetscCall(PetscMalloc1(nX, &buffer));
29882e1d0745SJose E. Roman     for (i = 0; i < n; ++i) {
29892e1d0745SJose E. Roman       owners[i].rank  = rank;
29902e1d0745SJose E. Roman       owners[i].index = i;
29912e1d0745SJose E. Roman     }
29922e1d0745SJose E. Roman     for (i = 0; i < nX; ++i) {
29932e1d0745SJose E. Roman       buffer[i].rank  = -1;
29942e1d0745SJose E. Roman       buffer[i].index = -1;
29952e1d0745SJose E. Roman     }
29962e1d0745SJose E. Roman     PetscCall(PetscSFReduceBegin(sfXA, MPIU_SF_NODE, owners, buffer, MPI_MAXLOC));
29972e1d0745SJose E. Roman     PetscCall(PetscSFReduceEnd(sfXA, MPIU_SF_NODE, owners, buffer, MPI_MAXLOC));
29982e1d0745SJose E. Roman     PetscCall(PetscSFDestroy(&sfXA));
29992e1d0745SJose E. Roman     PetscCall(PetscFree(owners));
30002e1d0745SJose E. Roman     for (i = 0, nleaves = 0; i < nX; ++i)
30012e1d0745SJose E. Roman       if (buffer[i].rank >= 0) nleaves++;
30022e1d0745SJose E. Roman     PetscCall(PetscMalloc1(nleaves, &ilocal));
30032e1d0745SJose E. Roman     PetscCall(PetscMalloc1(nleaves, &iremote));
30042e1d0745SJose E. Roman     for (i = 0, nleaves = 0; i < nX; ++i) {
30052e1d0745SJose E. Roman       if (buffer[i].rank >= 0) {
30062e1d0745SJose E. Roman         ilocal[nleaves]        = i;
30072e1d0745SJose E. Roman         iremote[nleaves].rank  = buffer[i].rank;
30082e1d0745SJose E. Roman         iremote[nleaves].index = buffer[i].index;
30092e1d0745SJose E. Roman         nleaves++;
30102e1d0745SJose E. Roman       }
30112e1d0745SJose E. Roman     }
30122e1d0745SJose E. Roman     PetscCall(PetscFree(buffer));
30132e1d0745SJose E. Roman     PetscCall(PetscSFCreate(comm, &sfAX));
30142e1d0745SJose E. Roman     PetscCall(PetscSFSetFromOptions(sfAX));
30152e1d0745SJose E. Roman     PetscCall(PetscSFSetGraph(sfAX, n, nleaves, ilocal, PETSC_OWN_POINTER, iremote, PETSC_OWN_POINTER));
30162e1d0745SJose E. Roman     PetscCall(PetscSFCompose(sfAX, sfXB, &sfAB));
30172e1d0745SJose E. Roman     PetscCall(PetscSFDestroy(&sfAX));
30182e1d0745SJose E. Roman   }
30192e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
30202e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
30212e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
30222e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
30232e1d0745SJose E. Roman   /* Create plex section (sectionB) */
30242e1d0745SJose E. Roman   PetscCall(DMGetLocalSection(sectiondm, &sectionB));
30252e1d0745SJose E. Roman   if (lsf || gsf) {
30262e1d0745SJose E. Roman     PetscLayout layout;
30272e1d0745SJose E. Roman     PetscInt    M, m;
30282e1d0745SJose E. Roman     PetscInt   *offsetsA;
30292e1d0745SJose E. Roman     PetscBool   includesConstraintsA;
30302e1d0745SJose E. Roman 
30312e1d0745SJose E. Roman     PetscCall(PetscSFDistributeSection(sfAB, sectionA, &offsetsA, sectionB));
30322e1d0745SJose E. Roman     PetscCall(PetscSectionGetIncludesConstraints(sectionA, &includesConstraintsA));
30332e1d0745SJose E. Roman     if (includesConstraintsA) PetscCall(PetscSectionGetStorageSize(sectionA, &m));
30342e1d0745SJose E. Roman     else PetscCall(PetscSectionGetConstrainedStorageSize(sectionA, &m));
30352e1d0745SJose E. Roman     PetscCallMPI(MPIU_Allreduce(&m, &M, 1, MPIU_INT, MPI_SUM, comm));
30362e1d0745SJose E. Roman     PetscCall(PetscLayoutCreate(comm, &layout));
30372e1d0745SJose E. Roman     PetscCall(PetscLayoutSetSize(layout, M));
30382e1d0745SJose E. Roman     PetscCall(PetscLayoutSetUp(layout));
30392e1d0745SJose E. Roman     if (lsf) {
30402e1d0745SJose E. Roman       PetscSF lsfABdata;
30412e1d0745SJose E. Roman 
30422e1d0745SJose E. Roman       PetscCall(DMPlexSectionLoad_HDF5_Internal_CreateDataSF(sectionA, layout, offsetsA, sectionB, &lsfABdata));
30432e1d0745SJose E. Roman       *lsf = lsfABdata;
30442e1d0745SJose E. Roman     }
30452e1d0745SJose E. Roman     if (gsf) {
30462e1d0745SJose E. Roman       PetscSection gsectionB, gsectionB1;
30472e1d0745SJose E. Roman       PetscBool    includesConstraintsB;
30482e1d0745SJose E. Roman       PetscSF      gsfABdata, pointsf;
30492e1d0745SJose E. Roman 
30502e1d0745SJose E. Roman       PetscCall(DMGetGlobalSection(sectiondm, &gsectionB1));
30512e1d0745SJose E. Roman       PetscCall(PetscSectionGetIncludesConstraints(gsectionB1, &includesConstraintsB));
30522e1d0745SJose E. Roman       PetscCall(DMGetPointSF(sectiondm, &pointsf));
30532e1d0745SJose E. Roman       PetscCall(PetscSectionCreateGlobalSection(sectionB, pointsf, PETSC_TRUE, includesConstraintsB, PETSC_TRUE, &gsectionB));
30542e1d0745SJose E. Roman       PetscCall(DMPlexSectionLoad_HDF5_Internal_CreateDataSF(sectionA, layout, offsetsA, gsectionB, &gsfABdata));
30552e1d0745SJose E. Roman       PetscCall(PetscSectionDestroy(&gsectionB));
30562e1d0745SJose E. Roman       *gsf = gsfABdata;
30572e1d0745SJose E. Roman     }
30582e1d0745SJose E. Roman     PetscCall(PetscLayoutDestroy(&layout));
30592e1d0745SJose E. Roman     PetscCall(PetscFree(offsetsA));
30602e1d0745SJose E. Roman   } else {
30612e1d0745SJose E. Roman     PetscCall(PetscSFDistributeSection(sfAB, sectionA, NULL, sectionB));
30622e1d0745SJose E. Roman   }
30632e1d0745SJose E. Roman   PetscCall(PetscSFDestroy(&sfAB));
30642e1d0745SJose E. Roman   PetscCall(PetscSectionDestroy(&sectionA));
30652e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
30662e1d0745SJose E. Roman }
30672e1d0745SJose E. Roman 
30682e1d0745SJose E. Roman PetscErrorCode DMPlexVecLoad_HDF5_Internal(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec)
30692e1d0745SJose E. Roman {
30702e1d0745SJose E. Roman   MPI_Comm           comm;
30712e1d0745SJose E. Roman   const char        *topologydm_name;
30722e1d0745SJose E. Roman   const char        *sectiondm_name;
30732e1d0745SJose E. Roman   const char        *vec_name;
30742e1d0745SJose E. Roman   Vec                vecA;
30752e1d0745SJose E. Roman   PetscInt           mA, m, bs;
30762e1d0745SJose E. Roman   const PetscInt    *ilocal;
30772e1d0745SJose E. Roman   const PetscScalar *src;
30782e1d0745SJose E. Roman   PetscScalar       *dest;
30792e1d0745SJose E. Roman 
30802e1d0745SJose E. Roman   PetscFunctionBegin;
30812e1d0745SJose E. Roman   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
30822e1d0745SJose E. Roman   PetscCall(DMPlexGetHDF5Name_Private(dm, &topologydm_name));
30832e1d0745SJose E. Roman   PetscCall(PetscObjectGetName((PetscObject)sectiondm, &sectiondm_name));
30842e1d0745SJose E. Roman   PetscCall(PetscObjectGetName((PetscObject)vec, &vec_name));
30852e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "topologies"));
30862e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, topologydm_name));
30872e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "dms"));
30882e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, sectiondm_name));
30892e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "vecs"));
30902e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, vec_name));
30912e1d0745SJose E. Roman   PetscCall(VecCreate(comm, &vecA));
30922e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)vecA, vec_name));
30932e1d0745SJose E. Roman   PetscCall(PetscSFGetGraph(sf, &mA, &m, &ilocal, NULL));
30942e1d0745SJose E. Roman   /* Check consistency */
30952e1d0745SJose E. Roman   {
30962e1d0745SJose E. Roman     PetscSF  pointsf, pointsf1;
30972e1d0745SJose E. Roman     PetscInt m1, i, j;
30982e1d0745SJose E. Roman 
30992e1d0745SJose E. Roman     PetscCall(DMGetPointSF(dm, &pointsf));
31002e1d0745SJose E. Roman     PetscCall(DMGetPointSF(sectiondm, &pointsf1));
31012e1d0745SJose E. Roman     PetscCheck(pointsf1 == pointsf, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatching point SFs for dm and sectiondm");
31022e1d0745SJose E. Roman #if defined(PETSC_USE_DEBUG)
31032e1d0745SJose E. Roman     {
31042e1d0745SJose E. Roman       PetscInt MA, MA1;
31052e1d0745SJose E. Roman 
31062e1d0745SJose E. Roman       PetscCallMPI(MPIU_Allreduce(&mA, &MA, 1, MPIU_INT, MPI_SUM, comm));
31072e1d0745SJose E. Roman       PetscCall(PetscViewerHDF5ReadSizes(viewer, vec_name, NULL, &MA1));
31082e1d0745SJose E. Roman       PetscCheck(MA1 == MA, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Total SF root size (%" PetscInt_FMT ") != On-disk vector data size (%" PetscInt_FMT ")", MA, MA1);
31092e1d0745SJose E. Roman     }
31102e1d0745SJose E. Roman #endif
31112e1d0745SJose E. Roman     PetscCall(VecGetLocalSize(vec, &m1));
31122e1d0745SJose E. Roman     PetscCheck(m1 >= m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Target vector size (%" PetscInt_FMT ") < SF leaf size (%" PetscInt_FMT ")", m1, m);
31132e1d0745SJose E. Roman     for (i = 0; i < m; ++i) {
31142e1d0745SJose E. Roman       j = ilocal ? ilocal[i] : i;
31152e1d0745SJose E. Roman       PetscCheck(j >= 0 && j < m1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Leaf's %" PetscInt_FMT "-th index, %" PetscInt_FMT ", not in [%" PetscInt_FMT ", %" PetscInt_FMT ")", i, j, (PetscInt)0, m1);
31162e1d0745SJose E. Roman     }
31172e1d0745SJose E. Roman   }
31182e1d0745SJose E. Roman   PetscCall(VecSetSizes(vecA, mA, PETSC_DECIDE));
31192e1d0745SJose E. Roman   PetscCall(VecLoad(vecA, viewer));
31202e1d0745SJose E. Roman   PetscCall(VecGetArrayRead(vecA, &src));
31212e1d0745SJose E. Roman   PetscCall(VecGetArray(vec, &dest));
31222e1d0745SJose E. Roman   PetscCall(PetscSFBcastBegin(sf, MPIU_SCALAR, src, dest, MPI_REPLACE));
31232e1d0745SJose E. Roman   PetscCall(PetscSFBcastEnd(sf, MPIU_SCALAR, src, dest, MPI_REPLACE));
31242e1d0745SJose E. Roman   PetscCall(VecRestoreArray(vec, &dest));
31252e1d0745SJose E. Roman   PetscCall(VecRestoreArrayRead(vecA, &src));
31262e1d0745SJose E. Roman   PetscCall(VecDestroy(&vecA));
31272e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5ReadAttribute(viewer, NULL, "blockSize", PETSC_INT, NULL, (void *)&bs));
31282e1d0745SJose E. Roman   PetscCall(VecSetBlockSize(vec, bs));
31292e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
31302e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
31312e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
31322e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
31332e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
31342e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
31352e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
31362e1d0745SJose E. Roman }
3137