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, °ree, &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, °ree, &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, °ree, &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, °ree, &support);
1370: return(0);
1371: }