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

/*
     Defines the interface to the partition query functions
*/

#include "src/mesh/meshimpl.h"    /*I "mesh.h" I*/

/*-------------------------------------------- Partition Query Functions ---------------------------------------------*/
#undef  __FUNCT__
#define __FUNCT__ "PartitionGetDimension"
/*@
  PartitionGetDimension - This function returns the dimension of the Partition.

  Not collective

  Input Parameter:
. part - The partition

  Output Parameter:
. dim  - The partition dimension

  Level: intermediate

.keywords: Partition, dimension
.seealso: MeshGetDimension()
@*/
int PartitionGetDimension(Partition part, int *dim)
{
  Mesh mesh;
  int ierr;

  PetscFunctionBegin;
  PetscValidHeaderSpecific(part, PARTITION_COOKIE);
  PetscValidIntPointer(dim);
  ierr = PartitionGetMesh(part, &mesh);                                                                   CHKERRQ(ierr);
  ierr = MeshGetDimension(mesh, dim);                                                                     CHKERRQ(ierr);
  PetscFunctionReturn(0);
}

#undef  __FUNCT__
#define __FUNCT__ "PartitionGetMesh"
/*@
  PartitionGetMesh - Returns the Mesh object for this Partition.

  Not collective

  Input Parameter:
. part - The partition

  Output Parameter:
. mesh - The mesh

  Level: intermediate

.keywords: Mesh, Partition, get
.seealso: MeshGetPartition()
@*/
int PartitionGetMesh(Partition part, Mesh *mesh)
{
  PetscFunctionBegin;
  PetscValidHeaderSpecific(part, PARTITION_COOKIE);
  PetscValidPointer(mesh);
  *mesh = part->mesh;
  PetscFunctionReturn(0);
}

/*--------------------------------------------- Element Query Functions ----------------------------------------------*/
#undef  __FUNCT__
#define __FUNCT__ "PartitionGetTotalElements"
/*@
  PartitionGetTotalElements - Gets the number of elements in the mesh.

  Not collective

  Input Parameter:
. part - The partition

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

  Level: intermediate

.keywords: partition, element
.seealso: PartitionGetStartElement(), PartitionGetEndElement()
@*/
int PartitionGetTotalElements(Partition part, int *size)
{
  PetscFunctionBegin;
  PetscValidHeaderSpecific(part, PARTITION_COOKIE);
  PetscValidIntPointer(size);
  *size = part->numElements;
  PetscFunctionReturn(0);
}

#undef  __FUNCT__
#define __FUNCT__ "PartitionGetStartElement"
/*@
  PartitionGetStartElement - Gets the first element in this domain.

  Not collective

  Input Parameter:
. part - The partition

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

  Level: intermediate

.keywords: partition, element
.seealso: PartitionGetEndElement(), PartitionGetNumElements()
@*/
int PartitionGetStartElement(Partition part, int *elem)
{
  PetscFunctionBegin;
  PetscValidHeaderSpecific(part, PARTITION_COOKIE);
  PetscValidIntPointer(elem);
  *elem = part->firstElement[part->rank];
  PetscFunctionReturn(0);
}

#undef  __FUNCT__
#define __FUNCT__ "PartitionGetEndElement"
/*@
  PartitionGetEndElement - Gets the first element in the next domain.

  Not collective

  Input Parameter:
. part - The partition

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

  Level: intermediate

.keywords: partition, element
.seealso: PartitionGetStartElement(), PartitionGetNumElements()
@*/
int PartitionGetEndElement(Partition part, int *elem)
{
  PetscFunctionBegin;
  PetscValidHeaderSpecific(part, PARTITION_COOKIE);
  PetscValidIntPointer(elem);
  *elem = part->firstElement[part->rank+1];
  PetscFunctionReturn(0);
}

