Actual source code: meshQuery.c

  1: #ifdef PETSC_RCS_HEADER
  2: static char vcid[] = "$Id: meshQuery.c,v 1.19 2000/10/17 13:48:57 knepley Exp $";
  3: #endif

  5: /*
  6:      Defines the interface to the mesh query functions
  7: */

 9:  #include src/mesh/meshimpl.h

 11: /*----------------------------------------------- Mesh Query Functions -----------------------------------------------*/
 12: /*@
 13:   MeshSetDimension - This function sets the dimension of the Mesh. This may only be done before a mesh is generated.

 15:   Not collective

 17:   Input Parameters:
 18: + mesh - The mesh
 19: - dim  - The mesh dimension

 21:   Level: intermediate

 23: .keywords: Mesh, dimension
 24: .seealso: MatGetDimension(), PartitionGetDimension()
 25: @*/
 26: int MeshSetDimension(Mesh mesh, int dim)
 27: {
 30:   if ((dim < 0) || (dim > 3)) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE, "Dimension %d is invalid", dim);
 31:   if (mesh->setupcalled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "Dimension cannot be set after mesh has been generated");
 32:   mesh->dim = dim;
 33:   return(0);
 34: }

 36: /*@
 37:   MeshGetDimension - This function returns the dimension of the Mesh

 39:   Not collective

 41:   Input Parameter:
 42: . mesh - The mesh

 44:   Output Parameter:
 45: . dim  - The mesh dimension

 47:   Level: intermediate

 49: .keywords: Mesh, dimension
 50: .seealso: MatSetDimension(), PartitionGetDimension()
 51: @*/
 52: int MeshGetDimension(Mesh mesh, int *dim)
 53: {
 57:   *dim = mesh->dim;
 58:   return(0);
 59: }

 61: /*@
 62:   MeshGetInfo - This function returns some information about the mesh.

 64:   Collective on Mesh

 66:   Input Parameter:
 67: . mesh - The mesh

 69:   Output Parameters:
 70: + vertices - The number of vertices
 71: . nodes    - The number of nodes
 72: . edges    - The number of edges
 73: - elements - The number of elements

 75:   Level: intermediate

 77: .keywords: mesh
 78: .seealso: MatGetCorners()
 79: @*/
 80: int MeshGetInfo(Mesh mesh, int *vertices, int *nodes, int *edges, int *elements) {
 83:   if (vertices != PETSC_NULL) *vertices = mesh->numVertices;
 84:   if (nodes    != PETSC_NULL) *nodes    = mesh->numNodes;
 85:   if (edges    != PETSC_NULL) *edges    = mesh->numEdges;
 86:   if (elements != PETSC_NULL) *elements = mesh->numFaces;
 87:   return(0);
 88: }

 90: /*@
 91:   MeshSetNumCorners - This function sets the number of nodes on each element. This may only be done before a mesh is generated.

 93:   Not collective

 95:   Input Parameters:
 96: + mesh       - The mesh
 97: - numCorners - The number of nodes on each element

 99:   Level: intermediate

101: .keywords: Mesh, dimension
102: .seealso: MatGetNumCorners()
103: @*/
104: int MeshSetNumCorners(Mesh mesh, int numCorners)
105: {
108:   if (numCorners <= 0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE, "Number of corners %d is invalid", numCorners);
109:   if (mesh->setupcalled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "Corners cannot be set after mesh has been generated");
110:   mesh->numCorners = numCorners;
111:   return(0);
112: }

114: /*@
115:   MeshGetNumCorners - This function returns the number of nodes on each element.

117:   Not collective

119:   Input Parameter:
120: . mesh       - The mesh

122:   Output Parameter:
123: . numCorners - The number of nodes on an element

125:   Level: intermediate

127: .keywords: mesh, corner
128: .seealso: MatGetInfo()
129: @*/
130: int MeshGetNumCorners(Mesh mesh, int *numCorners) {
134:   *numCorners = mesh->numCorners;
135:   return(0);
136: }

138: /*@
139:   MeshSetBoundingBox - This function sets the bounding box for the mesh. This can only be done before
140:   the mesh is generated.

142:   Not collective

144:   Input Parameters:
145: + mesh                   - The mesh
146: . startX, startY, startZ - The lower-left corner of the box
147: - endX,   endY,   endZ   - The upper-right corner of the box

149:   Level: intermediate

151: .keywords: mesh, bounding box
152: .seealso: MeshGetBoundingBox(), MeshSetLocalBoundingBox(), MeshUpdateBoundingBox()
153: @*/
154: int MeshSetBoundingBox(Mesh mesh, PetscReal startX, PetscReal startY, PetscReal startZ, PetscReal endX, PetscReal endY, PetscReal endZ)
155: {
158:   if ((startX > endX) || (startY > endY) || (startZ > endZ)) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE, "The bounding box is inverted");
159:   if (mesh->setupcalled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "Bounding box cannot be set after mesh has been generated");
160:   mesh->startX = startX;
161:   mesh->startY = startY;
162:   mesh->startZ = startZ;
163:   mesh->endX   = endX;
164:   mesh->endY   = endY;
165:   mesh->endZ   = endZ;
166:   mesh->sizeX  = endX - startX;
167:   mesh->sizeY  = endY - startY;
168:   mesh->sizeZ  = endZ - startZ;
169:   return(0);
170: }

