Actual source code: partitioner.c

      1: #include <petsc/private/partitionerimpl.h>

      3: /*@C
      4:   PetscPartitionerSetType - Builds a particular PetscPartitioner

      6:   Collective on PetscPartitioner

      8:   Input Parameters:
      9: + part - The PetscPartitioner object
     10: - name - The kind of partitioner

     12:   Options Database Key:
     13: . -petscpartitioner_type <type> - Sets the PetscPartitioner type; use -help for a list of available types

     15:   Note:
     16: $ PETSCPARTITIONERCHACO    - The Chaco partitioner (--download-chaco)
     17: $ PETSCPARTITIONERPARMETIS - The ParMetis partitioner (--download-parmetis)
     18: $ PETSCPARTITIONERSHELL    - A shell partitioner implemented by the user
     19: $ PETSCPARTITIONERSIMPLE   - A simple partitioner that divides cells into equal, contiguous chunks
     20: $ PETSCPARTITIONERGATHER   - Gathers all cells onto process 0

     22:   Level: intermediate

     24: .seealso: PetscPartitionerGetType(), PetscPartitionerCreate()
     25: @*/
     26: PetscErrorCode PetscPartitionerSetType(PetscPartitioner part, PetscPartitionerType name)
     27: {
     28:   PetscErrorCode (*r)(PetscPartitioner);
     29:   PetscBool      match;

     32:   PetscObjectTypeCompare((PetscObject) part, name, &match);
     33:   if (match) return 0;

     35:   PetscPartitionerRegisterAll();
     36:   PetscFunctionListFind(PetscPartitionerList, name, &r);

     39:   if (part->ops->destroy) {
     40:     (*part->ops->destroy)(part);
     41:   }
     42:   part->noGraph = PETSC_FALSE;
     43:   PetscMemzero(part->ops, sizeof(*part->ops));
     44:   PetscObjectChangeTypeName((PetscObject) part, name);
     45:   (*r)(part);
     46:   return 0;
     47: }

     49: /*@C
     50:   PetscPartitionerGetType - Gets the PetscPartitioner type name (as a string) from the object.

     52:   Not Collective

     54:   Input Parameter:
     55: . part - The PetscPartitioner

     57:   Output Parameter:
     58: . name - The PetscPartitioner type name

     60:   Level: intermediate

     62: .seealso: PetscPartitionerSetType(), PetscPartitionerCreate()
     63: @*/
     64: PetscErrorCode PetscPartitionerGetType(PetscPartitioner part, PetscPartitionerType *name)
     65: {
     68:   *name = ((PetscObject) part)->type_name;
     69:   return 0;
     70: }

     72: /*@C
     73:    PetscPartitionerViewFromOptions - View from Options

     75:    Collective on PetscPartitioner

     77:    Input Parameters:
     78: +  A - the PetscPartitioner object
     79: .  obj - Optional object
     80: -  name - command line option

     82:    Level: intermediate
     83: .seealso:  PetscPartitionerView(), PetscObjectViewFromOptions()
     84: @*/
     85: PetscErrorCode PetscPartitionerViewFromOptions(PetscPartitioner A,PetscObject obj,const char name[])
     86: {
     88:   PetscObjectViewFromOptions((PetscObject)A,obj,name);
     89:   return 0;
     90: }

     92: /*@
     93:   PetscPartitionerView - Views a PetscPartitioner

     95:   Collective on PetscPartitioner

     97:   Input Parameters:
     98: + part - the PetscPartitioner object to view
     99: - v    - the viewer

    101:   Level: developer

    103: .seealso: PetscPartitionerDestroy()
    104: @*/
    105: PetscErrorCode PetscPartitionerView(PetscPartitioner part, PetscViewer v)
    106: {
    107:   PetscMPIInt    size;
    108:   PetscBool      isascii;

    111:   if (!v) PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject) part), &v);
    112:   PetscObjectTypeCompare((PetscObject) v, PETSCVIEWERASCII, &isascii);
    113:   if (isascii) {
    114:     MPI_Comm_size(PetscObjectComm((PetscObject) part), &size);
    115:     PetscViewerASCIIPrintf(v, "Graph Partitioner: %d MPI Process%s\n", size, size > 1 ? "es" : "");
    116:     PetscViewerASCIIPrintf(v, "  type: %s\n", ((PetscObject)part)->type_name);
    117:     PetscViewerASCIIPrintf(v, "  edge cut: %D\n", part->edgeCut);
    118:     PetscViewerASCIIPrintf(v, "  balance: %.2g\n", part->balance);
    119:     PetscViewerASCIIPrintf(v, "  use vertex weights: %d\n", part->usevwgt);
    120:   }
    121:   if (part->ops->view) (*part->ops->view)(part, v);
    122:   return 0;
    123: }

    125: static PetscErrorCode PetscPartitionerGetDefaultType(MPI_Comm comm, const char **defaultType)
    126: {
    127:   PetscMPIInt    size;

    129:   MPI_Comm_size(comm, &size);
    130:   if (size == 1) {
    131:     *defaultType = PETSCPARTITIONERSIMPLE;
    132:   } else {
    133: #if defined(PETSC_HAVE_PARMETIS)
    134:     *defaultType = PETSCPARTITIONERPARMETIS;
    135: #elif defined(PETSC_HAVE_PTSCOTCH)
    136:     *defaultType = PETSCPARTITIONERPTSCOTCH;
    137: #elif defined(PETSC_HAVE_CHACO)
    138:     *defaultType = PETSCPARTITIONERCHACO;
    139: #else
    140:     *defaultType = PETSCPARTITIONERSIMPLE;
    141: #endif
    142:   }
    143:   return 0;
    144: }

    146: /*@
    147:   PetscPartitionerSetFromOptions - sets parameters in a PetscPartitioner from the options database

    149:   Collective on PetscPartitioner

    151:   Input Parameter:
    152: . part - the PetscPartitioner object to set options for

    154:   Options Database Keys:
    155: +  -petscpartitioner_type <type> - Sets the PetscPartitioner type; use -help for a list of available types
    156: .  -petscpartitioner_use_vertex_weights - Uses weights associated with the graph vertices
    157: -  -petscpartitioner_view_graph - View the graph each time PetscPartitionerPartition is called. Viewer can be customized, see PetscOptionsGetViewer()

    159:   Level: developer

    161: .seealso: PetscPartitionerView(), PetscPartitionerSetType(), PetscPartitionerPartition()
    162: @*/
    163: PetscErrorCode PetscPartitionerSetFromOptions(PetscPartitioner part)
    164: {
    165:   const char    *currentType = NULL;
    166:   char           name[256];
    167:   PetscBool      flg;

    171:   PetscObjectOptionsBegin((PetscObject) part);
    172:   PetscPartitionerGetType(part, &currentType);
    173:   PetscOptionsFList("-petscpartitioner_type", "Graph partitioner", "PetscPartitionerSetType", PetscPartitionerList, currentType, name, sizeof(name), &flg);
    174:   if (flg) {
    175:     PetscPartitionerSetType(part, name);
    176:   }
    177:   PetscOptionsBool("-petscpartitioner_use_vertex_weights","Use vertex weights","",part->usevwgt,&part->usevwgt,NULL);
    178:   if (part->ops->setfromoptions) {
    179:     (*part->ops->setfromoptions)(PetscOptionsObject,part);
    180:   }
    181:   PetscViewerDestroy(&part->viewer);
    182:   PetscViewerDestroy(&part->viewerGraph);
    183:   PetscOptionsGetViewer(((PetscObject) part)->comm, ((PetscObject) part)->options, ((PetscObject) part)->prefix, "-petscpartitioner_view", &part->viewer, NULL, NULL);
    184:   PetscOptionsGetViewer(((PetscObject) part)->comm, ((PetscObject) part)->options, ((PetscObject) part)->prefix, "-petscpartitioner_view_graph", &part->viewerGraph, NULL, &part->viewGraph);
    185:   /* process any options handlers added with PetscObjectAddOptionsHandler() */
    186:   PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject) part);
    187:   PetscOptionsEnd();
    188:   return 0;
    189: }

    191: /*@
    192:   PetscPartitionerSetUp - Construct data structures for the PetscPartitioner

    194:   Collective on PetscPartitioner

    196:   Input Parameter:
    197: . part - the PetscPartitioner object to setup

    199:   Level: developer

    201: .seealso: PetscPartitionerView(), PetscPartitionerDestroy()
    202: @*/
    203: PetscErrorCode PetscPartitionerSetUp(PetscPartitioner part)
    204: {
    206:   if (part->ops->setup) (*part->ops->setup)(part);
    207:   return 0;
    208: }

    210: /*@
    211:   PetscPartitionerReset - Resets data structures for the PetscPartitioner

    213:   Collective on PetscPartitioner

    215:   Input Parameter:
    216: . part - the PetscPartitioner object to reset

    218:   Level: developer

    220: .seealso: PetscPartitionerSetUp(), PetscPartitionerDestroy()
    221: @*/
    222: PetscErrorCode PetscPartitionerReset(PetscPartitioner part)
    223: {
    225:   if (part->ops->reset) (*part->ops->reset)(part);
    226:   return 0;
    227: }

    229: /*@
    230:   PetscPartitionerDestroy - Destroys a PetscPartitioner object

    232:   Collective on PetscPartitioner

    234:   Input Parameter:
    235: . part - the PetscPartitioner object to destroy

    237:   Level: developer

    239: .seealso: PetscPartitionerView()
    240: @*/
    241: PetscErrorCode PetscPartitionerDestroy(PetscPartitioner *part)
    242: {
    243:   if (!*part) return 0;

    246:   if (--((PetscObject)(*part))->refct > 0) {*part = NULL; return 0;}
    247:   ((PetscObject) (*part))->refct = 0;

    249:   PetscPartitionerReset(*part);

    251:   PetscViewerDestroy(&(*part)->viewer);
    252:   PetscViewerDestroy(&(*part)->viewerGraph);
    253:   if ((*part)->ops->destroy) (*(*part)->ops->destroy)(*part);
    254:   PetscHeaderDestroy(part);
    255:   return 0;
    256: }

    258: /*@
    259:   PetscPartitionerPartition - Partition a graph

    261:   Collective on PetscPartitioner

    263:   Input Parameters:
    264: + part    - The PetscPartitioner
    265: . nparts  - Number of partitions
    266: . numVertices - Number of vertices in the local part of the graph
    267: . start - row pointers for the local part of the graph (CSR style)
    268: . adjacency - adjacency list (CSR style)
    269: . vertexSection - PetscSection describing the absolute weight of each local vertex (can be NULL)
    270: - targetSection - PetscSection describing the absolute weight of each partition (can be NULL)

    272:   Output Parameters:
    273: + partSection     - The PetscSection giving the division of points by partition
    274: - partition       - The list of points by partition

    276:   Options Database:
    277: + -petscpartitioner_view - View the partitioner information
    278: - -petscpartitioner_view_graph - View the graph we are partitioning

    280:   Notes:
    281:     The chart of the vertexSection (if present) must contain [0,numVertices), with the number of dofs in the section specifying the absolute weight for each vertex.
    282:     The chart of the targetSection (if present) must contain [0,nparts), with the number of dofs in the section specifying the absolute weight for each partition. This information must be the same across processes, PETSc does not check it.

    284:   Level: developer

    286: .seealso PetscPartitionerCreate(), PetscPartitionerSetType(), PetscSectionCreate(), PetscSectionSetChart(), PetscSectionSetDof()
    287: @*/
    288: PetscErrorCode PetscPartitionerPartition(PetscPartitioner part, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection vertexSection, PetscSection targetSection, PetscSection partSection, IS *partition)
    289: {
    294:   if (numVertices && !part->noGraph) {
    298:   }
    299:   if (vertexSection) {
    300:     PetscInt s,e;

    303:     PetscSectionGetChart(vertexSection, &s, &e);
    305:   }
    306:   if (targetSection) {
    307:     PetscInt s,e;

    310:     PetscSectionGetChart(targetSection, &s, &e);
    312:   }

    316:   PetscSectionReset(partSection);
    317:   PetscSectionSetChart(partSection, 0, nparts);
    318:   if (nparts == 1) { /* quick */
    319:     PetscSectionSetDof(partSection, 0, numVertices);
    320:     ISCreateStride(PetscObjectComm((PetscObject)part),numVertices,0,1,partition);
    321:   } else {
    323:     (*part->ops->partition)(part, nparts, numVertices, start, adjacency, vertexSection, targetSection, partSection, partition);
    324:   }
    325:   PetscSectionSetUp(partSection);
    326:   if (part->viewerGraph) {
    327:     PetscViewer viewer = part->viewerGraph;
    328:     PetscBool   isascii;
    329:     PetscInt    v, i;
    330:     PetscMPIInt rank;

    332:     MPI_Comm_rank(PetscObjectComm((PetscObject) viewer), &rank);
    333:     PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &isascii);
    334:     if (isascii) {
    335:       PetscViewerASCIIPushSynchronized(viewer);
    336:       PetscViewerASCIISynchronizedPrintf(viewer, "[%d]Nv: %D\n", rank, numVertices);
    337:       for (v = 0; v < numVertices; ++v) {
    338:         const PetscInt s = start[v];
    339:         const PetscInt e = start[v+1];

    341:         PetscViewerASCIISynchronizedPrintf(viewer, "[%d]  ", rank);
    342:         for (i = s; i < e; ++i) PetscViewerASCIISynchronizedPrintf(viewer, "%D ", adjacency[i]);
    343:         PetscViewerASCIISynchronizedPrintf(viewer, "[%D-%D)\n", s, e);
    344:       }
    345:       PetscViewerFlush(viewer);
    346:       PetscViewerASCIIPopSynchronized(viewer);
    347:     }
    348:   }
    349:   if (part->viewer) {
    350:     PetscPartitionerView(part,part->viewer);
    351:   }
    352:   return 0;
    353: }

    355: /*@
    356:   PetscPartitionerCreate - Creates an empty PetscPartitioner object. The type can then be set with PetscPartitionerSetType().

    358:   Collective

    360:   Input Parameter:
    361: . comm - The communicator for the PetscPartitioner object

    363:   Output Parameter:
    364: . part - The PetscPartitioner object

    366:   Level: beginner

    368: .seealso: PetscPartitionerSetType(), PetscPartitionerDestroy()
    369: @*/
    370: PetscErrorCode PetscPartitionerCreate(MPI_Comm comm, PetscPartitioner *part)
    371: {
    372:   PetscPartitioner p;
    373:   const char       *partitionerType = NULL;

    376:   *part = NULL;
    377:   PetscPartitionerInitializePackage();

    379:   PetscHeaderCreate(p, PETSCPARTITIONER_CLASSID, "PetscPartitioner", "Graph Partitioner", "PetscPartitioner", comm, PetscPartitionerDestroy, PetscPartitionerView);
    380:   PetscPartitionerGetDefaultType(comm, &partitionerType);
    381:   PetscPartitionerSetType(p, partitionerType);

    383:   p->edgeCut = 0;
    384:   p->balance = 0.0;
    385:   p->usevwgt = PETSC_TRUE;

    387:   *part = p;
    388:   return 0;
    389: }