Actual source code: partQuery.c

  1: #ifdef PETSC_RCS_HEADER
  2: static char vcid[] = "$Id: partQuery.c,v 1.6 2000/01/31 17:37:32 knepley Exp $";
  3: #endif

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

 9:  #include src/mesh/meshimpl.h

 11: /*-------------------------------------------- Partition Query Functions ---------------------------------------------*/
 12: /*@
 13:   PartitionGetDimension - This function returns the dimension of the Partition.

 15:   Not collective

 17:   Input Parameter:
 18: . part - The partition

 20:   Output Parameter:
 21: . dim  - The partition dimension

 23:   Level: intermediate

 25: .keywords: Partition, dimension
 26: .seealso: MeshGetDimension()
 27: @*/
 28: int PartitionGetDimension(Partition part, int *dim)
 29: {
 30:   Mesh mesh;

 36:   PartitionGetMesh(part, &mesh);
 37:   MeshGetDimension(mesh, dim);
 38:   return(0);
 39: }

 41: /*@
 42:   PartitionGetMesh - Returns the Mesh object for this Partition.

 44:   Not collective

 46:   Input Parameter:
 47: . part - The partition

 49:   Output Parameter:
 50: . mesh - The mesh

 52:   Level: intermediate

 54: .keywords: Mesh, Partition, get
 55: .seealso: MeshGetPartition()
 56: @*/
 57: int PartitionGetMesh(Partition part, Mesh *mesh)
 58: {
 62:   *mesh = part->mesh;
 63:   return(0);
 64: }

 66: /*--------------------------------------------- Element Query Functions ----------------------------------------------*/
 67: /*@
 68:   PartitionGetTotalElements - Gets the number of elements in the mesh.

 70:   Not collective

 72:   Input Parameter:
 73: . part - The partition

 75:   Output Parameter:
 76: . size - The number of elements in the mesh

 78:   Level: intermediate

 80: .keywords: partition, element
 81: .seealso: PartitionGetStartElement(), PartitionGetEndElement()
 82: @*/
 83: int PartitionGetTotalElements(Partition part, int *size)
 84: {
 88:   *size = part->numElements;
 89:   return(0);
 90: }

 92: /*@
 93:   PartitionGetStartElement - Gets the first element in this domain.

 95:   Not collective

 97:   Input Parameter:
 98: . part - The partition

100:   Output Parameter:
101: . elem - The first element in this domain

103:   Level: intermediate

105: .keywords: partition, element
106: .seealso: PartitionGetEndElement(), PartitionGetNumElements()
107: @*/
108: int PartitionGetStartElement(Partition part, int *elem)
109: {
113:   *elem = part->firstElement[part->rank];
114:   return(0);
115: }

117: /*@
118:   PartitionGetEndElement - Gets the first element in the next domain.

120:   Not collective

122:   Input Parameter:
123: . part - The partition

125:   Output Parameter:
126: . elem - The first element in the next domain

128:   Level: intermediate

130: .keywords: partition, element
131: .seealso: PartitionGetStartElement(), PartitionGetNumElements()
132: @*/
133: int PartitionGetEndElement(Partition part, int *elem)
134: {
138:   *elem = part->firstElement[part->rank+1];
139:   return(0);
140: }

142: /*@
143:   PartitionGetNumElements - Gets the number of elements in this domain.

145:   Not collective

147:   Input Parameter:
148: . part - The partition

150:   Output Parameter:
151: . size - The number of elements in this domain

153:   Level: intermediate

155: .keywords: partition, element
156: .seealso: PartitionGetStartElement(), PartitionGetEndElement()
157: @*/
158: int PartitionGetNumElements(Partition part, int *size)
159: {
163:   *size = part->firstElement[part->rank+1] - part->firstElement[part->rank];
164:   return(0);
165: }

167: /*@
168:   PartitionGetNumOverlapElements - Gets the number of elements and ghost elements for this domain.

170:   Not collective

172:   Input Parameter:
173: . part - The partition

175:   Output Parameter:
176: . size - The number of elements and ghost element for this domain

178:   Level: intermediate

180: .keywords: partition, element
181: .seealso: PartitionGetStartElement(), PartitionGetEndElement()
182: @*/
183: int PartitionGetNumOverlapElements(Partition part, int *size)
184: {
188:   *size = part->numOverlapElements;
189:   return(0);
190: }