172: /*@
173:   MeshGetBoundingBox - This function returns the bounding box for the mesh

175:   Not collective

177:   Input Parameter:
178: . mesh - The mesh

180:   Output Parameters:
181: + startX, startY, startZ - The lower-left corner of the box
182: - endX,   endY,   endZ   - The upper-right corner of the box

184:   Level: intermediate

186: .keywords: mesh, bounding box
187: .seealso: MeshSetBoundingBox(), MeshGetLocalBoundingBox(), MeshUpdateBoundingBox()
188: @*/
189: int MeshGetBoundingBox(Mesh mesh, PetscReal *startX, PetscReal *startY, PetscReal *startZ, PetscReal *endX, PetscReal *endY, PetscReal *endZ)
190: {
193:   if (startX != PETSC_NULL) {
195:     *startX = mesh->startX;
196:   }
197:   if (startY != PETSC_NULL) {
199:     *startY = mesh->startY;
200:   }
201:   if (startZ != PETSC_NULL) {
203:     *startZ = mesh->startZ;
204:   }
205:   if (endX   != PETSC_NULL) {
207:     *endX   = mesh->endX;
208:   }
209:   if (endY   != PETSC_NULL) {
211:     *endY   = mesh->endY;
212:   }
213:   if (endZ   != PETSC_NULL) {
215:     *endZ   = mesh->endZ;
216:   }
217:   return(0);
218: }

220: /*@
221:   MeshSetLocalBoundingBox - This function sets the local bounding box for the mesh. This can only be done before
222:   the mesh is generated. The local box is the smallest rectangle enclosing the portion of the mesh allocated to
223:   this processor.

225:   Not collective

227:   Input Parameters:
228: + mesh                   - The mesh
229: . startX, startY, startZ - The lower-left corner of the local box
230: - endX,   endY,   endZ   - The upper-right corner of the local box

232:   Level: intermediate

234: .keywords: mesh, bounding box, local
235: .seealso: MeshGetLocalBoundingBox(), MeshSetBoundingBox(), MeshUpdateBoundingBox()
236: @*/
237: int MeshSetLocalBoundingBox(Mesh mesh, PetscReal startX, PetscReal startY, PetscReal startZ, PetscReal endX, PetscReal endY, PetscReal endZ)
238: {
241:   if ((startX > endX) || (startY > endY) || (startZ > endZ)) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE, "The bounding box is inverted");
242:   if (mesh->setupcalled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "Bounding box cannot be set after mesh has been generated");
243:   mesh->locStartX = startX;
244:   mesh->locStartY = startY;
245:   mesh->locStartZ = startZ;
246:   mesh->locEndX   = endX;
247:   mesh->locEndY   = endY;
248:   mesh->locEndZ   = endZ;
249:   mesh->locSizeX  = mesh->locEndX - mesh->locStartX;
250:   mesh->locSizeY  = mesh->locEndY - mesh->locStartY;
251:   mesh->locSizeZ  = mesh->locEndZ - mesh->locStartZ;
252:   return(0);
253: }

255: /*@
256:   MeshGetLocalBoundingBox - This function returns the local bounding box for the mesh. The local box is the smallest
257:   rectangle enclosing the portion of the mesh allocated to this processor.

259:   Not collective

261:   Input Parameter:
262: . mesh - The mesh

264:   Output Parameters:
265: + startX, startY, startZ - The lower-left corner of the local box
266: - endX,   endY,   endZ   - The upper-right corner of the local box

268:   Level: intermediate

270: .keywords: mesh, bounding box, local
271: .seealso: MeshSetLocalBoundingBox(), MeshGetBoundingBox(), MeshUpdateBoundingBox()
272: @*/
273: int MeshGetLocalBoundingBox(Mesh mesh, PetscReal *startX, PetscReal *startY, PetscReal *startZ, PetscReal *endX, PetscReal *endY, PetscReal *endZ)
274: {
277:   if (startX != PETSC_NULL) {
279:     *startX = mesh->locStartX;
280:   }
281:   if (startY != PETSC_NULL) {
283:     *startY = mesh->locStartY;
284:   }
285:   if (startZ != PETSC_NULL) {
287:     *startZ = mesh->locStartZ;
288:   }
289:   if (endX   != PETSC_NULL) {
291:     *endX   = mesh->locEndX;
292:   }
293:   if (endY   != PETSC_NULL) {
295:     *endY   = mesh->locEndY;
296:   }
297:   if (endZ   != PETSC_NULL) {
299:     *endZ   = mesh->locEndZ;
300:   }
301:   return(0);
302: }