#undef  __FUNCT__
#define __FUNCT__ "PartitionGetNumElements"
/*@
  PartitionGetNumElements - Gets the number of elements in this domain.

  Not collective

  Input Parameter:
. part - The partition

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

  Level: intermediate

.keywords: partition, element
.seealso: PartitionGetStartElement(), PartitionGetEndElement()
@*/
int PartitionGetNumElements(Partition part, int *size)
{
  PetscFunctionBegin;
  PetscValidHeaderSpecific(part, PARTITION_COOKIE);
  PetscValidIntPointer(size);
  *size = part->firstElement[part->rank+1] - part->firstElement[part->rank];
  PetscFunctionReturn(0);
}

#undef  __FUNCT__
#define __FUNCT__ "PartitionGetNumOverlapElements"
/*@
  PartitionGetNumOverlapElements - Gets the number of elements and ghost elements for this domain.

  Not collective

  Input Parameter:
. part - The partition

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

  Level: intermediate

.keywords: partition, element
.seealso: PartitionGetStartElement(), PartitionGetEndElement()
@*/
int PartitionGetNumOverlapElements(Partition part, int *size)
{
  PetscFunctionBegin;
  PetscValidHeaderSpecific(part, PARTITION_COOKIE);
  PetscValidIntPointer(size);
  *size = part->numOverlapElements;
  PetscFunctionReturn(0);
}

#undef  __FUNCT__
#define __FUNCT__ "PartitionGhostElementIndex_Private"
static int PartitionGhostElementIndex_Private(Partition p, int elem, int *gElem)
{
  int low, high, mid;

  PetscFunctionBegin;
  /* Use bisection since the array is assumed to be sorted */
  low  = 0;
  high = p->numOverlapElements - (p->firstElement[p->rank+1] - p->firstElement[p->rank]) - 1;
  while (low <= high) {
    mid = (low + high)/2;
    if (elem == p->ghostElements[mid]) {
      *gElem = mid;
      PetscFunctionReturn(0);
    } else if (elem < p->ghostElements[mid]) {
      high = mid - 1;
    } else {
      low  = mid + 1;
    }
  }
  /* We indicate elements which are not local and also not ghost by -2 */
  *gElem = -2;
  PetscFunctionReturn(0);
}

#undef  __FUNCT__
#define __FUNCT__ "PartitionGlobalToLocalElementIndex"
/*@
  PartitionGlobalToLocalElementIndex - Returns the local element number
  corresponding to the global element number.

  Not collective

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

  Output Parameter:
. locElem - The local element number

  Level: intermediate

.keywords: partition, local, global
.seealso PartitionLocalToGlobalElementIndex()
@*/
int PartitionGlobalToLocalElementIndex(Partition part, int elem, int *locElem)
{
  int numLocElements;
  int gElem; /* The local ghost element number */
  int ierr;

  PetscFunctionBegin;
  PetscValidHeaderSpecific(part, PARTITION_COOKIE);
  PetscValidIntPointer(locElem);
  numLocElements = part->firstElement[part->rank+1] - part->firstElement[part->rank];
  if (elem < 0) {
    *locElem = elem;
    PetscFunctionReturn(0);
  }
  /* Check for ghost element */
  if ((elem < part->firstElement[part->rank]) || (elem >= part->firstElement[part->rank+1])) {
    /* Search for canonical number */
    ierr = PartitionGhostElementIndex_Private(part, elem, &gElem);                                       CHKERRQ(ierr);
    if (gElem < 0) {
      *locElem = gElem;
    } else {
      *locElem = numLocElements + gElem;
    }
  } else {
    *locElem = elem - part->firstElement[part->rank];
  }
  PetscFunctionReturn(0);
}

#undef  __FUNCT__
#define __FUNCT__ "PartitionLocalToGlobalElementIndex"
/*@
  PartitionLocalToGlobalElementIndex - Returns the global element number
  corresponding to the local element number.

  Not collective

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

  Output Parameter:
. elem    - The global element number

  Level: intermediate

.keywords: partition, local, global
.seealso: PartitionGlobalToLocalElementIndex()
@*/
int PartitionLocalToGlobalElementIndex(Partition part, int locElem, int *elem)
{
  int numLocElements;

  PetscFunctionBegin;
  PetscValidHeaderSpecific(part, PARTITION_COOKIE);
  PetscValidIntPointer(elem);
  numLocElements = part->firstElement[part->rank+1] - part->firstElement[part->rank];
  if (locElem < 0) {
    *elem = locElem;
    PetscFunctionReturn(0);
  } else if (locElem < numLocElements) {
    *elem = locElem + part->firstElement[part->rank];
  } else if (locElem < part->numOverlapElements) {
    *elem = part->ghostElements[locElem - numLocElements];
  } else {
    SETERRQ(PETSC_ERR_ARG_WRONG, "Invalid local element index (too large)");
  }
  PetscFunctionReturn(0);
}

