Actual source code: plexnatural.c

petsc-3.10.5 2019-03-28
Report Typos and Errors
  1:  #include <petsc/private/dmpleximpl.h>

  3: /*@
  4:   DMPlexSetMigrationSF - Sets the SF for migrating from a parent DM into this DM

  6: + dm          - The DM
  7: . naturalSF   - The PetscSF
  8:   Level: intermediate

 10: .seealso: DMPlexDistribute(), DMPlexDistributeField(), DMPlexCreateMigrationSF(), DMPlexGetMigrationSF()
 11: @*/
 12: PetscErrorCode DMPlexSetMigrationSF(DM dm, PetscSF migrationSF)
 13: {
 16:   dm->sfMigration = migrationSF;
 17:   PetscObjectReference((PetscObject) migrationSF);
 18:   return(0);
 19: }

 21: /*@
 22:   DMPlexGetMigrationSF - Gets the SF for migrating from a parent DM into this DM

 24: + dm          - The DM
 25: . *migrationSF   - The PetscSF
 26:   Level: intermediate

 28: .seealso: DMPlexDistribute(), DMPlexDistributeField(), DMPlexCreateMigrationSF(), DMPlexSetMigrationSF
 29: @*/
 30: PetscErrorCode DMPlexGetMigrationSF(DM dm, PetscSF *migrationSF)
 31: {
 33:   *migrationSF = dm->sfMigration;
 34:   return(0);
 35: }

 37: /*@
 38:   DMPlexSetGlobalToNaturalSF - Sets the SF for mapping Global Vec to the Natural Vec

 40: + dm          - The DM
 41: . naturalSF   - The PetscSF
 42:   Level: intermediate

 44: .seealso: DMPlexDistribute(), DMPlexDistributeField(), DMPlexCreateGlobalToNaturalSF(), DMPlexGetGlobaltoNaturalSF()
 45: @*/
 46: PetscErrorCode DMPlexSetGlobalToNaturalSF(DM dm, PetscSF naturalSF)
 47: {
 50:   dm->sfNatural = naturalSF;
 51:   PetscObjectReference((PetscObject) naturalSF);
 52:   dm->useNatural = PETSC_TRUE;
 53:   return(0);
 54: }

 56: /*@
 57:   DMPlexGetGlobalToNaturalSF - Gets the SF for mapping Global Vec to the Natural Vec

 59: + dm          - The DM
 60: . *naturalSF   - The PetscSF
 61:   Level: intermediate

 63: .seealso: DMPlexDistribute(), DMPlexDistributeField(), DMPlexCreateGlobalToNaturalSF(), DMPlexSetGlobaltoNaturalSF
 64: @*/
 65: PetscErrorCode DMPlexGetGlobalToNaturalSF(DM dm, PetscSF *naturalSF)
 66: {
 68:   *naturalSF = dm->sfNatural;
 69:   return(0);
 70: }

 72: /*@
 73:   DMPlexCreateGlobalToNaturalSF - Creates the SF for mapping Global Vec to the Natural Vec

 75:   Input Parameters:
 76: + dm          - The DM
 77: . section     - The PetscSection before the mesh was distributed
 78: - sfMigration - The PetscSF used to distribute the mesh

 80:   Output Parameters:
 81: . sfNatural - PetscSF for mapping the Vec in PETSc ordering to the canonical ordering

 83:   Level: intermediate

 85: .seealso: DMPlexDistribute(), DMPlexDistributeField()
 86:  @*/
 87: PetscErrorCode DMPlexCreateGlobalToNaturalSF(DM dm, PetscSection section, PetscSF sfMigration, PetscSF *sfNatural)
 88: {
 89:   MPI_Comm       comm;
 90:   Vec            gv;
 91:   PetscSF        sf, sfEmbed, sfSeqToNatural, sfField, sfFieldInv;
 92:   PetscSection   gSection, sectionDist, gLocSection;
 93:   PetscInt      *spoints, *remoteOffsets;
 94:   PetscInt       ssize, pStart, pEnd, p;

 98:   PetscObjectGetComm((PetscObject) dm, &comm);
 99:   /* PetscPrintf(comm, "Point migration SF\n");
100:    PetscSFView(sfMigration, 0); */
101:   /* Create a new section from distributing the original section */
102:   PetscSectionCreate(comm, &sectionDist);
103:   PetscSFDistributeSection(sfMigration, section, &remoteOffsets, sectionDist);
104:   /* PetscPrintf(comm, "Distributed Section\n");
105:    PetscSectionView(sectionDist, PETSC_VIEWER_STDOUT_WORLD); */
106:   DMSetSection(dm, sectionDist);
107:   /* Get a pruned version of migration SF */
108:   DMGetGlobalSection(dm, &gSection);
109:   PetscSectionGetChart(gSection, &pStart, &pEnd);
110:   for (p = pStart, ssize = 0; p < pEnd; ++p) {
111:     PetscInt dof, off;

113:     PetscSectionGetDof(gSection, p, &dof);
114:     PetscSectionGetOffset(gSection, p, &off);
115:     if ((dof > 0) && (off >= 0)) ++ssize;
116:   }
117:   PetscMalloc1(ssize, &spoints);
118:   for (p = pStart, ssize = 0; p < pEnd; ++p) {
119:     PetscInt dof, off;

121:     PetscSectionGetDof(gSection, p, &dof);
122:     PetscSectionGetOffset(gSection, p, &off);
123:     if ((dof > 0) && (off >= 0)) spoints[ssize++] = p;
124:   }
125:   PetscSFCreateEmbeddedLeafSF(sfMigration, ssize, spoints, &sfEmbed);
126:   PetscFree(spoints);
127:   /* PetscPrintf(comm, "Embedded SF\n");
128:    PetscSFView(sfEmbed, 0); */
129:   /* Create the SF for seq to natural */
130:   DMGetGlobalVector(dm, &gv);
131:   PetscSFCreateFromZero(comm, gv, &sfSeqToNatural);
132:   DMRestoreGlobalVector(dm, &gv);
133:   /* PetscPrintf(comm, "Seq-to-Natural SF\n");
134:    PetscSFView(sfSeqToNatural, 0); */
135:   /* Create the SF associated with this section */
136:   DMGetPointSF(dm, &sf);
137:   PetscSectionCreateGlobalSection(sectionDist, sf, PETSC_FALSE, PETSC_TRUE, &gLocSection);
138:   PetscSFCreateSectionSF(sfEmbed, section, remoteOffsets, gLocSection, &sfField);
139:   PetscFree(remoteOffsets);
140:   PetscSFDestroy(&sfEmbed);
141:   PetscSectionDestroy(&gLocSection);
142:   PetscSectionDestroy(&sectionDist);
143:   /* PetscPrintf(comm, "Field SF\n");
144:    PetscSFView(sfField, 0); */
145:   /* Invert the field SF so it's now from distributed to sequential */
146:   PetscSFCreateInverseSF(sfField, &sfFieldInv);
147:   PetscSFDestroy(&sfField);
148:   /* PetscPrintf(comm, "Inverse Field SF\n");
149:    PetscSFView(sfFieldInv, 0); */
150:   /* Multiply the sfFieldInv with the */
151:   PetscSFCompose(sfFieldInv, sfSeqToNatural, sfNatural);
152:   PetscObjectViewFromOptions((PetscObject) *sfNatural, NULL, "-globaltonatural_sf_view");
153:   /* Clean up */
154:   PetscSFDestroy(&sfFieldInv);
155:   PetscSFDestroy(&sfSeqToNatural);
156:   return(0);
157: }