304: /*@
305:   MeshUpdateBoundingBox - This function updates the bounding box for the mesh based upon the current geometry.

307:   Not collective

309:   Input Parameter:
310: . mesh - The mesh

312:   Level: intermediate

314: .keywords: mesh, bounding box, update
315: .seealso: MeshSetBoundingBox(), MeshGetBoundingBox()
316: @*/
317: int MeshUpdateBoundingBox(Mesh mesh)
318: {
319:   MPI_Comm   comm;
320:   PetscTruth isPeriodic, isSetup;
321:   PetscReal  locStartX, locStartY, locStartZ;
322:   PetscReal  locEndX,   locEndY,   locEndZ;
323:   PetscReal  startX, startY, startZ;
324:   PetscReal  endX,   endY,   endZ;
325:   int        ierr;

329:   PetscObjectGetComm((PetscObject) mesh, &comm);
330:   MeshIsPeriodic(mesh, &isPeriodic);
331:   if (isPeriodic == PETSC_TRUE) return(0);
332:   /* Calculate the local bounding box */
333:   (*mesh->ops->updateboundingbox)(mesh);
334:   /* Calculate global bounding box */
335:   MeshGetLocalBoundingBox(mesh, &locStartX, &locStartY, &locStartZ, &locEndX, &locEndY, &locEndZ);
336:   MPI_Allreduce(&locStartX, &startX, 1, MPIU_REAL, MPI_MIN, comm);
337:   MPI_Allreduce(&locEndX,   &endX,   1, MPIU_REAL, MPI_MAX, comm);
338:   MPI_Allreduce(&locStartY, &startY, 1, MPIU_REAL, MPI_MIN, comm);
339:   MPI_Allreduce(&locEndY,   &endY,   1, MPIU_REAL, MPI_MAX, comm);
340:   MPI_Allreduce(&locStartZ, &startZ, 1, MPIU_REAL, MPI_MIN, comm);
341:   MPI_Allreduce(&locEndZ,   &endZ,   1, MPIU_REAL, MPI_MAX, comm);
342:   /* Pretend that the mesh is not setup */
343:   isSetup           = mesh->setupcalled;
344:   mesh->setupcalled = PETSC_FALSE;
345:   MeshSetBoundingBox(mesh, startX, startY, startZ, endX, endY, endZ);
346:   mesh->setupcalled = isSetup;
347:   return(0);
348: }

350: /*@
351:   MeshGetPartition - Returns the Partition object for this Mesh.

353:   Not collective

355:   Input Parameter:
356: . mesh - The mesh

358:   Output Parameter:
359: . part - The partition

361:   Level: intermediate

363: .keywords: Mesh, Partition, get
364: .seealso: PartitionGetMesh()
365: @*/
366: int MeshGetPartition(Mesh mesh, Partition *part)
367: {
371:   *part = mesh->part;
372:   return(0);
373: }
374: /*@
375:   MeshSetMovement - This function sets the dimension of the Mesh. This may only be done before a mesh is generated.

377:   Not collective

379:   Input Parameters:
380: + mesh - The mesh
381: - dim  - The mesh dimension

383:   Level: intermediate

385: .keywords: Mesh, dimension
386: .seealso: MeshGetMovement(), MeshGetMover()
387: @*/
388: int MeshSetMovement(Mesh mesh, PetscTruth isMoving)
389: {
392:   mesh->isMoving = isMoving;
393:   return(0);
394: }

396: /*@
397:   MeshGetMovement - This function determines whether the Mesh is moving.

399:   Not collective

401:   Input Parameter:
402: . mesh     - The mesh

404:   Output Parameter:
405: . isMoving - The flag for mesh movement

407:   Level: intermediate

409: .keywords: Mesh, movement
410: .seealso: MeshSetMovement(), MeshGetMover()
411: @*/
412: int MeshGetMovement(Mesh mesh, PetscTruth *isMoving)
413: {
417:   *isMoving = mesh->isMoving;
418:   return(0);
419: }

421: /*@
422:   MeshGetMaxDegree - This function returns the maximum degree of any node in the mesh.

424:   Not collective

426:   Input Parameter:
427: . mesh      - The mesh

429:   Output Parameter:
430: . maxDegree - The maximum degree of any node

432:   Level: intermediate

434: .keywords: Mesh, degree
435: .seealso: MeshSetFromOptions()
436: @*/
437: int MeshGetMaxDegree(Mesh mesh, int *maxDegree)
438: {
442:   *maxDegree = mesh->maxDegree;
443:   return(0);
444: }

446: /*------------------------------------------- Mesh Boundary Query Functions ------------------------------------------*/
447: /*@
448:   MeshGetNumBoundaries - Returns the number of boundaries in the mesh.

450:   Not collective

452:   Input Parameter:
453: . mesh  - The mesh

455:   Output Parameter:
456: . numBd - The number boundaries

458:   Level: intermediate

460: .keywords: mesh, boundary
461: .seealso: MeshGetBoundaryStart(), MeshGetBoundarySize()
462: @*/
463: int MeshGetNumBoundaries(Mesh mesh, int *numBd) {
467:   *numBd = mesh->numBd;
468:   return(0);
469: }

471: /*@
472:   MeshGetBoundarySize - Returns the number of nodes on the specified boundary.

474:   Not collective

476:   Input Parameters:
477: + mesh     - The mesh
478: - boundary - The boundary marker

480:   Output Parameter:
481: . size     - The number of nodes on the boundary

483:   Level: intermediate

485: .keywords: mesh, boundary
486: .seealso: MeshGetBoundaryStart()
487: @*/
488: int MeshGetBoundarySize(Mesh mesh, int boundary, int *size)
489: {

495:   (*mesh->ops->getboundarysize)(mesh, boundary, size);
496:   return(0);
497: }

499: /*@
500:   MeshGetBoundaryIndex - Returns the index of the specified boundary.

502:   Not collective

504:   Input Parameters:
505: + mesh     - The mesh
506: - boundary - The boundary marker

508:   Output Parameter:
509: . index - The index of the boundary

511:   Level: intermediate

513: .keywords: mesh, boundary
514: .seealso: MeshGetBoundarySize()
515: @*/
516: int MeshGetBoundaryIndex(Mesh mesh, int boundary, int *index)
517: {

523:   (*mesh->ops->getboundaryindex)(mesh, boundary, index);
524:   return(0);
525: }