#undef  __FUNCT__
#define __FUNCT__ "PartitionGetElementOrdering"
/*@
  PartitionGetElementOrdering - This function gets the AO which was used to reorder the mesh elements
  during partitioning.

  Not collective

  Input Parameter:
. part  - The partition

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

  Level: intermediate

.keywords: Partition, element, ordering, AO
.seealso: MeshGetNodeOrdering()
@*/
int PartitionGetElementOrdering(Partition part, AO *order)
{
  PetscFunctionBegin;
  PetscValidHeaderSpecific(part, PARTITION_COOKIE);
  PetscValidPointer(order);
  *order = part->ordering;
  PetscFunctionReturn(0);
}

/*----------------------------------------------- Node Query Functions -----------------------------------------------*/
#undef  __FUNCT__
#define __FUNCT__ "PartitionGetTotalNodes"
/*@
  PartitionGetTotalNodes - Gets the number of nodes in the mesh.

  Not collective

  Input Parameter:
. part - The partition

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

  Level: intermediate

.keywords: partition, node
.seealso: PartitionGetStartNode(), PartitionGetEndNode(), PartitionGetTotalElements()
@*/
int PartitionGetTotalNodes(Partition part, int *size)
{
  int ierr;

  PetscFunctionBegin;
  PetscValidHeaderSpecific(part, PARTITION_COOKIE);
  PetscValidIntPointer(size);
  if (part->ops->gettotalnodes == PETSC_NULL) {
    SETERRQ(PETSC_ERR_SUP, "Not implemented for this partition type");
  }
  ierr = (*part->ops->gettotalnodes)(part, size);                                                         CHKERRQ(ierr);
  PetscFunctionReturn(0);
}

#undef  __FUNCT__
#define __FUNCT__ "PartitionGetStartNode"
/*@
  PartitionGetStartNode - Gets the first node in this domain.

  Not collective

  Input Parameter:
. part - The partition

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

  Level: intermediate

.keywords: partition, node
.seealso: PartitionGetEndNode(), PartitionGetNumNodes(), PartitionGetStartElement()
@*/
int PartitionGetStartNode(Partition part, int *node)
{
  int ierr;

  PetscFunctionBegin;
  PetscValidHeaderSpecific(part, PARTITION_COOKIE);
  PetscValidIntPointer(node);
  if (part->ops->getstartnode == PETSC_NULL) {
    SETERRQ(PETSC_ERR_SUP, "Not implemented for this partition type");
  }
  ierr = (*part->ops->getstartnode)(part, node);                                                         CHKERRQ(ierr);
  PetscFunctionReturn(0);
}

#undef  __FUNCT__
#define __FUNCT__ "PartitionGetEndNode"
/*@
  PartitionGetEndNode - Gets the first node in the next domain.

  Not collective

  Input Parameter:
. part - The partition

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

  Level: intermediate

.keywords: partition, node
.seealso: PartitionGetStartNode(), PartitionGetNumNodes(), PartitionGetEndElement()
@*/
int PartitionGetEndNode(Partition part, int *node)
{
  int ierr;

  PetscFunctionBegin;
  PetscValidHeaderSpecific(part, PARTITION_COOKIE);
  PetscValidIntPointer(node);
  if (part->ops->getendnode == PETSC_NULL) {
    SETERRQ(PETSC_ERR_SUP, "Not implemented for this partition type");
  }
  ierr = (*part->ops->getendnode)(part, node);                                                           CHKERRQ(ierr);
  PetscFunctionReturn(0);
}