192: static int PartitionGhostElementIndex_Private(Partition p, int elem, int *gElem)
193: {
194:   int low, high, mid;

197:   /* Use bisection since the array is assumed to be sorted */
198:   low  = 0;
199:   high = p->numOverlapElements - (p->firstElement[p->rank+1] - p->firstElement[p->rank]) - 1;
200:   while (low <= high) {
201:     mid = (low + high)/2;
202:     if (elem == p->ghostElements[mid]) {
203:       *gElem = mid;
204:       return(0);
205:     } else if (elem < p->ghostElements[mid]) {
206:       high = mid - 1;
207:     } else {
208:       low  = mid + 1;
209:     }
210:   }
211:   /* We indicate elements which are not local and also not ghost by -2 */
212:   *gElem = -2;
213:   return(0);
214: }

216: /*@
217:   PartitionGlobalToLocalElementIndex - Returns the local element number
218:   corresponding to the global element number.

220:   Not collective

222:   Input Parameters:
223: + part    - The partition
224: - elem    - The canonical global element number

226:   Output Parameter:
227: . locElem - The local element number

229:   Level: intermediate

231: .keywords: partition, local, global
232: .seealso PartitionLocalToGlobalElementIndex()
233: @*/
234: int PartitionGlobalToLocalElementIndex(Partition part, int elem, int *locElem)
235: {
236:   int numLocElements;
237:   int gElem; /* The local ghost element number */

243:   numLocElements = part->firstElement[part->rank+1] - part->firstElement[part->rank];
244:   if (elem < 0) {
245:     *locElem = elem;
246:     return(0);
247:   }
248:   /* Check for ghost element */
249:   if ((elem < part->firstElement[part->rank]) || (elem >= part->firstElement[part->rank+1])) {
250:     /* Search for canonical number */
251:     PartitionGhostElementIndex_Private(part, elem, &gElem);
252:     if (gElem < 0) {
253:       *locElem = gElem;
254:     } else {
255:       *locElem = numLocElements + gElem;
256:     }
257:   } else {
258:     *locElem = elem - part->firstElement[part->rank];
259:   }
260:   return(0);
261: }

263: /*@
264:   PartitionLocalToGlobalElementIndex - Returns the global element number
265:   corresponding to the local element number.

267:   Not collective

269:   Input Parameters:
270: + part    - The partition
271: - locElem - The canonical local element number

273:   Output Parameter:
274: . elem    - The global element number

276:   Level: intermediate

278: .keywords: partition, local, global
279: .seealso: PartitionGlobalToLocalElementIndex()
280: @*/
281: int PartitionLocalToGlobalElementIndex(Partition part, int locElem, int *elem)
282: {
283:   int numLocElements;

288:   numLocElements = part->firstElement[part->rank+1] - part->firstElement[part->rank];
289:   if (locElem < 0) {
290:     *elem = locElem;
291:     return(0);
292:   } else if (locElem < numLocElements) {
293:     *elem = locElem + part->firstElement[part->rank];
294:   } else if (locElem < part->numOverlapElements) {
295:     *elem = part->ghostElements[locElem - numLocElements];
296:   } else {
297:     SETERRQ(PETSC_ERR_ARG_WRONG, "Invalid local element index (too large)");
298:   }
299:   return(0);
300: }

302: /*@
303:   PartitionGetElementOrdering - This function gets the AO which was used to reorder the mesh elements
304:   during partitioning.

306:   Not collective

308:   Input Parameter:
309: . part  - The partition

311:   Output Parameter:
312: . order - The element ordering, or PETSC_NULL if none exists

314:   Level: intermediate

316: .keywords: Partition, element, ordering, AO
317: .seealso: MeshGetNodeOrdering()
318: @*/
319: int PartitionGetElementOrdering(Partition part, AO *order)
320: {
324:   *order = part->ordering;
325:   return(0);
326: }