527: /*@
528:   MeshGetBoundaryStart - Retrieves the canonical node number of the first node
529:   on the specified boundary.

531:   Not collective

533:   Input Parameters:
534: + mesh     - The mesh
535: . boundary - The boundary marker
536: - ghost    - Flag for including ghost nodes

538:   Output Parameter:
539: . node     - The canonical node number

541:   Note:
542: $ This is typically used as an iteration construct with MeshGetBoundaryNext(),
543: $ for example:
544: $
545: $ MeshGetBoundaryStart(mesh, OUTER_BD, &node, PETSC_FALSE);
546: $ while (node >= 0) {
547: $   PetscPrintf(PETSC_COMM_SELF, "I have boundary node %dn", node);
548: $   MeshGetBoundaryNext(mesh, OUTER_BD, &node, PETSC_FALSE);
549: $ }

551:   Level: intermediate

553: .keywords: mesh, boundary, iterator
554: .seealso: MeshGetBoundaryNext()
555: @*/
556: int MeshGetBoundaryStart(Mesh mesh, int boundary, PetscTruth ghost, int *node)
557: {

563:   (*mesh->ops->getboundarystart)(mesh, boundary, ghost, node);
564:   return(0);
565: }

567: /*@
568:   MeshGetBoundaryNext - Retrieves the canonical node number of the next node
569:   on the specified boundary, with -1 indicating boundary termination.

571:   Not collective

573:   Input Parameters:
574: + mesh     - The mesh
575: . boundary - The boundary marker
576: - ghost    - Flag for including ghost nodes

578:   Output Parameter:
579: . node     - The canonical node number

581:   Note:
582: $ This is typically used as an iteration construct with MeshGetBoundaryStart(),
583: $ for example:
584: $
585: $ MeshGetBoundaryStart(mesh, OUTER_BD, &node, PETSC_FALSE);
586: $ while (node >= 0) {
587: $   PetscPrintf(PETSC_COMM_SELF, "I have boundary node %dn", node);
588: $   MeshGetBoundaryNext(mesh, OUTER_BD, &node, PETSC_FALSE);
589: $ }

591:   Also, this only returns nodes which lie in the given domain, thus the above
592:   loop would run in parallel on all processors, returning different nodes on each.

594:   Level: intermediate

596: .keywords: mesh, boundary, iterator
597: .seealso: MeshGetBoundaryStart()
598: @*/
599: int MeshGetBoundaryNext(Mesh mesh, int boundary, PetscTruth ghost, int *node)
600: {

606:   (*mesh->ops->getboundarynext)(mesh, boundary, ghost, node);
607:   return(0);
608: }

610: /*@
611:   MeshGetActiveBoundary - Retrieves the boundary marker for the boundary
612:   last iterated over, or -1 if no iteration has taken place.

614:   Not collective

616:   Input Parameter:
617: . mesh     - The mesh

619:   Output Parameter:
620: . boundary - The boundary marker

622:   Level: advanced

624: .keywords: grid, boundary, iterator
625: .seealso: GridGetBoundaryNext(), MeshGetBoundaryStart()
626: @*/
627: int MeshGetActiveBoundary(Mesh mesh, int *boundary)
628: {

634:   (*mesh->ops->getactiveboundary)(mesh, boundary);
635:   return(0);
636: }

638: /*--------------------------------------------- Mesh Node Query Functions --------------------------------------------*/
639: /*@
640:   MeshGetNodeBoundary - Returns the boundary on which the node lies, or 0 for interior nodes.

642:   Not collective

644:   Input Parameters:
645: + mesh  - The mesh
646: - node  - The node

648:   Output Parameter:
649: . bd    - The boundary

651:   Level: intermediate

653: .keywords: mesh, boundary, node
654: .seealso: MeshGetBoundarySize()
655: @*/
656: int MeshGetNodeBoundary(Mesh mesh, int node, int *bd)
657: {

663:   (*mesh->ops->getnodeboundary)(mesh, node, bd);
664:   return(0);
665: }

667: /*@
668:   MeshNodeIsVertex - This function determines whether or not a node is a vertex.

670:   Not collective

672:   Input Parameters:
673: + mesh     - The mesh
674: - node     - The node

676:   Output Parameter:
677: . isVertex - The flag for a vertex

679:   Note:
680:   Vertices are nodes which are connected to edges.

682:   Level: intermediate

684: .keywords: mesh, node, vertex
685: .seealso: MeshGetNodeCoords()
686: @*/
687: int MeshNodeIsVertex(Mesh mesh, int node, PetscTruth *isVertex)
688: {

694:   (*mesh->ops->nodeisvertex)(mesh, node, isVertex);
695:   return(0);
696: }

698: /*@
699:   MeshGetNodeCoords - Retrieves the coordinates of a selected node

701:   Input Parameters:
702: + mesh  - The mesh
703: - node  - The local node number

705:   Output Parameters:
706: . x,y,z - The coordinates

708:   Level: intermediate

710: .keywords: mesh, hole, coordinates
711: .seealso: MeshGetBoundaryStart()
712: @*/
713: int MeshGetNodeCoords(Mesh mesh, int node, double *x, double *y, double *z)
714: {

722:   (*mesh->ops->getnodecoords)(mesh, node, x, y, z);
723:   return(0);
724: }

726: /*@
727:   MeshSetNodeCoords - Sets the coordinates of a selected node

729:   Collective on Mesh

731:   Input Parameters:
732: + mesh  - The mesh
733: . node  - The local node number
734: - x,y,z - The coordinates

736:   Level: intermediate

738: .keywords: mesh, node, coordinates
739: .seealso: MeshGetBoundaryStart()
740: @*/
741: int MeshSetNodeCoords(Mesh mesh, int node, double x, double y, double z)
742: {

747:   (*mesh->ops->setnodecoords)(mesh, node, x, y, z);
748:   return(0);
749: }