#undef  __FUNCT__
#define __FUNCT__ "PartitionGetNumNodes"
/*@
  PartitionGetNumNodes - Gets the number of nodes in this domain.

  Not collective

  Input Parameter:
. part - The partition

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

  Level: intermediate

.keywords: partition, node
.seealso: PartitionGetStartNode(), PartitionGetEndNode(), PartitionGetNumElements()
@*/
int PartitionGetNumNodes(Partition part, int *size)
{
  int ierr;

  PetscFunctionBegin;
  PetscValidHeaderSpecific(part, PARTITION_COOKIE);
  PetscValidIntPointer(size);
  if (part->ops->getnumnodes == PETSC_NULL) {
    SETERRQ(PETSC_ERR_SUP, "Not implemented for this partition type");
  }
  ierr = (*part->ops->getnumnodes)(part, size);                                                          CHKERRQ(ierr);
  PetscFunctionReturn(0);
}

#undef  __FUNCT__
#define __FUNCT__ "PartitionGetNumOverlapNodes"
/*@
  PartitionGetNumOverlapNodes - Gets the number of nodes and ghost nodes for this domain.

  Not collective

  Input Parameter:
. part - The partition

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

  Level: intermediate

.keywords: partition, node
.seealso: PartitionGetStartNode(), PartitionGetEndNode(), PartitionGetNumOverlapElements()
@*/
int PartitionGetNumOverlapNodes(Partition part, int *size)
{
  int ierr;

  PetscFunctionBegin;
  PetscValidHeaderSpecific(part, PARTITION_COOKIE);
  PetscValidIntPointer(size);
  if (part->ops->getnumoverlapnodes == PETSC_NULL) {
    SETERRQ(PETSC_ERR_SUP, "Not implemented for this partition type");
  }
  ierr = (*part->ops->getnumoverlapnodes)(part, size);                                                   CHKERRQ(ierr);
  PetscFunctionReturn(0);
}

#undef  __FUNCT__
#define __FUNCT__ "PartitionGlobalToLocalNodeIndex"
/*@
  PartitionGlobalToLocalNodeIndex - Returns the local node number
  corresponding to the global node number.

  Not collective

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

  Output Parameter:
. locNode - The local node number

  Level: intermediate

.keywords: partition, local, global
.seealso: PartitionLocalToGlobalNodeIndex(), PartitionGlobalToLocalElementIndex()
@*/
int PartitionGlobalToLocalNodeIndex(Partition part, int node, int *locNode)
{
  int ierr;

  PetscFunctionBegin;
  PetscValidHeaderSpecific(part, PARTITION_COOKIE);
  PetscValidIntPointer(locNode);
  if (part->ops->globaltolocalnodeindex == PETSC_NULL) {
    SETERRQ(PETSC_ERR_SUP, "Not implemented for this partition type");
  }
  ierr = (*part->ops->globaltolocalnodeindex)(part, node, locNode);                                      CHKERRQ(ierr);
  PetscFunctionReturn(0);
}

#undef  __FUNCT__
#define __FUNCT__ "PartitionLocalToGlobalNodeIndex"
/*@
  PartitionLocalToGlobalNodeIndex - Returns the global node number
  corresponding to the local node number.

  Not collective

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

  Output Parameter:
. node    - The global node number

  Level: intermediate

.keywords: partition, local, global
.seealso: PartitionGlobalToLocalNodeIndex(), PartitionLocalToGlobalElementIndex()
@*/
int PartitionLocalToGlobalNodeIndex(Partition part, int locNode, int *node)
{
  int ierr;

  PetscFunctionBegin;
  PetscValidHeaderSpecific(part, PARTITION_COOKIE);
  PetscValidIntPointer(node);
  if (part->ops->localtoglobalnodeindex == PETSC_NULL) {
    SETERRQ(PETSC_ERR_SUP, "Not implemented for this partition type");
  }
  ierr = (*part->ops->localtoglobalnodeindex)(part, locNode, node);                                      CHKERRQ(ierr);
  PetscFunctionReturn(0);
}