328: /*----------------------------------------------- Node Query Functions -----------------------------------------------*/
329: /*@
330:   PartitionGetTotalNodes - Gets the number of nodes in the mesh.

332:   Not collective

334:   Input Parameter:
335: . part - The partition

337:   Output Parameter:
338: . size - The number of nodes in the mesh

340:   Level: intermediate

342: .keywords: partition, node
343: .seealso: PartitionGetStartNode(), PartitionGetEndNode(), PartitionGetTotalElements()
344: @*/
345: int PartitionGetTotalNodes(Partition part, int *size)
346: {

352:   if (part->ops->gettotalnodes == PETSC_NULL) {
353:     SETERRQ(PETSC_ERR_SUP, "Not implemented for this partition type");
354:   }
355:   (*part->ops->gettotalnodes)(part, size);
356:   return(0);
357: }

359: /*@
360:   PartitionGetStartNode - Gets the first node in this domain.

362:   Not collective

364:   Input Parameter:
365: . part - The partition

367:   Output Parameter:
368: . node - The first node in this domain

370:   Level: intermediate

372: .keywords: partition, node
373: .seealso: PartitionGetEndNode(), PartitionGetNumNodes(), PartitionGetStartElement()
374: @*/
375: int PartitionGetStartNode(Partition part, int *node)
376: {

382:   if (part->ops->getstartnode == PETSC_NULL) {
383:     SETERRQ(PETSC_ERR_SUP, "Not implemented for this partition type");
384:   }
385:   (*part->ops->getstartnode)(part, node);
386:   return(0);
387: }

389: /*@
390:   PartitionGetEndNode - Gets the first node in the next domain.

392:   Not collective

394:   Input Parameter:
395: . part - The partition

397:   Output Parameter:
398: . node - The first node in the next domain

400:   Level: intermediate

402: .keywords: partition, node
403: .seealso: PartitionGetStartNode(), PartitionGetNumNodes(), PartitionGetEndElement()
404: @*/
405: int PartitionGetEndNode(Partition part, int *node)
406: {

412:   if (part->ops->getendnode == PETSC_NULL) {
413:     SETERRQ(PETSC_ERR_SUP, "Not implemented for this partition type");
414:   }
415:   (*part->ops->getendnode)(part, node);
416:   return(0);
417: }

419: /*@
420:   PartitionGetNumNodes - Gets the number of nodes in this domain.

422:   Not collective

424:   Input Parameter:
425: . part - The partition

427:   Output Parameter:
428: . size - The number of nodes in this domain

430:   Level: intermediate

432: .keywords: partition, node
433: .seealso: PartitionGetStartNode(), PartitionGetEndNode(), PartitionGetNumElements()
434: @*/
435: int PartitionGetNumNodes(Partition part, int *size)
436: {

442:   if (part->ops->getnumnodes == PETSC_NULL) {
443:     SETERRQ(PETSC_ERR_SUP, "Not implemented for this partition type");
444:   }
445:   (*part->ops->getnumnodes)(part, size);
446:   return(0);
447: }

449: /*@
450:   PartitionGetNumOverlapNodes - Gets the number of nodes and ghost nodes for this domain.

452:   Not collective

454:   Input Parameter:
455: . part - The partition

457:   Output Parameter:
458: . size - The number of nodes and ghost nodes this domain

460:   Level: intermediate

462: .keywords: partition, node
463: .seealso: PartitionGetStartNode(), PartitionGetEndNode(), PartitionGetNumOverlapElements()
464: @*/
465: int PartitionGetNumOverlapNodes(Partition part, int *size)
466: {

472:   if (part->ops->getnumoverlapnodes == PETSC_NULL) {
473:     SETERRQ(PETSC_ERR_SUP, "Not implemented for this partition type");
474:   }
475:   (*part->ops->getnumoverlapnodes)(part, size);
476:   return(0);
477: }

479: /*@
480:   PartitionGlobalToLocalNodeIndex - Returns the local node number
481:   corresponding to the global node number.

483:   Not collective

485:   Input Parameters:
486: + part    - The partition
487: - node    - The canonical global node number

489:   Output Parameter:
490: . locNode - The local node number

492:   Level: intermediate

494: .keywords: partition, local, global
495: .seealso: PartitionLocalToGlobalNodeIndex(), PartitionGlobalToLocalElementIndex()
496: @*/
497: int PartitionGlobalToLocalNodeIndex(Partition part, int node, int *locNode)
498: {

504:   if (part->ops->globaltolocalnodeindex == PETSC_NULL) {
505:     SETERRQ(PETSC_ERR_SUP, "Not implemented for this partition type");
506:   }
507:   (*part->ops->globaltolocalnodeindex)(part, node, locNode);
508:   return(0);
509: }