751: /*@
752:   MeshGetNodeCoordsSaved - Retrieves the coordinates of a selected node
753:   from those saved with MeshSaveMesh().

755:   Input Parameters:
756: + mesh  - The mesh
757: - node  - The canonical node number

759:   Output Parameters:
760: . x,y,z - The coordinates

762:   Level: intermediate

764: .keywords: mesh, node, coordinates
765: .seealso: MeshGetNodeCoords(), MeshSaveMesh()
766: @*/
767: int MeshGetNodeCoordsSaved(Mesh mesh, int node, double *x, double *y, double *z)
768: {

776:   (*mesh->ops->getnodecoordssaved)(mesh, node, x, y, z);
777:   return(0);
778: }

780: /*@
781:   MeshGetNearestNode - This function returns the node nearest to
782:   the given point, or -1 if the closest node is not contained in
783:   the local mesh.

785:   Not collective

787:   Input Parameters:
788: + mesh    - The mesh
789: . x,y,z   - The node coordinates
790: - outside - A flag to allow points outside the domain

792:   Output Parameter:
793: . node    - The nearest node

795:   Note:
796:   The outside flag allows points outside the domain to be tested. If this flag
797:   is PETSC_FALSE, and (x,y,z) does not lie in the global domain, then an error
798:   will result.

800:   Level: beginner

802: .keywords: mesh, node, point location
803: .seealso MeshLocatePoint()
804: @*/
805: int MeshGetNearestNode(Mesh mesh, double x, double y, double z, PetscTruth outside, int *node)
806: {

812:   (*mesh->ops->nearestnode)(mesh, x, y, z, outside, node);
813:   return(0);
814: }

816: /*@
817:   MeshGetNearestBdNode - This function returns the boundary node nearest to
818:   the given point, or -1 if the closest node is not contained in the local mesh.

820:   Not collective

822:   Input Parameters:
823: + mesh  - The mesh
824: - x,y,z - The node coordinates

826:   Output Parameter:
827: . node  - The nearest boundary node

829:   Level: beginner

831: .keywords: mesh, node, point location
832: .seealso MeshGetNearestNode(), MeshLocatePoint()
833: @*/
834: int MeshGetNearestBdNode(Mesh mesh, double x, double y, double z, int *node)
835: {
836:   Partition p;
837:   double    minDist = PETSC_MAX;
838:   double    dist, nx, ny, nz;
839:   int       minNode, globalMinNode, allMinNode;
840:   int       numCorners, startNode, endNode;
841:   int       elem, corner, nearNode, bd;
842:   int       ierr;

847:   MeshGetNumCorners(mesh, &numCorners);
848:   MeshGetPartition(mesh, &p);
849:   PartitionGetStartNode(p, &startNode);
850:   PartitionGetEndNode(p, &endNode);
851:   MeshLocatePoint(mesh, x, y, z, &elem);
852:   if (elem >= 0) {
853:     /* Find first boundary node */
854:     for(corner = 0; corner < numCorners; corner++) {
855:       MeshGetNodeFromElement(mesh, elem, corner, &minNode);
856:       MeshGetNodeBoundary(mesh, minNode, &bd);
857:       if (bd != 0) {
858:         MeshGetNodeCoords(mesh, minNode, &nx, &ny, &nz);
859:         minDist = PetscSqr(MeshPeriodicDiffX(mesh, nx - x)) + PetscSqr(MeshPeriodicDiffY(mesh, ny - y));
860:         break;
861:       }
862:     }
863:     if (corner == numCorners) SETERRQ1(PETSC_ERR_ARG_WRONG, "Element %d has no node on a boundary", elem);
864:     /* Find closest node with field defined */
865:     for(corner = 1; corner < numCorners; corner++) {
866:       MeshGetNodeFromElement(mesh, elem, corner, &nearNode);
867:       MeshGetNodeCoords(mesh, nearNode, &nx, &ny, &nz);
868:       MeshGetNodeBoundary(mesh, nearNode, &bd);
869:       dist = PetscSqr(nx - x) + PetscSqr(ny - y);
870:       if ((bd != 0) && (dist < minDist)) {
871:         minDist = dist;
872:         minNode = nearNode;
873:       }
874:     }
875:     PartitionLocalToGlobalNodeIndex(p, minNode, &globalMinNode);
876:   } else {
877:     minNode       = -1;
878:     globalMinNode = -1;
879:   }

881:   /* The minimum node might still be a ghost node */
882:   MPI_Allreduce(&globalMinNode, &allMinNode, 1, MPI_INT, MPI_MAX, mesh->comm);
883:   if ((allMinNode >= startNode) && (allMinNode < endNode)) {
884:     *node = allMinNode - startNode;
885:   } else {
886:     *node = -1;
887:   }
888:   if (allMinNode < 0) PetscFunctionReturn(1);
889:   return(0);
890: }