#undef  __FUNCT__
#define __FUNCT__ "PartitionGlobalToGhostNodeIndex"
/*@
  PartitionGlobalToGhostNodeIndex - Returns the ghost node number
  corresponding to the global node number.

  Not collective

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

  Output Parameters:
+ ghostNode - The ghost node number (0..numGhosts)
- ghostProc - The processor on which the node resides

  Level: intermediate

.keywords: partition, ghost, global
.seealso: PartitionGhostToGlobalNodeIndex(), PartitionGlobalToLocalElementIndex()
@*/
int PartitionGlobalToGhostNodeIndex(Partition part, int node, int *ghostNode, int *ghostProc)
{
  int ierr;

  PetscFunctionBegin;
  PetscValidHeaderSpecific(part, PARTITION_COOKIE);
  PetscValidIntPointer(ghostNode);
  if (part->ops->globaltoghostnodeindex == PETSC_NULL) {
    SETERRQ(PETSC_ERR_SUP, "Not implemented for this partition type");
  }
  ierr = (*part->ops->globaltoghostnodeindex)(part, node, ghostNode, ghostProc);                          CHKERRQ(ierr);
  PetscFunctionReturn(0);
}

#undef  __FUNCT__
#define __FUNCT__ "PartitionGhostToGlobalNodeIndex"
/*@
  PartitionGhostToGlobalNodeIndex - Returns the global node number
  corresponding to the ghost node number.

  Not collective

  Input Parameters:
+ part      - The partition
- ghostNode - The canonical ghost node number (0..numGhosts)

  Output Parameters:
+ node      - The global node number
- ghostProc - The processor on which the node resides

  Level: intermediate

.keywords: partition, ghost, global
.seealso: PartitionGlobalToGhostNodeIndex(), PartitionLocalToGlobalElementIndex()
@*/
int PartitionGhostToGlobalNodeIndex(Partition part, int ghostNode, int *node, int *ghostProc)
{
  int ierr;

  PetscFunctionBegin;
  PetscValidHeaderSpecific(part, PARTITION_COOKIE);
  PetscValidIntPointer(node);
  if (part->ops->ghosttoglobalnodeindex == PETSC_NULL) {
    SETERRQ(PETSC_ERR_SUP, "Not implemented for this partition type");
  }
  ierr = (*part->ops->ghosttoglobalnodeindex)(part, ghostNode, node, ghostProc);                          CHKERRQ(ierr);
  PetscFunctionReturn(0);
}

#undef  __FUNCT__
#define __FUNCT__ "PartitionGetNodeOrdering"
/*@
  PartitionGetNodeOrdering - This function gets the AO which was used to reorder the mesh nodes
  during partitioning.

  Not collective

  Input Parameter:
. part  - The partition

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

  Level: intermediate

.keywords: Partition, node, ordering, AO
.seealso: MeshGetNodeOrdering()
@*/
int PartitionGetNodeOrdering(Partition part, AO *order)
{
  int ierr;

  PetscFunctionBegin;
  PetscValidHeaderSpecific(part, PARTITION_COOKIE);
  PetscValidPointer(order);
  ierr = (*part->ops->getnodeordering)(part, order);                                                      CHKERRQ(ierr);
  PetscFunctionReturn(0);
}

/*----------------------------------------------- Face Query Functions -----------------------------------------------*/
#undef  __FUNCT__
#define __FUNCT__ "PartitionGetTotalFaces"
/*@
  PartitionGetTotalFaces - Gets the number of faces in the mesh.

  Not collective

  Input Parameter:
. part - The partition

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

  Level: intermediate

.keywords: partition, face
.seealso: PartitionGetStartFace(), PartitionGetEndFace(), PartitionGetTotalElements()
@*/
int PartitionGetTotalFaces(Partition part, int *size)
{
  int ierr;

  PetscFunctionBegin;
  PetscValidHeaderSpecific(part, PARTITION_COOKIE);
  PetscValidIntPointer(size);
  if (part->ops->gettotalfaces == PETSC_NULL) {
    SETERRQ(PETSC_ERR_SUP, "Not implemented for this partition type");
  }
  ierr = (*part->ops->gettotalfaces)(part, size);                                                         CHKERRQ(ierr);
  PetscFunctionReturn(0);
}

