#ifdef PETSC_RCS_HEADER
static char vcid[] = "$Id: partcreate.c,v 1.4 2000/01/10 03:54:25 knepley Exp $";
#endif

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

#undef  __FUNCT__
#define __FUNCT__ "PartitionCreate"
/*@ 
  PartitionCreate - This function creates an empty mesh partition.

  Collective on Mesh

  Input Parameter:
. mesh - The mesh to be partitioned

  Output Parameter:
. part - The partition

  Level: beginner

.keywords: partition, mesh
.seealso: PartitionSetUp(), PartitionDestroy(), GridCreate()
@*/
int PartitionCreate(Mesh mesh, Partition *part)
{
  MPI_Comm  comm;
  Partition p;
  int       ierr;

  PetscFunctionBegin;
  ierr = PetscObjectGetComm((PetscObject) mesh, &comm);                                                   CHKERRQ(ierr);
  PetscValidPointer(part);
  PetscHeaderCreate(p, _Partition, struct _PartitionOps, PARTITION_COOKIE, -1, "Partition", comm, PartitionDestroy, PartitionView);
  PetscLogObjectCreate(p);
  PetscLogObjectMemory(p, sizeof(struct _Partition));
  ierr = PetscMemzero(p->ops, sizeof(struct _PartitionOps));                                              CHKERRQ(ierr);
  p->bops->publish        = PETSC_NULL /* PartitionPublish_Petsc */;
  p->type_name            = PETSC_NULL;
  p->mesh                 = mesh;
  p->data                 = PETSC_NULL;
  p->isElementPartitioned = PETSC_FALSE;
  p->ordering             = PETSC_NULL;
  p->numLocElements       = 0;
  p->numElements          = 0;
  p->numOverlapElements   = 0;
  p->firstElement         = PETSC_NULL;
  p->ghostElements        = PETSC_NULL;
  p->ghostElementProcs    = PETSC_NULL;
  ierr = MPI_Comm_size(comm, &p->numProcs);                                                               CHKERRQ(ierr);
  ierr = MPI_Comm_size(comm, &p->rank);                                                                   CHKERRQ(ierr);

  *part = p;
  PetscFunctionReturn(0);
}

#undef  __FUNCT__
#define __FUNCT__ "PartitionSerialize"
/*@ 
  PartitionSerialize - This function stores or recreates a partition using a viewer for a binary file.

  Collective on MPI_Comm

  Input Parameters:
+ mesh   - The mesh that is partitioned
. viewer - The viewer context
- store  - This flag is PETSC_TRUE is data is being written, otherwise it will be read

  Output Parameter:
. part   - The partition

  Level: beginner

.keywords: partition, serialize
.seealso: MeshSerialize(), GridSerialize()
@*/
int PartitionSerialize(Mesh mesh, Partition *part, PetscViewer viewer, PetscTruth store)
{
  MPI_Comm   comm;
  int      (*serialize)(Mesh, Partition *, PetscViewer, PetscTruth);
  int        fd, len;
  char      *name;
  PetscTruth match;
  int        ierr;

  PetscFunctionBegin;
  PetscValidHeaderSpecific(viewer, PETSC_VIEWER_COOKIE);
  PetscValidPointer(part);

  ierr = PetscTypeCompare((PetscObject) viewer, PETSC_VIEWER_BINARY, &match);                             CHKERRQ(ierr);
  if (match == PETSC_FALSE) SETERRQ(PETSC_ERR_ARG_WRONG, "Must be binary viewer");
  ierr = PetscViewerBinaryGetDescriptor(viewer, &fd);                                                     CHKERRQ(ierr);
  ierr = PetscObjectGetComm((PetscObject) mesh, &comm);                                                   CHKERRQ(ierr);

  if (store) {
    PetscValidHeaderSpecific(*part, PARTITION_COOKIE);
    ierr = PetscStrlen((*part)->class_name, &len);                                                        CHKERRQ(ierr);
    ierr = PetscBinaryWrite(fd, &len,                     1,   PETSC_INT,  0);                            CHKERRQ(ierr);
    ierr = PetscBinaryWrite(fd,  (*part)->class_name,     len, PETSC_CHAR, 0);                            CHKERRQ(ierr);
    ierr = PetscStrlen((*part)->serialize_name, &len);                                                    CHKERRQ(ierr);
    ierr = PetscBinaryWrite(fd, &len,                     1,   PETSC_INT,  0);                            CHKERRQ(ierr);
    ierr = PetscBinaryWrite(fd,  (*part)->serialize_name, len, PETSC_CHAR, 0);                            CHKERRQ(ierr);
    ierr = PetscFListFind(comm, PartitionSerializeList, (*part)->serialize_name, (void (**)(void)) &serialize);CHKERRQ(ierr);
    if (!serialize) SETERRQ(PETSC_ERR_ARG_WRONG, "Type cannot be serialized");
    ierr = (*serialize)(mesh, part, viewer, store);                                                       CHKERRQ(ierr);
  } else {
    ierr = PetscBinaryRead(fd, &len,    1,   PETSC_INT);                                                  CHKERRQ(ierr);
    ierr = PetscMalloc((len+1) * sizeof(char), &name);                                                    CHKERRQ(ierr);
    name[len] = 0;
    ierr = PetscBinaryRead(fd,  name,   len, PETSC_CHAR);                                                 CHKERRQ(ierr);
    ierr = PetscStrcmp(name, "Partition", &match);                                                        CHKERRQ(ierr);
    ierr = PetscFree(name);                                                                               CHKERRQ(ierr);
    if (match == PETSC_FALSE) SETERRQ(PETSC_ERR_ARG_WRONG, "Non-partition object");
    /* Dispatch to the correct routine */
    if (!PartitionSerializeRegisterAllCalled) {
      ierr = PartitionSerializeRegisterAll(PETSC_NULL);                                                   CHKERRQ(ierr);
    }
    if (!PartitionSerializeList) SETERRQ(PETSC_ERR_ARG_CORRUPT, "Could not find table of methods");
    ierr = PetscBinaryRead(fd, &len,    1,   PETSC_INT);                                                  CHKERRQ(ierr);
    ierr = PetscMalloc((len+1) * sizeof(char), &name);                                                    CHKERRQ(ierr);
    name[len] = 0;
    ierr = PetscBinaryRead(fd,  name,   len, PETSC_CHAR);                                                 CHKERRQ(ierr);
    ierr = PetscFListFind(comm, PartitionSerializeList, name, (void (**)(void)) &serialize);              CHKERRQ(ierr);
    if (!serialize) SETERRQ(PETSC_ERR_ARG_WRONG, "Type cannot be serialized");
    ierr = (*serialize)(mesh, part, viewer, store);                                                       CHKERRQ(ierr);
    ierr = PetscStrfree((*part)->serialize_name);                                                         CHKERRQ(ierr);
    (*part)->serialize_name = name;
  }

  PetscFunctionReturn(0);
}