892: /*@
893:   MeshGetNodeSupport - This function get the canonical element numbers of all elements
894:   within the support of a given basis function. A call to MeshRestoreNodeSupport() must
895:   be made before another call to this function.

897:   Not collective

899:   Input Parameters:
900: + mesh    - The mesh
901: . node    - The node containing the basis function
902: - elem    - An element containing the node, -1 for a search

904:   Output Parameters:
905: + degree  - The degree of the node
906: - support - A list of the elements in the support

908:   Note:
909:   This function currently only returns the elements containing
910:   any given node, so some basis functions will have a wider
911:   support than this definition.

913:   Level: intermediate

915: .keywords: mesh, support
916: .seealso: MeshRestoreNodeSupport()
917: @*/
918: int MeshGetNodeSupport(Mesh mesh, int node, int elem, int *degree, int **support)
919: {

926:   if (mesh->supportTaken == PETSC_TRUE) {
927:     SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "Missing call to MeshRestoreNodeSupport()");
928:   }
929:   mesh->supportTaken = PETSC_TRUE;
930:   (*mesh->ops->getnodesupport)(mesh, node, elem, degree, support);
931:   return(0);
932: }

934: /*@
935:   MeshRestoreNodeSupport - This function returns the support array from MeshGetNodeSupport().

937:   Not collective

939:   Input Parameters:
940: + mesh    - The mesh
941: . node    - The node containing the basis function
942: . elem    - An element containing the node, -1 for a search
943: . degree  - The degree pf the node
944: - support - A list of the elements in the support

946:   Level: intermediate

948: .keywords: mesh, support
949: .seealso: MeshGetNodeSupport()
950: @*/
951: int MeshRestoreNodeSupport(Mesh mesh, int node, int elem, int *degree, int **support)
952: {
955:   if (*support != mesh->support) {
956:     SETERRQ(PETSC_ERR_ARG_WRONG, "Invalid support argument");
957:   }
958:   mesh->supportTaken = PETSC_FALSE;
959:   return(0);
960: }

962: /*@
963:   MeshGetNodeOrdering - This function gets the AO which was used to reorder the mesh nodes
964:   before partitioning. This is sometimes used to bandwdith reduce the mesh graph.

966:   Not collective

968:   Input Parameter:
969: . mesh  - The mesh

971:   Output Parameter:
972: . order - The node ordering, or PETSC_NULL if none exists

974:   Level: intermediate

976: .keywords: Mesh, node, ordering, AO
977: .seealso: PartitionGetNodeOrdering()
978: @*/
979: int MeshGetNodeOrdering(Mesh mesh, AO *order)
980: {
984:   *order = mesh->nodeOrdering;
985:   return(0);
986: }

988: /*------------------------------------------- Mesh Element Query Functions -------------------------------------------*/
989: /*@
990:   MeshGetElementNeighbor - This function retrieves the local element number of the element, or neighbor, opposing a
991:   given corner.

993:   Not collective

995:   Input Parameters:
996: + mesh     - The mesh
997: . elem     - The element
998: - corner   - The corner, or element node number

1000:   Output Parameter:
1001: . neighbor - The neighbor opposing corner

1003:   Level: intermediate

1005: .keywords: mesh, element, neighbor
1006: .seealso: MeshGetNodeCoords()
1007: @*/
1008: int MeshGetElementNeighbor(Mesh mesh, int elem, int corner, int *neighbor)
1009: {

1015:   (*mesh->ops->getelemneighbor)(mesh, elem, corner, neighbor);
1016:   return(0);
1017: }

1019: /*@
1020:   MeshLocatePoint - This function returns the element containing
1021:   the given point, or -1 if it is not contained in the local mesh.

1023:   Not collective

1025:   Input Parameters:
1026: + mesh           - The mesh
1027: - x,y,z          - The node coordinates

1029:   Output Parameter:
1030: . containingElem - An element containing the node, -1 for failure

1032:   Level: beginner

1034: .keywords: mesh, point location
1035: .seealso MeshGetNearestNode(), MeshGetNodeSupport()
1036: @*/
1037: int MeshLocatePoint(Mesh mesh, double x, double y, double z, int *containingElem)
1038: {

1044:   PetscLogEventBegin(MESH_LocatePoint, mesh, 0, 0, 0);
1045:   (*mesh->ops->locatepoint)(mesh, x, y, z, containingElem);
1046:   PetscLogEventEnd(MESH_LocatePoint, mesh, 0, 0, 0);
1047:   return(0);
1048: }

1050: /*--------------------------------------------- Mesh Hole Query Functions --------------------------------------------*/
1051: /*@
1052:   MeshSetHoleCoords - Sets the coordinates of holes in the mesh

1054:   Collective on Mesh

1056:   Input Parameter:
1057: + mesh   - The mesh
1058: . num    - The number of holes
1059: - coords - The coordinates

1061:   Level: advanced

1063: .keywords: mesh, hole, coordinates
1064: .seealso: MeshGetBoundaryStart()
1065: @*/
1066: int MeshSetHoleCoords(Mesh mesh, int num, Vec coords)
1067: {
1068:   int          dim = mesh->dim;
1069:   PetscScalar *array;
1070:   int          size, vecDim;
1071:   int          h, d;
1072:   int          ierr;

1077:   if (num != mesh->numHoles) {
1078:     mesh->numHoles = num;
1079:     if (mesh->holes != PETSC_NULL) {
1080:       PetscFree(mesh->holes);
1081:     }
1082:     if (mesh->numHoles > 0) {
1083:       PetscMalloc(mesh->numHoles*dim * sizeof(double), &mesh->holes);
1084:     } else {
1085:       mesh->holes = PETSC_NULL;
1086:     }
1087:   }
1088:   VecGetArray(coords, &array);
1089:   VecGetLocalSize(coords, &size);
1090:   if (size == mesh->numHoles*dim) {
1091:     PetscMemcpy(mesh->holes, array, mesh->numHoles*dim * sizeof(double));
1092:   } else if ((size > mesh->numHoles*dim) && (size%mesh->numHoles == 0)) {
1093:     vecDim = (int) (size/mesh->numHoles);
1094:     for(h = 0; h < mesh->numHoles; h++) {
1095:       for(d = 0; d < dim; d++) {
1096:         mesh->holes[h*dim+d] = PetscRealPart(array[h*vecDim+d]);
1097:       }
1098:     }
1099:   } else {
1100:     SETERRQ(PETSC_ERR_ARG_WRONG, "Invalid vector of hole coordinates");
1101:   }
1102:   VecRestoreArray(coords, &array);
1103:   return(0);
1104: }