#undef  __FUNCT__
#define __FUNCT__ "PartitionGetStartFace"
/*@
  PartitionGetStartFace - Gets the first face in this domain.

  Not collective

  Input Parameter:
. part - The partition

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

  Level: intermediate

.keywords: partition, face
.seealso: PartitionGetEndFace(), PartitionGetNumFaces(), PartitionGetStartElement()
@*/
int PartitionGetStartFace(Partition part, int *face)
{
  int ierr;

  PetscFunctionBegin;
  PetscValidHeaderSpecific(part, PARTITION_COOKIE);
  PetscValidIntPointer(face);
  if (part->ops->getstartface == PETSC_NULL) {
    SETERRQ(PETSC_ERR_SUP, "Not implemented for this partition type");
  }
  ierr = (*part->ops->getstartface)(part, face);                                                         CHKERRQ(ierr);
  PetscFunctionReturn(0);
}

#undef  __FUNCT__
#define __FUNCT__ "PartitionGetEndFace"
/*@
  PartitionGetEndFace - Gets the first face in the next domain.

  Not collective

  Input Parameter:
. part - The partition

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

  Level: intermediate

.keywords: partition, face
.seealso: PartitionGetStartFace(), PartitionGetNumFaces(), PartitionGetEndElement()
@*/
int PartitionGetEndFace(Partition part, int *face)
{
  int ierr;

  PetscFunctionBegin;
  PetscValidHeaderSpecific(part, PARTITION_COOKIE);
  PetscValidIntPointer(face);
  if (part->ops->getendface == PETSC_NULL) {
    SETERRQ(PETSC_ERR_SUP, "Not implemented for this partition type");
  }
  ierr = (*part->ops->getendface)(part, face);                                                           CHKERRQ(ierr);
  PetscFunctionReturn(0);
}

#undef  __FUNCT__
#define __FUNCT__ "PartitionGetNumFaces"
/*@
  PartitionGetNumFaces - Gets the number of faces in this domain.

  Not collective

  Input Parameter:
. part - The partition

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

  Level: intermediate

.keywords: partition, face
.seealso: PartitionGetStartFace(), PartitionGetEndFace(), PartitionGetNumElements()
@*/
int PartitionGetNumFaces(Partition part, int *size)
{
  int ierr;

  PetscFunctionBegin;
  PetscValidHeaderSpecific(part, PARTITION_COOKIE);
  PetscValidIntPointer(size);
  if (part->ops->getnumfaces == PETSC_NULL) {
    SETERRQ(PETSC_ERR_SUP, "Not implemented for this partition type");
  }
  ierr = (*part->ops->getnumfaces)(part, size);                                                          CHKERRQ(ierr);
  PetscFunctionReturn(0);
}

#undef  __FUNCT__
#define __FUNCT__ "PartitionGetNumOverlapFaces"
/*@
  PartitionGetNumOverlapFaces - Gets the number of faces and ghost faces this domain.

  Not collective

  Input Parameter:
. part - The partition

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

  Level: intermediate

.keywords: partition, face
.seealso: PartitionGetStartFace(), PartitionGetEndFace(), PartitionGetNumOverlapElements()
@*/
int PartitionGetNumOverlapFaces(Partition part, int *size)
{
  int ierr;

  PetscFunctionBegin;
  PetscValidHeaderSpecific(part, PARTITION_COOKIE);
  PetscValidIntPointer(size);
  if (part->ops->getnumoverlapfaces == PETSC_NULL) {
    SETERRQ(PETSC_ERR_SUP, "Not implemented for this partition type");
  }
  ierr = (*part->ops->getnumoverlapfaces)(part, size);                                                   CHKERRQ(ierr);
  PetscFunctionReturn(0);
}