159: /*@
160:   DMPlexGlobalToNaturalBegin - Rearranges a global Vector in the natural order.

162:   Collective on dm

164:   Input Parameters:
165: + dm - The distributed DMPlex
166: - gv - The global Vec

168:   Output Parameters:
169: . nv - Vec in the canonical ordering distributed over all processors associated with gv

171:   Note: The user must call DMPlexSetUseNaturalSF(dm, PETSC_TRUE) before DMPlexDistribute().

173:   Level: intermediate

175: .seealso: DMPlexDistribute(), DMPlexDistributeField(), DMPlexNaturalToGlobalBegin(), DMPlexGlobalToNaturalEnd()
176: @*/
177: PetscErrorCode DMPlexGlobalToNaturalBegin(DM dm, Vec gv, Vec nv)
178: {
179:   const PetscScalar *inarray;
180:   PetscScalar       *outarray;
181:   PetscErrorCode     ierr;

184:   PetscLogEventBegin(DMPLEX_GlobalToNaturalBegin,dm,0,0,0);
185:   if (dm->sfNatural) {
186:     VecGetArray(nv, &outarray);
187:     VecGetArrayRead(gv, &inarray);
188:     PetscSFBcastBegin(dm->sfNatural, MPIU_SCALAR, (PetscScalar *) inarray, outarray);
189:     VecRestoreArrayRead(gv, &inarray);
190:     VecRestoreArray(nv, &outarray);
191:   } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created.\nYou must call DMSetUseNatural() before DMPlexDistribute().\n");
192:   PetscLogEventEnd(DMPLEX_GlobalToNaturalBegin,dm,0,0,0);
193:   return(0);
194: }