1106: /*------------------------------------------ Mesh Embedding Query Functions ------------------------------------------*/
1107: /*@
1108:   MeshGetElementFromNode - This function retrieves a local element number from the local
1109:   node number. Notice that this could be nondeterministic.

1111:   Not collective

1113:   Input Parameters:
1114: + mesh - The mesh
1115: - node - The number

1117:   Output Parameter:
1118: . elem - The element

1120:   Level: intermediate

1122: .keywords: mesh, node, element
1123: .seealso: MeshGetNodeFromElement()
1124: @*/
1125: int MeshGetElementFromNode(Mesh mesh, int node, int *elem)
1126: {
1127:   Partition part;
1128:   int       numElements, numCorners;
1129:   int       e, c, n;
1130:   int       ierr;

1135:   MeshGetPartition(mesh, &part);
1136:   PartitionGetNumElements(part, &numElements);
1137:   MeshGetNumCorners(mesh, &numCorners);
1138:   for(e = 0; e < numElements; e++) {
1139:     for(c = 0; c < numCorners; c++){
1140:       MeshGetNodeFromElement(mesh, e, c, &n);
1141:       if (n == node) {
1142:         *elem = e;
1143:         return(0);
1144:       }
1145:     }
1146:   }
1147:   PetscFunctionReturn(-1);
1148: }

1150: /*@
1151:   MeshGetBdElementFromEdge - This function retrieves the local element number of a
1152:   boundary element from the local edge number.

1154:   Not collective

1156:   Input Parameters:
1157: + mesh - The mesh
1158: - edge - The edge

1160:   Output Parameter:
1161: . elem - The element along the boundary

1163:   Level: intermediate

1165: .keywords: mesh, element, edge
1166: .seealso: MeshGetNodeFromElement(), MeshGetNodeCoords()
1167: @*/
1168: int MeshGetBdElementFromEdge(Mesh mesh, int edge, int *elem)
1169: {
1170: #if 0
1171:   int  neighbor;
1172: #endif
1173:   int  degree;
1174:   int *support;
1175:   int  startNode,   endNode;
1176:   int  startCorner, endCorner, numCorners;
1177:   int  sElem, corner, node;
1178:   int  ierr;

1182:   /* This should be a default function, which is only used if the implementation
1183:      does not have an optimized implementation
1184:   */
1185:   /* Search for element containing edge */
1186:   MeshGetNumCorners(mesh, &numCorners);
1187:   MeshGetNodeFromEdge(mesh, edge, 0, &startNode);
1188:   MeshGetNodeFromEdge(mesh, edge, 1, &endNode);
1189:   /* Loop over nodes on each element in the support of the node */
1190:   MeshGetNodeSupport(mesh, startNode, 0, &degree, &support);
1191:   for(sElem = 0; sElem < degree; sElem++) {
1192:     for(corner = 0, startCorner = -1, endCorner = -1; corner < numCorners; corner++) {
1193:       MeshGetNodeFromElement(mesh, support[sElem], corner, &node);
1194:       if (node == startNode) {
1195:         startCorner = corner;
1196:       } else if (node == endNode) {
1197:         endCorner   = corner;
1198:       }
1199:     }
1200:     if ((startCorner >= 0) && (endCorner >= 0)) break;
1201:   }
1202:   if (sElem == degree) SETERRQ1(PETSC_ERR_PLIB, "Edge %d not found in element list", edge);
1203:   *elem = support[sElem];
1204:   MeshRestoreNodeSupport(mesh, startNode, 0, &degree, &support);
1205: #if 0
1206:   MeshGetNeighbor(mesh, *elem, ((startCorner+endCorner)*2)%3, &neighbor);
1207:   if (neighbor != -1)
1208:     SETERRQ2(PETSC_ERR_ARG_WRONG, "Edge is not on a boundary since elem %d has neighbor %d", *elem, neighbor);
1209: #endif
1210:   return(0);
1211: }

1213: /*@
1214:   MeshGetNodeFromElement - This function retrieves the local node number from the local
1215:   element number and the corner.

1217:   Not collective

1219:   Input Parameters:
1220: + mesh   - The mesh
1221: . elem   - The element
1222: - corner - The corner, or element node number

1224:   Output Parameter:
1225: . node   - The local node number

1227:   Level: intermediate

1229: .keywords: mesh, node
1230: .seealso: MeshGetNodeCoords()
1231: @*/
1232: int MeshGetNodeFromElement(Mesh mesh, int elem, int corner, int *node)
1233: {
1234:   int numCorners         = mesh->numCorners;
1235:   int numOverlapElements = mesh->numFaces;

1241:   if (mesh->part != PETSC_NULL) {
1242:     ierr  = PartitionGetNumOverlapElements(mesh->part, &numOverlapElements);
1243:   }
1244:   if ((elem < 0) || (elem >= numOverlapElements)) {
1245:     SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE, "Invalid node %d should be in [0,%d)", elem, numOverlapElements);
1246:   }
1247:   if ((corner < 0) || (corner >= numCorners)) {
1248:     SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE, "Invalid corner %d should be in [0,%d)", elem, numCorners);
1249:   }
1250:   (*mesh->ops->getnodefromelement)(mesh, elem, corner, node);
1251:   return(0);
1252: }

