xref: /petsc/src/dm/impls/plex/plexnatural.c (revision 28b400f66ebc7ae0049166a2294dfcd3df27e64b)
1fa534816SMatthew G. Knepley #include <petsc/private/dmpleximpl.h>   /*I      "petscdmplex.h"   I*/
2fa534816SMatthew G. Knepley 
3fa534816SMatthew G. Knepley /*@
4f94b4a02SBlaise Bourdin   DMPlexSetMigrationSF - Sets the SF for migrating from a parent DM into this DM
5f94b4a02SBlaise Bourdin 
65d3b26e6SMatthew G. Knepley   Input Parameters:
7f94b4a02SBlaise Bourdin + dm        - The DM
85d3b26e6SMatthew G. Knepley - naturalSF - The PetscSF
95d3b26e6SMatthew G. Knepley 
105d3b26e6SMatthew G. Knepley   Note: It is necessary to call this in order to have DMCreateSubDM() or DMCreateSuperDM() build the Global-To-Natural map
115d3b26e6SMatthew G. Knepley 
12f94b4a02SBlaise Bourdin   Level: intermediate
13f94b4a02SBlaise Bourdin 
14f94b4a02SBlaise Bourdin .seealso: DMPlexDistribute(), DMPlexDistributeField(), DMPlexCreateMigrationSF(), DMPlexGetMigrationSF()
15f94b4a02SBlaise Bourdin @*/
16f94b4a02SBlaise Bourdin PetscErrorCode DMPlexSetMigrationSF(DM dm, PetscSF migrationSF)
17f94b4a02SBlaise Bourdin {
18f94b4a02SBlaise Bourdin   PetscFunctionBegin;
19f94b4a02SBlaise Bourdin   dm->sfMigration = migrationSF;
205f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectReference((PetscObject) migrationSF));
21f94b4a02SBlaise Bourdin   PetscFunctionReturn(0);
22f94b4a02SBlaise Bourdin }
23f94b4a02SBlaise Bourdin 
24f94b4a02SBlaise Bourdin /*@
25f94b4a02SBlaise Bourdin   DMPlexGetMigrationSF - Gets the SF for migrating from a parent DM into this DM
26f94b4a02SBlaise Bourdin 
275d3b26e6SMatthew G. Knepley   Input Parameter:
285d3b26e6SMatthew G. Knepley . dm          - The DM
295d3b26e6SMatthew G. Knepley 
305d3b26e6SMatthew G. Knepley   Output Parameter:
315d3b26e6SMatthew G. Knepley . migrationSF - The PetscSF
325d3b26e6SMatthew G. Knepley 
33f94b4a02SBlaise Bourdin   Level: intermediate
34f94b4a02SBlaise Bourdin 
35f94b4a02SBlaise Bourdin .seealso: DMPlexDistribute(), DMPlexDistributeField(), DMPlexCreateMigrationSF(), DMPlexSetMigrationSF
36f94b4a02SBlaise Bourdin @*/
37f94b4a02SBlaise Bourdin PetscErrorCode DMPlexGetMigrationSF(DM dm, PetscSF *migrationSF)
38f94b4a02SBlaise Bourdin {
39f94b4a02SBlaise Bourdin   PetscFunctionBegin;
40f94b4a02SBlaise Bourdin   *migrationSF = dm->sfMigration;
41f94b4a02SBlaise Bourdin   PetscFunctionReturn(0);
42f94b4a02SBlaise Bourdin }
43f94b4a02SBlaise Bourdin 
44f94b4a02SBlaise Bourdin /*@
45f94b4a02SBlaise Bourdin   DMPlexSetGlobalToNaturalSF - Sets the SF for mapping Global Vec to the Natural Vec
46f94b4a02SBlaise Bourdin 
475d3b26e6SMatthew G. Knepley   Input Parameters:
48f94b4a02SBlaise Bourdin + dm          - The DM
495d3b26e6SMatthew G. Knepley - naturalSF   - The PetscSF
505d3b26e6SMatthew G. Knepley 
51f94b4a02SBlaise Bourdin   Level: intermediate
52f94b4a02SBlaise Bourdin 
53f94b4a02SBlaise Bourdin .seealso: DMPlexDistribute(), DMPlexDistributeField(), DMPlexCreateGlobalToNaturalSF(), DMPlexGetGlobaltoNaturalSF()
54f94b4a02SBlaise Bourdin @*/
55f94b4a02SBlaise Bourdin PetscErrorCode DMPlexSetGlobalToNaturalSF(DM dm, PetscSF naturalSF)
56f94b4a02SBlaise Bourdin {
57f94b4a02SBlaise Bourdin   PetscFunctionBegin;
58f94b4a02SBlaise Bourdin   dm->sfNatural = naturalSF;
595f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectReference((PetscObject) naturalSF));
60f94b4a02SBlaise Bourdin   dm->useNatural = PETSC_TRUE;
61f94b4a02SBlaise Bourdin   PetscFunctionReturn(0);
62f94b4a02SBlaise Bourdin }
63f94b4a02SBlaise Bourdin 
64f94b4a02SBlaise Bourdin /*@
65f94b4a02SBlaise Bourdin   DMPlexGetGlobalToNaturalSF - Gets the SF for mapping Global Vec to the Natural Vec
66f94b4a02SBlaise Bourdin 
675d3b26e6SMatthew G. Knepley   Input Parameter:
685d3b26e6SMatthew G. Knepley . dm          - The DM
695d3b26e6SMatthew G. Knepley 
705d3b26e6SMatthew G. Knepley   Output Parameter:
715d3b26e6SMatthew G. Knepley . naturalSF   - The PetscSF
725d3b26e6SMatthew G. Knepley 
73f94b4a02SBlaise Bourdin   Level: intermediate
74f94b4a02SBlaise Bourdin 
75f94b4a02SBlaise Bourdin .seealso: DMPlexDistribute(), DMPlexDistributeField(), DMPlexCreateGlobalToNaturalSF(), DMPlexSetGlobaltoNaturalSF
76f94b4a02SBlaise Bourdin @*/
77f94b4a02SBlaise Bourdin PetscErrorCode DMPlexGetGlobalToNaturalSF(DM dm, PetscSF *naturalSF)
78f94b4a02SBlaise Bourdin {
79f94b4a02SBlaise Bourdin   PetscFunctionBegin;
80f94b4a02SBlaise Bourdin   *naturalSF = dm->sfNatural;
81f94b4a02SBlaise Bourdin   PetscFunctionReturn(0);
82f94b4a02SBlaise Bourdin }
83f94b4a02SBlaise Bourdin 
84f94b4a02SBlaise Bourdin /*@
85fa534816SMatthew G. Knepley   DMPlexCreateGlobalToNaturalSF - Creates the SF for mapping Global Vec to the Natural Vec
86fa534816SMatthew G. Knepley 
87fa534816SMatthew G. Knepley   Input Parameters:
88fa534816SMatthew G. Knepley + dm          - The DM
895c3f5608SAlexisMarb . section     - The PetscSection describing the Vec before the mesh was distributed,
905c3f5608SAlexisMarb                 or NULL if not available
915c3f5608SAlexisMarb - sfMigration - The PetscSF used to distribute the mesh, or NULL if it cannot be computed
92fa534816SMatthew G. Knepley 
935d3b26e6SMatthew G. Knepley   Output Parameter:
94fa534816SMatthew G. Knepley . sfNatural   - PetscSF for mapping the Vec in PETSc ordering to the canonical ordering
95fa534816SMatthew G. Knepley 
965d3b26e6SMatthew G. Knepley   Note: This is not typically called by the user.
975d3b26e6SMatthew G. Knepley 
98fa534816SMatthew G. Knepley   Level: intermediate
99fa534816SMatthew G. Knepley 
100fa534816SMatthew G. Knepley .seealso: DMPlexDistribute(), DMPlexDistributeField()
101fa534816SMatthew G. Knepley  @*/
102fa534816SMatthew G. Knepley PetscErrorCode DMPlexCreateGlobalToNaturalSF(DM dm, PetscSection section, PetscSF sfMigration, PetscSF *sfNatural)
103fa534816SMatthew G. Knepley {
104fa534816SMatthew G. Knepley   MPI_Comm       comm;
1055c3f5608SAlexisMarb   Vec            gv, tmpVec;
106e5b44f4fSMatthew G. Knepley   PetscSF        sf, sfEmbed, sfSeqToNatural, sfField, sfFieldInv;
107e5b44f4fSMatthew G. Knepley   PetscSection   gSection, sectionDist, gLocSection;
108fa534816SMatthew G. Knepley   PetscInt      *spoints, *remoteOffsets;
1095c3f5608SAlexisMarb   PetscInt       ssize, pStart, pEnd, p, globalSize;
1103a350576SJunchao Zhang   PetscLayout    map;
1115c3f5608SAlexisMarb   PetscBool      destroyFlag = PETSC_FALSE;
112fa534816SMatthew G. Knepley 
113fa534816SMatthew G. Knepley   PetscFunctionBegin;
1145f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject) dm, &comm));
1155c3f5608SAlexisMarb   if (!sfMigration) {
1165c3f5608SAlexisMarb     /* If sfMigration is missing,
1175c3f5608SAlexisMarb     sfNatural cannot be computed and is set to NULL */
1185c3f5608SAlexisMarb     *sfNatural = NULL;
1195c3f5608SAlexisMarb     PetscFunctionReturn(0);
1205c3f5608SAlexisMarb   } else if (!section) {
1215c3f5608SAlexisMarb     /* If the sequential section is not provided (NULL),
1225c3f5608SAlexisMarb     it is reconstructed from the parallel section */
1235c3f5608SAlexisMarb     PetscSF sfMigrationInv;
1245c3f5608SAlexisMarb     PetscSection localSection;
1255c3f5608SAlexisMarb 
1265f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetLocalSection(dm, &localSection));
1275f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFCreateInverseSF(sfMigration, &sfMigrationInv));
1285f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionCreate(PetscObjectComm((PetscObject) dm), &section));
1295f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFDistributeSection(sfMigrationInv, localSection, NULL, section));
1305f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFDestroy(&sfMigrationInv));
1315c3f5608SAlexisMarb     destroyFlag = PETSC_TRUE;
1325c3f5608SAlexisMarb   }
1335f80ce2aSJacob Faibussowitsch   /* CHKERRQ(PetscPrintf(comm, "Point migration SF\n"));
1345f80ce2aSJacob Faibussowitsch    CHKERRQ(PetscSFView(sfMigration, 0)); */
135e5b44f4fSMatthew G. Knepley   /* Create a new section from distributing the original section */
1365f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionCreate(comm, &sectionDist));
1375f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFDistributeSection(sfMigration, section, &remoteOffsets, sectionDist));
1385f80ce2aSJacob Faibussowitsch   /* CHKERRQ(PetscPrintf(comm, "Distributed Section\n"));
1395f80ce2aSJacob Faibussowitsch    CHKERRQ(PetscSectionView(sectionDist, PETSC_VIEWER_STDOUT_WORLD)); */
1405f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetLocalSection(dm, sectionDist));
1415c3f5608SAlexisMarb   /* If a sequential section is provided but no dof is affected,
1425c3f5608SAlexisMarb   sfNatural cannot be computed and is set to NULL */
1435f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreateGlobalVector(dm, &tmpVec));
1445f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetSize(tmpVec, &globalSize));
1455f80ce2aSJacob Faibussowitsch   CHKERRQ(DMRestoreGlobalVector(dm, &tmpVec));
14614744f87SBlaise Bourdin   if (globalSize) {
147fa534816SMatthew G. Knepley   /* Get a pruned version of migration SF */
1485f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetGlobalSection(dm, &gSection));
1495f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetChart(gSection, &pStart, &pEnd));
150fa534816SMatthew G. Knepley     for (p = pStart, ssize = 0; p < pEnd; ++p) {
151fa534816SMatthew G. Knepley       PetscInt dof, off;
152fa534816SMatthew G. Knepley 
1535f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetDof(gSection, p, &dof));
1545f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetOffset(gSection, p, &off));
155fa534816SMatthew G. Knepley       if ((dof > 0) && (off >= 0)) ++ssize;
156fa534816SMatthew G. Knepley     }
1575f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(ssize, &spoints));
158fa534816SMatthew G. Knepley     for (p = pStart, ssize = 0; p < pEnd; ++p) {
159fa534816SMatthew G. Knepley       PetscInt dof, off;
160fa534816SMatthew G. Knepley 
1615f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetDof(gSection, p, &dof));
1625f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetOffset(gSection, p, &off));
163fa534816SMatthew G. Knepley       if ((dof > 0) && (off >= 0)) spoints[ssize++] = p;
164fa534816SMatthew G. Knepley     }
1655f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFCreateEmbeddedLeafSF(sfMigration, ssize, spoints, &sfEmbed));
1665f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(spoints));
1675f80ce2aSJacob Faibussowitsch     /* CHKERRQ(PetscPrintf(comm, "Embedded SF\n"));
1685f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFView(sfEmbed, 0)); */
169fa534816SMatthew G. Knepley     /* Create the SF for seq to natural */
1705f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetGlobalVector(dm, &gv));
1715f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetLayout(gv,&map));
1723a350576SJunchao Zhang     /* Note that entries of gv are leaves in sfSeqToNatural, entries of the seq vec are roots */
1735f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFCreate(comm, &sfSeqToNatural));
1745f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFSetGraphWithPattern(sfSeqToNatural, map, PETSCSF_PATTERN_GATHER));
1755f80ce2aSJacob Faibussowitsch     CHKERRQ(DMRestoreGlobalVector(dm, &gv));
1765f80ce2aSJacob Faibussowitsch     /* CHKERRQ(PetscPrintf(comm, "Seq-to-Natural SF\n"));
1775f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFView(sfSeqToNatural, 0)); */
178fa534816SMatthew G. Knepley     /* Create the SF associated with this section */
1795f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetPointSF(dm, &sf));
1805f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionCreateGlobalSection(sectionDist, sf, PETSC_FALSE, PETSC_TRUE, &gLocSection));
1815f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFCreateSectionSF(sfEmbed, section, remoteOffsets, gLocSection, &sfField));
1825f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFDestroy(&sfEmbed));
1835f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionDestroy(&gLocSection));
1845f80ce2aSJacob Faibussowitsch     /* CHKERRQ(PetscPrintf(comm, "Field SF\n"));
1855f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFView(sfField, 0)); */
186fa534816SMatthew G. Knepley     /* Invert the field SF so it's now from distributed to sequential */
1875f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFCreateInverseSF(sfField, &sfFieldInv));
1885f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFDestroy(&sfField));
1895f80ce2aSJacob Faibussowitsch     /* CHKERRQ(PetscPrintf(comm, "Inverse Field SF\n"));
1905f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFView(sfFieldInv, 0)); */
191fa534816SMatthew G. Knepley     /* Multiply the sfFieldInv with the */
1925f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFComposeInverse(sfFieldInv, sfSeqToNatural, sfNatural));
1935f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectViewFromOptions((PetscObject) *sfNatural, NULL, "-globaltonatural_sf_view"));
194fa534816SMatthew G. Knepley     /* Clean up */
1955f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFDestroy(&sfFieldInv));
1965f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFDestroy(&sfSeqToNatural));
19714744f87SBlaise Bourdin   } else {
19814744f87SBlaise Bourdin     *sfNatural = NULL;
19914744f87SBlaise Bourdin   }
2005f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionDestroy(&sectionDist));
2015f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(remoteOffsets));
2025f80ce2aSJacob Faibussowitsch   if (destroyFlag) CHKERRQ(PetscSectionDestroy(&section));
203fa534816SMatthew G. Knepley   PetscFunctionReturn(0);
204fa534816SMatthew G. Knepley }
205fa534816SMatthew G. Knepley 
206fa534816SMatthew G. Knepley /*@
207fa534816SMatthew G. Knepley   DMPlexGlobalToNaturalBegin - Rearranges a global Vector in the natural order.
208fa534816SMatthew G. Knepley 
209fa534816SMatthew G. Knepley   Collective on dm
210fa534816SMatthew G. Knepley 
211fa534816SMatthew G. Knepley   Input Parameters:
212fa534816SMatthew G. Knepley + dm - The distributed DMPlex
213fa534816SMatthew G. Knepley - gv - The global Vec
214fa534816SMatthew G. Knepley 
215fa534816SMatthew G. Knepley   Output Parameters:
216fa534816SMatthew G. Knepley . nv - Vec in the canonical ordering distributed over all processors associated with gv
217fa534816SMatthew G. Knepley 
21842ea106eSTristan Konolige   Note: The user must call DMSetUseNatural(dm, PETSC_TRUE) before DMPlexDistribute().
219fa534816SMatthew G. Knepley 
220fa534816SMatthew G. Knepley   Level: intermediate
221fa534816SMatthew G. Knepley 
222fa534816SMatthew G. Knepley .seealso: DMPlexDistribute(), DMPlexDistributeField(), DMPlexNaturalToGlobalBegin(), DMPlexGlobalToNaturalEnd()
223fa534816SMatthew G. Knepley @*/
224fa534816SMatthew G. Knepley PetscErrorCode DMPlexGlobalToNaturalBegin(DM dm, Vec gv, Vec nv)
225fa534816SMatthew G. Knepley {
226fa534816SMatthew G. Knepley   const PetscScalar *inarray;
227fa534816SMatthew G. Knepley   PetscScalar       *outarray;
228a6a55facSMatthew G. Knepley   PetscMPIInt        size;
229fa534816SMatthew G. Knepley 
230fa534816SMatthew G. Knepley   PetscFunctionBegin;
2315f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(DMPLEX_GlobalToNaturalBegin,dm,0,0,0));
2325f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_size(PetscObjectComm((PetscObject) dm), &size));
233fa534816SMatthew G. Knepley   if (dm->sfNatural) {
2345f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArray(nv, &outarray));
2355f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArrayRead(gv, &inarray));
2365f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFBcastBegin(dm->sfNatural, MPIU_SCALAR, (PetscScalar *) inarray, outarray,MPI_REPLACE));
2375f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArrayRead(gv, &inarray));
2385f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArray(nv, &outarray));
239a6a55facSMatthew G. Knepley   } else if (size == 1) {
2405f80ce2aSJacob Faibussowitsch     CHKERRQ(VecCopy(gv, nv));
241*28b400f6SJacob Faibussowitsch   } else 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.");
242546078acSJacob Faibussowitsch   else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created.\nYou must call DMSetUseNatural() before DMPlexDistribute().");
2435f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventEnd(DMPLEX_GlobalToNaturalBegin,dm,0,0,0));
244fa534816SMatthew G. Knepley   PetscFunctionReturn(0);
245fa534816SMatthew G. Knepley }
246fa534816SMatthew G. Knepley 
247fa534816SMatthew G. Knepley /*@
248fa534816SMatthew G. Knepley   DMPlexGlobalToNaturalEnd - Rearranges a global Vector in the natural order.
249fa534816SMatthew G. Knepley 
250fa534816SMatthew G. Knepley   Collective on dm
251fa534816SMatthew G. Knepley 
252fa534816SMatthew G. Knepley   Input Parameters:
253fa534816SMatthew G. Knepley + dm - The distributed DMPlex
254fa534816SMatthew G. Knepley - gv - The global Vec
255fa534816SMatthew G. Knepley 
25697bb3fdcSJose E. Roman   Output Parameter:
257fa534816SMatthew G. Knepley . nv - The natural Vec
258fa534816SMatthew G. Knepley 
25942ea106eSTristan Konolige   Note: The user must call DMSetUseNatural(dm, PETSC_TRUE) before DMPlexDistribute().
260fa534816SMatthew G. Knepley 
261fa534816SMatthew G. Knepley   Level: intermediate
262fa534816SMatthew G. Knepley 
263fa534816SMatthew G. Knepley  .seealso: DMPlexDistribute(), DMPlexDistributeField(), DMPlexNaturalToGlobalBegin(), DMPlexGlobalToNaturalBegin()
264fa534816SMatthew G. Knepley  @*/
265fa534816SMatthew G. Knepley PetscErrorCode DMPlexGlobalToNaturalEnd(DM dm, Vec gv, Vec nv)
266fa534816SMatthew G. Knepley {
267fa534816SMatthew G. Knepley   const PetscScalar *inarray;
268fa534816SMatthew G. Knepley   PetscScalar       *outarray;
269a6a55facSMatthew G. Knepley   PetscMPIInt        size;
270fa534816SMatthew G. Knepley 
271fa534816SMatthew G. Knepley   PetscFunctionBegin;
2725f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(DMPLEX_GlobalToNaturalEnd,dm,0,0,0));
2735f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_size(PetscObjectComm((PetscObject) dm), &size));
274fa534816SMatthew G. Knepley   if (dm->sfNatural) {
2755f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArrayRead(gv, &inarray));
2765f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArray(nv, &outarray));
2775f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFBcastEnd(dm->sfNatural, MPIU_SCALAR, (PetscScalar *) inarray, outarray,MPI_REPLACE));
2785f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArrayRead(gv, &inarray));
2795f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArray(nv, &outarray));
280a6a55facSMatthew G. Knepley   } else if (size == 1) {
281*28b400f6SJacob Faibussowitsch   } else 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.");
282546078acSJacob Faibussowitsch   else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created.\nYou must call DMSetUseNatural() before DMPlexDistribute().");
2835f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventEnd(DMPLEX_GlobalToNaturalEnd,dm,0,0,0));
284fa534816SMatthew G. Knepley   PetscFunctionReturn(0);
285fa534816SMatthew G. Knepley }
286fa534816SMatthew G. Knepley 
287fa534816SMatthew G. Knepley /*@
288fa534816SMatthew G. Knepley   DMPlexNaturalToGlobalBegin - Rearranges a Vector in the natural order to the Global order.
289fa534816SMatthew G. Knepley 
290fa534816SMatthew G. Knepley   Collective on dm
291fa534816SMatthew G. Knepley 
292fa534816SMatthew G. Knepley   Input Parameters:
293fa534816SMatthew G. Knepley + dm - The distributed DMPlex
294fa534816SMatthew G. Knepley - nv - The natural Vec
295fa534816SMatthew G. Knepley 
296fa534816SMatthew G. Knepley   Output Parameters:
297fa534816SMatthew G. Knepley . gv - The global Vec
298fa534816SMatthew G. Knepley 
29942ea106eSTristan Konolige   Note: The user must call DMSetUseNatural(dm, PETSC_TRUE) before DMPlexDistribute().
300fa534816SMatthew G. Knepley 
301fa534816SMatthew G. Knepley   Level: intermediate
302fa534816SMatthew G. Knepley 
303fa534816SMatthew G. Knepley .seealso: DMPlexDistribute(), DMPlexDistributeField(), DMPlexNaturalToGlobalBegin(),DMPlexGlobalToNaturalEnd()
304fa534816SMatthew G. Knepley @*/
305fa534816SMatthew G. Knepley PetscErrorCode DMPlexNaturalToGlobalBegin(DM dm, Vec nv, Vec gv)
306fa534816SMatthew G. Knepley {
307fa534816SMatthew G. Knepley   const PetscScalar *inarray;
308fa534816SMatthew G. Knepley   PetscScalar       *outarray;
309a6a55facSMatthew G. Knepley   PetscMPIInt        size;
310fa534816SMatthew G. Knepley 
311fa534816SMatthew G. Knepley   PetscFunctionBegin;
3125f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(DMPLEX_NaturalToGlobalBegin,dm,0,0,0));
3135f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_size(PetscObjectComm((PetscObject) dm), &size));
314fa534816SMatthew G. Knepley   if (dm->sfNatural) {
315a5b23f4aSJose E. Roman     /* We only have access to the SF that goes from Global to Natural.
316b64f75a9SBlaise Bourdin        Instead of inverting dm->sfNatural, we can call PetscSFReduceBegin/End with MPI_Op MPI_SUM.
317b64f75a9SBlaise Bourdin        Here the SUM really does nothing since sfNatural is one to one, as long as gV is set to zero first. */
3185f80ce2aSJacob Faibussowitsch     CHKERRQ(VecZeroEntries(gv));
3195f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArray(gv, &outarray));
3205f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArrayRead(nv, &inarray));
3215f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFReduceBegin(dm->sfNatural, MPIU_SCALAR, (PetscScalar *) inarray, outarray, MPI_SUM));
3225f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArrayRead(nv, &inarray));
3235f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArray(gv, &outarray));
324a6a55facSMatthew G. Knepley   } else if (size == 1) {
3255f80ce2aSJacob Faibussowitsch     CHKERRQ(VecCopy(nv, gv));
326*28b400f6SJacob Faibussowitsch   } else 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.");
327546078acSJacob Faibussowitsch   else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created.\nYou must call DMSetUseNatural() before DMPlexDistribute().");
3285f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventEnd(DMPLEX_NaturalToGlobalBegin,dm,0,0,0));
329fa534816SMatthew G. Knepley   PetscFunctionReturn(0);
330fa534816SMatthew G. Knepley }
331fa534816SMatthew G. Knepley 
332fa534816SMatthew G. Knepley /*@
333fa534816SMatthew G. Knepley   DMPlexNaturalToGlobalEnd - Rearranges a Vector in the natural order to the Global order.
334fa534816SMatthew G. Knepley 
335fa534816SMatthew G. Knepley   Collective on dm
336fa534816SMatthew G. Knepley 
337fa534816SMatthew G. Knepley   Input Parameters:
338fa534816SMatthew G. Knepley + dm - The distributed DMPlex
339fa534816SMatthew G. Knepley - nv - The natural Vec
340fa534816SMatthew G. Knepley 
341fa534816SMatthew G. Knepley   Output Parameters:
342fa534816SMatthew G. Knepley . gv - The global Vec
343fa534816SMatthew G. Knepley 
34442ea106eSTristan Konolige   Note: The user must call DMSetUseNatural(dm, PETSC_TRUE) before DMPlexDistribute().
345fa534816SMatthew G. Knepley 
346fa534816SMatthew G. Knepley   Level: intermediate
347fa534816SMatthew G. Knepley 
348fa534816SMatthew G. Knepley .seealso: DMPlexDistribute(), DMPlexDistributeField(), DMPlexNaturalToGlobalBegin(), DMPlexGlobalToNaturalBegin()
349fa534816SMatthew G. Knepley  @*/
350fa534816SMatthew G. Knepley PetscErrorCode DMPlexNaturalToGlobalEnd(DM dm, Vec nv, Vec gv)
351fa534816SMatthew G. Knepley {
352fa534816SMatthew G. Knepley   const PetscScalar *inarray;
353fa534816SMatthew G. Knepley   PetscScalar       *outarray;
354a6a55facSMatthew G. Knepley   PetscMPIInt        size;
355fa534816SMatthew G. Knepley 
356fa534816SMatthew G. Knepley   PetscFunctionBegin;
3575f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(DMPLEX_NaturalToGlobalEnd,dm,0,0,0));
3585f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_size(PetscObjectComm((PetscObject) dm), &size));
359fa534816SMatthew G. Knepley   if (dm->sfNatural) {
3605f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArrayRead(nv, &inarray));
3615f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArray(gv, &outarray));
3625f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFReduceEnd(dm->sfNatural, MPIU_SCALAR, (PetscScalar *) inarray, outarray, MPI_SUM));
3635f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArrayRead(nv, &inarray));
3645f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArray(gv, &outarray));
365a6a55facSMatthew G. Knepley   } else if (size == 1) {
366*28b400f6SJacob Faibussowitsch   } else 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.");
367546078acSJacob Faibussowitsch   else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created.\nYou must call DMSetUseNatural() before DMPlexDistribute().");
3685f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventEnd(DMPLEX_NaturalToGlobalEnd,dm,0,0,0));
369fa534816SMatthew G. Knepley   PetscFunctionReturn(0);
370fa534816SMatthew G. Knepley }
371