Actual source code: partsimple.c

petsc-3.14.6 2021-03-30
Report Typos and Errors
  1: #include <petscvec.h>
  2: #include <petsc/private/partitionerimpl.h>

  4: typedef struct {
  5:   PetscInt dummy;
  6: } PetscPartitioner_Simple;

  8: static PetscErrorCode PetscPartitionerDestroy_Simple(PetscPartitioner part)
  9: {

 13:   PetscFree(part->data);
 14:   return(0);
 15: }

 17: static PetscErrorCode PetscPartitionerView_Simple_ASCII(PetscPartitioner part, PetscViewer viewer)
 18: {
 20:   return(0);
 21: }

 23: static PetscErrorCode PetscPartitionerView_Simple(PetscPartitioner part, PetscViewer viewer)
 24: {
 25:   PetscBool      iascii;

 31:   PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);
 32:   if (iascii) {PetscPartitionerView_Simple_ASCII(part, viewer);}
 33:   return(0);
 34: }

 36: static PetscErrorCode PetscPartitionerPartition_Simple(PetscPartitioner part, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection vertSection, PetscSection targetSection, PetscSection partSection, IS *partition)
 37: {
 38:   MPI_Comm       comm;
 39:   PetscInt       np, *tpwgts = NULL, sumw = 0, numVerticesGlobal  = 0;
 40:   PetscMPIInt    size;

 44:   if (vertSection) { PetscInfo(part,"PETSCPARTITIONERSIMPLE ignores vertex weights\n"); }
 45:   comm = PetscObjectComm((PetscObject)part);
 46:   MPI_Comm_size(comm,&size);
 47:   if (targetSection) {
 48:     MPIU_Allreduce(&numVertices, &numVerticesGlobal, 1, MPIU_INT, MPI_SUM, comm);
 49:     PetscCalloc1(nparts,&tpwgts);
 50:     for (np = 0; np < nparts; ++np) {
 51:       PetscSectionGetDof(targetSection,np,&tpwgts[np]);
 52:       sumw += tpwgts[np];
 53:     }
 54:     if (sumw) {
 55:       PetscInt m,mp;
 56:       for (np = 0; np < nparts; ++np) tpwgts[np] = (tpwgts[np]*numVerticesGlobal)/sumw;
 57:       for (np = 0, m = -1, mp = 0, sumw = 0; np < nparts; ++np) {
 58:         if (m < tpwgts[np]) { m = tpwgts[np]; mp = np; }
 59:         sumw += tpwgts[np];
 60:       }
 61:       if (sumw != numVerticesGlobal) tpwgts[mp] += numVerticesGlobal - sumw;
 62:     }
 63:     if (!sumw) {PetscFree(tpwgts);}
 64:   }

 66:   ISCreateStride(PETSC_COMM_SELF, numVertices, 0, 1, partition);
 67:   if (size == 1) {
 68:     if (tpwgts) {
 69:       for (np = 0; np < nparts; ++np) {
 70:         PetscSectionSetDof(partSection, np, tpwgts[np]);
 71:       }
 72:     } else {
 73:       for (np = 0; np < nparts; ++np) {
 74:         PetscSectionSetDof(partSection, np, numVertices/nparts + ((numVertices % nparts) > np));
 75:       }
 76:     }
 77:   } else {
 78:     if (tpwgts) {
 79:       Vec         v;
 80:       PetscScalar *array;
 81:       PetscInt    st,j;
 82:       PetscMPIInt rank;

 84:       VecCreate(comm,&v);
 85:       VecSetSizes(v,numVertices,numVerticesGlobal);
 86:       VecSetType(v,VECSTANDARD);
 87:       MPI_Comm_rank(comm,&rank);
 88:       for (np = 0,st = 0; np < nparts; ++np) {
 89:         if (rank == np || (rank == size-1 && size < nparts && np >= size)) {
 90:           for (j = 0; j < tpwgts[np]; j++) {
 91:             VecSetValue(v,st+j,np,INSERT_VALUES);
 92:           }
 93:         }
 94:         st += tpwgts[np];
 95:       }
 96:       VecAssemblyBegin(v);
 97:       VecAssemblyEnd(v);
 98:       VecGetArray(v,&array);
 99:       for (j = 0; j < numVertices; ++j) {
100:         PetscSectionAddDof(partSection,PetscRealPart(array[j]),1);
101:       }
102:       VecRestoreArray(v,&array);
103:       VecDestroy(&v);
104:     } else {
105:       PetscMPIInt rank;
106:       PetscInt nvGlobal, *offsets, myFirst, myLast;

108:       PetscMalloc1(size+1,&offsets);
109:       offsets[0] = 0;
110:       MPI_Allgather(&numVertices,1,MPIU_INT,&offsets[1],1,MPIU_INT,comm);
111:       for (np = 2; np <= size; np++) {
112:         offsets[np] += offsets[np-1];
113:       }
114:       nvGlobal = offsets[size];
115:       MPI_Comm_rank(comm,&rank);
116:       myFirst = offsets[rank];
117:       myLast  = offsets[rank + 1] - 1;
118:       PetscFree(offsets);
119:       if (numVertices) {
120:         PetscInt firstPart = 0, firstLargePart = 0;
121:         PetscInt lastPart = 0, lastLargePart = 0;
122:         PetscInt rem = nvGlobal % nparts;
123:         PetscInt pSmall = nvGlobal/nparts;
124:         PetscInt pBig = nvGlobal/nparts + 1;

126:         if (rem) {
127:           firstLargePart = myFirst / pBig;
128:           lastLargePart  = myLast  / pBig;

130:           if (firstLargePart < rem) {
131:             firstPart = firstLargePart;
132:           } else {
133:             firstPart = rem + (myFirst - (rem * pBig)) / pSmall;
134:           }
135:           if (lastLargePart < rem) {
136:             lastPart = lastLargePart;
137:           } else {
138:             lastPart = rem + (myLast - (rem * pBig)) / pSmall;
139:           }
140:         } else {
141:           firstPart = myFirst / (nvGlobal/nparts);
142:           lastPart  = myLast  / (nvGlobal/nparts);
143:         }

145:         for (np = firstPart; np <= lastPart; np++) {
146:           PetscInt PartStart =  np    * (nvGlobal/nparts) + PetscMin(nvGlobal % nparts,np);
147:           PetscInt PartEnd   = (np+1) * (nvGlobal/nparts) + PetscMin(nvGlobal % nparts,np+1);

149:           PartStart = PetscMax(PartStart,myFirst);
150:           PartEnd   = PetscMin(PartEnd,myLast+1);
151:           PetscSectionSetDof(partSection,np,PartEnd-PartStart);
152:         }
153:       }
154:     }
155:   }
156:   PetscFree(tpwgts);
157:   return(0);
158: }

160: static PetscErrorCode PetscPartitionerInitialize_Simple(PetscPartitioner part)
161: {
163:   part->noGraph        = PETSC_TRUE;
164:   part->ops->view      = PetscPartitionerView_Simple;
165:   part->ops->destroy   = PetscPartitionerDestroy_Simple;
166:   part->ops->partition = PetscPartitionerPartition_Simple;
167:   return(0);
168: }

170: /*MC
171:   PETSCPARTITIONERSIMPLE = "simple" - A PetscPartitioner object

173:   Level: intermediate

175: .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType()
176: M*/

178: PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_Simple(PetscPartitioner part)
179: {
180:   PetscPartitioner_Simple *p;
181:   PetscErrorCode           ierr;

185:   PetscNewLog(part, &p);
186:   part->data = p;

188:   PetscPartitionerInitialize_Simple(part);
189:   return(0);
190: }