1254: /*@
1255:   MeshGetNodeFromEdge - This function retrieves the local node number from the local
1256:   edge number and the corner.

1258:   Not collective

1260:   Input Parameters:
1261: + mesh   - The mesh
1262: . edge   - The edge
1263: - corner - The corner, or edge node number (0 or 1)

1265:   Output Parameter:
1266: . node   - The local node number

1268:   Level: intermediate

1270: .keywords: mesh, node, edge
1271: .seealso: MeshGetNodeCoords()
1272: @*/
1273: int MeshGetNodeFromEdge(Mesh mesh, int edge, int corner, int *node)
1274: {
1275:   int numOverlapEdges = mesh->numEdges;

1281:   if ((corner < 0) || (corner >= 2)) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE, "Invalid corner %d should be in [0,2)", edge);
1282:   if (mesh->part != PETSC_NULL) {
1283:     ierr  = PartitionGetNumOverlapEdges(mesh->part, &numOverlapEdges);
1284:   }
1285:   if ((edge < 0) || (edge >= numOverlapEdges)) {
1286:     SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE, "Invalid edge %d should be in [0,%d)", edge, numOverlapEdges);
1287:   }
1288:   (*mesh->ops->getnodefromedge)(mesh, edge, corner, node);
1289:   return(0);
1290: }

1292: /*@
1293:   MeshGetMidnodeFromEdge - This function retrieves the local node number of the midnode from the local edge number.

1295:   Not collective

1297:   Input Parameters:
1298: + mesh    - The mesh
1299: - edge    - The edge

1301:   Output Parameter:
1302: . midnode - The local node number of the midnode

1304:   Level: intermediate

1306: .keywords: mesh, midnode, edge
1307: .seealso: MeshGetNodeFromElement(), MeshGetNodeCoords()
1308: @*/
1309: int MeshGetMidnodeFromEdge(Mesh mesh, int edge, int *midnode)
1310: {
1311:   int  degree;
1312:   int *support;
1313:   int  startNode,   endNode;
1314:   int  numCorners;
1315:   int  startCorner = -1;
1316:   int  endCorner   = -1;
1317:   int  elem, corner, node;
1318:   int  ierr;

1322:   /* This should be a default function, which is only used if the implementation
1323:      does not have an optimized implementation
1324:   */
1325:   MeshGetNumCorners(mesh, &numCorners);
1326:   if (numCorners == 3) return(0);
1327:   if (numCorners != 6) SETERRQ1(PETSC_ERR_ARG_WRONG, "Cannot find midnode for %d corners", numCorners);

1329:   /* Search for midnode on edge */
1330:   MeshGetNodeFromEdge(mesh, edge, 0, &startNode);
1331:   MeshGetNodeFromEdge(mesh, edge, 1, &endNode);
1332:   /* Loop over nodes on each element in the support of the node */
1333:   MeshGetNodeSupport(mesh, startNode, 0, &degree, &support);
1334:   for(elem = 0; elem < degree; elem++) {
1335:     for(corner = 0, startCorner = -1, endCorner = -1; corner < numCorners; corner++) {
1336:       MeshGetNodeFromElement(mesh, support[elem], corner, &node);
1337:       if (node == startNode) {
1338:         startCorner = corner;
1339:       } else if (node == endNode) {
1340:         endCorner   = corner;
1341:       }
1342:     }
1343:     if ((startCorner >= 0) && (endCorner >= 0)) break;
1344:   }
1345:   if (elem == degree) {
1346:     if (startCorner < 0) SETERRQ1(PETSC_ERR_PLIB, "Invalid support of node %d did not contain node", startNode);
1347:     if (endCorner   < 0) {
1348:       for(elem = 0; elem < mesh->numFaces; elem++) {
1349:         for(corner = 0, startCorner = -1, endCorner = -1; corner < numCorners; corner++) {
1350:           MeshGetNodeFromElement(mesh, elem, corner, &node);
1351:           if (node == startNode) {
1352:             startCorner = corner;
1353:           } else if (node == endNode) {
1354:             endCorner   = corner;
1355:           }
1356:         }
1357:         if ((startCorner >= 0) && (endCorner >= 0)) break;
1358:       }
1359:       if (elem == mesh->numFaces) {
1360:         SETERRQ3(PETSC_ERR_PLIB, "Edge %d (%d,%d) not found in element list", edge, startNode, endNode);
1361:       } else {
1362:         SETERRQ5(PETSC_ERR_PLIB, "Edge %d (%d,%d) found in element %d not in support list of node %d",
1363:                  edge, startNode, endNode, elem, startNode);
1364:       }
1365:     }
1366:   }

1368:   MeshGetNodeFromElement(mesh, support[elem], ((startCorner + endCorner)*2)%3 + 3, midnode);
1369:   MeshRestoreNodeSupport(mesh, startNode, 0, &degree, &support);
1370:   return(0);
1371: }