#undef  __FUNCT__
#define __FUNCT__ "PartitionGlobalToLocalFaceIndex"
/*@
  PartitionGlobalToLocalFaceIndex - Returns the local face number
  corresponding to the global face number.

  Not collective

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

  Output Parameter:
. locFace - The local face number

  Level: intermediate

.keywords: partition, local, global
.seealso: PartitionLocalToGlobalFaceIndex(), PartitionGlobalToLocalElementIndex()
@*/
int PartitionGlobalToLocalFaceIndex(Partition part, int face, int *locFace)
{
  int ierr;

  PetscFunctionBegin;
  PetscValidHeaderSpecific(part, PARTITION_COOKIE);
  PetscValidIntPointer(locFace);
  if (part->ops->globaltolocalfaceindex == PETSC_NULL) {
    SETERRQ(PETSC_ERR_SUP, "Not implemented for this partition type");
  }
  ierr = (*part->ops->globaltolocalfaceindex)(part, face, locFace);                                      CHKERRQ(ierr);
  PetscFunctionReturn(0);
}

#undef  __FUNCT__
#define __FUNCT__ "PartitionLocalToGlobalFaceIndex"
/*@
  PartitionLocalToGlobalFaceIndex - Returns the global face number
  corresponding to the local face number.

  Not collective

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

  Output Parameter:
. face    - The global face number

  Level: intermediate

.keywords: partition, local, global
.seealso: PartitionGlobalToLocalNodeIndex(), PartitionLocalToGlobalElementIndex()
@*/
int PartitionLocalToGlobalFaceIndex(Partition part, int locFace, int *face)
{
  int ierr;

  PetscFunctionBegin;
  PetscValidHeaderSpecific(part, PARTITION_COOKIE);
  PetscValidIntPointer(face);
  if (part->ops->localtoglobalfaceindex == PETSC_NULL) {
    SETERRQ(PETSC_ERR_SUP, "Not implemented for this partition type");
  }
  ierr = (*part->ops->localtoglobalfaceindex)(part, locFace, face);                                      CHKERRQ(ierr);
  PetscFunctionReturn(0);
}

#undef  __FUNCT__
#define __FUNCT__ "PartitionGetFaceOrdering"
/*@
  PartitionGetFaceOrdering - This function gets the AO which was used to reorder the mesh faces
  during partitioning.

  Not collective

  Input Parameter:
. part  - The partition

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

  Level: intermediate

.keywords: Partition, face, ordering, AO
.seealso: MeshGetNodeOrdering()
@*/
int PartitionGetFaceOrdering(Partition part, AO *order)
{
  int ierr;

  PetscFunctionBegin;
  PetscValidHeaderSpecific(part, PARTITION_COOKIE);
  PetscValidPointer(order);
  ierr = (*part->ops->getfaceordering)(part, order);                                                      CHKERRQ(ierr);
  PetscFunctionReturn(0);
}

/*----------------------------------------------- Edge Query Functions -----------------------------------------------*/
#undef  __FUNCT__
#define __FUNCT__ "PartitionGetTotalEdges"
/*@
  PartitionGetTotalEdges - Gets the number of edges in the mesh.

  Not collective

  Input Parameter:
. part - The partition

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

  Level: intermediate

.keywords: partition, edge
.seealso: PartitionGetStartEdge(), PartitionGetEndEdge(), PartitionGetTotalElements()
@*/
int PartitionGetTotalEdges(Partition part, int *size)
{
  int ierr;

  PetscFunctionBegin;
  PetscValidHeaderSpecific(part, PARTITION_COOKIE);
  PetscValidIntPointer(size);
  if (part->ops->gettotaledges == PETSC_NULL) {
    SETERRQ(PETSC_ERR_SUP, "Not implemented for this partition type");
  }
  ierr = (*part->ops->gettotaledges)(part, size);                                                         CHKERRQ(ierr);
  PetscFunctionReturn(0);
}

#undef  __FUNCT__
#define __FUNCT__ "PartitionGetStartEdge"
/*@
  PartitionGetStartEdge - Gets the first edge in this domain.

  Not collective

  Input Parameter:
. part - The partition

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

  Level: intermediate

.keywords: partition, edge
.seealso: PartitionGetEndEdge(), PartitionGetNumEdges(), PartitionGetStartElement()
@*/
int PartitionGetStartEdge(Partition part, int *edge)
{
  int ierr;

  PetscFunctionBegin;
  PetscValidHeaderSpecific(part, PARTITION_COOKIE);
  PetscValidIntPointer(edge);
  if (part->ops->getstartedge == PETSC_NULL) {
    SETERRQ(PETSC_ERR_SUP, "Not implemented for this partition type");
  }
  ierr = (*part->ops->getstartedge)(part, edge);                                                         CHKERRQ(ierr);
  PetscFunctionReturn(0);
}