511: /*@
512:   PartitionLocalToGlobalNodeIndex - Returns the global node number
513:   corresponding to the local node number.

515:   Not collective

517:   Input Parameters:
518: + part    - The partition
519: - locNode - The canonical local node number

521:   Output Parameter:
522: . node    - The global node number

524:   Level: intermediate

526: .keywords: partition, local, global
527: .seealso: PartitionGlobalToLocalNodeIndex(), PartitionLocalToGlobalElementIndex()
528: @*/
529: int PartitionLocalToGlobalNodeIndex(Partition part, int locNode, int *node)
530: {

536:   if (part->ops->localtoglobalnodeindex == PETSC_NULL) {
537:     SETERRQ(PETSC_ERR_SUP, "Not implemented for this partition type");
538:   }
539:   (*part->ops->localtoglobalnodeindex)(part, locNode, node);
540:   return(0);
541: }

543: /*@
544:   PartitionGetNodeOrdering - This function gets the AO which was used to reorder the mesh nodes
545:   during partitioning.

547:   Not collective

549:   Input Parameter:
550: . part  - The partition

552:   Output Parameter:
553: . order - The node ordering, or PETSC_NULL if none exists

555:   Level: intermediate

557: .keywords: Partition, node, ordering, AO
558: .seealso: MeshGetNodeOrdering()
559: @*/
560: int PartitionGetNodeOrdering(Partition part, AO *order)
561: {

567:   (*part->ops->getnodeordering)(part, order);
568:   return(0);
569: }

571: /*----------------------------------------------- Face Query Functions -----------------------------------------------*/
572: /*@
573:   PartitionGetTotalFaces - Gets the number of faces in the mesh.

575:   Not collective

577:   Input Parameter:
578: . part - The partition

580:   Output Parameter:
581: . size - The number of faces in the mesh

583:   Level: intermediate

585: .keywords: partition, face
586: .seealso: PartitionGetStartFace(), PartitionGetEndFace(), PartitionGetTotalElements()
587: @*/
588: int PartitionGetTotalFaces(Partition part, int *size)
589: {

595:   if (part->ops->gettotalfaces == PETSC_NULL) {
596:     SETERRQ(PETSC_ERR_SUP, "Not implemented for this partition type");
597:   }
598:   (*part->ops->gettotalfaces)(part, size);
599:   return(0);
600: }

602: /*@
603:   PartitionGetStartFace - Gets the first face in this domain.

605:   Not collective

607:   Input Parameter:
608: . part - The partition

610:   Output Parameter:
611: . face - The first face in this domain

613:   Level: intermediate

615: .keywords: partition, face
616: .seealso: PartitionGetEndFace(), PartitionGetNumFaces(), PartitionGetStartElement()
617: @*/
618: int PartitionGetStartFace(Partition part, int *face)
619: {

625:   if (part->ops->getstartface == PETSC_NULL) {
626:     SETERRQ(PETSC_ERR_SUP, "Not implemented for this partition type");
627:   }
628:   (*part->ops->getstartface)(part, face);
629:   return(0);
630: }

632: /*@
633:   PartitionGetEndFace - Gets the first face in the next domain.

635:   Not collective

637:   Input Parameter:
638: . part - The partition

640:   Output Parameter:
641: . face - The first face in the next domain

643:   Level: intermediate

645: .keywords: partition, face
646: .seealso: PartitionGetStartFace(), PartitionGetNumFaces(), PartitionGetEndElement()
647: @*/
648: int PartitionGetEndFace(Partition part, int *face)
649: {

655:   if (part->ops->getendface == PETSC_NULL) {
656:     SETERRQ(PETSC_ERR_SUP, "Not implemented for this partition type");
657:   }
658:   (*part->ops->getendface)(part, face);
659:   return(0);
660: }

