xref: /petsc/src/dm/impls/plex/plexnatural.c (revision 3ba1676111f5c958fe6c2729b46ca4d523958bb3)
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), &section));
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, &sectionDist));
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(&sectionDist));
2029566063dSJacob Faibussowitsch   PetscCall(PetscFree(remoteOffsets));
2039566063dSJacob Faibussowitsch   if (destroyFlag) PetscCall(PetscSectionDestroy(&section));
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