1*2e1d0745SJose E. Roman #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2*2e1d0745SJose E. Roman #include <petsc/private/isimpl.h> 3*2e1d0745SJose E. Roman #include <petsc/private/vecimpl.h> 4*2e1d0745SJose E. Roman #include <petsc/private/viewerhdf5impl.h> 5*2e1d0745SJose E. Roman #include <petsclayouthdf5.h> 6*2e1d0745SJose E. Roman 7*2e1d0745SJose E. Roman /* Logging support */ 8*2e1d0745SJose E. Roman PetscLogEvent DMPLEX_DistributionView, DMPLEX_DistributionLoad; 9*2e1d0745SJose E. Roman 10*2e1d0745SJose E. Roman static PetscErrorCode PetscViewerParseVersion_Private(PetscViewer, const char[], DMPlexStorageVersion *); 11*2e1d0745SJose E. Roman static PetscErrorCode PetscViewerCheckVersion_Private(PetscViewer, DMPlexStorageVersion); 12*2e1d0745SJose E. Roman static PetscErrorCode PetscViewerAttachVersion_Private(PetscViewer, const char[], DMPlexStorageVersion); 13*2e1d0745SJose E. Roman static PetscErrorCode PetscViewerGetAttachedVersion_Private(PetscViewer, const char[], DMPlexStorageVersion *); 14*2e1d0745SJose E. Roman 15*2e1d0745SJose E. Roman PETSC_EXTERN PetscErrorCode VecView_MPI(Vec, PetscViewer); 16*2e1d0745SJose E. Roman 17*2e1d0745SJose E. Roman static PetscErrorCode PetscViewerPrintVersion_Private(PetscViewer viewer, DMPlexStorageVersion version, char str[], size_t len) 18*2e1d0745SJose E. Roman { 19*2e1d0745SJose E. Roman PetscFunctionBegin; 20*2e1d0745SJose E. Roman PetscCall(PetscViewerCheckVersion_Private(viewer, version)); 21*2e1d0745SJose E. Roman PetscCall(PetscSNPrintf(str, len, "%d.%d.%d", version->major, version->minor, version->subminor)); 22*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 23*2e1d0745SJose E. Roman } 24*2e1d0745SJose E. Roman 25*2e1d0745SJose E. Roman static PetscErrorCode PetscViewerParseVersion_Private(PetscViewer viewer, const char str[], DMPlexStorageVersion *version) 26*2e1d0745SJose E. Roman { 27*2e1d0745SJose E. Roman PetscToken t; 28*2e1d0745SJose E. Roman char *ts; 29*2e1d0745SJose E. Roman PetscInt i; 30*2e1d0745SJose E. Roman PetscInt ti[3]; 31*2e1d0745SJose E. Roman DMPlexStorageVersion v; 32*2e1d0745SJose E. Roman 33*2e1d0745SJose E. Roman PetscFunctionBegin; 34*2e1d0745SJose E. Roman PetscCall(PetscTokenCreate(str, '.', &t)); 35*2e1d0745SJose E. Roman for (i = 0; i < 3; i++) { 36*2e1d0745SJose E. Roman PetscCall(PetscTokenFind(t, &ts)); 37*2e1d0745SJose E. Roman PetscCheck(ts, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONG, "Malformed version string %s", str); 38*2e1d0745SJose E. Roman PetscCall(PetscOptionsStringToInt(ts, &ti[i])); 39*2e1d0745SJose E. Roman } 40*2e1d0745SJose E. Roman PetscCall(PetscTokenFind(t, &ts)); 41*2e1d0745SJose E. Roman PetscCheck(!ts, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONG, "Malformed version string %s", str); 42*2e1d0745SJose E. Roman PetscCall(PetscTokenDestroy(&t)); 43*2e1d0745SJose E. Roman PetscCall(PetscNew(&v)); 44*2e1d0745SJose E. Roman v->major = (int)ti[0]; 45*2e1d0745SJose E. Roman v->minor = (int)ti[1]; 46*2e1d0745SJose E. Roman v->subminor = (int)ti[2]; 47*2e1d0745SJose E. Roman PetscCall(PetscViewerCheckVersion_Private(viewer, v)); 48*2e1d0745SJose E. Roman *version = v; 49*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 50*2e1d0745SJose E. Roman } 51*2e1d0745SJose E. Roman 52*2e1d0745SJose E. Roman static PetscErrorCode PetscViewerAttachVersion_Private(PetscViewer viewer, const char key[], DMPlexStorageVersion v) 53*2e1d0745SJose E. Roman { 54*2e1d0745SJose E. Roman PetscFunctionBegin; 55*2e1d0745SJose E. Roman PetscCall(PetscObjectContainerCompose((PetscObject)viewer, key, v, PetscContainerUserDestroyDefault)); 56*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 57*2e1d0745SJose E. Roman } 58*2e1d0745SJose E. Roman 59*2e1d0745SJose E. Roman static PetscErrorCode PetscViewerGetAttachedVersion_Private(PetscViewer viewer, const char key[], DMPlexStorageVersion *v) 60*2e1d0745SJose E. Roman { 61*2e1d0745SJose E. Roman PetscContainer cont; 62*2e1d0745SJose E. Roman 63*2e1d0745SJose E. Roman PetscFunctionBegin; 64*2e1d0745SJose E. Roman PetscCall(PetscObjectQuery((PetscObject)viewer, key, (PetscObject *)&cont)); 65*2e1d0745SJose E. Roman *v = NULL; 66*2e1d0745SJose E. Roman if (cont) PetscCall(PetscContainerGetPointer(cont, (void **)v)); 67*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 68*2e1d0745SJose E. Roman } 69*2e1d0745SJose E. Roman 70*2e1d0745SJose E. Roman /* 71*2e1d0745SJose E. Roman Version log: 72*2e1d0745SJose E. Roman 1.0.0 legacy version (default if no "dmplex_storage_version" attribute found in file) 73*2e1d0745SJose E. Roman 1.1.0 legacy version, but output VIZ by default 74*2e1d0745SJose E. Roman 2.0.0 introduce versioning and multiple topologies 75*2e1d0745SJose E. Roman 2.1.0 introduce distributions 76*2e1d0745SJose E. Roman 3.0.0 new checkpointing format in Firedrake paper 77*2e1d0745SJose E. Roman 3.1.0 new format with IS compression 78*2e1d0745SJose E. Roman */ 79*2e1d0745SJose E. Roman static PetscErrorCode PetscViewerCheckVersion_Private(PetscViewer viewer, DMPlexStorageVersion version) 80*2e1d0745SJose E. Roman { 81*2e1d0745SJose E. Roman PetscBool valid = PETSC_FALSE; 82*2e1d0745SJose E. Roman 83*2e1d0745SJose E. Roman PetscFunctionBegin; 84*2e1d0745SJose E. Roman switch (version->major) { 85*2e1d0745SJose E. Roman case 1: 86*2e1d0745SJose E. Roman switch (version->minor) { 87*2e1d0745SJose E. Roman case 0: 88*2e1d0745SJose E. Roman switch (version->subminor) { 89*2e1d0745SJose E. Roman case 0: 90*2e1d0745SJose E. Roman valid = PETSC_TRUE; 91*2e1d0745SJose E. Roman break; 92*2e1d0745SJose E. Roman } 93*2e1d0745SJose E. Roman break; 94*2e1d0745SJose E. Roman case 1: 95*2e1d0745SJose E. Roman switch (version->subminor) { 96*2e1d0745SJose E. Roman case 0: 97*2e1d0745SJose E. Roman valid = PETSC_TRUE; 98*2e1d0745SJose E. Roman break; 99*2e1d0745SJose E. Roman } 100*2e1d0745SJose E. Roman break; 101*2e1d0745SJose E. Roman } 102*2e1d0745SJose E. Roman break; 103*2e1d0745SJose E. Roman case 2: 104*2e1d0745SJose E. Roman switch (version->minor) { 105*2e1d0745SJose E. Roman case 0: 106*2e1d0745SJose E. Roman switch (version->subminor) { 107*2e1d0745SJose E. Roman case 0: 108*2e1d0745SJose E. Roman valid = PETSC_TRUE; 109*2e1d0745SJose E. Roman break; 110*2e1d0745SJose E. Roman } 111*2e1d0745SJose E. Roman break; 112*2e1d0745SJose E. Roman case 1: 113*2e1d0745SJose E. Roman switch (version->subminor) { 114*2e1d0745SJose E. Roman case 0: 115*2e1d0745SJose E. Roman valid = PETSC_TRUE; 116*2e1d0745SJose E. Roman break; 117*2e1d0745SJose E. Roman } 118*2e1d0745SJose E. Roman break; 119*2e1d0745SJose E. Roman } 120*2e1d0745SJose E. Roman break; 121*2e1d0745SJose E. Roman case 3: 122*2e1d0745SJose E. Roman switch (version->minor) { 123*2e1d0745SJose E. Roman case 0: 124*2e1d0745SJose E. Roman switch (version->subminor) { 125*2e1d0745SJose E. Roman case 0: 126*2e1d0745SJose E. Roman valid = PETSC_TRUE; 127*2e1d0745SJose E. Roman break; 128*2e1d0745SJose E. Roman } 129*2e1d0745SJose E. Roman break; 130*2e1d0745SJose E. Roman case 1: 131*2e1d0745SJose E. Roman switch (version->subminor) { 132*2e1d0745SJose E. Roman case 0: 133*2e1d0745SJose E. Roman valid = PETSC_TRUE; 134*2e1d0745SJose E. Roman break; 135*2e1d0745SJose E. Roman } 136*2e1d0745SJose E. Roman break; 137*2e1d0745SJose E. Roman } 138*2e1d0745SJose E. Roman break; 139*2e1d0745SJose E. Roman } 140*2e1d0745SJose E. Roman PetscCheck(valid, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "DMPlexStorageVersion %d.%d.%d not supported", version->major, version->minor, version->subminor); 141*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 142*2e1d0745SJose E. Roman } 143*2e1d0745SJose E. Roman 144*2e1d0745SJose E. Roman static inline PetscBool DMPlexStorageVersionEQ(DMPlexStorageVersion version, int major, int minor, int subminor) 145*2e1d0745SJose E. Roman { 146*2e1d0745SJose E. Roman return (PetscBool)(version->major == major && version->minor == minor && version->subminor == subminor); 147*2e1d0745SJose E. Roman } 148*2e1d0745SJose E. Roman 149*2e1d0745SJose E. Roman static inline PetscBool DMPlexStorageVersionGE(DMPlexStorageVersion version, int major, int minor, int subminor) 150*2e1d0745SJose E. Roman { 151*2e1d0745SJose E. Roman return (PetscBool)((version->major == major && version->minor == minor && version->subminor >= subminor) || (version->major == major && version->minor > minor) || (version->major > major)); 152*2e1d0745SJose E. Roman } 153*2e1d0745SJose E. Roman 154*2e1d0745SJose E. Roman /*@C 155*2e1d0745SJose E. Roman PetscViewerHDF5SetDMPlexStorageVersionWriting - Set the storage version for writing 156*2e1d0745SJose E. Roman 157*2e1d0745SJose E. Roman Logically collective 158*2e1d0745SJose E. Roman 159*2e1d0745SJose E. Roman Input Parameters: 160*2e1d0745SJose E. Roman + viewer - The `PetscViewer` 161*2e1d0745SJose E. Roman - version - The storage format version 162*2e1d0745SJose E. Roman 163*2e1d0745SJose E. Roman Level: advanced 164*2e1d0745SJose E. Roman 165*2e1d0745SJose E. Roman Note: 166*2e1d0745SJose E. Roman The version has major, minor, and subminor integers. Parallel operations are only available for version 3.0.0. 167*2e1d0745SJose E. Roman 168*2e1d0745SJose E. Roman .seealso: [](ch_dmbase), `DM`, `PetscViewerHDF5GetDMPlexStorageVersionWriting()`, `PetscViewerHDF5GetDMPlexStorageVersionReading()`, `PetscViewerHDF5SetDMPlexStorageVersionReading()` 169*2e1d0745SJose E. Roman @*/ 170*2e1d0745SJose E. Roman PetscErrorCode PetscViewerHDF5SetDMPlexStorageVersionWriting(PetscViewer viewer, DMPlexStorageVersion version) 171*2e1d0745SJose E. Roman { 172*2e1d0745SJose E. Roman const char ATTR_NAME[] = "dmplex_storage_version"; 173*2e1d0745SJose E. Roman DMPlexStorageVersion viewerVersion; 174*2e1d0745SJose E. Roman PetscBool fileHasVersion; 175*2e1d0745SJose E. Roman char fileVersion[16], versionStr[16], viewerVersionStr[16]; 176*2e1d0745SJose E. Roman 177*2e1d0745SJose E. Roman PetscFunctionBegin; 178*2e1d0745SJose E. Roman PetscValidHeaderSpecificType(viewer, PETSC_VIEWER_CLASSID, 1, PETSCVIEWERHDF5); 179*2e1d0745SJose E. Roman PetscAssertPointer(version, 2); 180*2e1d0745SJose E. Roman PetscCall(PetscViewerPrintVersion_Private(viewer, version, versionStr, 16)); 181*2e1d0745SJose E. Roman PetscCall(PetscViewerGetAttachedVersion_Private(viewer, DMPLEX_STORAGE_VERSION_WRITING_KEY, &viewerVersion)); 182*2e1d0745SJose E. Roman if (viewerVersion) { 183*2e1d0745SJose E. Roman PetscBool flg; 184*2e1d0745SJose E. Roman 185*2e1d0745SJose E. Roman PetscCall(PetscViewerPrintVersion_Private(viewer, viewerVersion, viewerVersionStr, 16)); 186*2e1d0745SJose E. Roman PetscCall(PetscStrcmp(versionStr, viewerVersionStr, &flg)); 187*2e1d0745SJose 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); 188*2e1d0745SJose E. Roman } 189*2e1d0745SJose E. Roman 190*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5HasAttribute(viewer, NULL, ATTR_NAME, &fileHasVersion)); 191*2e1d0745SJose E. Roman if (fileHasVersion) { 192*2e1d0745SJose E. Roman PetscBool flg; 193*2e1d0745SJose E. Roman char *tmp; 194*2e1d0745SJose E. Roman 195*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5ReadAttribute(viewer, "/", ATTR_NAME, PETSC_STRING, NULL, &tmp)); 196*2e1d0745SJose E. Roman PetscCall(PetscStrncpy(fileVersion, tmp, sizeof(fileVersion))); 197*2e1d0745SJose E. Roman PetscCall(PetscFree(tmp)); 198*2e1d0745SJose E. Roman PetscCall(PetscStrcmp(fileVersion, versionStr, &flg)); 199*2e1d0745SJose 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); 200*2e1d0745SJose E. Roman } else { 201*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5WriteAttribute(viewer, "/", ATTR_NAME, PETSC_STRING, versionStr)); 202*2e1d0745SJose E. Roman } 203*2e1d0745SJose E. Roman PetscCall(PetscNew(&viewerVersion)); 204*2e1d0745SJose E. Roman viewerVersion->major = version->major; 205*2e1d0745SJose E. Roman viewerVersion->minor = version->minor; 206*2e1d0745SJose E. Roman viewerVersion->subminor = version->subminor; 207*2e1d0745SJose E. Roman PetscCall(PetscViewerAttachVersion_Private(viewer, DMPLEX_STORAGE_VERSION_WRITING_KEY, viewerVersion)); 208*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 209*2e1d0745SJose E. Roman } 210*2e1d0745SJose E. Roman 211*2e1d0745SJose E. Roman /*@C 212*2e1d0745SJose E. Roman PetscViewerHDF5GetDMPlexStorageVersionWriting - Get the storage version for writing 213*2e1d0745SJose E. Roman 214*2e1d0745SJose E. Roman Logically collective 215*2e1d0745SJose E. Roman 216*2e1d0745SJose E. Roman Input Parameter: 217*2e1d0745SJose E. Roman . viewer - The `PetscViewer` 218*2e1d0745SJose E. Roman 219*2e1d0745SJose E. Roman Output Parameter: 220*2e1d0745SJose E. Roman . version - The storage format version 221*2e1d0745SJose E. Roman 222*2e1d0745SJose E. Roman Options Database Keys: 223*2e1d0745SJose E. Roman . -dm_plex_view_hdf5_storage_version <num> - Overrides the storage format version 224*2e1d0745SJose E. Roman 225*2e1d0745SJose E. Roman Level: advanced 226*2e1d0745SJose E. Roman 227*2e1d0745SJose E. Roman Note: 228*2e1d0745SJose E. Roman The version has major, minor, and subminor integers. Parallel operations are only available for version 3.0.0. 229*2e1d0745SJose E. Roman 230*2e1d0745SJose E. Roman .seealso: [](ch_dmbase), `DM`, `PetscViewerHDF5SetDMPlexStorageVersionWriting()`, `PetscViewerHDF5GetDMPlexStorageVersionReading()`, `PetscViewerHDF5SetDMPlexStorageVersionReading()` 231*2e1d0745SJose E. Roman @*/ 232*2e1d0745SJose E. Roman PetscErrorCode PetscViewerHDF5GetDMPlexStorageVersionWriting(PetscViewer viewer, DMPlexStorageVersion *version) 233*2e1d0745SJose E. Roman { 234*2e1d0745SJose E. Roman const char ATTR_NAME[] = "dmplex_storage_version"; 235*2e1d0745SJose E. Roman PetscBool fileHasVersion; 236*2e1d0745SJose E. Roman char optVersion[16], fileVersion[16]; 237*2e1d0745SJose E. Roman 238*2e1d0745SJose E. Roman PetscFunctionBegin; 239*2e1d0745SJose E. Roman PetscValidHeaderSpecificType(viewer, PETSC_VIEWER_CLASSID, 1, PETSCVIEWERHDF5); 240*2e1d0745SJose E. Roman PetscAssertPointer(version, 2); 241*2e1d0745SJose E. Roman PetscCall(PetscViewerGetAttachedVersion_Private(viewer, DMPLEX_STORAGE_VERSION_WRITING_KEY, version)); 242*2e1d0745SJose E. Roman if (*version) PetscFunctionReturn(PETSC_SUCCESS); 243*2e1d0745SJose E. Roman 244*2e1d0745SJose E. Roman PetscCall(PetscStrncpy(fileVersion, DMPLEX_STORAGE_VERSION_STABLE, sizeof(fileVersion))); 245*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5HasAttribute(viewer, NULL, ATTR_NAME, &fileHasVersion)); 246*2e1d0745SJose E. Roman if (fileHasVersion) { 247*2e1d0745SJose E. Roman char *tmp; 248*2e1d0745SJose E. Roman 249*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5ReadAttribute(viewer, "/", ATTR_NAME, PETSC_STRING, NULL, &tmp)); 250*2e1d0745SJose E. Roman PetscCall(PetscStrncpy(fileVersion, tmp, sizeof(fileVersion))); 251*2e1d0745SJose E. Roman PetscCall(PetscFree(tmp)); 252*2e1d0745SJose E. Roman } 253*2e1d0745SJose E. Roman PetscCall(PetscStrncpy(optVersion, fileVersion, sizeof(optVersion))); 254*2e1d0745SJose E. Roman PetscObjectOptionsBegin((PetscObject)viewer); 255*2e1d0745SJose E. Roman PetscCall(PetscOptionsString("-dm_plex_view_hdf5_storage_version", "DMPlex HDF5 viewer storage version", NULL, optVersion, optVersion, sizeof(optVersion), NULL)); 256*2e1d0745SJose E. Roman PetscOptionsEnd(); 257*2e1d0745SJose E. Roman if (!fileHasVersion) { 258*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5WriteAttribute(viewer, "/", ATTR_NAME, PETSC_STRING, optVersion)); 259*2e1d0745SJose E. Roman } else { 260*2e1d0745SJose E. Roman PetscBool flg; 261*2e1d0745SJose E. Roman 262*2e1d0745SJose E. Roman PetscCall(PetscStrcmp(fileVersion, optVersion, &flg)); 263*2e1d0745SJose 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); 264*2e1d0745SJose E. Roman } 265*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5WriteAttribute(viewer, NULL, "petsc_version_git", PETSC_STRING, PETSC_VERSION_GIT)); 266*2e1d0745SJose E. Roman PetscCall(PetscViewerParseVersion_Private(viewer, optVersion, version)); 267*2e1d0745SJose E. Roman PetscCall(PetscViewerAttachVersion_Private(viewer, DMPLEX_STORAGE_VERSION_WRITING_KEY, *version)); 268*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 269*2e1d0745SJose E. Roman } 270*2e1d0745SJose E. Roman 271*2e1d0745SJose E. Roman /*@C 272*2e1d0745SJose E. Roman PetscViewerHDF5SetDMPlexStorageVersionReading - Set the storage version for reading 273*2e1d0745SJose E. Roman 274*2e1d0745SJose E. Roman Logically collective 275*2e1d0745SJose E. Roman 276*2e1d0745SJose E. Roman Input Parameters: 277*2e1d0745SJose E. Roman + viewer - The `PetscViewer` 278*2e1d0745SJose E. Roman - version - The storage format version 279*2e1d0745SJose E. Roman 280*2e1d0745SJose E. Roman Level: advanced 281*2e1d0745SJose E. Roman 282*2e1d0745SJose E. Roman Note: 283*2e1d0745SJose E. Roman The version has major, minor, and subminor integers. Parallel operations are only available for version 3.0.0. 284*2e1d0745SJose E. Roman 285*2e1d0745SJose E. Roman .seealso: [](ch_dmbase), `DM`, `PetscViewerHDF5GetDMPlexStorageVersionReading()`, `PetscViewerHDF5GetDMPlexStorageVersionWriting()`, `PetscViewerHDF5SetDMPlexStorageVersionWriting()` 286*2e1d0745SJose E. Roman @*/ 287*2e1d0745SJose E. Roman PetscErrorCode PetscViewerHDF5SetDMPlexStorageVersionReading(PetscViewer viewer, DMPlexStorageVersion version) 288*2e1d0745SJose E. Roman { 289*2e1d0745SJose E. Roman const char ATTR_NAME[] = "dmplex_storage_version"; 290*2e1d0745SJose E. Roman DMPlexStorageVersion viewerVersion; 291*2e1d0745SJose E. Roman PetscBool fileHasVersion; 292*2e1d0745SJose E. Roman char versionStr[16], viewerVersionStr[16]; 293*2e1d0745SJose E. Roman 294*2e1d0745SJose E. Roman PetscFunctionBegin; 295*2e1d0745SJose E. Roman PetscValidHeaderSpecificType(viewer, PETSC_VIEWER_CLASSID, 1, PETSCVIEWERHDF5); 296*2e1d0745SJose E. Roman PetscAssertPointer(version, 2); 297*2e1d0745SJose E. Roman PetscCall(PetscViewerPrintVersion_Private(viewer, version, versionStr, 16)); 298*2e1d0745SJose E. Roman PetscCall(PetscViewerGetAttachedVersion_Private(viewer, DMPLEX_STORAGE_VERSION_READING_KEY, &viewerVersion)); 299*2e1d0745SJose E. Roman if (viewerVersion) { 300*2e1d0745SJose E. Roman PetscBool flg; 301*2e1d0745SJose E. Roman 302*2e1d0745SJose E. Roman PetscCall(PetscViewerPrintVersion_Private(viewer, viewerVersion, viewerVersionStr, 16)); 303*2e1d0745SJose E. Roman PetscCall(PetscStrcmp(versionStr, viewerVersionStr, &flg)); 304*2e1d0745SJose 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); 305*2e1d0745SJose E. Roman } 306*2e1d0745SJose E. Roman 307*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5HasAttribute(viewer, NULL, ATTR_NAME, &fileHasVersion)); 308*2e1d0745SJose E. Roman if (fileHasVersion) { 309*2e1d0745SJose E. Roman char *fileVersion; 310*2e1d0745SJose E. Roman PetscBool flg; 311*2e1d0745SJose E. Roman 312*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5ReadAttribute(viewer, "/", ATTR_NAME, PETSC_STRING, NULL, &fileVersion)); 313*2e1d0745SJose E. Roman PetscCall(PetscStrcmp(fileVersion, versionStr, &flg)); 314*2e1d0745SJose 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); 315*2e1d0745SJose E. Roman PetscCall(PetscFree(fileVersion)); 316*2e1d0745SJose E. Roman } 317*2e1d0745SJose E. Roman PetscCall(PetscNew(&viewerVersion)); 318*2e1d0745SJose E. Roman viewerVersion->major = version->major; 319*2e1d0745SJose E. Roman viewerVersion->minor = version->minor; 320*2e1d0745SJose E. Roman viewerVersion->subminor = version->subminor; 321*2e1d0745SJose E. Roman PetscCall(PetscViewerAttachVersion_Private(viewer, DMPLEX_STORAGE_VERSION_READING_KEY, viewerVersion)); 322*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 323*2e1d0745SJose E. Roman } 324*2e1d0745SJose E. Roman 325*2e1d0745SJose E. Roman /*@C 326*2e1d0745SJose E. Roman PetscViewerHDF5GetDMPlexStorageVersionReading - Get the storage version for reading 327*2e1d0745SJose E. Roman 328*2e1d0745SJose E. Roman Logically collective 329*2e1d0745SJose E. Roman 330*2e1d0745SJose E. Roman Input Parameter: 331*2e1d0745SJose E. Roman . viewer - The `PetscViewer` 332*2e1d0745SJose E. Roman 333*2e1d0745SJose E. Roman Output Parameter: 334*2e1d0745SJose E. Roman . version - The storage format version 335*2e1d0745SJose E. Roman 336*2e1d0745SJose E. Roman Options Database Keys: 337*2e1d0745SJose E. Roman . -dm_plex_view_hdf5_storage_version <num> - Overrides the storage format version 338*2e1d0745SJose E. Roman 339*2e1d0745SJose E. Roman Level: advanced 340*2e1d0745SJose E. Roman 341*2e1d0745SJose E. Roman Note: 342*2e1d0745SJose E. Roman The version has major, minor, and subminor integers. Parallel operations are only available for version 3.0.0. 343*2e1d0745SJose E. Roman 344*2e1d0745SJose E. Roman .seealso: [](ch_dmbase), `DM`, `PetscViewerHDF5SetDMPlexStorageVersionReading()`, `PetscViewerHDF5GetDMPlexStorageVersionWriting()`, `PetscViewerHDF5SetDMPlexStorageVersionWriting()` 345*2e1d0745SJose E. Roman @*/ 346*2e1d0745SJose E. Roman PetscErrorCode PetscViewerHDF5GetDMPlexStorageVersionReading(PetscViewer viewer, DMPlexStorageVersion *version) 347*2e1d0745SJose E. Roman { 348*2e1d0745SJose E. Roman const char ATTR_NAME[] = "dmplex_storage_version"; 349*2e1d0745SJose E. Roman char *defaultVersion; 350*2e1d0745SJose E. Roman char *versionString; 351*2e1d0745SJose E. Roman 352*2e1d0745SJose E. Roman PetscFunctionBegin; 353*2e1d0745SJose E. Roman PetscValidHeaderSpecificType(viewer, PETSC_VIEWER_CLASSID, 1, PETSCVIEWERHDF5); 354*2e1d0745SJose E. Roman PetscAssertPointer(version, 2); 355*2e1d0745SJose E. Roman PetscCall(PetscViewerGetAttachedVersion_Private(viewer, DMPLEX_STORAGE_VERSION_READING_KEY, version)); 356*2e1d0745SJose E. Roman if (*version) PetscFunctionReturn(PETSC_SUCCESS); 357*2e1d0745SJose E. Roman 358*2e1d0745SJose E. Roman //TODO string HDF5 attribute handling is terrible and should be redesigned 359*2e1d0745SJose E. Roman PetscCall(PetscStrallocpy(DMPLEX_STORAGE_VERSION_FIRST, &defaultVersion)); 360*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5ReadAttribute(viewer, "/", ATTR_NAME, PETSC_STRING, &defaultVersion, &versionString)); 361*2e1d0745SJose E. Roman PetscCall(PetscViewerParseVersion_Private(viewer, versionString, version)); 362*2e1d0745SJose E. Roman PetscCall(PetscViewerAttachVersion_Private(viewer, DMPLEX_STORAGE_VERSION_READING_KEY, *version)); 363*2e1d0745SJose E. Roman PetscCall(PetscFree(versionString)); 364*2e1d0745SJose E. Roman PetscCall(PetscFree(defaultVersion)); 365*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 366*2e1d0745SJose E. Roman } 367*2e1d0745SJose E. Roman 368*2e1d0745SJose E. Roman static PetscErrorCode DMPlexGetHDF5Name_Private(DM dm, const char *name[]) 369*2e1d0745SJose E. Roman { 370*2e1d0745SJose E. Roman PetscFunctionBegin; 371*2e1d0745SJose E. Roman if (((PetscObject)dm)->name) { 372*2e1d0745SJose E. Roman PetscCall(PetscObjectGetName((PetscObject)dm, name)); 373*2e1d0745SJose E. Roman } else { 374*2e1d0745SJose E. Roman *name = "plex"; 375*2e1d0745SJose E. Roman } 376*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 377*2e1d0745SJose E. Roman } 378*2e1d0745SJose E. Roman 379*2e1d0745SJose E. Roman PetscErrorCode DMSequenceGetLength_HDF5_Internal(DM dm, const char seqname[], PetscInt *seqlen, PetscViewer viewer) 380*2e1d0745SJose E. Roman { 381*2e1d0745SJose E. Roman hid_t file, group, dset, dspace; 382*2e1d0745SJose E. Roman hsize_t rdim, *dims; 383*2e1d0745SJose E. Roman char *groupname; 384*2e1d0745SJose E. Roman PetscBool has; 385*2e1d0745SJose E. Roman 386*2e1d0745SJose E. Roman PetscFunctionBegin; 387*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5GetGroup(viewer, NULL, &groupname)); 388*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5HasDataset(viewer, seqname, &has)); 389*2e1d0745SJose E. Roman PetscCheck(has, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Object (dataset) \"%s\" not stored in group %s", seqname, groupname); 390*2e1d0745SJose E. Roman 391*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5OpenGroup(viewer, NULL, &file, &group)); 392*2e1d0745SJose E. Roman PetscCallHDF5Return(dset, H5Dopen2, (group, seqname, H5P_DEFAULT)); 393*2e1d0745SJose E. Roman PetscCallHDF5Return(dspace, H5Dget_space, (dset)); 394*2e1d0745SJose E. Roman PetscCallHDF5ReturnNoCheck(rdim, H5Sget_simple_extent_dims, (dspace, NULL, NULL)); 395*2e1d0745SJose E. Roman PetscCall(PetscMalloc1(rdim, &dims)); 396*2e1d0745SJose E. Roman PetscCallHDF5ReturnNoCheck(rdim, H5Sget_simple_extent_dims, (dspace, dims, NULL)); 397*2e1d0745SJose E. Roman *seqlen = (PetscInt)dims[0]; 398*2e1d0745SJose E. Roman PetscCall(PetscFree(dims)); 399*2e1d0745SJose E. Roman PetscCallHDF5(H5Dclose, (dset)); 400*2e1d0745SJose E. Roman PetscCallHDF5(H5Gclose, (group)); 401*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 402*2e1d0745SJose E. Roman } 403*2e1d0745SJose E. Roman 404*2e1d0745SJose E. Roman static PetscErrorCode DMSequenceView_HDF5(DM dm, const char seqname[], PetscInt seqnum, PetscScalar value, PetscViewer viewer) 405*2e1d0745SJose E. Roman { 406*2e1d0745SJose E. Roman Vec stamp; 407*2e1d0745SJose E. Roman PetscMPIInt rank; 408*2e1d0745SJose E. Roman 409*2e1d0745SJose E. Roman PetscFunctionBegin; 410*2e1d0745SJose E. Roman if (seqnum < 0) PetscFunctionReturn(PETSC_SUCCESS); 411*2e1d0745SJose E. Roman PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 412*2e1d0745SJose E. Roman PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)viewer), rank ? 0 : 1, 1, &stamp)); 413*2e1d0745SJose E. Roman PetscCall(VecSetBlockSize(stamp, 1)); 414*2e1d0745SJose E. Roman PetscCall(PetscObjectSetName((PetscObject)stamp, seqname)); 415*2e1d0745SJose E. Roman if (rank == 0) { 416*2e1d0745SJose E. Roman PetscReal timeScale; 417*2e1d0745SJose E. Roman PetscBool istime; 418*2e1d0745SJose E. Roman 419*2e1d0745SJose E. Roman PetscCall(PetscStrncmp(seqname, "time", 5, &istime)); 420*2e1d0745SJose E. Roman if (istime) { 421*2e1d0745SJose E. Roman PetscCall(DMPlexGetScale(dm, PETSC_UNIT_TIME, &timeScale)); 422*2e1d0745SJose E. Roman value *= timeScale; 423*2e1d0745SJose E. Roman } 424*2e1d0745SJose E. Roman PetscCall(VecSetValue(stamp, 0, value, INSERT_VALUES)); 425*2e1d0745SJose E. Roman } 426*2e1d0745SJose E. Roman PetscCall(VecAssemblyBegin(stamp)); 427*2e1d0745SJose E. Roman PetscCall(VecAssemblyEnd(stamp)); 428*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, "/")); 429*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushTimestepping(viewer)); 430*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5SetTimestep(viewer, seqnum)); /* seqnum < 0 jumps out above */ 431*2e1d0745SJose E. Roman PetscCall(VecView(stamp, viewer)); 432*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopTimestepping(viewer)); 433*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 434*2e1d0745SJose E. Roman PetscCall(VecDestroy(&stamp)); 435*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 436*2e1d0745SJose E. Roman } 437*2e1d0745SJose E. Roman 438*2e1d0745SJose E. Roman PetscErrorCode DMSequenceLoad_HDF5_Internal(DM dm, const char seqname[], PetscInt seqnum, PetscScalar *value, PetscViewer viewer) 439*2e1d0745SJose E. Roman { 440*2e1d0745SJose E. Roman Vec stamp; 441*2e1d0745SJose E. Roman PetscMPIInt rank; 442*2e1d0745SJose E. Roman 443*2e1d0745SJose E. Roman PetscFunctionBegin; 444*2e1d0745SJose E. Roman if (seqnum < 0) PetscFunctionReturn(PETSC_SUCCESS); 445*2e1d0745SJose E. Roman PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 446*2e1d0745SJose E. Roman PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)viewer), rank ? 0 : 1, 1, &stamp)); 447*2e1d0745SJose E. Roman PetscCall(VecSetBlockSize(stamp, 1)); 448*2e1d0745SJose E. Roman PetscCall(PetscObjectSetName((PetscObject)stamp, seqname)); 449*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, "/")); 450*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushTimestepping(viewer)); 451*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5SetTimestep(viewer, seqnum)); /* seqnum < 0 jumps out above */ 452*2e1d0745SJose E. Roman PetscCall(VecLoad(stamp, viewer)); 453*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopTimestepping(viewer)); 454*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 455*2e1d0745SJose E. Roman if (rank == 0) { 456*2e1d0745SJose E. Roman const PetscScalar *a; 457*2e1d0745SJose E. Roman PetscReal timeScale; 458*2e1d0745SJose E. Roman PetscBool istime; 459*2e1d0745SJose E. Roman 460*2e1d0745SJose E. Roman PetscCall(VecGetArrayRead(stamp, &a)); 461*2e1d0745SJose E. Roman *value = a[0]; 462*2e1d0745SJose E. Roman PetscCall(VecRestoreArrayRead(stamp, &a)); 463*2e1d0745SJose E. Roman PetscCall(PetscStrncmp(seqname, "time", 5, &istime)); 464*2e1d0745SJose E. Roman if (istime) { 465*2e1d0745SJose E. Roman PetscCall(DMPlexGetScale(dm, PETSC_UNIT_TIME, &timeScale)); 466*2e1d0745SJose E. Roman *value /= timeScale; 467*2e1d0745SJose E. Roman } 468*2e1d0745SJose E. Roman } 469*2e1d0745SJose E. Roman PetscCall(VecDestroy(&stamp)); 470*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 471*2e1d0745SJose E. Roman } 472*2e1d0745SJose E. Roman 473*2e1d0745SJose E. Roman static PetscErrorCode DMPlexCreateCutVertexLabel_Private(DM dm, DMLabel cutLabel, DMLabel *cutVertexLabel) 474*2e1d0745SJose E. Roman { 475*2e1d0745SJose E. Roman IS cutcells = NULL; 476*2e1d0745SJose E. Roman const PetscInt *cutc; 477*2e1d0745SJose E. Roman PetscInt cellHeight, vStart, vEnd, cStart, cEnd, c; 478*2e1d0745SJose E. Roman 479*2e1d0745SJose E. Roman PetscFunctionBegin; 480*2e1d0745SJose E. Roman if (!cutLabel) PetscFunctionReturn(PETSC_SUCCESS); 481*2e1d0745SJose E. Roman PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 482*2e1d0745SJose E. Roman PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 483*2e1d0745SJose E. Roman PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 484*2e1d0745SJose E. Roman /* Label vertices that should be duplicated */ 485*2e1d0745SJose E. Roman PetscCall(DMLabelCreate(PETSC_COMM_SELF, "Cut Vertices", cutVertexLabel)); 486*2e1d0745SJose E. Roman PetscCall(DMLabelGetStratumIS(cutLabel, 2, &cutcells)); 487*2e1d0745SJose E. Roman if (cutcells) { 488*2e1d0745SJose E. Roman PetscInt n; 489*2e1d0745SJose E. Roman 490*2e1d0745SJose E. Roman PetscCall(ISGetIndices(cutcells, &cutc)); 491*2e1d0745SJose E. Roman PetscCall(ISGetLocalSize(cutcells, &n)); 492*2e1d0745SJose E. Roman for (c = 0; c < n; ++c) { 493*2e1d0745SJose E. Roman if ((cutc[c] >= cStart) && (cutc[c] < cEnd)) { 494*2e1d0745SJose E. Roman PetscInt *closure = NULL; 495*2e1d0745SJose E. Roman PetscInt closureSize, cl, value; 496*2e1d0745SJose E. Roman 497*2e1d0745SJose E. Roman PetscCall(DMPlexGetTransitiveClosure(dm, cutc[c], PETSC_TRUE, &closureSize, &closure)); 498*2e1d0745SJose E. Roman for (cl = 0; cl < closureSize * 2; cl += 2) { 499*2e1d0745SJose E. Roman if ((closure[cl] >= vStart) && (closure[cl] < vEnd)) { 500*2e1d0745SJose E. Roman PetscCall(DMLabelGetValue(cutLabel, closure[cl], &value)); 501*2e1d0745SJose E. Roman if (value == 1) PetscCall(DMLabelSetValue(*cutVertexLabel, closure[cl], 1)); 502*2e1d0745SJose E. Roman } 503*2e1d0745SJose E. Roman } 504*2e1d0745SJose E. Roman PetscCall(DMPlexRestoreTransitiveClosure(dm, cutc[c], PETSC_TRUE, &closureSize, &closure)); 505*2e1d0745SJose E. Roman } 506*2e1d0745SJose E. Roman } 507*2e1d0745SJose E. Roman PetscCall(ISRestoreIndices(cutcells, &cutc)); 508*2e1d0745SJose E. Roman } 509*2e1d0745SJose E. Roman PetscCall(ISDestroy(&cutcells)); 510*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 511*2e1d0745SJose E. Roman } 512*2e1d0745SJose E. Roman 513*2e1d0745SJose E. Roman PetscErrorCode VecView_Plex_Local_HDF5_Internal(Vec v, PetscViewer viewer) 514*2e1d0745SJose E. Roman { 515*2e1d0745SJose E. Roman DM dm; 516*2e1d0745SJose E. Roman DM dmBC; 517*2e1d0745SJose E. Roman PetscSection section, sectionGlobal; 518*2e1d0745SJose E. Roman Vec gv; 519*2e1d0745SJose E. Roman const char *name; 520*2e1d0745SJose E. Roman PetscViewerFormat format; 521*2e1d0745SJose E. Roman PetscInt seqnum; 522*2e1d0745SJose E. Roman PetscReal seqval; 523*2e1d0745SJose E. Roman PetscBool isseq; 524*2e1d0745SJose E. Roman 525*2e1d0745SJose E. Roman PetscFunctionBegin; 526*2e1d0745SJose E. Roman PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq)); 527*2e1d0745SJose E. Roman PetscCall(VecGetDM(v, &dm)); 528*2e1d0745SJose E. Roman PetscCall(DMGetLocalSection(dm, §ion)); 529*2e1d0745SJose E. Roman PetscCall(DMGetOutputSequenceNumber(dm, &seqnum, &seqval)); 530*2e1d0745SJose E. Roman PetscCall(DMSequenceView_HDF5(dm, "time", seqnum, (PetscScalar)seqval, viewer)); 531*2e1d0745SJose E. Roman if (seqnum >= 0) { 532*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushTimestepping(viewer)); 533*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5SetTimestep(viewer, seqnum)); 534*2e1d0745SJose E. Roman } 535*2e1d0745SJose E. Roman PetscCall(PetscViewerGetFormat(viewer, &format)); 536*2e1d0745SJose E. Roman PetscCall(DMGetOutputDM(dm, &dmBC)); 537*2e1d0745SJose E. Roman PetscCall(DMGetGlobalSection(dmBC, §ionGlobal)); 538*2e1d0745SJose E. Roman PetscCall(DMGetGlobalVector(dmBC, &gv)); 539*2e1d0745SJose E. Roman PetscCall(PetscObjectGetName((PetscObject)v, &name)); 540*2e1d0745SJose E. Roman PetscCall(PetscObjectSetName((PetscObject)gv, name)); 541*2e1d0745SJose E. Roman PetscCall(DMLocalToGlobalBegin(dmBC, v, INSERT_VALUES, gv)); 542*2e1d0745SJose E. Roman PetscCall(DMLocalToGlobalEnd(dmBC, v, INSERT_VALUES, gv)); 543*2e1d0745SJose E. Roman PetscCall(PetscObjectTypeCompare((PetscObject)gv, VECSEQ, &isseq)); 544*2e1d0745SJose E. Roman if (format == PETSC_VIEWER_HDF5_VIZ) { 545*2e1d0745SJose E. Roman /* Output visualization representation */ 546*2e1d0745SJose E. Roman PetscInt numFields, f; 547*2e1d0745SJose E. Roman DMLabel cutLabel, cutVertexLabel = NULL; 548*2e1d0745SJose E. Roman 549*2e1d0745SJose E. Roman PetscCall(PetscSectionGetNumFields(section, &numFields)); 550*2e1d0745SJose E. Roman PetscCall(DMGetLabel(dm, "periodic_cut", &cutLabel)); 551*2e1d0745SJose E. Roman for (f = 0; f < numFields; ++f) { 552*2e1d0745SJose E. Roman Vec subv; 553*2e1d0745SJose E. Roman IS is; 554*2e1d0745SJose E. Roman const char *fname, *fgroup, *componentName, *fname_def = "unnamed"; 555*2e1d0745SJose E. Roman char subname[PETSC_MAX_PATH_LEN]; 556*2e1d0745SJose E. Roman PetscInt Nc, c; 557*2e1d0745SJose E. Roman PetscInt pStart, pEnd; 558*2e1d0745SJose E. Roman PetscViewerVTKFieldType ft; 559*2e1d0745SJose E. Roman 560*2e1d0745SJose E. Roman PetscCall(DMPlexGetFieldType_Internal(dm, section, f, &pStart, &pEnd, &ft)); 561*2e1d0745SJose E. Roman if (ft == PETSC_VTK_INVALID) continue; 562*2e1d0745SJose E. Roman fgroup = (ft == PETSC_VTK_POINT_VECTOR_FIELD) || (ft == PETSC_VTK_POINT_FIELD) ? "/vertex_fields" : "/cell_fields"; 563*2e1d0745SJose E. Roman PetscCall(PetscSectionGetFieldName(section, f, &fname)); 564*2e1d0745SJose E. Roman if (!fname) fname = fname_def; 565*2e1d0745SJose E. Roman 566*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, fgroup)); 567*2e1d0745SJose E. Roman 568*2e1d0745SJose E. Roman if (cutLabel) { 569*2e1d0745SJose E. Roman const PetscScalar *ga; 570*2e1d0745SJose E. Roman PetscScalar *suba; 571*2e1d0745SJose E. Roman PetscInt gstart, subSize = 0, extSize = 0, subOff = 0, newOff = 0, p; 572*2e1d0745SJose E. Roman 573*2e1d0745SJose E. Roman PetscCall(DMPlexCreateCutVertexLabel_Private(dm, cutLabel, &cutVertexLabel)); 574*2e1d0745SJose E. Roman PetscCall(PetscSectionGetFieldComponents(section, f, &Nc)); 575*2e1d0745SJose E. Roman for (p = pStart; p < pEnd; ++p) { 576*2e1d0745SJose E. Roman PetscInt gdof, fdof = 0, val; 577*2e1d0745SJose E. Roman 578*2e1d0745SJose E. Roman PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof)); 579*2e1d0745SJose E. Roman if (gdof > 0) PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof)); 580*2e1d0745SJose E. Roman subSize += fdof; 581*2e1d0745SJose E. Roman PetscCall(DMLabelGetValue(cutVertexLabel, p, &val)); 582*2e1d0745SJose E. Roman if (val == 1) extSize += fdof; 583*2e1d0745SJose E. Roman } 584*2e1d0745SJose E. Roman PetscCall(VecCreate(PetscObjectComm((PetscObject)gv), &subv)); 585*2e1d0745SJose E. Roman PetscCall(VecSetSizes(subv, subSize + extSize, PETSC_DETERMINE)); 586*2e1d0745SJose E. Roman PetscCall(VecSetBlockSize(subv, Nc)); 587*2e1d0745SJose E. Roman PetscCall(VecSetType(subv, VECSTANDARD)); 588*2e1d0745SJose E. Roman PetscCall(VecGetOwnershipRange(gv, &gstart, NULL)); 589*2e1d0745SJose E. Roman PetscCall(VecGetArrayRead(gv, &ga)); 590*2e1d0745SJose E. Roman PetscCall(VecGetArray(subv, &suba)); 591*2e1d0745SJose E. Roman for (p = pStart; p < pEnd; ++p) { 592*2e1d0745SJose E. Roman PetscInt gdof, goff, val; 593*2e1d0745SJose E. Roman 594*2e1d0745SJose E. Roman PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof)); 595*2e1d0745SJose E. Roman if (gdof > 0) { 596*2e1d0745SJose E. Roman PetscInt fdof, fc, f2, poff = 0; 597*2e1d0745SJose E. Roman 598*2e1d0745SJose E. Roman PetscCall(PetscSectionGetOffset(sectionGlobal, p, &goff)); 599*2e1d0745SJose E. Roman /* Can get rid of this loop by storing field information in the global section */ 600*2e1d0745SJose E. Roman for (f2 = 0; f2 < f; ++f2) { 601*2e1d0745SJose E. Roman PetscCall(PetscSectionGetFieldDof(section, p, f2, &fdof)); 602*2e1d0745SJose E. Roman poff += fdof; 603*2e1d0745SJose E. Roman } 604*2e1d0745SJose E. Roman PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof)); 605*2e1d0745SJose E. Roman for (fc = 0; fc < fdof; ++fc, ++subOff) suba[subOff] = ga[goff + poff + fc - gstart]; 606*2e1d0745SJose E. Roman PetscCall(DMLabelGetValue(cutVertexLabel, p, &val)); 607*2e1d0745SJose E. Roman if (val == 1) { 608*2e1d0745SJose E. Roman for (fc = 0; fc < fdof; ++fc, ++newOff) suba[subSize + newOff] = ga[goff + poff + fc - gstart]; 609*2e1d0745SJose E. Roman } 610*2e1d0745SJose E. Roman } 611*2e1d0745SJose E. Roman } 612*2e1d0745SJose E. Roman PetscCall(VecRestoreArrayRead(gv, &ga)); 613*2e1d0745SJose E. Roman PetscCall(VecRestoreArray(subv, &suba)); 614*2e1d0745SJose E. Roman PetscCall(DMLabelDestroy(&cutVertexLabel)); 615*2e1d0745SJose E. Roman } else { 616*2e1d0745SJose E. Roman PetscCall(PetscSectionGetField_Internal(section, sectionGlobal, gv, f, pStart, pEnd, &is, &subv)); 617*2e1d0745SJose E. Roman } 618*2e1d0745SJose E. Roman PetscCall(PetscStrncpy(subname, name, sizeof(subname))); 619*2e1d0745SJose E. Roman PetscCall(PetscStrlcat(subname, "_", sizeof(subname))); 620*2e1d0745SJose E. Roman PetscCall(PetscStrlcat(subname, fname, sizeof(subname))); 621*2e1d0745SJose E. Roman PetscCall(PetscObjectSetName((PetscObject)subv, subname)); 622*2e1d0745SJose E. Roman if (isseq) PetscCall(VecView_Seq(subv, viewer)); 623*2e1d0745SJose E. Roman else PetscCall(VecView_MPI(subv, viewer)); 624*2e1d0745SJose E. Roman if (ft == PETSC_VTK_POINT_VECTOR_FIELD || ft == PETSC_VTK_CELL_VECTOR_FIELD) { 625*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5WriteObjectAttribute(viewer, (PetscObject)subv, "vector_field_type", PETSC_STRING, "vector")); 626*2e1d0745SJose E. Roman } else { 627*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5WriteObjectAttribute(viewer, (PetscObject)subv, "vector_field_type", PETSC_STRING, "scalar")); 628*2e1d0745SJose E. Roman } 629*2e1d0745SJose E. Roman 630*2e1d0745SJose E. Roman /* Output the component names in the field if available */ 631*2e1d0745SJose E. Roman PetscCall(PetscSectionGetFieldComponents(section, f, &Nc)); 632*2e1d0745SJose E. Roman for (c = 0; c < Nc; ++c) { 633*2e1d0745SJose E. Roman char componentNameLabel[PETSC_MAX_PATH_LEN]; 634*2e1d0745SJose E. Roman PetscCall(PetscSectionGetComponentName(section, f, c, &componentName)); 635*2e1d0745SJose E. Roman PetscCall(PetscSNPrintf(componentNameLabel, sizeof(componentNameLabel), "componentName%" PetscInt_FMT, c)); 636*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5WriteObjectAttribute(viewer, (PetscObject)subv, componentNameLabel, PETSC_STRING, componentName)); 637*2e1d0745SJose E. Roman } 638*2e1d0745SJose E. Roman 639*2e1d0745SJose E. Roman if (cutLabel) PetscCall(VecDestroy(&subv)); 640*2e1d0745SJose E. Roman else PetscCall(PetscSectionRestoreField_Internal(section, sectionGlobal, gv, f, pStart, pEnd, &is, &subv)); 641*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 642*2e1d0745SJose E. Roman } 643*2e1d0745SJose E. Roman } else { 644*2e1d0745SJose E. Roman /* Output full vector */ 645*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, "/fields")); 646*2e1d0745SJose E. Roman if (isseq) PetscCall(VecView_Seq(gv, viewer)); 647*2e1d0745SJose E. Roman else PetscCall(VecView_MPI(gv, viewer)); 648*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 649*2e1d0745SJose E. Roman } 650*2e1d0745SJose E. Roman if (seqnum >= 0) PetscCall(PetscViewerHDF5PopTimestepping(viewer)); 651*2e1d0745SJose E. Roman PetscCall(DMRestoreGlobalVector(dmBC, &gv)); 652*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 653*2e1d0745SJose E. Roman } 654*2e1d0745SJose E. Roman 655*2e1d0745SJose E. Roman PetscErrorCode VecView_Plex_HDF5_Internal(Vec v, PetscViewer viewer) 656*2e1d0745SJose E. Roman { 657*2e1d0745SJose E. Roman DMPlexStorageVersion version; 658*2e1d0745SJose E. Roman DM dm; 659*2e1d0745SJose E. Roman Vec locv; 660*2e1d0745SJose E. Roman PetscObject isZero; 661*2e1d0745SJose E. Roman const char *name; 662*2e1d0745SJose E. Roman PetscReal time; 663*2e1d0745SJose E. Roman 664*2e1d0745SJose E. Roman PetscFunctionBegin; 665*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5GetDMPlexStorageVersionWriting(viewer, &version)); 666*2e1d0745SJose E. Roman PetscCall(PetscInfo(v, "Writing Vec %s storage version %d.%d.%d\n", v->hdr.name, version->major, version->minor, version->subminor)); 667*2e1d0745SJose E. Roman 668*2e1d0745SJose E. Roman PetscCall(VecGetDM(v, &dm)); 669*2e1d0745SJose E. Roman PetscCall(DMGetLocalVector(dm, &locv)); 670*2e1d0745SJose E. Roman PetscCall(PetscObjectGetName((PetscObject)v, &name)); 671*2e1d0745SJose E. Roman PetscCall(PetscObjectSetName((PetscObject)locv, name)); 672*2e1d0745SJose E. Roman PetscCall(PetscObjectQuery((PetscObject)v, "__Vec_bc_zero__", &isZero)); 673*2e1d0745SJose E. Roman PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", isZero)); 674*2e1d0745SJose E. Roman PetscCall(DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv)); 675*2e1d0745SJose E. Roman PetscCall(DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv)); 676*2e1d0745SJose E. Roman PetscCall(DMGetOutputSequenceNumber(dm, NULL, &time)); 677*2e1d0745SJose E. Roman PetscCall(DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locv, time, NULL, NULL, NULL)); 678*2e1d0745SJose E. Roman PetscCall(VecView_Plex_Local_HDF5_Internal(locv, viewer)); 679*2e1d0745SJose E. Roman if (DMPlexStorageVersionEQ(version, 1, 1, 0)) { 680*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, "/fields")); 681*2e1d0745SJose E. Roman PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_HDF5_VIZ)); 682*2e1d0745SJose E. Roman PetscCall(VecView_Plex_Local_HDF5_Internal(locv, viewer)); 683*2e1d0745SJose E. Roman PetscCall(PetscViewerPopFormat(viewer)); 684*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 685*2e1d0745SJose E. Roman } 686*2e1d0745SJose E. Roman PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", NULL)); 687*2e1d0745SJose E. Roman PetscCall(DMRestoreLocalVector(dm, &locv)); 688*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 689*2e1d0745SJose E. Roman } 690*2e1d0745SJose E. Roman 691*2e1d0745SJose E. Roman PetscErrorCode VecView_Plex_HDF5_Native_Internal(Vec v, PetscViewer viewer) 692*2e1d0745SJose E. Roman { 693*2e1d0745SJose E. Roman PetscBool isseq; 694*2e1d0745SJose E. Roman 695*2e1d0745SJose E. Roman PetscFunctionBegin; 696*2e1d0745SJose E. Roman PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq)); 697*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, "/fields")); 698*2e1d0745SJose E. Roman if (isseq) PetscCall(VecView_Seq(v, viewer)); 699*2e1d0745SJose E. Roman else PetscCall(VecView_MPI(v, viewer)); 700*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 701*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 702*2e1d0745SJose E. Roman } 703*2e1d0745SJose E. Roman 704*2e1d0745SJose E. Roman PetscErrorCode VecLoad_Plex_HDF5_Internal(Vec v, PetscViewer viewer) 705*2e1d0745SJose E. Roman { 706*2e1d0745SJose E. Roman DM dm; 707*2e1d0745SJose E. Roman Vec locv; 708*2e1d0745SJose E. Roman const char *name; 709*2e1d0745SJose E. Roman PetscInt seqnum; 710*2e1d0745SJose E. Roman 711*2e1d0745SJose E. Roman PetscFunctionBegin; 712*2e1d0745SJose E. Roman PetscCall(VecGetDM(v, &dm)); 713*2e1d0745SJose E. Roman PetscCall(DMGetLocalVector(dm, &locv)); 714*2e1d0745SJose E. Roman PetscCall(PetscObjectGetName((PetscObject)v, &name)); 715*2e1d0745SJose E. Roman PetscCall(PetscObjectSetName((PetscObject)locv, name)); 716*2e1d0745SJose E. Roman PetscCall(DMGetOutputSequenceNumber(dm, &seqnum, NULL)); 717*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, "/fields")); 718*2e1d0745SJose E. Roman if (seqnum >= 0) { 719*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushTimestepping(viewer)); 720*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5SetTimestep(viewer, seqnum)); 721*2e1d0745SJose E. Roman } 722*2e1d0745SJose E. Roman PetscCall(VecLoad_Plex_Local(locv, viewer)); 723*2e1d0745SJose E. Roman if (seqnum >= 0) PetscCall(PetscViewerHDF5PopTimestepping(viewer)); 724*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 725*2e1d0745SJose E. Roman PetscCall(DMLocalToGlobalBegin(dm, locv, INSERT_VALUES, v)); 726*2e1d0745SJose E. Roman PetscCall(DMLocalToGlobalEnd(dm, locv, INSERT_VALUES, v)); 727*2e1d0745SJose E. Roman PetscCall(DMRestoreLocalVector(dm, &locv)); 728*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 729*2e1d0745SJose E. Roman } 730*2e1d0745SJose E. Roman 731*2e1d0745SJose E. Roman PetscErrorCode VecLoad_Plex_HDF5_Native_Internal(Vec v, PetscViewer viewer) 732*2e1d0745SJose E. Roman { 733*2e1d0745SJose E. Roman DM dm; 734*2e1d0745SJose E. Roman PetscInt seqnum; 735*2e1d0745SJose E. Roman 736*2e1d0745SJose E. Roman PetscFunctionBegin; 737*2e1d0745SJose E. Roman PetscCall(VecGetDM(v, &dm)); 738*2e1d0745SJose E. Roman PetscCall(DMGetOutputSequenceNumber(dm, &seqnum, NULL)); 739*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, "/fields")); 740*2e1d0745SJose E. Roman if (seqnum >= 0) { 741*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushTimestepping(viewer)); 742*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5SetTimestep(viewer, seqnum)); 743*2e1d0745SJose E. Roman } 744*2e1d0745SJose E. Roman PetscCall(VecLoad_Default(v, viewer)); 745*2e1d0745SJose E. Roman if (seqnum >= 0) PetscCall(PetscViewerHDF5PopTimestepping(viewer)); 746*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 747*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 748*2e1d0745SJose E. Roman } 749*2e1d0745SJose E. Roman 750*2e1d0745SJose E. Roman static PetscErrorCode DMPlexDistributionView_HDF5_Private(DM dm, IS globalPointNumbers, PetscViewer viewer) 751*2e1d0745SJose E. Roman { 752*2e1d0745SJose E. Roman MPI_Comm comm; 753*2e1d0745SJose E. Roman PetscMPIInt size, rank; 754*2e1d0745SJose E. Roman PetscInt size_petsc_int; 755*2e1d0745SJose E. Roman const char *topologydm_name, *distribution_name; 756*2e1d0745SJose E. Roman const PetscInt *gpoint; 757*2e1d0745SJose E. Roman PetscInt pStart, pEnd, p; 758*2e1d0745SJose E. Roman PetscSF pointSF; 759*2e1d0745SJose E. Roman PetscInt nroots, nleaves; 760*2e1d0745SJose E. Roman const PetscInt *ilocal; 761*2e1d0745SJose E. Roman const PetscSFNode *iremote; 762*2e1d0745SJose E. Roman IS chartSizesIS, ownersIS, gpointsIS; 763*2e1d0745SJose E. Roman PetscInt *chartSize, *owners, *gpoints; 764*2e1d0745SJose E. Roman 765*2e1d0745SJose E. Roman PetscFunctionBegin; 766*2e1d0745SJose E. Roman PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 767*2e1d0745SJose E. Roman PetscCallMPI(MPI_Comm_size(comm, &size)); 768*2e1d0745SJose E. Roman PetscCallMPI(MPI_Comm_rank(comm, &rank)); 769*2e1d0745SJose E. Roman PetscCall(DMPlexGetHDF5Name_Private(dm, &topologydm_name)); 770*2e1d0745SJose E. Roman PetscCall(DMPlexDistributionGetName(dm, &distribution_name)); 771*2e1d0745SJose E. Roman if (!distribution_name) PetscFunctionReturn(PETSC_SUCCESS); 772*2e1d0745SJose E. Roman PetscCall(PetscLogEventBegin(DMPLEX_DistributionView, viewer, 0, 0, 0)); 773*2e1d0745SJose E. Roman size_petsc_int = (PetscInt)size; 774*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5WriteAttribute(viewer, NULL, "comm_size", PETSC_INT, (void *)&size_petsc_int)); 775*2e1d0745SJose E. Roman PetscCall(ISGetIndices(globalPointNumbers, &gpoint)); 776*2e1d0745SJose E. Roman PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 777*2e1d0745SJose E. Roman PetscCall(PetscMalloc1(1, &chartSize)); 778*2e1d0745SJose E. Roman *chartSize = pEnd - pStart; 779*2e1d0745SJose E. Roman PetscCall(PetscMalloc1(*chartSize, &owners)); 780*2e1d0745SJose E. Roman PetscCall(PetscMalloc1(*chartSize, &gpoints)); 781*2e1d0745SJose E. Roman PetscCall(DMGetPointSF(dm, &pointSF)); 782*2e1d0745SJose E. Roman PetscCall(PetscSFGetGraph(pointSF, &nroots, &nleaves, &ilocal, &iremote)); 783*2e1d0745SJose E. Roman for (p = pStart; p < pEnd; ++p) { 784*2e1d0745SJose E. Roman PetscInt gp = gpoint[p - pStart]; 785*2e1d0745SJose E. Roman 786*2e1d0745SJose E. Roman owners[p - pStart] = rank; 787*2e1d0745SJose E. Roman gpoints[p - pStart] = (gp < 0 ? -(gp + 1) : gp); 788*2e1d0745SJose E. Roman } 789*2e1d0745SJose E. Roman for (p = 0; p < nleaves; ++p) { 790*2e1d0745SJose E. Roman PetscInt ilocalp = (ilocal ? ilocal[p] : p); 791*2e1d0745SJose E. Roman 792*2e1d0745SJose E. Roman owners[ilocalp] = iremote[p].rank; 793*2e1d0745SJose E. Roman } 794*2e1d0745SJose E. Roman PetscCall(ISCreateGeneral(comm, 1, chartSize, PETSC_OWN_POINTER, &chartSizesIS)); 795*2e1d0745SJose E. Roman PetscCall(ISCreateGeneral(comm, *chartSize, owners, PETSC_OWN_POINTER, &ownersIS)); 796*2e1d0745SJose E. Roman PetscCall(ISCreateGeneral(comm, *chartSize, gpoints, PETSC_OWN_POINTER, &gpointsIS)); 797*2e1d0745SJose E. Roman PetscCall(PetscObjectSetName((PetscObject)chartSizesIS, "chart_sizes")); 798*2e1d0745SJose E. Roman PetscCall(PetscObjectSetName((PetscObject)ownersIS, "owners")); 799*2e1d0745SJose E. Roman PetscCall(PetscObjectSetName((PetscObject)gpointsIS, "global_point_numbers")); 800*2e1d0745SJose E. Roman PetscCall(ISView(chartSizesIS, viewer)); 801*2e1d0745SJose E. Roman PetscCall(ISView(ownersIS, viewer)); 802*2e1d0745SJose E. Roman PetscCall(ISView(gpointsIS, viewer)); 803*2e1d0745SJose E. Roman PetscCall(ISDestroy(&chartSizesIS)); 804*2e1d0745SJose E. Roman PetscCall(ISDestroy(&ownersIS)); 805*2e1d0745SJose E. Roman PetscCall(ISDestroy(&gpointsIS)); 806*2e1d0745SJose E. Roman PetscCall(ISRestoreIndices(globalPointNumbers, &gpoint)); 807*2e1d0745SJose E. Roman PetscCall(PetscLogEventEnd(DMPLEX_DistributionView, viewer, 0, 0, 0)); 808*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 809*2e1d0745SJose E. Roman } 810*2e1d0745SJose E. Roman 811*2e1d0745SJose 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[]) 812*2e1d0745SJose E. Roman { 813*2e1d0745SJose E. Roman IS coneSizesIS, conesIS, orientationsIS; 814*2e1d0745SJose E. Roman PetscInt *coneSizes, *cones, *orientations; 815*2e1d0745SJose E. Roman const PetscInt *gpoint; 816*2e1d0745SJose E. Roman PetscInt nPoints = 0, conesSize = 0; 817*2e1d0745SJose E. Roman PetscInt p, c, s; 818*2e1d0745SJose E. Roman MPI_Comm comm; 819*2e1d0745SJose E. Roman 820*2e1d0745SJose E. Roman PetscFunctionBegin; 821*2e1d0745SJose E. Roman PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 822*2e1d0745SJose E. Roman PetscCall(ISGetIndices(globalPointNumbers, &gpoint)); 823*2e1d0745SJose E. Roman for (p = pStart; p < pEnd; ++p) { 824*2e1d0745SJose E. Roman if (gpoint[p] >= 0) { 825*2e1d0745SJose E. Roman PetscInt coneSize; 826*2e1d0745SJose E. Roman 827*2e1d0745SJose E. Roman PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 828*2e1d0745SJose E. Roman nPoints += 1; 829*2e1d0745SJose E. Roman conesSize += coneSize; 830*2e1d0745SJose E. Roman } 831*2e1d0745SJose E. Roman } 832*2e1d0745SJose E. Roman PetscCall(PetscMalloc1(nPoints, &coneSizes)); 833*2e1d0745SJose E. Roman PetscCall(PetscMalloc1(conesSize, &cones)); 834*2e1d0745SJose E. Roman PetscCall(PetscMalloc1(conesSize, &orientations)); 835*2e1d0745SJose E. Roman for (p = pStart, c = 0, s = 0; p < pEnd; ++p) { 836*2e1d0745SJose E. Roman if (gpoint[p] >= 0) { 837*2e1d0745SJose E. Roman const PetscInt *cone, *ornt; 838*2e1d0745SJose E. Roman PetscInt coneSize, cp; 839*2e1d0745SJose E. Roman 840*2e1d0745SJose E. Roman PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 841*2e1d0745SJose E. Roman PetscCall(DMPlexGetCone(dm, p, &cone)); 842*2e1d0745SJose E. Roman PetscCall(DMPlexGetConeOrientation(dm, p, &ornt)); 843*2e1d0745SJose E. Roman coneSizes[s] = coneSize; 844*2e1d0745SJose E. Roman for (cp = 0; cp < coneSize; ++cp, ++c) { 845*2e1d0745SJose E. Roman cones[c] = gpoint[cone[cp]] < 0 ? -(gpoint[cone[cp]] + 1) : gpoint[cone[cp]]; 846*2e1d0745SJose E. Roman orientations[c] = ornt[cp]; 847*2e1d0745SJose E. Roman } 848*2e1d0745SJose E. Roman ++s; 849*2e1d0745SJose E. Roman } 850*2e1d0745SJose E. Roman } 851*2e1d0745SJose E. Roman PetscCheck(s == nPoints, PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of points %" PetscInt_FMT " != %" PetscInt_FMT, s, nPoints); 852*2e1d0745SJose E. Roman PetscCheck(c == conesSize, PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of cone points %" PetscInt_FMT " != %" PetscInt_FMT, c, conesSize); 853*2e1d0745SJose E. Roman PetscCall(ISCreateGeneral(comm, nPoints, coneSizes, PETSC_OWN_POINTER, &coneSizesIS)); 854*2e1d0745SJose E. Roman PetscCall(ISCreateGeneral(comm, conesSize, cones, PETSC_OWN_POINTER, &conesIS)); 855*2e1d0745SJose E. Roman PetscCall(ISCreateGeneral(comm, conesSize, orientations, PETSC_OWN_POINTER, &orientationsIS)); 856*2e1d0745SJose E. Roman PetscCall(PetscObjectSetName((PetscObject)coneSizesIS, coneSizesName)); 857*2e1d0745SJose E. Roman PetscCall(PetscObjectSetName((PetscObject)conesIS, conesName)); 858*2e1d0745SJose E. Roman PetscCall(PetscObjectSetName((PetscObject)orientationsIS, orientationsName)); 859*2e1d0745SJose E. Roman PetscCall(ISView(coneSizesIS, viewer)); 860*2e1d0745SJose E. Roman PetscCall(ISView(conesIS, viewer)); 861*2e1d0745SJose E. Roman PetscCall(ISView(orientationsIS, viewer)); 862*2e1d0745SJose E. Roman PetscCall(ISDestroy(&coneSizesIS)); 863*2e1d0745SJose E. Roman PetscCall(ISDestroy(&conesIS)); 864*2e1d0745SJose E. Roman PetscCall(ISDestroy(&orientationsIS)); 865*2e1d0745SJose E. Roman if (pointsName) { 866*2e1d0745SJose E. Roman IS pointsIS; 867*2e1d0745SJose E. Roman PetscInt *points; 868*2e1d0745SJose E. Roman 869*2e1d0745SJose E. Roman PetscCall(PetscMalloc1(nPoints, &points)); 870*2e1d0745SJose E. Roman for (p = pStart, c = 0, s = 0; p < pEnd; ++p) { 871*2e1d0745SJose E. Roman if (gpoint[p] >= 0) { 872*2e1d0745SJose E. Roman points[s] = gpoint[p]; 873*2e1d0745SJose E. Roman ++s; 874*2e1d0745SJose E. Roman } 875*2e1d0745SJose E. Roman } 876*2e1d0745SJose E. Roman PetscCall(ISCreateGeneral(comm, nPoints, points, PETSC_OWN_POINTER, &pointsIS)); 877*2e1d0745SJose E. Roman PetscCall(PetscObjectSetName((PetscObject)pointsIS, pointsName)); 878*2e1d0745SJose E. Roman PetscCall(ISView(pointsIS, viewer)); 879*2e1d0745SJose E. Roman PetscCall(ISDestroy(&pointsIS)); 880*2e1d0745SJose E. Roman } 881*2e1d0745SJose E. Roman PetscCall(ISRestoreIndices(globalPointNumbers, &gpoint)); 882*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 883*2e1d0745SJose E. Roman } 884*2e1d0745SJose E. Roman 885*2e1d0745SJose E. Roman static PetscErrorCode DMPlexTopologyView_HDF5_Legacy_Private(DM dm, IS globalPointNumbers, PetscViewer viewer) 886*2e1d0745SJose E. Roman { 887*2e1d0745SJose E. Roman const char *pointsName, *coneSizesName, *conesName, *orientationsName; 888*2e1d0745SJose E. Roman PetscInt pStart, pEnd, dim; 889*2e1d0745SJose E. Roman 890*2e1d0745SJose E. Roman PetscFunctionBegin; 891*2e1d0745SJose E. Roman pointsName = "order"; 892*2e1d0745SJose E. Roman coneSizesName = "cones"; 893*2e1d0745SJose E. Roman conesName = "cells"; 894*2e1d0745SJose E. Roman orientationsName = "orientation"; 895*2e1d0745SJose E. Roman PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 896*2e1d0745SJose E. Roman PetscCall(DMPlexTopologyView_HDF5_Inner_Private(dm, globalPointNumbers, viewer, pStart, pEnd, pointsName, coneSizesName, conesName, orientationsName)); 897*2e1d0745SJose E. Roman PetscCall(DMGetDimension(dm, &dim)); 898*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5WriteAttribute(viewer, conesName, "cell_dim", PETSC_INT, (void *)&dim)); 899*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 900*2e1d0745SJose E. Roman } 901*2e1d0745SJose E. Roman 902*2e1d0745SJose E. Roman //TODO get this numbering right away without needing this function 903*2e1d0745SJose E. Roman /* Renumber global point numbers so that they are 0-based per stratum */ 904*2e1d0745SJose E. Roman static PetscErrorCode RenumberGlobalPointNumbersPerStratum_Private(DM dm, IS globalPointNumbers, IS *newGlobalPointNumbers, IS *strataPermutation) 905*2e1d0745SJose E. Roman { 906*2e1d0745SJose E. Roman PetscInt d, depth, p, n; 907*2e1d0745SJose E. Roman PetscInt *offsets; 908*2e1d0745SJose E. Roman const PetscInt *gpn; 909*2e1d0745SJose E. Roman PetscInt *ngpn; 910*2e1d0745SJose E. Roman MPI_Comm comm; 911*2e1d0745SJose E. Roman 912*2e1d0745SJose E. Roman PetscFunctionBegin; 913*2e1d0745SJose E. Roman PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 914*2e1d0745SJose E. Roman PetscCall(ISGetLocalSize(globalPointNumbers, &n)); 915*2e1d0745SJose E. Roman PetscCall(ISGetIndices(globalPointNumbers, &gpn)); 916*2e1d0745SJose E. Roman PetscCall(PetscMalloc1(n, &ngpn)); 917*2e1d0745SJose E. Roman PetscCall(DMPlexGetDepth(dm, &depth)); 918*2e1d0745SJose E. Roman PetscCall(PetscMalloc1(depth + 1, &offsets)); 919*2e1d0745SJose E. Roman for (d = 0; d <= depth; d++) { 920*2e1d0745SJose E. Roman PetscInt pStart, pEnd; 921*2e1d0745SJose E. Roman 922*2e1d0745SJose E. Roman PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 923*2e1d0745SJose E. Roman offsets[d] = PETSC_INT_MAX; 924*2e1d0745SJose E. Roman for (p = pStart; p < pEnd; p++) { 925*2e1d0745SJose E. Roman if (gpn[p] >= 0 && gpn[p] < offsets[d]) offsets[d] = gpn[p]; 926*2e1d0745SJose E. Roman } 927*2e1d0745SJose E. Roman } 928*2e1d0745SJose E. Roman PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, offsets, depth + 1, MPIU_INT, MPI_MIN, comm)); 929*2e1d0745SJose E. Roman for (d = 0; d <= depth; d++) { 930*2e1d0745SJose E. Roman PetscInt pStart, pEnd; 931*2e1d0745SJose E. Roman 932*2e1d0745SJose E. Roman PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 933*2e1d0745SJose E. Roman for (p = pStart; p < pEnd; p++) ngpn[p] = gpn[p] - PetscSign(gpn[p]) * offsets[d]; 934*2e1d0745SJose E. Roman } 935*2e1d0745SJose E. Roman PetscCall(ISRestoreIndices(globalPointNumbers, &gpn)); 936*2e1d0745SJose E. Roman PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)globalPointNumbers), n, ngpn, PETSC_OWN_POINTER, newGlobalPointNumbers)); 937*2e1d0745SJose E. Roman { 938*2e1d0745SJose E. Roman PetscInt *perm; 939*2e1d0745SJose E. Roman 940*2e1d0745SJose E. Roman PetscCall(PetscMalloc1(depth + 1, &perm)); 941*2e1d0745SJose E. Roman for (d = 0; d <= depth; d++) perm[d] = d; 942*2e1d0745SJose E. Roman PetscCall(PetscSortIntWithPermutation(depth + 1, offsets, perm)); 943*2e1d0745SJose E. Roman PetscCall(ISCreateGeneral(PETSC_COMM_SELF, depth + 1, perm, PETSC_OWN_POINTER, strataPermutation)); 944*2e1d0745SJose E. Roman } 945*2e1d0745SJose E. Roman PetscCall(PetscFree(offsets)); 946*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 947*2e1d0745SJose E. Roman } 948*2e1d0745SJose E. Roman 949*2e1d0745SJose E. Roman static PetscErrorCode DMPlexTopologyView_HDF5_Private(DM dm, IS globalPointNumbers, PetscViewer viewer) 950*2e1d0745SJose E. Roman { 951*2e1d0745SJose E. Roman IS globalPointNumbers0, strataPermutation; 952*2e1d0745SJose E. Roman const char *coneSizesName, *conesName, *orientationsName; 953*2e1d0745SJose E. Roman PetscInt depth, d; 954*2e1d0745SJose E. Roman MPI_Comm comm; 955*2e1d0745SJose E. Roman 956*2e1d0745SJose E. Roman PetscFunctionBegin; 957*2e1d0745SJose E. Roman coneSizesName = "cone_sizes"; 958*2e1d0745SJose E. Roman conesName = "cones"; 959*2e1d0745SJose E. Roman orientationsName = "orientations"; 960*2e1d0745SJose E. Roman PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 961*2e1d0745SJose E. Roman PetscCall(DMPlexGetDepth(dm, &depth)); 962*2e1d0745SJose E. Roman { 963*2e1d0745SJose E. Roman PetscInt dim; 964*2e1d0745SJose E. Roman 965*2e1d0745SJose E. Roman PetscCall(DMGetDimension(dm, &dim)); 966*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5WriteAttribute(viewer, NULL, "cell_dim", PETSC_INT, &dim)); 967*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5WriteAttribute(viewer, NULL, "depth", PETSC_INT, &depth)); 968*2e1d0745SJose E. Roman } 969*2e1d0745SJose E. Roman 970*2e1d0745SJose E. Roman PetscCall(RenumberGlobalPointNumbersPerStratum_Private(dm, globalPointNumbers, &globalPointNumbers0, &strataPermutation)); 971*2e1d0745SJose E. Roman /* TODO dirty trick to save serial IS using the same parallel viewer */ 972*2e1d0745SJose E. Roman { 973*2e1d0745SJose E. Roman IS spOnComm; 974*2e1d0745SJose E. Roman PetscInt n = 0, N; 975*2e1d0745SJose E. Roman const PetscInt *idx = NULL; 976*2e1d0745SJose E. Roman const PetscInt *old; 977*2e1d0745SJose E. Roman PetscMPIInt rank; 978*2e1d0745SJose E. Roman 979*2e1d0745SJose E. Roman PetscCallMPI(MPI_Comm_rank(comm, &rank)); 980*2e1d0745SJose E. Roman PetscCall(ISGetLocalSize(strataPermutation, &N)); 981*2e1d0745SJose E. Roman PetscCall(ISGetIndices(strataPermutation, &old)); 982*2e1d0745SJose E. Roman if (!rank) { 983*2e1d0745SJose E. Roman n = N; 984*2e1d0745SJose E. Roman idx = old; 985*2e1d0745SJose E. Roman } 986*2e1d0745SJose E. Roman PetscCall(ISCreateGeneral(comm, n, idx, PETSC_COPY_VALUES, &spOnComm)); 987*2e1d0745SJose E. Roman PetscCall(ISRestoreIndices(strataPermutation, &old)); 988*2e1d0745SJose E. Roman PetscCall(ISDestroy(&strataPermutation)); 989*2e1d0745SJose E. Roman strataPermutation = spOnComm; 990*2e1d0745SJose E. Roman } 991*2e1d0745SJose E. Roman PetscCall(PetscObjectSetName((PetscObject)strataPermutation, "permutation")); 992*2e1d0745SJose E. Roman PetscCall(ISView(strataPermutation, viewer)); 993*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, "strata")); 994*2e1d0745SJose E. Roman for (d = 0; d <= depth; d++) { 995*2e1d0745SJose E. Roman PetscInt pStart, pEnd; 996*2e1d0745SJose E. Roman char group[128]; 997*2e1d0745SJose E. Roman 998*2e1d0745SJose E. Roman PetscCall(PetscSNPrintf(group, sizeof(group), "%" PetscInt_FMT, d)); 999*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, group)); 1000*2e1d0745SJose E. Roman PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 1001*2e1d0745SJose E. Roman PetscCall(DMPlexTopologyView_HDF5_Inner_Private(dm, globalPointNumbers0, viewer, pStart, pEnd, NULL, coneSizesName, conesName, orientationsName)); 1002*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 1003*2e1d0745SJose E. Roman } 1004*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); /* strata */ 1005*2e1d0745SJose E. Roman PetscCall(ISDestroy(&globalPointNumbers0)); 1006*2e1d0745SJose E. Roman PetscCall(ISDestroy(&strataPermutation)); 1007*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 1008*2e1d0745SJose E. Roman } 1009*2e1d0745SJose E. Roman 1010*2e1d0745SJose E. Roman PetscErrorCode DMPlexTopologyView_HDF5_Internal(DM dm, IS globalPointNumbers, PetscViewer viewer) 1011*2e1d0745SJose E. Roman { 1012*2e1d0745SJose E. Roman DMPlexStorageVersion version; 1013*2e1d0745SJose E. Roman const char *topologydm_name; 1014*2e1d0745SJose E. Roman char group[PETSC_MAX_PATH_LEN]; 1015*2e1d0745SJose E. Roman 1016*2e1d0745SJose E. Roman PetscFunctionBegin; 1017*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5GetDMPlexStorageVersionWriting(viewer, &version)); 1018*2e1d0745SJose E. Roman PetscCall(PetscInfo(dm, "Writing DM %s storage version %d.%d.%d\n", dm->hdr.name, version->major, version->minor, version->subminor)); 1019*2e1d0745SJose E. Roman PetscCall(DMPlexGetHDF5Name_Private(dm, &topologydm_name)); 1020*2e1d0745SJose E. Roman if (DMPlexStorageVersionGE(version, 2, 0, 0)) { 1021*2e1d0745SJose E. Roman PetscCall(PetscSNPrintf(group, sizeof(group), "topologies/%s", topologydm_name)); 1022*2e1d0745SJose E. Roman } else { 1023*2e1d0745SJose E. Roman PetscCall(PetscStrncpy(group, "/", sizeof(group))); 1024*2e1d0745SJose E. Roman } 1025*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, group)); 1026*2e1d0745SJose E. Roman 1027*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, "topology")); 1028*2e1d0745SJose E. Roman if (version->major < 3) { 1029*2e1d0745SJose E. Roman PetscCall(DMPlexTopologyView_HDF5_Legacy_Private(dm, globalPointNumbers, viewer)); 1030*2e1d0745SJose E. Roman } else { 1031*2e1d0745SJose E. Roman /* since DMPlexStorageVersion 3.0.0 */ 1032*2e1d0745SJose E. Roman PetscCall(DMPlexTopologyView_HDF5_Private(dm, globalPointNumbers, viewer)); 1033*2e1d0745SJose E. Roman } 1034*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); /* "topology" */ 1035*2e1d0745SJose E. Roman 1036*2e1d0745SJose E. Roman if (DMPlexStorageVersionGE(version, 2, 1, 0)) { 1037*2e1d0745SJose E. Roman const char *distribution_name; 1038*2e1d0745SJose E. Roman 1039*2e1d0745SJose E. Roman PetscCall(DMPlexDistributionGetName(dm, &distribution_name)); 1040*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, "distributions")); 1041*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5WriteGroup(viewer, NULL)); 1042*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, distribution_name)); 1043*2e1d0745SJose E. Roman PetscCall(DMPlexDistributionView_HDF5_Private(dm, globalPointNumbers, viewer)); 1044*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); /* distribution_name */ 1045*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); /* "distributions" */ 1046*2e1d0745SJose E. Roman } 1047*2e1d0745SJose E. Roman 1048*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 1049*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 1050*2e1d0745SJose E. Roman } 1051*2e1d0745SJose E. Roman 1052*2e1d0745SJose E. Roman static PetscErrorCode CreateConesIS_Private(DM dm, PetscInt cStart, PetscInt cEnd, IS globalCellNumbers, PetscInt *numCorners, IS *cellIS) 1053*2e1d0745SJose E. Roman { 1054*2e1d0745SJose E. Roman PetscSF sfPoint; 1055*2e1d0745SJose E. Roman DMLabel cutLabel, cutVertexLabel = NULL; 1056*2e1d0745SJose E. Roman IS globalVertexNumbers, cutvertices = NULL; 1057*2e1d0745SJose E. Roman const PetscInt *gcell, *gvertex, *cutverts = NULL; 1058*2e1d0745SJose E. Roman PetscInt *vertices; 1059*2e1d0745SJose E. Roman PetscInt conesSize = 0; 1060*2e1d0745SJose E. Roman PetscInt dim, numCornersLocal = 0, cell, vStart, vEnd, vExtra = 0, v; 1061*2e1d0745SJose E. Roman 1062*2e1d0745SJose E. Roman PetscFunctionBegin; 1063*2e1d0745SJose E. Roman *numCorners = 0; 1064*2e1d0745SJose E. Roman PetscCall(DMGetDimension(dm, &dim)); 1065*2e1d0745SJose E. Roman PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 1066*2e1d0745SJose E. Roman PetscCall(ISGetIndices(globalCellNumbers, &gcell)); 1067*2e1d0745SJose E. Roman 1068*2e1d0745SJose E. Roman for (cell = cStart; cell < cEnd; ++cell) { 1069*2e1d0745SJose E. Roman PetscInt *closure = NULL; 1070*2e1d0745SJose E. Roman PetscInt closureSize, v, Nc = 0; 1071*2e1d0745SJose E. Roman 1072*2e1d0745SJose E. Roman if (gcell[cell] < 0) continue; 1073*2e1d0745SJose E. Roman PetscCall(DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure)); 1074*2e1d0745SJose E. Roman for (v = 0; v < closureSize * 2; v += 2) { 1075*2e1d0745SJose E. Roman if ((closure[v] >= vStart) && (closure[v] < vEnd)) ++Nc; 1076*2e1d0745SJose E. Roman } 1077*2e1d0745SJose E. Roman PetscCall(DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure)); 1078*2e1d0745SJose E. Roman conesSize += Nc; 1079*2e1d0745SJose E. Roman if (!numCornersLocal) numCornersLocal = Nc; 1080*2e1d0745SJose E. Roman else if (numCornersLocal != Nc) numCornersLocal = 1; 1081*2e1d0745SJose E. Roman } 1082*2e1d0745SJose E. Roman PetscCallMPI(MPIU_Allreduce(&numCornersLocal, numCorners, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 1083*2e1d0745SJose E. Roman PetscCheck(!numCornersLocal || !(numCornersLocal != *numCorners || *numCorners == 0), PETSC_COMM_SELF, PETSC_ERR_SUP, "Visualization topology currently only supports identical cell shapes"); 1084*2e1d0745SJose E. Roman /* Handle periodic cuts by identifying vertices which should be duplicated */ 1085*2e1d0745SJose E. Roman PetscCall(DMGetLabel(dm, "periodic_cut", &cutLabel)); 1086*2e1d0745SJose E. Roman PetscCall(DMPlexCreateCutVertexLabel_Private(dm, cutLabel, &cutVertexLabel)); 1087*2e1d0745SJose E. Roman if (cutVertexLabel) PetscCall(DMLabelGetStratumIS(cutVertexLabel, 1, &cutvertices)); 1088*2e1d0745SJose E. Roman if (cutvertices) { 1089*2e1d0745SJose E. Roman PetscCall(ISGetIndices(cutvertices, &cutverts)); 1090*2e1d0745SJose E. Roman PetscCall(ISGetLocalSize(cutvertices, &vExtra)); 1091*2e1d0745SJose E. Roman } 1092*2e1d0745SJose E. Roman PetscCall(DMGetPointSF(dm, &sfPoint)); 1093*2e1d0745SJose E. Roman if (cutLabel) { 1094*2e1d0745SJose E. Roman const PetscInt *ilocal; 1095*2e1d0745SJose E. Roman const PetscSFNode *iremote; 1096*2e1d0745SJose E. Roman PetscInt nroots, nleaves; 1097*2e1d0745SJose E. Roman 1098*2e1d0745SJose E. Roman PetscCall(PetscSFGetGraph(sfPoint, &nroots, &nleaves, &ilocal, &iremote)); 1099*2e1d0745SJose E. Roman if (nleaves < 0) { 1100*2e1d0745SJose E. Roman PetscCall(PetscObjectReference((PetscObject)sfPoint)); 1101*2e1d0745SJose E. Roman } else { 1102*2e1d0745SJose E. Roman PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)sfPoint), &sfPoint)); 1103*2e1d0745SJose E. Roman PetscCall(PetscSFSetGraph(sfPoint, nroots + vExtra, nleaves, (PetscInt *)ilocal, PETSC_COPY_VALUES, (PetscSFNode *)iremote, PETSC_COPY_VALUES)); 1104*2e1d0745SJose E. Roman } 1105*2e1d0745SJose E. Roman } else { 1106*2e1d0745SJose E. Roman PetscCall(PetscObjectReference((PetscObject)sfPoint)); 1107*2e1d0745SJose E. Roman } 1108*2e1d0745SJose E. Roman /* Number all vertices */ 1109*2e1d0745SJose E. Roman PetscCall(DMPlexCreateNumbering_Plex(dm, vStart, vEnd + vExtra, 0, NULL, sfPoint, &globalVertexNumbers)); 1110*2e1d0745SJose E. Roman PetscCall(PetscSFDestroy(&sfPoint)); 1111*2e1d0745SJose E. Roman /* Create cones */ 1112*2e1d0745SJose E. Roman PetscCall(ISGetIndices(globalVertexNumbers, &gvertex)); 1113*2e1d0745SJose E. Roman PetscCall(PetscMalloc1(conesSize, &vertices)); 1114*2e1d0745SJose E. Roman for (cell = cStart, v = 0; cell < cEnd; ++cell) { 1115*2e1d0745SJose E. Roman PetscInt *closure = NULL; 1116*2e1d0745SJose E. Roman PetscInt closureSize, Nc = 0, p, value = -1; 1117*2e1d0745SJose E. Roman PetscBool replace; 1118*2e1d0745SJose E. Roman 1119*2e1d0745SJose E. Roman if (gcell[cell] < 0) continue; 1120*2e1d0745SJose E. Roman if (cutLabel) PetscCall(DMLabelGetValue(cutLabel, cell, &value)); 1121*2e1d0745SJose E. Roman replace = (value == 2) ? PETSC_TRUE : PETSC_FALSE; 1122*2e1d0745SJose E. Roman PetscCall(DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure)); 1123*2e1d0745SJose E. Roman for (p = 0; p < closureSize * 2; p += 2) { 1124*2e1d0745SJose E. Roman if ((closure[p] >= vStart) && (closure[p] < vEnd)) closure[Nc++] = closure[p]; 1125*2e1d0745SJose E. Roman } 1126*2e1d0745SJose E. Roman PetscCall(DMPlexReorderCell(dm, cell, closure)); 1127*2e1d0745SJose E. Roman for (p = 0; p < Nc; ++p) { 1128*2e1d0745SJose E. Roman PetscInt nv, gv = gvertex[closure[p] - vStart]; 1129*2e1d0745SJose E. Roman 1130*2e1d0745SJose E. Roman if (replace) { 1131*2e1d0745SJose E. Roman PetscCall(PetscFindInt(closure[p], vExtra, cutverts, &nv)); 1132*2e1d0745SJose E. Roman if (nv >= 0) gv = gvertex[vEnd - vStart + nv]; 1133*2e1d0745SJose E. Roman } 1134*2e1d0745SJose E. Roman vertices[v++] = gv < 0 ? -(gv + 1) : gv; 1135*2e1d0745SJose E. Roman } 1136*2e1d0745SJose E. Roman PetscCall(DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure)); 1137*2e1d0745SJose E. Roman } 1138*2e1d0745SJose E. Roman PetscCall(ISRestoreIndices(globalVertexNumbers, &gvertex)); 1139*2e1d0745SJose E. Roman PetscCall(ISDestroy(&globalVertexNumbers)); 1140*2e1d0745SJose E. Roman PetscCall(ISRestoreIndices(globalCellNumbers, &gcell)); 1141*2e1d0745SJose E. Roman if (cutvertices) PetscCall(ISRestoreIndices(cutvertices, &cutverts)); 1142*2e1d0745SJose E. Roman PetscCall(ISDestroy(&cutvertices)); 1143*2e1d0745SJose E. Roman PetscCall(DMLabelDestroy(&cutVertexLabel)); 1144*2e1d0745SJose E. Roman PetscCheck(v == conesSize, PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of cell vertices %" PetscInt_FMT " != %" PetscInt_FMT, v, conesSize); 1145*2e1d0745SJose E. Roman PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), conesSize, vertices, PETSC_OWN_POINTER, cellIS)); 1146*2e1d0745SJose E. Roman PetscCall(PetscLayoutSetBlockSize((*cellIS)->map, *numCorners)); 1147*2e1d0745SJose E. Roman PetscCall(PetscObjectSetName((PetscObject)*cellIS, "cells")); 1148*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 1149*2e1d0745SJose E. Roman } 1150*2e1d0745SJose E. Roman 1151*2e1d0745SJose E. Roman static PetscErrorCode DMPlexTopologyView_HDF5_XDMF_Private(DM dm, IS globalCellNumbers, PetscViewer viewer) 1152*2e1d0745SJose E. Roman { 1153*2e1d0745SJose E. Roman DM cdm; 1154*2e1d0745SJose E. Roman DMLabel depthLabel, ctLabel; 1155*2e1d0745SJose E. Roman IS cellIS; 1156*2e1d0745SJose E. Roman PetscInt dim, depth, cellHeight, c, n = 0; 1157*2e1d0745SJose E. Roman 1158*2e1d0745SJose E. Roman PetscFunctionBegin; 1159*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, "/viz")); 1160*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5WriteGroup(viewer, NULL)); 1161*2e1d0745SJose E. Roman 1162*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 1163*2e1d0745SJose E. Roman PetscCall(DMGetDimension(dm, &dim)); 1164*2e1d0745SJose E. Roman PetscCall(DMPlexGetDepth(dm, &depth)); 1165*2e1d0745SJose E. Roman PetscCall(DMGetCoordinateDM(dm, &cdm)); 1166*2e1d0745SJose E. Roman PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 1167*2e1d0745SJose E. Roman PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 1168*2e1d0745SJose E. Roman PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel)); 1169*2e1d0745SJose E. Roman for (c = 0; c < DM_NUM_POLYTOPES; ++c) { 1170*2e1d0745SJose E. Roman const DMPolytopeType ict = (DMPolytopeType)c; 1171*2e1d0745SJose E. Roman PetscInt pStart, pEnd, dep, numCorners; 1172*2e1d0745SJose E. Roman PetscBool output = PETSC_FALSE, doOutput; 1173*2e1d0745SJose E. Roman 1174*2e1d0745SJose E. Roman if (ict == DM_POLYTOPE_FV_GHOST) continue; 1175*2e1d0745SJose E. Roman PetscCall(DMLabelGetStratumBounds(ctLabel, ict, &pStart, &pEnd)); 1176*2e1d0745SJose E. Roman if (pStart >= 0) { 1177*2e1d0745SJose E. Roman PetscCall(DMLabelGetValue(depthLabel, pStart, &dep)); 1178*2e1d0745SJose E. Roman if (dep == depth - cellHeight) output = PETSC_TRUE; 1179*2e1d0745SJose E. Roman } 1180*2e1d0745SJose E. Roman PetscCallMPI(MPIU_Allreduce(&output, &doOutput, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)dm))); 1181*2e1d0745SJose E. Roman if (!doOutput) continue; 1182*2e1d0745SJose E. Roman PetscCall(CreateConesIS_Private(dm, pStart, pEnd, globalCellNumbers, &numCorners, &cellIS)); 1183*2e1d0745SJose E. Roman if (!n) { 1184*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, "/viz/topology")); 1185*2e1d0745SJose E. Roman } else { 1186*2e1d0745SJose E. Roman char group[PETSC_MAX_PATH_LEN]; 1187*2e1d0745SJose E. Roman 1188*2e1d0745SJose E. Roman PetscCall(PetscSNPrintf(group, PETSC_MAX_PATH_LEN, "/viz/topology_%" PetscInt_FMT, n)); 1189*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, group)); 1190*2e1d0745SJose E. Roman } 1191*2e1d0745SJose E. Roman PetscCall(ISView(cellIS, viewer)); 1192*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5WriteObjectAttribute(viewer, (PetscObject)cellIS, "cell_corners", PETSC_INT, (void *)&numCorners)); 1193*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5WriteObjectAttribute(viewer, (PetscObject)cellIS, "cell_dim", PETSC_INT, (void *)&dim)); 1194*2e1d0745SJose E. Roman PetscCall(ISDestroy(&cellIS)); 1195*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 1196*2e1d0745SJose E. Roman ++n; 1197*2e1d0745SJose E. Roman } 1198*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 1199*2e1d0745SJose E. Roman } 1200*2e1d0745SJose E. Roman 1201*2e1d0745SJose E. Roman static PetscErrorCode DMPlexCoordinatesView_HDF5_Legacy_Private(DM dm, PetscViewer viewer) 1202*2e1d0745SJose E. Roman { 1203*2e1d0745SJose E. Roman DM cdm; 1204*2e1d0745SJose E. Roman Vec coordinates, newcoords; 1205*2e1d0745SJose E. Roman PetscReal lengthScale; 1206*2e1d0745SJose E. Roman PetscInt m, M, bs; 1207*2e1d0745SJose E. Roman 1208*2e1d0745SJose E. Roman PetscFunctionBegin; 1209*2e1d0745SJose E. Roman PetscCall(DMPlexGetScale(dm, PETSC_UNIT_LENGTH, &lengthScale)); 1210*2e1d0745SJose E. Roman PetscCall(DMGetCoordinateDM(dm, &cdm)); 1211*2e1d0745SJose E. Roman PetscCall(DMGetCoordinates(dm, &coordinates)); 1212*2e1d0745SJose E. Roman PetscCall(VecCreate(PetscObjectComm((PetscObject)coordinates), &newcoords)); 1213*2e1d0745SJose E. Roman PetscCall(PetscObjectSetName((PetscObject)newcoords, "vertices")); 1214*2e1d0745SJose E. Roman PetscCall(VecGetSize(coordinates, &M)); 1215*2e1d0745SJose E. Roman PetscCall(VecGetLocalSize(coordinates, &m)); 1216*2e1d0745SJose E. Roman PetscCall(VecSetSizes(newcoords, m, M)); 1217*2e1d0745SJose E. Roman PetscCall(VecGetBlockSize(coordinates, &bs)); 1218*2e1d0745SJose E. Roman PetscCall(VecSetBlockSize(newcoords, bs)); 1219*2e1d0745SJose E. Roman PetscCall(VecSetType(newcoords, VECSTANDARD)); 1220*2e1d0745SJose E. Roman PetscCall(VecCopy(coordinates, newcoords)); 1221*2e1d0745SJose E. Roman PetscCall(VecScale(newcoords, lengthScale)); 1222*2e1d0745SJose E. Roman /* Did not use DMGetGlobalVector() in order to bypass default group assignment */ 1223*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, "/geometry")); 1224*2e1d0745SJose E. Roman PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_NATIVE)); 1225*2e1d0745SJose E. Roman PetscCall(VecView(newcoords, viewer)); 1226*2e1d0745SJose E. Roman PetscCall(PetscViewerPopFormat(viewer)); 1227*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 1228*2e1d0745SJose E. Roman PetscCall(VecDestroy(&newcoords)); 1229*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 1230*2e1d0745SJose E. Roman } 1231*2e1d0745SJose E. Roman 1232*2e1d0745SJose E. Roman PetscErrorCode DMPlexCoordinatesView_HDF5_Internal(DM dm, PetscViewer viewer) 1233*2e1d0745SJose E. Roman { 1234*2e1d0745SJose E. Roman DM cdm; 1235*2e1d0745SJose E. Roman Vec coords, newcoords; 1236*2e1d0745SJose E. Roman PetscInt m, M, bs; 1237*2e1d0745SJose E. Roman PetscReal lengthScale; 1238*2e1d0745SJose E. Roman PetscBool viewSection = PETSC_TRUE; 1239*2e1d0745SJose E. Roman const char *topologydm_name, *coordinatedm_name, *coordinates_name; 1240*2e1d0745SJose E. Roman 1241*2e1d0745SJose E. Roman PetscFunctionBegin; 1242*2e1d0745SJose E. Roman { 1243*2e1d0745SJose E. Roman PetscViewerFormat format; 1244*2e1d0745SJose E. Roman DMPlexStorageVersion version; 1245*2e1d0745SJose E. Roman 1246*2e1d0745SJose E. Roman PetscCall(PetscViewerGetFormat(viewer, &format)); 1247*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5GetDMPlexStorageVersionWriting(viewer, &version)); 1248*2e1d0745SJose E. Roman if (!DMPlexStorageVersionGE(version, 2, 0, 0) || format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) { 1249*2e1d0745SJose E. Roman PetscCall(DMPlexCoordinatesView_HDF5_Legacy_Private(dm, viewer)); 1250*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 1251*2e1d0745SJose E. Roman } 1252*2e1d0745SJose E. Roman } 1253*2e1d0745SJose E. Roman /* since 2.0.0 */ 1254*2e1d0745SJose E. Roman PetscCall(PetscOptionsGetBool(NULL, dm->hdr.prefix, "-dm_plex_view_coordinate_section", &viewSection, NULL)); 1255*2e1d0745SJose E. Roman PetscCall(DMGetCoordinateDM(dm, &cdm)); 1256*2e1d0745SJose E. Roman PetscCall(DMGetCoordinates(dm, &coords)); 1257*2e1d0745SJose E. Roman PetscCall(PetscObjectGetName((PetscObject)cdm, &coordinatedm_name)); 1258*2e1d0745SJose E. Roman PetscCall(PetscObjectGetName((PetscObject)coords, &coordinates_name)); 1259*2e1d0745SJose E. Roman PetscCall(DMPlexGetHDF5Name_Private(dm, &topologydm_name)); 1260*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, "topologies")); 1261*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, topologydm_name)); 1262*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5WriteAttribute(viewer, NULL, "coordinateDMName", PETSC_STRING, coordinatedm_name)); 1263*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5WriteAttribute(viewer, NULL, "coordinatesName", PETSC_STRING, coordinates_name)); 1264*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 1265*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 1266*2e1d0745SJose E. Roman if (viewSection) PetscCall(DMPlexSectionView(dm, viewer, cdm)); 1267*2e1d0745SJose E. Roman PetscCall(VecCreate(PetscObjectComm((PetscObject)coords), &newcoords)); 1268*2e1d0745SJose E. Roman PetscCall(PetscObjectSetName((PetscObject)newcoords, coordinates_name)); 1269*2e1d0745SJose E. Roman PetscCall(VecGetSize(coords, &M)); 1270*2e1d0745SJose E. Roman PetscCall(VecGetLocalSize(coords, &m)); 1271*2e1d0745SJose E. Roman PetscCall(VecSetSizes(newcoords, m, M)); 1272*2e1d0745SJose E. Roman PetscCall(VecGetBlockSize(coords, &bs)); 1273*2e1d0745SJose E. Roman PetscCall(VecSetBlockSize(newcoords, bs)); 1274*2e1d0745SJose E. Roman PetscCall(VecSetType(newcoords, VECSTANDARD)); 1275*2e1d0745SJose E. Roman PetscCall(VecCopy(coords, newcoords)); 1276*2e1d0745SJose E. Roman PetscCall(DMPlexGetScale(dm, PETSC_UNIT_LENGTH, &lengthScale)); 1277*2e1d0745SJose E. Roman PetscCall(VecScale(newcoords, lengthScale)); 1278*2e1d0745SJose E. Roman PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_NATIVE)); 1279*2e1d0745SJose E. Roman PetscCall(DMPlexGlobalVectorView(dm, viewer, cdm, newcoords)); 1280*2e1d0745SJose E. Roman PetscCall(PetscViewerPopFormat(viewer)); 1281*2e1d0745SJose E. Roman PetscCall(VecDestroy(&newcoords)); 1282*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 1283*2e1d0745SJose E. Roman } 1284*2e1d0745SJose E. Roman 1285*2e1d0745SJose E. Roman static PetscErrorCode DMPlexCoordinatesView_HDF5_XDMF_Private(DM dm, PetscViewer viewer) 1286*2e1d0745SJose E. Roman { 1287*2e1d0745SJose E. Roman DM cdm; 1288*2e1d0745SJose E. Roman Vec coordinatesLocal, newcoords; 1289*2e1d0745SJose E. Roman PetscSection cSection, cGlobalSection; 1290*2e1d0745SJose E. Roman PetscScalar *coords, *ncoords; 1291*2e1d0745SJose E. Roman DMLabel cutLabel, cutVertexLabel = NULL; 1292*2e1d0745SJose E. Roman const PetscReal *L; 1293*2e1d0745SJose E. Roman PetscReal lengthScale; 1294*2e1d0745SJose E. Roman PetscInt vStart, vEnd, v, bs, N, coordSize, dof, off, d; 1295*2e1d0745SJose E. Roman PetscBool localized, embedded; 1296*2e1d0745SJose E. Roman 1297*2e1d0745SJose E. Roman PetscFunctionBegin; 1298*2e1d0745SJose E. Roman PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 1299*2e1d0745SJose E. Roman PetscCall(DMPlexGetScale(dm, PETSC_UNIT_LENGTH, &lengthScale)); 1300*2e1d0745SJose E. Roman PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal)); 1301*2e1d0745SJose E. Roman PetscCall(VecGetBlockSize(coordinatesLocal, &bs)); 1302*2e1d0745SJose E. Roman PetscCall(DMGetCoordinatesLocalized(dm, &localized)); 1303*2e1d0745SJose E. Roman if (localized == PETSC_FALSE) PetscFunctionReturn(PETSC_SUCCESS); 1304*2e1d0745SJose E. Roman PetscCall(DMGetPeriodicity(dm, NULL, NULL, &L)); 1305*2e1d0745SJose E. Roman PetscCall(DMGetCoordinateDM(dm, &cdm)); 1306*2e1d0745SJose E. Roman PetscCall(DMGetLocalSection(cdm, &cSection)); 1307*2e1d0745SJose E. Roman PetscCall(DMGetGlobalSection(cdm, &cGlobalSection)); 1308*2e1d0745SJose E. Roman PetscCall(DMGetLabel(dm, "periodic_cut", &cutLabel)); 1309*2e1d0745SJose E. Roman N = 0; 1310*2e1d0745SJose E. Roman 1311*2e1d0745SJose E. Roman PetscCall(DMPlexCreateCutVertexLabel_Private(dm, cutLabel, &cutVertexLabel)); 1312*2e1d0745SJose E. Roman PetscCall(VecCreate(PetscObjectComm((PetscObject)dm), &newcoords)); 1313*2e1d0745SJose E. Roman PetscCall(PetscSectionGetDof(cSection, vStart, &dof)); 1314*2e1d0745SJose E. Roman PetscCall(PetscPrintf(PETSC_COMM_SELF, "DOF: %" PetscInt_FMT "\n", dof)); 1315*2e1d0745SJose E. Roman embedded = (PetscBool)(L && dof == 2 && !cutLabel); 1316*2e1d0745SJose E. Roman if (cutVertexLabel) { 1317*2e1d0745SJose E. Roman PetscCall(DMLabelGetStratumSize(cutVertexLabel, 1, &v)); 1318*2e1d0745SJose E. Roman N += dof * v; 1319*2e1d0745SJose E. Roman } 1320*2e1d0745SJose E. Roman for (v = vStart; v < vEnd; ++v) { 1321*2e1d0745SJose E. Roman PetscCall(PetscSectionGetDof(cGlobalSection, v, &dof)); 1322*2e1d0745SJose E. Roman if (dof < 0) continue; 1323*2e1d0745SJose E. Roman if (embedded) N += dof + 1; 1324*2e1d0745SJose E. Roman else N += dof; 1325*2e1d0745SJose E. Roman } 1326*2e1d0745SJose E. Roman if (embedded) PetscCall(VecSetBlockSize(newcoords, bs + 1)); 1327*2e1d0745SJose E. Roman else PetscCall(VecSetBlockSize(newcoords, bs)); 1328*2e1d0745SJose E. Roman PetscCall(VecSetSizes(newcoords, N, PETSC_DETERMINE)); 1329*2e1d0745SJose E. Roman PetscCall(VecSetType(newcoords, VECSTANDARD)); 1330*2e1d0745SJose E. Roman PetscCall(VecGetArray(coordinatesLocal, &coords)); 1331*2e1d0745SJose E. Roman PetscCall(VecGetArray(newcoords, &ncoords)); 1332*2e1d0745SJose E. Roman coordSize = 0; 1333*2e1d0745SJose E. Roman for (v = vStart; v < vEnd; ++v) { 1334*2e1d0745SJose E. Roman PetscCall(PetscSectionGetDof(cGlobalSection, v, &dof)); 1335*2e1d0745SJose E. Roman PetscCall(PetscSectionGetOffset(cSection, v, &off)); 1336*2e1d0745SJose E. Roman if (dof < 0) continue; 1337*2e1d0745SJose E. Roman if (embedded) { 1338*2e1d0745SJose E. Roman if (L && (L[0] > 0.0) && (L[1] > 0.0)) { 1339*2e1d0745SJose E. Roman PetscReal theta, phi, r, R; 1340*2e1d0745SJose E. Roman /* XY-periodic */ 1341*2e1d0745SJose E. Roman /* Suppose its an y-z circle, then 1342*2e1d0745SJose E. Roman \hat r = (0, cos(th), sin(th)) \hat x = (1, 0, 0) 1343*2e1d0745SJose E. Roman and the circle in that plane is 1344*2e1d0745SJose E. Roman \hat r cos(phi) + \hat x sin(phi) */ 1345*2e1d0745SJose E. Roman theta = 2.0 * PETSC_PI * PetscRealPart(coords[off + 1]) / L[1]; 1346*2e1d0745SJose E. Roman phi = 2.0 * PETSC_PI * PetscRealPart(coords[off + 0]) / L[0]; 1347*2e1d0745SJose E. Roman r = L[0] / (2.0 * PETSC_PI * 2.0 * L[1]); 1348*2e1d0745SJose E. Roman R = L[1] / (2.0 * PETSC_PI); 1349*2e1d0745SJose E. Roman ncoords[coordSize++] = PetscSinReal(phi) * r; 1350*2e1d0745SJose E. Roman ncoords[coordSize++] = -PetscCosReal(theta) * (R + r * PetscCosReal(phi)); 1351*2e1d0745SJose E. Roman ncoords[coordSize++] = PetscSinReal(theta) * (R + r * PetscCosReal(phi)); 1352*2e1d0745SJose E. Roman } else if (L && (L[0] > 0.0)) { 1353*2e1d0745SJose E. Roman /* X-periodic */ 1354*2e1d0745SJose E. Roman ncoords[coordSize++] = -PetscCosReal(2.0 * PETSC_PI * PetscRealPart(coords[off + 0]) / L[0]) * (L[0] / (2.0 * PETSC_PI)); 1355*2e1d0745SJose E. Roman ncoords[coordSize++] = coords[off + 1]; 1356*2e1d0745SJose E. Roman ncoords[coordSize++] = PetscSinReal(2.0 * PETSC_PI * PetscRealPart(coords[off + 0]) / L[0]) * (L[0] / (2.0 * PETSC_PI)); 1357*2e1d0745SJose E. Roman } else if (L && (L[1] > 0.0)) { 1358*2e1d0745SJose E. Roman /* Y-periodic */ 1359*2e1d0745SJose E. Roman ncoords[coordSize++] = coords[off + 0]; 1360*2e1d0745SJose E. Roman ncoords[coordSize++] = PetscSinReal(2.0 * PETSC_PI * PetscRealPart(coords[off + 1]) / L[1]) * (L[1] / (2.0 * PETSC_PI)); 1361*2e1d0745SJose E. Roman ncoords[coordSize++] = -PetscCosReal(2.0 * PETSC_PI * PetscRealPart(coords[off + 1]) / L[1]) * (L[1] / (2.0 * PETSC_PI)); 1362*2e1d0745SJose E. Roman #if 0 1363*2e1d0745SJose E. Roman } else if ((bd[0] == DM_BOUNDARY_TWIST)) { 1364*2e1d0745SJose E. Roman PetscReal phi, r, R; 1365*2e1d0745SJose E. Roman /* Mobius strip */ 1366*2e1d0745SJose E. Roman /* Suppose its an x-z circle, then 1367*2e1d0745SJose E. Roman \hat r = (-cos(phi), 0, sin(phi)) \hat y = (0, 1, 0) 1368*2e1d0745SJose E. Roman and in that plane we rotate by pi as we go around the circle 1369*2e1d0745SJose E. Roman \hat r cos(phi/2) + \hat y sin(phi/2) */ 1370*2e1d0745SJose E. Roman phi = 2.0*PETSC_PI*PetscRealPart(coords[off+0])/L[0]; 1371*2e1d0745SJose E. Roman R = L[0]; 1372*2e1d0745SJose E. Roman r = PetscRealPart(coords[off+1]) - L[1]/2.0; 1373*2e1d0745SJose E. Roman ncoords[coordSize++] = -PetscCosReal(phi) * (R + r * PetscCosReal(phi/2.0)); 1374*2e1d0745SJose E. Roman ncoords[coordSize++] = PetscSinReal(phi/2.0) * r; 1375*2e1d0745SJose E. Roman ncoords[coordSize++] = PetscSinReal(phi) * (R + r * PetscCosReal(phi/2.0)); 1376*2e1d0745SJose E. Roman #endif 1377*2e1d0745SJose E. Roman } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Cannot handle periodicity in this domain"); 1378*2e1d0745SJose E. Roman } else { 1379*2e1d0745SJose E. Roman for (d = 0; d < dof; ++d, ++coordSize) ncoords[coordSize] = coords[off + d]; 1380*2e1d0745SJose E. Roman } 1381*2e1d0745SJose E. Roman } 1382*2e1d0745SJose E. Roman if (cutVertexLabel) { 1383*2e1d0745SJose E. Roman IS vertices; 1384*2e1d0745SJose E. Roman const PetscInt *verts; 1385*2e1d0745SJose E. Roman PetscInt n; 1386*2e1d0745SJose E. Roman 1387*2e1d0745SJose E. Roman PetscCall(DMLabelGetStratumIS(cutVertexLabel, 1, &vertices)); 1388*2e1d0745SJose E. Roman if (vertices) { 1389*2e1d0745SJose E. Roman PetscCall(ISGetIndices(vertices, &verts)); 1390*2e1d0745SJose E. Roman PetscCall(ISGetLocalSize(vertices, &n)); 1391*2e1d0745SJose E. Roman for (v = 0; v < n; ++v) { 1392*2e1d0745SJose E. Roman PetscCall(PetscSectionGetDof(cSection, verts[v], &dof)); 1393*2e1d0745SJose E. Roman PetscCall(PetscSectionGetOffset(cSection, verts[v], &off)); 1394*2e1d0745SJose E. Roman for (d = 0; d < dof; ++d) ncoords[coordSize++] = coords[off + d] + ((L[d] > 0.) ? L[d] : 0.0); 1395*2e1d0745SJose E. Roman } 1396*2e1d0745SJose E. Roman PetscCall(ISRestoreIndices(vertices, &verts)); 1397*2e1d0745SJose E. Roman PetscCall(ISDestroy(&vertices)); 1398*2e1d0745SJose E. Roman } 1399*2e1d0745SJose E. Roman } 1400*2e1d0745SJose E. Roman PetscCheck(coordSize == N, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched sizes: %" PetscInt_FMT " != %" PetscInt_FMT, coordSize, N); 1401*2e1d0745SJose E. Roman PetscCall(DMLabelDestroy(&cutVertexLabel)); 1402*2e1d0745SJose E. Roman PetscCall(VecRestoreArray(coordinatesLocal, &coords)); 1403*2e1d0745SJose E. Roman PetscCall(VecRestoreArray(newcoords, &ncoords)); 1404*2e1d0745SJose E. Roman PetscCall(PetscObjectSetName((PetscObject)newcoords, "vertices")); 1405*2e1d0745SJose E. Roman PetscCall(VecScale(newcoords, lengthScale)); 1406*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, "/viz")); 1407*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5WriteGroup(viewer, NULL)); 1408*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 1409*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, "/viz/geometry")); 1410*2e1d0745SJose E. Roman PetscCall(VecView(newcoords, viewer)); 1411*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 1412*2e1d0745SJose E. Roman PetscCall(VecDestroy(&newcoords)); 1413*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 1414*2e1d0745SJose E. Roman } 1415*2e1d0745SJose E. Roman 1416*2e1d0745SJose E. Roman PetscErrorCode DMPlexLabelsView_HDF5_Internal(DM dm, IS globalPointNumbers, PetscViewer viewer) 1417*2e1d0745SJose E. Roman { 1418*2e1d0745SJose E. Roman const char *topologydm_name; 1419*2e1d0745SJose E. Roman const PetscInt *gpoint; 1420*2e1d0745SJose E. Roman PetscInt numLabels; 1421*2e1d0745SJose E. Roman PetscBool omitCelltypes = PETSC_FALSE; 1422*2e1d0745SJose E. Roman DMPlexStorageVersion version; 1423*2e1d0745SJose E. Roman char group[PETSC_MAX_PATH_LEN]; 1424*2e1d0745SJose E. Roman 1425*2e1d0745SJose E. Roman PetscFunctionBegin; 1426*2e1d0745SJose E. Roman PetscCall(PetscOptionsGetBool(NULL, dm->hdr.prefix, "-dm_plex_omit_celltypes", &omitCelltypes, NULL)); 1427*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5GetDMPlexStorageVersionWriting(viewer, &version)); 1428*2e1d0745SJose E. Roman PetscCall(ISGetIndices(globalPointNumbers, &gpoint)); 1429*2e1d0745SJose E. Roman PetscCall(DMPlexGetHDF5Name_Private(dm, &topologydm_name)); 1430*2e1d0745SJose E. Roman if (DMPlexStorageVersionGE(version, 2, 0, 0)) { 1431*2e1d0745SJose E. Roman PetscCall(PetscSNPrintf(group, sizeof(group), "topologies/%s/labels", topologydm_name)); 1432*2e1d0745SJose E. Roman } else { 1433*2e1d0745SJose E. Roman PetscCall(PetscStrncpy(group, "/labels", sizeof(group))); 1434*2e1d0745SJose E. Roman } 1435*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, group)); 1436*2e1d0745SJose E. Roman PetscCall(DMGetNumLabels(dm, &numLabels)); 1437*2e1d0745SJose E. Roman for (PetscInt l = 0; l < numLabels; ++l) { 1438*2e1d0745SJose E. Roman DMLabel label; 1439*2e1d0745SJose E. Roman const char *name; 1440*2e1d0745SJose E. Roman IS valueIS, pvalueIS, globalValueIS; 1441*2e1d0745SJose E. Roman const PetscInt *values; 1442*2e1d0745SJose E. Roman PetscInt numValues, v; 1443*2e1d0745SJose E. Roman PetscBool isDepth, isCelltype, output; 1444*2e1d0745SJose E. Roman 1445*2e1d0745SJose E. Roman PetscCall(DMGetLabelByNum(dm, l, &label)); 1446*2e1d0745SJose E. Roman PetscCall(PetscObjectGetName((PetscObject)label, &name)); 1447*2e1d0745SJose E. Roman PetscCall(DMGetLabelOutput(dm, name, &output)); 1448*2e1d0745SJose E. Roman PetscCall(PetscStrncmp(name, "depth", 10, &isDepth)); 1449*2e1d0745SJose E. Roman PetscCall(PetscStrncmp(name, "celltype", 10, &isCelltype)); 1450*2e1d0745SJose E. Roman // TODO Should only filter out celltype if it can be calculated 1451*2e1d0745SJose E. Roman if (isDepth || (isCelltype && omitCelltypes) || !output) continue; 1452*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, name)); 1453*2e1d0745SJose E. Roman PetscCall(DMLabelGetValueIS(label, &valueIS)); 1454*2e1d0745SJose E. Roman /* Must copy to a new IS on the global comm */ 1455*2e1d0745SJose E. Roman PetscCall(ISGetLocalSize(valueIS, &numValues)); 1456*2e1d0745SJose E. Roman PetscCall(ISGetIndices(valueIS, &values)); 1457*2e1d0745SJose E. Roman PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), numValues, values, PETSC_COPY_VALUES, &pvalueIS)); 1458*2e1d0745SJose E. Roman PetscCall(ISRestoreIndices(valueIS, &values)); 1459*2e1d0745SJose E. Roman PetscCall(ISAllGather(pvalueIS, &globalValueIS)); 1460*2e1d0745SJose E. Roman PetscCall(ISDestroy(&pvalueIS)); 1461*2e1d0745SJose E. Roman PetscCall(ISSortRemoveDups(globalValueIS)); 1462*2e1d0745SJose E. Roman PetscCall(ISGetLocalSize(globalValueIS, &numValues)); 1463*2e1d0745SJose E. Roman PetscCall(ISGetIndices(globalValueIS, &values)); 1464*2e1d0745SJose E. Roman for (v = 0; v < numValues; ++v) { 1465*2e1d0745SJose E. Roman IS stratumIS, globalStratumIS; 1466*2e1d0745SJose E. Roman const PetscInt *spoints = NULL; 1467*2e1d0745SJose E. Roman PetscInt *gspoints, n = 0, gn, p; 1468*2e1d0745SJose E. Roman const char *iname = "indices"; 1469*2e1d0745SJose E. Roman char group[PETSC_MAX_PATH_LEN]; 1470*2e1d0745SJose E. Roman 1471*2e1d0745SJose E. Roman PetscCall(PetscSNPrintf(group, sizeof(group), "%" PetscInt_FMT, values[v])); 1472*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, group)); 1473*2e1d0745SJose E. Roman PetscCall(DMLabelGetStratumIS(label, values[v], &stratumIS)); 1474*2e1d0745SJose E. Roman 1475*2e1d0745SJose E. Roman if (stratumIS) PetscCall(ISGetLocalSize(stratumIS, &n)); 1476*2e1d0745SJose E. Roman if (stratumIS) PetscCall(ISGetIndices(stratumIS, &spoints)); 1477*2e1d0745SJose E. Roman for (gn = 0, p = 0; p < n; ++p) 1478*2e1d0745SJose E. Roman if (gpoint[spoints[p]] >= 0) ++gn; 1479*2e1d0745SJose E. Roman PetscCall(PetscMalloc1(gn, &gspoints)); 1480*2e1d0745SJose E. Roman for (gn = 0, p = 0; p < n; ++p) 1481*2e1d0745SJose E. Roman if (gpoint[spoints[p]] >= 0) gspoints[gn++] = gpoint[spoints[p]]; 1482*2e1d0745SJose E. Roman if (stratumIS) PetscCall(ISRestoreIndices(stratumIS, &spoints)); 1483*2e1d0745SJose E. Roman PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), gn, gspoints, PETSC_OWN_POINTER, &globalStratumIS)); 1484*2e1d0745SJose E. Roman PetscCall(PetscObjectSetName((PetscObject)globalStratumIS, iname)); 1485*2e1d0745SJose E. Roman 1486*2e1d0745SJose E. Roman PetscCall(ISView(globalStratumIS, viewer)); 1487*2e1d0745SJose E. Roman PetscCall(ISDestroy(&globalStratumIS)); 1488*2e1d0745SJose E. Roman PetscCall(ISDestroy(&stratumIS)); 1489*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 1490*2e1d0745SJose E. Roman } 1491*2e1d0745SJose E. Roman PetscCall(ISRestoreIndices(globalValueIS, &values)); 1492*2e1d0745SJose E. Roman PetscCall(ISDestroy(&globalValueIS)); 1493*2e1d0745SJose E. Roman PetscCall(ISDestroy(&valueIS)); 1494*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 1495*2e1d0745SJose E. Roman } 1496*2e1d0745SJose E. Roman PetscCall(ISRestoreIndices(globalPointNumbers, &gpoint)); 1497*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 1498*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 1499*2e1d0745SJose E. Roman } 1500*2e1d0745SJose E. Roman 1501*2e1d0745SJose E. Roman /* We only write cells and vertices. Does this screw up parallel reading? */ 1502*2e1d0745SJose E. Roman PetscErrorCode DMPlexView_HDF5_Internal(DM dm, PetscViewer viewer) 1503*2e1d0745SJose E. Roman { 1504*2e1d0745SJose E. Roman IS globalPointNumbers; 1505*2e1d0745SJose E. Roman PetscViewerFormat format; 1506*2e1d0745SJose E. Roman PetscBool viz_geom = PETSC_FALSE, xdmf_topo = PETSC_FALSE, petsc_topo = PETSC_FALSE; 1507*2e1d0745SJose E. Roman 1508*2e1d0745SJose E. Roman PetscFunctionBegin; 1509*2e1d0745SJose E. Roman PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbers)); 1510*2e1d0745SJose E. Roman PetscCall(DMPlexCoordinatesView_HDF5_Internal(dm, viewer)); 1511*2e1d0745SJose E. Roman 1512*2e1d0745SJose E. Roman PetscCall(PetscViewerGetFormat(viewer, &format)); 1513*2e1d0745SJose E. Roman switch (format) { 1514*2e1d0745SJose E. Roman case PETSC_VIEWER_HDF5_VIZ: 1515*2e1d0745SJose E. Roman viz_geom = PETSC_TRUE; 1516*2e1d0745SJose E. Roman xdmf_topo = PETSC_TRUE; 1517*2e1d0745SJose E. Roman break; 1518*2e1d0745SJose E. Roman case PETSC_VIEWER_HDF5_XDMF: 1519*2e1d0745SJose E. Roman xdmf_topo = PETSC_TRUE; 1520*2e1d0745SJose E. Roman break; 1521*2e1d0745SJose E. Roman case PETSC_VIEWER_HDF5_PETSC: 1522*2e1d0745SJose E. Roman petsc_topo = PETSC_TRUE; 1523*2e1d0745SJose E. Roman break; 1524*2e1d0745SJose E. Roman case PETSC_VIEWER_DEFAULT: 1525*2e1d0745SJose E. Roman case PETSC_VIEWER_NATIVE: 1526*2e1d0745SJose E. Roman viz_geom = PETSC_TRUE; 1527*2e1d0745SJose E. Roman xdmf_topo = PETSC_TRUE; 1528*2e1d0745SJose E. Roman petsc_topo = PETSC_TRUE; 1529*2e1d0745SJose E. Roman break; 1530*2e1d0745SJose E. Roman default: 1531*2e1d0745SJose E. Roman SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]); 1532*2e1d0745SJose E. Roman } 1533*2e1d0745SJose E. Roman 1534*2e1d0745SJose E. Roman if (viz_geom) PetscCall(DMPlexCoordinatesView_HDF5_XDMF_Private(dm, viewer)); 1535*2e1d0745SJose E. Roman if (xdmf_topo) PetscCall(DMPlexTopologyView_HDF5_XDMF_Private(dm, globalPointNumbers, viewer)); 1536*2e1d0745SJose E. Roman if (petsc_topo) { 1537*2e1d0745SJose E. Roman PetscBool viewLabels = PETSC_TRUE; 1538*2e1d0745SJose E. Roman 1539*2e1d0745SJose E. Roman PetscCall(DMPlexTopologyView_HDF5_Internal(dm, globalPointNumbers, viewer)); 1540*2e1d0745SJose E. Roman PetscCall(PetscOptionsGetBool(NULL, dm->hdr.prefix, "-dm_plex_view_labels", &viewLabels, NULL)); 1541*2e1d0745SJose E. Roman if (viewLabels) PetscCall(DMPlexLabelsView_HDF5_Internal(dm, globalPointNumbers, viewer)); 1542*2e1d0745SJose E. Roman } 1543*2e1d0745SJose E. Roman 1544*2e1d0745SJose E. Roman PetscCall(ISDestroy(&globalPointNumbers)); 1545*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 1546*2e1d0745SJose E. Roman } 1547*2e1d0745SJose E. Roman 1548*2e1d0745SJose E. Roman PetscErrorCode DMPlexSectionView_HDF5_Internal(DM dm, PetscViewer viewer, DM sectiondm) 1549*2e1d0745SJose E. Roman { 1550*2e1d0745SJose E. Roman MPI_Comm comm; 1551*2e1d0745SJose E. Roman const char *topologydm_name; 1552*2e1d0745SJose E. Roman const char *sectiondm_name; 1553*2e1d0745SJose E. Roman PetscSection gsection; 1554*2e1d0745SJose E. Roman 1555*2e1d0745SJose E. Roman PetscFunctionBegin; 1556*2e1d0745SJose E. Roman PetscCall(PetscObjectGetComm((PetscObject)sectiondm, &comm)); 1557*2e1d0745SJose E. Roman PetscCall(DMPlexGetHDF5Name_Private(dm, &topologydm_name)); 1558*2e1d0745SJose E. Roman PetscCall(PetscObjectGetName((PetscObject)sectiondm, §iondm_name)); 1559*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, "topologies")); 1560*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, topologydm_name)); 1561*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, "dms")); 1562*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, sectiondm_name)); 1563*2e1d0745SJose E. Roman PetscCall(DMGetGlobalSection(sectiondm, &gsection)); 1564*2e1d0745SJose E. Roman /* Save raw section */ 1565*2e1d0745SJose E. Roman PetscCall(PetscSectionView(gsection, viewer)); 1566*2e1d0745SJose E. Roman /* Save plex wrapper */ 1567*2e1d0745SJose E. Roman { 1568*2e1d0745SJose E. Roman PetscInt pStart, pEnd, p, n; 1569*2e1d0745SJose E. Roman IS globalPointNumbers; 1570*2e1d0745SJose E. Roman const PetscInt *gpoints; 1571*2e1d0745SJose E. Roman IS orderIS; 1572*2e1d0745SJose E. Roman PetscInt *order; 1573*2e1d0745SJose E. Roman 1574*2e1d0745SJose E. Roman PetscCall(PetscSectionGetChart(gsection, &pStart, &pEnd)); 1575*2e1d0745SJose E. Roman PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbers)); 1576*2e1d0745SJose E. Roman PetscCall(ISGetIndices(globalPointNumbers, &gpoints)); 1577*2e1d0745SJose E. Roman for (p = pStart, n = 0; p < pEnd; ++p) 1578*2e1d0745SJose E. Roman if (gpoints[p] >= 0) n++; 1579*2e1d0745SJose E. Roman /* "order" is an array of global point numbers. 1580*2e1d0745SJose E. Roman When loading, it is used with topology/order array 1581*2e1d0745SJose E. Roman to match section points with plex topology points. */ 1582*2e1d0745SJose E. Roman PetscCall(PetscMalloc1(n, &order)); 1583*2e1d0745SJose E. Roman for (p = pStart, n = 0; p < pEnd; ++p) 1584*2e1d0745SJose E. Roman if (gpoints[p] >= 0) order[n++] = gpoints[p]; 1585*2e1d0745SJose E. Roman PetscCall(ISRestoreIndices(globalPointNumbers, &gpoints)); 1586*2e1d0745SJose E. Roman PetscCall(ISDestroy(&globalPointNumbers)); 1587*2e1d0745SJose E. Roman PetscCall(ISCreateGeneral(comm, n, order, PETSC_OWN_POINTER, &orderIS)); 1588*2e1d0745SJose E. Roman PetscCall(PetscObjectSetName((PetscObject)orderIS, "order")); 1589*2e1d0745SJose E. Roman PetscCall(ISView(orderIS, viewer)); 1590*2e1d0745SJose E. Roman PetscCall(ISDestroy(&orderIS)); 1591*2e1d0745SJose E. Roman } 1592*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 1593*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 1594*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 1595*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 1596*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 1597*2e1d0745SJose E. Roman } 1598*2e1d0745SJose E. Roman 1599*2e1d0745SJose E. Roman PetscErrorCode DMPlexGlobalVectorView_HDF5_Internal(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 1600*2e1d0745SJose E. Roman { 1601*2e1d0745SJose E. Roman const char *topologydm_name; 1602*2e1d0745SJose E. Roman const char *sectiondm_name; 1603*2e1d0745SJose E. Roman const char *vec_name; 1604*2e1d0745SJose E. Roman PetscInt bs; 1605*2e1d0745SJose E. Roman 1606*2e1d0745SJose E. Roman PetscFunctionBegin; 1607*2e1d0745SJose E. Roman /* Check consistency */ 1608*2e1d0745SJose E. Roman { 1609*2e1d0745SJose E. Roman PetscSF pointsf, pointsf1; 1610*2e1d0745SJose E. Roman 1611*2e1d0745SJose E. Roman PetscCall(DMGetPointSF(dm, &pointsf)); 1612*2e1d0745SJose E. Roman PetscCall(DMGetPointSF(sectiondm, &pointsf1)); 1613*2e1d0745SJose E. Roman PetscCheck(pointsf1 == pointsf, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatching point SFs for dm and sectiondm"); 1614*2e1d0745SJose E. Roman } 1615*2e1d0745SJose E. Roman PetscCall(DMPlexGetHDF5Name_Private(dm, &topologydm_name)); 1616*2e1d0745SJose E. Roman PetscCall(PetscObjectGetName((PetscObject)sectiondm, §iondm_name)); 1617*2e1d0745SJose E. Roman PetscCall(PetscObjectGetName((PetscObject)vec, &vec_name)); 1618*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, "topologies")); 1619*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, topologydm_name)); 1620*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, "dms")); 1621*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, sectiondm_name)); 1622*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, "vecs")); 1623*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, vec_name)); 1624*2e1d0745SJose E. Roman PetscCall(VecGetBlockSize(vec, &bs)); 1625*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5WriteAttribute(viewer, NULL, "blockSize", PETSC_INT, (void *)&bs)); 1626*2e1d0745SJose E. Roman PetscCall(VecSetBlockSize(vec, 1)); 1627*2e1d0745SJose E. Roman /* VecView(vec, viewer) would call (*vec->opt->view)(vec, viewer), but, */ 1628*2e1d0745SJose E. Roman /* if vec was created with DMGet{Global, Local}Vector(), vec->opt->view */ 1629*2e1d0745SJose E. Roman /* is set to VecView_Plex, which would save vec in a predefined location. */ 1630*2e1d0745SJose E. Roman /* To save vec in where we want, we create a new Vec (temp) with */ 1631*2e1d0745SJose E. Roman /* VecCreate(), wrap the vec data in temp, and call VecView(temp, viewer). */ 1632*2e1d0745SJose E. Roman { 1633*2e1d0745SJose E. Roman Vec temp; 1634*2e1d0745SJose E. Roman const PetscScalar *array; 1635*2e1d0745SJose E. Roman PetscLayout map; 1636*2e1d0745SJose E. Roman 1637*2e1d0745SJose E. Roman PetscCall(VecCreate(PetscObjectComm((PetscObject)vec), &temp)); 1638*2e1d0745SJose E. Roman PetscCall(PetscObjectSetName((PetscObject)temp, vec_name)); 1639*2e1d0745SJose E. Roman PetscCall(VecGetLayout(vec, &map)); 1640*2e1d0745SJose E. Roman PetscCall(VecSetLayout(temp, map)); 1641*2e1d0745SJose E. Roman PetscCall(VecSetUp(temp)); 1642*2e1d0745SJose E. Roman PetscCall(VecGetArrayRead(vec, &array)); 1643*2e1d0745SJose E. Roman PetscCall(VecPlaceArray(temp, array)); 1644*2e1d0745SJose E. Roman PetscCall(VecView(temp, viewer)); 1645*2e1d0745SJose E. Roman PetscCall(VecResetArray(temp)); 1646*2e1d0745SJose E. Roman PetscCall(VecRestoreArrayRead(vec, &array)); 1647*2e1d0745SJose E. Roman PetscCall(VecDestroy(&temp)); 1648*2e1d0745SJose E. Roman } 1649*2e1d0745SJose E. Roman PetscCall(VecSetBlockSize(vec, bs)); 1650*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 1651*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 1652*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 1653*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 1654*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 1655*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 1656*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 1657*2e1d0745SJose E. Roman } 1658*2e1d0745SJose E. Roman 1659*2e1d0745SJose E. Roman PetscErrorCode DMPlexLocalVectorView_HDF5_Internal(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 1660*2e1d0745SJose E. Roman { 1661*2e1d0745SJose E. Roman MPI_Comm comm; 1662*2e1d0745SJose E. Roman const char *topologydm_name; 1663*2e1d0745SJose E. Roman const char *sectiondm_name; 1664*2e1d0745SJose E. Roman const char *vec_name; 1665*2e1d0745SJose E. Roman PetscSection section; 1666*2e1d0745SJose E. Roman PetscBool includesConstraints; 1667*2e1d0745SJose E. Roman Vec gvec; 1668*2e1d0745SJose E. Roman PetscInt m, bs; 1669*2e1d0745SJose E. Roman 1670*2e1d0745SJose E. Roman PetscFunctionBegin; 1671*2e1d0745SJose E. Roman PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 1672*2e1d0745SJose E. Roman /* Check consistency */ 1673*2e1d0745SJose E. Roman { 1674*2e1d0745SJose E. Roman PetscSF pointsf, pointsf1; 1675*2e1d0745SJose E. Roman 1676*2e1d0745SJose E. Roman PetscCall(DMGetPointSF(dm, &pointsf)); 1677*2e1d0745SJose E. Roman PetscCall(DMGetPointSF(sectiondm, &pointsf1)); 1678*2e1d0745SJose E. Roman PetscCheck(pointsf1 == pointsf, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatching point SFs for dm and sectiondm"); 1679*2e1d0745SJose E. Roman } 1680*2e1d0745SJose E. Roman PetscCall(DMPlexGetHDF5Name_Private(dm, &topologydm_name)); 1681*2e1d0745SJose E. Roman PetscCall(PetscObjectGetName((PetscObject)sectiondm, §iondm_name)); 1682*2e1d0745SJose E. Roman PetscCall(PetscObjectGetName((PetscObject)vec, &vec_name)); 1683*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, "topologies")); 1684*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, topologydm_name)); 1685*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, "dms")); 1686*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, sectiondm_name)); 1687*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, "vecs")); 1688*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, vec_name)); 1689*2e1d0745SJose E. Roman PetscCall(VecGetBlockSize(vec, &bs)); 1690*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5WriteAttribute(viewer, NULL, "blockSize", PETSC_INT, (void *)&bs)); 1691*2e1d0745SJose E. Roman PetscCall(VecCreate(comm, &gvec)); 1692*2e1d0745SJose E. Roman PetscCall(PetscObjectSetName((PetscObject)gvec, vec_name)); 1693*2e1d0745SJose E. Roman PetscCall(DMGetGlobalSection(sectiondm, §ion)); 1694*2e1d0745SJose E. Roman PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 1695*2e1d0745SJose E. Roman if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 1696*2e1d0745SJose E. Roman else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 1697*2e1d0745SJose E. Roman PetscCall(VecSetSizes(gvec, m, PETSC_DECIDE)); 1698*2e1d0745SJose E. Roman PetscCall(VecSetUp(gvec)); 1699*2e1d0745SJose E. Roman PetscCall(DMLocalToGlobalBegin(sectiondm, vec, INSERT_VALUES, gvec)); 1700*2e1d0745SJose E. Roman PetscCall(DMLocalToGlobalEnd(sectiondm, vec, INSERT_VALUES, gvec)); 1701*2e1d0745SJose E. Roman PetscCall(VecView(gvec, viewer)); 1702*2e1d0745SJose E. Roman PetscCall(VecDestroy(&gvec)); 1703*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 1704*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 1705*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 1706*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 1707*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 1708*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 1709*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 1710*2e1d0745SJose E. Roman } 1711*2e1d0745SJose E. Roman 1712*2e1d0745SJose E. Roman struct _n_LoadLabelsCtx { 1713*2e1d0745SJose E. Roman MPI_Comm comm; 1714*2e1d0745SJose E. Roman PetscMPIInt rank; 1715*2e1d0745SJose E. Roman DM dm; 1716*2e1d0745SJose E. Roman PetscViewer viewer; 1717*2e1d0745SJose E. Roman DMLabel label; 1718*2e1d0745SJose E. Roman PetscSF sfXC; 1719*2e1d0745SJose E. Roman PetscLayout layoutX; 1720*2e1d0745SJose E. Roman }; 1721*2e1d0745SJose E. Roman typedef struct _n_LoadLabelsCtx *LoadLabelsCtx; 1722*2e1d0745SJose E. Roman 1723*2e1d0745SJose E. Roman static PetscErrorCode LoadLabelsCtxCreate(DM dm, PetscViewer viewer, PetscSF sfXC, LoadLabelsCtx *ctx) 1724*2e1d0745SJose E. Roman { 1725*2e1d0745SJose E. Roman PetscFunctionBegin; 1726*2e1d0745SJose E. Roman PetscCall(PetscNew(ctx)); 1727*2e1d0745SJose E. Roman PetscCall(PetscObjectReference((PetscObject)((*ctx)->dm = dm))); 1728*2e1d0745SJose E. Roman PetscCall(PetscObjectReference((PetscObject)((*ctx)->viewer = viewer))); 1729*2e1d0745SJose E. Roman PetscCall(PetscObjectGetComm((PetscObject)dm, &(*ctx)->comm)); 1730*2e1d0745SJose E. Roman PetscCallMPI(MPI_Comm_rank((*ctx)->comm, &(*ctx)->rank)); 1731*2e1d0745SJose E. Roman (*ctx)->sfXC = sfXC; 1732*2e1d0745SJose E. Roman if (sfXC) { 1733*2e1d0745SJose E. Roman PetscInt nX; 1734*2e1d0745SJose E. Roman 1735*2e1d0745SJose E. Roman PetscCall(PetscObjectReference((PetscObject)sfXC)); 1736*2e1d0745SJose E. Roman PetscCall(PetscSFGetGraph(sfXC, &nX, NULL, NULL, NULL)); 1737*2e1d0745SJose E. Roman PetscCall(PetscLayoutCreateFromSizes((*ctx)->comm, nX, PETSC_DECIDE, 1, &(*ctx)->layoutX)); 1738*2e1d0745SJose E. Roman } 1739*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 1740*2e1d0745SJose E. Roman } 1741*2e1d0745SJose E. Roman 1742*2e1d0745SJose E. Roman static PetscErrorCode LoadLabelsCtxDestroy(LoadLabelsCtx *ctx) 1743*2e1d0745SJose E. Roman { 1744*2e1d0745SJose E. Roman PetscFunctionBegin; 1745*2e1d0745SJose E. Roman if (!*ctx) PetscFunctionReturn(PETSC_SUCCESS); 1746*2e1d0745SJose E. Roman PetscCall(DMDestroy(&(*ctx)->dm)); 1747*2e1d0745SJose E. Roman PetscCall(PetscViewerDestroy(&(*ctx)->viewer)); 1748*2e1d0745SJose E. Roman PetscCall(PetscSFDestroy(&(*ctx)->sfXC)); 1749*2e1d0745SJose E. Roman PetscCall(PetscLayoutDestroy(&(*ctx)->layoutX)); 1750*2e1d0745SJose E. Roman PetscCall(PetscFree(*ctx)); 1751*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 1752*2e1d0745SJose E. Roman } 1753*2e1d0745SJose E. Roman 1754*2e1d0745SJose E. Roman /* 1755*2e1d0745SJose E. Roman A: on-disk points 1756*2e1d0745SJose E. Roman X: global points [0, NX) 1757*2e1d0745SJose E. Roman C: distributed plex points 1758*2e1d0745SJose E. Roman */ 1759*2e1d0745SJose E. Roman static herr_t ReadLabelStratumHDF5_Distribute_Private(IS stratumIS, LoadLabelsCtx ctx, IS *newStratumIS) 1760*2e1d0745SJose E. Roman { 1761*2e1d0745SJose E. Roman MPI_Comm comm = ctx->comm; 1762*2e1d0745SJose E. Roman PetscSF sfXC = ctx->sfXC; 1763*2e1d0745SJose E. Roman PetscLayout layoutX = ctx->layoutX; 1764*2e1d0745SJose E. Roman PetscSF sfXA; 1765*2e1d0745SJose E. Roman const PetscInt *A_points; 1766*2e1d0745SJose E. Roman PetscInt nX, nC; 1767*2e1d0745SJose E. Roman PetscInt n; 1768*2e1d0745SJose E. Roman 1769*2e1d0745SJose E. Roman PetscFunctionBegin; 1770*2e1d0745SJose E. Roman PetscCall(PetscSFGetGraph(sfXC, &nX, &nC, NULL, NULL)); 1771*2e1d0745SJose E. Roman PetscCall(ISGetLocalSize(stratumIS, &n)); 1772*2e1d0745SJose E. Roman PetscCall(ISGetIndices(stratumIS, &A_points)); 1773*2e1d0745SJose E. Roman PetscCall(PetscSFCreate(comm, &sfXA)); 1774*2e1d0745SJose E. Roman PetscCall(PetscSFSetGraphLayout(sfXA, layoutX, n, NULL, PETSC_USE_POINTER, A_points)); 1775*2e1d0745SJose E. Roman PetscCall(ISCreate(comm, newStratumIS)); 1776*2e1d0745SJose E. Roman PetscCall(ISSetType(*newStratumIS, ISGENERAL)); 1777*2e1d0745SJose E. Roman { 1778*2e1d0745SJose E. Roman PetscInt i; 1779*2e1d0745SJose E. Roman PetscBool *A_mask, *X_mask, *C_mask; 1780*2e1d0745SJose E. Roman 1781*2e1d0745SJose E. Roman PetscCall(PetscCalloc3(n, &A_mask, nX, &X_mask, nC, &C_mask)); 1782*2e1d0745SJose E. Roman for (i = 0; i < n; i++) A_mask[i] = PETSC_TRUE; 1783*2e1d0745SJose E. Roman PetscCall(PetscSFReduceBegin(sfXA, MPIU_BOOL, A_mask, X_mask, MPI_REPLACE)); 1784*2e1d0745SJose E. Roman PetscCall(PetscSFReduceEnd(sfXA, MPIU_BOOL, A_mask, X_mask, MPI_REPLACE)); 1785*2e1d0745SJose E. Roman PetscCall(PetscSFBcastBegin(sfXC, MPIU_BOOL, X_mask, C_mask, MPI_LOR)); 1786*2e1d0745SJose E. Roman PetscCall(PetscSFBcastEnd(sfXC, MPIU_BOOL, X_mask, C_mask, MPI_LOR)); 1787*2e1d0745SJose E. Roman PetscCall(ISGeneralSetIndicesFromMask(*newStratumIS, 0, nC, C_mask)); 1788*2e1d0745SJose E. Roman PetscCall(PetscFree3(A_mask, X_mask, C_mask)); 1789*2e1d0745SJose E. Roman } 1790*2e1d0745SJose E. Roman PetscCall(PetscSFDestroy(&sfXA)); 1791*2e1d0745SJose E. Roman PetscCall(ISRestoreIndices(stratumIS, &A_points)); 1792*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 1793*2e1d0745SJose E. Roman } 1794*2e1d0745SJose E. Roman 1795*2e1d0745SJose E. Roman static herr_t ReadLabelStratumHDF5_Static(hid_t g_id, const char *vname, const H5L_info_t *info, void *op_data) 1796*2e1d0745SJose E. Roman { 1797*2e1d0745SJose E. Roman LoadLabelsCtx ctx = (LoadLabelsCtx)op_data; 1798*2e1d0745SJose E. Roman PetscViewer viewer = ctx->viewer; 1799*2e1d0745SJose E. Roman DMLabel label = ctx->label; 1800*2e1d0745SJose E. Roman MPI_Comm comm = ctx->comm; 1801*2e1d0745SJose E. Roman IS stratumIS; 1802*2e1d0745SJose E. Roman const PetscInt *ind; 1803*2e1d0745SJose E. Roman PetscInt value, N, i; 1804*2e1d0745SJose E. Roman 1805*2e1d0745SJose E. Roman PetscCall(PetscOptionsStringToInt(vname, &value)); 1806*2e1d0745SJose E. Roman PetscCall(ISCreate(comm, &stratumIS)); 1807*2e1d0745SJose E. Roman PetscCall(PetscObjectSetName((PetscObject)stratumIS, "indices")); 1808*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, vname)); /* labels/<lname>/<vname> */ 1809*2e1d0745SJose E. Roman 1810*2e1d0745SJose E. Roman if (!ctx->sfXC) { 1811*2e1d0745SJose E. Roman /* Force serial load */ 1812*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5ReadSizes(viewer, "indices", NULL, &N)); 1813*2e1d0745SJose E. Roman PetscCall(PetscLayoutSetLocalSize(stratumIS->map, !ctx->rank ? N : 0)); 1814*2e1d0745SJose E. Roman PetscCall(PetscLayoutSetSize(stratumIS->map, N)); 1815*2e1d0745SJose E. Roman } 1816*2e1d0745SJose E. Roman PetscCall(ISLoad(stratumIS, viewer)); 1817*2e1d0745SJose E. Roman 1818*2e1d0745SJose E. Roman if (ctx->sfXC) { 1819*2e1d0745SJose E. Roman IS newStratumIS; 1820*2e1d0745SJose E. Roman 1821*2e1d0745SJose E. Roman PetscCallHDF5(ReadLabelStratumHDF5_Distribute_Private, (stratumIS, ctx, &newStratumIS)); 1822*2e1d0745SJose E. Roman PetscCall(ISDestroy(&stratumIS)); 1823*2e1d0745SJose E. Roman stratumIS = newStratumIS; 1824*2e1d0745SJose E. Roman } 1825*2e1d0745SJose E. Roman 1826*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 1827*2e1d0745SJose E. Roman PetscCall(ISGetLocalSize(stratumIS, &N)); 1828*2e1d0745SJose E. Roman PetscCall(ISGetIndices(stratumIS, &ind)); 1829*2e1d0745SJose E. Roman for (i = 0; i < N; ++i) PetscCall(DMLabelSetValue(label, ind[i], value)); 1830*2e1d0745SJose E. Roman PetscCall(ISRestoreIndices(stratumIS, &ind)); 1831*2e1d0745SJose E. Roman PetscCall(ISDestroy(&stratumIS)); 1832*2e1d0745SJose E. Roman return 0; 1833*2e1d0745SJose E. Roman } 1834*2e1d0745SJose E. Roman 1835*2e1d0745SJose E. Roman /* TODO: Fix this code, it is returning PETSc error codes when it should be translating them to herr_t codes */ 1836*2e1d0745SJose E. Roman static herr_t ReadLabelHDF5_Static(hid_t g_id, const char *lname, const H5L_info_t *info, void *op_data) 1837*2e1d0745SJose E. Roman { 1838*2e1d0745SJose E. Roman LoadLabelsCtx ctx = (LoadLabelsCtx)op_data; 1839*2e1d0745SJose E. Roman DM dm = ctx->dm; 1840*2e1d0745SJose E. Roman hsize_t idx = 0; 1841*2e1d0745SJose E. Roman PetscErrorCode ierr; 1842*2e1d0745SJose E. Roman PetscBool flg; 1843*2e1d0745SJose E. Roman herr_t err; 1844*2e1d0745SJose E. Roman 1845*2e1d0745SJose E. Roman PetscCall(DMHasLabel(dm, lname, &flg)); 1846*2e1d0745SJose E. Roman if (flg) PetscCall(DMRemoveLabel(dm, lname, NULL)); 1847*2e1d0745SJose E. Roman ierr = DMCreateLabel(dm, lname); 1848*2e1d0745SJose E. Roman if (ierr) return (herr_t)ierr; 1849*2e1d0745SJose E. Roman ierr = DMGetLabel(dm, lname, &ctx->label); 1850*2e1d0745SJose E. Roman if (ierr) return (herr_t)ierr; 1851*2e1d0745SJose E. Roman ierr = PetscViewerHDF5PushGroup(ctx->viewer, lname); 1852*2e1d0745SJose E. Roman if (ierr) return (herr_t)ierr; 1853*2e1d0745SJose E. Roman /* Iterate over the label's strata */ 1854*2e1d0745SJose E. Roman PetscCallHDF5Return(err, H5Literate_by_name, (g_id, lname, H5_INDEX_NAME, H5_ITER_NATIVE, &idx, ReadLabelStratumHDF5_Static, op_data, 0)); 1855*2e1d0745SJose E. Roman ierr = PetscViewerHDF5PopGroup(ctx->viewer); 1856*2e1d0745SJose E. Roman if (ierr) return (herr_t)ierr; 1857*2e1d0745SJose E. Roman return err; 1858*2e1d0745SJose E. Roman } 1859*2e1d0745SJose E. Roman 1860*2e1d0745SJose E. Roman PetscErrorCode DMPlexLabelsLoad_HDF5_Internal(DM dm, PetscViewer viewer, PetscSF sfXC) 1861*2e1d0745SJose E. Roman { 1862*2e1d0745SJose E. Roman const char *topologydm_name; 1863*2e1d0745SJose E. Roman LoadLabelsCtx ctx; 1864*2e1d0745SJose E. Roman hsize_t idx = 0; 1865*2e1d0745SJose E. Roman char group[PETSC_MAX_PATH_LEN]; 1866*2e1d0745SJose E. Roman DMPlexStorageVersion version; 1867*2e1d0745SJose E. Roman PetscBool distributed, hasGroup; 1868*2e1d0745SJose E. Roman 1869*2e1d0745SJose E. Roman PetscFunctionBegin; 1870*2e1d0745SJose E. Roman PetscCall(DMPlexIsDistributed(dm, &distributed)); 1871*2e1d0745SJose E. Roman if (distributed) PetscCheck(sfXC, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_NULL, "PetscSF must be given for parallel load"); 1872*2e1d0745SJose E. Roman PetscCall(LoadLabelsCtxCreate(dm, viewer, sfXC, &ctx)); 1873*2e1d0745SJose E. Roman PetscCall(DMPlexGetHDF5Name_Private(dm, &topologydm_name)); 1874*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5GetDMPlexStorageVersionReading(viewer, &version)); 1875*2e1d0745SJose E. Roman if (DMPlexStorageVersionGE(version, 2, 0, 0)) { 1876*2e1d0745SJose E. Roman PetscCall(PetscSNPrintf(group, sizeof(group), "topologies/%s/labels", topologydm_name)); 1877*2e1d0745SJose E. Roman } else { 1878*2e1d0745SJose E. Roman PetscCall(PetscStrncpy(group, "labels", sizeof(group))); 1879*2e1d0745SJose E. Roman } 1880*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, group)); 1881*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5HasGroup(viewer, NULL, &hasGroup)); 1882*2e1d0745SJose E. Roman if (hasGroup) { 1883*2e1d0745SJose E. Roman hid_t fileId, groupId; 1884*2e1d0745SJose E. Roman 1885*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5OpenGroup(viewer, NULL, &fileId, &groupId)); 1886*2e1d0745SJose E. Roman /* Iterate over labels */ 1887*2e1d0745SJose E. Roman PetscCallHDF5(H5Literate, (groupId, H5_INDEX_NAME, H5_ITER_NATIVE, &idx, ReadLabelHDF5_Static, ctx)); 1888*2e1d0745SJose E. Roman PetscCallHDF5(H5Gclose, (groupId)); 1889*2e1d0745SJose E. Roman } 1890*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 1891*2e1d0745SJose E. Roman PetscCall(LoadLabelsCtxDestroy(&ctx)); 1892*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 1893*2e1d0745SJose E. Roman } 1894*2e1d0745SJose E. Roman 1895*2e1d0745SJose E. Roman static PetscErrorCode DMPlexDistributionLoad_HDF5_Private(DM dm, PetscViewer viewer, PetscSF sf, PetscSF *distsf, DM *distdm) 1896*2e1d0745SJose E. Roman { 1897*2e1d0745SJose E. Roman MPI_Comm comm; 1898*2e1d0745SJose E. Roman PetscMPIInt size, rank; 1899*2e1d0745SJose E. Roman PetscInt dist_size; 1900*2e1d0745SJose E. Roman const char *distribution_name; 1901*2e1d0745SJose E. Roman PetscInt p, lsize; 1902*2e1d0745SJose E. Roman IS chartSizesIS, ownersIS, gpointsIS; 1903*2e1d0745SJose E. Roman const PetscInt *chartSize, *owners, *gpoints; 1904*2e1d0745SJose E. Roman PetscLayout layout; 1905*2e1d0745SJose E. Roman PetscBool has; 1906*2e1d0745SJose E. Roman 1907*2e1d0745SJose E. Roman PetscFunctionBegin; 1908*2e1d0745SJose E. Roman *distsf = NULL; 1909*2e1d0745SJose E. Roman *distdm = NULL; 1910*2e1d0745SJose E. Roman PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 1911*2e1d0745SJose E. Roman PetscCallMPI(MPI_Comm_size(comm, &size)); 1912*2e1d0745SJose E. Roman PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1913*2e1d0745SJose E. Roman PetscCall(DMPlexDistributionGetName(dm, &distribution_name)); 1914*2e1d0745SJose E. Roman if (!distribution_name) PetscFunctionReturn(PETSC_SUCCESS); 1915*2e1d0745SJose E. Roman PetscCall(PetscLogEventBegin(DMPLEX_DistributionLoad, viewer, 0, 0, 0)); 1916*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5HasGroup(viewer, NULL, &has)); 1917*2e1d0745SJose E. Roman if (!has) { 1918*2e1d0745SJose E. Roman char *full_group; 1919*2e1d0745SJose E. Roman 1920*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5GetGroup(viewer, NULL, &full_group)); 1921*2e1d0745SJose 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); 1922*2e1d0745SJose E. Roman } 1923*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5ReadAttribute(viewer, NULL, "comm_size", PETSC_INT, NULL, (void *)&dist_size)); 1924*2e1d0745SJose 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); 1925*2e1d0745SJose E. Roman PetscCall(ISCreate(comm, &chartSizesIS)); 1926*2e1d0745SJose E. Roman PetscCall(PetscObjectSetName((PetscObject)chartSizesIS, "chart_sizes")); 1927*2e1d0745SJose E. Roman PetscCall(ISCreate(comm, &ownersIS)); 1928*2e1d0745SJose E. Roman PetscCall(PetscObjectSetName((PetscObject)ownersIS, "owners")); 1929*2e1d0745SJose E. Roman PetscCall(ISCreate(comm, &gpointsIS)); 1930*2e1d0745SJose E. Roman PetscCall(PetscObjectSetName((PetscObject)gpointsIS, "global_point_numbers")); 1931*2e1d0745SJose E. Roman PetscCall(PetscLayoutSetLocalSize(chartSizesIS->map, 1)); 1932*2e1d0745SJose E. Roman PetscCall(ISLoad(chartSizesIS, viewer)); 1933*2e1d0745SJose E. Roman PetscCall(ISGetIndices(chartSizesIS, &chartSize)); 1934*2e1d0745SJose E. Roman PetscCall(PetscLayoutSetLocalSize(ownersIS->map, *chartSize)); 1935*2e1d0745SJose E. Roman PetscCall(PetscLayoutSetLocalSize(gpointsIS->map, *chartSize)); 1936*2e1d0745SJose E. Roman PetscCall(ISLoad(ownersIS, viewer)); 1937*2e1d0745SJose E. Roman PetscCall(ISLoad(gpointsIS, viewer)); 1938*2e1d0745SJose E. Roman PetscCall(ISGetIndices(ownersIS, &owners)); 1939*2e1d0745SJose E. Roman PetscCall(ISGetIndices(gpointsIS, &gpoints)); 1940*2e1d0745SJose E. Roman PetscCall(PetscSFCreate(comm, distsf)); 1941*2e1d0745SJose E. Roman PetscCall(PetscSFSetFromOptions(*distsf)); 1942*2e1d0745SJose E. Roman PetscCall(PetscLayoutCreate(comm, &layout)); 1943*2e1d0745SJose E. Roman PetscCall(PetscSFGetGraph(sf, &lsize, NULL, NULL, NULL)); 1944*2e1d0745SJose E. Roman PetscCall(PetscLayoutSetLocalSize(layout, lsize)); 1945*2e1d0745SJose E. Roman PetscCall(PetscLayoutSetBlockSize(layout, 1)); 1946*2e1d0745SJose E. Roman PetscCall(PetscLayoutSetUp(layout)); 1947*2e1d0745SJose E. Roman PetscCall(PetscSFSetGraphLayout(*distsf, layout, *chartSize, NULL, PETSC_OWN_POINTER, gpoints)); 1948*2e1d0745SJose E. Roman PetscCall(PetscLayoutDestroy(&layout)); 1949*2e1d0745SJose E. Roman /* Migrate DM */ 1950*2e1d0745SJose E. Roman { 1951*2e1d0745SJose E. Roman PetscInt pStart, pEnd; 1952*2e1d0745SJose E. Roman PetscSFNode *buffer0, *buffer1, *buffer2; 1953*2e1d0745SJose E. Roman 1954*2e1d0745SJose E. Roman PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 1955*2e1d0745SJose E. Roman PetscCall(PetscMalloc2(pEnd - pStart, &buffer0, lsize, &buffer1)); 1956*2e1d0745SJose E. Roman PetscCall(PetscMalloc1(*chartSize, &buffer2)); 1957*2e1d0745SJose E. Roman { 1958*2e1d0745SJose E. Roman PetscSF workPointSF; 1959*2e1d0745SJose E. Roman PetscInt workNroots, workNleaves; 1960*2e1d0745SJose E. Roman const PetscInt *workIlocal; 1961*2e1d0745SJose E. Roman const PetscSFNode *workIremote; 1962*2e1d0745SJose E. Roman 1963*2e1d0745SJose E. Roman for (p = pStart; p < pEnd; ++p) { 1964*2e1d0745SJose E. Roman buffer0[p - pStart].rank = rank; 1965*2e1d0745SJose E. Roman buffer0[p - pStart].index = p - pStart; 1966*2e1d0745SJose E. Roman } 1967*2e1d0745SJose E. Roman PetscCall(DMGetPointSF(dm, &workPointSF)); 1968*2e1d0745SJose E. Roman PetscCall(PetscSFGetGraph(workPointSF, &workNroots, &workNleaves, &workIlocal, &workIremote)); 1969*2e1d0745SJose E. Roman for (p = 0; p < workNleaves; ++p) { 1970*2e1d0745SJose E. Roman PetscInt workIlocalp = (workIlocal ? workIlocal[p] : p); 1971*2e1d0745SJose E. Roman 1972*2e1d0745SJose E. Roman buffer0[workIlocalp].rank = -1; 1973*2e1d0745SJose E. Roman } 1974*2e1d0745SJose E. Roman } 1975*2e1d0745SJose E. Roman for (p = 0; p < lsize; ++p) buffer1[p].rank = -1; 1976*2e1d0745SJose E. Roman for (p = 0; p < *chartSize; ++p) buffer2[p].rank = -1; 1977*2e1d0745SJose E. Roman PetscCall(PetscSFReduceBegin(sf, MPIU_SF_NODE, buffer0, buffer1, MPI_MAXLOC)); 1978*2e1d0745SJose E. Roman PetscCall(PetscSFReduceEnd(sf, MPIU_SF_NODE, buffer0, buffer1, MPI_MAXLOC)); 1979*2e1d0745SJose E. Roman PetscCall(PetscSFBcastBegin(*distsf, MPIU_SF_NODE, buffer1, buffer2, MPI_REPLACE)); 1980*2e1d0745SJose E. Roman PetscCall(PetscSFBcastEnd(*distsf, MPIU_SF_NODE, buffer1, buffer2, MPI_REPLACE)); 1981*2e1d0745SJose E. Roman if (PetscDefined(USE_DEBUG)) { 1982*2e1d0745SJose E. Roman for (p = 0; p < *chartSize; ++p) { 1983*2e1d0745SJose 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); 1984*2e1d0745SJose E. Roman } 1985*2e1d0745SJose E. Roman } 1986*2e1d0745SJose E. Roman PetscCall(PetscFree2(buffer0, buffer1)); 1987*2e1d0745SJose E. Roman PetscCall(DMCreate(comm, distdm)); 1988*2e1d0745SJose E. Roman PetscCall(DMSetType(*distdm, DMPLEX)); 1989*2e1d0745SJose E. Roman PetscCall(PetscObjectSetName((PetscObject)*distdm, ((PetscObject)dm)->name)); 1990*2e1d0745SJose E. Roman PetscCall(DMPlexDistributionSetName(*distdm, distribution_name)); 1991*2e1d0745SJose E. Roman { 1992*2e1d0745SJose E. Roman PetscSF migrationSF; 1993*2e1d0745SJose E. Roman 1994*2e1d0745SJose E. Roman PetscCall(PetscSFCreate(comm, &migrationSF)); 1995*2e1d0745SJose E. Roman PetscCall(PetscSFSetFromOptions(migrationSF)); 1996*2e1d0745SJose E. Roman PetscCall(PetscSFSetGraph(migrationSF, pEnd - pStart, *chartSize, NULL, PETSC_OWN_POINTER, buffer2, PETSC_OWN_POINTER)); 1997*2e1d0745SJose E. Roman PetscCall(PetscSFSetUp(migrationSF)); 1998*2e1d0745SJose E. Roman PetscCall(DMPlexMigrate(dm, migrationSF, *distdm)); 1999*2e1d0745SJose E. Roman PetscCall(PetscSFDestroy(&migrationSF)); 2000*2e1d0745SJose E. Roman } 2001*2e1d0745SJose E. Roman } 2002*2e1d0745SJose E. Roman /* Set pointSF */ 2003*2e1d0745SJose E. Roman { 2004*2e1d0745SJose E. Roman PetscSF pointSF; 2005*2e1d0745SJose E. Roman PetscInt *ilocal, nleaves, q; 2006*2e1d0745SJose E. Roman PetscSFNode *iremote, *buffer0, *buffer1; 2007*2e1d0745SJose E. Roman 2008*2e1d0745SJose E. Roman PetscCall(PetscMalloc2(*chartSize, &buffer0, lsize, &buffer1)); 2009*2e1d0745SJose E. Roman for (p = 0, nleaves = 0; p < *chartSize; ++p) { 2010*2e1d0745SJose E. Roman if (owners[p] == rank) { 2011*2e1d0745SJose E. Roman buffer0[p].rank = rank; 2012*2e1d0745SJose E. Roman } else { 2013*2e1d0745SJose E. Roman buffer0[p].rank = -1; 2014*2e1d0745SJose E. Roman nleaves++; 2015*2e1d0745SJose E. Roman } 2016*2e1d0745SJose E. Roman buffer0[p].index = p; 2017*2e1d0745SJose E. Roman } 2018*2e1d0745SJose E. Roman for (p = 0; p < lsize; ++p) buffer1[p].rank = -1; 2019*2e1d0745SJose E. Roman PetscCall(PetscSFReduceBegin(*distsf, MPIU_SF_NODE, buffer0, buffer1, MPI_MAXLOC)); 2020*2e1d0745SJose E. Roman PetscCall(PetscSFReduceEnd(*distsf, MPIU_SF_NODE, buffer0, buffer1, MPI_MAXLOC)); 2021*2e1d0745SJose E. Roman for (p = 0; p < *chartSize; ++p) buffer0[p].rank = -1; 2022*2e1d0745SJose E. Roman PetscCall(PetscSFBcastBegin(*distsf, MPIU_SF_NODE, buffer1, buffer0, MPI_REPLACE)); 2023*2e1d0745SJose E. Roman PetscCall(PetscSFBcastEnd(*distsf, MPIU_SF_NODE, buffer1, buffer0, MPI_REPLACE)); 2024*2e1d0745SJose E. Roman if (PetscDefined(USE_DEBUG)) { 2025*2e1d0745SJose 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); 2026*2e1d0745SJose E. Roman } 2027*2e1d0745SJose E. Roman PetscCall(PetscMalloc1(nleaves, &ilocal)); 2028*2e1d0745SJose E. Roman PetscCall(PetscMalloc1(nleaves, &iremote)); 2029*2e1d0745SJose E. Roman for (p = 0, q = 0; p < *chartSize; ++p) { 2030*2e1d0745SJose E. Roman if (buffer0[p].rank != rank) { 2031*2e1d0745SJose E. Roman ilocal[q] = p; 2032*2e1d0745SJose E. Roman iremote[q].rank = buffer0[p].rank; 2033*2e1d0745SJose E. Roman iremote[q].index = buffer0[p].index; 2034*2e1d0745SJose E. Roman q++; 2035*2e1d0745SJose E. Roman } 2036*2e1d0745SJose E. Roman } 2037*2e1d0745SJose E. Roman PetscCheck(q == nleaves, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatching leaf sizes: %" PetscInt_FMT " != %" PetscInt_FMT, q, nleaves); 2038*2e1d0745SJose E. Roman PetscCall(PetscFree2(buffer0, buffer1)); 2039*2e1d0745SJose E. Roman PetscCall(PetscSFCreate(comm, &pointSF)); 2040*2e1d0745SJose E. Roman PetscCall(PetscSFSetFromOptions(pointSF)); 2041*2e1d0745SJose E. Roman PetscCall(PetscSFSetGraph(pointSF, *chartSize, nleaves, ilocal, PETSC_OWN_POINTER, iremote, PETSC_OWN_POINTER)); 2042*2e1d0745SJose E. Roman PetscCall(DMSetPointSF(*distdm, pointSF)); 2043*2e1d0745SJose E. Roman { 2044*2e1d0745SJose E. Roman DM cdm; 2045*2e1d0745SJose E. Roman 2046*2e1d0745SJose E. Roman PetscCall(DMGetCoordinateDM(*distdm, &cdm)); 2047*2e1d0745SJose E. Roman PetscCall(DMSetPointSF(cdm, pointSF)); 2048*2e1d0745SJose E. Roman } 2049*2e1d0745SJose E. Roman PetscCall(PetscSFDestroy(&pointSF)); 2050*2e1d0745SJose E. Roman } 2051*2e1d0745SJose E. Roman PetscCall(ISRestoreIndices(chartSizesIS, &chartSize)); 2052*2e1d0745SJose E. Roman PetscCall(ISRestoreIndices(ownersIS, &owners)); 2053*2e1d0745SJose E. Roman PetscCall(ISRestoreIndices(gpointsIS, &gpoints)); 2054*2e1d0745SJose E. Roman PetscCall(ISDestroy(&chartSizesIS)); 2055*2e1d0745SJose E. Roman PetscCall(ISDestroy(&ownersIS)); 2056*2e1d0745SJose E. Roman PetscCall(ISDestroy(&gpointsIS)); 2057*2e1d0745SJose E. Roman /* Record that overlap has been manually created. */ 2058*2e1d0745SJose E. Roman /* This is to pass `DMPlexCheckPointSF()`, which checks that */ 2059*2e1d0745SJose E. Roman /* pointSF does not contain cells in the leaves if overlap = 0. */ 2060*2e1d0745SJose E. Roman PetscCall(DMPlexSetOverlap_Plex(*distdm, NULL, DMPLEX_OVERLAP_MANUAL)); 2061*2e1d0745SJose E. Roman PetscCall(DMPlexDistributeSetDefault(*distdm, PETSC_FALSE)); 2062*2e1d0745SJose E. Roman PetscCall(DMPlexReorderSetDefault(*distdm, DM_REORDER_DEFAULT_FALSE)); 2063*2e1d0745SJose E. Roman PetscCall(PetscLogEventEnd(DMPLEX_DistributionLoad, viewer, 0, 0, 0)); 2064*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 2065*2e1d0745SJose E. Roman } 2066*2e1d0745SJose E. Roman 2067*2e1d0745SJose E. Roman // Serial load of topology 2068*2e1d0745SJose E. Roman static PetscErrorCode DMPlexTopologyLoad_HDF5_Legacy_Private(DM dm, PetscViewer viewer, PetscSF *sf) 2069*2e1d0745SJose E. Roman { 2070*2e1d0745SJose E. Roman MPI_Comm comm; 2071*2e1d0745SJose E. Roman const char *pointsName, *coneSizesName, *conesName, *orientationsName; 2072*2e1d0745SJose E. Roman IS pointsIS, coneSizesIS, conesIS, orientationsIS; 2073*2e1d0745SJose E. Roman const PetscInt *points, *coneSizes, *cones, *orientations; 2074*2e1d0745SJose E. Roman PetscInt *cone, *ornt; 2075*2e1d0745SJose E. Roman PetscInt dim, N, Np, pEnd, p, q, maxConeSize = 0, c; 2076*2e1d0745SJose E. Roman PetscMPIInt size, rank; 2077*2e1d0745SJose E. Roman 2078*2e1d0745SJose E. Roman PetscFunctionBegin; 2079*2e1d0745SJose E. Roman pointsName = "order"; 2080*2e1d0745SJose E. Roman coneSizesName = "cones"; 2081*2e1d0745SJose E. Roman conesName = "cells"; 2082*2e1d0745SJose E. Roman orientationsName = "orientation"; 2083*2e1d0745SJose E. Roman PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 2084*2e1d0745SJose E. Roman PetscCallMPI(MPI_Comm_size(comm, &size)); 2085*2e1d0745SJose E. Roman PetscCallMPI(MPI_Comm_rank(comm, &rank)); 2086*2e1d0745SJose E. Roman PetscCall(ISCreate(comm, &pointsIS)); 2087*2e1d0745SJose E. Roman PetscCall(PetscObjectSetName((PetscObject)pointsIS, pointsName)); 2088*2e1d0745SJose E. Roman PetscCall(ISCreate(comm, &coneSizesIS)); 2089*2e1d0745SJose E. Roman PetscCall(PetscObjectSetName((PetscObject)coneSizesIS, coneSizesName)); 2090*2e1d0745SJose E. Roman PetscCall(ISCreate(comm, &conesIS)); 2091*2e1d0745SJose E. Roman PetscCall(PetscObjectSetName((PetscObject)conesIS, conesName)); 2092*2e1d0745SJose E. Roman PetscCall(ISCreate(comm, &orientationsIS)); 2093*2e1d0745SJose E. Roman PetscCall(PetscObjectSetName((PetscObject)orientationsIS, orientationsName)); 2094*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5ReadObjectAttribute(viewer, (PetscObject)conesIS, "cell_dim", PETSC_INT, NULL, &dim)); 2095*2e1d0745SJose E. Roman PetscCall(DMSetDimension(dm, dim)); 2096*2e1d0745SJose E. Roman { 2097*2e1d0745SJose E. Roman /* Force serial load */ 2098*2e1d0745SJose E. Roman PetscCall(PetscInfo(dm, "Loading DM %s in serial\n", dm->hdr.name)); 2099*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5ReadSizes(viewer, pointsName, NULL, &Np)); 2100*2e1d0745SJose E. Roman PetscCall(PetscLayoutSetLocalSize(pointsIS->map, rank == 0 ? Np : 0)); 2101*2e1d0745SJose E. Roman PetscCall(PetscLayoutSetSize(pointsIS->map, Np)); 2102*2e1d0745SJose E. Roman pEnd = rank == 0 ? Np : 0; 2103*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5ReadSizes(viewer, coneSizesName, NULL, &Np)); 2104*2e1d0745SJose E. Roman PetscCall(PetscLayoutSetLocalSize(coneSizesIS->map, rank == 0 ? Np : 0)); 2105*2e1d0745SJose E. Roman PetscCall(PetscLayoutSetSize(coneSizesIS->map, Np)); 2106*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5ReadSizes(viewer, conesName, NULL, &N)); 2107*2e1d0745SJose E. Roman PetscCall(PetscLayoutSetLocalSize(conesIS->map, rank == 0 ? N : 0)); 2108*2e1d0745SJose E. Roman PetscCall(PetscLayoutSetSize(conesIS->map, N)); 2109*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5ReadSizes(viewer, orientationsName, NULL, &N)); 2110*2e1d0745SJose E. Roman PetscCall(PetscLayoutSetLocalSize(orientationsIS->map, rank == 0 ? N : 0)); 2111*2e1d0745SJose E. Roman PetscCall(PetscLayoutSetSize(orientationsIS->map, N)); 2112*2e1d0745SJose E. Roman } 2113*2e1d0745SJose E. Roman PetscCall(ISLoad(pointsIS, viewer)); 2114*2e1d0745SJose E. Roman PetscCall(ISLoad(coneSizesIS, viewer)); 2115*2e1d0745SJose E. Roman PetscCall(ISLoad(conesIS, viewer)); 2116*2e1d0745SJose E. Roman PetscCall(ISLoad(orientationsIS, viewer)); 2117*2e1d0745SJose E. Roman /* Create Plex */ 2118*2e1d0745SJose E. Roman PetscCall(DMPlexSetChart(dm, 0, pEnd)); 2119*2e1d0745SJose E. Roman PetscCall(ISGetIndices(pointsIS, &points)); 2120*2e1d0745SJose E. Roman PetscCall(ISGetIndices(coneSizesIS, &coneSizes)); 2121*2e1d0745SJose E. Roman for (p = 0; p < pEnd; ++p) { 2122*2e1d0745SJose E. Roman PetscCall(DMPlexSetConeSize(dm, points[p], coneSizes[p])); 2123*2e1d0745SJose E. Roman maxConeSize = PetscMax(maxConeSize, coneSizes[p]); 2124*2e1d0745SJose E. Roman } 2125*2e1d0745SJose E. Roman PetscCall(DMSetUp(dm)); 2126*2e1d0745SJose E. Roman PetscCall(ISGetIndices(conesIS, &cones)); 2127*2e1d0745SJose E. Roman PetscCall(ISGetIndices(orientationsIS, &orientations)); 2128*2e1d0745SJose E. Roman PetscCall(PetscMalloc2(maxConeSize, &cone, maxConeSize, &ornt)); 2129*2e1d0745SJose E. Roman for (p = 0, q = 0; p < pEnd; ++p) { 2130*2e1d0745SJose E. Roman for (c = 0; c < coneSizes[p]; ++c, ++q) { 2131*2e1d0745SJose E. Roman cone[c] = cones[q]; 2132*2e1d0745SJose E. Roman ornt[c] = orientations[q]; 2133*2e1d0745SJose E. Roman } 2134*2e1d0745SJose E. Roman PetscCall(DMPlexSetCone(dm, points[p], cone)); 2135*2e1d0745SJose E. Roman PetscCall(DMPlexSetConeOrientation(dm, points[p], ornt)); 2136*2e1d0745SJose E. Roman } 2137*2e1d0745SJose E. Roman PetscCall(PetscFree2(cone, ornt)); 2138*2e1d0745SJose E. Roman /* Create global section migration SF */ 2139*2e1d0745SJose E. Roman if (sf) { 2140*2e1d0745SJose E. Roman PetscLayout layout; 2141*2e1d0745SJose E. Roman PetscInt *globalIndices; 2142*2e1d0745SJose E. Roman 2143*2e1d0745SJose E. Roman PetscCall(PetscMalloc1(pEnd, &globalIndices)); 2144*2e1d0745SJose E. Roman /* plex point == globalPointNumber in this case */ 2145*2e1d0745SJose E. Roman for (p = 0; p < pEnd; ++p) globalIndices[p] = p; 2146*2e1d0745SJose E. Roman PetscCall(PetscLayoutCreate(comm, &layout)); 2147*2e1d0745SJose E. Roman PetscCall(PetscLayoutSetSize(layout, Np)); 2148*2e1d0745SJose E. Roman PetscCall(PetscLayoutSetBlockSize(layout, 1)); 2149*2e1d0745SJose E. Roman PetscCall(PetscLayoutSetUp(layout)); 2150*2e1d0745SJose E. Roman PetscCall(PetscSFCreate(comm, sf)); 2151*2e1d0745SJose E. Roman PetscCall(PetscSFSetFromOptions(*sf)); 2152*2e1d0745SJose E. Roman PetscCall(PetscSFSetGraphLayout(*sf, layout, pEnd, NULL, PETSC_OWN_POINTER, globalIndices)); 2153*2e1d0745SJose E. Roman PetscCall(PetscLayoutDestroy(&layout)); 2154*2e1d0745SJose E. Roman PetscCall(PetscFree(globalIndices)); 2155*2e1d0745SJose E. Roman } 2156*2e1d0745SJose E. Roman /* Clean-up */ 2157*2e1d0745SJose E. Roman PetscCall(ISRestoreIndices(pointsIS, &points)); 2158*2e1d0745SJose E. Roman PetscCall(ISRestoreIndices(coneSizesIS, &coneSizes)); 2159*2e1d0745SJose E. Roman PetscCall(ISRestoreIndices(conesIS, &cones)); 2160*2e1d0745SJose E. Roman PetscCall(ISRestoreIndices(orientationsIS, &orientations)); 2161*2e1d0745SJose E. Roman PetscCall(ISDestroy(&pointsIS)); 2162*2e1d0745SJose E. Roman PetscCall(ISDestroy(&coneSizesIS)); 2163*2e1d0745SJose E. Roman PetscCall(ISDestroy(&conesIS)); 2164*2e1d0745SJose E. Roman PetscCall(ISDestroy(&orientationsIS)); 2165*2e1d0745SJose E. Roman /* Fill in the rest of the topology structure */ 2166*2e1d0745SJose E. Roman PetscCall(DMPlexSymmetrize(dm)); 2167*2e1d0745SJose E. Roman PetscCall(DMPlexStratify(dm)); 2168*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 2169*2e1d0745SJose E. Roman } 2170*2e1d0745SJose E. Roman 2171*2e1d0745SJose E. Roman /* Representation of two DMPlex strata in 0-based global numbering */ 2172*2e1d0745SJose E. Roman struct _n_PlexLayer { 2173*2e1d0745SJose E. Roman PetscInt d; 2174*2e1d0745SJose E. Roman IS conesIS, orientationsIS; 2175*2e1d0745SJose E. Roman PetscSection coneSizesSection; 2176*2e1d0745SJose E. Roman PetscLayout vertexLayout; 2177*2e1d0745SJose E. Roman PetscSF overlapSF, l2gSF; //TODO maybe confusing names (in DMPlex in general) 2178*2e1d0745SJose E. Roman PetscInt offset, conesOffset, leafOffset; 2179*2e1d0745SJose E. Roman }; 2180*2e1d0745SJose E. Roman typedef struct _n_PlexLayer *PlexLayer; 2181*2e1d0745SJose E. Roman 2182*2e1d0745SJose E. Roman static PetscErrorCode PlexLayerDestroy(PlexLayer *layer) 2183*2e1d0745SJose E. Roman { 2184*2e1d0745SJose E. Roman PetscFunctionBegin; 2185*2e1d0745SJose E. Roman if (!*layer) PetscFunctionReturn(PETSC_SUCCESS); 2186*2e1d0745SJose E. Roman PetscCall(PetscSectionDestroy(&(*layer)->coneSizesSection)); 2187*2e1d0745SJose E. Roman PetscCall(ISDestroy(&(*layer)->conesIS)); 2188*2e1d0745SJose E. Roman PetscCall(ISDestroy(&(*layer)->orientationsIS)); 2189*2e1d0745SJose E. Roman PetscCall(PetscSFDestroy(&(*layer)->overlapSF)); 2190*2e1d0745SJose E. Roman PetscCall(PetscSFDestroy(&(*layer)->l2gSF)); 2191*2e1d0745SJose E. Roman PetscCall(PetscLayoutDestroy(&(*layer)->vertexLayout)); 2192*2e1d0745SJose E. Roman PetscCall(PetscFree(*layer)); 2193*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 2194*2e1d0745SJose E. Roman } 2195*2e1d0745SJose E. Roman 2196*2e1d0745SJose E. Roman static PetscErrorCode PlexLayerCreate_Private(PlexLayer *layer) 2197*2e1d0745SJose E. Roman { 2198*2e1d0745SJose E. Roman PetscFunctionBegin; 2199*2e1d0745SJose E. Roman PetscCall(PetscNew(layer)); 2200*2e1d0745SJose E. Roman (*layer)->d = -1; 2201*2e1d0745SJose E. Roman (*layer)->offset = -1; 2202*2e1d0745SJose E. Roman (*layer)->conesOffset = -1; 2203*2e1d0745SJose E. Roman (*layer)->leafOffset = -1; 2204*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 2205*2e1d0745SJose E. Roman } 2206*2e1d0745SJose E. Roman 2207*2e1d0745SJose E. Roman // Parallel load of a depth stratum 2208*2e1d0745SJose E. Roman static PetscErrorCode PlexLayerLoad_Private(PlexLayer layer, PetscViewer viewer, PetscInt d, PetscLayout pointsLayout) 2209*2e1d0745SJose E. Roman { 2210*2e1d0745SJose E. Roman char path[128]; 2211*2e1d0745SJose E. Roman MPI_Comm comm; 2212*2e1d0745SJose E. Roman const char *coneSizesName, *conesName, *orientationsName; 2213*2e1d0745SJose E. Roman IS coneSizesIS, conesIS, orientationsIS; 2214*2e1d0745SJose E. Roman PetscSection coneSizesSection; 2215*2e1d0745SJose E. Roman PetscLayout vertexLayout = NULL; 2216*2e1d0745SJose E. Roman PetscInt s; 2217*2e1d0745SJose E. Roman 2218*2e1d0745SJose E. Roman PetscFunctionBegin; 2219*2e1d0745SJose E. Roman coneSizesName = "cone_sizes"; 2220*2e1d0745SJose E. Roman conesName = "cones"; 2221*2e1d0745SJose E. Roman orientationsName = "orientations"; 2222*2e1d0745SJose E. Roman PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm)); 2223*2e1d0745SJose E. Roman 2224*2e1d0745SJose E. Roman /* query size of next lower depth stratum (next lower dimension) */ 2225*2e1d0745SJose E. Roman if (d > 0) { 2226*2e1d0745SJose E. Roman PetscInt NVertices; 2227*2e1d0745SJose E. Roman 2228*2e1d0745SJose E. Roman PetscCall(PetscSNPrintf(path, sizeof(path), "%" PetscInt_FMT "/%s", d - 1, coneSizesName)); 2229*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5ReadSizes(viewer, path, NULL, &NVertices)); 2230*2e1d0745SJose E. Roman PetscCall(PetscLayoutCreate(comm, &vertexLayout)); 2231*2e1d0745SJose E. Roman PetscCall(PetscLayoutSetSize(vertexLayout, NVertices)); 2232*2e1d0745SJose E. Roman PetscCall(PetscLayoutSetUp(vertexLayout)); 2233*2e1d0745SJose E. Roman } 2234*2e1d0745SJose E. Roman 2235*2e1d0745SJose E. Roman PetscCall(PetscSNPrintf(path, sizeof(path), "%" PetscInt_FMT, d)); 2236*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, path)); 2237*2e1d0745SJose E. Roman 2238*2e1d0745SJose E. Roman /* create coneSizesSection from stored IS coneSizes */ 2239*2e1d0745SJose E. Roman { 2240*2e1d0745SJose E. Roman const PetscInt *coneSizes; 2241*2e1d0745SJose E. Roman 2242*2e1d0745SJose E. Roman PetscCall(ISCreate(comm, &coneSizesIS)); 2243*2e1d0745SJose E. Roman PetscCall(PetscObjectSetName((PetscObject)coneSizesIS, coneSizesName)); 2244*2e1d0745SJose E. Roman if (pointsLayout) PetscCall(ISSetLayout(coneSizesIS, pointsLayout)); 2245*2e1d0745SJose E. Roman PetscCall(ISLoad(coneSizesIS, viewer)); 2246*2e1d0745SJose E. Roman if (!pointsLayout) PetscCall(ISGetLayout(coneSizesIS, &pointsLayout)); 2247*2e1d0745SJose E. Roman PetscCall(ISGetIndices(coneSizesIS, &coneSizes)); 2248*2e1d0745SJose E. Roman PetscCall(PetscSectionCreate(comm, &coneSizesSection)); 2249*2e1d0745SJose E. Roman //TODO different start ? 2250*2e1d0745SJose E. Roman PetscCall(PetscSectionSetChart(coneSizesSection, 0, pointsLayout->n)); 2251*2e1d0745SJose E. Roman for (s = 0; s < pointsLayout->n; ++s) PetscCall(PetscSectionSetDof(coneSizesSection, s, coneSizes[s])); 2252*2e1d0745SJose E. Roman PetscCall(PetscSectionSetUp(coneSizesSection)); 2253*2e1d0745SJose E. Roman PetscCall(ISRestoreIndices(coneSizesIS, &coneSizes)); 2254*2e1d0745SJose E. Roman { 2255*2e1d0745SJose E. Roman PetscLayout tmp = NULL; 2256*2e1d0745SJose E. Roman 2257*2e1d0745SJose E. Roman /* We need to keep the layout until the end of function */ 2258*2e1d0745SJose E. Roman PetscCall(PetscLayoutReference((PetscLayout)pointsLayout, &tmp)); 2259*2e1d0745SJose E. Roman } 2260*2e1d0745SJose E. Roman PetscCall(ISDestroy(&coneSizesIS)); 2261*2e1d0745SJose E. Roman } 2262*2e1d0745SJose E. Roman 2263*2e1d0745SJose E. Roman /* use value layout of coneSizesSection as layout of cones and orientations */ 2264*2e1d0745SJose E. Roman { 2265*2e1d0745SJose E. Roman PetscLayout conesLayout; 2266*2e1d0745SJose E. Roman 2267*2e1d0745SJose E. Roman PetscCall(PetscSectionGetValueLayout(comm, coneSizesSection, &conesLayout)); 2268*2e1d0745SJose E. Roman PetscCall(ISCreate(comm, &conesIS)); 2269*2e1d0745SJose E. Roman PetscCall(ISCreate(comm, &orientationsIS)); 2270*2e1d0745SJose E. Roman PetscCall(PetscObjectSetName((PetscObject)conesIS, conesName)); 2271*2e1d0745SJose E. Roman PetscCall(PetscObjectSetName((PetscObject)orientationsIS, orientationsName)); 2272*2e1d0745SJose E. Roman PetscCall(PetscLayoutDuplicate(conesLayout, &conesIS->map)); 2273*2e1d0745SJose E. Roman PetscCall(PetscLayoutDuplicate(conesLayout, &orientationsIS->map)); 2274*2e1d0745SJose E. Roman PetscCall(ISLoad(conesIS, viewer)); 2275*2e1d0745SJose E. Roman PetscCall(ISLoad(orientationsIS, viewer)); 2276*2e1d0745SJose E. Roman PetscCall(PetscLayoutDestroy(&conesLayout)); 2277*2e1d0745SJose E. Roman } 2278*2e1d0745SJose E. Roman 2279*2e1d0745SJose E. Roman /* check assertion that layout of points is the same as point layout of coneSizesSection */ 2280*2e1d0745SJose E. Roman { 2281*2e1d0745SJose E. Roman PetscLayout pointsLayout0; 2282*2e1d0745SJose E. Roman PetscBool flg; 2283*2e1d0745SJose E. Roman 2284*2e1d0745SJose E. Roman PetscCall(PetscSectionGetPointLayout(comm, coneSizesSection, &pointsLayout0)); 2285*2e1d0745SJose E. Roman PetscCall(PetscLayoutCompare(pointsLayout, pointsLayout0, &flg)); 2286*2e1d0745SJose E. Roman PetscCheck(flg, comm, PETSC_ERR_PLIB, "points layout != coneSizesSection point layout"); 2287*2e1d0745SJose E. Roman PetscCall(PetscLayoutDestroy(&pointsLayout0)); 2288*2e1d0745SJose E. Roman } 2289*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 2290*2e1d0745SJose E. Roman PetscCall(PetscLayoutDestroy(&pointsLayout)); 2291*2e1d0745SJose E. Roman 2292*2e1d0745SJose E. Roman layer->d = d; 2293*2e1d0745SJose E. Roman layer->conesIS = conesIS; 2294*2e1d0745SJose E. Roman layer->coneSizesSection = coneSizesSection; 2295*2e1d0745SJose E. Roman layer->orientationsIS = orientationsIS; 2296*2e1d0745SJose E. Roman layer->vertexLayout = vertexLayout; 2297*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 2298*2e1d0745SJose E. Roman } 2299*2e1d0745SJose E. Roman 2300*2e1d0745SJose E. Roman static PetscErrorCode PlexLayerDistribute_Private(PlexLayer layer, PetscSF cellLocalToGlobalSF) 2301*2e1d0745SJose E. Roman { 2302*2e1d0745SJose E. Roman IS newConesIS, newOrientationsIS; 2303*2e1d0745SJose E. Roman PetscSection newConeSizesSection; 2304*2e1d0745SJose E. Roman MPI_Comm comm; 2305*2e1d0745SJose E. Roman 2306*2e1d0745SJose E. Roman PetscFunctionBegin; 2307*2e1d0745SJose E. Roman PetscCall(PetscObjectGetComm((PetscObject)cellLocalToGlobalSF, &comm)); 2308*2e1d0745SJose E. Roman PetscCall(PetscSectionCreate(comm, &newConeSizesSection)); 2309*2e1d0745SJose E. Roman //TODO rename to something like ISDistribute() with optional PetscSection argument 2310*2e1d0745SJose E. Roman PetscCall(DMPlexDistributeFieldIS(NULL, cellLocalToGlobalSF, layer->coneSizesSection, layer->conesIS, newConeSizesSection, &newConesIS)); 2311*2e1d0745SJose E. Roman PetscCall(DMPlexDistributeFieldIS(NULL, cellLocalToGlobalSF, layer->coneSizesSection, layer->orientationsIS, newConeSizesSection, &newOrientationsIS)); 2312*2e1d0745SJose E. Roman 2313*2e1d0745SJose E. Roman PetscCall(PetscObjectSetName((PetscObject)newConeSizesSection, ((PetscObject)layer->coneSizesSection)->name)); 2314*2e1d0745SJose E. Roman PetscCall(PetscObjectSetName((PetscObject)newConesIS, ((PetscObject)layer->conesIS)->name)); 2315*2e1d0745SJose E. Roman PetscCall(PetscObjectSetName((PetscObject)newOrientationsIS, ((PetscObject)layer->orientationsIS)->name)); 2316*2e1d0745SJose E. Roman PetscCall(PetscSectionDestroy(&layer->coneSizesSection)); 2317*2e1d0745SJose E. Roman PetscCall(ISDestroy(&layer->conesIS)); 2318*2e1d0745SJose E. Roman PetscCall(ISDestroy(&layer->orientationsIS)); 2319*2e1d0745SJose E. Roman layer->coneSizesSection = newConeSizesSection; 2320*2e1d0745SJose E. Roman layer->conesIS = newConesIS; 2321*2e1d0745SJose E. Roman layer->orientationsIS = newOrientationsIS; 2322*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 2323*2e1d0745SJose E. Roman } 2324*2e1d0745SJose E. Roman 2325*2e1d0745SJose E. Roman //TODO share code with DMPlexBuildFromCellListParallel() 2326*2e1d0745SJose E. Roman #include <petsc/private/hashseti.h> 2327*2e1d0745SJose E. Roman static PetscErrorCode PlexLayerCreateSFs_Private(PlexLayer layer, PetscSF *vertexOverlapSF, PetscSF *sfXC) 2328*2e1d0745SJose E. Roman { 2329*2e1d0745SJose E. Roman PetscLayout vertexLayout = layer->vertexLayout; 2330*2e1d0745SJose E. Roman PetscSection coneSection = layer->coneSizesSection; 2331*2e1d0745SJose E. Roman IS cellVertexData = layer->conesIS; 2332*2e1d0745SJose E. Roman IS coneOrientations = layer->orientationsIS; 2333*2e1d0745SJose E. Roman PetscSF vl2gSF, vOverlapSF; 2334*2e1d0745SJose E. Roman PetscInt *verticesAdj; 2335*2e1d0745SJose E. Roman PetscInt i, n, numVerticesAdj; 2336*2e1d0745SJose E. Roman const PetscInt *cvd, *co = NULL; 2337*2e1d0745SJose E. Roman MPI_Comm comm; 2338*2e1d0745SJose E. Roman 2339*2e1d0745SJose E. Roman PetscFunctionBegin; 2340*2e1d0745SJose E. Roman PetscCall(PetscObjectGetComm((PetscObject)coneSection, &comm)); 2341*2e1d0745SJose E. Roman PetscCall(PetscSectionGetStorageSize(coneSection, &n)); 2342*2e1d0745SJose E. Roman { 2343*2e1d0745SJose E. Roman PetscInt n0; 2344*2e1d0745SJose E. Roman 2345*2e1d0745SJose E. Roman PetscCall(ISGetLocalSize(cellVertexData, &n0)); 2346*2e1d0745SJose 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); 2347*2e1d0745SJose E. Roman PetscCall(ISGetIndices(cellVertexData, &cvd)); 2348*2e1d0745SJose E. Roman } 2349*2e1d0745SJose E. Roman if (coneOrientations) { 2350*2e1d0745SJose E. Roman PetscInt n0; 2351*2e1d0745SJose E. Roman 2352*2e1d0745SJose E. Roman PetscCall(ISGetLocalSize(coneOrientations, &n0)); 2353*2e1d0745SJose 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); 2354*2e1d0745SJose E. Roman PetscCall(ISGetIndices(coneOrientations, &co)); 2355*2e1d0745SJose E. Roman } 2356*2e1d0745SJose E. Roman /* Get/check global number of vertices */ 2357*2e1d0745SJose E. Roman { 2358*2e1d0745SJose E. Roman PetscInt NVerticesInCells = PETSC_INT_MIN; 2359*2e1d0745SJose E. Roman 2360*2e1d0745SJose E. Roman /* NVerticesInCells = max(cellVertexData) + 1 */ 2361*2e1d0745SJose E. Roman for (i = 0; i < n; i++) 2362*2e1d0745SJose E. Roman if (cvd[i] > NVerticesInCells) NVerticesInCells = cvd[i]; 2363*2e1d0745SJose E. Roman ++NVerticesInCells; 2364*2e1d0745SJose E. Roman PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, comm)); 2365*2e1d0745SJose E. Roman 2366*2e1d0745SJose E. Roman if (vertexLayout->n == PETSC_DECIDE && vertexLayout->N == PETSC_DECIDE) vertexLayout->N = NVerticesInCells; 2367*2e1d0745SJose E. Roman else 2368*2e1d0745SJose 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, 2369*2e1d0745SJose E. Roman vertexLayout->N, NVerticesInCells); 2370*2e1d0745SJose E. Roman PetscCall(PetscLayoutSetUp(vertexLayout)); 2371*2e1d0745SJose E. Roman } 2372*2e1d0745SJose E. Roman /* Find locally unique vertices in cellVertexData */ 2373*2e1d0745SJose E. Roman { 2374*2e1d0745SJose E. Roman PetscHSetI vhash; 2375*2e1d0745SJose E. Roman PetscInt off = 0; 2376*2e1d0745SJose E. Roman 2377*2e1d0745SJose E. Roman PetscCall(PetscHSetICreate(&vhash)); 2378*2e1d0745SJose E. Roman for (i = 0; i < n; ++i) PetscCall(PetscHSetIAdd(vhash, cvd[i])); 2379*2e1d0745SJose E. Roman PetscCall(PetscHSetIGetSize(vhash, &numVerticesAdj)); 2380*2e1d0745SJose E. Roman PetscCall(PetscMalloc1(numVerticesAdj, &verticesAdj)); 2381*2e1d0745SJose E. Roman PetscCall(PetscHSetIGetElems(vhash, &off, verticesAdj)); 2382*2e1d0745SJose E. Roman PetscAssert(off == numVerticesAdj, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Assertion failed: off == numVerticesAdj (%" PetscInt_FMT " != %" PetscInt_FMT ")", off, numVerticesAdj); 2383*2e1d0745SJose E. Roman PetscCall(PetscHSetIDestroy(&vhash)); 2384*2e1d0745SJose E. Roman } 2385*2e1d0745SJose E. Roman /* We must sort vertices to preserve numbering */ 2386*2e1d0745SJose E. Roman PetscCall(PetscSortInt(numVerticesAdj, verticesAdj)); 2387*2e1d0745SJose E. Roman /* Connect locally unique vertices with star forest */ 2388*2e1d0745SJose E. Roman PetscCall(PetscSFCreateByMatchingIndices(vertexLayout, numVerticesAdj, verticesAdj, NULL, 0, numVerticesAdj, verticesAdj, NULL, 0, &vl2gSF, &vOverlapSF)); 2389*2e1d0745SJose E. Roman PetscCall(PetscObjectSetName((PetscObject)vOverlapSF, "overlapSF")); 2390*2e1d0745SJose E. Roman PetscCall(PetscObjectSetName((PetscObject)vl2gSF, "localToGlobalSF")); 2391*2e1d0745SJose E. Roman 2392*2e1d0745SJose E. Roman PetscCall(PetscFree(verticesAdj)); 2393*2e1d0745SJose E. Roman *vertexOverlapSF = vOverlapSF; 2394*2e1d0745SJose E. Roman *sfXC = vl2gSF; 2395*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 2396*2e1d0745SJose E. Roman } 2397*2e1d0745SJose E. Roman 2398*2e1d0745SJose E. Roman static PetscErrorCode PlexLayerCreateCellSFs_Private(PlexLayer layer, PetscSF *cellOverlapSF, PetscSF *cellLocalToGlobalSF) 2399*2e1d0745SJose E. Roman { 2400*2e1d0745SJose E. Roman PetscSection coneSection = layer->coneSizesSection; 2401*2e1d0745SJose E. Roman PetscInt nCells; 2402*2e1d0745SJose E. Roman MPI_Comm comm; 2403*2e1d0745SJose E. Roman 2404*2e1d0745SJose E. Roman PetscFunctionBegin; 2405*2e1d0745SJose E. Roman PetscCall(PetscObjectGetComm((PetscObject)coneSection, &comm)); 2406*2e1d0745SJose E. Roman { 2407*2e1d0745SJose E. Roman PetscInt cStart; 2408*2e1d0745SJose E. Roman 2409*2e1d0745SJose E. Roman PetscCall(PetscSectionGetChart(coneSection, &cStart, &nCells)); 2410*2e1d0745SJose E. Roman PetscCheck(cStart == 0, comm, PETSC_ERR_ARG_OUTOFRANGE, "coneSection must start at 0"); 2411*2e1d0745SJose E. Roman } 2412*2e1d0745SJose E. Roman /* Create overlapSF as empty SF with the right number of roots */ 2413*2e1d0745SJose E. Roman PetscCall(PetscSFCreate(comm, cellOverlapSF)); 2414*2e1d0745SJose E. Roman PetscCall(PetscSFSetGraph(*cellOverlapSF, nCells, 0, NULL, PETSC_USE_POINTER, NULL, PETSC_USE_POINTER)); 2415*2e1d0745SJose E. Roman PetscCall(PetscSFSetUp(*cellOverlapSF)); 2416*2e1d0745SJose E. Roman /* Create localToGlobalSF as identity mapping */ 2417*2e1d0745SJose E. Roman { 2418*2e1d0745SJose E. Roman PetscLayout map; 2419*2e1d0745SJose E. Roman 2420*2e1d0745SJose E. Roman PetscCall(PetscLayoutCreateFromSizes(comm, nCells, PETSC_DECIDE, 1, &map)); 2421*2e1d0745SJose E. Roman PetscCall(PetscSFCreateFromLayouts(map, map, cellLocalToGlobalSF)); 2422*2e1d0745SJose E. Roman PetscCall(PetscSFSetUp(*cellLocalToGlobalSF)); 2423*2e1d0745SJose E. Roman PetscCall(PetscLayoutDestroy(&map)); 2424*2e1d0745SJose E. Roman } 2425*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 2426*2e1d0745SJose E. Roman } 2427*2e1d0745SJose E. Roman 2428*2e1d0745SJose E. Roman static PetscErrorCode DMPlexTopologyBuildFromLayers_Private(DM dm, PetscInt depth, PlexLayer *layers, IS strataPermutation) 2429*2e1d0745SJose E. Roman { 2430*2e1d0745SJose E. Roman const PetscInt *permArr; 2431*2e1d0745SJose E. Roman PetscInt d, nPoints; 2432*2e1d0745SJose E. Roman MPI_Comm comm; 2433*2e1d0745SJose E. Roman 2434*2e1d0745SJose E. Roman PetscFunctionBegin; 2435*2e1d0745SJose E. Roman PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 2436*2e1d0745SJose E. Roman PetscCall(ISGetIndices(strataPermutation, &permArr)); 2437*2e1d0745SJose E. Roman 2438*2e1d0745SJose E. Roman /* Count points, strata offsets and cones offsets (taking strataPermutation into account) */ 2439*2e1d0745SJose E. Roman { 2440*2e1d0745SJose E. Roman PetscInt stratumOffset = 0; 2441*2e1d0745SJose E. Roman PetscInt conesOffset = 0; 2442*2e1d0745SJose E. Roman 2443*2e1d0745SJose E. Roman for (d = 0; d <= depth; d++) { 2444*2e1d0745SJose E. Roman const PetscInt e = permArr[d]; 2445*2e1d0745SJose E. Roman const PlexLayer l = layers[e]; 2446*2e1d0745SJose E. Roman PetscInt lo, n, size; 2447*2e1d0745SJose E. Roman 2448*2e1d0745SJose E. Roman PetscCall(PetscSectionGetChart(l->coneSizesSection, &lo, &n)); 2449*2e1d0745SJose E. Roman PetscCall(PetscSectionGetStorageSize(l->coneSizesSection, &size)); 2450*2e1d0745SJose E. Roman PetscCheck(lo == 0, comm, PETSC_ERR_PLIB, "starting point should be 0 in coneSizesSection %" PetscInt_FMT, d); 2451*2e1d0745SJose E. Roman l->offset = stratumOffset; 2452*2e1d0745SJose E. Roman l->conesOffset = conesOffset; 2453*2e1d0745SJose E. Roman stratumOffset += n; 2454*2e1d0745SJose E. Roman conesOffset += size; 2455*2e1d0745SJose E. Roman } 2456*2e1d0745SJose E. Roman nPoints = stratumOffset; 2457*2e1d0745SJose E. Roman } 2458*2e1d0745SJose E. Roman 2459*2e1d0745SJose E. Roman /* Set interval for all plex points */ 2460*2e1d0745SJose E. Roman //TODO we should store starting point of plex 2461*2e1d0745SJose E. Roman PetscCall(DMPlexSetChart(dm, 0, nPoints)); 2462*2e1d0745SJose E. Roman 2463*2e1d0745SJose E. Roman /* Set up plex coneSection from layer coneSections */ 2464*2e1d0745SJose E. Roman { 2465*2e1d0745SJose E. Roman PetscSection coneSection; 2466*2e1d0745SJose E. Roman 2467*2e1d0745SJose E. Roman PetscCall(DMPlexGetConeSection(dm, &coneSection)); 2468*2e1d0745SJose E. Roman for (d = 0; d <= depth; d++) { 2469*2e1d0745SJose E. Roman const PlexLayer l = layers[d]; 2470*2e1d0745SJose E. Roman PetscInt n, q; 2471*2e1d0745SJose E. Roman 2472*2e1d0745SJose E. Roman PetscCall(PetscSectionGetChart(l->coneSizesSection, NULL, &n)); 2473*2e1d0745SJose E. Roman for (q = 0; q < n; q++) { 2474*2e1d0745SJose E. Roman const PetscInt p = l->offset + q; 2475*2e1d0745SJose E. Roman PetscInt coneSize; 2476*2e1d0745SJose E. Roman 2477*2e1d0745SJose E. Roman PetscCall(PetscSectionGetDof(l->coneSizesSection, q, &coneSize)); 2478*2e1d0745SJose E. Roman PetscCall(PetscSectionSetDof(coneSection, p, coneSize)); 2479*2e1d0745SJose E. Roman } 2480*2e1d0745SJose E. Roman } 2481*2e1d0745SJose E. Roman } 2482*2e1d0745SJose E. Roman //TODO this is terrible, DMSetUp_Plex() should be DMPlexSetUpSections() or so 2483*2e1d0745SJose E. Roman PetscCall(DMSetUp(dm)); 2484*2e1d0745SJose E. Roman 2485*2e1d0745SJose E. Roman /* Renumber cones points from layer-global numbering to plex-local numbering */ 2486*2e1d0745SJose E. Roman { 2487*2e1d0745SJose E. Roman PetscInt *cones, *ornts; 2488*2e1d0745SJose E. Roman 2489*2e1d0745SJose E. Roman PetscCall(DMPlexGetCones(dm, &cones)); 2490*2e1d0745SJose E. Roman PetscCall(DMPlexGetConeOrientations(dm, &ornts)); 2491*2e1d0745SJose E. Roman for (d = 1; d <= depth; d++) { 2492*2e1d0745SJose E. Roman const PlexLayer l = layers[d]; 2493*2e1d0745SJose E. Roman PetscInt i, lConesSize; 2494*2e1d0745SJose E. Roman PetscInt *lCones; 2495*2e1d0745SJose E. Roman const PetscInt *lOrnts; 2496*2e1d0745SJose E. Roman PetscInt *pCones = &cones[l->conesOffset]; 2497*2e1d0745SJose E. Roman PetscInt *pOrnts = &ornts[l->conesOffset]; 2498*2e1d0745SJose E. Roman 2499*2e1d0745SJose E. Roman PetscCall(PetscSectionGetStorageSize(l->coneSizesSection, &lConesSize)); 2500*2e1d0745SJose E. Roman /* Get cones in local plex numbering */ 2501*2e1d0745SJose E. Roman { 2502*2e1d0745SJose E. Roman ISLocalToGlobalMapping l2g; 2503*2e1d0745SJose E. Roman PetscLayout vertexLayout = l->vertexLayout; 2504*2e1d0745SJose E. Roman PetscSF vertexSF = layers[d - 1]->l2gSF; /* vertices of this layer are cells of previous layer */ 2505*2e1d0745SJose E. Roman const PetscInt *gCones; 2506*2e1d0745SJose E. Roman PetscInt lConesSize0; 2507*2e1d0745SJose E. Roman 2508*2e1d0745SJose E. Roman PetscCall(ISGetLocalSize(l->conesIS, &lConesSize0)); 2509*2e1d0745SJose E. Roman PetscCheck(lConesSize0 == lConesSize, comm, PETSC_ERR_PLIB, "layer %" PetscInt_FMT " size(conesIS) = %" PetscInt_FMT " != %" PetscInt_FMT " = storageSize(coneSizesSection)", d, lConesSize0, lConesSize); 2510*2e1d0745SJose E. Roman PetscCall(ISGetLocalSize(l->orientationsIS, &lConesSize0)); 2511*2e1d0745SJose E. Roman PetscCheck(lConesSize0 == lConesSize, comm, PETSC_ERR_PLIB, "layer %" PetscInt_FMT " size(orientationsIS) = %" PetscInt_FMT " != %" PetscInt_FMT " = storageSize(coneSizesSection)", d, lConesSize0, lConesSize); 2512*2e1d0745SJose E. Roman 2513*2e1d0745SJose E. Roman PetscCall(PetscMalloc1(lConesSize, &lCones)); 2514*2e1d0745SJose E. Roman PetscCall(ISGetIndices(l->conesIS, &gCones)); 2515*2e1d0745SJose E. Roman PetscCall(ISLocalToGlobalMappingCreateSF(vertexSF, vertexLayout->rstart, &l2g)); 2516*2e1d0745SJose E. Roman PetscCall(ISGlobalToLocalMappingApply(l2g, IS_GTOLM_MASK, lConesSize, gCones, &lConesSize0, lCones)); 2517*2e1d0745SJose E. Roman PetscCheck(lConesSize0 == lConesSize, comm, PETSC_ERR_PLIB, "global to local does not cover all indices (%" PetscInt_FMT " of %" PetscInt_FMT ")", lConesSize0, lConesSize); 2518*2e1d0745SJose E. Roman PetscCall(ISLocalToGlobalMappingDestroy(&l2g)); 2519*2e1d0745SJose E. Roman PetscCall(ISRestoreIndices(l->conesIS, &gCones)); 2520*2e1d0745SJose E. Roman } 2521*2e1d0745SJose E. Roman PetscCall(ISGetIndices(l->orientationsIS, &lOrnts)); 2522*2e1d0745SJose E. Roman /* Set cones, need to add stratum offset */ 2523*2e1d0745SJose E. Roman for (i = 0; i < lConesSize; i++) { 2524*2e1d0745SJose E. Roman pCones[i] = lCones[i] + layers[d - 1]->offset; /* cone points of current layer are points of previous layer */ 2525*2e1d0745SJose E. Roman pOrnts[i] = lOrnts[i]; 2526*2e1d0745SJose E. Roman } 2527*2e1d0745SJose E. Roman PetscCall(PetscFree(lCones)); 2528*2e1d0745SJose E. Roman PetscCall(ISRestoreIndices(l->orientationsIS, &lOrnts)); 2529*2e1d0745SJose E. Roman } 2530*2e1d0745SJose E. Roman } 2531*2e1d0745SJose E. Roman PetscCall(DMPlexSymmetrize(dm)); 2532*2e1d0745SJose E. Roman PetscCall(DMPlexStratify(dm)); 2533*2e1d0745SJose E. Roman PetscCall(ISRestoreIndices(strataPermutation, &permArr)); 2534*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 2535*2e1d0745SJose E. Roman } 2536*2e1d0745SJose E. Roman 2537*2e1d0745SJose E. Roman static PetscErrorCode PlexLayerConcatenateSFs_Private(MPI_Comm comm, PetscInt depth, PlexLayer layers[], IS strataPermutation, PetscSF *overlapSF, PetscSF *l2gSF) 2538*2e1d0745SJose E. Roman { 2539*2e1d0745SJose E. Roman PetscInt d; 2540*2e1d0745SJose E. Roman PetscSF *osfs, *lsfs; 2541*2e1d0745SJose E. Roman PetscInt *leafOffsets; 2542*2e1d0745SJose E. Roman const PetscInt *permArr; 2543*2e1d0745SJose E. Roman 2544*2e1d0745SJose E. Roman PetscFunctionBegin; 2545*2e1d0745SJose E. Roman PetscCall(ISGetIndices(strataPermutation, &permArr)); 2546*2e1d0745SJose E. Roman PetscCall(PetscCalloc3(depth + 1, &osfs, depth + 1, &lsfs, depth + 1, &leafOffsets)); 2547*2e1d0745SJose E. Roman for (d = 0; d <= depth; d++) { 2548*2e1d0745SJose E. Roman const PetscInt e = permArr[d]; 2549*2e1d0745SJose E. Roman 2550*2e1d0745SJose E. Roman PetscAssert(e == layers[e]->d, PETSC_COMM_SELF, PETSC_ERR_PLIB, "assertion: e == layers[e]->d"); 2551*2e1d0745SJose E. Roman osfs[d] = layers[e]->overlapSF; 2552*2e1d0745SJose E. Roman lsfs[d] = layers[e]->l2gSF; 2553*2e1d0745SJose E. Roman leafOffsets[d] = layers[e]->offset; 2554*2e1d0745SJose E. Roman } 2555*2e1d0745SJose E. Roman PetscCall(PetscSFConcatenate(comm, depth + 1, osfs, PETSCSF_CONCATENATE_ROOTMODE_LOCAL, leafOffsets, overlapSF)); 2556*2e1d0745SJose E. Roman PetscCall(PetscSFConcatenate(comm, depth + 1, lsfs, PETSCSF_CONCATENATE_ROOTMODE_GLOBAL, leafOffsets, l2gSF)); 2557*2e1d0745SJose E. Roman PetscCall(PetscFree3(osfs, lsfs, leafOffsets)); 2558*2e1d0745SJose E. Roman PetscCall(ISRestoreIndices(strataPermutation, &permArr)); 2559*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 2560*2e1d0745SJose E. Roman } 2561*2e1d0745SJose E. Roman 2562*2e1d0745SJose E. Roman // Parallel load of topology 2563*2e1d0745SJose E. Roman static PetscErrorCode DMPlexTopologyLoad_HDF5_Private(DM dm, PetscViewer viewer, PetscSF *sfXC) 2564*2e1d0745SJose E. Roman { 2565*2e1d0745SJose E. Roman PlexLayer *layers; 2566*2e1d0745SJose E. Roman IS strataPermutation; 2567*2e1d0745SJose E. Roman PetscLayout pointsLayout; 2568*2e1d0745SJose E. Roman PetscInt depth; 2569*2e1d0745SJose E. Roman PetscInt d; 2570*2e1d0745SJose E. Roman MPI_Comm comm; 2571*2e1d0745SJose E. Roman 2572*2e1d0745SJose E. Roman PetscFunctionBegin; 2573*2e1d0745SJose E. Roman { 2574*2e1d0745SJose E. Roman PetscInt dim; 2575*2e1d0745SJose E. Roman 2576*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5ReadAttribute(viewer, NULL, "depth", PETSC_INT, NULL, &depth)); 2577*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5ReadAttribute(viewer, NULL, "cell_dim", PETSC_INT, NULL, &dim)); 2578*2e1d0745SJose E. Roman PetscCall(DMSetDimension(dm, dim)); 2579*2e1d0745SJose E. Roman } 2580*2e1d0745SJose E. Roman PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 2581*2e1d0745SJose E. Roman 2582*2e1d0745SJose E. Roman PetscCall(PetscInfo(dm, "Loading DM %s in parallel\n", dm->hdr.name)); 2583*2e1d0745SJose E. Roman { 2584*2e1d0745SJose E. Roman IS spOnComm; 2585*2e1d0745SJose E. Roman 2586*2e1d0745SJose E. Roman PetscCall(ISCreate(comm, &spOnComm)); 2587*2e1d0745SJose E. Roman PetscCall(PetscObjectSetName((PetscObject)spOnComm, "permutation")); 2588*2e1d0745SJose E. Roman PetscCall(ISLoad(spOnComm, viewer)); 2589*2e1d0745SJose E. Roman /* have the same serial IS on every rank */ 2590*2e1d0745SJose E. Roman PetscCall(ISAllGather(spOnComm, &strataPermutation)); 2591*2e1d0745SJose E. Roman PetscCall(PetscObjectSetName((PetscObject)strataPermutation, ((PetscObject)spOnComm)->name)); 2592*2e1d0745SJose E. Roman PetscCall(ISDestroy(&spOnComm)); 2593*2e1d0745SJose E. Roman } 2594*2e1d0745SJose E. Roman 2595*2e1d0745SJose E. Roman /* Create layers, load raw data for each layer */ 2596*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, "strata")); 2597*2e1d0745SJose E. Roman PetscCall(PetscMalloc1(depth + 1, &layers)); 2598*2e1d0745SJose E. Roman for (d = depth, pointsLayout = NULL; d >= 0; pointsLayout = layers[d]->vertexLayout, d--) { 2599*2e1d0745SJose E. Roman PetscCall(PlexLayerCreate_Private(&layers[d])); 2600*2e1d0745SJose E. Roman PetscCall(PlexLayerLoad_Private(layers[d], viewer, d, pointsLayout)); 2601*2e1d0745SJose E. Roman } 2602*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); /* strata */ 2603*2e1d0745SJose E. Roman 2604*2e1d0745SJose E. Roman for (d = depth; d >= 0; d--) { 2605*2e1d0745SJose E. Roman /* Redistribute cells and vertices for each applicable layer */ 2606*2e1d0745SJose E. Roman if (d < depth) PetscCall(PlexLayerDistribute_Private(layers[d], layers[d]->l2gSF)); 2607*2e1d0745SJose E. Roman /* Create vertex overlap SF and vertex localToGlobal SF for each applicable layer */ 2608*2e1d0745SJose E. Roman if (d > 0) PetscCall(PlexLayerCreateSFs_Private(layers[d], &layers[d - 1]->overlapSF, &layers[d - 1]->l2gSF)); 2609*2e1d0745SJose E. Roman } 2610*2e1d0745SJose E. Roman /* Build trivial SFs for the cell layer as well */ 2611*2e1d0745SJose E. Roman PetscCall(PlexLayerCreateCellSFs_Private(layers[depth], &layers[depth]->overlapSF, &layers[depth]->l2gSF)); 2612*2e1d0745SJose E. Roman 2613*2e1d0745SJose E. Roman /* Build DMPlex topology from the layers */ 2614*2e1d0745SJose E. Roman PetscCall(DMPlexTopologyBuildFromLayers_Private(dm, depth, layers, strataPermutation)); 2615*2e1d0745SJose E. Roman 2616*2e1d0745SJose E. Roman /* Build overall point SF alias overlap SF */ 2617*2e1d0745SJose E. Roman { 2618*2e1d0745SJose E. Roman PetscSF overlapSF; 2619*2e1d0745SJose E. Roman 2620*2e1d0745SJose E. Roman PetscCall(PlexLayerConcatenateSFs_Private(comm, depth, layers, strataPermutation, &overlapSF, sfXC)); 2621*2e1d0745SJose E. Roman PetscCall(DMSetPointSF(dm, overlapSF)); 2622*2e1d0745SJose E. Roman PetscCall(PetscSFDestroy(&overlapSF)); 2623*2e1d0745SJose E. Roman } 2624*2e1d0745SJose E. Roman 2625*2e1d0745SJose E. Roman for (d = depth; d >= 0; d--) PetscCall(PlexLayerDestroy(&layers[d])); 2626*2e1d0745SJose E. Roman PetscCall(PetscFree(layers)); 2627*2e1d0745SJose E. Roman PetscCall(ISDestroy(&strataPermutation)); 2628*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 2629*2e1d0745SJose E. Roman } 2630*2e1d0745SJose E. Roman 2631*2e1d0745SJose E. Roman PetscErrorCode DMPlexTopologyLoad_HDF5_Internal(DM dm, PetscViewer viewer, PetscSF *sfXC) 2632*2e1d0745SJose E. Roman { 2633*2e1d0745SJose E. Roman DMPlexStorageVersion version; 2634*2e1d0745SJose E. Roman const char *topologydm_name; 2635*2e1d0745SJose E. Roman char group[PETSC_MAX_PATH_LEN]; 2636*2e1d0745SJose E. Roman PetscSF sfwork = NULL; 2637*2e1d0745SJose E. Roman 2638*2e1d0745SJose E. Roman PetscFunctionBegin; 2639*2e1d0745SJose E. Roman PetscCall(DMPlexGetHDF5Name_Private(dm, &topologydm_name)); 2640*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5GetDMPlexStorageVersionReading(viewer, &version)); 2641*2e1d0745SJose E. Roman if (DMPlexStorageVersionGE(version, 2, 0, 0)) { 2642*2e1d0745SJose E. Roman PetscCall(PetscSNPrintf(group, sizeof(group), "topologies/%s", topologydm_name)); 2643*2e1d0745SJose E. Roman } else { 2644*2e1d0745SJose E. Roman PetscCall(PetscStrncpy(group, "/", sizeof(group))); 2645*2e1d0745SJose E. Roman } 2646*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, group)); 2647*2e1d0745SJose E. Roman 2648*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, "topology")); 2649*2e1d0745SJose E. Roman if (version->major < 3) { 2650*2e1d0745SJose E. Roman PetscCall(DMPlexTopologyLoad_HDF5_Legacy_Private(dm, viewer, &sfwork)); 2651*2e1d0745SJose E. Roman } else { 2652*2e1d0745SJose E. Roman /* since DMPlexStorageVersion 3.0.0 */ 2653*2e1d0745SJose E. Roman PetscCall(DMPlexTopologyLoad_HDF5_Private(dm, viewer, &sfwork)); 2654*2e1d0745SJose E. Roman } 2655*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); /* "topology" */ 2656*2e1d0745SJose E. Roman 2657*2e1d0745SJose E. Roman if (DMPlexStorageVersionGE(version, 2, 0, 0)) { 2658*2e1d0745SJose E. Roman DM distdm; 2659*2e1d0745SJose E. Roman PetscSF distsf; 2660*2e1d0745SJose E. Roman const char *distribution_name; 2661*2e1d0745SJose E. Roman PetscBool exists; 2662*2e1d0745SJose E. Roman 2663*2e1d0745SJose E. Roman PetscCall(DMPlexDistributionGetName(dm, &distribution_name)); 2664*2e1d0745SJose E. Roman /* this group is guaranteed to be present since DMPlexStorageVersion 2.1.0 */ 2665*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, "distributions")); 2666*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5HasGroup(viewer, NULL, &exists)); 2667*2e1d0745SJose E. Roman if (exists) { 2668*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, distribution_name)); 2669*2e1d0745SJose E. Roman PetscCall(DMPlexDistributionLoad_HDF5_Private(dm, viewer, sfwork, &distsf, &distdm)); 2670*2e1d0745SJose E. Roman if (distdm) { 2671*2e1d0745SJose E. Roman PetscCall(DMPlexReplace_Internal(dm, &distdm)); 2672*2e1d0745SJose E. Roman PetscCall(PetscSFDestroy(&sfwork)); 2673*2e1d0745SJose E. Roman sfwork = distsf; 2674*2e1d0745SJose E. Roman } 2675*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); /* distribution_name */ 2676*2e1d0745SJose E. Roman } 2677*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); /* "distributions" */ 2678*2e1d0745SJose E. Roman } 2679*2e1d0745SJose E. Roman if (sfXC) { 2680*2e1d0745SJose E. Roman *sfXC = sfwork; 2681*2e1d0745SJose E. Roman } else { 2682*2e1d0745SJose E. Roman PetscCall(PetscSFDestroy(&sfwork)); 2683*2e1d0745SJose E. Roman } 2684*2e1d0745SJose E. Roman 2685*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 2686*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 2687*2e1d0745SJose E. Roman } 2688*2e1d0745SJose E. Roman 2689*2e1d0745SJose E. Roman /* If the file is old, it not only has different path to the coordinates, but */ 2690*2e1d0745SJose E. Roman /* does not contain coordinateDMs, so must fall back to the old implementation. */ 2691*2e1d0745SJose E. Roman static PetscErrorCode DMPlexCoordinatesLoad_HDF5_Legacy_Private(DM dm, PetscViewer viewer) 2692*2e1d0745SJose E. Roman { 2693*2e1d0745SJose E. Roman PetscSection coordSection; 2694*2e1d0745SJose E. Roman Vec coordinates; 2695*2e1d0745SJose E. Roman PetscReal lengthScale; 2696*2e1d0745SJose E. Roman PetscInt spatialDim, N, numVertices, vStart, vEnd, v; 2697*2e1d0745SJose E. Roman PetscMPIInt rank; 2698*2e1d0745SJose E. Roman 2699*2e1d0745SJose E. Roman PetscFunctionBegin; 2700*2e1d0745SJose E. Roman PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 2701*2e1d0745SJose E. Roman /* Read geometry */ 2702*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, "/geometry")); 2703*2e1d0745SJose E. Roman PetscCall(VecCreate(PetscObjectComm((PetscObject)dm), &coordinates)); 2704*2e1d0745SJose E. Roman PetscCall(PetscObjectSetName((PetscObject)coordinates, "vertices")); 2705*2e1d0745SJose E. Roman { 2706*2e1d0745SJose E. Roman /* Force serial load */ 2707*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5ReadSizes(viewer, "vertices", &spatialDim, &N)); 2708*2e1d0745SJose E. Roman PetscCall(VecSetSizes(coordinates, rank == 0 ? N : 0, N)); 2709*2e1d0745SJose E. Roman PetscCall(VecSetBlockSize(coordinates, spatialDim)); 2710*2e1d0745SJose E. Roman } 2711*2e1d0745SJose E. Roman PetscCall(VecLoad(coordinates, viewer)); 2712*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 2713*2e1d0745SJose E. Roman PetscCall(DMPlexGetScale(dm, PETSC_UNIT_LENGTH, &lengthScale)); 2714*2e1d0745SJose E. Roman PetscCall(VecScale(coordinates, 1.0 / lengthScale)); 2715*2e1d0745SJose E. Roman PetscCall(VecGetLocalSize(coordinates, &numVertices)); 2716*2e1d0745SJose E. Roman PetscCall(VecGetBlockSize(coordinates, &spatialDim)); 2717*2e1d0745SJose E. Roman numVertices /= spatialDim; 2718*2e1d0745SJose E. Roman /* Create coordinates */ 2719*2e1d0745SJose E. Roman PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 2720*2e1d0745SJose 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); 2721*2e1d0745SJose E. Roman PetscCall(DMGetCoordinateSection(dm, &coordSection)); 2722*2e1d0745SJose E. Roman PetscCall(PetscSectionSetNumFields(coordSection, 1)); 2723*2e1d0745SJose E. Roman PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spatialDim)); 2724*2e1d0745SJose E. Roman PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd)); 2725*2e1d0745SJose E. Roman for (v = vStart; v < vEnd; ++v) { 2726*2e1d0745SJose E. Roman PetscCall(PetscSectionSetDof(coordSection, v, spatialDim)); 2727*2e1d0745SJose E. Roman PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spatialDim)); 2728*2e1d0745SJose E. Roman } 2729*2e1d0745SJose E. Roman PetscCall(PetscSectionSetUp(coordSection)); 2730*2e1d0745SJose E. Roman PetscCall(DMSetCoordinates(dm, coordinates)); 2731*2e1d0745SJose E. Roman PetscCall(VecDestroy(&coordinates)); 2732*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 2733*2e1d0745SJose E. Roman } 2734*2e1d0745SJose E. Roman 2735*2e1d0745SJose E. Roman PetscErrorCode DMPlexCoordinatesLoad_HDF5_Internal(DM dm, PetscViewer viewer, PetscSF sfXC) 2736*2e1d0745SJose E. Roman { 2737*2e1d0745SJose E. Roman DMPlexStorageVersion version; 2738*2e1d0745SJose E. Roman DM cdm; 2739*2e1d0745SJose E. Roman Vec coords; 2740*2e1d0745SJose E. Roman PetscInt blockSize; 2741*2e1d0745SJose E. Roman PetscReal lengthScale; 2742*2e1d0745SJose E. Roman PetscSF lsf; 2743*2e1d0745SJose E. Roman const char *topologydm_name; 2744*2e1d0745SJose E. Roman char *coordinatedm_name, *coordinates_name; 2745*2e1d0745SJose E. Roman 2746*2e1d0745SJose E. Roman PetscFunctionBegin; 2747*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5GetDMPlexStorageVersionReading(viewer, &version)); 2748*2e1d0745SJose E. Roman if (!DMPlexStorageVersionGE(version, 2, 0, 0)) { 2749*2e1d0745SJose E. Roman PetscCall(DMPlexCoordinatesLoad_HDF5_Legacy_Private(dm, viewer)); 2750*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 2751*2e1d0745SJose E. Roman } 2752*2e1d0745SJose E. Roman /* else: since DMPlexStorageVersion 2.0.0 */ 2753*2e1d0745SJose E. Roman PetscCheck(sfXC, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_NULL, "PetscSF must be given for parallel load"); 2754*2e1d0745SJose E. Roman PetscCall(DMPlexGetHDF5Name_Private(dm, &topologydm_name)); 2755*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, "topologies")); 2756*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, topologydm_name)); 2757*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5ReadAttribute(viewer, NULL, "coordinateDMName", PETSC_STRING, NULL, &coordinatedm_name)); 2758*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5ReadAttribute(viewer, NULL, "coordinatesName", PETSC_STRING, NULL, &coordinates_name)); 2759*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 2760*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 2761*2e1d0745SJose E. Roman PetscCall(DMGetCoordinateDM(dm, &cdm)); 2762*2e1d0745SJose E. Roman PetscCall(PetscObjectSetName((PetscObject)cdm, coordinatedm_name)); 2763*2e1d0745SJose E. Roman PetscCall(PetscFree(coordinatedm_name)); 2764*2e1d0745SJose E. Roman /* lsf: on-disk data -> in-memory local vector associated with cdm's local section */ 2765*2e1d0745SJose E. Roman PetscCall(DMPlexSectionLoad(dm, viewer, cdm, sfXC, NULL, &lsf)); 2766*2e1d0745SJose E. Roman PetscCall(DMCreateLocalVector(cdm, &coords)); 2767*2e1d0745SJose E. Roman PetscCall(PetscObjectSetName((PetscObject)coords, coordinates_name)); 2768*2e1d0745SJose E. Roman PetscCall(PetscFree(coordinates_name)); 2769*2e1d0745SJose E. Roman PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_NATIVE)); 2770*2e1d0745SJose E. Roman PetscCall(DMPlexLocalVectorLoad(dm, viewer, cdm, lsf, coords)); 2771*2e1d0745SJose E. Roman PetscCall(PetscViewerPopFormat(viewer)); 2772*2e1d0745SJose E. Roman PetscCall(DMPlexGetScale(dm, PETSC_UNIT_LENGTH, &lengthScale)); 2773*2e1d0745SJose E. Roman PetscCall(VecScale(coords, 1.0 / lengthScale)); 2774*2e1d0745SJose E. Roman PetscCall(DMSetCoordinatesLocal(dm, coords)); 2775*2e1d0745SJose E. Roman PetscCall(VecGetBlockSize(coords, &blockSize)); 2776*2e1d0745SJose E. Roman PetscCall(DMSetCoordinateDim(dm, blockSize)); 2777*2e1d0745SJose E. Roman PetscCall(VecDestroy(&coords)); 2778*2e1d0745SJose E. Roman PetscCall(PetscSFDestroy(&lsf)); 2779*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 2780*2e1d0745SJose E. Roman } 2781*2e1d0745SJose E. Roman 2782*2e1d0745SJose E. Roman PetscErrorCode DMPlexLoad_HDF5_Internal(DM dm, PetscViewer viewer) 2783*2e1d0745SJose E. Roman { 2784*2e1d0745SJose E. Roman DMPlexStorageVersion version; 2785*2e1d0745SJose E. Roman 2786*2e1d0745SJose E. Roman PetscFunctionBegin; 2787*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5GetDMPlexStorageVersionReading(viewer, &version)); 2788*2e1d0745SJose E. Roman PetscCall(PetscInfo(dm, "Loading DM %s storage version %d.%d.%d\n", dm->hdr.name, version->major, version->minor, version->subminor)); 2789*2e1d0745SJose E. Roman if (!DMPlexStorageVersionGE(version, 2, 0, 0)) { 2790*2e1d0745SJose E. Roman PetscCall(DMPlexTopologyLoad_HDF5_Internal(dm, viewer, NULL)); 2791*2e1d0745SJose E. Roman PetscCall(DMPlexLabelsLoad_HDF5_Internal(dm, viewer, NULL)); 2792*2e1d0745SJose E. Roman PetscCall(DMPlexCoordinatesLoad_HDF5_Legacy_Private(dm, viewer)); 2793*2e1d0745SJose E. Roman } else { 2794*2e1d0745SJose E. Roman PetscSF sfXC; 2795*2e1d0745SJose E. Roman 2796*2e1d0745SJose E. Roman /* since DMPlexStorageVersion 2.0.0 */ 2797*2e1d0745SJose E. Roman PetscCall(DMPlexTopologyLoad_HDF5_Internal(dm, viewer, &sfXC)); 2798*2e1d0745SJose E. Roman PetscCall(DMPlexLabelsLoad_HDF5_Internal(dm, viewer, sfXC)); 2799*2e1d0745SJose E. Roman PetscCall(DMPlexCoordinatesLoad_HDF5_Internal(dm, viewer, sfXC)); 2800*2e1d0745SJose E. Roman PetscCall(PetscSFDestroy(&sfXC)); 2801*2e1d0745SJose E. Roman } 2802*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 2803*2e1d0745SJose E. Roman } 2804*2e1d0745SJose E. Roman 2805*2e1d0745SJose E. Roman static PetscErrorCode DMPlexSectionLoad_HDF5_Internal_CreateDataSF(PetscSection rootSection, PetscLayout layout, PetscInt globalOffsets[], PetscSection leafSection, PetscSF *sectionSF) 2806*2e1d0745SJose E. Roman { 2807*2e1d0745SJose E. Roman MPI_Comm comm; 2808*2e1d0745SJose E. Roman PetscInt pStart, pEnd, p, m; 2809*2e1d0745SJose E. Roman PetscInt *goffs, *ilocal; 2810*2e1d0745SJose E. Roman PetscBool rootIncludeConstraints, leafIncludeConstraints; 2811*2e1d0745SJose E. Roman 2812*2e1d0745SJose E. Roman PetscFunctionBegin; 2813*2e1d0745SJose E. Roman PetscCall(PetscObjectGetComm((PetscObject)leafSection, &comm)); 2814*2e1d0745SJose E. Roman PetscCall(PetscSectionGetChart(leafSection, &pStart, &pEnd)); 2815*2e1d0745SJose E. Roman PetscCall(PetscSectionGetIncludesConstraints(rootSection, &rootIncludeConstraints)); 2816*2e1d0745SJose E. Roman PetscCall(PetscSectionGetIncludesConstraints(leafSection, &leafIncludeConstraints)); 2817*2e1d0745SJose E. Roman if (rootIncludeConstraints && leafIncludeConstraints) PetscCall(PetscSectionGetStorageSize(leafSection, &m)); 2818*2e1d0745SJose E. Roman else PetscCall(PetscSectionGetConstrainedStorageSize(leafSection, &m)); 2819*2e1d0745SJose E. Roman PetscCall(PetscMalloc1(m, &ilocal)); 2820*2e1d0745SJose E. Roman PetscCall(PetscMalloc1(m, &goffs)); 2821*2e1d0745SJose E. Roman /* Currently, PetscSFDistributeSection() returns globalOffsets[] only */ 2822*2e1d0745SJose E. Roman /* for the top-level section (not for each field), so one must have */ 2823*2e1d0745SJose E. Roman /* rootSection->pointMajor == PETSC_TRUE. */ 2824*2e1d0745SJose E. Roman PetscCheck(rootSection->pointMajor, PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for field major ordering"); 2825*2e1d0745SJose E. Roman /* Currently, we also assume that leafSection->pointMajor == PETSC_TRUE. */ 2826*2e1d0745SJose E. Roman PetscCheck(leafSection->pointMajor, PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for field major ordering"); 2827*2e1d0745SJose E. Roman for (p = pStart, m = 0; p < pEnd; ++p) { 2828*2e1d0745SJose E. Roman PetscInt dof, cdof, i, j, off, goff; 2829*2e1d0745SJose E. Roman const PetscInt *cinds; 2830*2e1d0745SJose E. Roman 2831*2e1d0745SJose E. Roman PetscCall(PetscSectionGetDof(leafSection, p, &dof)); 2832*2e1d0745SJose E. Roman if (dof < 0) continue; 2833*2e1d0745SJose E. Roman goff = globalOffsets[p - pStart]; 2834*2e1d0745SJose E. Roman PetscCall(PetscSectionGetOffset(leafSection, p, &off)); 2835*2e1d0745SJose E. Roman PetscCall(PetscSectionGetConstraintDof(leafSection, p, &cdof)); 2836*2e1d0745SJose E. Roman PetscCall(PetscSectionGetConstraintIndices(leafSection, p, &cinds)); 2837*2e1d0745SJose E. Roman for (i = 0, j = 0; i < dof; ++i) { 2838*2e1d0745SJose E. Roman PetscBool constrained = (PetscBool)(j < cdof && i == cinds[j]); 2839*2e1d0745SJose E. Roman 2840*2e1d0745SJose E. Roman if (!constrained || (leafIncludeConstraints && rootIncludeConstraints)) { 2841*2e1d0745SJose E. Roman ilocal[m] = off++; 2842*2e1d0745SJose E. Roman goffs[m++] = goff++; 2843*2e1d0745SJose E. Roman } else if (leafIncludeConstraints && !rootIncludeConstraints) ++off; 2844*2e1d0745SJose E. Roman else if (!leafIncludeConstraints && rootIncludeConstraints) ++goff; 2845*2e1d0745SJose E. Roman if (constrained) ++j; 2846*2e1d0745SJose E. Roman } 2847*2e1d0745SJose E. Roman } 2848*2e1d0745SJose E. Roman PetscCall(PetscSFCreate(comm, sectionSF)); 2849*2e1d0745SJose E. Roman PetscCall(PetscSFSetFromOptions(*sectionSF)); 2850*2e1d0745SJose E. Roman PetscCall(PetscSFSetGraphLayout(*sectionSF, layout, m, ilocal, PETSC_OWN_POINTER, goffs)); 2851*2e1d0745SJose E. Roman PetscCall(PetscFree(goffs)); 2852*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 2853*2e1d0745SJose E. Roman } 2854*2e1d0745SJose E. Roman 2855*2e1d0745SJose E. Roman PetscErrorCode DMPlexSectionLoad_HDF5_Internal(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sfXB, PetscSF *gsf, PetscSF *lsf) 2856*2e1d0745SJose E. Roman { 2857*2e1d0745SJose E. Roman MPI_Comm comm; 2858*2e1d0745SJose E. Roman PetscMPIInt size, rank; 2859*2e1d0745SJose E. Roman const char *topologydm_name; 2860*2e1d0745SJose E. Roman const char *sectiondm_name; 2861*2e1d0745SJose E. Roman PetscSection sectionA, sectionB; 2862*2e1d0745SJose E. Roman PetscBool has; 2863*2e1d0745SJose E. Roman PetscInt nX, n, i; 2864*2e1d0745SJose E. Roman PetscSF sfAB; 2865*2e1d0745SJose E. Roman 2866*2e1d0745SJose E. Roman PetscFunctionBegin; 2867*2e1d0745SJose E. Roman PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 2868*2e1d0745SJose E. Roman PetscCallMPI(MPI_Comm_size(comm, &size)); 2869*2e1d0745SJose E. Roman PetscCallMPI(MPI_Comm_rank(comm, &rank)); 2870*2e1d0745SJose E. Roman PetscCall(DMPlexGetHDF5Name_Private(dm, &topologydm_name)); 2871*2e1d0745SJose E. Roman PetscCall(PetscObjectGetName((PetscObject)sectiondm, §iondm_name)); 2872*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, "topologies")); 2873*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, topologydm_name)); 2874*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, "dms")); 2875*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, sectiondm_name)); 2876*2e1d0745SJose E. Roman /* A: on-disk points */ 2877*2e1d0745SJose E. Roman /* X: list of global point numbers, [0, NX) */ 2878*2e1d0745SJose E. Roman /* B: plex points */ 2879*2e1d0745SJose E. Roman /* Load raw section (sectionA) */ 2880*2e1d0745SJose E. Roman PetscCall(PetscSectionCreate(comm, §ionA)); 2881*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5HasGroup(viewer, "section", &has)); 2882*2e1d0745SJose E. Roman if (has) PetscCall(PetscSectionLoad(sectionA, viewer)); 2883*2e1d0745SJose E. Roman else { 2884*2e1d0745SJose E. Roman // TODO If section is missing, create the default affine section with dim dofs on each vertex. Use PetscSplitOwnership() to split vertices. 2885*2e1d0745SJose E. Roman // How do I know the total number of vertices? 2886*2e1d0745SJose E. Roman PetscInt dim, Nf = 1, Nv, nv = PETSC_DECIDE; 2887*2e1d0745SJose E. Roman 2888*2e1d0745SJose E. Roman PetscCall(DMGetDimension(dm, &dim)); 2889*2e1d0745SJose E. Roman PetscCall(DMPlexGetDepthStratumGlobalSize(dm, 0, &Nv)); 2890*2e1d0745SJose E. Roman PetscCall(PetscSectionSetNumFields(sectionA, Nf)); 2891*2e1d0745SJose E. Roman PetscCall(PetscSectionSetFieldName(sectionA, 0, "Cartesian")); 2892*2e1d0745SJose E. Roman PetscCall(PetscSectionSetFieldComponents(sectionA, 0, dim)); 2893*2e1d0745SJose E. Roman for (PetscInt c = 0; c < dim; ++c) { 2894*2e1d0745SJose E. Roman char axis = 'X' + (char)c; 2895*2e1d0745SJose E. Roman 2896*2e1d0745SJose E. Roman PetscCall(PetscSectionSetComponentName(sectionA, 0, c, &axis)); 2897*2e1d0745SJose E. Roman } 2898*2e1d0745SJose E. Roman PetscCall(PetscSplitOwnership(comm, &nv, &Nv)); 2899*2e1d0745SJose E. Roman PetscCall(PetscSectionSetChart(sectionA, 0, nv)); 2900*2e1d0745SJose E. Roman for (PetscInt p = 0; p < nv; ++p) { 2901*2e1d0745SJose E. Roman PetscCall(PetscSectionSetDof(sectionA, p, dim)); 2902*2e1d0745SJose E. Roman PetscCall(PetscSectionSetFieldDof(sectionA, p, 0, dim)); 2903*2e1d0745SJose E. Roman } 2904*2e1d0745SJose E. Roman PetscCall(PetscSectionSetUp(sectionA)); 2905*2e1d0745SJose E. Roman } 2906*2e1d0745SJose E. Roman PetscCall(PetscSectionGetChart(sectionA, NULL, &n)); 2907*2e1d0745SJose E. Roman /* Create sfAB: A -> B */ 2908*2e1d0745SJose E. Roman #if defined(PETSC_USE_DEBUG) 2909*2e1d0745SJose E. Roman { 2910*2e1d0745SJose E. Roman PetscInt N, N1; 2911*2e1d0745SJose E. Roman 2912*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5ReadSizes(viewer, "order", NULL, &N1)); 2913*2e1d0745SJose E. Roman PetscCallMPI(MPIU_Allreduce(&n, &N, 1, MPIU_INT, MPI_SUM, comm)); 2914*2e1d0745SJose 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); 2915*2e1d0745SJose E. Roman } 2916*2e1d0745SJose E. Roman #endif 2917*2e1d0745SJose E. Roman { 2918*2e1d0745SJose E. Roman IS orderIS; 2919*2e1d0745SJose E. Roman const PetscInt *gpoints; 2920*2e1d0745SJose E. Roman PetscSF sfXA, sfAX; 2921*2e1d0745SJose E. Roman PetscLayout layout; 2922*2e1d0745SJose E. Roman PetscSFNode *owners, *buffer; 2923*2e1d0745SJose E. Roman PetscInt nleaves; 2924*2e1d0745SJose E. Roman PetscInt *ilocal; 2925*2e1d0745SJose E. Roman PetscSFNode *iremote; 2926*2e1d0745SJose E. Roman 2927*2e1d0745SJose E. Roman /* Create sfAX: A -> X */ 2928*2e1d0745SJose E. Roman PetscCall(ISCreate(comm, &orderIS)); 2929*2e1d0745SJose E. Roman PetscCall(PetscObjectSetName((PetscObject)orderIS, "order")); 2930*2e1d0745SJose E. Roman PetscCall(PetscLayoutSetLocalSize(orderIS->map, n)); 2931*2e1d0745SJose E. Roman PetscCall(ISLoad(orderIS, viewer)); 2932*2e1d0745SJose E. Roman PetscCall(PetscLayoutCreate(comm, &layout)); 2933*2e1d0745SJose E. Roman PetscCall(PetscSFGetGraph(sfXB, &nX, NULL, NULL, NULL)); 2934*2e1d0745SJose E. Roman PetscCall(PetscLayoutSetLocalSize(layout, nX)); 2935*2e1d0745SJose E. Roman PetscCall(PetscLayoutSetBlockSize(layout, 1)); 2936*2e1d0745SJose E. Roman PetscCall(PetscLayoutSetUp(layout)); 2937*2e1d0745SJose E. Roman PetscCall(PetscSFCreate(comm, &sfXA)); 2938*2e1d0745SJose E. Roman PetscCall(ISGetIndices(orderIS, &gpoints)); 2939*2e1d0745SJose E. Roman PetscCall(PetscSFSetGraphLayout(sfXA, layout, n, NULL, PETSC_OWN_POINTER, gpoints)); 2940*2e1d0745SJose E. Roman PetscCall(ISRestoreIndices(orderIS, &gpoints)); 2941*2e1d0745SJose E. Roman PetscCall(ISDestroy(&orderIS)); 2942*2e1d0745SJose E. Roman PetscCall(PetscLayoutDestroy(&layout)); 2943*2e1d0745SJose E. Roman PetscCall(PetscMalloc1(n, &owners)); 2944*2e1d0745SJose E. Roman PetscCall(PetscMalloc1(nX, &buffer)); 2945*2e1d0745SJose E. Roman for (i = 0; i < n; ++i) { 2946*2e1d0745SJose E. Roman owners[i].rank = rank; 2947*2e1d0745SJose E. Roman owners[i].index = i; 2948*2e1d0745SJose E. Roman } 2949*2e1d0745SJose E. Roman for (i = 0; i < nX; ++i) { 2950*2e1d0745SJose E. Roman buffer[i].rank = -1; 2951*2e1d0745SJose E. Roman buffer[i].index = -1; 2952*2e1d0745SJose E. Roman } 2953*2e1d0745SJose E. Roman PetscCall(PetscSFReduceBegin(sfXA, MPIU_SF_NODE, owners, buffer, MPI_MAXLOC)); 2954*2e1d0745SJose E. Roman PetscCall(PetscSFReduceEnd(sfXA, MPIU_SF_NODE, owners, buffer, MPI_MAXLOC)); 2955*2e1d0745SJose E. Roman PetscCall(PetscSFDestroy(&sfXA)); 2956*2e1d0745SJose E. Roman PetscCall(PetscFree(owners)); 2957*2e1d0745SJose E. Roman for (i = 0, nleaves = 0; i < nX; ++i) 2958*2e1d0745SJose E. Roman if (buffer[i].rank >= 0) nleaves++; 2959*2e1d0745SJose E. Roman PetscCall(PetscMalloc1(nleaves, &ilocal)); 2960*2e1d0745SJose E. Roman PetscCall(PetscMalloc1(nleaves, &iremote)); 2961*2e1d0745SJose E. Roman for (i = 0, nleaves = 0; i < nX; ++i) { 2962*2e1d0745SJose E. Roman if (buffer[i].rank >= 0) { 2963*2e1d0745SJose E. Roman ilocal[nleaves] = i; 2964*2e1d0745SJose E. Roman iremote[nleaves].rank = buffer[i].rank; 2965*2e1d0745SJose E. Roman iremote[nleaves].index = buffer[i].index; 2966*2e1d0745SJose E. Roman nleaves++; 2967*2e1d0745SJose E. Roman } 2968*2e1d0745SJose E. Roman } 2969*2e1d0745SJose E. Roman PetscCall(PetscFree(buffer)); 2970*2e1d0745SJose E. Roman PetscCall(PetscSFCreate(comm, &sfAX)); 2971*2e1d0745SJose E. Roman PetscCall(PetscSFSetFromOptions(sfAX)); 2972*2e1d0745SJose E. Roman PetscCall(PetscSFSetGraph(sfAX, n, nleaves, ilocal, PETSC_OWN_POINTER, iremote, PETSC_OWN_POINTER)); 2973*2e1d0745SJose E. Roman PetscCall(PetscSFCompose(sfAX, sfXB, &sfAB)); 2974*2e1d0745SJose E. Roman PetscCall(PetscSFDestroy(&sfAX)); 2975*2e1d0745SJose E. Roman } 2976*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 2977*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 2978*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 2979*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 2980*2e1d0745SJose E. Roman /* Create plex section (sectionB) */ 2981*2e1d0745SJose E. Roman PetscCall(DMGetLocalSection(sectiondm, §ionB)); 2982*2e1d0745SJose E. Roman if (lsf || gsf) { 2983*2e1d0745SJose E. Roman PetscLayout layout; 2984*2e1d0745SJose E. Roman PetscInt M, m; 2985*2e1d0745SJose E. Roman PetscInt *offsetsA; 2986*2e1d0745SJose E. Roman PetscBool includesConstraintsA; 2987*2e1d0745SJose E. Roman 2988*2e1d0745SJose E. Roman PetscCall(PetscSFDistributeSection(sfAB, sectionA, &offsetsA, sectionB)); 2989*2e1d0745SJose E. Roman PetscCall(PetscSectionGetIncludesConstraints(sectionA, &includesConstraintsA)); 2990*2e1d0745SJose E. Roman if (includesConstraintsA) PetscCall(PetscSectionGetStorageSize(sectionA, &m)); 2991*2e1d0745SJose E. Roman else PetscCall(PetscSectionGetConstrainedStorageSize(sectionA, &m)); 2992*2e1d0745SJose E. Roman PetscCallMPI(MPIU_Allreduce(&m, &M, 1, MPIU_INT, MPI_SUM, comm)); 2993*2e1d0745SJose E. Roman PetscCall(PetscLayoutCreate(comm, &layout)); 2994*2e1d0745SJose E. Roman PetscCall(PetscLayoutSetSize(layout, M)); 2995*2e1d0745SJose E. Roman PetscCall(PetscLayoutSetUp(layout)); 2996*2e1d0745SJose E. Roman if (lsf) { 2997*2e1d0745SJose E. Roman PetscSF lsfABdata; 2998*2e1d0745SJose E. Roman 2999*2e1d0745SJose E. Roman PetscCall(DMPlexSectionLoad_HDF5_Internal_CreateDataSF(sectionA, layout, offsetsA, sectionB, &lsfABdata)); 3000*2e1d0745SJose E. Roman *lsf = lsfABdata; 3001*2e1d0745SJose E. Roman } 3002*2e1d0745SJose E. Roman if (gsf) { 3003*2e1d0745SJose E. Roman PetscSection gsectionB, gsectionB1; 3004*2e1d0745SJose E. Roman PetscBool includesConstraintsB; 3005*2e1d0745SJose E. Roman PetscSF gsfABdata, pointsf; 3006*2e1d0745SJose E. Roman 3007*2e1d0745SJose E. Roman PetscCall(DMGetGlobalSection(sectiondm, &gsectionB1)); 3008*2e1d0745SJose E. Roman PetscCall(PetscSectionGetIncludesConstraints(gsectionB1, &includesConstraintsB)); 3009*2e1d0745SJose E. Roman PetscCall(DMGetPointSF(sectiondm, &pointsf)); 3010*2e1d0745SJose E. Roman PetscCall(PetscSectionCreateGlobalSection(sectionB, pointsf, PETSC_TRUE, includesConstraintsB, PETSC_TRUE, &gsectionB)); 3011*2e1d0745SJose E. Roman PetscCall(DMPlexSectionLoad_HDF5_Internal_CreateDataSF(sectionA, layout, offsetsA, gsectionB, &gsfABdata)); 3012*2e1d0745SJose E. Roman PetscCall(PetscSectionDestroy(&gsectionB)); 3013*2e1d0745SJose E. Roman *gsf = gsfABdata; 3014*2e1d0745SJose E. Roman } 3015*2e1d0745SJose E. Roman PetscCall(PetscLayoutDestroy(&layout)); 3016*2e1d0745SJose E. Roman PetscCall(PetscFree(offsetsA)); 3017*2e1d0745SJose E. Roman } else { 3018*2e1d0745SJose E. Roman PetscCall(PetscSFDistributeSection(sfAB, sectionA, NULL, sectionB)); 3019*2e1d0745SJose E. Roman } 3020*2e1d0745SJose E. Roman PetscCall(PetscSFDestroy(&sfAB)); 3021*2e1d0745SJose E. Roman PetscCall(PetscSectionDestroy(§ionA)); 3022*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 3023*2e1d0745SJose E. Roman } 3024*2e1d0745SJose E. Roman 3025*2e1d0745SJose E. Roman PetscErrorCode DMPlexVecLoad_HDF5_Internal(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 3026*2e1d0745SJose E. Roman { 3027*2e1d0745SJose E. Roman MPI_Comm comm; 3028*2e1d0745SJose E. Roman const char *topologydm_name; 3029*2e1d0745SJose E. Roman const char *sectiondm_name; 3030*2e1d0745SJose E. Roman const char *vec_name; 3031*2e1d0745SJose E. Roman Vec vecA; 3032*2e1d0745SJose E. Roman PetscInt mA, m, bs; 3033*2e1d0745SJose E. Roman const PetscInt *ilocal; 3034*2e1d0745SJose E. Roman const PetscScalar *src; 3035*2e1d0745SJose E. Roman PetscScalar *dest; 3036*2e1d0745SJose E. Roman 3037*2e1d0745SJose E. Roman PetscFunctionBegin; 3038*2e1d0745SJose E. Roman PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 3039*2e1d0745SJose E. Roman PetscCall(DMPlexGetHDF5Name_Private(dm, &topologydm_name)); 3040*2e1d0745SJose E. Roman PetscCall(PetscObjectGetName((PetscObject)sectiondm, §iondm_name)); 3041*2e1d0745SJose E. Roman PetscCall(PetscObjectGetName((PetscObject)vec, &vec_name)); 3042*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, "topologies")); 3043*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, topologydm_name)); 3044*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, "dms")); 3045*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, sectiondm_name)); 3046*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, "vecs")); 3047*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PushGroup(viewer, vec_name)); 3048*2e1d0745SJose E. Roman PetscCall(VecCreate(comm, &vecA)); 3049*2e1d0745SJose E. Roman PetscCall(PetscObjectSetName((PetscObject)vecA, vec_name)); 3050*2e1d0745SJose E. Roman PetscCall(PetscSFGetGraph(sf, &mA, &m, &ilocal, NULL)); 3051*2e1d0745SJose E. Roman /* Check consistency */ 3052*2e1d0745SJose E. Roman { 3053*2e1d0745SJose E. Roman PetscSF pointsf, pointsf1; 3054*2e1d0745SJose E. Roman PetscInt m1, i, j; 3055*2e1d0745SJose E. Roman 3056*2e1d0745SJose E. Roman PetscCall(DMGetPointSF(dm, &pointsf)); 3057*2e1d0745SJose E. Roman PetscCall(DMGetPointSF(sectiondm, &pointsf1)); 3058*2e1d0745SJose E. Roman PetscCheck(pointsf1 == pointsf, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatching point SFs for dm and sectiondm"); 3059*2e1d0745SJose E. Roman #if defined(PETSC_USE_DEBUG) 3060*2e1d0745SJose E. Roman { 3061*2e1d0745SJose E. Roman PetscInt MA, MA1; 3062*2e1d0745SJose E. Roman 3063*2e1d0745SJose E. Roman PetscCallMPI(MPIU_Allreduce(&mA, &MA, 1, MPIU_INT, MPI_SUM, comm)); 3064*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5ReadSizes(viewer, vec_name, NULL, &MA1)); 3065*2e1d0745SJose 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); 3066*2e1d0745SJose E. Roman } 3067*2e1d0745SJose E. Roman #endif 3068*2e1d0745SJose E. Roman PetscCall(VecGetLocalSize(vec, &m1)); 3069*2e1d0745SJose E. Roman PetscCheck(m1 >= m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Target vector size (%" PetscInt_FMT ") < SF leaf size (%" PetscInt_FMT ")", m1, m); 3070*2e1d0745SJose E. Roman for (i = 0; i < m; ++i) { 3071*2e1d0745SJose E. Roman j = ilocal ? ilocal[i] : i; 3072*2e1d0745SJose 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); 3073*2e1d0745SJose E. Roman } 3074*2e1d0745SJose E. Roman } 3075*2e1d0745SJose E. Roman PetscCall(VecSetSizes(vecA, mA, PETSC_DECIDE)); 3076*2e1d0745SJose E. Roman PetscCall(VecLoad(vecA, viewer)); 3077*2e1d0745SJose E. Roman PetscCall(VecGetArrayRead(vecA, &src)); 3078*2e1d0745SJose E. Roman PetscCall(VecGetArray(vec, &dest)); 3079*2e1d0745SJose E. Roman PetscCall(PetscSFBcastBegin(sf, MPIU_SCALAR, src, dest, MPI_REPLACE)); 3080*2e1d0745SJose E. Roman PetscCall(PetscSFBcastEnd(sf, MPIU_SCALAR, src, dest, MPI_REPLACE)); 3081*2e1d0745SJose E. Roman PetscCall(VecRestoreArray(vec, &dest)); 3082*2e1d0745SJose E. Roman PetscCall(VecRestoreArrayRead(vecA, &src)); 3083*2e1d0745SJose E. Roman PetscCall(VecDestroy(&vecA)); 3084*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5ReadAttribute(viewer, NULL, "blockSize", PETSC_INT, NULL, (void *)&bs)); 3085*2e1d0745SJose E. Roman PetscCall(VecSetBlockSize(vec, bs)); 3086*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 3087*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 3088*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 3089*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 3090*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 3091*2e1d0745SJose E. Roman PetscCall(PetscViewerHDF5PopGroup(viewer)); 3092*2e1d0745SJose E. Roman PetscFunctionReturn(PETSC_SUCCESS); 3093*2e1d0745SJose E. Roman } 3094