662: /*@
663:   PartitionGetNumFaces - Gets the number of faces in this domain.

665:   Not collective

667:   Input Parameter:
668: . part - The partition

670:   Output Parameter:
671: . size - The number of faces in this domain

673:   Level: intermediate

675: .keywords: partition, face
676: .seealso: PartitionGetStartFace(), PartitionGetEndFace(), PartitionGetNumElements()
677: @*/
678: int PartitionGetNumFaces(Partition part, int *size)
679: {

685:   if (part->ops->getnumfaces == PETSC_NULL) {
686:     SETERRQ(PETSC_ERR_SUP, "Not implemented for this partition type");
687:   }
688:   (*part->ops->getnumfaces)(part, size);
689:   return(0);
690: }

692: /*@
693:   PartitionGetNumOverlapFaces - Gets the number of faces and ghost faces this domain.

695:   Not collective

697:   Input Parameter:
698: . part - The partition

700:   Output Parameter:
701: . size - The number of faces and ghost faces this domain

703:   Level: intermediate

705: .keywords: partition, face
706: .seealso: PartitionGetStartFace(), PartitionGetEndFace(), PartitionGetNumOverlapElements()
707: @*/
708: int PartitionGetNumOverlapFaces(Partition part, int *size)
709: {

715:   if (part->ops->getnumoverlapfaces == PETSC_NULL) {
716:     SETERRQ(PETSC_ERR_SUP, "Not implemented for this partition type");
717:   }
718:   (*part->ops->getnumoverlapfaces)(part, size);
719:   return(0);
720: }

722: /*@
723:   PartitionGlobalToLocalFaceIndex - Returns the local face number
724:   corresponding to the global face number.

726:   Not collective

728:   Input Parameters:
729: + part    - The partition
730: - face    - The canonical global face number

732:   Output Parameter:
733: . locFace - The local face number

735:   Level: intermediate

737: .keywords: partition, local, global
738: .seealso: PartitionLocalToGlobalFaceIndex(), PartitionGlobalToLocalElementIndex()
739: @*/
740: int PartitionGlobalToLocalFaceIndex(Partition part, int face, int *locFace)
741: {

747:   if (part->ops->globaltolocalfaceindex == PETSC_NULL) {
748:     SETERRQ(PETSC_ERR_SUP, "Not implemented for this partition type");
749:   }
750:   (*part->ops->globaltolocalfaceindex)(part, face, locFace);
751:   return(0);
752: }

754: /*@
755:   PartitionLocalToGlobalFaceIndex - Returns the global face number
756:   corresponding to the local face number.

758:   Not collective

760:   Input Parameters:
761: + part    - The partition
762: - locFace - The canonical local face number

764:   Output Parameter:
765: . face    - The global face number

767:   Level: intermediate

769: .keywords: partition, local, global
770: .seealso: PartitionGlobalToLocalNodeIndex(), PartitionLocalToGlobalElementIndex()
771: @*/
772: int PartitionLocalToGlobalFaceIndex(Partition part, int locFace, int *face)
773: {

779:   if (part->ops->localtoglobalfaceindex == PETSC_NULL) {
780:     SETERRQ(PETSC_ERR_SUP, "Not implemented for this partition type");
781:   }
782:   (*part->ops->localtoglobalfaceindex)(part, locFace, face);
783:   return(0);
784: }

786: /*@
787:   PartitionGetFaceOrdering - This function gets the AO which was used to reorder the mesh faces
788:   during partitioning.

790:   Not collective

792:   Input Parameter:
793: . part  - The partition

795:   Output Parameter:
796: . order - The face ordering, or PETSC_NULL if none exists

798:   Level: intermediate

800: .keywords: Partition, face, ordering, AO
801: .seealso: MeshGetNodeOrdering()
802: @*/
803: int PartitionGetFaceOrdering(Partition part, AO *order)
804: {

810:   (*part->ops->getfaceordering)(part, order);
811:   return(0);
812: }

