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, §ion));
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, §ionGlobal));
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, §iondm_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, §iondm_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, §iondm_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, §ion));
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, §iondm_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, §ionA));
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, §ionB));
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(§ionA));
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, §iondm_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