1fa534816SMatthew G. Knepley #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2fa534816SMatthew G. Knepley 3fa534816SMatthew G. Knepley /*@ 4a1cb98faSBarry Smith DMPlexSetMigrationSF - Sets the `PetscSF` for migrating from a parent `DM` into this `DM` 5a1cb98faSBarry Smith 6a1cb98faSBarry Smith Logically Collective on dm 7f94b4a02SBlaise Bourdin 85d3b26e6SMatthew G. Knepley Input Parameters: 9a1cb98faSBarry Smith + dm - The `DM` 10a1cb98faSBarry Smith - naturalSF - The `PetscSF` 115d3b26e6SMatthew G. Knepley 12f94b4a02SBlaise Bourdin Level: intermediate 13f94b4a02SBlaise Bourdin 14a1cb98faSBarry Smith Note: 15a1cb98faSBarry Smith It is necessary to call this in order to have `DMCreateSubDM()` or `DMCreateSuperDM()` build the Global-To-Natural map 16a1cb98faSBarry Smith 17a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `PetscSF`, `DMPlexDistribute()`, `DMPlexDistributeField()`, `DMPlexCreateMigrationSF()`, `DMPlexGetMigrationSF()` 18f94b4a02SBlaise Bourdin @*/ 19d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetMigrationSF(DM dm, PetscSF migrationSF) 20d71ae5a4SJacob Faibussowitsch { 21f94b4a02SBlaise Bourdin PetscFunctionBegin; 22f94b4a02SBlaise Bourdin dm->sfMigration = migrationSF; 239566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)migrationSF)); 24*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 25f94b4a02SBlaise Bourdin } 26f94b4a02SBlaise Bourdin 27f94b4a02SBlaise Bourdin /*@ 28a1cb98faSBarry Smith DMPlexGetMigrationSF - Gets the `PetscSF` for migrating from a parent `DM` into this `DM` 29a1cb98faSBarry Smith 30a1cb98faSBarry Smith Note Collective 31f94b4a02SBlaise Bourdin 325d3b26e6SMatthew G. Knepley Input Parameter: 33a1cb98faSBarry Smith . dm - The `DM` 345d3b26e6SMatthew G. Knepley 355d3b26e6SMatthew G. Knepley Output Parameter: 36a1cb98faSBarry Smith . migrationSF - The `PetscSF` 375d3b26e6SMatthew G. Knepley 38f94b4a02SBlaise Bourdin Level: intermediate 39f94b4a02SBlaise Bourdin 40a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `PetscSF`, `DMPlexDistribute()`, `DMPlexDistributeField()`, `DMPlexCreateMigrationSF()`, `DMPlexSetMigrationSF` 41f94b4a02SBlaise Bourdin @*/ 42d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetMigrationSF(DM dm, PetscSF *migrationSF) 43d71ae5a4SJacob Faibussowitsch { 44f94b4a02SBlaise Bourdin PetscFunctionBegin; 45f94b4a02SBlaise Bourdin *migrationSF = dm->sfMigration; 46*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 47f94b4a02SBlaise Bourdin } 48f94b4a02SBlaise Bourdin 49f94b4a02SBlaise Bourdin /*@ 50a1cb98faSBarry Smith DMPlexSetGlobalToNaturalSF - Sets the `PetscSF` for mapping Global `Vec` to the Natural `Vec` 51f94b4a02SBlaise Bourdin 525d3b26e6SMatthew G. Knepley Input Parameters: 53a1cb98faSBarry Smith + dm - The `DM` 54a1cb98faSBarry Smith - naturalSF - The `PetscSF` 555d3b26e6SMatthew G. Knepley 56f94b4a02SBlaise Bourdin Level: intermediate 57f94b4a02SBlaise Bourdin 58a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `PetscSF`, `DMPlexDistribute()`, `DMPlexDistributeField()`, `DMPlexCreateGlobalToNaturalSF()`, `DMPlexGetGlobaltoNaturalSF()` 59f94b4a02SBlaise Bourdin @*/ 60d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetGlobalToNaturalSF(DM dm, PetscSF naturalSF) 61d71ae5a4SJacob Faibussowitsch { 62f94b4a02SBlaise Bourdin PetscFunctionBegin; 63f94b4a02SBlaise Bourdin dm->sfNatural = naturalSF; 649566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)naturalSF)); 65f94b4a02SBlaise Bourdin dm->useNatural = PETSC_TRUE; 66*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 67f94b4a02SBlaise Bourdin } 68f94b4a02SBlaise Bourdin 69f94b4a02SBlaise Bourdin /*@ 70a1cb98faSBarry Smith DMPlexGetGlobalToNaturalSF - Gets the `PetscSF` for mapping Global `Vec` to the Natural `Vec` 71f94b4a02SBlaise Bourdin 725d3b26e6SMatthew G. Knepley Input Parameter: 73a1cb98faSBarry Smith . dm - The `DM` 745d3b26e6SMatthew G. Knepley 755d3b26e6SMatthew G. Knepley Output Parameter: 76a1cb98faSBarry Smith . naturalSF - The `PetscSF` 775d3b26e6SMatthew G. Knepley 78f94b4a02SBlaise Bourdin Level: intermediate 79f94b4a02SBlaise Bourdin 80a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `PetscSF`, `DMPlexDistribute()`, `DMPlexDistributeField()`, `DMPlexCreateGlobalToNaturalSF()`, `DMPlexSetGlobaltoNaturalSF` 81f94b4a02SBlaise Bourdin @*/ 82d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetGlobalToNaturalSF(DM dm, PetscSF *naturalSF) 83d71ae5a4SJacob Faibussowitsch { 84f94b4a02SBlaise Bourdin PetscFunctionBegin; 85f94b4a02SBlaise Bourdin *naturalSF = dm->sfNatural; 86*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 87f94b4a02SBlaise Bourdin } 88f94b4a02SBlaise Bourdin 89f94b4a02SBlaise Bourdin /*@ 90a1cb98faSBarry Smith DMPlexCreateGlobalToNaturalSF - Creates the `PetscSF` for mapping Global `Vec` to the Natural `Vec` 91fa534816SMatthew G. Knepley 92fa534816SMatthew G. Knepley Input Parameters: 93a1cb98faSBarry Smith + dm - The redistributed `DM` 94a1cb98faSBarry Smith . section - The local `PetscSection` describing the `Vec` before the mesh was distributed, or NULL if not available 95a1cb98faSBarry Smith - sfMigration - The `PetscSF` used to distribute the mesh, or NULL if it cannot be computed 96fa534816SMatthew G. Knepley 975d3b26e6SMatthew G. Knepley Output Parameter: 98a1cb98faSBarry Smith . sfNatural - `PetscSF` for mapping the `Vec` in PETSc ordering to the canonical ordering 995d3b26e6SMatthew G. Knepley 100fa534816SMatthew G. Knepley Level: intermediate 101fa534816SMatthew G. Knepley 102a1cb98faSBarry Smith Note: 103a1cb98faSBarry Smith This is not typically called by the user. 104a1cb98faSBarry Smith 105a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `PetscSF`, `PetscSection`, `DMPlexDistribute()`, `DMPlexDistributeField()` 106fa534816SMatthew G. Knepley @*/ 107d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateGlobalToNaturalSF(DM dm, PetscSection section, PetscSF sfMigration, PetscSF *sfNatural) 108d71ae5a4SJacob Faibussowitsch { 109fa534816SMatthew G. Knepley MPI_Comm comm; 110e7858701SMatthew G. Knepley PetscSF sf, sfEmbed, sfField; 111e5b44f4fSMatthew G. Knepley PetscSection gSection, sectionDist, gLocSection; 112fa534816SMatthew G. Knepley PetscInt *spoints, *remoteOffsets; 11357a2b1f8SBlaise Bourdin PetscInt ssize, pStart, pEnd, p, localSize, maxStorageSize; 114e7858701SMatthew G. Knepley PetscBool destroyFlag = PETSC_FALSE, debug = PETSC_FALSE; 115fa534816SMatthew G. Knepley 116fa534816SMatthew G. Knepley PetscFunctionBegin; 1179566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 1185c3f5608SAlexisMarb if (!sfMigration) { 119e7858701SMatthew G. Knepley /* If sfMigration is missing, sfNatural cannot be computed and is set to NULL */ 1205c3f5608SAlexisMarb *sfNatural = NULL; 121*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1225c3f5608SAlexisMarb } else if (!section) { 123e7858701SMatthew G. Knepley /* If the sequential section is not provided (NULL), it is reconstructed from the parallel section */ 1245c3f5608SAlexisMarb PetscSF sfMigrationInv; 1255c3f5608SAlexisMarb PetscSection localSection; 1265c3f5608SAlexisMarb 1279566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, &localSection)); 1289566063dSJacob Faibussowitsch PetscCall(PetscSFCreateInverseSF(sfMigration, &sfMigrationInv)); 1299566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 1309566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(sfMigrationInv, localSection, NULL, section)); 1319566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfMigrationInv)); 1325c3f5608SAlexisMarb destroyFlag = PETSC_TRUE; 1335c3f5608SAlexisMarb } 134e7858701SMatthew G. Knepley if (debug) PetscCall(PetscSFView(sfMigration, NULL)); 135e5b44f4fSMatthew G. Knepley /* Create a new section from distributing the original section */ 1369566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, §ionDist)); 1379566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(sfMigration, section, &remoteOffsets, sectionDist)); 138e7858701SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)sectionDist, "Migrated Section")); 139e7858701SMatthew G. Knepley if (debug) PetscCall(PetscSectionView(sectionDist, NULL)); 1409566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(dm, sectionDist)); 141e7858701SMatthew G. Knepley /* If a sequential section is provided but no dof is affected, sfNatural cannot be computed and is set to NULL */ 14257a2b1f8SBlaise Bourdin PetscCall(PetscSectionGetStorageSize(sectionDist, &localSize)); 14357a2b1f8SBlaise Bourdin PetscCallMPI(MPI_Allreduce(&localSize, &maxStorageSize, 1, MPI_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 14457a2b1f8SBlaise Bourdin if (maxStorageSize) { 145e7858701SMatthew G. Knepley const PetscInt *leaves; 146e7858701SMatthew G. Knepley PetscInt *sortleaves, *indices; 147e7858701SMatthew G. Knepley PetscInt Nl; 148e7858701SMatthew G. Knepley 149fa534816SMatthew G. Knepley /* Get a pruned version of migration SF */ 1509566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dm, &gSection)); 151e7858701SMatthew G. Knepley if (debug) PetscCall(PetscSectionView(gSection, NULL)); 152e7858701SMatthew G. Knepley PetscCall(PetscSFGetGraph(sfMigration, NULL, &Nl, &leaves, NULL)); 1539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(gSection, &pStart, &pEnd)); 154fa534816SMatthew G. Knepley for (p = pStart, ssize = 0; p < pEnd; ++p) { 155fa534816SMatthew G. Knepley PetscInt dof, off; 156fa534816SMatthew G. Knepley 1579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(gSection, p, &dof)); 1589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(gSection, p, &off)); 159fa534816SMatthew G. Knepley if ((dof > 0) && (off >= 0)) ++ssize; 160fa534816SMatthew G. Knepley } 161e7858701SMatthew G. Knepley PetscCall(PetscMalloc3(ssize, &spoints, Nl, &sortleaves, Nl, &indices)); 1629371c9d4SSatish Balay for (p = 0; p < Nl; ++p) { 1639371c9d4SSatish Balay sortleaves[p] = leaves ? leaves[p] : p; 1649371c9d4SSatish Balay indices[p] = p; 1659371c9d4SSatish Balay } 166e7858701SMatthew G. Knepley PetscCall(PetscSortIntWithArray(Nl, sortleaves, indices)); 167fa534816SMatthew G. Knepley for (p = pStart, ssize = 0; p < pEnd; ++p) { 168e7858701SMatthew G. Knepley PetscInt dof, off, loc; 169fa534816SMatthew G. Knepley 1709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(gSection, p, &dof)); 1719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(gSection, p, &off)); 172e7858701SMatthew G. Knepley if ((dof > 0) && (off >= 0)) { 173e7858701SMatthew G. Knepley PetscCall(PetscFindInt(p, Nl, sortleaves, &loc)); 174e7858701SMatthew G. Knepley PetscCheck(loc >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Point %" PetscInt_FMT " with nonzero dof is not a leaf of the migration SF", p); 175e7858701SMatthew G. Knepley spoints[ssize++] = indices[loc]; 176e7858701SMatthew G. Knepley } 177fa534816SMatthew G. Knepley } 1789566063dSJacob Faibussowitsch PetscCall(PetscSFCreateEmbeddedLeafSF(sfMigration, ssize, spoints, &sfEmbed)); 179e7858701SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)sfEmbed, "Embedded SF")); 180e7858701SMatthew G. Knepley PetscCall(PetscFree3(spoints, sortleaves, indices)); 181e7858701SMatthew G. Knepley if (debug) PetscCall(PetscSFView(sfEmbed, NULL)); 182e7858701SMatthew G. Knepley /* Create the SF associated with this section 183e7858701SMatthew G. Knepley Roots are natural dofs, leaves are global dofs */ 1849566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 18599a026b9SAlexis Marboeuf PetscCall(PetscSectionCreateGlobalSection(sectionDist, sf, PETSC_TRUE, PETSC_TRUE, &gLocSection)); 1869566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(sfEmbed, section, remoteOffsets, gLocSection, &sfField)); 1879566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfEmbed)); 1889566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&gLocSection)); 189e7858701SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)sfField, "Natural-to-Global SF")); 190e7858701SMatthew G. Knepley if (debug) PetscCall(PetscSFView(sfField, NULL)); 191e7858701SMatthew G. Knepley /* Invert the field SF 192e7858701SMatthew G. Knepley Roots are global dofs, leaves are natural dofs */ 193e7858701SMatthew G. Knepley PetscCall(PetscSFCreateInverseSF(sfField, sfNatural)); 194e7858701SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)*sfNatural, "Global-to-Natural SF")); 1959566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)*sfNatural, NULL, "-globaltonatural_sf_view")); 196fa534816SMatthew G. Knepley /* Clean up */ 197e7858701SMatthew G. Knepley PetscCall(PetscSFDestroy(&sfField)); 19814744f87SBlaise Bourdin } else { 19914744f87SBlaise Bourdin *sfNatural = NULL; 20014744f87SBlaise Bourdin } 2019566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ionDist)); 2029566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets)); 2039566063dSJacob Faibussowitsch if (destroyFlag) PetscCall(PetscSectionDestroy(§ion)); 204*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 205fa534816SMatthew G. Knepley } 206fa534816SMatthew G. Knepley 207fa534816SMatthew G. Knepley /*@ 208a1cb98faSBarry Smith DMPlexGlobalToNaturalBegin - Rearranges a global `Vec` in the natural order. 209fa534816SMatthew G. Knepley 210fa534816SMatthew G. Knepley Collective on dm 211fa534816SMatthew G. Knepley 212fa534816SMatthew G. Knepley Input Parameters: 213a1cb98faSBarry Smith + dm - The distributed `DMPLEX` 214a1cb98faSBarry Smith - gv - The global `Vec` 215fa534816SMatthew G. Knepley 216fa534816SMatthew G. Knepley Output Parameters: 217a1cb98faSBarry Smith . nv - `Vec` in the canonical ordering distributed over all processors associated with gv 218fa534816SMatthew G. Knepley 219fa534816SMatthew G. Knepley Level: intermediate 220fa534816SMatthew G. Knepley 221a1cb98faSBarry Smith Note: 222a1cb98faSBarry Smith The user must call `DMSetUseNatural`(dm, `PETSC_TRUE`) before `DMPlexDistribute()`. 223a1cb98faSBarry Smith 224a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `Vec`, `DMPlexDistribute()`, `DMPlexDistributeField()`, `DMPlexNaturalToGlobalBegin()`, `DMPlexGlobalToNaturalEnd()` 225fa534816SMatthew G. Knepley @*/ 226d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGlobalToNaturalBegin(DM dm, Vec gv, Vec nv) 227d71ae5a4SJacob Faibussowitsch { 228fa534816SMatthew G. Knepley const PetscScalar *inarray; 229fa534816SMatthew G. Knepley PetscScalar *outarray; 230a6a55facSMatthew G. Knepley PetscMPIInt size; 231fa534816SMatthew G. Knepley 232fa534816SMatthew G. Knepley PetscFunctionBegin; 2339566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_GlobalToNaturalBegin, dm, 0, 0, 0)); 2349566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 235fa534816SMatthew G. Knepley if (dm->sfNatural) { 2369566063dSJacob Faibussowitsch PetscCall(VecGetArray(nv, &outarray)); 2379566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(gv, &inarray)); 2389566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(dm->sfNatural, MPIU_SCALAR, (PetscScalar *)inarray, outarray, MPI_REPLACE)); 2399566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(gv, &inarray)); 2409566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(nv, &outarray)); 241a6a55facSMatthew G. Knepley } else if (size == 1) { 2429566063dSJacob Faibussowitsch PetscCall(VecCopy(gv, nv)); 243f7d195e4SLawrence Mitchell } else { 244f7d195e4SLawrence Mitchell PetscCheck(!dm->useNatural, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "DM global to natural SF not present.\nIf DMPlexDistribute() was called and a section was defined, report to petsc-maint@mcs.anl.gov."); 245f7d195e4SLawrence Mitchell SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created.\nYou must call DMSetUseNatural() before DMPlexDistribute()."); 246f7d195e4SLawrence Mitchell } 2479566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_GlobalToNaturalBegin, dm, 0, 0, 0)); 248*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 249fa534816SMatthew G. Knepley } 250fa534816SMatthew G. Knepley 251fa534816SMatthew G. Knepley /*@ 252a1cb98faSBarry Smith DMPlexGlobalToNaturalEnd - Rearranges a global `Vec` in the natural order. 253fa534816SMatthew G. Knepley 254fa534816SMatthew G. Knepley Collective on dm 255fa534816SMatthew G. Knepley 256fa534816SMatthew G. Knepley Input Parameters: 257a1cb98faSBarry Smith + dm - The distributed `DMPLEX` 258a1cb98faSBarry Smith - gv - The global `Vec` 259fa534816SMatthew G. Knepley 26097bb3fdcSJose E. Roman Output Parameter: 261a1cb98faSBarry Smith . nv - The natural `Vec` 262fa534816SMatthew G. Knepley 263fa534816SMatthew G. Knepley Level: intermediate 264fa534816SMatthew G. Knepley 265a1cb98faSBarry Smith Note: 266a1cb98faSBarry Smith The user must call `DMSetUseNatural`(dm, `PETSC_TRUE`) before `DMPlexDistribute()`. 267a1cb98faSBarry Smith 268a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `Vec`, `DMPlexDistribute()`, `DMPlexDistributeField()`, `DMPlexNaturalToGlobalBegin()`, `DMPlexGlobalToNaturalBegin()` 269fa534816SMatthew G. Knepley @*/ 270d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGlobalToNaturalEnd(DM dm, Vec gv, Vec nv) 271d71ae5a4SJacob Faibussowitsch { 272fa534816SMatthew G. Knepley const PetscScalar *inarray; 273fa534816SMatthew G. Knepley PetscScalar *outarray; 274a6a55facSMatthew G. Knepley PetscMPIInt size; 275fa534816SMatthew G. Knepley 276fa534816SMatthew G. Knepley PetscFunctionBegin; 2779566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_GlobalToNaturalEnd, dm, 0, 0, 0)); 2789566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 279fa534816SMatthew G. Knepley if (dm->sfNatural) { 2809566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(gv, &inarray)); 2819566063dSJacob Faibussowitsch PetscCall(VecGetArray(nv, &outarray)); 2829566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(dm->sfNatural, MPIU_SCALAR, (PetscScalar *)inarray, outarray, MPI_REPLACE)); 2839566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(gv, &inarray)); 2849566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(nv, &outarray)); 285a6a55facSMatthew G. Knepley } else if (size == 1) { 286f7d195e4SLawrence Mitchell } else { 287f7d195e4SLawrence Mitchell PetscCheck(!dm->useNatural, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "DM global to natural SF not present.\nIf DMPlexDistribute() was called and a section was defined, report to petsc-maint@mcs.anl.gov."); 288f7d195e4SLawrence Mitchell SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created.\nYou must call DMSetUseNatural() before DMPlexDistribute()."); 289f7d195e4SLawrence Mitchell } 2909566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_GlobalToNaturalEnd, dm, 0, 0, 0)); 291*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 292fa534816SMatthew G. Knepley } 293fa534816SMatthew G. Knepley 294fa534816SMatthew G. Knepley /*@ 295a1cb98faSBarry Smith DMPlexNaturalToGlobalBegin - Rearranges a `Vec` in the natural order to the Global order. 296fa534816SMatthew G. Knepley 297fa534816SMatthew G. Knepley Collective on dm 298fa534816SMatthew G. Knepley 299fa534816SMatthew G. Knepley Input Parameters: 300a1cb98faSBarry Smith + dm - The distributed `DMPLEX` 301a1cb98faSBarry Smith - nv - The natural `Vec` 302fa534816SMatthew G. Knepley 303fa534816SMatthew G. Knepley Output Parameters: 304a1cb98faSBarry Smith . gv - The global `Vec` 305fa534816SMatthew G. Knepley 306fa534816SMatthew G. Knepley Level: intermediate 307fa534816SMatthew G. Knepley 308a1cb98faSBarry Smith Note: 309a1cb98faSBarry Smith The user must call `DMSetUseNatural`(dm, `PETSC_TRUE`) before `DMPlexDistribute()`. 310a1cb98faSBarry Smith 311a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `Vec`, `DMPlexDistribute()`, `DMPlexDistributeField()`, `DMPlexNaturalToGlobalBegin()`, `DMPlexGlobalToNaturalEnd()` 312fa534816SMatthew G. Knepley @*/ 313d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexNaturalToGlobalBegin(DM dm, Vec nv, Vec gv) 314d71ae5a4SJacob Faibussowitsch { 315fa534816SMatthew G. Knepley const PetscScalar *inarray; 316fa534816SMatthew G. Knepley PetscScalar *outarray; 317a6a55facSMatthew G. Knepley PetscMPIInt size; 318fa534816SMatthew G. Knepley 319fa534816SMatthew G. Knepley PetscFunctionBegin; 3209566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_NaturalToGlobalBegin, dm, 0, 0, 0)); 3219566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 322fa534816SMatthew G. Knepley if (dm->sfNatural) { 323a5b23f4aSJose E. Roman /* We only have access to the SF that goes from Global to Natural. 324b64f75a9SBlaise Bourdin Instead of inverting dm->sfNatural, we can call PetscSFReduceBegin/End with MPI_Op MPI_SUM. 325b64f75a9SBlaise Bourdin Here the SUM really does nothing since sfNatural is one to one, as long as gV is set to zero first. */ 3269566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(gv)); 3279566063dSJacob Faibussowitsch PetscCall(VecGetArray(gv, &outarray)); 3289566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(nv, &inarray)); 3299566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(dm->sfNatural, MPIU_SCALAR, (PetscScalar *)inarray, outarray, MPI_SUM)); 3309566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(nv, &inarray)); 3319566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(gv, &outarray)); 332a6a55facSMatthew G. Knepley } else if (size == 1) { 3339566063dSJacob Faibussowitsch PetscCall(VecCopy(nv, gv)); 334f7d195e4SLawrence Mitchell } else { 335f7d195e4SLawrence Mitchell PetscCheck(!dm->useNatural, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "DM global to natural SF not present.\nIf DMPlexDistribute() was called and a section was defined, report to petsc-maint@mcs.anl.gov."); 336f7d195e4SLawrence Mitchell SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created.\nYou must call DMSetUseNatural() before DMPlexDistribute()."); 337f7d195e4SLawrence Mitchell } 3389566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_NaturalToGlobalBegin, dm, 0, 0, 0)); 339*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 340fa534816SMatthew G. Knepley } 341fa534816SMatthew G. Knepley 342fa534816SMatthew G. Knepley /*@ 343a1cb98faSBarry Smith DMPlexNaturalToGlobalEnd - Rearranges a `Vec` in the natural order to the Global order. 344fa534816SMatthew G. Knepley 345fa534816SMatthew G. Knepley Collective on dm 346fa534816SMatthew G. Knepley 347fa534816SMatthew G. Knepley Input Parameters: 348a1cb98faSBarry Smith + dm - The distributed `DMPLEX` 349a1cb98faSBarry Smith - nv - The natural `Vec` 350fa534816SMatthew G. Knepley 351fa534816SMatthew G. Knepley Output Parameters: 352a1cb98faSBarry Smith . gv - The global `Vec` 353fa534816SMatthew G. Knepley 354fa534816SMatthew G. Knepley Level: intermediate 355fa534816SMatthew G. Knepley 356a1cb98faSBarry Smith Note: 357a1cb98faSBarry Smith The user must call `DMSetUseNatural`(dm, `PETSC_TRUE`) before `DMPlexDistribute()`. 358a1cb98faSBarry Smith 359a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `Vec`, `DMPlexDistribute()`, `DMPlexDistributeField()`, `DMPlexNaturalToGlobalBegin()`, `DMPlexGlobalToNaturalBegin()` 360fa534816SMatthew G. Knepley @*/ 361d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexNaturalToGlobalEnd(DM dm, Vec nv, Vec gv) 362d71ae5a4SJacob Faibussowitsch { 363fa534816SMatthew G. Knepley const PetscScalar *inarray; 364fa534816SMatthew G. Knepley PetscScalar *outarray; 365a6a55facSMatthew G. Knepley PetscMPIInt size; 366fa534816SMatthew G. Knepley 367fa534816SMatthew G. Knepley PetscFunctionBegin; 3689566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_NaturalToGlobalEnd, dm, 0, 0, 0)); 3699566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 370fa534816SMatthew G. Knepley if (dm->sfNatural) { 3719566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(nv, &inarray)); 3729566063dSJacob Faibussowitsch PetscCall(VecGetArray(gv, &outarray)); 3739566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(dm->sfNatural, MPIU_SCALAR, (PetscScalar *)inarray, outarray, MPI_SUM)); 3749566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(nv, &inarray)); 3759566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(gv, &outarray)); 376a6a55facSMatthew G. Knepley } else if (size == 1) { 377f7d195e4SLawrence Mitchell } else { 378f7d195e4SLawrence Mitchell PetscCheck(!dm->useNatural, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "DM global to natural SF not present.\nIf DMPlexDistribute() was called and a section was defined, report to petsc-maint@mcs.anl.gov."); 379f7d195e4SLawrence Mitchell SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created.\nYou must call DMSetUseNatural() before DMPlexDistribute()."); 380f7d195e4SLawrence Mitchell } 3819566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_NaturalToGlobalEnd, dm, 0, 0, 0)); 382*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 383fa534816SMatthew G. Knepley } 38409cf685aSAlexis Marboeuf 38509cf685aSAlexis Marboeuf /*@ 3865cb80ecdSBarry Smith DMPlexCreateNaturalVector - Provide a `Vec` capable of holding the natural ordering and distribution. 38709cf685aSAlexis Marboeuf 38809cf685aSAlexis Marboeuf Collective on dm 38909cf685aSAlexis Marboeuf 3905cb80ecdSBarry Smith Input Parameter: 391a1cb98faSBarry Smith . dm - The distributed `DMPLEX` 39209cf685aSAlexis Marboeuf 3935cb80ecdSBarry Smith Output Parameter: 3945cb80ecdSBarry Smith . nv - The natural `Vec` 39509cf685aSAlexis Marboeuf 39609cf685aSAlexis Marboeuf Level: intermediate 39709cf685aSAlexis Marboeuf 398a1cb98faSBarry Smith Note: 399a1cb98faSBarry Smith The user must call `DMSetUseNatural`(dm, `PETSC_TRUE`) before `DMPlexDistribute()`. 400a1cb98faSBarry Smith 401a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `Vec`, `DMPlexDistribute()`, `DMPlexNaturalToGlobalBegin()`, `DMPlexGlobalToNaturalBegin()` 40209cf685aSAlexis Marboeuf @*/ 403d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateNaturalVector(DM dm, Vec *nv) 404d71ae5a4SJacob Faibussowitsch { 40509cf685aSAlexis Marboeuf PetscMPIInt size; 40609cf685aSAlexis Marboeuf 40709cf685aSAlexis Marboeuf PetscFunctionBegin; 40809cf685aSAlexis Marboeuf PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 40909cf685aSAlexis Marboeuf if (dm->sfNatural) { 4106fba1fe0SBlaise Bourdin PetscInt nleaves, bs, maxbs; 4112e8d78feSBlaise Bourdin Vec v; 4126fba1fe0SBlaise Bourdin 4136fba1fe0SBlaise Bourdin /* 4146fba1fe0SBlaise Bourdin Setting the natural vector block size. 4156fba1fe0SBlaise Bourdin We can't get it from a global vector because of constraints, and the block size in the local vector 4166fba1fe0SBlaise Bourdin may be inconsistent across processes, typically when some local vectors have size 0, their block size is set to 1 4176fba1fe0SBlaise Bourdin */ 4182e8d78feSBlaise Bourdin PetscCall(DMGetLocalVector(dm, &v)); 4192e8d78feSBlaise Bourdin PetscCall(VecGetBlockSize(v, &bs)); 4206fba1fe0SBlaise Bourdin PetscCallMPI(MPI_Allreduce(&bs, &maxbs, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 4216fba1fe0SBlaise Bourdin if (bs == 1 && maxbs > 1) bs = maxbs; 4222e8d78feSBlaise Bourdin PetscCall(DMRestoreLocalVector(dm, &v)); 4232e8d78feSBlaise Bourdin 42409cf685aSAlexis Marboeuf PetscCall(PetscSFGetGraph(dm->sfNatural, NULL, &nleaves, NULL, NULL)); 42509cf685aSAlexis Marboeuf PetscCall(VecCreate(PetscObjectComm((PetscObject)dm), nv)); 42609cf685aSAlexis Marboeuf PetscCall(VecSetSizes(*nv, nleaves, PETSC_DETERMINE)); 42709cf685aSAlexis Marboeuf PetscCall(VecSetBlockSize(*nv, bs)); 42809cf685aSAlexis Marboeuf PetscCall(VecSetType(*nv, dm->vectype)); 42909cf685aSAlexis Marboeuf PetscCall(VecSetDM(*nv, dm)); 43009cf685aSAlexis Marboeuf } else if (size == 1) { 4312e8d78feSBlaise Bourdin PetscCall(DMCreateLocalVector(dm, nv)); 43209cf685aSAlexis Marboeuf } else { 43309cf685aSAlexis Marboeuf PetscCheck(!dm->useNatural, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "DM global to natural SF not present.\nIf DMPlexDistribute() was called and a section was defined, report to petsc-maint@mcs.anl.gov."); 43409cf685aSAlexis Marboeuf SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created.\nYou must call DMSetUseNatural() before DMPlexDistribute()."); 43509cf685aSAlexis Marboeuf } 436*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 43709cf685aSAlexis Marboeuf } 438