Actual source code: partsimple.c
petsc-3.14.6 2021-03-30
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: }