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