xref: /petsc/src/dm/impls/plex/hdf5/plexhdf5.c (revision 4e8208cbcbc709572b8abe32f33c78b69c819375)
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 
12d6acfc2dSPierre Jolivet PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode VecView_MPI(Vec, PetscViewer);
132e1d0745SJose E. Roman 
PetscViewerPrintVersion_Private(PetscViewer viewer,DMPlexStorageVersion version,char str[],size_t len)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 
PetscViewerParseVersion_Private(PetscViewer viewer,const char str[],DMPlexStorageVersion * version)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 
PetscViewerAttachVersion_Private(PetscViewer viewer,const char key[],DMPlexStorageVersion v)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 
PetscViewerGetAttachedVersion_Private(PetscViewer viewer,const char key[],DMPlexStorageVersion * v)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;
63*2a8381b2SBarry Smith   if (cont) PetscCall(PetscContainerGetPointer(cont, 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 */
PetscViewerCheckVersion_Private(PetscViewer viewer,DMPlexStorageVersion version)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 
DMPlexStorageVersionEQ(DMPlexStorageVersion version,int major,int minor,int subminor)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 
DMPlexStorageVersionGE(DMPlexStorageVersion version,int major,int minor,int subminor)1462e1d0745SJose E. Roman static inline PetscBool DMPlexStorageVersionGE(DMPlexStorageVersion version, int major, int minor, int subminor)
1472e1d0745SJose E. Roman {
148b6555650SPierre Jolivet   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 @*/
PetscViewerHDF5SetDMPlexStorageVersionWriting(PetscViewer viewer,DMPlexStorageVersion version)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 @*/
PetscViewerHDF5GetDMPlexStorageVersionWriting(PetscViewer viewer,DMPlexStorageVersion * version)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 @*/
PetscViewerHDF5SetDMPlexStorageVersionReading(PetscViewer viewer,DMPlexStorageVersion version)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 @*/
PetscViewerHDF5GetDMPlexStorageVersionReading(PetscViewer viewer,DMPlexStorageVersion * version)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 
DMPlexGetHDF5Name_Private(DM dm,const char * name[])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 
DMSequenceGetLength_HDF5_Internal(DM dm,const char seqname[],PetscInt * seqlen,PetscViewer viewer)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 
DMSequenceView_HDF5(DM dm,const char seqname[],PetscInt seqnum,PetscScalar value,PetscViewer viewer)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 
DMSequenceLoad_HDF5_Internal(DM dm,const char seqname[],PetscInt seqnum,PetscScalar * value,PetscViewer viewer)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 
DMPlexCreateCutVertexLabel_Private(DM dm,DMLabel cutLabel,DMLabel * cutVertexLabel)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 
VecView_Plex_Local_HDF5_Internal(Vec v,PetscViewer viewer)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) {
565298ebf1dSStefano Zampini         size_t lname;
566298ebf1dSStefano Zampini 
5675a236de6SSatish Balay         if (ft[t] == PETSC_VTK_INVALID) continue;
5685a236de6SSatish Balay         fgroup = (ft[t] == PETSC_VTK_POINT_VECTOR_FIELD) || (ft[t] == PETSC_VTK_POINT_FIELD) ? "/vertex_fields" : "/cell_fields";
5692e1d0745SJose E. Roman         PetscCall(PetscSectionGetFieldName(section, f, &fname));
5702e1d0745SJose E. Roman         if (!fname) fname = fname_def;
5712e1d0745SJose E. Roman 
5725a236de6SSatish Balay         if (!t) {
5732e1d0745SJose E. Roman           PetscCall(PetscViewerHDF5PushGroup(viewer, fgroup));
5745a236de6SSatish Balay         } else {
5755a236de6SSatish Balay           char group[PETSC_MAX_PATH_LEN];
5765a236de6SSatish Balay 
5775a236de6SSatish Balay           PetscCall(PetscSNPrintf(group, PETSC_MAX_PATH_LEN, "%s_%" PetscInt_FMT, fgroup, t));
5785a236de6SSatish Balay           PetscCall(PetscViewerHDF5PushGroup(viewer, group));
5795a236de6SSatish Balay         }
5802e1d0745SJose E. Roman 
5812e1d0745SJose E. Roman         if (cutLabel) {
5822e1d0745SJose E. Roman           const PetscScalar *ga;
5832e1d0745SJose E. Roman           PetscScalar       *suba;
5845a236de6SSatish Balay           PetscInt           gstart, subSize = 0, extSize = 0, subOff = 0, newOff = 0;
5852e1d0745SJose E. Roman 
5862e1d0745SJose E. Roman           PetscCall(DMPlexCreateCutVertexLabel_Private(dm, cutLabel, &cutVertexLabel));
5872e1d0745SJose E. Roman           PetscCall(PetscSectionGetFieldComponents(section, f, &Nc));
5885a236de6SSatish Balay           for (PetscInt p = pStart[t]; p < pEnd[t]; ++p) {
5892e1d0745SJose E. Roman             PetscInt gdof, fdof = 0, val;
5902e1d0745SJose E. Roman 
5912e1d0745SJose E. Roman             PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof));
5922e1d0745SJose E. Roman             if (gdof > 0) PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof));
5932e1d0745SJose E. Roman             subSize += fdof;
5942e1d0745SJose E. Roman             PetscCall(DMLabelGetValue(cutVertexLabel, p, &val));
5952e1d0745SJose E. Roman             if (val == 1) extSize += fdof;
5962e1d0745SJose E. Roman           }
5972e1d0745SJose E. Roman           PetscCall(VecCreate(PetscObjectComm((PetscObject)gv), &subv));
5982e1d0745SJose E. Roman           PetscCall(VecSetSizes(subv, subSize + extSize, PETSC_DETERMINE));
5992e1d0745SJose E. Roman           PetscCall(VecSetBlockSize(subv, Nc));
6002e1d0745SJose E. Roman           PetscCall(VecSetType(subv, VECSTANDARD));
6012e1d0745SJose E. Roman           PetscCall(VecGetOwnershipRange(gv, &gstart, NULL));
6022e1d0745SJose E. Roman           PetscCall(VecGetArrayRead(gv, &ga));
6032e1d0745SJose E. Roman           PetscCall(VecGetArray(subv, &suba));
6045a236de6SSatish Balay           for (PetscInt p = pStart[t]; p < pEnd[t]; ++p) {
6052e1d0745SJose E. Roman             PetscInt gdof, goff, val;
6062e1d0745SJose E. Roman 
6072e1d0745SJose E. Roman             PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof));
6082e1d0745SJose E. Roman             if (gdof > 0) {
6092e1d0745SJose E. Roman               PetscInt fdof, fc, f2, poff = 0;
6102e1d0745SJose E. Roman 
6112e1d0745SJose E. Roman               PetscCall(PetscSectionGetOffset(sectionGlobal, p, &goff));
6122e1d0745SJose E. Roman               /* Can get rid of this loop by storing field information in the global section */
6132e1d0745SJose E. Roman               for (f2 = 0; f2 < f; ++f2) {
6142e1d0745SJose E. Roman                 PetscCall(PetscSectionGetFieldDof(section, p, f2, &fdof));
6152e1d0745SJose E. Roman                 poff += fdof;
6162e1d0745SJose E. Roman               }
6172e1d0745SJose E. Roman               PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof));
6182e1d0745SJose E. Roman               for (fc = 0; fc < fdof; ++fc, ++subOff) suba[subOff] = ga[goff + poff + fc - gstart];
6192e1d0745SJose E. Roman               PetscCall(DMLabelGetValue(cutVertexLabel, p, &val));
6202e1d0745SJose E. Roman               if (val == 1) {
6212e1d0745SJose E. Roman                 for (fc = 0; fc < fdof; ++fc, ++newOff) suba[subSize + newOff] = ga[goff + poff + fc - gstart];
6222e1d0745SJose E. Roman               }
6232e1d0745SJose E. Roman             }
6242e1d0745SJose E. Roman           }
6252e1d0745SJose E. Roman           PetscCall(VecRestoreArrayRead(gv, &ga));
6262e1d0745SJose E. Roman           PetscCall(VecRestoreArray(subv, &suba));
6272e1d0745SJose E. Roman           PetscCall(DMLabelDestroy(&cutVertexLabel));
6282e1d0745SJose E. Roman         } else {
6295a236de6SSatish Balay           PetscCall(PetscSectionGetField_Internal(section, sectionGlobal, gv, f, pStart[t], pEnd[t], &is, &subv));
6302e1d0745SJose E. Roman         }
631298ebf1dSStefano Zampini         PetscCall(PetscStrlen(name, &lname));
632298ebf1dSStefano Zampini         if (lname) {
6332e1d0745SJose E. Roman           PetscCall(PetscStrncpy(subname, name, sizeof(subname)));
6342e1d0745SJose E. Roman           PetscCall(PetscStrlcat(subname, "_", sizeof(subname)));
635298ebf1dSStefano Zampini         }
6362e1d0745SJose E. Roman         PetscCall(PetscStrlcat(subname, fname, sizeof(subname)));
6372e1d0745SJose E. Roman         PetscCall(PetscObjectSetName((PetscObject)subv, subname));
6382e1d0745SJose E. Roman         if (isseq) PetscCall(VecView_Seq(subv, viewer));
6392e1d0745SJose E. Roman         else PetscCall(VecView_MPI(subv, viewer));
6405a236de6SSatish Balay         if (ft[t] == PETSC_VTK_POINT_VECTOR_FIELD || ft[t] == PETSC_VTK_CELL_VECTOR_FIELD) {
6412e1d0745SJose E. Roman           PetscCall(PetscViewerHDF5WriteObjectAttribute(viewer, (PetscObject)subv, "vector_field_type", PETSC_STRING, "vector"));
6422e1d0745SJose E. Roman         } else {
6432e1d0745SJose E. Roman           PetscCall(PetscViewerHDF5WriteObjectAttribute(viewer, (PetscObject)subv, "vector_field_type", PETSC_STRING, "scalar"));
6442e1d0745SJose E. Roman         }
6452e1d0745SJose E. Roman 
6462e1d0745SJose E. Roman         /* Output the component names in the field if available */
6472e1d0745SJose E. Roman         PetscCall(PetscSectionGetFieldComponents(section, f, &Nc));
6485a236de6SSatish Balay         for (PetscInt c = 0; c < Nc; ++c) {
6492e1d0745SJose E. Roman           char componentNameLabel[PETSC_MAX_PATH_LEN];
6502e1d0745SJose E. Roman           PetscCall(PetscSectionGetComponentName(section, f, c, &componentName));
6512e1d0745SJose E. Roman           PetscCall(PetscSNPrintf(componentNameLabel, sizeof(componentNameLabel), "componentName%" PetscInt_FMT, c));
6522e1d0745SJose E. Roman           PetscCall(PetscViewerHDF5WriteObjectAttribute(viewer, (PetscObject)subv, componentNameLabel, PETSC_STRING, componentName));
6532e1d0745SJose E. Roman         }
6542e1d0745SJose E. Roman 
6552e1d0745SJose E. Roman         if (cutLabel) PetscCall(VecDestroy(&subv));
6565a236de6SSatish Balay         else PetscCall(PetscSectionRestoreField_Internal(section, sectionGlobal, gv, f, pStart[t], pEnd[t], &is, &subv));
6572e1d0745SJose E. Roman         PetscCall(PetscViewerHDF5PopGroup(viewer));
6582e1d0745SJose E. Roman       }
659c935b23eSStefano Zampini       if (!DMPlexStorageVersionEQ(version, 1, 1, 0)) PetscCall(PetscFree3(pStart, pEnd, ft));
6605a236de6SSatish Balay     }
6612e1d0745SJose E. Roman   } else {
6622e1d0745SJose E. Roman     /* Output full vector */
6632e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5PushGroup(viewer, "/fields"));
6642e1d0745SJose E. Roman     if (isseq) PetscCall(VecView_Seq(gv, viewer));
6652e1d0745SJose E. Roman     else PetscCall(VecView_MPI(gv, viewer));
6662e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5PopGroup(viewer));
6672e1d0745SJose E. Roman   }
6682e1d0745SJose E. Roman   if (seqnum >= 0) PetscCall(PetscViewerHDF5PopTimestepping(viewer));
6692e1d0745SJose E. Roman   PetscCall(DMRestoreGlobalVector(dmBC, &gv));
6702e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
6712e1d0745SJose E. Roman }
6722e1d0745SJose E. Roman 
VecView_Plex_HDF5_Internal(Vec v,PetscViewer viewer)6732e1d0745SJose E. Roman PetscErrorCode VecView_Plex_HDF5_Internal(Vec v, PetscViewer viewer)
6742e1d0745SJose E. Roman {
6752e1d0745SJose E. Roman   DMPlexStorageVersion version;
6762e1d0745SJose E. Roman   DM                   dm;
6772e1d0745SJose E. Roman   Vec                  locv;
6782e1d0745SJose E. Roman   PetscObject          isZero;
6792e1d0745SJose E. Roman   const char          *name;
6802e1d0745SJose E. Roman   PetscReal            time;
6812e1d0745SJose E. Roman 
6822e1d0745SJose E. Roman   PetscFunctionBegin;
6832e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5GetDMPlexStorageVersionWriting(viewer, &version));
6842e1d0745SJose E. Roman   PetscCall(PetscInfo(v, "Writing Vec %s storage version %d.%d.%d\n", v->hdr.name, version->major, version->minor, version->subminor));
6852e1d0745SJose E. Roman 
6862e1d0745SJose E. Roman   PetscCall(VecGetDM(v, &dm));
6872e1d0745SJose E. Roman   PetscCall(DMGetLocalVector(dm, &locv));
6882e1d0745SJose E. Roman   PetscCall(PetscObjectGetName((PetscObject)v, &name));
6892e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)locv, name));
6902e1d0745SJose E. Roman   PetscCall(PetscObjectQuery((PetscObject)v, "__Vec_bc_zero__", &isZero));
6912e1d0745SJose E. Roman   PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", isZero));
6922e1d0745SJose E. Roman   PetscCall(DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv));
6932e1d0745SJose E. Roman   PetscCall(DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv));
6942e1d0745SJose E. Roman   PetscCall(DMGetOutputSequenceNumber(dm, NULL, &time));
6952e1d0745SJose E. Roman   PetscCall(DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locv, time, NULL, NULL, NULL));
6962e1d0745SJose E. Roman   PetscCall(VecView_Plex_Local_HDF5_Internal(locv, viewer));
6972e1d0745SJose E. Roman   if (DMPlexStorageVersionEQ(version, 1, 1, 0)) {
6982e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5PushGroup(viewer, "/fields"));
6992e1d0745SJose E. Roman     PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_HDF5_VIZ));
7002e1d0745SJose E. Roman     PetscCall(VecView_Plex_Local_HDF5_Internal(locv, viewer));
7012e1d0745SJose E. Roman     PetscCall(PetscViewerPopFormat(viewer));
7022e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5PopGroup(viewer));
7032e1d0745SJose E. Roman   }
7042e1d0745SJose E. Roman   PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", NULL));
7052e1d0745SJose E. Roman   PetscCall(DMRestoreLocalVector(dm, &locv));
7062e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
7072e1d0745SJose E. Roman }
7082e1d0745SJose E. Roman 
VecView_Plex_HDF5_Native_Internal(Vec v,PetscViewer viewer)7092e1d0745SJose E. Roman PetscErrorCode VecView_Plex_HDF5_Native_Internal(Vec v, PetscViewer viewer)
7102e1d0745SJose E. Roman {
7112e1d0745SJose E. Roman   PetscBool isseq;
7122e1d0745SJose E. Roman 
7132e1d0745SJose E. Roman   PetscFunctionBegin;
7142e1d0745SJose E. Roman   PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq));
7152e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "/fields"));
7162e1d0745SJose E. Roman   if (isseq) PetscCall(VecView_Seq(v, viewer));
7172e1d0745SJose E. Roman   else PetscCall(VecView_MPI(v, viewer));
7182e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
7192e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
7202e1d0745SJose E. Roman }
7212e1d0745SJose E. Roman 
VecLoad_Plex_HDF5_Internal(Vec v,PetscViewer viewer)7222e1d0745SJose E. Roman PetscErrorCode VecLoad_Plex_HDF5_Internal(Vec v, PetscViewer viewer)
7232e1d0745SJose E. Roman {
7242e1d0745SJose E. Roman   DM          dm;
7252e1d0745SJose E. Roman   Vec         locv;
7262e1d0745SJose E. Roman   const char *name;
7272e1d0745SJose E. Roman   PetscInt    seqnum;
7282e1d0745SJose E. Roman 
7292e1d0745SJose E. Roman   PetscFunctionBegin;
7302e1d0745SJose E. Roman   PetscCall(VecGetDM(v, &dm));
7312e1d0745SJose E. Roman   PetscCall(DMGetLocalVector(dm, &locv));
7322e1d0745SJose E. Roman   PetscCall(PetscObjectGetName((PetscObject)v, &name));
7332e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)locv, name));
7342e1d0745SJose E. Roman   PetscCall(DMGetOutputSequenceNumber(dm, &seqnum, NULL));
7352e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "/fields"));
7362e1d0745SJose E. Roman   if (seqnum >= 0) {
7372e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5PushTimestepping(viewer));
7382e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5SetTimestep(viewer, seqnum));
7392e1d0745SJose E. Roman   }
7402e1d0745SJose E. Roman   PetscCall(VecLoad_Plex_Local(locv, viewer));
7412e1d0745SJose E. Roman   if (seqnum >= 0) PetscCall(PetscViewerHDF5PopTimestepping(viewer));
7422e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
7432e1d0745SJose E. Roman   PetscCall(DMLocalToGlobalBegin(dm, locv, INSERT_VALUES, v));
7442e1d0745SJose E. Roman   PetscCall(DMLocalToGlobalEnd(dm, locv, INSERT_VALUES, v));
7452e1d0745SJose E. Roman   PetscCall(DMRestoreLocalVector(dm, &locv));
7462e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
7472e1d0745SJose E. Roman }
7482e1d0745SJose E. Roman 
VecLoad_Plex_HDF5_Native_Internal(Vec v,PetscViewer viewer)7492e1d0745SJose E. Roman PetscErrorCode VecLoad_Plex_HDF5_Native_Internal(Vec v, PetscViewer viewer)
7502e1d0745SJose E. Roman {
7512e1d0745SJose E. Roman   DM       dm;
7522e1d0745SJose E. Roman   PetscInt seqnum;
7532e1d0745SJose E. Roman 
7542e1d0745SJose E. Roman   PetscFunctionBegin;
7552e1d0745SJose E. Roman   PetscCall(VecGetDM(v, &dm));
7562e1d0745SJose E. Roman   PetscCall(DMGetOutputSequenceNumber(dm, &seqnum, NULL));
7572e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "/fields"));
7582e1d0745SJose E. Roman   if (seqnum >= 0) {
7592e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5PushTimestepping(viewer));
7602e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5SetTimestep(viewer, seqnum));
7612e1d0745SJose E. Roman   }
7622e1d0745SJose E. Roman   PetscCall(VecLoad_Default(v, viewer));
7632e1d0745SJose E. Roman   if (seqnum >= 0) PetscCall(PetscViewerHDF5PopTimestepping(viewer));
7642e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
7652e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
7662e1d0745SJose E. Roman }
7672e1d0745SJose E. Roman 
DMPlexDistributionView_HDF5_Private(DM dm,IS globalPointNumbers,PetscViewer viewer)7682e1d0745SJose E. Roman static PetscErrorCode DMPlexDistributionView_HDF5_Private(DM dm, IS globalPointNumbers, PetscViewer viewer)
7692e1d0745SJose E. Roman {
7705a236de6SSatish Balay   DMPlexStorageVersion version;
7712e1d0745SJose E. Roman   MPI_Comm             comm;
7722e1d0745SJose E. Roman   PetscMPIInt          size, rank;
7732e1d0745SJose E. Roman   PetscInt             size_petsc_int;
7742e1d0745SJose E. Roman   const char          *topologydm_name, *distribution_name;
7752e1d0745SJose E. Roman   const PetscInt      *gpoint;
7762e1d0745SJose E. Roman   PetscInt             pStart, pEnd, p;
7772e1d0745SJose E. Roman   PetscSF              pointSF;
7782e1d0745SJose E. Roman   PetscInt             nroots, nleaves;
7792e1d0745SJose E. Roman   const PetscInt      *ilocal;
7802e1d0745SJose E. Roman   const PetscSFNode   *iremote;
7812e1d0745SJose E. Roman   IS                   chartSizesIS, ownersIS, gpointsIS;
7822e1d0745SJose E. Roman   PetscInt            *chartSize, *owners, *gpoints;
783ea87367fSMatthew G. Knepley   PetscBool            ocompress;
7842e1d0745SJose E. Roman 
7852e1d0745SJose E. Roman   PetscFunctionBegin;
7865a236de6SSatish Balay   PetscCall(PetscViewerHDF5GetDMPlexStorageVersionWriting(viewer, &version));
7872e1d0745SJose E. Roman   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
7882e1d0745SJose E. Roman   PetscCallMPI(MPI_Comm_size(comm, &size));
7892e1d0745SJose E. Roman   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7902e1d0745SJose E. Roman   PetscCall(DMPlexGetHDF5Name_Private(dm, &topologydm_name));
7912e1d0745SJose E. Roman   PetscCall(DMPlexDistributionGetName(dm, &distribution_name));
7922e1d0745SJose E. Roman   if (!distribution_name) PetscFunctionReturn(PETSC_SUCCESS);
7932e1d0745SJose E. Roman   PetscCall(PetscLogEventBegin(DMPLEX_DistributionView, viewer, 0, 0, 0));
7942e1d0745SJose E. Roman   size_petsc_int = (PetscInt)size;
7952e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5WriteAttribute(viewer, NULL, "comm_size", PETSC_INT, (void *)&size_petsc_int));
7962e1d0745SJose E. Roman   PetscCall(ISGetIndices(globalPointNumbers, &gpoint));
7972e1d0745SJose E. Roman   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
7982e1d0745SJose E. Roman   PetscCall(PetscMalloc1(1, &chartSize));
7992e1d0745SJose E. Roman   *chartSize = pEnd - pStart;
8002e1d0745SJose E. Roman   PetscCall(PetscMalloc1(*chartSize, &owners));
8012e1d0745SJose E. Roman   PetscCall(PetscMalloc1(*chartSize, &gpoints));
8022e1d0745SJose E. Roman   PetscCall(DMGetPointSF(dm, &pointSF));
8032e1d0745SJose E. Roman   PetscCall(PetscSFGetGraph(pointSF, &nroots, &nleaves, &ilocal, &iremote));
8042e1d0745SJose E. Roman   for (p = pStart; p < pEnd; ++p) {
8052e1d0745SJose E. Roman     PetscInt gp = gpoint[p - pStart];
8062e1d0745SJose E. Roman 
8072e1d0745SJose E. Roman     owners[p - pStart]  = rank;
8082e1d0745SJose E. Roman     gpoints[p - pStart] = (gp < 0 ? -(gp + 1) : gp);
8092e1d0745SJose E. Roman   }
8102e1d0745SJose E. Roman   for (p = 0; p < nleaves; ++p) {
8112e1d0745SJose E. Roman     PetscInt ilocalp = (ilocal ? ilocal[p] : p);
8122e1d0745SJose E. Roman 
8132e1d0745SJose E. Roman     owners[ilocalp] = iremote[p].rank;
8142e1d0745SJose E. Roman   }
8152e1d0745SJose E. Roman   PetscCall(ISCreateGeneral(comm, 1, chartSize, PETSC_OWN_POINTER, &chartSizesIS));
8162e1d0745SJose E. Roman   PetscCall(ISCreateGeneral(comm, *chartSize, owners, PETSC_OWN_POINTER, &ownersIS));
8172e1d0745SJose E. Roman   PetscCall(ISCreateGeneral(comm, *chartSize, gpoints, PETSC_OWN_POINTER, &gpointsIS));
8185a236de6SSatish Balay   if (DMPlexStorageVersionGE(version, 3, 1, 0)) {
819ea87367fSMatthew G. Knepley     PetscCall(PetscViewerHDF5GetCompress(viewer, &ocompress));
820ea87367fSMatthew G. Knepley     PetscCall(PetscViewerHDF5SetCompress(viewer, PETSC_TRUE));
8215a236de6SSatish Balay   }
8222e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)chartSizesIS, "chart_sizes"));
8232e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)ownersIS, "owners"));
8242e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)gpointsIS, "global_point_numbers"));
8252e1d0745SJose E. Roman   PetscCall(ISView(chartSizesIS, viewer));
8262e1d0745SJose E. Roman   PetscCall(ISView(ownersIS, viewer));
8272e1d0745SJose E. Roman   PetscCall(ISView(gpointsIS, viewer));
8282e1d0745SJose E. Roman   PetscCall(ISDestroy(&chartSizesIS));
8292e1d0745SJose E. Roman   PetscCall(ISDestroy(&ownersIS));
8302e1d0745SJose E. Roman   PetscCall(ISDestroy(&gpointsIS));
8312e1d0745SJose E. Roman   PetscCall(ISRestoreIndices(globalPointNumbers, &gpoint));
832ea87367fSMatthew G. Knepley   if (DMPlexStorageVersionGE(version, 3, 1, 0)) PetscCall(PetscViewerHDF5SetCompress(viewer, ocompress));
8332e1d0745SJose E. Roman   PetscCall(PetscLogEventEnd(DMPLEX_DistributionView, viewer, 0, 0, 0));
8342e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
8352e1d0745SJose E. Roman }
8362e1d0745SJose E. Roman 
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[])8372e1d0745SJose 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[])
8382e1d0745SJose E. Roman {
8395a236de6SSatish Balay   DMPlexStorageVersion version;
8402e1d0745SJose E. Roman   IS                   coneSizesIS, conesIS, orientationsIS;
8412e1d0745SJose E. Roman   PetscInt            *coneSizes, *cones, *orientations;
8422e1d0745SJose E. Roman   const PetscInt      *gpoint;
8432e1d0745SJose E. Roman   PetscInt             nPoints = 0, conesSize = 0;
8442e1d0745SJose E. Roman   PetscInt             p, c, s;
845ea87367fSMatthew G. Knepley   PetscBool            ocompress;
8462e1d0745SJose E. Roman   MPI_Comm             comm;
8472e1d0745SJose E. Roman 
8482e1d0745SJose E. Roman   PetscFunctionBegin;
8495a236de6SSatish Balay   PetscCall(PetscViewerHDF5GetDMPlexStorageVersionWriting(viewer, &version));
8502e1d0745SJose E. Roman   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
8512e1d0745SJose E. Roman   PetscCall(ISGetIndices(globalPointNumbers, &gpoint));
8522e1d0745SJose E. Roman   for (p = pStart; p < pEnd; ++p) {
8532e1d0745SJose E. Roman     if (gpoint[p] >= 0) {
8542e1d0745SJose E. Roman       PetscInt coneSize;
8552e1d0745SJose E. Roman 
8562e1d0745SJose E. Roman       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
8572e1d0745SJose E. Roman       nPoints += 1;
8582e1d0745SJose E. Roman       conesSize += coneSize;
8592e1d0745SJose E. Roman     }
8602e1d0745SJose E. Roman   }
8612e1d0745SJose E. Roman   PetscCall(PetscMalloc1(nPoints, &coneSizes));
8622e1d0745SJose E. Roman   PetscCall(PetscMalloc1(conesSize, &cones));
8632e1d0745SJose E. Roman   PetscCall(PetscMalloc1(conesSize, &orientations));
8642e1d0745SJose E. Roman   for (p = pStart, c = 0, s = 0; p < pEnd; ++p) {
8652e1d0745SJose E. Roman     if (gpoint[p] >= 0) {
8662e1d0745SJose E. Roman       const PetscInt *cone, *ornt;
8672e1d0745SJose E. Roman       PetscInt        coneSize, cp;
8682e1d0745SJose E. Roman 
8692e1d0745SJose E. Roman       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
8702e1d0745SJose E. Roman       PetscCall(DMPlexGetCone(dm, p, &cone));
8712e1d0745SJose E. Roman       PetscCall(DMPlexGetConeOrientation(dm, p, &ornt));
8722e1d0745SJose E. Roman       coneSizes[s] = coneSize;
8732e1d0745SJose E. Roman       for (cp = 0; cp < coneSize; ++cp, ++c) {
8742e1d0745SJose E. Roman         cones[c]        = gpoint[cone[cp]] < 0 ? -(gpoint[cone[cp]] + 1) : gpoint[cone[cp]];
8752e1d0745SJose E. Roman         orientations[c] = ornt[cp];
8762e1d0745SJose E. Roman       }
8772e1d0745SJose E. Roman       ++s;
8782e1d0745SJose E. Roman     }
8792e1d0745SJose E. Roman   }
8802e1d0745SJose E. Roman   PetscCheck(s == nPoints, PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of points %" PetscInt_FMT " != %" PetscInt_FMT, s, nPoints);
8812e1d0745SJose E. Roman   PetscCheck(c == conesSize, PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of cone points %" PetscInt_FMT " != %" PetscInt_FMT, c, conesSize);
8822e1d0745SJose E. Roman   PetscCall(ISCreateGeneral(comm, nPoints, coneSizes, PETSC_OWN_POINTER, &coneSizesIS));
8832e1d0745SJose E. Roman   PetscCall(ISCreateGeneral(comm, conesSize, cones, PETSC_OWN_POINTER, &conesIS));
8842e1d0745SJose E. Roman   PetscCall(ISCreateGeneral(comm, conesSize, orientations, PETSC_OWN_POINTER, &orientationsIS));
8852e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)coneSizesIS, coneSizesName));
8862e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)conesIS, conesName));
8872e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)orientationsIS, orientationsName));
8885a236de6SSatish Balay   if (DMPlexStorageVersionGE(version, 3, 1, 0)) {
889ea87367fSMatthew G. Knepley     PetscCall(PetscViewerHDF5GetCompress(viewer, &ocompress));
890ea87367fSMatthew G. Knepley     PetscCall(PetscViewerHDF5SetCompress(viewer, PETSC_TRUE));
8915a236de6SSatish Balay   }
8922e1d0745SJose E. Roman   PetscCall(ISView(coneSizesIS, viewer));
8932e1d0745SJose E. Roman   PetscCall(ISView(conesIS, viewer));
8942e1d0745SJose E. Roman   PetscCall(ISView(orientationsIS, viewer));
8952e1d0745SJose E. Roman   PetscCall(ISDestroy(&coneSizesIS));
8962e1d0745SJose E. Roman   PetscCall(ISDestroy(&conesIS));
8972e1d0745SJose E. Roman   PetscCall(ISDestroy(&orientationsIS));
8982e1d0745SJose E. Roman   if (pointsName) {
8992e1d0745SJose E. Roman     IS        pointsIS;
9002e1d0745SJose E. Roman     PetscInt *points;
9012e1d0745SJose E. Roman 
9022e1d0745SJose E. Roman     PetscCall(PetscMalloc1(nPoints, &points));
9032e1d0745SJose E. Roman     for (p = pStart, c = 0, s = 0; p < pEnd; ++p) {
9042e1d0745SJose E. Roman       if (gpoint[p] >= 0) {
9052e1d0745SJose E. Roman         points[s] = gpoint[p];
9062e1d0745SJose E. Roman         ++s;
9072e1d0745SJose E. Roman       }
9082e1d0745SJose E. Roman     }
9092e1d0745SJose E. Roman     PetscCall(ISCreateGeneral(comm, nPoints, points, PETSC_OWN_POINTER, &pointsIS));
9102e1d0745SJose E. Roman     PetscCall(PetscObjectSetName((PetscObject)pointsIS, pointsName));
9112e1d0745SJose E. Roman     PetscCall(ISView(pointsIS, viewer));
9122e1d0745SJose E. Roman     PetscCall(ISDestroy(&pointsIS));
9132e1d0745SJose E. Roman   }
9142e1d0745SJose E. Roman   PetscCall(ISRestoreIndices(globalPointNumbers, &gpoint));
915ea87367fSMatthew G. Knepley   if (DMPlexStorageVersionGE(version, 3, 1, 0)) PetscCall(PetscViewerHDF5SetCompress(viewer, ocompress));
9162e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
9172e1d0745SJose E. Roman }
9182e1d0745SJose E. Roman 
DMPlexTopologyView_HDF5_Legacy_Private(DM dm,IS globalPointNumbers,PetscViewer viewer)9192e1d0745SJose E. Roman static PetscErrorCode DMPlexTopologyView_HDF5_Legacy_Private(DM dm, IS globalPointNumbers, PetscViewer viewer)
9202e1d0745SJose E. Roman {
9212e1d0745SJose E. Roman   const char *pointsName, *coneSizesName, *conesName, *orientationsName;
9222e1d0745SJose E. Roman   PetscInt    pStart, pEnd, dim;
9232e1d0745SJose E. Roman 
9242e1d0745SJose E. Roman   PetscFunctionBegin;
9252e1d0745SJose E. Roman   pointsName       = "order";
9262e1d0745SJose E. Roman   coneSizesName    = "cones";
9272e1d0745SJose E. Roman   conesName        = "cells";
9282e1d0745SJose E. Roman   orientationsName = "orientation";
9292e1d0745SJose E. Roman   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
9302e1d0745SJose E. Roman   PetscCall(DMPlexTopologyView_HDF5_Inner_Private(dm, globalPointNumbers, viewer, pStart, pEnd, pointsName, coneSizesName, conesName, orientationsName));
9312e1d0745SJose E. Roman   PetscCall(DMGetDimension(dm, &dim));
9322e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5WriteAttribute(viewer, conesName, "cell_dim", PETSC_INT, (void *)&dim));
9332e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
9342e1d0745SJose E. Roman }
9352e1d0745SJose E. Roman 
9362e1d0745SJose E. Roman //TODO get this numbering right away without needing this function
9372e1d0745SJose E. Roman /* Renumber global point numbers so that they are 0-based per stratum */
RenumberGlobalPointNumbersPerStratum_Private(DM dm,IS globalPointNumbers,IS * newGlobalPointNumbers,IS * strataPermutation)9382e1d0745SJose E. Roman static PetscErrorCode RenumberGlobalPointNumbersPerStratum_Private(DM dm, IS globalPointNumbers, IS *newGlobalPointNumbers, IS *strataPermutation)
9392e1d0745SJose E. Roman {
9402e1d0745SJose E. Roman   PetscInt        d, depth, p, n;
9412e1d0745SJose E. Roman   PetscInt       *offsets;
9422e1d0745SJose E. Roman   const PetscInt *gpn;
9432e1d0745SJose E. Roman   PetscInt       *ngpn;
9442e1d0745SJose E. Roman   MPI_Comm        comm;
9452e1d0745SJose E. Roman 
9462e1d0745SJose E. Roman   PetscFunctionBegin;
9472e1d0745SJose E. Roman   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
9482e1d0745SJose E. Roman   PetscCall(ISGetLocalSize(globalPointNumbers, &n));
9492e1d0745SJose E. Roman   PetscCall(ISGetIndices(globalPointNumbers, &gpn));
9502e1d0745SJose E. Roman   PetscCall(PetscMalloc1(n, &ngpn));
9512e1d0745SJose E. Roman   PetscCall(DMPlexGetDepth(dm, &depth));
9522e1d0745SJose E. Roman   PetscCall(PetscMalloc1(depth + 1, &offsets));
9532e1d0745SJose E. Roman   for (d = 0; d <= depth; d++) {
9542e1d0745SJose E. Roman     PetscInt pStart, pEnd;
9552e1d0745SJose E. Roman 
9562e1d0745SJose E. Roman     PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
9572e1d0745SJose E. Roman     offsets[d] = PETSC_INT_MAX;
9582e1d0745SJose E. Roman     for (p = pStart; p < pEnd; p++) {
9592e1d0745SJose E. Roman       if (gpn[p] >= 0 && gpn[p] < offsets[d]) offsets[d] = gpn[p];
9602e1d0745SJose E. Roman     }
9612e1d0745SJose E. Roman   }
9622e1d0745SJose E. Roman   PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, offsets, depth + 1, MPIU_INT, MPI_MIN, comm));
9632e1d0745SJose E. Roman   for (d = 0; d <= depth; d++) {
9642e1d0745SJose E. Roman     PetscInt pStart, pEnd;
9652e1d0745SJose E. Roman 
9662e1d0745SJose E. Roman     PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
9672e1d0745SJose E. Roman     for (p = pStart; p < pEnd; p++) ngpn[p] = gpn[p] - PetscSign(gpn[p]) * offsets[d];
9682e1d0745SJose E. Roman   }
9692e1d0745SJose E. Roman   PetscCall(ISRestoreIndices(globalPointNumbers, &gpn));
9702e1d0745SJose E. Roman   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)globalPointNumbers), n, ngpn, PETSC_OWN_POINTER, newGlobalPointNumbers));
9712e1d0745SJose E. Roman   {
9722e1d0745SJose E. Roman     PetscInt *perm;
9732e1d0745SJose E. Roman 
9742e1d0745SJose E. Roman     PetscCall(PetscMalloc1(depth + 1, &perm));
9752e1d0745SJose E. Roman     for (d = 0; d <= depth; d++) perm[d] = d;
9762e1d0745SJose E. Roman     PetscCall(PetscSortIntWithPermutation(depth + 1, offsets, perm));
9772e1d0745SJose E. Roman     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, depth + 1, perm, PETSC_OWN_POINTER, strataPermutation));
9782e1d0745SJose E. Roman   }
9792e1d0745SJose E. Roman   PetscCall(PetscFree(offsets));
9802e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
9812e1d0745SJose E. Roman }
9822e1d0745SJose E. Roman 
DMPlexTopologyView_HDF5_Private(DM dm,IS globalPointNumbers,PetscViewer viewer)9832e1d0745SJose E. Roman static PetscErrorCode DMPlexTopologyView_HDF5_Private(DM dm, IS globalPointNumbers, PetscViewer viewer)
9842e1d0745SJose E. Roman {
9852e1d0745SJose E. Roman   IS          globalPointNumbers0, strataPermutation;
9862e1d0745SJose E. Roman   const char *coneSizesName, *conesName, *orientationsName;
9872e1d0745SJose E. Roman   PetscInt    depth, d;
9882e1d0745SJose E. Roman   MPI_Comm    comm;
9892e1d0745SJose E. Roman 
9902e1d0745SJose E. Roman   PetscFunctionBegin;
9912e1d0745SJose E. Roman   coneSizesName    = "cone_sizes";
9922e1d0745SJose E. Roman   conesName        = "cones";
9932e1d0745SJose E. Roman   orientationsName = "orientations";
9942e1d0745SJose E. Roman   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
9952e1d0745SJose E. Roman   PetscCall(DMPlexGetDepth(dm, &depth));
9962e1d0745SJose E. Roman   {
9972e1d0745SJose E. Roman     PetscInt dim;
9982e1d0745SJose E. Roman 
9992e1d0745SJose E. Roman     PetscCall(DMGetDimension(dm, &dim));
10002e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5WriteAttribute(viewer, NULL, "cell_dim", PETSC_INT, &dim));
10012e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5WriteAttribute(viewer, NULL, "depth", PETSC_INT, &depth));
10022e1d0745SJose E. Roman   }
10032e1d0745SJose E. Roman 
10042e1d0745SJose E. Roman   PetscCall(RenumberGlobalPointNumbersPerStratum_Private(dm, globalPointNumbers, &globalPointNumbers0, &strataPermutation));
10052e1d0745SJose E. Roman   /* TODO dirty trick to save serial IS using the same parallel viewer */
10062e1d0745SJose E. Roman   {
10072e1d0745SJose E. Roman     IS              spOnComm;
10082e1d0745SJose E. Roman     PetscInt        n   = 0, N;
10092e1d0745SJose E. Roman     const PetscInt *idx = NULL;
10102e1d0745SJose E. Roman     const PetscInt *old;
10112e1d0745SJose E. Roman     PetscMPIInt     rank;
10122e1d0745SJose E. Roman 
10132e1d0745SJose E. Roman     PetscCallMPI(MPI_Comm_rank(comm, &rank));
10142e1d0745SJose E. Roman     PetscCall(ISGetLocalSize(strataPermutation, &N));
10152e1d0745SJose E. Roman     PetscCall(ISGetIndices(strataPermutation, &old));
10162e1d0745SJose E. Roman     if (!rank) {
10172e1d0745SJose E. Roman       n   = N;
10182e1d0745SJose E. Roman       idx = old;
10192e1d0745SJose E. Roman     }
10202e1d0745SJose E. Roman     PetscCall(ISCreateGeneral(comm, n, idx, PETSC_COPY_VALUES, &spOnComm));
10212e1d0745SJose E. Roman     PetscCall(ISRestoreIndices(strataPermutation, &old));
10222e1d0745SJose E. Roman     PetscCall(ISDestroy(&strataPermutation));
10232e1d0745SJose E. Roman     strataPermutation = spOnComm;
10242e1d0745SJose E. Roman   }
10252e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)strataPermutation, "permutation"));
10262e1d0745SJose E. Roman   PetscCall(ISView(strataPermutation, viewer));
10272e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "strata"));
10282e1d0745SJose E. Roman   for (d = 0; d <= depth; d++) {
10292e1d0745SJose E. Roman     PetscInt pStart, pEnd;
10302e1d0745SJose E. Roman     char     group[128];
10312e1d0745SJose E. Roman 
10322e1d0745SJose E. Roman     PetscCall(PetscSNPrintf(group, sizeof(group), "%" PetscInt_FMT, d));
10332e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5PushGroup(viewer, group));
10342e1d0745SJose E. Roman     PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
10352e1d0745SJose E. Roman     PetscCall(DMPlexTopologyView_HDF5_Inner_Private(dm, globalPointNumbers0, viewer, pStart, pEnd, NULL, coneSizesName, conesName, orientationsName));
10362e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5PopGroup(viewer));
10372e1d0745SJose E. Roman   }
10382e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer)); /* strata */
10392e1d0745SJose E. Roman   PetscCall(ISDestroy(&globalPointNumbers0));
10402e1d0745SJose E. Roman   PetscCall(ISDestroy(&strataPermutation));
10412e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
10422e1d0745SJose E. Roman }
10432e1d0745SJose E. Roman 
DMPlexTopologyView_HDF5_Internal(DM dm,IS globalPointNumbers,PetscViewer viewer)10442e1d0745SJose E. Roman PetscErrorCode DMPlexTopologyView_HDF5_Internal(DM dm, IS globalPointNumbers, PetscViewer viewer)
10452e1d0745SJose E. Roman {
10462e1d0745SJose E. Roman   DMPlexStorageVersion version;
10472e1d0745SJose E. Roman   const char          *topologydm_name;
10482e1d0745SJose E. Roman   char                 group[PETSC_MAX_PATH_LEN];
10492e1d0745SJose E. Roman 
10502e1d0745SJose E. Roman   PetscFunctionBegin;
10512e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5GetDMPlexStorageVersionWriting(viewer, &version));
10522e1d0745SJose E. Roman   PetscCall(PetscInfo(dm, "Writing DM %s storage version %d.%d.%d\n", dm->hdr.name, version->major, version->minor, version->subminor));
10532e1d0745SJose E. Roman   PetscCall(DMPlexGetHDF5Name_Private(dm, &topologydm_name));
10542e1d0745SJose E. Roman   if (DMPlexStorageVersionGE(version, 2, 0, 0)) {
10552e1d0745SJose E. Roman     PetscCall(PetscSNPrintf(group, sizeof(group), "topologies/%s", topologydm_name));
10562e1d0745SJose E. Roman   } else {
10572e1d0745SJose E. Roman     PetscCall(PetscStrncpy(group, "/", sizeof(group)));
10582e1d0745SJose E. Roman   }
10592e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, group));
10602e1d0745SJose E. Roman 
10612e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "topology"));
10622e1d0745SJose E. Roman   if (version->major < 3) {
10632e1d0745SJose E. Roman     PetscCall(DMPlexTopologyView_HDF5_Legacy_Private(dm, globalPointNumbers, viewer));
10642e1d0745SJose E. Roman   } else {
10652e1d0745SJose E. Roman     /* since DMPlexStorageVersion 3.0.0 */
10662e1d0745SJose E. Roman     PetscCall(DMPlexTopologyView_HDF5_Private(dm, globalPointNumbers, viewer));
10672e1d0745SJose E. Roman   }
10682e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer)); /* "topology" */
10692e1d0745SJose E. Roman 
10702e1d0745SJose E. Roman   if (DMPlexStorageVersionGE(version, 2, 1, 0)) {
10712e1d0745SJose E. Roman     const char *distribution_name;
10722e1d0745SJose E. Roman 
10732e1d0745SJose E. Roman     PetscCall(DMPlexDistributionGetName(dm, &distribution_name));
10742e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5PushGroup(viewer, "distributions"));
10752e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5WriteGroup(viewer, NULL));
10762e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5PushGroup(viewer, distribution_name));
10772e1d0745SJose E. Roman     PetscCall(DMPlexDistributionView_HDF5_Private(dm, globalPointNumbers, viewer));
10782e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5PopGroup(viewer)); /* distribution_name */
10792e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5PopGroup(viewer)); /* "distributions" */
10802e1d0745SJose E. Roman   }
10812e1d0745SJose E. Roman 
10822e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
10832e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
10842e1d0745SJose E. Roman }
10852e1d0745SJose E. Roman 
CreateConesIS_Private(DM dm,PetscInt cStart,PetscInt cEnd,IS globalCellNumbers,PetscInt * numCorners,IS * cellIS)10862e1d0745SJose E. Roman static PetscErrorCode CreateConesIS_Private(DM dm, PetscInt cStart, PetscInt cEnd, IS globalCellNumbers, PetscInt *numCorners, IS *cellIS)
10872e1d0745SJose E. Roman {
10882e1d0745SJose E. Roman   PetscSF         sfPoint;
10892e1d0745SJose E. Roman   DMLabel         cutLabel, cutVertexLabel         = NULL;
10902e1d0745SJose E. Roman   IS              globalVertexNumbers, cutvertices = NULL;
10912e1d0745SJose E. Roman   const PetscInt *gcell, *gvertex, *cutverts = NULL;
10922e1d0745SJose E. Roman   PetscInt       *vertices;
10932e1d0745SJose E. Roman   PetscInt        conesSize = 0;
10942e1d0745SJose E. Roman   PetscInt        dim, numCornersLocal = 0, cell, vStart, vEnd, vExtra = 0, v;
10952e1d0745SJose E. Roman 
10962e1d0745SJose E. Roman   PetscFunctionBegin;
10972e1d0745SJose E. Roman   *numCorners = 0;
10982e1d0745SJose E. Roman   PetscCall(DMGetDimension(dm, &dim));
10992e1d0745SJose E. Roman   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
11002e1d0745SJose E. Roman   PetscCall(ISGetIndices(globalCellNumbers, &gcell));
11012e1d0745SJose E. Roman 
11022e1d0745SJose E. Roman   for (cell = cStart; cell < cEnd; ++cell) {
11032e1d0745SJose E. Roman     PetscInt *closure = NULL;
11042e1d0745SJose E. Roman     PetscInt  closureSize, v, Nc = 0;
11052e1d0745SJose E. Roman 
11062e1d0745SJose E. Roman     if (gcell[cell] < 0) continue;
11072e1d0745SJose E. Roman     PetscCall(DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure));
11082e1d0745SJose E. Roman     for (v = 0; v < closureSize * 2; v += 2) {
11092e1d0745SJose E. Roman       if ((closure[v] >= vStart) && (closure[v] < vEnd)) ++Nc;
11102e1d0745SJose E. Roman     }
11112e1d0745SJose E. Roman     PetscCall(DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure));
11122e1d0745SJose E. Roman     conesSize += Nc;
11132e1d0745SJose E. Roman     if (!numCornersLocal) numCornersLocal = Nc;
11142e1d0745SJose E. Roman     else if (numCornersLocal != Nc) numCornersLocal = 1;
11152e1d0745SJose E. Roman   }
11162e1d0745SJose E. Roman   PetscCallMPI(MPIU_Allreduce(&numCornersLocal, numCorners, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
11172e1d0745SJose E. Roman   PetscCheck(!numCornersLocal || !(numCornersLocal != *numCorners || *numCorners == 0), PETSC_COMM_SELF, PETSC_ERR_SUP, "Visualization topology currently only supports identical cell shapes");
11182e1d0745SJose E. Roman   /* Handle periodic cuts by identifying vertices which should be duplicated */
11192e1d0745SJose E. Roman   PetscCall(DMGetLabel(dm, "periodic_cut", &cutLabel));
11202e1d0745SJose E. Roman   PetscCall(DMPlexCreateCutVertexLabel_Private(dm, cutLabel, &cutVertexLabel));
11212e1d0745SJose E. Roman   if (cutVertexLabel) PetscCall(DMLabelGetStratumIS(cutVertexLabel, 1, &cutvertices));
11222e1d0745SJose E. Roman   if (cutvertices) {
11232e1d0745SJose E. Roman     PetscCall(ISGetIndices(cutvertices, &cutverts));
11242e1d0745SJose E. Roman     PetscCall(ISGetLocalSize(cutvertices, &vExtra));
11252e1d0745SJose E. Roman   }
11262e1d0745SJose E. Roman   PetscCall(DMGetPointSF(dm, &sfPoint));
11272e1d0745SJose E. Roman   if (cutLabel) {
11282e1d0745SJose E. Roman     const PetscInt    *ilocal;
11292e1d0745SJose E. Roman     const PetscSFNode *iremote;
11302e1d0745SJose E. Roman     PetscInt           nroots, nleaves;
11312e1d0745SJose E. Roman 
11322e1d0745SJose E. Roman     PetscCall(PetscSFGetGraph(sfPoint, &nroots, &nleaves, &ilocal, &iremote));
11332e1d0745SJose E. Roman     if (nleaves < 0) {
11342e1d0745SJose E. Roman       PetscCall(PetscObjectReference((PetscObject)sfPoint));
11352e1d0745SJose E. Roman     } else {
11362e1d0745SJose E. Roman       PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)sfPoint), &sfPoint));
11372e1d0745SJose E. Roman       PetscCall(PetscSFSetGraph(sfPoint, nroots + vExtra, nleaves, (PetscInt *)ilocal, PETSC_COPY_VALUES, (PetscSFNode *)iremote, PETSC_COPY_VALUES));
11382e1d0745SJose E. Roman     }
11392e1d0745SJose E. Roman   } else {
11402e1d0745SJose E. Roman     PetscCall(PetscObjectReference((PetscObject)sfPoint));
11412e1d0745SJose E. Roman   }
11422e1d0745SJose E. Roman   /* Number all vertices */
11432e1d0745SJose E. Roman   PetscCall(DMPlexCreateNumbering_Plex(dm, vStart, vEnd + vExtra, 0, NULL, sfPoint, &globalVertexNumbers));
11442e1d0745SJose E. Roman   PetscCall(PetscSFDestroy(&sfPoint));
11452e1d0745SJose E. Roman   /* Create cones */
11462e1d0745SJose E. Roman   PetscCall(ISGetIndices(globalVertexNumbers, &gvertex));
11472e1d0745SJose E. Roman   PetscCall(PetscMalloc1(conesSize, &vertices));
11482e1d0745SJose E. Roman   for (cell = cStart, v = 0; cell < cEnd; ++cell) {
11492e1d0745SJose E. Roman     PetscInt *closure = NULL;
11502e1d0745SJose E. Roman     PetscInt  closureSize, Nc = 0, p, value = -1;
11512e1d0745SJose E. Roman     PetscBool replace;
11522e1d0745SJose E. Roman 
11532e1d0745SJose E. Roman     if (gcell[cell] < 0) continue;
11542e1d0745SJose E. Roman     if (cutLabel) PetscCall(DMLabelGetValue(cutLabel, cell, &value));
11552e1d0745SJose E. Roman     replace = (value == 2) ? PETSC_TRUE : PETSC_FALSE;
11562e1d0745SJose E. Roman     PetscCall(DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure));
11572e1d0745SJose E. Roman     for (p = 0; p < closureSize * 2; p += 2) {
11582e1d0745SJose E. Roman       if ((closure[p] >= vStart) && (closure[p] < vEnd)) closure[Nc++] = closure[p];
11592e1d0745SJose E. Roman     }
11602e1d0745SJose E. Roman     PetscCall(DMPlexReorderCell(dm, cell, closure));
11612e1d0745SJose E. Roman     for (p = 0; p < Nc; ++p) {
11622e1d0745SJose E. Roman       PetscInt nv, gv = gvertex[closure[p] - vStart];
11632e1d0745SJose E. Roman 
11642e1d0745SJose E. Roman       if (replace) {
11652e1d0745SJose E. Roman         PetscCall(PetscFindInt(closure[p], vExtra, cutverts, &nv));
11662e1d0745SJose E. Roman         if (nv >= 0) gv = gvertex[vEnd - vStart + nv];
11672e1d0745SJose E. Roman       }
11682e1d0745SJose E. Roman       vertices[v++] = gv < 0 ? -(gv + 1) : gv;
11692e1d0745SJose E. Roman     }
11702e1d0745SJose E. Roman     PetscCall(DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure));
11712e1d0745SJose E. Roman   }
11722e1d0745SJose E. Roman   PetscCall(ISRestoreIndices(globalVertexNumbers, &gvertex));
11732e1d0745SJose E. Roman   PetscCall(ISDestroy(&globalVertexNumbers));
11742e1d0745SJose E. Roman   PetscCall(ISRestoreIndices(globalCellNumbers, &gcell));
11752e1d0745SJose E. Roman   if (cutvertices) PetscCall(ISRestoreIndices(cutvertices, &cutverts));
11762e1d0745SJose E. Roman   PetscCall(ISDestroy(&cutvertices));
11772e1d0745SJose E. Roman   PetscCall(DMLabelDestroy(&cutVertexLabel));
11782e1d0745SJose E. Roman   PetscCheck(v == conesSize, PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of cell vertices %" PetscInt_FMT " != %" PetscInt_FMT, v, conesSize);
11792e1d0745SJose E. Roman   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), conesSize, vertices, PETSC_OWN_POINTER, cellIS));
11802e1d0745SJose E. Roman   PetscCall(PetscLayoutSetBlockSize((*cellIS)->map, *numCorners));
11812e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)*cellIS, "cells"));
11822e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
11832e1d0745SJose E. Roman }
11842e1d0745SJose E. Roman 
DMPlexTopologyView_HDF5_XDMF_Private(DM dm,IS globalCellNumbers,PetscViewer viewer)11852e1d0745SJose E. Roman static PetscErrorCode DMPlexTopologyView_HDF5_XDMF_Private(DM dm, IS globalCellNumbers, PetscViewer viewer)
11862e1d0745SJose E. Roman {
11872e1d0745SJose E. Roman   DM       cdm;
11882e1d0745SJose E. Roman   DMLabel  depthLabel, ctLabel;
11892e1d0745SJose E. Roman   IS       cellIS;
11902e1d0745SJose E. Roman   PetscInt dim, depth, cellHeight, c, n = 0;
11912e1d0745SJose E. Roman 
11922e1d0745SJose E. Roman   PetscFunctionBegin;
11932e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "/viz"));
11942e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5WriteGroup(viewer, NULL));
11952e1d0745SJose E. Roman 
11962e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
11972e1d0745SJose E. Roman   PetscCall(DMGetDimension(dm, &dim));
11982e1d0745SJose E. Roman   PetscCall(DMPlexGetDepth(dm, &depth));
11992e1d0745SJose E. Roman   PetscCall(DMGetCoordinateDM(dm, &cdm));
12002e1d0745SJose E. Roman   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
12012e1d0745SJose E. Roman   PetscCall(DMPlexGetDepthLabel(dm, &depthLabel));
12022e1d0745SJose E. Roman   PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel));
12032e1d0745SJose E. Roman   for (c = 0; c < DM_NUM_POLYTOPES; ++c) {
12042e1d0745SJose E. Roman     const DMPolytopeType ict = (DMPolytopeType)c;
12052e1d0745SJose E. Roman     PetscInt             pStart, pEnd, dep, numCorners;
12062e1d0745SJose E. Roman     PetscBool            output = PETSC_FALSE, doOutput;
12072e1d0745SJose E. Roman 
12082e1d0745SJose E. Roman     if (ict == DM_POLYTOPE_FV_GHOST) continue;
12092e1d0745SJose E. Roman     PetscCall(DMLabelGetStratumBounds(ctLabel, ict, &pStart, &pEnd));
12102e1d0745SJose E. Roman     if (pStart >= 0) {
12112e1d0745SJose E. Roman       PetscCall(DMLabelGetValue(depthLabel, pStart, &dep));
12122e1d0745SJose E. Roman       if (dep == depth - cellHeight) output = PETSC_TRUE;
12132e1d0745SJose E. Roman     }
12145440e5dcSBarry Smith     PetscCallMPI(MPIU_Allreduce(&output, &doOutput, 1, MPI_C_BOOL, MPI_LOR, PetscObjectComm((PetscObject)dm)));
12152e1d0745SJose E. Roman     if (!doOutput) continue;
12162e1d0745SJose E. Roman     PetscCall(CreateConesIS_Private(dm, pStart, pEnd, globalCellNumbers, &numCorners, &cellIS));
12172e1d0745SJose E. Roman     if (!n) {
12182e1d0745SJose E. Roman       PetscCall(PetscViewerHDF5PushGroup(viewer, "/viz/topology"));
12192e1d0745SJose E. Roman     } else {
12202e1d0745SJose E. Roman       char group[PETSC_MAX_PATH_LEN];
12212e1d0745SJose E. Roman 
12222e1d0745SJose E. Roman       PetscCall(PetscSNPrintf(group, PETSC_MAX_PATH_LEN, "/viz/topology_%" PetscInt_FMT, n));
12232e1d0745SJose E. Roman       PetscCall(PetscViewerHDF5PushGroup(viewer, group));
12242e1d0745SJose E. Roman     }
12252e1d0745SJose E. Roman     PetscCall(ISView(cellIS, viewer));
12262e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5WriteObjectAttribute(viewer, (PetscObject)cellIS, "cell_corners", PETSC_INT, (void *)&numCorners));
12272e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5WriteObjectAttribute(viewer, (PetscObject)cellIS, "cell_dim", PETSC_INT, (void *)&dim));
12282e1d0745SJose E. Roman     PetscCall(ISDestroy(&cellIS));
12292e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5PopGroup(viewer));
12302e1d0745SJose E. Roman     ++n;
12312e1d0745SJose E. Roman   }
12322e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
12332e1d0745SJose E. Roman }
12342e1d0745SJose E. Roman 
DMPlexCoordinatesView_HDF5_Legacy_Private(DM dm,PetscViewer viewer)12352e1d0745SJose E. Roman static PetscErrorCode DMPlexCoordinatesView_HDF5_Legacy_Private(DM dm, PetscViewer viewer)
12362e1d0745SJose E. Roman {
12372e1d0745SJose E. Roman   DM        cdm;
12382e1d0745SJose E. Roman   Vec       coordinates, newcoords;
12392e1d0745SJose E. Roman   PetscReal lengthScale;
12402e1d0745SJose E. Roman   PetscInt  m, M, bs;
12412e1d0745SJose E. Roman 
12422e1d0745SJose E. Roman   PetscFunctionBegin;
12432e1d0745SJose E. Roman   PetscCall(DMPlexGetScale(dm, PETSC_UNIT_LENGTH, &lengthScale));
12442e1d0745SJose E. Roman   PetscCall(DMGetCoordinateDM(dm, &cdm));
12452e1d0745SJose E. Roman   PetscCall(DMGetCoordinates(dm, &coordinates));
12462e1d0745SJose E. Roman   PetscCall(VecCreate(PetscObjectComm((PetscObject)coordinates), &newcoords));
12472e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)newcoords, "vertices"));
12482e1d0745SJose E. Roman   PetscCall(VecGetSize(coordinates, &M));
12492e1d0745SJose E. Roman   PetscCall(VecGetLocalSize(coordinates, &m));
12502e1d0745SJose E. Roman   PetscCall(VecSetSizes(newcoords, m, M));
12512e1d0745SJose E. Roman   PetscCall(VecGetBlockSize(coordinates, &bs));
12522e1d0745SJose E. Roman   PetscCall(VecSetBlockSize(newcoords, bs));
12532e1d0745SJose E. Roman   PetscCall(VecSetType(newcoords, VECSTANDARD));
12542e1d0745SJose E. Roman   PetscCall(VecCopy(coordinates, newcoords));
12552e1d0745SJose E. Roman   PetscCall(VecScale(newcoords, lengthScale));
12562e1d0745SJose E. Roman   /* Did not use DMGetGlobalVector() in order to bypass default group assignment */
12572e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "/geometry"));
12582e1d0745SJose E. Roman   PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_NATIVE));
12592e1d0745SJose E. Roman   PetscCall(VecView(newcoords, viewer));
12602e1d0745SJose E. Roman   PetscCall(PetscViewerPopFormat(viewer));
12612e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
12622e1d0745SJose E. Roman   PetscCall(VecDestroy(&newcoords));
12632e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
12642e1d0745SJose E. Roman }
12652e1d0745SJose E. Roman 
DMPlexCoordinatesView_HDF5_Internal(DM dm,PetscViewer viewer)12662e1d0745SJose E. Roman PetscErrorCode DMPlexCoordinatesView_HDF5_Internal(DM dm, PetscViewer viewer)
12672e1d0745SJose E. Roman {
12682e1d0745SJose E. Roman   DM                   cdm;
12692e1d0745SJose E. Roman   Vec                  coords, newcoords;
12702e1d0745SJose E. Roman   PetscInt             m, M, bs;
12712e1d0745SJose E. Roman   PetscReal            lengthScale;
1272ea87367fSMatthew G. Knepley   PetscBool            viewSection = PETSC_TRUE, ocompress;
12732e1d0745SJose E. Roman   const char          *topologydm_name, *coordinatedm_name, *coordinates_name;
12742e1d0745SJose E. Roman   PetscViewerFormat    format;
12752e1d0745SJose E. Roman   DMPlexStorageVersion version;
12762e1d0745SJose E. Roman 
1277ea87367fSMatthew G. Knepley   PetscFunctionBegin;
12782e1d0745SJose E. Roman   PetscCall(PetscViewerGetFormat(viewer, &format));
12792e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5GetDMPlexStorageVersionWriting(viewer, &version));
12802e1d0745SJose E. Roman   if (!DMPlexStorageVersionGE(version, 2, 0, 0) || format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) {
12812e1d0745SJose E. Roman     PetscCall(DMPlexCoordinatesView_HDF5_Legacy_Private(dm, viewer));
12822e1d0745SJose E. Roman     PetscFunctionReturn(PETSC_SUCCESS);
12832e1d0745SJose E. Roman   }
12842e1d0745SJose E. Roman   /* since 2.0.0 */
1285ea87367fSMatthew G. Knepley   if (DMPlexStorageVersionGE(version, 3, 1, 0)) {
1286ea87367fSMatthew G. Knepley     PetscCall(PetscViewerHDF5GetCompress(viewer, &ocompress));
1287ea87367fSMatthew G. Knepley     PetscCall(PetscViewerHDF5SetCompress(viewer, PETSC_TRUE));
1288ea87367fSMatthew G. Knepley   }
12892e1d0745SJose E. Roman   PetscCall(PetscOptionsGetBool(NULL, dm->hdr.prefix, "-dm_plex_view_coordinate_section", &viewSection, NULL));
12902e1d0745SJose E. Roman   PetscCall(DMGetCoordinateDM(dm, &cdm));
12912e1d0745SJose E. Roman   PetscCall(DMGetCoordinates(dm, &coords));
12922e1d0745SJose E. Roman   PetscCall(PetscObjectGetName((PetscObject)cdm, &coordinatedm_name));
12932e1d0745SJose E. Roman   PetscCall(PetscObjectGetName((PetscObject)coords, &coordinates_name));
12942e1d0745SJose E. Roman   PetscCall(DMPlexGetHDF5Name_Private(dm, &topologydm_name));
12952e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "topologies"));
12962e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, topologydm_name));
12972e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5WriteAttribute(viewer, NULL, "coordinateDMName", PETSC_STRING, coordinatedm_name));
12982e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5WriteAttribute(viewer, NULL, "coordinatesName", PETSC_STRING, coordinates_name));
12992e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
13002e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
13012e1d0745SJose E. Roman   if (viewSection) PetscCall(DMPlexSectionView(dm, viewer, cdm));
13022e1d0745SJose E. Roman   PetscCall(VecCreate(PetscObjectComm((PetscObject)coords), &newcoords));
13032e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)newcoords, coordinates_name));
13042e1d0745SJose E. Roman   PetscCall(VecGetSize(coords, &M));
13052e1d0745SJose E. Roman   PetscCall(VecGetLocalSize(coords, &m));
13062e1d0745SJose E. Roman   PetscCall(VecSetSizes(newcoords, m, M));
13072e1d0745SJose E. Roman   PetscCall(VecGetBlockSize(coords, &bs));
13082e1d0745SJose E. Roman   PetscCall(VecSetBlockSize(newcoords, bs));
13092e1d0745SJose E. Roman   PetscCall(VecSetType(newcoords, VECSTANDARD));
13102e1d0745SJose E. Roman   PetscCall(VecCopy(coords, newcoords));
13112e1d0745SJose E. Roman   PetscCall(DMPlexGetScale(dm, PETSC_UNIT_LENGTH, &lengthScale));
13122e1d0745SJose E. Roman   PetscCall(VecScale(newcoords, lengthScale));
13132e1d0745SJose E. Roman   PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_NATIVE));
13142e1d0745SJose E. Roman   PetscCall(DMPlexGlobalVectorView(dm, viewer, cdm, newcoords));
13152e1d0745SJose E. Roman   PetscCall(PetscViewerPopFormat(viewer));
13162e1d0745SJose E. Roman   PetscCall(VecDestroy(&newcoords));
1317ea87367fSMatthew G. Knepley   if (DMPlexStorageVersionGE(version, 3, 1, 0)) PetscCall(PetscViewerHDF5SetCompress(viewer, ocompress));
13182e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
13192e1d0745SJose E. Roman }
13202e1d0745SJose E. Roman 
DMPlexCoordinatesView_HDF5_XDMF_Private(DM dm,PetscViewer viewer)13212e1d0745SJose E. Roman static PetscErrorCode DMPlexCoordinatesView_HDF5_XDMF_Private(DM dm, PetscViewer viewer)
13222e1d0745SJose E. Roman {
13232e1d0745SJose E. Roman   DM               cdm;
13242e1d0745SJose E. Roman   Vec              coordinatesLocal, newcoords;
13252e1d0745SJose E. Roman   PetscSection     cSection, cGlobalSection;
13262e1d0745SJose E. Roman   PetscScalar     *coords, *ncoords;
13272e1d0745SJose E. Roman   DMLabel          cutLabel, cutVertexLabel = NULL;
13282e1d0745SJose E. Roman   const PetscReal *L;
13292e1d0745SJose E. Roman   PetscReal        lengthScale;
13302e1d0745SJose E. Roman   PetscInt         vStart, vEnd, v, bs, N, coordSize, dof, off, d;
13312e1d0745SJose E. Roman   PetscBool        localized, embedded;
13322e1d0745SJose E. Roman 
13332e1d0745SJose E. Roman   PetscFunctionBegin;
13342e1d0745SJose E. Roman   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
13352e1d0745SJose E. Roman   PetscCall(DMPlexGetScale(dm, PETSC_UNIT_LENGTH, &lengthScale));
13362e1d0745SJose E. Roman   PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal));
13372e1d0745SJose E. Roman   PetscCall(VecGetBlockSize(coordinatesLocal, &bs));
13382e1d0745SJose E. Roman   PetscCall(DMGetCoordinatesLocalized(dm, &localized));
13392e1d0745SJose E. Roman   if (localized == PETSC_FALSE) PetscFunctionReturn(PETSC_SUCCESS);
13402e1d0745SJose E. Roman   PetscCall(DMGetPeriodicity(dm, NULL, NULL, &L));
13412e1d0745SJose E. Roman   PetscCall(DMGetCoordinateDM(dm, &cdm));
13422e1d0745SJose E. Roman   PetscCall(DMGetLocalSection(cdm, &cSection));
13432e1d0745SJose E. Roman   PetscCall(DMGetGlobalSection(cdm, &cGlobalSection));
13442e1d0745SJose E. Roman   PetscCall(DMGetLabel(dm, "periodic_cut", &cutLabel));
13452e1d0745SJose E. Roman   N = 0;
13462e1d0745SJose E. Roman 
13472e1d0745SJose E. Roman   PetscCall(DMPlexCreateCutVertexLabel_Private(dm, cutLabel, &cutVertexLabel));
13482e1d0745SJose E. Roman   PetscCall(VecCreate(PetscObjectComm((PetscObject)dm), &newcoords));
13492e1d0745SJose E. Roman   PetscCall(PetscSectionGetDof(cSection, vStart, &dof));
13502e1d0745SJose E. Roman   PetscCall(PetscPrintf(PETSC_COMM_SELF, "DOF: %" PetscInt_FMT "\n", dof));
13512e1d0745SJose E. Roman   embedded = (PetscBool)(L && dof == 2 && !cutLabel);
13522e1d0745SJose E. Roman   if (cutVertexLabel) {
13532e1d0745SJose E. Roman     PetscCall(DMLabelGetStratumSize(cutVertexLabel, 1, &v));
13542e1d0745SJose E. Roman     N += dof * v;
13552e1d0745SJose E. Roman   }
13562e1d0745SJose E. Roman   for (v = vStart; v < vEnd; ++v) {
13572e1d0745SJose E. Roman     PetscCall(PetscSectionGetDof(cGlobalSection, v, &dof));
13582e1d0745SJose E. Roman     if (dof < 0) continue;
13592e1d0745SJose E. Roman     if (embedded) N += dof + 1;
13602e1d0745SJose E. Roman     else N += dof;
13612e1d0745SJose E. Roman   }
13622e1d0745SJose E. Roman   if (embedded) PetscCall(VecSetBlockSize(newcoords, bs + 1));
13632e1d0745SJose E. Roman   else PetscCall(VecSetBlockSize(newcoords, bs));
13642e1d0745SJose E. Roman   PetscCall(VecSetSizes(newcoords, N, PETSC_DETERMINE));
13652e1d0745SJose E. Roman   PetscCall(VecSetType(newcoords, VECSTANDARD));
13662e1d0745SJose E. Roman   PetscCall(VecGetArray(coordinatesLocal, &coords));
13672e1d0745SJose E. Roman   PetscCall(VecGetArray(newcoords, &ncoords));
13682e1d0745SJose E. Roman   coordSize = 0;
13692e1d0745SJose E. Roman   for (v = vStart; v < vEnd; ++v) {
13702e1d0745SJose E. Roman     PetscCall(PetscSectionGetDof(cGlobalSection, v, &dof));
13712e1d0745SJose E. Roman     PetscCall(PetscSectionGetOffset(cSection, v, &off));
13722e1d0745SJose E. Roman     if (dof < 0) continue;
13732e1d0745SJose E. Roman     if (embedded) {
13742e1d0745SJose E. Roman       if (L && (L[0] > 0.0) && (L[1] > 0.0)) {
13752e1d0745SJose E. Roman         PetscReal theta, phi, r, R;
13762e1d0745SJose E. Roman         /* XY-periodic */
13772e1d0745SJose E. Roman         /* Suppose its an y-z circle, then
13782e1d0745SJose E. Roman              \hat r = (0, cos(th), sin(th)) \hat x = (1, 0, 0)
13792e1d0745SJose E. Roman            and the circle in that plane is
13802e1d0745SJose E. Roman              \hat r cos(phi) + \hat x sin(phi) */
13812e1d0745SJose E. Roman         theta                = 2.0 * PETSC_PI * PetscRealPart(coords[off + 1]) / L[1];
13822e1d0745SJose E. Roman         phi                  = 2.0 * PETSC_PI * PetscRealPart(coords[off + 0]) / L[0];
13832e1d0745SJose E. Roman         r                    = L[0] / (2.0 * PETSC_PI * 2.0 * L[1]);
13842e1d0745SJose E. Roman         R                    = L[1] / (2.0 * PETSC_PI);
13852e1d0745SJose E. Roman         ncoords[coordSize++] = PetscSinReal(phi) * r;
13862e1d0745SJose E. Roman         ncoords[coordSize++] = -PetscCosReal(theta) * (R + r * PetscCosReal(phi));
13872e1d0745SJose E. Roman         ncoords[coordSize++] = PetscSinReal(theta) * (R + r * PetscCosReal(phi));
13882e1d0745SJose E. Roman       } else if (L && (L[0] > 0.0)) {
13892e1d0745SJose E. Roman         /* X-periodic */
13902e1d0745SJose E. Roman         ncoords[coordSize++] = -PetscCosReal(2.0 * PETSC_PI * PetscRealPart(coords[off + 0]) / L[0]) * (L[0] / (2.0 * PETSC_PI));
13912e1d0745SJose E. Roman         ncoords[coordSize++] = coords[off + 1];
13922e1d0745SJose E. Roman         ncoords[coordSize++] = PetscSinReal(2.0 * PETSC_PI * PetscRealPart(coords[off + 0]) / L[0]) * (L[0] / (2.0 * PETSC_PI));
13932e1d0745SJose E. Roman       } else if (L && (L[1] > 0.0)) {
13942e1d0745SJose E. Roman         /* Y-periodic */
13952e1d0745SJose E. Roman         ncoords[coordSize++] = coords[off + 0];
13962e1d0745SJose E. Roman         ncoords[coordSize++] = PetscSinReal(2.0 * PETSC_PI * PetscRealPart(coords[off + 1]) / L[1]) * (L[1] / (2.0 * PETSC_PI));
13972e1d0745SJose E. Roman         ncoords[coordSize++] = -PetscCosReal(2.0 * PETSC_PI * PetscRealPart(coords[off + 1]) / L[1]) * (L[1] / (2.0 * PETSC_PI));
13982e1d0745SJose E. Roman #if 0
13992e1d0745SJose E. Roman       } else if ((bd[0] == DM_BOUNDARY_TWIST)) {
14002e1d0745SJose E. Roman         PetscReal phi, r, R;
14012e1d0745SJose E. Roman         /* Mobius strip */
14022e1d0745SJose E. Roman         /* Suppose its an x-z circle, then
14032e1d0745SJose E. Roman              \hat r = (-cos(phi), 0, sin(phi)) \hat y = (0, 1, 0)
14042e1d0745SJose E. Roman            and in that plane we rotate by pi as we go around the circle
14052e1d0745SJose E. Roman              \hat r cos(phi/2) + \hat y sin(phi/2) */
14062e1d0745SJose E. Roman         phi   = 2.0*PETSC_PI*PetscRealPart(coords[off+0])/L[0];
14072e1d0745SJose E. Roman         R     = L[0];
14082e1d0745SJose E. Roman         r     = PetscRealPart(coords[off+1]) - L[1]/2.0;
14092e1d0745SJose E. Roman         ncoords[coordSize++] = -PetscCosReal(phi) * (R + r * PetscCosReal(phi/2.0));
14102e1d0745SJose E. Roman         ncoords[coordSize++] =  PetscSinReal(phi/2.0) * r;
14112e1d0745SJose E. Roman         ncoords[coordSize++] =  PetscSinReal(phi) * (R + r * PetscCosReal(phi/2.0));
14122e1d0745SJose E. Roman #endif
14132e1d0745SJose E. Roman       } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Cannot handle periodicity in this domain");
14142e1d0745SJose E. Roman     } else {
14152e1d0745SJose E. Roman       for (d = 0; d < dof; ++d, ++coordSize) ncoords[coordSize] = coords[off + d];
14162e1d0745SJose E. Roman     }
14172e1d0745SJose E. Roman   }
14182e1d0745SJose E. Roman   if (cutVertexLabel) {
14192e1d0745SJose E. Roman     IS              vertices;
14202e1d0745SJose E. Roman     const PetscInt *verts;
14212e1d0745SJose E. Roman     PetscInt        n;
14222e1d0745SJose E. Roman 
14232e1d0745SJose E. Roman     PetscCall(DMLabelGetStratumIS(cutVertexLabel, 1, &vertices));
14242e1d0745SJose E. Roman     if (vertices) {
14252e1d0745SJose E. Roman       PetscCall(ISGetIndices(vertices, &verts));
14262e1d0745SJose E. Roman       PetscCall(ISGetLocalSize(vertices, &n));
14272e1d0745SJose E. Roman       for (v = 0; v < n; ++v) {
14282e1d0745SJose E. Roman         PetscCall(PetscSectionGetDof(cSection, verts[v], &dof));
14292e1d0745SJose E. Roman         PetscCall(PetscSectionGetOffset(cSection, verts[v], &off));
14302e1d0745SJose E. Roman         for (d = 0; d < dof; ++d) ncoords[coordSize++] = coords[off + d] + ((L[d] > 0.) ? L[d] : 0.0);
14312e1d0745SJose E. Roman       }
14322e1d0745SJose E. Roman       PetscCall(ISRestoreIndices(vertices, &verts));
14332e1d0745SJose E. Roman       PetscCall(ISDestroy(&vertices));
14342e1d0745SJose E. Roman     }
14352e1d0745SJose E. Roman   }
14362e1d0745SJose E. Roman   PetscCheck(coordSize == N, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched sizes: %" PetscInt_FMT " != %" PetscInt_FMT, coordSize, N);
14372e1d0745SJose E. Roman   PetscCall(DMLabelDestroy(&cutVertexLabel));
14382e1d0745SJose E. Roman   PetscCall(VecRestoreArray(coordinatesLocal, &coords));
14392e1d0745SJose E. Roman   PetscCall(VecRestoreArray(newcoords, &ncoords));
14402e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)newcoords, "vertices"));
14412e1d0745SJose E. Roman   PetscCall(VecScale(newcoords, lengthScale));
14422e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "/viz"));
14432e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5WriteGroup(viewer, NULL));
14442e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
14452e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "/viz/geometry"));
14462e1d0745SJose E. Roman   PetscCall(VecView(newcoords, viewer));
14472e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
14482e1d0745SJose E. Roman   PetscCall(VecDestroy(&newcoords));
14492e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
14502e1d0745SJose E. Roman }
14512e1d0745SJose E. Roman 
DMPlexLabelsView_HDF5_Internal(DM dm,IS globalPointNumbers,PetscViewer viewer)14522e1d0745SJose E. Roman PetscErrorCode DMPlexLabelsView_HDF5_Internal(DM dm, IS globalPointNumbers, PetscViewer viewer)
14532e1d0745SJose E. Roman {
14542e1d0745SJose E. Roman   const char          *topologydm_name;
14552e1d0745SJose E. Roman   const PetscInt      *gpoint;
14562e1d0745SJose E. Roman   PetscInt             numLabels;
1457ea87367fSMatthew G. Knepley   PetscBool            omitCelltypes = PETSC_FALSE, ocompress;
14582e1d0745SJose E. Roman   DMPlexStorageVersion version;
14592e1d0745SJose E. Roman   char                 group[PETSC_MAX_PATH_LEN];
14602e1d0745SJose E. Roman 
14612e1d0745SJose E. Roman   PetscFunctionBegin;
14622e1d0745SJose E. Roman   PetscCall(PetscOptionsGetBool(NULL, dm->hdr.prefix, "-dm_plex_omit_celltypes", &omitCelltypes, NULL));
14632e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5GetDMPlexStorageVersionWriting(viewer, &version));
1464ea87367fSMatthew G. Knepley   if (DMPlexStorageVersionGE(version, 3, 1, 0)) {
1465ea87367fSMatthew G. Knepley     PetscCall(PetscViewerHDF5GetCompress(viewer, &ocompress));
1466ea87367fSMatthew G. Knepley     PetscCall(PetscViewerHDF5SetCompress(viewer, PETSC_TRUE));
1467ea87367fSMatthew G. Knepley   }
14682e1d0745SJose E. Roman   PetscCall(ISGetIndices(globalPointNumbers, &gpoint));
14692e1d0745SJose E. Roman   PetscCall(DMPlexGetHDF5Name_Private(dm, &topologydm_name));
14702e1d0745SJose E. Roman   if (DMPlexStorageVersionGE(version, 2, 0, 0)) {
14712e1d0745SJose E. Roman     PetscCall(PetscSNPrintf(group, sizeof(group), "topologies/%s/labels", topologydm_name));
14722e1d0745SJose E. Roman   } else {
14732e1d0745SJose E. Roman     PetscCall(PetscStrncpy(group, "/labels", sizeof(group)));
14742e1d0745SJose E. Roman   }
14752e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, group));
14762e1d0745SJose E. Roman   PetscCall(DMGetNumLabels(dm, &numLabels));
14772e1d0745SJose E. Roman   for (PetscInt l = 0; l < numLabels; ++l) {
14782e1d0745SJose E. Roman     DMLabel         label;
14792e1d0745SJose E. Roman     const char     *name;
14802e1d0745SJose E. Roman     IS              valueIS, pvalueIS, globalValueIS;
14812e1d0745SJose E. Roman     const PetscInt *values;
14822e1d0745SJose E. Roman     PetscInt        numValues, v;
14832e1d0745SJose E. Roman     PetscBool       isDepth, isCelltype, output;
14842e1d0745SJose E. Roman 
14852e1d0745SJose E. Roman     PetscCall(DMGetLabelByNum(dm, l, &label));
14862e1d0745SJose E. Roman     PetscCall(PetscObjectGetName((PetscObject)label, &name));
14872e1d0745SJose E. Roman     PetscCall(DMGetLabelOutput(dm, name, &output));
14882e1d0745SJose E. Roman     PetscCall(PetscStrncmp(name, "depth", 10, &isDepth));
14892e1d0745SJose E. Roman     PetscCall(PetscStrncmp(name, "celltype", 10, &isCelltype));
14902e1d0745SJose E. Roman     // TODO Should only filter out celltype if it can be calculated
14912e1d0745SJose E. Roman     if (isDepth || (isCelltype && omitCelltypes) || !output) continue;
14922e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5PushGroup(viewer, name));
14932e1d0745SJose E. Roman     PetscCall(DMLabelGetValueIS(label, &valueIS));
14942e1d0745SJose E. Roman     /* Must copy to a new IS on the global comm */
14952e1d0745SJose E. Roman     PetscCall(ISGetLocalSize(valueIS, &numValues));
14962e1d0745SJose E. Roman     PetscCall(ISGetIndices(valueIS, &values));
14972e1d0745SJose E. Roman     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), numValues, values, PETSC_COPY_VALUES, &pvalueIS));
14982e1d0745SJose E. Roman     PetscCall(ISRestoreIndices(valueIS, &values));
14992e1d0745SJose E. Roman     PetscCall(ISAllGather(pvalueIS, &globalValueIS));
15002e1d0745SJose E. Roman     PetscCall(ISDestroy(&pvalueIS));
15012e1d0745SJose E. Roman     PetscCall(ISSortRemoveDups(globalValueIS));
15022e1d0745SJose E. Roman     PetscCall(ISGetLocalSize(globalValueIS, &numValues));
15032e1d0745SJose E. Roman     PetscCall(ISGetIndices(globalValueIS, &values));
15042e1d0745SJose E. Roman     for (v = 0; v < numValues; ++v) {
15052e1d0745SJose E. Roman       IS              stratumIS, globalStratumIS;
15062e1d0745SJose E. Roman       const PetscInt *spoints = NULL;
15072e1d0745SJose E. Roman       PetscInt       *gspoints, n = 0, gn, p;
15082e1d0745SJose E. Roman       const char     *iname = "indices";
15092e1d0745SJose E. Roman       char            group[PETSC_MAX_PATH_LEN];
15102e1d0745SJose E. Roman 
15112e1d0745SJose E. Roman       PetscCall(PetscSNPrintf(group, sizeof(group), "%" PetscInt_FMT, values[v]));
15122e1d0745SJose E. Roman       PetscCall(PetscViewerHDF5PushGroup(viewer, group));
15132e1d0745SJose E. Roman       PetscCall(DMLabelGetStratumIS(label, values[v], &stratumIS));
15142e1d0745SJose E. Roman 
15152e1d0745SJose E. Roman       if (stratumIS) PetscCall(ISGetLocalSize(stratumIS, &n));
15162e1d0745SJose E. Roman       if (stratumIS) PetscCall(ISGetIndices(stratumIS, &spoints));
15172e1d0745SJose E. Roman       for (gn = 0, p = 0; p < n; ++p)
15182e1d0745SJose E. Roman         if (gpoint[spoints[p]] >= 0) ++gn;
15192e1d0745SJose E. Roman       PetscCall(PetscMalloc1(gn, &gspoints));
15202e1d0745SJose E. Roman       for (gn = 0, p = 0; p < n; ++p)
15212e1d0745SJose E. Roman         if (gpoint[spoints[p]] >= 0) gspoints[gn++] = gpoint[spoints[p]];
15222e1d0745SJose E. Roman       if (stratumIS) PetscCall(ISRestoreIndices(stratumIS, &spoints));
15232e1d0745SJose E. Roman       PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), gn, gspoints, PETSC_OWN_POINTER, &globalStratumIS));
15242e1d0745SJose E. Roman       PetscCall(PetscObjectSetName((PetscObject)globalStratumIS, iname));
15252e1d0745SJose E. Roman       PetscCall(ISView(globalStratumIS, viewer));
15262e1d0745SJose E. Roman       PetscCall(ISDestroy(&globalStratumIS));
15272e1d0745SJose E. Roman       PetscCall(ISDestroy(&stratumIS));
15282e1d0745SJose E. Roman       PetscCall(PetscViewerHDF5PopGroup(viewer));
15292e1d0745SJose E. Roman     }
15302e1d0745SJose E. Roman     PetscCall(ISRestoreIndices(globalValueIS, &values));
15312e1d0745SJose E. Roman     PetscCall(ISDestroy(&globalValueIS));
15322e1d0745SJose E. Roman     PetscCall(ISDestroy(&valueIS));
15332e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5PopGroup(viewer));
15342e1d0745SJose E. Roman   }
15352e1d0745SJose E. Roman   PetscCall(ISRestoreIndices(globalPointNumbers, &gpoint));
15362e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
1537ea87367fSMatthew G. Knepley   if (DMPlexStorageVersionGE(version, 3, 1, 0)) PetscCall(PetscViewerHDF5SetCompress(viewer, ocompress));
15382e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
15392e1d0745SJose E. Roman }
15402e1d0745SJose E. Roman 
15412e1d0745SJose E. Roman /* We only write cells and vertices. Does this screw up parallel reading? */
DMPlexView_HDF5_Internal(DM dm,PetscViewer viewer)15422e1d0745SJose E. Roman PetscErrorCode DMPlexView_HDF5_Internal(DM dm, PetscViewer viewer)
15432e1d0745SJose E. Roman {
15442e1d0745SJose E. Roman   IS                globalPointNumbers;
15452e1d0745SJose E. Roman   PetscViewerFormat format;
1546298ebf1dSStefano Zampini   PetscBool         viz_geom = PETSC_FALSE, xdmf_topo = PETSC_FALSE, petsc_topo = PETSC_FALSE, view_rank = PETSC_FALSE;
15472e1d0745SJose E. Roman 
15482e1d0745SJose E. Roman   PetscFunctionBegin;
15492e1d0745SJose E. Roman   PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbers));
15502e1d0745SJose E. Roman   PetscCall(DMPlexCoordinatesView_HDF5_Internal(dm, viewer));
15512e1d0745SJose E. Roman 
15522e1d0745SJose E. Roman   PetscCall(PetscViewerGetFormat(viewer, &format));
15532e1d0745SJose E. Roman   switch (format) {
15542e1d0745SJose E. Roman   case PETSC_VIEWER_HDF5_VIZ:
15552e1d0745SJose E. Roman     viz_geom  = PETSC_TRUE;
15562e1d0745SJose E. Roman     xdmf_topo = PETSC_TRUE;
1557298ebf1dSStefano Zampini     view_rank = PETSC_TRUE;
15582e1d0745SJose E. Roman     break;
15592e1d0745SJose E. Roman   case PETSC_VIEWER_HDF5_XDMF:
15602e1d0745SJose E. Roman     xdmf_topo = PETSC_TRUE;
15612e1d0745SJose E. Roman     break;
15622e1d0745SJose E. Roman   case PETSC_VIEWER_HDF5_PETSC:
15632e1d0745SJose E. Roman     petsc_topo = PETSC_TRUE;
15642e1d0745SJose E. Roman     break;
15652e1d0745SJose E. Roman   case PETSC_VIEWER_DEFAULT:
15662e1d0745SJose E. Roman   case PETSC_VIEWER_NATIVE:
15672e1d0745SJose E. Roman     viz_geom   = PETSC_TRUE;
15682e1d0745SJose E. Roman     xdmf_topo  = PETSC_TRUE;
15692e1d0745SJose E. Roman     petsc_topo = PETSC_TRUE;
15702e1d0745SJose E. Roman     break;
15712e1d0745SJose E. Roman   default:
15722e1d0745SJose E. Roman     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]);
15732e1d0745SJose E. Roman   }
15742e1d0745SJose E. Roman 
15752e1d0745SJose E. Roman   if (viz_geom) PetscCall(DMPlexCoordinatesView_HDF5_XDMF_Private(dm, viewer));
15762e1d0745SJose E. Roman   if (xdmf_topo) PetscCall(DMPlexTopologyView_HDF5_XDMF_Private(dm, globalPointNumbers, viewer));
15772e1d0745SJose E. Roman   if (petsc_topo) {
15782e1d0745SJose E. Roman     PetscBool viewLabels = PETSC_TRUE;
15792e1d0745SJose E. Roman 
15802e1d0745SJose E. Roman     PetscCall(DMPlexTopologyView_HDF5_Internal(dm, globalPointNumbers, viewer));
15812e1d0745SJose E. Roman     PetscCall(PetscOptionsGetBool(NULL, dm->hdr.prefix, "-dm_plex_view_labels", &viewLabels, NULL));
15822e1d0745SJose E. Roman     if (viewLabels) PetscCall(DMPlexLabelsView_HDF5_Internal(dm, globalPointNumbers, viewer));
15832e1d0745SJose E. Roman   }
1584298ebf1dSStefano Zampini   if (view_rank) {
1585298ebf1dSStefano Zampini     Vec v;
15862e1d0745SJose E. Roman 
1587298ebf1dSStefano Zampini     PetscCall(DMPlexCreateRankField(dm, &v));
1588298ebf1dSStefano Zampini     PetscCall(VecView(v, viewer));
1589298ebf1dSStefano Zampini     PetscCall(VecDestroy(&v));
1590298ebf1dSStefano Zampini   }
15912e1d0745SJose E. Roman   PetscCall(ISDestroy(&globalPointNumbers));
15922e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
15932e1d0745SJose E. Roman }
15942e1d0745SJose E. Roman 
DMPlexSectionView_HDF5_Internal(DM dm,PetscViewer viewer,DM sectiondm)15952e1d0745SJose E. Roman PetscErrorCode DMPlexSectionView_HDF5_Internal(DM dm, PetscViewer viewer, DM sectiondm)
15962e1d0745SJose E. Roman {
15975a236de6SSatish Balay   DMPlexStorageVersion version;
15982e1d0745SJose E. Roman   MPI_Comm             comm;
15992e1d0745SJose E. Roman   const char          *topologydm_name;
16002e1d0745SJose E. Roman   const char          *sectiondm_name;
16012e1d0745SJose E. Roman   PetscSection         gsection;
1602ea87367fSMatthew G. Knepley   PetscBool            ocompress;
16032e1d0745SJose E. Roman 
16042e1d0745SJose E. Roman   PetscFunctionBegin;
16055a236de6SSatish Balay   PetscCall(PetscViewerHDF5GetDMPlexStorageVersionWriting(viewer, &version));
1606ea87367fSMatthew G. Knepley   if (DMPlexStorageVersionGE(version, 3, 1, 0)) {
1607ea87367fSMatthew G. Knepley     PetscCall(PetscViewerHDF5GetCompress(viewer, &ocompress));
1608ea87367fSMatthew G. Knepley     PetscCall(PetscViewerHDF5SetCompress(viewer, PETSC_TRUE));
1609ea87367fSMatthew G. Knepley   }
16102e1d0745SJose E. Roman   PetscCall(PetscObjectGetComm((PetscObject)sectiondm, &comm));
16112e1d0745SJose E. Roman   PetscCall(DMPlexGetHDF5Name_Private(dm, &topologydm_name));
16122e1d0745SJose E. Roman   PetscCall(PetscObjectGetName((PetscObject)sectiondm, &sectiondm_name));
16132e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "topologies"));
16142e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, topologydm_name));
16152e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "dms"));
16162e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, sectiondm_name));
16172e1d0745SJose E. Roman   PetscCall(DMGetGlobalSection(sectiondm, &gsection));
16182e1d0745SJose E. Roman   /* Save raw section */
16192e1d0745SJose E. Roman   PetscCall(PetscSectionView(gsection, viewer));
16202e1d0745SJose E. Roman   /* Save plex wrapper */
16212e1d0745SJose E. Roman   {
16222e1d0745SJose E. Roman     PetscInt        pStart, pEnd, p, n;
16232e1d0745SJose E. Roman     IS              globalPointNumbers;
16242e1d0745SJose E. Roman     const PetscInt *gpoints;
16252e1d0745SJose E. Roman     IS              orderIS;
16262e1d0745SJose E. Roman     PetscInt       *order;
16272e1d0745SJose E. Roman 
16282e1d0745SJose E. Roman     PetscCall(PetscSectionGetChart(gsection, &pStart, &pEnd));
16292e1d0745SJose E. Roman     PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbers));
16302e1d0745SJose E. Roman     PetscCall(ISGetIndices(globalPointNumbers, &gpoints));
16312e1d0745SJose E. Roman     for (p = pStart, n = 0; p < pEnd; ++p)
16322e1d0745SJose E. Roman       if (gpoints[p] >= 0) n++;
16332e1d0745SJose E. Roman     /* "order" is an array of global point numbers.
16342e1d0745SJose E. Roman        When loading, it is used with topology/order array
16352e1d0745SJose E. Roman        to match section points with plex topology points. */
16362e1d0745SJose E. Roman     PetscCall(PetscMalloc1(n, &order));
16372e1d0745SJose E. Roman     for (p = pStart, n = 0; p < pEnd; ++p)
16382e1d0745SJose E. Roman       if (gpoints[p] >= 0) order[n++] = gpoints[p];
16392e1d0745SJose E. Roman     PetscCall(ISRestoreIndices(globalPointNumbers, &gpoints));
16402e1d0745SJose E. Roman     PetscCall(ISDestroy(&globalPointNumbers));
16412e1d0745SJose E. Roman     PetscCall(ISCreateGeneral(comm, n, order, PETSC_OWN_POINTER, &orderIS));
16422e1d0745SJose E. Roman     PetscCall(PetscObjectSetName((PetscObject)orderIS, "order"));
16432e1d0745SJose E. Roman     PetscCall(ISView(orderIS, viewer));
16442e1d0745SJose E. Roman     PetscCall(ISDestroy(&orderIS));
16452e1d0745SJose E. Roman   }
16462e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
16472e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
16482e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
16492e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
1650ea87367fSMatthew G. Knepley   if (DMPlexStorageVersionGE(version, 3, 1, 0)) PetscCall(PetscViewerHDF5SetCompress(viewer, ocompress));
16512e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
16522e1d0745SJose E. Roman }
16532e1d0745SJose E. Roman 
DMPlexGlobalVectorView_HDF5_Internal(DM dm,PetscViewer viewer,DM sectiondm,Vec vec)16542e1d0745SJose E. Roman PetscErrorCode DMPlexGlobalVectorView_HDF5_Internal(DM dm, PetscViewer viewer, DM sectiondm, Vec vec)
16552e1d0745SJose E. Roman {
16562e1d0745SJose E. Roman   const char *topologydm_name;
16572e1d0745SJose E. Roman   const char *sectiondm_name;
16582e1d0745SJose E. Roman   const char *vec_name;
16592e1d0745SJose E. Roman   PetscInt    bs;
16602e1d0745SJose E. Roman 
16612e1d0745SJose E. Roman   PetscFunctionBegin;
16622e1d0745SJose E. Roman   /* Check consistency */
16632e1d0745SJose E. Roman   {
16642e1d0745SJose E. Roman     PetscSF pointsf, pointsf1;
16652e1d0745SJose E. Roman 
16662e1d0745SJose E. Roman     PetscCall(DMGetPointSF(dm, &pointsf));
16672e1d0745SJose E. Roman     PetscCall(DMGetPointSF(sectiondm, &pointsf1));
16682e1d0745SJose E. Roman     PetscCheck(pointsf1 == pointsf, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatching point SFs for dm and sectiondm");
16692e1d0745SJose E. Roman   }
16702e1d0745SJose E. Roman   PetscCall(DMPlexGetHDF5Name_Private(dm, &topologydm_name));
16712e1d0745SJose E. Roman   PetscCall(PetscObjectGetName((PetscObject)sectiondm, &sectiondm_name));
16722e1d0745SJose E. Roman   PetscCall(PetscObjectGetName((PetscObject)vec, &vec_name));
16732e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "topologies"));
16742e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, topologydm_name));
16752e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "dms"));
16762e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, sectiondm_name));
16772e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "vecs"));
16782e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, vec_name));
16792e1d0745SJose E. Roman   PetscCall(VecGetBlockSize(vec, &bs));
16802e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5WriteAttribute(viewer, NULL, "blockSize", PETSC_INT, (void *)&bs));
16812e1d0745SJose E. Roman   PetscCall(VecSetBlockSize(vec, 1));
16822e1d0745SJose E. Roman   /* VecView(vec, viewer) would call (*vec->opt->view)(vec, viewer), but,    */
16832e1d0745SJose E. Roman   /* if vec was created with DMGet{Global, Local}Vector(), vec->opt->view    */
16842e1d0745SJose E. Roman   /* is set to VecView_Plex, which would save vec in a predefined location.  */
16852e1d0745SJose E. Roman   /* To save vec in where we want, we create a new Vec (temp) with           */
16862e1d0745SJose E. Roman   /* VecCreate(), wrap the vec data in temp, and call VecView(temp, viewer). */
16872e1d0745SJose E. Roman   {
16882e1d0745SJose E. Roman     Vec                temp;
16892e1d0745SJose E. Roman     const PetscScalar *array;
16902e1d0745SJose E. Roman     PetscLayout        map;
16912e1d0745SJose E. Roman 
16922e1d0745SJose E. Roman     PetscCall(VecCreate(PetscObjectComm((PetscObject)vec), &temp));
16932e1d0745SJose E. Roman     PetscCall(PetscObjectSetName((PetscObject)temp, vec_name));
16942e1d0745SJose E. Roman     PetscCall(VecGetLayout(vec, &map));
16952e1d0745SJose E. Roman     PetscCall(VecSetLayout(temp, map));
16962e1d0745SJose E. Roman     PetscCall(VecSetUp(temp));
16972e1d0745SJose E. Roman     PetscCall(VecGetArrayRead(vec, &array));
16982e1d0745SJose E. Roman     PetscCall(VecPlaceArray(temp, array));
16992e1d0745SJose E. Roman     PetscCall(VecView(temp, viewer));
17002e1d0745SJose E. Roman     PetscCall(VecResetArray(temp));
17012e1d0745SJose E. Roman     PetscCall(VecRestoreArrayRead(vec, &array));
17022e1d0745SJose E. Roman     PetscCall(VecDestroy(&temp));
17032e1d0745SJose E. Roman   }
17042e1d0745SJose E. Roman   PetscCall(VecSetBlockSize(vec, bs));
17052e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
17062e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
17072e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
17082e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
17092e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
17102e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
17112e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
17122e1d0745SJose E. Roman }
17132e1d0745SJose E. Roman 
DMPlexLocalVectorView_HDF5_Internal(DM dm,PetscViewer viewer,DM sectiondm,Vec vec)17142e1d0745SJose E. Roman PetscErrorCode DMPlexLocalVectorView_HDF5_Internal(DM dm, PetscViewer viewer, DM sectiondm, Vec vec)
17152e1d0745SJose E. Roman {
17162e1d0745SJose E. Roman   MPI_Comm     comm;
17172e1d0745SJose E. Roman   const char  *topologydm_name;
17182e1d0745SJose E. Roman   const char  *sectiondm_name;
17192e1d0745SJose E. Roman   const char  *vec_name;
17202e1d0745SJose E. Roman   PetscSection section;
17212e1d0745SJose E. Roman   PetscBool    includesConstraints;
17222e1d0745SJose E. Roman   Vec          gvec;
17232e1d0745SJose E. Roman   PetscInt     m, bs;
17242e1d0745SJose E. Roman 
17252e1d0745SJose E. Roman   PetscFunctionBegin;
17262e1d0745SJose E. Roman   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
17272e1d0745SJose E. Roman   /* Check consistency */
17282e1d0745SJose E. Roman   {
17292e1d0745SJose E. Roman     PetscSF pointsf, pointsf1;
17302e1d0745SJose E. Roman 
17312e1d0745SJose E. Roman     PetscCall(DMGetPointSF(dm, &pointsf));
17322e1d0745SJose E. Roman     PetscCall(DMGetPointSF(sectiondm, &pointsf1));
17332e1d0745SJose E. Roman     PetscCheck(pointsf1 == pointsf, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatching point SFs for dm and sectiondm");
17342e1d0745SJose E. Roman   }
17352e1d0745SJose E. Roman   PetscCall(DMPlexGetHDF5Name_Private(dm, &topologydm_name));
17362e1d0745SJose E. Roman   PetscCall(PetscObjectGetName((PetscObject)sectiondm, &sectiondm_name));
17372e1d0745SJose E. Roman   PetscCall(PetscObjectGetName((PetscObject)vec, &vec_name));
17382e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "topologies"));
17392e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, topologydm_name));
17402e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "dms"));
17412e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, sectiondm_name));
17422e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "vecs"));
17432e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, vec_name));
17442e1d0745SJose E. Roman   PetscCall(VecGetBlockSize(vec, &bs));
17452e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5WriteAttribute(viewer, NULL, "blockSize", PETSC_INT, (void *)&bs));
17462e1d0745SJose E. Roman   PetscCall(VecCreate(comm, &gvec));
17472e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)gvec, vec_name));
17482e1d0745SJose E. Roman   PetscCall(DMGetGlobalSection(sectiondm, &section));
17492e1d0745SJose E. Roman   PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
17502e1d0745SJose E. Roman   if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
17512e1d0745SJose E. Roman   else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
17522e1d0745SJose E. Roman   PetscCall(VecSetSizes(gvec, m, PETSC_DECIDE));
17532e1d0745SJose E. Roman   PetscCall(VecSetUp(gvec));
17542e1d0745SJose E. Roman   PetscCall(DMLocalToGlobalBegin(sectiondm, vec, INSERT_VALUES, gvec));
17552e1d0745SJose E. Roman   PetscCall(DMLocalToGlobalEnd(sectiondm, vec, INSERT_VALUES, gvec));
17562e1d0745SJose E. Roman   PetscCall(VecView(gvec, viewer));
17572e1d0745SJose E. Roman   PetscCall(VecDestroy(&gvec));
17582e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
17592e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
17602e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
17612e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
17622e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
17632e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
17642e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
17652e1d0745SJose E. Roman }
17662e1d0745SJose E. Roman 
17672e1d0745SJose E. Roman struct _n_LoadLabelsCtx {
17682e1d0745SJose E. Roman   MPI_Comm    comm;
17692e1d0745SJose E. Roman   PetscMPIInt rank;
17702e1d0745SJose E. Roman   DM          dm;
17712e1d0745SJose E. Roman   PetscViewer viewer;
17722e1d0745SJose E. Roman   DMLabel     label;
17732e1d0745SJose E. Roman   PetscSF     sfXC;
17742e1d0745SJose E. Roman   PetscLayout layoutX;
17752e1d0745SJose E. Roman };
17762e1d0745SJose E. Roman typedef struct _n_LoadLabelsCtx *LoadLabelsCtx;
17772e1d0745SJose E. Roman 
LoadLabelsCtxCreate(DM dm,PetscViewer viewer,PetscSF sfXC,LoadLabelsCtx * ctx)17782e1d0745SJose E. Roman static PetscErrorCode LoadLabelsCtxCreate(DM dm, PetscViewer viewer, PetscSF sfXC, LoadLabelsCtx *ctx)
17792e1d0745SJose E. Roman {
17802e1d0745SJose E. Roman   PetscFunctionBegin;
17812e1d0745SJose E. Roman   PetscCall(PetscNew(ctx));
17822e1d0745SJose E. Roman   PetscCall(PetscObjectReference((PetscObject)((*ctx)->dm = dm)));
17832e1d0745SJose E. Roman   PetscCall(PetscObjectReference((PetscObject)((*ctx)->viewer = viewer)));
17842e1d0745SJose E. Roman   PetscCall(PetscObjectGetComm((PetscObject)dm, &(*ctx)->comm));
17852e1d0745SJose E. Roman   PetscCallMPI(MPI_Comm_rank((*ctx)->comm, &(*ctx)->rank));
17862e1d0745SJose E. Roman   (*ctx)->sfXC = sfXC;
17872e1d0745SJose E. Roman   if (sfXC) {
17882e1d0745SJose E. Roman     PetscInt nX;
17892e1d0745SJose E. Roman 
17902e1d0745SJose E. Roman     PetscCall(PetscObjectReference((PetscObject)sfXC));
17912e1d0745SJose E. Roman     PetscCall(PetscSFGetGraph(sfXC, &nX, NULL, NULL, NULL));
17922e1d0745SJose E. Roman     PetscCall(PetscLayoutCreateFromSizes((*ctx)->comm, nX, PETSC_DECIDE, 1, &(*ctx)->layoutX));
17932e1d0745SJose E. Roman   }
17942e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
17952e1d0745SJose E. Roman }
17962e1d0745SJose E. Roman 
LoadLabelsCtxDestroy(LoadLabelsCtx * ctx)17972e1d0745SJose E. Roman static PetscErrorCode LoadLabelsCtxDestroy(LoadLabelsCtx *ctx)
17982e1d0745SJose E. Roman {
17992e1d0745SJose E. Roman   PetscFunctionBegin;
18002e1d0745SJose E. Roman   if (!*ctx) PetscFunctionReturn(PETSC_SUCCESS);
18012e1d0745SJose E. Roman   PetscCall(DMDestroy(&(*ctx)->dm));
18022e1d0745SJose E. Roman   PetscCall(PetscViewerDestroy(&(*ctx)->viewer));
18032e1d0745SJose E. Roman   PetscCall(PetscSFDestroy(&(*ctx)->sfXC));
18042e1d0745SJose E. Roman   PetscCall(PetscLayoutDestroy(&(*ctx)->layoutX));
18052e1d0745SJose E. Roman   PetscCall(PetscFree(*ctx));
18062e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
18072e1d0745SJose E. Roman }
18082e1d0745SJose E. Roman 
18092e1d0745SJose E. Roman /*
18102e1d0745SJose E. Roman     A: on-disk points
18112e1d0745SJose E. Roman     X: global points [0, NX)
18122e1d0745SJose E. Roman     C: distributed plex points
18132e1d0745SJose E. Roman */
ReadLabelStratumHDF5_Distribute_Private(IS stratumIS,LoadLabelsCtx ctx,IS * newStratumIS)18142e1d0745SJose E. Roman static herr_t ReadLabelStratumHDF5_Distribute_Private(IS stratumIS, LoadLabelsCtx ctx, IS *newStratumIS)
18152e1d0745SJose E. Roman {
18162e1d0745SJose E. Roman   MPI_Comm        comm    = ctx->comm;
18172e1d0745SJose E. Roman   PetscSF         sfXC    = ctx->sfXC;
18182e1d0745SJose E. Roman   PetscLayout     layoutX = ctx->layoutX;
18192e1d0745SJose E. Roman   PetscSF         sfXA;
18202e1d0745SJose E. Roman   const PetscInt *A_points;
18212e1d0745SJose E. Roman   PetscInt        nX, nC;
18222e1d0745SJose E. Roman   PetscInt        n;
18232e1d0745SJose E. Roman 
18242e1d0745SJose E. Roman   PetscFunctionBegin;
18252e1d0745SJose E. Roman   PetscCall(PetscSFGetGraph(sfXC, &nX, &nC, NULL, NULL));
18262e1d0745SJose E. Roman   PetscCall(ISGetLocalSize(stratumIS, &n));
18272e1d0745SJose E. Roman   PetscCall(ISGetIndices(stratumIS, &A_points));
18282e1d0745SJose E. Roman   PetscCall(PetscSFCreate(comm, &sfXA));
18292e1d0745SJose E. Roman   PetscCall(PetscSFSetGraphLayout(sfXA, layoutX, n, NULL, PETSC_USE_POINTER, A_points));
18302e1d0745SJose E. Roman   PetscCall(ISCreate(comm, newStratumIS));
18312e1d0745SJose E. Roman   PetscCall(ISSetType(*newStratumIS, ISGENERAL));
18322e1d0745SJose E. Roman   {
18332e1d0745SJose E. Roman     PetscInt   i;
18342e1d0745SJose E. Roman     PetscBool *A_mask, *X_mask, *C_mask;
18352e1d0745SJose E. Roman 
18362e1d0745SJose E. Roman     PetscCall(PetscCalloc3(n, &A_mask, nX, &X_mask, nC, &C_mask));
18372e1d0745SJose E. Roman     for (i = 0; i < n; i++) A_mask[i] = PETSC_TRUE;
18385440e5dcSBarry Smith     PetscCall(PetscSFReduceBegin(sfXA, MPI_C_BOOL, A_mask, X_mask, MPI_REPLACE));
18395440e5dcSBarry Smith     PetscCall(PetscSFReduceEnd(sfXA, MPI_C_BOOL, A_mask, X_mask, MPI_REPLACE));
18405440e5dcSBarry Smith     PetscCall(PetscSFBcastBegin(sfXC, MPI_C_BOOL, X_mask, C_mask, MPI_LOR));
18415440e5dcSBarry Smith     PetscCall(PetscSFBcastEnd(sfXC, MPI_C_BOOL, X_mask, C_mask, MPI_LOR));
18422e1d0745SJose E. Roman     PetscCall(ISGeneralSetIndicesFromMask(*newStratumIS, 0, nC, C_mask));
18432e1d0745SJose E. Roman     PetscCall(PetscFree3(A_mask, X_mask, C_mask));
18442e1d0745SJose E. Roman   }
18452e1d0745SJose E. Roman   PetscCall(PetscSFDestroy(&sfXA));
18462e1d0745SJose E. Roman   PetscCall(ISRestoreIndices(stratumIS, &A_points));
18472e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
18482e1d0745SJose E. Roman }
18492e1d0745SJose E. Roman 
ReadLabelStratumHDF5_Static(hid_t g_id,const char * vname,const H5L_info_t * info,void * op_data)18502e1d0745SJose E. Roman static herr_t ReadLabelStratumHDF5_Static(hid_t g_id, const char *vname, const H5L_info_t *info, void *op_data)
18512e1d0745SJose E. Roman {
18522e1d0745SJose E. Roman   LoadLabelsCtx   ctx    = (LoadLabelsCtx)op_data;
18532e1d0745SJose E. Roman   PetscViewer     viewer = ctx->viewer;
18542e1d0745SJose E. Roman   DMLabel         label  = ctx->label;
18552e1d0745SJose E. Roman   MPI_Comm        comm   = ctx->comm;
18562e1d0745SJose E. Roman   IS              stratumIS;
18572e1d0745SJose E. Roman   const PetscInt *ind;
18582e1d0745SJose E. Roman   PetscInt        value, N, i;
18592e1d0745SJose E. Roman 
18602e1d0745SJose E. Roman   PetscCall(PetscOptionsStringToInt(vname, &value));
18612e1d0745SJose E. Roman   PetscCall(ISCreate(comm, &stratumIS));
18622e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)stratumIS, "indices"));
18632e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, vname)); /* labels/<lname>/<vname> */
18642e1d0745SJose E. Roman 
18652e1d0745SJose E. Roman   if (!ctx->sfXC) {
18662e1d0745SJose E. Roman     /* Force serial load */
18672e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5ReadSizes(viewer, "indices", NULL, &N));
18682e1d0745SJose E. Roman     PetscCall(PetscLayoutSetLocalSize(stratumIS->map, !ctx->rank ? N : 0));
18692e1d0745SJose E. Roman     PetscCall(PetscLayoutSetSize(stratumIS->map, N));
18702e1d0745SJose E. Roman   }
18712e1d0745SJose E. Roman   PetscCall(ISLoad(stratumIS, viewer));
18722e1d0745SJose E. Roman 
18732e1d0745SJose E. Roman   if (ctx->sfXC) {
18742e1d0745SJose E. Roman     IS newStratumIS;
18752e1d0745SJose E. Roman 
18762e1d0745SJose E. Roman     PetscCallHDF5(ReadLabelStratumHDF5_Distribute_Private, (stratumIS, ctx, &newStratumIS));
18772e1d0745SJose E. Roman     PetscCall(ISDestroy(&stratumIS));
18782e1d0745SJose E. Roman     stratumIS = newStratumIS;
18792e1d0745SJose E. Roman   }
18802e1d0745SJose E. Roman 
18812e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
18822e1d0745SJose E. Roman   PetscCall(ISGetLocalSize(stratumIS, &N));
18832e1d0745SJose E. Roman   PetscCall(ISGetIndices(stratumIS, &ind));
18842e1d0745SJose E. Roman   for (i = 0; i < N; ++i) PetscCall(DMLabelSetValue(label, ind[i], value));
18852e1d0745SJose E. Roman   PetscCall(ISRestoreIndices(stratumIS, &ind));
18862e1d0745SJose E. Roman   PetscCall(ISDestroy(&stratumIS));
18872e1d0745SJose E. Roman   return 0;
18882e1d0745SJose E. Roman }
18892e1d0745SJose E. Roman 
18902e1d0745SJose E. Roman /* TODO: Fix this code, it is returning PETSc error codes when it should be translating them to herr_t codes */
ReadLabelHDF5_Static(hid_t g_id,const char * lname,const H5L_info_t * info,void * op_data)18912e1d0745SJose E. Roman static herr_t ReadLabelHDF5_Static(hid_t g_id, const char *lname, const H5L_info_t *info, void *op_data)
18922e1d0745SJose E. Roman {
18932e1d0745SJose E. Roman   LoadLabelsCtx  ctx = (LoadLabelsCtx)op_data;
18942e1d0745SJose E. Roman   DM             dm  = ctx->dm;
18952e1d0745SJose E. Roman   hsize_t        idx = 0;
18962e1d0745SJose E. Roman   PetscErrorCode ierr;
18972e1d0745SJose E. Roman   PetscBool      flg;
18982e1d0745SJose E. Roman   herr_t         err;
18992e1d0745SJose E. Roman 
19002e1d0745SJose E. Roman   PetscCall(DMHasLabel(dm, lname, &flg));
19012e1d0745SJose E. Roman   if (flg) PetscCall(DMRemoveLabel(dm, lname, NULL));
19022e1d0745SJose E. Roman   ierr = DMCreateLabel(dm, lname);
19032e1d0745SJose E. Roman   if (ierr) return (herr_t)ierr;
19042e1d0745SJose E. Roman   ierr = DMGetLabel(dm, lname, &ctx->label);
19052e1d0745SJose E. Roman   if (ierr) return (herr_t)ierr;
19062e1d0745SJose E. Roman   ierr = PetscViewerHDF5PushGroup(ctx->viewer, lname);
19072e1d0745SJose E. Roman   if (ierr) return (herr_t)ierr;
19082e1d0745SJose E. Roman   /* Iterate over the label's strata */
19092e1d0745SJose E. Roman   PetscCallHDF5Return(err, H5Literate_by_name, (g_id, lname, H5_INDEX_NAME, H5_ITER_NATIVE, &idx, ReadLabelStratumHDF5_Static, op_data, 0));
19102e1d0745SJose E. Roman   ierr = PetscViewerHDF5PopGroup(ctx->viewer);
19112e1d0745SJose E. Roman   if (ierr) return (herr_t)ierr;
19122e1d0745SJose E. Roman   return err;
19132e1d0745SJose E. Roman }
19142e1d0745SJose E. Roman 
DMPlexLabelsLoad_HDF5_Internal(DM dm,PetscViewer viewer,PetscSF sfXC)19152e1d0745SJose E. Roman PetscErrorCode DMPlexLabelsLoad_HDF5_Internal(DM dm, PetscViewer viewer, PetscSF sfXC)
19162e1d0745SJose E. Roman {
19172e1d0745SJose E. Roman   const char          *topologydm_name;
19182e1d0745SJose E. Roman   LoadLabelsCtx        ctx;
19192e1d0745SJose E. Roman   hsize_t              idx = 0;
19202e1d0745SJose E. Roman   char                 group[PETSC_MAX_PATH_LEN];
19212e1d0745SJose E. Roman   DMPlexStorageVersion version;
19222e1d0745SJose E. Roman   PetscBool            distributed, hasGroup;
19232e1d0745SJose E. Roman 
19242e1d0745SJose E. Roman   PetscFunctionBegin;
19252e1d0745SJose E. Roman   PetscCall(DMPlexIsDistributed(dm, &distributed));
19262e1d0745SJose E. Roman   if (distributed) PetscCheck(sfXC, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_NULL, "PetscSF must be given for parallel load");
19272e1d0745SJose E. Roman   PetscCall(LoadLabelsCtxCreate(dm, viewer, sfXC, &ctx));
19282e1d0745SJose E. Roman   PetscCall(DMPlexGetHDF5Name_Private(dm, &topologydm_name));
19292e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5GetDMPlexStorageVersionReading(viewer, &version));
19302e1d0745SJose E. Roman   if (DMPlexStorageVersionGE(version, 2, 0, 0)) {
19312e1d0745SJose E. Roman     PetscCall(PetscSNPrintf(group, sizeof(group), "topologies/%s/labels", topologydm_name));
19322e1d0745SJose E. Roman   } else {
19332e1d0745SJose E. Roman     PetscCall(PetscStrncpy(group, "labels", sizeof(group)));
19342e1d0745SJose E. Roman   }
19352e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, group));
19362e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5HasGroup(viewer, NULL, &hasGroup));
19372e1d0745SJose E. Roman   if (hasGroup) {
19382e1d0745SJose E. Roman     hid_t fileId, groupId;
19392e1d0745SJose E. Roman 
19402e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5OpenGroup(viewer, NULL, &fileId, &groupId));
19412e1d0745SJose E. Roman     /* Iterate over labels */
19422e1d0745SJose E. Roman     PetscCallHDF5(H5Literate, (groupId, H5_INDEX_NAME, H5_ITER_NATIVE, &idx, ReadLabelHDF5_Static, ctx));
19432e1d0745SJose E. Roman     PetscCallHDF5(H5Gclose, (groupId));
19442e1d0745SJose E. Roman   }
19452e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
19462e1d0745SJose E. Roman   PetscCall(LoadLabelsCtxDestroy(&ctx));
19472e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
19482e1d0745SJose E. Roman }
19492e1d0745SJose E. Roman 
DMPlexDistributionLoad_HDF5_Private(DM dm,PetscViewer viewer,PetscSF sf,PetscSF * distsf,DM * distdm)19502e1d0745SJose E. Roman static PetscErrorCode DMPlexDistributionLoad_HDF5_Private(DM dm, PetscViewer viewer, PetscSF sf, PetscSF *distsf, DM *distdm)
19512e1d0745SJose E. Roman {
19522e1d0745SJose E. Roman   MPI_Comm        comm;
19532e1d0745SJose E. Roman   PetscMPIInt     size, rank;
19542e1d0745SJose E. Roman   PetscInt        dist_size;
19552e1d0745SJose E. Roman   const char     *distribution_name;
19562e1d0745SJose E. Roman   PetscInt        p, lsize;
19572e1d0745SJose E. Roman   IS              chartSizesIS, ownersIS, gpointsIS;
19582e1d0745SJose E. Roman   const PetscInt *chartSize, *owners, *gpoints;
19592e1d0745SJose E. Roman   PetscLayout     layout;
19602e1d0745SJose E. Roman   PetscBool       has;
19612e1d0745SJose E. Roman 
19622e1d0745SJose E. Roman   PetscFunctionBegin;
19632e1d0745SJose E. Roman   *distsf = NULL;
19642e1d0745SJose E. Roman   *distdm = NULL;
19652e1d0745SJose E. Roman   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
19662e1d0745SJose E. Roman   PetscCallMPI(MPI_Comm_size(comm, &size));
19672e1d0745SJose E. Roman   PetscCallMPI(MPI_Comm_rank(comm, &rank));
19682e1d0745SJose E. Roman   PetscCall(DMPlexDistributionGetName(dm, &distribution_name));
19692e1d0745SJose E. Roman   if (!distribution_name) PetscFunctionReturn(PETSC_SUCCESS);
19702e1d0745SJose E. Roman   PetscCall(PetscLogEventBegin(DMPLEX_DistributionLoad, viewer, 0, 0, 0));
19712e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5HasGroup(viewer, NULL, &has));
19722e1d0745SJose E. Roman   if (!has) {
1973ce78bad3SBarry Smith     const char *full_group;
19742e1d0745SJose E. Roman 
19752e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5GetGroup(viewer, NULL, &full_group));
19762e1d0745SJose 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);
19772e1d0745SJose E. Roman   }
19782e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5ReadAttribute(viewer, NULL, "comm_size", PETSC_INT, NULL, (void *)&dist_size));
19792e1d0745SJose 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);
19802e1d0745SJose E. Roman   PetscCall(ISCreate(comm, &chartSizesIS));
19812e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)chartSizesIS, "chart_sizes"));
19822e1d0745SJose E. Roman   PetscCall(ISCreate(comm, &ownersIS));
19832e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)ownersIS, "owners"));
19842e1d0745SJose E. Roman   PetscCall(ISCreate(comm, &gpointsIS));
19852e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)gpointsIS, "global_point_numbers"));
19862e1d0745SJose E. Roman   PetscCall(PetscLayoutSetLocalSize(chartSizesIS->map, 1));
19872e1d0745SJose E. Roman   PetscCall(ISLoad(chartSizesIS, viewer));
19882e1d0745SJose E. Roman   PetscCall(ISGetIndices(chartSizesIS, &chartSize));
19892e1d0745SJose E. Roman   PetscCall(PetscLayoutSetLocalSize(ownersIS->map, *chartSize));
19902e1d0745SJose E. Roman   PetscCall(PetscLayoutSetLocalSize(gpointsIS->map, *chartSize));
19912e1d0745SJose E. Roman   PetscCall(ISLoad(ownersIS, viewer));
19922e1d0745SJose E. Roman   PetscCall(ISLoad(gpointsIS, viewer));
19932e1d0745SJose E. Roman   PetscCall(ISGetIndices(ownersIS, &owners));
19942e1d0745SJose E. Roman   PetscCall(ISGetIndices(gpointsIS, &gpoints));
19952e1d0745SJose E. Roman   PetscCall(PetscSFCreate(comm, distsf));
19962e1d0745SJose E. Roman   PetscCall(PetscSFSetFromOptions(*distsf));
19972e1d0745SJose E. Roman   PetscCall(PetscLayoutCreate(comm, &layout));
19982e1d0745SJose E. Roman   PetscCall(PetscSFGetGraph(sf, &lsize, NULL, NULL, NULL));
19992e1d0745SJose E. Roman   PetscCall(PetscLayoutSetLocalSize(layout, lsize));
20002e1d0745SJose E. Roman   PetscCall(PetscLayoutSetBlockSize(layout, 1));
20012e1d0745SJose E. Roman   PetscCall(PetscLayoutSetUp(layout));
20022e1d0745SJose E. Roman   PetscCall(PetscSFSetGraphLayout(*distsf, layout, *chartSize, NULL, PETSC_OWN_POINTER, gpoints));
20032e1d0745SJose E. Roman   PetscCall(PetscLayoutDestroy(&layout));
20042e1d0745SJose E. Roman   /* Migrate DM */
20052e1d0745SJose E. Roman   {
20062e1d0745SJose E. Roman     PetscInt     pStart, pEnd;
20072e1d0745SJose E. Roman     PetscSFNode *buffer0, *buffer1, *buffer2;
20082e1d0745SJose E. Roman 
20092e1d0745SJose E. Roman     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
20102e1d0745SJose E. Roman     PetscCall(PetscMalloc2(pEnd - pStart, &buffer0, lsize, &buffer1));
20112e1d0745SJose E. Roman     PetscCall(PetscMalloc1(*chartSize, &buffer2));
20122e1d0745SJose E. Roman     {
20132e1d0745SJose E. Roman       PetscSF            workPointSF;
20142e1d0745SJose E. Roman       PetscInt           workNroots, workNleaves;
20152e1d0745SJose E. Roman       const PetscInt    *workIlocal;
20162e1d0745SJose E. Roman       const PetscSFNode *workIremote;
20172e1d0745SJose E. Roman 
20182e1d0745SJose E. Roman       for (p = pStart; p < pEnd; ++p) {
20192e1d0745SJose E. Roman         buffer0[p - pStart].rank  = rank;
20202e1d0745SJose E. Roman         buffer0[p - pStart].index = p - pStart;
20212e1d0745SJose E. Roman       }
20222e1d0745SJose E. Roman       PetscCall(DMGetPointSF(dm, &workPointSF));
20232e1d0745SJose E. Roman       PetscCall(PetscSFGetGraph(workPointSF, &workNroots, &workNleaves, &workIlocal, &workIremote));
20242e1d0745SJose E. Roman       for (p = 0; p < workNleaves; ++p) {
20252e1d0745SJose E. Roman         PetscInt workIlocalp = (workIlocal ? workIlocal[p] : p);
20262e1d0745SJose E. Roman 
20272e1d0745SJose E. Roman         buffer0[workIlocalp].rank = -1;
20282e1d0745SJose E. Roman       }
20292e1d0745SJose E. Roman     }
20302e1d0745SJose E. Roman     for (p = 0; p < lsize; ++p) buffer1[p].rank = -1;
20312e1d0745SJose E. Roman     for (p = 0; p < *chartSize; ++p) buffer2[p].rank = -1;
20322e1d0745SJose E. Roman     PetscCall(PetscSFReduceBegin(sf, MPIU_SF_NODE, buffer0, buffer1, MPI_MAXLOC));
20332e1d0745SJose E. Roman     PetscCall(PetscSFReduceEnd(sf, MPIU_SF_NODE, buffer0, buffer1, MPI_MAXLOC));
20342e1d0745SJose E. Roman     PetscCall(PetscSFBcastBegin(*distsf, MPIU_SF_NODE, buffer1, buffer2, MPI_REPLACE));
20352e1d0745SJose E. Roman     PetscCall(PetscSFBcastEnd(*distsf, MPIU_SF_NODE, buffer1, buffer2, MPI_REPLACE));
20362e1d0745SJose E. Roman     if (PetscDefined(USE_DEBUG)) {
20373a7d0413SPierre Jolivet       for (p = 0; p < *chartSize; ++p) 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);
20382e1d0745SJose E. Roman     }
20392e1d0745SJose E. Roman     PetscCall(PetscFree2(buffer0, buffer1));
20402e1d0745SJose E. Roman     PetscCall(DMCreate(comm, distdm));
20412e1d0745SJose E. Roman     PetscCall(DMSetType(*distdm, DMPLEX));
20422e1d0745SJose E. Roman     PetscCall(PetscObjectSetName((PetscObject)*distdm, ((PetscObject)dm)->name));
20432e1d0745SJose E. Roman     PetscCall(DMPlexDistributionSetName(*distdm, distribution_name));
20442e1d0745SJose E. Roman     {
20452e1d0745SJose E. Roman       PetscSF migrationSF;
20462e1d0745SJose E. Roman 
20472e1d0745SJose E. Roman       PetscCall(PetscSFCreate(comm, &migrationSF));
20482e1d0745SJose E. Roman       PetscCall(PetscSFSetFromOptions(migrationSF));
20492e1d0745SJose E. Roman       PetscCall(PetscSFSetGraph(migrationSF, pEnd - pStart, *chartSize, NULL, PETSC_OWN_POINTER, buffer2, PETSC_OWN_POINTER));
20502e1d0745SJose E. Roman       PetscCall(PetscSFSetUp(migrationSF));
20512e1d0745SJose E. Roman       PetscCall(DMPlexMigrate(dm, migrationSF, *distdm));
20522e1d0745SJose E. Roman       PetscCall(PetscSFDestroy(&migrationSF));
20532e1d0745SJose E. Roman     }
20542e1d0745SJose E. Roman   }
20552e1d0745SJose E. Roman   /* Set pointSF */
20562e1d0745SJose E. Roman   {
20572e1d0745SJose E. Roman     PetscSF      pointSF;
20582e1d0745SJose E. Roman     PetscInt    *ilocal, nleaves, q;
20592e1d0745SJose E. Roman     PetscSFNode *iremote, *buffer0, *buffer1;
20602e1d0745SJose E. Roman 
20612e1d0745SJose E. Roman     PetscCall(PetscMalloc2(*chartSize, &buffer0, lsize, &buffer1));
20622e1d0745SJose E. Roman     for (p = 0, nleaves = 0; p < *chartSize; ++p) {
20632e1d0745SJose E. Roman       if (owners[p] == rank) {
20642e1d0745SJose E. Roman         buffer0[p].rank = rank;
20652e1d0745SJose E. Roman       } else {
20662e1d0745SJose E. Roman         buffer0[p].rank = -1;
20672e1d0745SJose E. Roman         nleaves++;
20682e1d0745SJose E. Roman       }
20692e1d0745SJose E. Roman       buffer0[p].index = p;
20702e1d0745SJose E. Roman     }
20712e1d0745SJose E. Roman     for (p = 0; p < lsize; ++p) buffer1[p].rank = -1;
20722e1d0745SJose E. Roman     PetscCall(PetscSFReduceBegin(*distsf, MPIU_SF_NODE, buffer0, buffer1, MPI_MAXLOC));
20732e1d0745SJose E. Roman     PetscCall(PetscSFReduceEnd(*distsf, MPIU_SF_NODE, buffer0, buffer1, MPI_MAXLOC));
20742e1d0745SJose E. Roman     for (p = 0; p < *chartSize; ++p) buffer0[p].rank = -1;
20752e1d0745SJose E. Roman     PetscCall(PetscSFBcastBegin(*distsf, MPIU_SF_NODE, buffer1, buffer0, MPI_REPLACE));
20762e1d0745SJose E. Roman     PetscCall(PetscSFBcastEnd(*distsf, MPIU_SF_NODE, buffer1, buffer0, MPI_REPLACE));
20772e1d0745SJose E. Roman     if (PetscDefined(USE_DEBUG)) {
20782e1d0745SJose 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);
20792e1d0745SJose E. Roman     }
20802e1d0745SJose E. Roman     PetscCall(PetscMalloc1(nleaves, &ilocal));
20812e1d0745SJose E. Roman     PetscCall(PetscMalloc1(nleaves, &iremote));
20822e1d0745SJose E. Roman     for (p = 0, q = 0; p < *chartSize; ++p) {
20832e1d0745SJose E. Roman       if (buffer0[p].rank != rank) {
20842e1d0745SJose E. Roman         ilocal[q]        = p;
20852e1d0745SJose E. Roman         iremote[q].rank  = buffer0[p].rank;
20862e1d0745SJose E. Roman         iremote[q].index = buffer0[p].index;
20872e1d0745SJose E. Roman         q++;
20882e1d0745SJose E. Roman       }
20892e1d0745SJose E. Roman     }
20902e1d0745SJose E. Roman     PetscCheck(q == nleaves, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatching leaf sizes: %" PetscInt_FMT " != %" PetscInt_FMT, q, nleaves);
20912e1d0745SJose E. Roman     PetscCall(PetscFree2(buffer0, buffer1));
20922e1d0745SJose E. Roman     PetscCall(PetscSFCreate(comm, &pointSF));
20932e1d0745SJose E. Roman     PetscCall(PetscSFSetFromOptions(pointSF));
20942e1d0745SJose E. Roman     PetscCall(PetscSFSetGraph(pointSF, *chartSize, nleaves, ilocal, PETSC_OWN_POINTER, iremote, PETSC_OWN_POINTER));
20952e1d0745SJose E. Roman     PetscCall(DMSetPointSF(*distdm, pointSF));
20962e1d0745SJose E. Roman     {
20972e1d0745SJose E. Roman       DM cdm;
20982e1d0745SJose E. Roman 
20992e1d0745SJose E. Roman       PetscCall(DMGetCoordinateDM(*distdm, &cdm));
21002e1d0745SJose E. Roman       PetscCall(DMSetPointSF(cdm, pointSF));
21012e1d0745SJose E. Roman     }
21022e1d0745SJose E. Roman     PetscCall(PetscSFDestroy(&pointSF));
21032e1d0745SJose E. Roman   }
21042e1d0745SJose E. Roman   PetscCall(ISRestoreIndices(chartSizesIS, &chartSize));
21052e1d0745SJose E. Roman   PetscCall(ISRestoreIndices(ownersIS, &owners));
21062e1d0745SJose E. Roman   PetscCall(ISRestoreIndices(gpointsIS, &gpoints));
21072e1d0745SJose E. Roman   PetscCall(ISDestroy(&chartSizesIS));
21082e1d0745SJose E. Roman   PetscCall(ISDestroy(&ownersIS));
21092e1d0745SJose E. Roman   PetscCall(ISDestroy(&gpointsIS));
21102e1d0745SJose E. Roman   /* Record that overlap has been manually created.               */
21112e1d0745SJose E. Roman   /* This is to pass `DMPlexCheckPointSF()`, which checks that    */
21122e1d0745SJose E. Roman   /* pointSF does not contain cells in the leaves if overlap = 0. */
21132e1d0745SJose E. Roman   PetscCall(DMPlexSetOverlap_Plex(*distdm, NULL, DMPLEX_OVERLAP_MANUAL));
21142e1d0745SJose E. Roman   PetscCall(DMPlexDistributeSetDefault(*distdm, PETSC_FALSE));
21152e1d0745SJose E. Roman   PetscCall(DMPlexReorderSetDefault(*distdm, DM_REORDER_DEFAULT_FALSE));
21162e1d0745SJose E. Roman   PetscCall(PetscLogEventEnd(DMPLEX_DistributionLoad, viewer, 0, 0, 0));
21172e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
21182e1d0745SJose E. Roman }
21192e1d0745SJose E. Roman 
21202e1d0745SJose E. Roman // Serial load of topology
DMPlexTopologyLoad_HDF5_Legacy_Private(DM dm,PetscViewer viewer,PetscSF * sf)21212e1d0745SJose E. Roman static PetscErrorCode DMPlexTopologyLoad_HDF5_Legacy_Private(DM dm, PetscViewer viewer, PetscSF *sf)
21222e1d0745SJose E. Roman {
21232e1d0745SJose E. Roman   MPI_Comm        comm;
21242e1d0745SJose E. Roman   const char     *pointsName, *coneSizesName, *conesName, *orientationsName;
21252e1d0745SJose E. Roman   IS              pointsIS, coneSizesIS, conesIS, orientationsIS;
21262e1d0745SJose E. Roman   const PetscInt *points, *coneSizes, *cones, *orientations;
21272e1d0745SJose E. Roman   PetscInt       *cone, *ornt;
21282e1d0745SJose E. Roman   PetscInt        dim, N, Np, pEnd, p, q, maxConeSize = 0, c;
21292e1d0745SJose E. Roman   PetscMPIInt     size, rank;
21302e1d0745SJose E. Roman 
21312e1d0745SJose E. Roman   PetscFunctionBegin;
21322e1d0745SJose E. Roman   pointsName       = "order";
21332e1d0745SJose E. Roman   coneSizesName    = "cones";
21342e1d0745SJose E. Roman   conesName        = "cells";
21352e1d0745SJose E. Roman   orientationsName = "orientation";
21362e1d0745SJose E. Roman   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
21372e1d0745SJose E. Roman   PetscCallMPI(MPI_Comm_size(comm, &size));
21382e1d0745SJose E. Roman   PetscCallMPI(MPI_Comm_rank(comm, &rank));
21392e1d0745SJose E. Roman   PetscCall(ISCreate(comm, &pointsIS));
21402e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)pointsIS, pointsName));
21412e1d0745SJose E. Roman   PetscCall(ISCreate(comm, &coneSizesIS));
21422e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)coneSizesIS, coneSizesName));
21432e1d0745SJose E. Roman   PetscCall(ISCreate(comm, &conesIS));
21442e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)conesIS, conesName));
21452e1d0745SJose E. Roman   PetscCall(ISCreate(comm, &orientationsIS));
21462e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)orientationsIS, orientationsName));
21472e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5ReadObjectAttribute(viewer, (PetscObject)conesIS, "cell_dim", PETSC_INT, NULL, &dim));
21482e1d0745SJose E. Roman   PetscCall(DMSetDimension(dm, dim));
21492e1d0745SJose E. Roman   {
21502e1d0745SJose E. Roman     /* Force serial load */
21512e1d0745SJose E. Roman     PetscCall(PetscInfo(dm, "Loading DM %s in serial\n", dm->hdr.name));
21522e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5ReadSizes(viewer, pointsName, NULL, &Np));
21532e1d0745SJose E. Roman     PetscCall(PetscLayoutSetLocalSize(pointsIS->map, rank == 0 ? Np : 0));
21542e1d0745SJose E. Roman     PetscCall(PetscLayoutSetSize(pointsIS->map, Np));
21552e1d0745SJose E. Roman     pEnd = rank == 0 ? Np : 0;
21562e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5ReadSizes(viewer, coneSizesName, NULL, &Np));
21572e1d0745SJose E. Roman     PetscCall(PetscLayoutSetLocalSize(coneSizesIS->map, rank == 0 ? Np : 0));
21582e1d0745SJose E. Roman     PetscCall(PetscLayoutSetSize(coneSizesIS->map, Np));
21592e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5ReadSizes(viewer, conesName, NULL, &N));
21602e1d0745SJose E. Roman     PetscCall(PetscLayoutSetLocalSize(conesIS->map, rank == 0 ? N : 0));
21612e1d0745SJose E. Roman     PetscCall(PetscLayoutSetSize(conesIS->map, N));
21622e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5ReadSizes(viewer, orientationsName, NULL, &N));
21632e1d0745SJose E. Roman     PetscCall(PetscLayoutSetLocalSize(orientationsIS->map, rank == 0 ? N : 0));
21642e1d0745SJose E. Roman     PetscCall(PetscLayoutSetSize(orientationsIS->map, N));
21652e1d0745SJose E. Roman   }
21662e1d0745SJose E. Roman   PetscCall(ISLoad(pointsIS, viewer));
21672e1d0745SJose E. Roman   PetscCall(ISLoad(coneSizesIS, viewer));
21682e1d0745SJose E. Roman   PetscCall(ISLoad(conesIS, viewer));
21692e1d0745SJose E. Roman   PetscCall(ISLoad(orientationsIS, viewer));
21702e1d0745SJose E. Roman   /* Create Plex */
21712e1d0745SJose E. Roman   PetscCall(DMPlexSetChart(dm, 0, pEnd));
21722e1d0745SJose E. Roman   PetscCall(ISGetIndices(pointsIS, &points));
21732e1d0745SJose E. Roman   PetscCall(ISGetIndices(coneSizesIS, &coneSizes));
21742e1d0745SJose E. Roman   for (p = 0; p < pEnd; ++p) {
21752e1d0745SJose E. Roman     PetscCall(DMPlexSetConeSize(dm, points[p], coneSizes[p]));
21762e1d0745SJose E. Roman     maxConeSize = PetscMax(maxConeSize, coneSizes[p]);
21772e1d0745SJose E. Roman   }
21782e1d0745SJose E. Roman   PetscCall(DMSetUp(dm));
21792e1d0745SJose E. Roman   PetscCall(ISGetIndices(conesIS, &cones));
21802e1d0745SJose E. Roman   PetscCall(ISGetIndices(orientationsIS, &orientations));
21812e1d0745SJose E. Roman   PetscCall(PetscMalloc2(maxConeSize, &cone, maxConeSize, &ornt));
21822e1d0745SJose E. Roman   for (p = 0, q = 0; p < pEnd; ++p) {
21832e1d0745SJose E. Roman     for (c = 0; c < coneSizes[p]; ++c, ++q) {
21842e1d0745SJose E. Roman       cone[c] = cones[q];
21852e1d0745SJose E. Roman       ornt[c] = orientations[q];
21862e1d0745SJose E. Roman     }
21872e1d0745SJose E. Roman     PetscCall(DMPlexSetCone(dm, points[p], cone));
21882e1d0745SJose E. Roman     PetscCall(DMPlexSetConeOrientation(dm, points[p], ornt));
21892e1d0745SJose E. Roman   }
21902e1d0745SJose E. Roman   PetscCall(PetscFree2(cone, ornt));
21912e1d0745SJose E. Roman   /* Create global section migration SF */
21922e1d0745SJose E. Roman   if (sf) {
21932e1d0745SJose E. Roman     PetscLayout layout;
21942e1d0745SJose E. Roman     PetscInt   *globalIndices;
21952e1d0745SJose E. Roman 
21962e1d0745SJose E. Roman     PetscCall(PetscMalloc1(pEnd, &globalIndices));
21972e1d0745SJose E. Roman     /* plex point == globalPointNumber in this case */
21982e1d0745SJose E. Roman     for (p = 0; p < pEnd; ++p) globalIndices[p] = p;
21992e1d0745SJose E. Roman     PetscCall(PetscLayoutCreate(comm, &layout));
22002e1d0745SJose E. Roman     PetscCall(PetscLayoutSetSize(layout, Np));
22012e1d0745SJose E. Roman     PetscCall(PetscLayoutSetBlockSize(layout, 1));
22022e1d0745SJose E. Roman     PetscCall(PetscLayoutSetUp(layout));
22032e1d0745SJose E. Roman     PetscCall(PetscSFCreate(comm, sf));
22042e1d0745SJose E. Roman     PetscCall(PetscSFSetFromOptions(*sf));
22052e1d0745SJose E. Roman     PetscCall(PetscSFSetGraphLayout(*sf, layout, pEnd, NULL, PETSC_OWN_POINTER, globalIndices));
22062e1d0745SJose E. Roman     PetscCall(PetscLayoutDestroy(&layout));
22072e1d0745SJose E. Roman     PetscCall(PetscFree(globalIndices));
22082e1d0745SJose E. Roman   }
22092e1d0745SJose E. Roman   /* Clean-up */
22102e1d0745SJose E. Roman   PetscCall(ISRestoreIndices(pointsIS, &points));
22112e1d0745SJose E. Roman   PetscCall(ISRestoreIndices(coneSizesIS, &coneSizes));
22122e1d0745SJose E. Roman   PetscCall(ISRestoreIndices(conesIS, &cones));
22132e1d0745SJose E. Roman   PetscCall(ISRestoreIndices(orientationsIS, &orientations));
22142e1d0745SJose E. Roman   PetscCall(ISDestroy(&pointsIS));
22152e1d0745SJose E. Roman   PetscCall(ISDestroy(&coneSizesIS));
22162e1d0745SJose E. Roman   PetscCall(ISDestroy(&conesIS));
22172e1d0745SJose E. Roman   PetscCall(ISDestroy(&orientationsIS));
22182e1d0745SJose E. Roman   /* Fill in the rest of the topology structure */
22192e1d0745SJose E. Roman   PetscCall(DMPlexSymmetrize(dm));
22202e1d0745SJose E. Roman   PetscCall(DMPlexStratify(dm));
22212e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
22222e1d0745SJose E. Roman }
22232e1d0745SJose E. Roman 
22242e1d0745SJose E. Roman /* Representation of two DMPlex strata in 0-based global numbering */
22252e1d0745SJose E. Roman struct _n_PlexLayer {
22262e1d0745SJose E. Roman   PetscInt     d;
22272e1d0745SJose E. Roman   IS           conesIS, orientationsIS;
22282e1d0745SJose E. Roman   PetscSection coneSizesSection;
22292e1d0745SJose E. Roman   PetscLayout  vertexLayout;
22302e1d0745SJose E. Roman   PetscSF      overlapSF, l2gSF; //TODO maybe confusing names (in DMPlex in general)
22312e1d0745SJose E. Roman   PetscInt     offset, conesOffset, leafOffset;
22322e1d0745SJose E. Roman };
22332e1d0745SJose E. Roman typedef struct _n_PlexLayer *PlexLayer;
22342e1d0745SJose E. Roman 
PlexLayerDestroy(PlexLayer * layer)22352e1d0745SJose E. Roman static PetscErrorCode PlexLayerDestroy(PlexLayer *layer)
22362e1d0745SJose E. Roman {
22372e1d0745SJose E. Roman   PetscFunctionBegin;
22382e1d0745SJose E. Roman   if (!*layer) PetscFunctionReturn(PETSC_SUCCESS);
22392e1d0745SJose E. Roman   PetscCall(PetscSectionDestroy(&(*layer)->coneSizesSection));
22402e1d0745SJose E. Roman   PetscCall(ISDestroy(&(*layer)->conesIS));
22412e1d0745SJose E. Roman   PetscCall(ISDestroy(&(*layer)->orientationsIS));
22422e1d0745SJose E. Roman   PetscCall(PetscSFDestroy(&(*layer)->overlapSF));
22432e1d0745SJose E. Roman   PetscCall(PetscSFDestroy(&(*layer)->l2gSF));
22442e1d0745SJose E. Roman   PetscCall(PetscLayoutDestroy(&(*layer)->vertexLayout));
22452e1d0745SJose E. Roman   PetscCall(PetscFree(*layer));
22462e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
22472e1d0745SJose E. Roman }
22482e1d0745SJose E. Roman 
PlexLayerCreate_Private(PlexLayer * layer)22492e1d0745SJose E. Roman static PetscErrorCode PlexLayerCreate_Private(PlexLayer *layer)
22502e1d0745SJose E. Roman {
22512e1d0745SJose E. Roman   PetscFunctionBegin;
22522e1d0745SJose E. Roman   PetscCall(PetscNew(layer));
22532e1d0745SJose E. Roman   (*layer)->d           = -1;
22542e1d0745SJose E. Roman   (*layer)->offset      = -1;
22552e1d0745SJose E. Roman   (*layer)->conesOffset = -1;
22562e1d0745SJose E. Roman   (*layer)->leafOffset  = -1;
22572e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
22582e1d0745SJose E. Roman }
22592e1d0745SJose E. Roman 
22602e1d0745SJose E. Roman // Parallel load of a depth stratum
PlexLayerLoad_Private(PlexLayer layer,PetscViewer viewer,PetscInt d,PetscLayout pointsLayout)22612e1d0745SJose E. Roman static PetscErrorCode PlexLayerLoad_Private(PlexLayer layer, PetscViewer viewer, PetscInt d, PetscLayout pointsLayout)
22622e1d0745SJose E. Roman {
22632e1d0745SJose E. Roman   char         path[128];
22642e1d0745SJose E. Roman   MPI_Comm     comm;
22652e1d0745SJose E. Roman   const char  *coneSizesName, *conesName, *orientationsName;
22662e1d0745SJose E. Roman   IS           coneSizesIS, conesIS, orientationsIS;
22672e1d0745SJose E. Roman   PetscSection coneSizesSection;
22682e1d0745SJose E. Roman   PetscLayout  vertexLayout = NULL;
22692e1d0745SJose E. Roman   PetscInt     s;
22702e1d0745SJose E. Roman 
22712e1d0745SJose E. Roman   PetscFunctionBegin;
22722e1d0745SJose E. Roman   coneSizesName    = "cone_sizes";
22732e1d0745SJose E. Roman   conesName        = "cones";
22742e1d0745SJose E. Roman   orientationsName = "orientations";
22752e1d0745SJose E. Roman   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
22762e1d0745SJose E. Roman 
22772e1d0745SJose E. Roman   /* query size of next lower depth stratum (next lower dimension) */
22782e1d0745SJose E. Roman   if (d > 0) {
22792e1d0745SJose E. Roman     PetscInt NVertices;
22802e1d0745SJose E. Roman 
22812e1d0745SJose E. Roman     PetscCall(PetscSNPrintf(path, sizeof(path), "%" PetscInt_FMT "/%s", d - 1, coneSizesName));
22822e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5ReadSizes(viewer, path, NULL, &NVertices));
22832e1d0745SJose E. Roman     PetscCall(PetscLayoutCreate(comm, &vertexLayout));
22842e1d0745SJose E. Roman     PetscCall(PetscLayoutSetSize(vertexLayout, NVertices));
22852e1d0745SJose E. Roman     PetscCall(PetscLayoutSetUp(vertexLayout));
22862e1d0745SJose E. Roman   }
22872e1d0745SJose E. Roman 
22882e1d0745SJose E. Roman   PetscCall(PetscSNPrintf(path, sizeof(path), "%" PetscInt_FMT, d));
22892e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, path));
22902e1d0745SJose E. Roman 
22912e1d0745SJose E. Roman   /* create coneSizesSection from stored IS coneSizes */
22922e1d0745SJose E. Roman   {
22932e1d0745SJose E. Roman     const PetscInt *coneSizes;
22942e1d0745SJose E. Roman 
22952e1d0745SJose E. Roman     PetscCall(ISCreate(comm, &coneSizesIS));
22962e1d0745SJose E. Roman     PetscCall(PetscObjectSetName((PetscObject)coneSizesIS, coneSizesName));
22972e1d0745SJose E. Roman     if (pointsLayout) PetscCall(ISSetLayout(coneSizesIS, pointsLayout));
22982e1d0745SJose E. Roman     PetscCall(ISLoad(coneSizesIS, viewer));
22992e1d0745SJose E. Roman     if (!pointsLayout) PetscCall(ISGetLayout(coneSizesIS, &pointsLayout));
23002e1d0745SJose E. Roman     PetscCall(ISGetIndices(coneSizesIS, &coneSizes));
23012e1d0745SJose E. Roman     PetscCall(PetscSectionCreate(comm, &coneSizesSection));
23022e1d0745SJose E. Roman     //TODO different start ?
23032e1d0745SJose E. Roman     PetscCall(PetscSectionSetChart(coneSizesSection, 0, pointsLayout->n));
23042e1d0745SJose E. Roman     for (s = 0; s < pointsLayout->n; ++s) PetscCall(PetscSectionSetDof(coneSizesSection, s, coneSizes[s]));
23052e1d0745SJose E. Roman     PetscCall(PetscSectionSetUp(coneSizesSection));
23062e1d0745SJose E. Roman     PetscCall(ISRestoreIndices(coneSizesIS, &coneSizes));
23072e1d0745SJose E. Roman     {
23082e1d0745SJose E. Roman       PetscLayout tmp = NULL;
23092e1d0745SJose E. Roman 
23102e1d0745SJose E. Roman       /* We need to keep the layout until the end of function */
23112e1d0745SJose E. Roman       PetscCall(PetscLayoutReference((PetscLayout)pointsLayout, &tmp));
23122e1d0745SJose E. Roman     }
23132e1d0745SJose E. Roman     PetscCall(ISDestroy(&coneSizesIS));
23142e1d0745SJose E. Roman   }
23152e1d0745SJose E. Roman 
23162e1d0745SJose E. Roman   /* use value layout of coneSizesSection as layout of cones and orientations */
23172e1d0745SJose E. Roman   {
23182e1d0745SJose E. Roman     PetscLayout conesLayout;
23192e1d0745SJose E. Roman 
23202e1d0745SJose E. Roman     PetscCall(PetscSectionGetValueLayout(comm, coneSizesSection, &conesLayout));
23212e1d0745SJose E. Roman     PetscCall(ISCreate(comm, &conesIS));
23222e1d0745SJose E. Roman     PetscCall(ISCreate(comm, &orientationsIS));
23232e1d0745SJose E. Roman     PetscCall(PetscObjectSetName((PetscObject)conesIS, conesName));
23242e1d0745SJose E. Roman     PetscCall(PetscObjectSetName((PetscObject)orientationsIS, orientationsName));
23252e1d0745SJose E. Roman     PetscCall(PetscLayoutDuplicate(conesLayout, &conesIS->map));
23262e1d0745SJose E. Roman     PetscCall(PetscLayoutDuplicate(conesLayout, &orientationsIS->map));
23272e1d0745SJose E. Roman     PetscCall(ISLoad(conesIS, viewer));
23282e1d0745SJose E. Roman     PetscCall(ISLoad(orientationsIS, viewer));
23292e1d0745SJose E. Roman     PetscCall(PetscLayoutDestroy(&conesLayout));
23302e1d0745SJose E. Roman   }
23312e1d0745SJose E. Roman 
23322e1d0745SJose E. Roman   /* check assertion that layout of points is the same as point layout of coneSizesSection */
23332e1d0745SJose E. Roman   {
23342e1d0745SJose E. Roman     PetscLayout pointsLayout0;
23352e1d0745SJose E. Roman     PetscBool   flg;
23362e1d0745SJose E. Roman 
23372e1d0745SJose E. Roman     PetscCall(PetscSectionGetPointLayout(comm, coneSizesSection, &pointsLayout0));
23382e1d0745SJose E. Roman     PetscCall(PetscLayoutCompare(pointsLayout, pointsLayout0, &flg));
23392e1d0745SJose E. Roman     PetscCheck(flg, comm, PETSC_ERR_PLIB, "points layout != coneSizesSection point layout");
23402e1d0745SJose E. Roman     PetscCall(PetscLayoutDestroy(&pointsLayout0));
23412e1d0745SJose E. Roman   }
23422e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
23432e1d0745SJose E. Roman   PetscCall(PetscLayoutDestroy(&pointsLayout));
23442e1d0745SJose E. Roman 
23452e1d0745SJose E. Roman   layer->d                = d;
23462e1d0745SJose E. Roman   layer->conesIS          = conesIS;
23472e1d0745SJose E. Roman   layer->coneSizesSection = coneSizesSection;
23482e1d0745SJose E. Roman   layer->orientationsIS   = orientationsIS;
23492e1d0745SJose E. Roman   layer->vertexLayout     = vertexLayout;
23502e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
23512e1d0745SJose E. Roman }
23522e1d0745SJose E. Roman 
PlexLayerDistribute_Private(PlexLayer layer,PetscSF cellLocalToGlobalSF)23532e1d0745SJose E. Roman static PetscErrorCode PlexLayerDistribute_Private(PlexLayer layer, PetscSF cellLocalToGlobalSF)
23542e1d0745SJose E. Roman {
23552e1d0745SJose E. Roman   IS           newConesIS, newOrientationsIS;
23562e1d0745SJose E. Roman   PetscSection newConeSizesSection;
23572e1d0745SJose E. Roman   MPI_Comm     comm;
23582e1d0745SJose E. Roman 
23592e1d0745SJose E. Roman   PetscFunctionBegin;
23602e1d0745SJose E. Roman   PetscCall(PetscObjectGetComm((PetscObject)cellLocalToGlobalSF, &comm));
23612e1d0745SJose E. Roman   PetscCall(PetscSectionCreate(comm, &newConeSizesSection));
23622e1d0745SJose E. Roman   //TODO rename to something like ISDistribute() with optional PetscSection argument
23632e1d0745SJose E. Roman   PetscCall(DMPlexDistributeFieldIS(NULL, cellLocalToGlobalSF, layer->coneSizesSection, layer->conesIS, newConeSizesSection, &newConesIS));
23642e1d0745SJose E. Roman   PetscCall(DMPlexDistributeFieldIS(NULL, cellLocalToGlobalSF, layer->coneSizesSection, layer->orientationsIS, newConeSizesSection, &newOrientationsIS));
23652e1d0745SJose E. Roman 
23662e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)newConeSizesSection, ((PetscObject)layer->coneSizesSection)->name));
23672e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)newConesIS, ((PetscObject)layer->conesIS)->name));
23682e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)newOrientationsIS, ((PetscObject)layer->orientationsIS)->name));
23692e1d0745SJose E. Roman   PetscCall(PetscSectionDestroy(&layer->coneSizesSection));
23702e1d0745SJose E. Roman   PetscCall(ISDestroy(&layer->conesIS));
23712e1d0745SJose E. Roman   PetscCall(ISDestroy(&layer->orientationsIS));
23722e1d0745SJose E. Roman   layer->coneSizesSection = newConeSizesSection;
23732e1d0745SJose E. Roman   layer->conesIS          = newConesIS;
23742e1d0745SJose E. Roman   layer->orientationsIS   = newOrientationsIS;
23752e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
23762e1d0745SJose E. Roman }
23772e1d0745SJose E. Roman 
23782e1d0745SJose E. Roman //TODO share code with DMPlexBuildFromCellListParallel()
23792e1d0745SJose E. Roman #include <petsc/private/hashseti.h>
PlexLayerCreateSFs_Private(PlexLayer layer,PetscSF * vertexOverlapSF,PetscSF * sfXC)23802e1d0745SJose E. Roman static PetscErrorCode PlexLayerCreateSFs_Private(PlexLayer layer, PetscSF *vertexOverlapSF, PetscSF *sfXC)
23812e1d0745SJose E. Roman {
23822e1d0745SJose E. Roman   PetscLayout     vertexLayout     = layer->vertexLayout;
23832e1d0745SJose E. Roman   PetscSection    coneSection      = layer->coneSizesSection;
23842e1d0745SJose E. Roman   IS              cellVertexData   = layer->conesIS;
23852e1d0745SJose E. Roman   IS              coneOrientations = layer->orientationsIS;
23862e1d0745SJose E. Roman   PetscSF         vl2gSF, vOverlapSF;
23872e1d0745SJose E. Roman   PetscInt       *verticesAdj;
23882e1d0745SJose E. Roman   PetscInt        i, n, numVerticesAdj;
23892e1d0745SJose E. Roman   const PetscInt *cvd, *co = NULL;
23902e1d0745SJose E. Roman   MPI_Comm        comm;
23912e1d0745SJose E. Roman 
23922e1d0745SJose E. Roman   PetscFunctionBegin;
23932e1d0745SJose E. Roman   PetscCall(PetscObjectGetComm((PetscObject)coneSection, &comm));
23942e1d0745SJose E. Roman   PetscCall(PetscSectionGetStorageSize(coneSection, &n));
23952e1d0745SJose E. Roman   {
23962e1d0745SJose E. Roman     PetscInt n0;
23972e1d0745SJose E. Roman 
23982e1d0745SJose E. Roman     PetscCall(ISGetLocalSize(cellVertexData, &n0));
23992e1d0745SJose 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);
24002e1d0745SJose E. Roman     PetscCall(ISGetIndices(cellVertexData, &cvd));
24012e1d0745SJose E. Roman   }
24022e1d0745SJose E. Roman   if (coneOrientations) {
24032e1d0745SJose E. Roman     PetscInt n0;
24042e1d0745SJose E. Roman 
24052e1d0745SJose E. Roman     PetscCall(ISGetLocalSize(coneOrientations, &n0));
24062e1d0745SJose 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);
24072e1d0745SJose E. Roman     PetscCall(ISGetIndices(coneOrientations, &co));
24082e1d0745SJose E. Roman   }
24092e1d0745SJose E. Roman   /* Get/check global number of vertices */
24102e1d0745SJose E. Roman   {
24112e1d0745SJose E. Roman     PetscInt NVerticesInCells = PETSC_INT_MIN;
24122e1d0745SJose E. Roman 
24132e1d0745SJose E. Roman     /* NVerticesInCells = max(cellVertexData) + 1 */
24142e1d0745SJose E. Roman     for (i = 0; i < n; i++)
24152e1d0745SJose E. Roman       if (cvd[i] > NVerticesInCells) NVerticesInCells = cvd[i];
24162e1d0745SJose E. Roman     ++NVerticesInCells;
24172e1d0745SJose E. Roman     PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, comm));
24182e1d0745SJose E. Roman 
24192e1d0745SJose E. Roman     if (vertexLayout->n == PETSC_DECIDE && vertexLayout->N == PETSC_DECIDE) vertexLayout->N = NVerticesInCells;
24202e1d0745SJose E. Roman     else
24212e1d0745SJose 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,
24222e1d0745SJose E. Roman                  vertexLayout->N, NVerticesInCells);
24232e1d0745SJose E. Roman     PetscCall(PetscLayoutSetUp(vertexLayout));
24242e1d0745SJose E. Roman   }
24252e1d0745SJose E. Roman   /* Find locally unique vertices in cellVertexData */
24262e1d0745SJose E. Roman   {
24272e1d0745SJose E. Roman     PetscHSetI vhash;
24282e1d0745SJose E. Roman     PetscInt   off = 0;
24292e1d0745SJose E. Roman 
24302e1d0745SJose E. Roman     PetscCall(PetscHSetICreate(&vhash));
24312e1d0745SJose E. Roman     for (i = 0; i < n; ++i) PetscCall(PetscHSetIAdd(vhash, cvd[i]));
24322e1d0745SJose E. Roman     PetscCall(PetscHSetIGetSize(vhash, &numVerticesAdj));
24332e1d0745SJose E. Roman     PetscCall(PetscMalloc1(numVerticesAdj, &verticesAdj));
24342e1d0745SJose E. Roman     PetscCall(PetscHSetIGetElems(vhash, &off, verticesAdj));
24352e1d0745SJose E. Roman     PetscAssert(off == numVerticesAdj, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Assertion failed: off == numVerticesAdj (%" PetscInt_FMT " != %" PetscInt_FMT ")", off, numVerticesAdj);
24362e1d0745SJose E. Roman     PetscCall(PetscHSetIDestroy(&vhash));
24372e1d0745SJose E. Roman   }
24382e1d0745SJose E. Roman   /* We must sort vertices to preserve numbering */
24392e1d0745SJose E. Roman   PetscCall(PetscSortInt(numVerticesAdj, verticesAdj));
24402e1d0745SJose E. Roman   /* Connect locally unique vertices with star forest */
24412e1d0745SJose E. Roman   PetscCall(PetscSFCreateByMatchingIndices(vertexLayout, numVerticesAdj, verticesAdj, NULL, 0, numVerticesAdj, verticesAdj, NULL, 0, &vl2gSF, &vOverlapSF));
24422e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)vOverlapSF, "overlapSF"));
24432e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)vl2gSF, "localToGlobalSF"));
24442e1d0745SJose E. Roman 
24452e1d0745SJose E. Roman   PetscCall(PetscFree(verticesAdj));
24462e1d0745SJose E. Roman   *vertexOverlapSF = vOverlapSF;
24472e1d0745SJose E. Roman   *sfXC            = vl2gSF;
24482e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
24492e1d0745SJose E. Roman }
24502e1d0745SJose E. Roman 
PlexLayerCreateCellSFs_Private(PlexLayer layer,PetscSF * cellOverlapSF,PetscSF * cellLocalToGlobalSF)24512e1d0745SJose E. Roman static PetscErrorCode PlexLayerCreateCellSFs_Private(PlexLayer layer, PetscSF *cellOverlapSF, PetscSF *cellLocalToGlobalSF)
24522e1d0745SJose E. Roman {
24532e1d0745SJose E. Roman   PetscSection coneSection = layer->coneSizesSection;
24542e1d0745SJose E. Roman   PetscInt     nCells;
24552e1d0745SJose E. Roman   MPI_Comm     comm;
24562e1d0745SJose E. Roman 
24572e1d0745SJose E. Roman   PetscFunctionBegin;
24582e1d0745SJose E. Roman   PetscCall(PetscObjectGetComm((PetscObject)coneSection, &comm));
24592e1d0745SJose E. Roman   {
24602e1d0745SJose E. Roman     PetscInt cStart;
24612e1d0745SJose E. Roman 
24622e1d0745SJose E. Roman     PetscCall(PetscSectionGetChart(coneSection, &cStart, &nCells));
24632e1d0745SJose E. Roman     PetscCheck(cStart == 0, comm, PETSC_ERR_ARG_OUTOFRANGE, "coneSection must start at 0");
24642e1d0745SJose E. Roman   }
24652e1d0745SJose E. Roman   /* Create overlapSF as empty SF with the right number of roots */
24662e1d0745SJose E. Roman   PetscCall(PetscSFCreate(comm, cellOverlapSF));
24672e1d0745SJose E. Roman   PetscCall(PetscSFSetGraph(*cellOverlapSF, nCells, 0, NULL, PETSC_USE_POINTER, NULL, PETSC_USE_POINTER));
24682e1d0745SJose E. Roman   PetscCall(PetscSFSetUp(*cellOverlapSF));
24692e1d0745SJose E. Roman   /* Create localToGlobalSF as identity mapping */
24702e1d0745SJose E. Roman   {
24712e1d0745SJose E. Roman     PetscLayout map;
24722e1d0745SJose E. Roman 
24732e1d0745SJose E. Roman     PetscCall(PetscLayoutCreateFromSizes(comm, nCells, PETSC_DECIDE, 1, &map));
24742e1d0745SJose E. Roman     PetscCall(PetscSFCreateFromLayouts(map, map, cellLocalToGlobalSF));
24752e1d0745SJose E. Roman     PetscCall(PetscSFSetUp(*cellLocalToGlobalSF));
24762e1d0745SJose E. Roman     PetscCall(PetscLayoutDestroy(&map));
24772e1d0745SJose E. Roman   }
24782e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
24792e1d0745SJose E. Roman }
24802e1d0745SJose E. Roman 
DMPlexTopologyBuildFromLayers_Private(DM dm,PetscInt depth,PlexLayer * layers,IS strataPermutation)24812e1d0745SJose E. Roman static PetscErrorCode DMPlexTopologyBuildFromLayers_Private(DM dm, PetscInt depth, PlexLayer *layers, IS strataPermutation)
24822e1d0745SJose E. Roman {
24832e1d0745SJose E. Roman   const PetscInt *permArr;
24842e1d0745SJose E. Roman   PetscInt        d, nPoints;
24852e1d0745SJose E. Roman   MPI_Comm        comm;
24862e1d0745SJose E. Roman 
24872e1d0745SJose E. Roman   PetscFunctionBegin;
24882e1d0745SJose E. Roman   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
24892e1d0745SJose E. Roman   PetscCall(ISGetIndices(strataPermutation, &permArr));
24902e1d0745SJose E. Roman 
24912e1d0745SJose E. Roman   /* Count points, strata offsets and cones offsets (taking strataPermutation into account) */
24922e1d0745SJose E. Roman   {
24932e1d0745SJose E. Roman     PetscInt stratumOffset = 0;
24942e1d0745SJose E. Roman     PetscInt conesOffset   = 0;
24952e1d0745SJose E. Roman 
24962e1d0745SJose E. Roman     for (d = 0; d <= depth; d++) {
24972e1d0745SJose E. Roman       const PetscInt  e = permArr[d];
24982e1d0745SJose E. Roman       const PlexLayer l = layers[e];
24992e1d0745SJose E. Roman       PetscInt        lo, n, size;
25002e1d0745SJose E. Roman 
25012e1d0745SJose E. Roman       PetscCall(PetscSectionGetChart(l->coneSizesSection, &lo, &n));
25022e1d0745SJose E. Roman       PetscCall(PetscSectionGetStorageSize(l->coneSizesSection, &size));
25032e1d0745SJose E. Roman       PetscCheck(lo == 0, comm, PETSC_ERR_PLIB, "starting point should be 0 in coneSizesSection %" PetscInt_FMT, d);
25042e1d0745SJose E. Roman       l->offset      = stratumOffset;
25052e1d0745SJose E. Roman       l->conesOffset = conesOffset;
25062e1d0745SJose E. Roman       stratumOffset += n;
25072e1d0745SJose E. Roman       conesOffset += size;
25082e1d0745SJose E. Roman     }
25092e1d0745SJose E. Roman     nPoints = stratumOffset;
25102e1d0745SJose E. Roman   }
25112e1d0745SJose E. Roman 
25122e1d0745SJose E. Roman   /* Set interval for all plex points */
25132e1d0745SJose E. Roman   //TODO we should store starting point of plex
25142e1d0745SJose E. Roman   PetscCall(DMPlexSetChart(dm, 0, nPoints));
25152e1d0745SJose E. Roman 
25162e1d0745SJose E. Roman   /* Set up plex coneSection from layer coneSections */
25172e1d0745SJose E. Roman   {
25182e1d0745SJose E. Roman     PetscSection coneSection;
25192e1d0745SJose E. Roman 
25202e1d0745SJose E. Roman     PetscCall(DMPlexGetConeSection(dm, &coneSection));
25212e1d0745SJose E. Roman     for (d = 0; d <= depth; d++) {
25222e1d0745SJose E. Roman       const PlexLayer l = layers[d];
25232e1d0745SJose E. Roman       PetscInt        n, q;
25242e1d0745SJose E. Roman 
25252e1d0745SJose E. Roman       PetscCall(PetscSectionGetChart(l->coneSizesSection, NULL, &n));
25262e1d0745SJose E. Roman       for (q = 0; q < n; q++) {
25272e1d0745SJose E. Roman         const PetscInt p = l->offset + q;
25282e1d0745SJose E. Roman         PetscInt       coneSize;
25292e1d0745SJose E. Roman 
25302e1d0745SJose E. Roman         PetscCall(PetscSectionGetDof(l->coneSizesSection, q, &coneSize));
25312e1d0745SJose E. Roman         PetscCall(PetscSectionSetDof(coneSection, p, coneSize));
25322e1d0745SJose E. Roman       }
25332e1d0745SJose E. Roman     }
25342e1d0745SJose E. Roman   }
25352e1d0745SJose E. Roman   //TODO this is terrible, DMSetUp_Plex() should be DMPlexSetUpSections() or so
25362e1d0745SJose E. Roman   PetscCall(DMSetUp(dm));
25372e1d0745SJose E. Roman 
25382e1d0745SJose E. Roman   /* Renumber cones points from layer-global numbering to plex-local numbering */
25392e1d0745SJose E. Roman   {
25402e1d0745SJose E. Roman     PetscInt *cones, *ornts;
25412e1d0745SJose E. Roman 
25422e1d0745SJose E. Roman     PetscCall(DMPlexGetCones(dm, &cones));
25432e1d0745SJose E. Roman     PetscCall(DMPlexGetConeOrientations(dm, &ornts));
25442e1d0745SJose E. Roman     for (d = 1; d <= depth; d++) {
25452e1d0745SJose E. Roman       const PlexLayer l = layers[d];
25462e1d0745SJose E. Roman       PetscInt        i, lConesSize;
25472e1d0745SJose E. Roman       PetscInt       *lCones;
25482e1d0745SJose E. Roman       const PetscInt *lOrnts;
25492e1d0745SJose E. Roman       PetscInt       *pCones = &cones[l->conesOffset];
25502e1d0745SJose E. Roman       PetscInt       *pOrnts = &ornts[l->conesOffset];
25512e1d0745SJose E. Roman 
25522e1d0745SJose E. Roman       PetscCall(PetscSectionGetStorageSize(l->coneSizesSection, &lConesSize));
25532e1d0745SJose E. Roman       /* Get cones in local plex numbering */
25542e1d0745SJose E. Roman       {
25552e1d0745SJose E. Roman         ISLocalToGlobalMapping l2g;
25562e1d0745SJose E. Roman         PetscLayout            vertexLayout = l->vertexLayout;
25572e1d0745SJose E. Roman         PetscSF                vertexSF     = layers[d - 1]->l2gSF; /* vertices of this layer are cells of previous layer */
25582e1d0745SJose E. Roman         const PetscInt        *gCones;
25592e1d0745SJose E. Roman         PetscInt               lConesSize0;
25602e1d0745SJose E. Roman 
25612e1d0745SJose E. Roman         PetscCall(ISGetLocalSize(l->conesIS, &lConesSize0));
25622e1d0745SJose E. Roman         PetscCheck(lConesSize0 == lConesSize, comm, PETSC_ERR_PLIB, "layer %" PetscInt_FMT " size(conesIS) = %" PetscInt_FMT " != %" PetscInt_FMT " = storageSize(coneSizesSection)", d, lConesSize0, lConesSize);
25632e1d0745SJose E. Roman         PetscCall(ISGetLocalSize(l->orientationsIS, &lConesSize0));
25642e1d0745SJose E. Roman         PetscCheck(lConesSize0 == lConesSize, comm, PETSC_ERR_PLIB, "layer %" PetscInt_FMT " size(orientationsIS) = %" PetscInt_FMT " != %" PetscInt_FMT " = storageSize(coneSizesSection)", d, lConesSize0, lConesSize);
25652e1d0745SJose E. Roman 
25662e1d0745SJose E. Roman         PetscCall(PetscMalloc1(lConesSize, &lCones));
25672e1d0745SJose E. Roman         PetscCall(ISGetIndices(l->conesIS, &gCones));
25682e1d0745SJose E. Roman         PetscCall(ISLocalToGlobalMappingCreateSF(vertexSF, vertexLayout->rstart, &l2g));
25692e1d0745SJose E. Roman         PetscCall(ISGlobalToLocalMappingApply(l2g, IS_GTOLM_MASK, lConesSize, gCones, &lConesSize0, lCones));
25702e1d0745SJose E. Roman         PetscCheck(lConesSize0 == lConesSize, comm, PETSC_ERR_PLIB, "global to local does not cover all indices (%" PetscInt_FMT " of %" PetscInt_FMT ")", lConesSize0, lConesSize);
25712e1d0745SJose E. Roman         PetscCall(ISLocalToGlobalMappingDestroy(&l2g));
25722e1d0745SJose E. Roman         PetscCall(ISRestoreIndices(l->conesIS, &gCones));
25732e1d0745SJose E. Roman       }
25742e1d0745SJose E. Roman       PetscCall(ISGetIndices(l->orientationsIS, &lOrnts));
25752e1d0745SJose E. Roman       /* Set cones, need to add stratum offset */
25762e1d0745SJose E. Roman       for (i = 0; i < lConesSize; i++) {
25772e1d0745SJose E. Roman         pCones[i] = lCones[i] + layers[d - 1]->offset; /* cone points of current layer are points of previous layer */
25782e1d0745SJose E. Roman         pOrnts[i] = lOrnts[i];
25792e1d0745SJose E. Roman       }
25802e1d0745SJose E. Roman       PetscCall(PetscFree(lCones));
25812e1d0745SJose E. Roman       PetscCall(ISRestoreIndices(l->orientationsIS, &lOrnts));
25822e1d0745SJose E. Roman     }
25832e1d0745SJose E. Roman   }
25842e1d0745SJose E. Roman   PetscCall(DMPlexSymmetrize(dm));
25852e1d0745SJose E. Roman   PetscCall(DMPlexStratify(dm));
25862e1d0745SJose E. Roman   PetscCall(ISRestoreIndices(strataPermutation, &permArr));
25872e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
25882e1d0745SJose E. Roman }
25892e1d0745SJose E. Roman 
PlexLayerConcatenateSFs_Private(MPI_Comm comm,PetscInt depth,PlexLayer layers[],IS strataPermutation,PetscSF * overlapSF,PetscSF * l2gSF)25902e1d0745SJose E. Roman static PetscErrorCode PlexLayerConcatenateSFs_Private(MPI_Comm comm, PetscInt depth, PlexLayer layers[], IS strataPermutation, PetscSF *overlapSF, PetscSF *l2gSF)
25912e1d0745SJose E. Roman {
25922e1d0745SJose E. Roman   PetscInt        d;
25932e1d0745SJose E. Roman   PetscSF        *osfs, *lsfs;
25942e1d0745SJose E. Roman   PetscInt       *leafOffsets;
25952e1d0745SJose E. Roman   const PetscInt *permArr;
25962e1d0745SJose E. Roman 
25972e1d0745SJose E. Roman   PetscFunctionBegin;
25982e1d0745SJose E. Roman   PetscCall(ISGetIndices(strataPermutation, &permArr));
25992e1d0745SJose E. Roman   PetscCall(PetscCalloc3(depth + 1, &osfs, depth + 1, &lsfs, depth + 1, &leafOffsets));
26002e1d0745SJose E. Roman   for (d = 0; d <= depth; d++) {
26012e1d0745SJose E. Roman     const PetscInt e = permArr[d];
26022e1d0745SJose E. Roman 
26032e1d0745SJose E. Roman     PetscAssert(e == layers[e]->d, PETSC_COMM_SELF, PETSC_ERR_PLIB, "assertion: e == layers[e]->d");
26042e1d0745SJose E. Roman     osfs[d]        = layers[e]->overlapSF;
26052e1d0745SJose E. Roman     lsfs[d]        = layers[e]->l2gSF;
26062e1d0745SJose E. Roman     leafOffsets[d] = layers[e]->offset;
26072e1d0745SJose E. Roman   }
26082e1d0745SJose E. Roman   PetscCall(PetscSFConcatenate(comm, depth + 1, osfs, PETSCSF_CONCATENATE_ROOTMODE_LOCAL, leafOffsets, overlapSF));
26092e1d0745SJose E. Roman   PetscCall(PetscSFConcatenate(comm, depth + 1, lsfs, PETSCSF_CONCATENATE_ROOTMODE_GLOBAL, leafOffsets, l2gSF));
26102e1d0745SJose E. Roman   PetscCall(PetscFree3(osfs, lsfs, leafOffsets));
26112e1d0745SJose E. Roman   PetscCall(ISRestoreIndices(strataPermutation, &permArr));
26122e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
26132e1d0745SJose E. Roman }
26142e1d0745SJose E. Roman 
26152e1d0745SJose E. Roman // Parallel load of topology
DMPlexTopologyLoad_HDF5_Private(DM dm,PetscViewer viewer,PetscSF * sfXC)26162e1d0745SJose E. Roman static PetscErrorCode DMPlexTopologyLoad_HDF5_Private(DM dm, PetscViewer viewer, PetscSF *sfXC)
26172e1d0745SJose E. Roman {
26182e1d0745SJose E. Roman   PlexLayer  *layers;
26192e1d0745SJose E. Roman   IS          strataPermutation;
26202e1d0745SJose E. Roman   PetscLayout pointsLayout;
26212e1d0745SJose E. Roman   PetscInt    depth;
26222e1d0745SJose E. Roman   PetscInt    d;
26232e1d0745SJose E. Roman   MPI_Comm    comm;
26242e1d0745SJose E. Roman 
26252e1d0745SJose E. Roman   PetscFunctionBegin;
26262e1d0745SJose E. Roman   {
26272e1d0745SJose E. Roman     PetscInt dim;
26282e1d0745SJose E. Roman 
26292e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5ReadAttribute(viewer, NULL, "depth", PETSC_INT, NULL, &depth));
26302e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5ReadAttribute(viewer, NULL, "cell_dim", PETSC_INT, NULL, &dim));
26312e1d0745SJose E. Roman     PetscCall(DMSetDimension(dm, dim));
26322e1d0745SJose E. Roman   }
26332e1d0745SJose E. Roman   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
26342e1d0745SJose E. Roman 
26352e1d0745SJose E. Roman   PetscCall(PetscInfo(dm, "Loading DM %s in parallel\n", dm->hdr.name));
26362e1d0745SJose E. Roman   {
26372e1d0745SJose E. Roman     IS spOnComm;
26382e1d0745SJose E. Roman 
26392e1d0745SJose E. Roman     PetscCall(ISCreate(comm, &spOnComm));
26402e1d0745SJose E. Roman     PetscCall(PetscObjectSetName((PetscObject)spOnComm, "permutation"));
26412e1d0745SJose E. Roman     PetscCall(ISLoad(spOnComm, viewer));
26422e1d0745SJose E. Roman     /* have the same serial IS on every rank */
26432e1d0745SJose E. Roman     PetscCall(ISAllGather(spOnComm, &strataPermutation));
26442e1d0745SJose E. Roman     PetscCall(PetscObjectSetName((PetscObject)strataPermutation, ((PetscObject)spOnComm)->name));
26452e1d0745SJose E. Roman     PetscCall(ISDestroy(&spOnComm));
26462e1d0745SJose E. Roman   }
26472e1d0745SJose E. Roman 
26482e1d0745SJose E. Roman   /* Create layers, load raw data for each layer */
26492e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "strata"));
26502e1d0745SJose E. Roman   PetscCall(PetscMalloc1(depth + 1, &layers));
26512e1d0745SJose E. Roman   for (d = depth, pointsLayout = NULL; d >= 0; pointsLayout = layers[d]->vertexLayout, d--) {
26522e1d0745SJose E. Roman     PetscCall(PlexLayerCreate_Private(&layers[d]));
26532e1d0745SJose E. Roman     PetscCall(PlexLayerLoad_Private(layers[d], viewer, d, pointsLayout));
26542e1d0745SJose E. Roman   }
26552e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer)); /* strata */
26562e1d0745SJose E. Roman 
26572e1d0745SJose E. Roman   for (d = depth; d >= 0; d--) {
26582e1d0745SJose E. Roman     /* Redistribute cells and vertices for each applicable layer */
26592e1d0745SJose E. Roman     if (d < depth) PetscCall(PlexLayerDistribute_Private(layers[d], layers[d]->l2gSF));
26602e1d0745SJose E. Roman     /* Create vertex overlap SF and vertex localToGlobal SF for each applicable layer */
26612e1d0745SJose E. Roman     if (d > 0) PetscCall(PlexLayerCreateSFs_Private(layers[d], &layers[d - 1]->overlapSF, &layers[d - 1]->l2gSF));
26622e1d0745SJose E. Roman   }
26632e1d0745SJose E. Roman   /* Build trivial SFs for the cell layer as well */
26642e1d0745SJose E. Roman   PetscCall(PlexLayerCreateCellSFs_Private(layers[depth], &layers[depth]->overlapSF, &layers[depth]->l2gSF));
26652e1d0745SJose E. Roman 
26662e1d0745SJose E. Roman   /* Build DMPlex topology from the layers */
26672e1d0745SJose E. Roman   PetscCall(DMPlexTopologyBuildFromLayers_Private(dm, depth, layers, strataPermutation));
26682e1d0745SJose E. Roman 
26692e1d0745SJose E. Roman   /* Build overall point SF alias overlap SF */
26702e1d0745SJose E. Roman   {
26712e1d0745SJose E. Roman     PetscSF overlapSF;
26722e1d0745SJose E. Roman 
26732e1d0745SJose E. Roman     PetscCall(PlexLayerConcatenateSFs_Private(comm, depth, layers, strataPermutation, &overlapSF, sfXC));
26742e1d0745SJose E. Roman     PetscCall(DMSetPointSF(dm, overlapSF));
26752e1d0745SJose E. Roman     PetscCall(PetscSFDestroy(&overlapSF));
26762e1d0745SJose E. Roman   }
26772e1d0745SJose E. Roman 
26782e1d0745SJose E. Roman   for (d = depth; d >= 0; d--) PetscCall(PlexLayerDestroy(&layers[d]));
26792e1d0745SJose E. Roman   PetscCall(PetscFree(layers));
26802e1d0745SJose E. Roman   PetscCall(ISDestroy(&strataPermutation));
26812e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
26822e1d0745SJose E. Roman }
26832e1d0745SJose E. Roman 
DMPlexTopologyLoad_HDF5_Internal(DM dm,PetscViewer viewer,PetscSF * sfXC)26842e1d0745SJose E. Roman PetscErrorCode DMPlexTopologyLoad_HDF5_Internal(DM dm, PetscViewer viewer, PetscSF *sfXC)
26852e1d0745SJose E. Roman {
26862e1d0745SJose E. Roman   DMPlexStorageVersion version;
26872e1d0745SJose E. Roman   const char          *topologydm_name;
26882e1d0745SJose E. Roman   char                 group[PETSC_MAX_PATH_LEN];
26892e1d0745SJose E. Roman   PetscSF              sfwork = NULL;
26902e1d0745SJose E. Roman 
26912e1d0745SJose E. Roman   PetscFunctionBegin;
26922e1d0745SJose E. Roman   PetscCall(DMPlexGetHDF5Name_Private(dm, &topologydm_name));
26932e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5GetDMPlexStorageVersionReading(viewer, &version));
26942e1d0745SJose E. Roman   if (DMPlexStorageVersionGE(version, 2, 0, 0)) {
26952e1d0745SJose E. Roman     PetscCall(PetscSNPrintf(group, sizeof(group), "topologies/%s", topologydm_name));
26962e1d0745SJose E. Roman   } else {
26972e1d0745SJose E. Roman     PetscCall(PetscStrncpy(group, "/", sizeof(group)));
26982e1d0745SJose E. Roman   }
26992e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, group));
27002e1d0745SJose E. Roman 
27012e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "topology"));
27022e1d0745SJose E. Roman   if (version->major < 3) {
27032e1d0745SJose E. Roman     PetscCall(DMPlexTopologyLoad_HDF5_Legacy_Private(dm, viewer, &sfwork));
27042e1d0745SJose E. Roman   } else {
27052e1d0745SJose E. Roman     /* since DMPlexStorageVersion 3.0.0 */
27062e1d0745SJose E. Roman     PetscCall(DMPlexTopologyLoad_HDF5_Private(dm, viewer, &sfwork));
27072e1d0745SJose E. Roman   }
27082e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer)); /* "topology" */
27092e1d0745SJose E. Roman 
27102e1d0745SJose E. Roman   if (DMPlexStorageVersionGE(version, 2, 0, 0)) {
27112e1d0745SJose E. Roman     DM          distdm;
27122e1d0745SJose E. Roman     PetscSF     distsf;
27132e1d0745SJose E. Roman     const char *distribution_name;
27142e1d0745SJose E. Roman     PetscBool   exists;
27152e1d0745SJose E. Roman 
27162e1d0745SJose E. Roman     PetscCall(DMPlexDistributionGetName(dm, &distribution_name));
27172e1d0745SJose E. Roman     /* this group is guaranteed to be present since DMPlexStorageVersion 2.1.0 */
27182e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5PushGroup(viewer, "distributions"));
27192e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5HasGroup(viewer, NULL, &exists));
27202e1d0745SJose E. Roman     if (exists) {
27212e1d0745SJose E. Roman       PetscCall(PetscViewerHDF5PushGroup(viewer, distribution_name));
27222e1d0745SJose E. Roman       PetscCall(DMPlexDistributionLoad_HDF5_Private(dm, viewer, sfwork, &distsf, &distdm));
27232e1d0745SJose E. Roman       if (distdm) {
27242e1d0745SJose E. Roman         PetscCall(DMPlexReplace_Internal(dm, &distdm));
27252e1d0745SJose E. Roman         PetscCall(PetscSFDestroy(&sfwork));
27262e1d0745SJose E. Roman         sfwork = distsf;
27272e1d0745SJose E. Roman       }
27282e1d0745SJose E. Roman       PetscCall(PetscViewerHDF5PopGroup(viewer)); /* distribution_name */
27292e1d0745SJose E. Roman     }
27302e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5PopGroup(viewer)); /* "distributions" */
27312e1d0745SJose E. Roman   }
27322e1d0745SJose E. Roman   if (sfXC) {
27332e1d0745SJose E. Roman     *sfXC = sfwork;
27342e1d0745SJose E. Roman   } else {
27352e1d0745SJose E. Roman     PetscCall(PetscSFDestroy(&sfwork));
27362e1d0745SJose E. Roman   }
27372e1d0745SJose E. Roman 
27382e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
27392e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
27402e1d0745SJose E. Roman }
27412e1d0745SJose E. Roman 
27422e1d0745SJose E. Roman /* If the file is old, it not only has different path to the coordinates, but   */
27432e1d0745SJose E. Roman /* does not contain coordinateDMs, so must fall back to the old implementation. */
DMPlexCoordinatesLoad_HDF5_Legacy_Private(DM dm,PetscViewer viewer)27442e1d0745SJose E. Roman static PetscErrorCode DMPlexCoordinatesLoad_HDF5_Legacy_Private(DM dm, PetscViewer viewer)
27452e1d0745SJose E. Roman {
27462e1d0745SJose E. Roman   PetscSection coordSection;
27472e1d0745SJose E. Roman   Vec          coordinates;
27482e1d0745SJose E. Roman   PetscReal    lengthScale;
27492e1d0745SJose E. Roman   PetscInt     spatialDim, N, numVertices, vStart, vEnd, v;
27502e1d0745SJose E. Roman   PetscMPIInt  rank;
27512e1d0745SJose E. Roman 
27522e1d0745SJose E. Roman   PetscFunctionBegin;
27532e1d0745SJose E. Roman   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
27542e1d0745SJose E. Roman   /* Read geometry */
27552e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "/geometry"));
27562e1d0745SJose E. Roman   PetscCall(VecCreate(PetscObjectComm((PetscObject)dm), &coordinates));
27572e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)coordinates, "vertices"));
27582e1d0745SJose E. Roman   {
27592e1d0745SJose E. Roman     /* Force serial load */
27602e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5ReadSizes(viewer, "vertices", &spatialDim, &N));
27612e1d0745SJose E. Roman     PetscCall(VecSetSizes(coordinates, rank == 0 ? N : 0, N));
27622e1d0745SJose E. Roman     PetscCall(VecSetBlockSize(coordinates, spatialDim));
27632e1d0745SJose E. Roman   }
27642e1d0745SJose E. Roman   PetscCall(VecLoad(coordinates, viewer));
27652e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
27662e1d0745SJose E. Roman   PetscCall(DMPlexGetScale(dm, PETSC_UNIT_LENGTH, &lengthScale));
27672e1d0745SJose E. Roman   PetscCall(VecScale(coordinates, 1.0 / lengthScale));
27682e1d0745SJose E. Roman   PetscCall(VecGetLocalSize(coordinates, &numVertices));
27692e1d0745SJose E. Roman   PetscCall(VecGetBlockSize(coordinates, &spatialDim));
27702e1d0745SJose E. Roman   numVertices /= spatialDim;
27712e1d0745SJose E. Roman   /* Create coordinates */
27722e1d0745SJose E. Roman   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
27732e1d0745SJose 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);
27742e1d0745SJose E. Roman   PetscCall(DMGetCoordinateSection(dm, &coordSection));
27752e1d0745SJose E. Roman   PetscCall(PetscSectionSetNumFields(coordSection, 1));
27762e1d0745SJose E. Roman   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spatialDim));
27772e1d0745SJose E. Roman   PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd));
27782e1d0745SJose E. Roman   for (v = vStart; v < vEnd; ++v) {
27792e1d0745SJose E. Roman     PetscCall(PetscSectionSetDof(coordSection, v, spatialDim));
27802e1d0745SJose E. Roman     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spatialDim));
27812e1d0745SJose E. Roman   }
27822e1d0745SJose E. Roman   PetscCall(PetscSectionSetUp(coordSection));
27832e1d0745SJose E. Roman   PetscCall(DMSetCoordinates(dm, coordinates));
27842e1d0745SJose E. Roman   PetscCall(VecDestroy(&coordinates));
27852e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
27862e1d0745SJose E. Roman }
27872e1d0745SJose E. Roman 
DMPlexCoordinatesLoad_HDF5_Internal(DM dm,PetscViewer viewer,PetscSF sfXC)27882e1d0745SJose E. Roman PetscErrorCode DMPlexCoordinatesLoad_HDF5_Internal(DM dm, PetscViewer viewer, PetscSF sfXC)
27892e1d0745SJose E. Roman {
27902e1d0745SJose E. Roman   DMPlexStorageVersion version;
27912e1d0745SJose E. Roman   DM                   cdm;
27922e1d0745SJose E. Roman   Vec                  coords;
27932e1d0745SJose E. Roman   PetscInt             blockSize;
27942e1d0745SJose E. Roman   PetscReal            lengthScale;
27952e1d0745SJose E. Roman   PetscSF              lsf;
27962e1d0745SJose E. Roman   const char          *topologydm_name;
27972e1d0745SJose E. Roman   char                *coordinatedm_name, *coordinates_name;
27982e1d0745SJose E. Roman 
27992e1d0745SJose E. Roman   PetscFunctionBegin;
28002e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5GetDMPlexStorageVersionReading(viewer, &version));
28012e1d0745SJose E. Roman   if (!DMPlexStorageVersionGE(version, 2, 0, 0)) {
28022e1d0745SJose E. Roman     PetscCall(DMPlexCoordinatesLoad_HDF5_Legacy_Private(dm, viewer));
28032e1d0745SJose E. Roman     PetscFunctionReturn(PETSC_SUCCESS);
28042e1d0745SJose E. Roman   }
28052e1d0745SJose E. Roman   /* else: since DMPlexStorageVersion 2.0.0 */
28062e1d0745SJose E. Roman   PetscCheck(sfXC, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_NULL, "PetscSF must be given for parallel load");
28072e1d0745SJose E. Roman   PetscCall(DMPlexGetHDF5Name_Private(dm, &topologydm_name));
28082e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "topologies"));
28092e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, topologydm_name));
28102e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5ReadAttribute(viewer, NULL, "coordinateDMName", PETSC_STRING, NULL, &coordinatedm_name));
28112e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5ReadAttribute(viewer, NULL, "coordinatesName", PETSC_STRING, NULL, &coordinates_name));
28122e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
28132e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
28142e1d0745SJose E. Roman   PetscCall(DMGetCoordinateDM(dm, &cdm));
28152e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)cdm, coordinatedm_name));
28162e1d0745SJose E. Roman   PetscCall(PetscFree(coordinatedm_name));
28172e1d0745SJose E. Roman   /* lsf: on-disk data -> in-memory local vector associated with cdm's local section */
28182e1d0745SJose E. Roman   PetscCall(DMPlexSectionLoad(dm, viewer, cdm, sfXC, NULL, &lsf));
28192e1d0745SJose E. Roman   PetscCall(DMCreateLocalVector(cdm, &coords));
28202e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)coords, coordinates_name));
28212e1d0745SJose E. Roman   PetscCall(PetscFree(coordinates_name));
28222e1d0745SJose E. Roman   PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_NATIVE));
28232e1d0745SJose E. Roman   PetscCall(DMPlexLocalVectorLoad(dm, viewer, cdm, lsf, coords));
28242e1d0745SJose E. Roman   PetscCall(PetscViewerPopFormat(viewer));
28252e1d0745SJose E. Roman   PetscCall(DMPlexGetScale(dm, PETSC_UNIT_LENGTH, &lengthScale));
28262e1d0745SJose E. Roman   PetscCall(VecScale(coords, 1.0 / lengthScale));
28272e1d0745SJose E. Roman   PetscCall(DMSetCoordinatesLocal(dm, coords));
28282e1d0745SJose E. Roman   PetscCall(VecGetBlockSize(coords, &blockSize));
28292e1d0745SJose E. Roman   PetscCall(DMSetCoordinateDim(dm, blockSize));
28302e1d0745SJose E. Roman   PetscCall(VecDestroy(&coords));
28312e1d0745SJose E. Roman   PetscCall(PetscSFDestroy(&lsf));
28322e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
28332e1d0745SJose E. Roman }
28342e1d0745SJose E. Roman 
DMPlexLoad_HDF5_Internal(DM dm,PetscViewer viewer)28352e1d0745SJose E. Roman PetscErrorCode DMPlexLoad_HDF5_Internal(DM dm, PetscViewer viewer)
28362e1d0745SJose E. Roman {
28372e1d0745SJose E. Roman   DMPlexStorageVersion version;
28382e1d0745SJose E. Roman 
28392e1d0745SJose E. Roman   PetscFunctionBegin;
28402e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5GetDMPlexStorageVersionReading(viewer, &version));
28412e1d0745SJose E. Roman   PetscCall(PetscInfo(dm, "Loading DM %s storage version %d.%d.%d\n", dm->hdr.name, version->major, version->minor, version->subminor));
28422e1d0745SJose E. Roman   if (!DMPlexStorageVersionGE(version, 2, 0, 0)) {
28432e1d0745SJose E. Roman     PetscCall(DMPlexTopologyLoad_HDF5_Internal(dm, viewer, NULL));
28442e1d0745SJose E. Roman     PetscCall(DMPlexLabelsLoad_HDF5_Internal(dm, viewer, NULL));
28452e1d0745SJose E. Roman     PetscCall(DMPlexCoordinatesLoad_HDF5_Legacy_Private(dm, viewer));
28462e1d0745SJose E. Roman   } else {
28472e1d0745SJose E. Roman     PetscSF sfXC;
28482e1d0745SJose E. Roman 
28492e1d0745SJose E. Roman     /* since DMPlexStorageVersion 2.0.0 */
28502e1d0745SJose E. Roman     PetscCall(DMPlexTopologyLoad_HDF5_Internal(dm, viewer, &sfXC));
28512e1d0745SJose E. Roman     PetscCall(DMPlexLabelsLoad_HDF5_Internal(dm, viewer, sfXC));
28522e1d0745SJose E. Roman     PetscCall(DMPlexCoordinatesLoad_HDF5_Internal(dm, viewer, sfXC));
28532e1d0745SJose E. Roman     PetscCall(PetscSFDestroy(&sfXC));
28542e1d0745SJose E. Roman   }
28552e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
28562e1d0745SJose E. Roman }
28572e1d0745SJose E. Roman 
DMPlexSectionLoad_HDF5_Internal_CreateDataSF(PetscSection rootSection,PetscLayout layout,PetscInt globalOffsets[],PetscSection leafSection,PetscSF * sectionSF)28582e1d0745SJose E. Roman static PetscErrorCode DMPlexSectionLoad_HDF5_Internal_CreateDataSF(PetscSection rootSection, PetscLayout layout, PetscInt globalOffsets[], PetscSection leafSection, PetscSF *sectionSF)
28592e1d0745SJose E. Roman {
28602e1d0745SJose E. Roman   MPI_Comm  comm;
28612e1d0745SJose E. Roman   PetscInt  pStart, pEnd, p, m;
28622e1d0745SJose E. Roman   PetscInt *goffs, *ilocal;
28632e1d0745SJose E. Roman   PetscBool rootIncludeConstraints, leafIncludeConstraints;
28642e1d0745SJose E. Roman 
28652e1d0745SJose E. Roman   PetscFunctionBegin;
28662e1d0745SJose E. Roman   PetscCall(PetscObjectGetComm((PetscObject)leafSection, &comm));
28672e1d0745SJose E. Roman   PetscCall(PetscSectionGetChart(leafSection, &pStart, &pEnd));
28682e1d0745SJose E. Roman   PetscCall(PetscSectionGetIncludesConstraints(rootSection, &rootIncludeConstraints));
28692e1d0745SJose E. Roman   PetscCall(PetscSectionGetIncludesConstraints(leafSection, &leafIncludeConstraints));
28702e1d0745SJose E. Roman   if (rootIncludeConstraints && leafIncludeConstraints) PetscCall(PetscSectionGetStorageSize(leafSection, &m));
28712e1d0745SJose E. Roman   else PetscCall(PetscSectionGetConstrainedStorageSize(leafSection, &m));
28722e1d0745SJose E. Roman   PetscCall(PetscMalloc1(m, &ilocal));
28732e1d0745SJose E. Roman   PetscCall(PetscMalloc1(m, &goffs));
28742e1d0745SJose E. Roman   /* Currently, PetscSFDistributeSection() returns globalOffsets[] only */
28752e1d0745SJose E. Roman   /* for the top-level section (not for each field), so one must have   */
28762e1d0745SJose E. Roman   /* rootSection->pointMajor == PETSC_TRUE.                             */
28772e1d0745SJose E. Roman   PetscCheck(rootSection->pointMajor, PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for field major ordering");
28782e1d0745SJose E. Roman   /* Currently, we also assume that leafSection->pointMajor == PETSC_TRUE. */
28792e1d0745SJose E. Roman   PetscCheck(leafSection->pointMajor, PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for field major ordering");
28802e1d0745SJose E. Roman   for (p = pStart, m = 0; p < pEnd; ++p) {
28812e1d0745SJose E. Roman     PetscInt        dof, cdof, i, j, off, goff;
28822e1d0745SJose E. Roman     const PetscInt *cinds;
28832e1d0745SJose E. Roman 
28842e1d0745SJose E. Roman     PetscCall(PetscSectionGetDof(leafSection, p, &dof));
28852e1d0745SJose E. Roman     if (dof < 0) continue;
28862e1d0745SJose E. Roman     goff = globalOffsets[p - pStart];
28872e1d0745SJose E. Roman     PetscCall(PetscSectionGetOffset(leafSection, p, &off));
28882e1d0745SJose E. Roman     PetscCall(PetscSectionGetConstraintDof(leafSection, p, &cdof));
28892e1d0745SJose E. Roman     PetscCall(PetscSectionGetConstraintIndices(leafSection, p, &cinds));
28902e1d0745SJose E. Roman     for (i = 0, j = 0; i < dof; ++i) {
28912e1d0745SJose E. Roman       PetscBool constrained = (PetscBool)(j < cdof && i == cinds[j]);
28922e1d0745SJose E. Roman 
28932e1d0745SJose E. Roman       if (!constrained || (leafIncludeConstraints && rootIncludeConstraints)) {
28942e1d0745SJose E. Roman         ilocal[m]  = off++;
28952e1d0745SJose E. Roman         goffs[m++] = goff++;
28962e1d0745SJose E. Roman       } else if (leafIncludeConstraints && !rootIncludeConstraints) ++off;
28972e1d0745SJose E. Roman       else if (!leafIncludeConstraints && rootIncludeConstraints) ++goff;
28982e1d0745SJose E. Roman       if (constrained) ++j;
28992e1d0745SJose E. Roman     }
29002e1d0745SJose E. Roman   }
29012e1d0745SJose E. Roman   PetscCall(PetscSFCreate(comm, sectionSF));
29022e1d0745SJose E. Roman   PetscCall(PetscSFSetFromOptions(*sectionSF));
29032e1d0745SJose E. Roman   PetscCall(PetscSFSetGraphLayout(*sectionSF, layout, m, ilocal, PETSC_OWN_POINTER, goffs));
29042e1d0745SJose E. Roman   PetscCall(PetscFree(goffs));
29052e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
29062e1d0745SJose E. Roman }
29072e1d0745SJose E. Roman 
DMPlexSectionLoad_HDF5_Internal(DM dm,PetscViewer viewer,DM sectiondm,PetscSF sfXB,PetscSF * gsf,PetscSF * lsf)29082e1d0745SJose E. Roman PetscErrorCode DMPlexSectionLoad_HDF5_Internal(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sfXB, PetscSF *gsf, PetscSF *lsf)
29092e1d0745SJose E. Roman {
29102e1d0745SJose E. Roman   MPI_Comm     comm;
29112e1d0745SJose E. Roman   PetscMPIInt  size, rank;
29122e1d0745SJose E. Roman   const char  *topologydm_name;
29132e1d0745SJose E. Roman   const char  *sectiondm_name;
29142e1d0745SJose E. Roman   PetscSection sectionA, sectionB;
29152e1d0745SJose E. Roman   PetscBool    has;
29162e1d0745SJose E. Roman   PetscInt     nX, n, i;
29172e1d0745SJose E. Roman   PetscSF      sfAB;
29182e1d0745SJose E. Roman 
29192e1d0745SJose E. Roman   PetscFunctionBegin;
29202e1d0745SJose E. Roman   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
29212e1d0745SJose E. Roman   PetscCallMPI(MPI_Comm_size(comm, &size));
29222e1d0745SJose E. Roman   PetscCallMPI(MPI_Comm_rank(comm, &rank));
29232e1d0745SJose E. Roman   PetscCall(DMPlexGetHDF5Name_Private(dm, &topologydm_name));
29242e1d0745SJose E. Roman   PetscCall(PetscObjectGetName((PetscObject)sectiondm, &sectiondm_name));
29252e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "topologies"));
29262e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, topologydm_name));
29272e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "dms"));
29282e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, sectiondm_name));
29292e1d0745SJose E. Roman   /* A: on-disk points                        */
29302e1d0745SJose E. Roman   /* X: list of global point numbers, [0, NX) */
29312e1d0745SJose E. Roman   /* B: plex points                           */
29322e1d0745SJose E. Roman   /* Load raw section (sectionA)              */
29332e1d0745SJose E. Roman   PetscCall(PetscSectionCreate(comm, &sectionA));
29342e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5HasGroup(viewer, "section", &has));
29352e1d0745SJose E. Roman   if (has) PetscCall(PetscSectionLoad(sectionA, viewer));
29362e1d0745SJose E. Roman   else {
29372e1d0745SJose E. Roman     // TODO If section is missing, create the default affine section with dim dofs on each vertex. Use PetscSplitOwnership() to split vertices.
29382e1d0745SJose E. Roman     //   How do I know the total number of vertices?
29392e1d0745SJose E. Roman     PetscInt dim, Nf = 1, Nv, nv = PETSC_DECIDE;
29402e1d0745SJose E. Roman 
29412e1d0745SJose E. Roman     PetscCall(DMGetDimension(dm, &dim));
29422e1d0745SJose E. Roman     PetscCall(DMPlexGetDepthStratumGlobalSize(dm, 0, &Nv));
29432e1d0745SJose E. Roman     PetscCall(PetscSectionSetNumFields(sectionA, Nf));
29442e1d0745SJose E. Roman     PetscCall(PetscSectionSetFieldName(sectionA, 0, "Cartesian"));
29452e1d0745SJose E. Roman     PetscCall(PetscSectionSetFieldComponents(sectionA, 0, dim));
29462e1d0745SJose E. Roman     for (PetscInt c = 0; c < dim; ++c) {
29472e1d0745SJose E. Roman       char axis = 'X' + (char)c;
29482e1d0745SJose E. Roman 
29492e1d0745SJose E. Roman       PetscCall(PetscSectionSetComponentName(sectionA, 0, c, &axis));
29502e1d0745SJose E. Roman     }
29512e1d0745SJose E. Roman     PetscCall(PetscSplitOwnership(comm, &nv, &Nv));
29522e1d0745SJose E. Roman     PetscCall(PetscSectionSetChart(sectionA, 0, nv));
29532e1d0745SJose E. Roman     for (PetscInt p = 0; p < nv; ++p) {
29542e1d0745SJose E. Roman       PetscCall(PetscSectionSetDof(sectionA, p, dim));
29552e1d0745SJose E. Roman       PetscCall(PetscSectionSetFieldDof(sectionA, p, 0, dim));
29562e1d0745SJose E. Roman     }
29572e1d0745SJose E. Roman     PetscCall(PetscSectionSetUp(sectionA));
29582e1d0745SJose E. Roman   }
29592e1d0745SJose E. Roman   PetscCall(PetscSectionGetChart(sectionA, NULL, &n));
29602e1d0745SJose E. Roman /* Create sfAB: A -> B */
29612e1d0745SJose E. Roman #if defined(PETSC_USE_DEBUG)
29622e1d0745SJose E. Roman   {
29632e1d0745SJose E. Roman     PetscInt N, N1;
29642e1d0745SJose E. Roman 
29652e1d0745SJose E. Roman     PetscCall(PetscViewerHDF5ReadSizes(viewer, "order", NULL, &N1));
29662e1d0745SJose E. Roman     PetscCallMPI(MPIU_Allreduce(&n, &N, 1, MPIU_INT, MPI_SUM, comm));
29672e1d0745SJose 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);
29682e1d0745SJose E. Roman   }
29692e1d0745SJose E. Roman #endif
29702e1d0745SJose E. Roman   {
29712e1d0745SJose E. Roman     IS              orderIS;
29722e1d0745SJose E. Roman     const PetscInt *gpoints;
29732e1d0745SJose E. Roman     PetscSF         sfXA, sfAX;
29742e1d0745SJose E. Roman     PetscLayout     layout;
29752e1d0745SJose E. Roman     PetscSFNode    *owners, *buffer;
29762e1d0745SJose E. Roman     PetscInt        nleaves;
29772e1d0745SJose E. Roman     PetscInt       *ilocal;
29782e1d0745SJose E. Roman     PetscSFNode    *iremote;
29792e1d0745SJose E. Roman 
29802e1d0745SJose E. Roman     /* Create sfAX: A -> X */
29812e1d0745SJose E. Roman     PetscCall(ISCreate(comm, &orderIS));
29822e1d0745SJose E. Roman     PetscCall(PetscObjectSetName((PetscObject)orderIS, "order"));
29832e1d0745SJose E. Roman     PetscCall(PetscLayoutSetLocalSize(orderIS->map, n));
29842e1d0745SJose E. Roman     PetscCall(ISLoad(orderIS, viewer));
29852e1d0745SJose E. Roman     PetscCall(PetscLayoutCreate(comm, &layout));
29862e1d0745SJose E. Roman     PetscCall(PetscSFGetGraph(sfXB, &nX, NULL, NULL, NULL));
29872e1d0745SJose E. Roman     PetscCall(PetscLayoutSetLocalSize(layout, nX));
29882e1d0745SJose E. Roman     PetscCall(PetscLayoutSetBlockSize(layout, 1));
29892e1d0745SJose E. Roman     PetscCall(PetscLayoutSetUp(layout));
29902e1d0745SJose E. Roman     PetscCall(PetscSFCreate(comm, &sfXA));
29912e1d0745SJose E. Roman     PetscCall(ISGetIndices(orderIS, &gpoints));
29922e1d0745SJose E. Roman     PetscCall(PetscSFSetGraphLayout(sfXA, layout, n, NULL, PETSC_OWN_POINTER, gpoints));
29932e1d0745SJose E. Roman     PetscCall(ISRestoreIndices(orderIS, &gpoints));
29942e1d0745SJose E. Roman     PetscCall(ISDestroy(&orderIS));
29952e1d0745SJose E. Roman     PetscCall(PetscLayoutDestroy(&layout));
29962e1d0745SJose E. Roman     PetscCall(PetscMalloc1(n, &owners));
29972e1d0745SJose E. Roman     PetscCall(PetscMalloc1(nX, &buffer));
29982e1d0745SJose E. Roman     for (i = 0; i < n; ++i) {
29992e1d0745SJose E. Roman       owners[i].rank  = rank;
30002e1d0745SJose E. Roman       owners[i].index = i;
30012e1d0745SJose E. Roman     }
30022e1d0745SJose E. Roman     for (i = 0; i < nX; ++i) {
30032e1d0745SJose E. Roman       buffer[i].rank  = -1;
30042e1d0745SJose E. Roman       buffer[i].index = -1;
30052e1d0745SJose E. Roman     }
30062e1d0745SJose E. Roman     PetscCall(PetscSFReduceBegin(sfXA, MPIU_SF_NODE, owners, buffer, MPI_MAXLOC));
30072e1d0745SJose E. Roman     PetscCall(PetscSFReduceEnd(sfXA, MPIU_SF_NODE, owners, buffer, MPI_MAXLOC));
30082e1d0745SJose E. Roman     PetscCall(PetscSFDestroy(&sfXA));
30092e1d0745SJose E. Roman     PetscCall(PetscFree(owners));
30102e1d0745SJose E. Roman     for (i = 0, nleaves = 0; i < nX; ++i)
30112e1d0745SJose E. Roman       if (buffer[i].rank >= 0) nleaves++;
30122e1d0745SJose E. Roman     PetscCall(PetscMalloc1(nleaves, &ilocal));
30132e1d0745SJose E. Roman     PetscCall(PetscMalloc1(nleaves, &iremote));
30142e1d0745SJose E. Roman     for (i = 0, nleaves = 0; i < nX; ++i) {
30152e1d0745SJose E. Roman       if (buffer[i].rank >= 0) {
30162e1d0745SJose E. Roman         ilocal[nleaves]        = i;
30172e1d0745SJose E. Roman         iremote[nleaves].rank  = buffer[i].rank;
30182e1d0745SJose E. Roman         iremote[nleaves].index = buffer[i].index;
30192e1d0745SJose E. Roman         nleaves++;
30202e1d0745SJose E. Roman       }
30212e1d0745SJose E. Roman     }
30222e1d0745SJose E. Roman     PetscCall(PetscFree(buffer));
30232e1d0745SJose E. Roman     PetscCall(PetscSFCreate(comm, &sfAX));
30242e1d0745SJose E. Roman     PetscCall(PetscSFSetFromOptions(sfAX));
30252e1d0745SJose E. Roman     PetscCall(PetscSFSetGraph(sfAX, n, nleaves, ilocal, PETSC_OWN_POINTER, iremote, PETSC_OWN_POINTER));
30262e1d0745SJose E. Roman     PetscCall(PetscSFCompose(sfAX, sfXB, &sfAB));
30272e1d0745SJose E. Roman     PetscCall(PetscSFDestroy(&sfAX));
30282e1d0745SJose E. Roman   }
30292e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
30302e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
30312e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
30322e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
30332e1d0745SJose E. Roman   /* Create plex section (sectionB) */
30342e1d0745SJose E. Roman   PetscCall(DMGetLocalSection(sectiondm, &sectionB));
30352e1d0745SJose E. Roman   if (lsf || gsf) {
30362e1d0745SJose E. Roman     PetscLayout layout;
30372e1d0745SJose E. Roman     PetscInt    M, m;
30382e1d0745SJose E. Roman     PetscInt   *offsetsA;
30392e1d0745SJose E. Roman     PetscBool   includesConstraintsA;
30402e1d0745SJose E. Roman 
30412e1d0745SJose E. Roman     PetscCall(PetscSFDistributeSection(sfAB, sectionA, &offsetsA, sectionB));
30422e1d0745SJose E. Roman     PetscCall(PetscSectionGetIncludesConstraints(sectionA, &includesConstraintsA));
30432e1d0745SJose E. Roman     if (includesConstraintsA) PetscCall(PetscSectionGetStorageSize(sectionA, &m));
30442e1d0745SJose E. Roman     else PetscCall(PetscSectionGetConstrainedStorageSize(sectionA, &m));
30452e1d0745SJose E. Roman     PetscCallMPI(MPIU_Allreduce(&m, &M, 1, MPIU_INT, MPI_SUM, comm));
30462e1d0745SJose E. Roman     PetscCall(PetscLayoutCreate(comm, &layout));
30472e1d0745SJose E. Roman     PetscCall(PetscLayoutSetSize(layout, M));
30482e1d0745SJose E. Roman     PetscCall(PetscLayoutSetUp(layout));
30492e1d0745SJose E. Roman     if (lsf) {
30502e1d0745SJose E. Roman       PetscSF lsfABdata;
30512e1d0745SJose E. Roman 
30522e1d0745SJose E. Roman       PetscCall(DMPlexSectionLoad_HDF5_Internal_CreateDataSF(sectionA, layout, offsetsA, sectionB, &lsfABdata));
30532e1d0745SJose E. Roman       *lsf = lsfABdata;
30542e1d0745SJose E. Roman     }
30552e1d0745SJose E. Roman     if (gsf) {
30562e1d0745SJose E. Roman       PetscSection gsectionB, gsectionB1;
30572e1d0745SJose E. Roman       PetscBool    includesConstraintsB;
30582e1d0745SJose E. Roman       PetscSF      gsfABdata, pointsf;
30592e1d0745SJose E. Roman 
30602e1d0745SJose E. Roman       PetscCall(DMGetGlobalSection(sectiondm, &gsectionB1));
30612e1d0745SJose E. Roman       PetscCall(PetscSectionGetIncludesConstraints(gsectionB1, &includesConstraintsB));
30622e1d0745SJose E. Roman       PetscCall(DMGetPointSF(sectiondm, &pointsf));
30632e1d0745SJose E. Roman       PetscCall(PetscSectionCreateGlobalSection(sectionB, pointsf, PETSC_TRUE, includesConstraintsB, PETSC_TRUE, &gsectionB));
30642e1d0745SJose E. Roman       PetscCall(DMPlexSectionLoad_HDF5_Internal_CreateDataSF(sectionA, layout, offsetsA, gsectionB, &gsfABdata));
30652e1d0745SJose E. Roman       PetscCall(PetscSectionDestroy(&gsectionB));
30662e1d0745SJose E. Roman       *gsf = gsfABdata;
30672e1d0745SJose E. Roman     }
30682e1d0745SJose E. Roman     PetscCall(PetscLayoutDestroy(&layout));
30692e1d0745SJose E. Roman     PetscCall(PetscFree(offsetsA));
30702e1d0745SJose E. Roman   } else {
30712e1d0745SJose E. Roman     PetscCall(PetscSFDistributeSection(sfAB, sectionA, NULL, sectionB));
30722e1d0745SJose E. Roman   }
30732e1d0745SJose E. Roman   PetscCall(PetscSFDestroy(&sfAB));
30742e1d0745SJose E. Roman   PetscCall(PetscSectionDestroy(&sectionA));
30752e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
30762e1d0745SJose E. Roman }
30772e1d0745SJose E. Roman 
DMPlexVecLoad_HDF5_Internal(DM dm,PetscViewer viewer,DM sectiondm,PetscSF sf,Vec vec)30782e1d0745SJose E. Roman PetscErrorCode DMPlexVecLoad_HDF5_Internal(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec)
30792e1d0745SJose E. Roman {
30802e1d0745SJose E. Roman   MPI_Comm           comm;
30812e1d0745SJose E. Roman   const char        *topologydm_name;
30822e1d0745SJose E. Roman   const char        *sectiondm_name;
30832e1d0745SJose E. Roman   const char        *vec_name;
30842e1d0745SJose E. Roman   Vec                vecA;
30852e1d0745SJose E. Roman   PetscInt           mA, m, bs;
30862e1d0745SJose E. Roman   const PetscInt    *ilocal;
30872e1d0745SJose E. Roman   const PetscScalar *src;
30882e1d0745SJose E. Roman   PetscScalar       *dest;
30892e1d0745SJose E. Roman 
30902e1d0745SJose E. Roman   PetscFunctionBegin;
30912e1d0745SJose E. Roman   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
30922e1d0745SJose E. Roman   PetscCall(DMPlexGetHDF5Name_Private(dm, &topologydm_name));
30932e1d0745SJose E. Roman   PetscCall(PetscObjectGetName((PetscObject)sectiondm, &sectiondm_name));
30942e1d0745SJose E. Roman   PetscCall(PetscObjectGetName((PetscObject)vec, &vec_name));
30952e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "topologies"));
30962e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, topologydm_name));
30972e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "dms"));
30982e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, sectiondm_name));
30992e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, "vecs"));
31002e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PushGroup(viewer, vec_name));
31012e1d0745SJose E. Roman   PetscCall(VecCreate(comm, &vecA));
31022e1d0745SJose E. Roman   PetscCall(PetscObjectSetName((PetscObject)vecA, vec_name));
31032e1d0745SJose E. Roman   PetscCall(PetscSFGetGraph(sf, &mA, &m, &ilocal, NULL));
31042e1d0745SJose E. Roman   /* Check consistency */
31052e1d0745SJose E. Roman   {
31062e1d0745SJose E. Roman     PetscSF  pointsf, pointsf1;
31072e1d0745SJose E. Roman     PetscInt m1, i, j;
31082e1d0745SJose E. Roman 
31092e1d0745SJose E. Roman     PetscCall(DMGetPointSF(dm, &pointsf));
31102e1d0745SJose E. Roman     PetscCall(DMGetPointSF(sectiondm, &pointsf1));
31112e1d0745SJose E. Roman     PetscCheck(pointsf1 == pointsf, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatching point SFs for dm and sectiondm");
31122e1d0745SJose E. Roman #if defined(PETSC_USE_DEBUG)
31132e1d0745SJose E. Roman     {
31142e1d0745SJose E. Roman       PetscInt MA, MA1;
31152e1d0745SJose E. Roman 
31162e1d0745SJose E. Roman       PetscCallMPI(MPIU_Allreduce(&mA, &MA, 1, MPIU_INT, MPI_SUM, comm));
31172e1d0745SJose E. Roman       PetscCall(PetscViewerHDF5ReadSizes(viewer, vec_name, NULL, &MA1));
31182e1d0745SJose 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);
31192e1d0745SJose E. Roman     }
31202e1d0745SJose E. Roman #endif
31212e1d0745SJose E. Roman     PetscCall(VecGetLocalSize(vec, &m1));
31222e1d0745SJose E. Roman     PetscCheck(m1 >= m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Target vector size (%" PetscInt_FMT ") < SF leaf size (%" PetscInt_FMT ")", m1, m);
31232e1d0745SJose E. Roman     for (i = 0; i < m; ++i) {
31242e1d0745SJose E. Roman       j = ilocal ? ilocal[i] : i;
31252e1d0745SJose 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);
31262e1d0745SJose E. Roman     }
31272e1d0745SJose E. Roman   }
31282e1d0745SJose E. Roman   PetscCall(VecSetSizes(vecA, mA, PETSC_DECIDE));
31292e1d0745SJose E. Roman   PetscCall(VecLoad(vecA, viewer));
31302e1d0745SJose E. Roman   PetscCall(VecGetArrayRead(vecA, &src));
31312e1d0745SJose E. Roman   PetscCall(VecGetArray(vec, &dest));
31322e1d0745SJose E. Roman   PetscCall(PetscSFBcastBegin(sf, MPIU_SCALAR, src, dest, MPI_REPLACE));
31332e1d0745SJose E. Roman   PetscCall(PetscSFBcastEnd(sf, MPIU_SCALAR, src, dest, MPI_REPLACE));
31342e1d0745SJose E. Roman   PetscCall(VecRestoreArray(vec, &dest));
31352e1d0745SJose E. Roman   PetscCall(VecRestoreArrayRead(vecA, &src));
31362e1d0745SJose E. Roman   PetscCall(VecDestroy(&vecA));
31372e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5ReadAttribute(viewer, NULL, "blockSize", PETSC_INT, NULL, (void *)&bs));
31382e1d0745SJose E. Roman   PetscCall(VecSetBlockSize(vec, bs));
31392e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
31402e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
31412e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
31422e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
31432e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
31442e1d0745SJose E. Roman   PetscCall(PetscViewerHDF5PopGroup(viewer));
31452e1d0745SJose E. Roman   PetscFunctionReturn(PETSC_SUCCESS);
31462e1d0745SJose E. Roman }
3147