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