#undef  __FUNCT__
#define __FUNCT__ "PartitionGetEndEdge"
/*@
  PartitionGetEndEdge - Gets the first edge in the next domain.

  Not collective

  Input Parameter:
. part - The partition

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

  Level: intermediate

.keywords: partition, edge
.seealso: PartitionGetStartEdge(), PartitionGetNumEdges(), PartitionGetEndElement()
@*/
int PartitionGetEndEdge(Partition part, int *edge)
{
  int ierr;

  PetscFunctionBegin;
  PetscValidHeaderSpecific(part, PARTITION_COOKIE);
  PetscValidIntPointer(edge);
  if (part->ops->getendedge == PETSC_NULL) {
    SETERRQ(PETSC_ERR_SUP, "Not implemented for this partition type");
  }
  ierr = (*part->ops->getendedge)(part, edge);                                                           CHKERRQ(ierr);
  PetscFunctionReturn(0);
}

#undef  __FUNCT__
#define __FUNCT__ "PartitionGetNumEdges"
/*@
  PartitionGetNumEdges - Gets the number of edges in this domain.

  Not collective

  Input Parameter:
. part - The partition

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

  Level: intermediate

.keywords: partition, edge
.seealso: PartitionGetStartEdge(), PartitionGetEndEdge(), PartitionGetNumElements()
@*/
int PartitionGetNumEdges(Partition part, int *size)
{
  int ierr;

  PetscFunctionBegin;
  PetscValidHeaderSpecific(part, PARTITION_COOKIE);
  PetscValidIntPointer(size);
  if (part->ops->getnumedges == PETSC_NULL) {
    SETERRQ(PETSC_ERR_SUP, "Not implemented for this partition type");
  }
  ierr = (*part->ops->getnumedges)(part, size);                                                          CHKERRQ(ierr);
  PetscFunctionReturn(0);
}

#undef  __FUNCT__
#define __FUNCT__ "PartitionGetNumOverlapEdges"
/*@
  PartitionGetNumOverlapEdges - Gets the number of edges and ghost edges this domain.

  Not collective

  Input Parameter:
. part - The partition

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

  Level: intermediate

.keywords: partition, edge
.seealso: PartitionGetStartEdge(), PartitionGetEndEdge(), PartitionGetNumOverlapElements()
@*/
int PartitionGetNumOverlapEdges(Partition part, int *size)
{
  int ierr;

  PetscFunctionBegin;
  PetscValidHeaderSpecific(part, PARTITION_COOKIE);
  PetscValidIntPointer(size);
  if (part->ops->getnumoverlapedges == PETSC_NULL) {
    SETERRQ(PETSC_ERR_SUP, "Not implemented for this partition type");
  }
  ierr = (*part->ops->getnumoverlapedges)(part, size);                                                   CHKERRQ(ierr);
  PetscFunctionReturn(0);
}

#undef  __FUNCT__
#define __FUNCT__ "PartitionGetEdgeOrdering"
/*@
  PartitionGetEdgeOrdering - This function gets the AO which was used to reorder the mesh edges
  during partitioning.

  Not collective

  Input Parameter:
. part  - The partition

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

  Level: intermediate

.keywords: Partition, edge, ordering, AO
.seealso: MeshGetNodeOrdering()
@*/
int PartitionGetEdgeOrdering(Partition part, AO *order)
{
  int ierr;

  PetscFunctionBegin;
  PetscValidHeaderSpecific(part, PARTITION_COOKIE);
  PetscValidPointer(order);
  ierr = (*part->ops->getedgeordering)(part, order);                                                      CHKERRQ(ierr);
  PetscFunctionReturn(0);
}