196: /*@
197:   DMPlexGlobalToNaturalEnd - Rearranges a global Vector in the natural order.

199:   Collective on dm

201:   Input Parameters:
202: + dm - The distributed DMPlex
203: - gv - The global Vec

205:   Output Parameters:
206: . nv - The natural Vec

208:   Note: The user must call DMPlexSetUseNaturalSF(dm, PETSC_TRUE) before DMPlexDistribute().

210:   Level: intermediate

212:  .seealso: DMPlexDistribute(), DMPlexDistributeField(), DMPlexNaturalToGlobalBegin(), DMPlexGlobalToNaturalBegin()
213:  @*/
214: PetscErrorCode DMPlexGlobalToNaturalEnd(DM dm, Vec gv, Vec nv)
215: {
216:   const PetscScalar *inarray;
217:   PetscScalar       *outarray;
218:   PetscErrorCode     ierr;

221:   PetscLogEventBegin(DMPLEX_GlobalToNaturalEnd,dm,0,0,0);
222:   if (dm->sfNatural) {
223:     VecGetArrayRead(gv, &inarray);
224:     VecGetArray(nv, &outarray);
225:     PetscSFBcastEnd(dm->sfNatural, MPIU_SCALAR, (PetscScalar *) inarray, outarray);
226:     VecRestoreArrayRead(gv, &inarray);
227:     VecRestoreArray(nv, &outarray);
228:   }
229:   PetscLogEventEnd(DMPLEX_GlobalToNaturalEnd,dm,0,0,0);
230:   return(0);
231: }

233: /*@
234:   DMPlexNaturalToGlobalBegin - Rearranges a Vector in the natural order to the Global order.

236:   Collective on dm

238:   Input Parameters:
239: + dm - The distributed DMPlex
240: - nv - The natural Vec

242:   Output Parameters:
243: . gv - The global Vec

245:   Note: The user must call DMPlexSetUseNaturalSF(dm, PETSC_TRUE) before DMPlexDistribute().

247:   Level: intermediate

249: .seealso: DMPlexDistribute(), DMPlexDistributeField(), DMPlexNaturalToGlobalBegin(),DMPlexGlobalToNaturalEnd()
250: @*/
251: PetscErrorCode DMPlexNaturalToGlobalBegin(DM dm, Vec nv, Vec gv)
252: {
253:   const PetscScalar *inarray;
254:   PetscScalar       *outarray;
255:   PetscErrorCode     ierr;

258:   PetscLogEventBegin(DMPLEX_NaturalToGlobalBegin,dm,0,0,0);
259:   if (dm->sfNatural) {
260:     /* We only have acces to the SF that goes from Global to Natural.
261:        Instead of inverting dm->sfNatural, we can call PetscSFReduceBegin/End with MPI_Op MPI_SUM.
262:        Here the SUM really does nothing since sfNatural is one to one, as long as gV is set to zero first. */
263:     VecZeroEntries(gv);
264:     VecGetArray(gv, &outarray);
265:     VecGetArrayRead(nv, &inarray);
266:     PetscSFReduceBegin(dm->sfNatural, MPIU_SCALAR, (PetscScalar *) inarray, outarray, MPI_SUM);
267:     VecRestoreArrayRead(nv, &inarray);
268:     VecRestoreArray(gv, &outarray);
269:   } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created.\nYou must call DMPlexSetUseNaturalSF() before DMPlexDistribute().\n");
270:   PetscLogEventEnd(DMPLEX_NaturalToGlobalBegin,dm,0,0,0);
271:   return(0);
272: }

274: /*@
275:   DMPlexNaturalToGlobalEnd - Rearranges a Vector in the natural order to the Global order.

277:   Collective on dm

279:   Input Parameters:
280: + dm - The distributed DMPlex
281: - nv - The natural Vec

283:   Output Parameters:
284: . gv - The global Vec

286:   Note: The user must call DMPlexSetUseNaturalSF(dm, PETSC_TRUE) before DMPlexDistribute().

288:   Level: intermediate

290: .seealso: DMPlexDistribute(), DMPlexDistributeField(), DMPlexNaturalToGlobalBegin(), DMPlexGlobalToNaturalBegin()
291:  @*/
292: PetscErrorCode DMPlexNaturalToGlobalEnd(DM dm, Vec nv, Vec gv)
293: {
294:   const PetscScalar *inarray;
295:   PetscScalar       *outarray;
296:   PetscErrorCode     ierr;

299:   PetscLogEventBegin(DMPLEX_NaturalToGlobalEnd,dm,0,0,0);
300:   if (dm->sfNatural) {
301:     VecGetArrayRead(nv, &inarray);
302:     VecGetArray(gv, &outarray);
303:     PetscSFReduceEnd(dm->sfNatural, MPIU_SCALAR, (PetscScalar *) inarray, outarray, MPI_SUM);
304:     VecRestoreArrayRead(nv, &inarray);
305:     VecRestoreArray(gv, &outarray);
306:   }
307:   PetscLogEventEnd(DMPLEX_NaturalToGlobalEnd,dm,0,0,0);
308:   return(0);
309: }