814: /*----------------------------------------------- Edge Query Functions -----------------------------------------------*/
815: /*@
816:   PartitionGetTotalEdges - Gets the number of edges in the mesh.

818:   Not collective

820:   Input Parameter:
821: . part - The partition

823:   Output Parameter:
824: . size - The number of edges in the mesh

826:   Level: intermediate

828: .keywords: partition, edge
829: .seealso: PartitionGetStartEdge(), PartitionGetEndEdge(), PartitionGetTotalElements()
830: @*/
831: int PartitionGetTotalEdges(Partition part, int *size)
832: {

838:   if (part->ops->gettotaledges == PETSC_NULL) {
839:     SETERRQ(PETSC_ERR_SUP, "Not implemented for this partition type");
840:   }
841:   (*part->ops->gettotaledges)(part, size);
842:   return(0);
843: }

845: /*@
846:   PartitionGetStartEdge - Gets the first edge in this domain.

848:   Not collective

850:   Input Parameter:
851: . part - The partition

853:   Output Parameter:
854: . edge - The first edge in this domain

856:   Level: intermediate

858: .keywords: partition, edge
859: .seealso: PartitionGetEndEdge(), PartitionGetNumEdges(), PartitionGetStartElement()
860: @*/
861: int PartitionGetStartEdge(Partition part, int *edge)
862: {

868:   if (part->ops->getstartedge == PETSC_NULL) {
869:     SETERRQ(PETSC_ERR_SUP, "Not implemented for this partition type");
870:   }
871:   (*part->ops->getstartedge)(part, edge);
872:   return(0);
873: }

875: /*@
876:   PartitionGetEndEdge - Gets the first edge in the next domain.

878:   Not collective

880:   Input Parameter:
881: . part - The partition

883:   Output Parameter:
884: . edge - The first edge in the next domain

886:   Level: intermediate

888: .keywords: partition, edge
889: .seealso: PartitionGetStartEdge(), PartitionGetNumEdges(), PartitionGetEndElement()
890: @*/
891: int PartitionGetEndEdge(Partition part, int *edge)
892: {

898:   if (part->ops->getendedge == PETSC_NULL) {
899:     SETERRQ(PETSC_ERR_SUP, "Not implemented for this partition type");
900:   }
901:   (*part->ops->getendedge)(part, edge);
902:   return(0);
903: }

905: /*@
906:   PartitionGetNumEdges - Gets the number of edges in this domain.

908:   Not collective

910:   Input Parameter:
911: . part - The partition

913:   Output Parameter:
914: . size - The number of edges in this domain

916:   Level: intermediate

918: .keywords: partition, edge
919: .seealso: PartitionGetStartEdge(), PartitionGetEndEdge(), PartitionGetNumElements()
920: @*/
921: int PartitionGetNumEdges(Partition part, int *size)
922: {

928:   if (part->ops->getnumedges == PETSC_NULL) {
929:     SETERRQ(PETSC_ERR_SUP, "Not implemented for this partition type");
930:   }
931:   (*part->ops->getnumedges)(part, size);
932:   return(0);
933: }

935: /*@
936:   PartitionGetNumOverlapEdges - Gets the number of edges and ghost edges this domain.

938:   Not collective

940:   Input Parameter:
941: . part - The partition

943:   Output Parameter:
944: . size - The number of edges and ghost edges this domain

946:   Level: intermediate

948: .keywords: partition, edge
949: .seealso: PartitionGetStartEdge(), PartitionGetEndEdge(), PartitionGetNumOverlapElements()
950: @*/
951: int PartitionGetNumOverlapEdges(Partition part, int *size)
952: {

958:   if (part->ops->getnumoverlapedges == PETSC_NULL) {
959:     SETERRQ(PETSC_ERR_SUP, "Not implemented for this partition type");
960:   }
961:   (*part->ops->getnumoverlapedges)(part, size);
962:   return(0);
963: }

965: /*@
966:   PartitionGetEdgeOrdering - This function gets the AO which was used to reorder the mesh edges
967:   during partitioning.

969:   Not collective

971:   Input Parameter:
972: . part  - The partition

974:   Output Parameter:
975: . order - The edge ordering, or PETSC_NULL if none exists

977:   Level: intermediate

979: .keywords: Partition, edge, ordering, AO
980: .seealso: MeshGetNodeOrdering()
981: @*/
982: int PartitionGetEdgeOrdering(Partition part, AO *order)
983: {

989:   (*part->ops->getedgeordering)(part, order);
990:   return(0);
991: }