xref: /petsc/src/dm/partitioner/impls/matpart/partmatpart.c (revision cac4c232dc4f93991e342196e27ef7b0655dac7b)
1abe9303eSLisandro Dalcin #include <petscmat.h>
2abe9303eSLisandro Dalcin #include <petsc/private/partitionerimpl.h>   /*I      "petscpartitioner.h"   I*/
3abe9303eSLisandro Dalcin 
4abe9303eSLisandro Dalcin typedef struct {
5abe9303eSLisandro Dalcin   MatPartitioning mp;
6abe9303eSLisandro Dalcin } PetscPartitioner_MatPartitioning;
7abe9303eSLisandro Dalcin 
8abe9303eSLisandro Dalcin static PetscErrorCode PetscPartitionerMatPartitioningGetMatPartitioning_MatPartitioning(PetscPartitioner part, MatPartitioning *mp)
9abe9303eSLisandro Dalcin {
10abe9303eSLisandro Dalcin   PetscPartitioner_MatPartitioning  *p = (PetscPartitioner_MatPartitioning *) part->data;
11abe9303eSLisandro Dalcin 
12abe9303eSLisandro Dalcin   PetscFunctionBegin;
13abe9303eSLisandro Dalcin   *mp = p->mp;
14abe9303eSLisandro Dalcin   PetscFunctionReturn(0);
15abe9303eSLisandro Dalcin }
16abe9303eSLisandro Dalcin 
17abe9303eSLisandro Dalcin /*@C
18abe9303eSLisandro Dalcin   PetscPartitionerMatPartitioningGetMatPartitioning - Get a MatPartitioning instance wrapped by this PetscPartitioner.
19abe9303eSLisandro Dalcin 
20abe9303eSLisandro Dalcin   Not Collective
21abe9303eSLisandro Dalcin 
22abe9303eSLisandro Dalcin   Input Parameters:
23abe9303eSLisandro Dalcin . part     - The PetscPartitioner
24abe9303eSLisandro Dalcin 
25abe9303eSLisandro Dalcin   Output Parameters:
26abe9303eSLisandro Dalcin . mp       - The MatPartitioning
27abe9303eSLisandro Dalcin 
28abe9303eSLisandro Dalcin   Level: developer
29abe9303eSLisandro Dalcin 
30abe9303eSLisandro Dalcin .seealso DMPlexDistribute(), PetscPartitionerCreate()
31abe9303eSLisandro Dalcin @*/
32abe9303eSLisandro Dalcin PetscErrorCode PetscPartitionerMatPartitioningGetMatPartitioning(PetscPartitioner part, MatPartitioning *mp)
33abe9303eSLisandro Dalcin {
34abe9303eSLisandro Dalcin   PetscFunctionBegin;
35abe9303eSLisandro Dalcin   PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1);
36abe9303eSLisandro Dalcin   PetscValidPointer(mp, 2);
37*cac4c232SBarry Smith   PetscUseMethod(part,"PetscPartitionerMatPartitioningGetMatPartitioning_C",(PetscPartitioner,MatPartitioning*),(part,mp));
38abe9303eSLisandro Dalcin   PetscFunctionReturn(0);
39abe9303eSLisandro Dalcin }
40abe9303eSLisandro Dalcin 
41abe9303eSLisandro Dalcin static PetscErrorCode PetscPartitionerDestroy_MatPartitioning(PetscPartitioner part)
42abe9303eSLisandro Dalcin {
43abe9303eSLisandro Dalcin   PetscPartitioner_MatPartitioning  *p = (PetscPartitioner_MatPartitioning *) part->data;
44abe9303eSLisandro Dalcin 
45abe9303eSLisandro Dalcin   PetscFunctionBegin;
469566063dSJacob Faibussowitsch   PetscCall(MatPartitioningDestroy(&p->mp));
479566063dSJacob Faibussowitsch   PetscCall(PetscFree(part->data));
48abe9303eSLisandro Dalcin   PetscFunctionReturn(0);
49abe9303eSLisandro Dalcin }
50abe9303eSLisandro Dalcin 
51abe9303eSLisandro Dalcin static PetscErrorCode PetscPartitionerView_MatPartitioning_ASCII(PetscPartitioner part, PetscViewer viewer)
52abe9303eSLisandro Dalcin {
53abe9303eSLisandro Dalcin   PetscPartitioner_MatPartitioning  *p = (PetscPartitioner_MatPartitioning *) part->data;
54abe9303eSLisandro Dalcin   PetscViewerFormat                 format;
55abe9303eSLisandro Dalcin 
56abe9303eSLisandro Dalcin   PetscFunctionBegin;
579566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
589566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "MatPartitioning Graph Partitioner:\n"));
599566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushTab(viewer));
609566063dSJacob Faibussowitsch   if (p->mp) PetscCall(MatPartitioningView(p->mp, viewer));
619566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopTab(viewer));
62abe9303eSLisandro Dalcin   PetscFunctionReturn(0);
63abe9303eSLisandro Dalcin }
64abe9303eSLisandro Dalcin 
65abe9303eSLisandro Dalcin static PetscErrorCode PetscPartitionerView_MatPartitioning(PetscPartitioner part, PetscViewer viewer)
66abe9303eSLisandro Dalcin {
67abe9303eSLisandro Dalcin   PetscBool      iascii;
68abe9303eSLisandro Dalcin 
69abe9303eSLisandro Dalcin   PetscFunctionBegin;
70abe9303eSLisandro Dalcin   PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1);
71abe9303eSLisandro Dalcin   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
729566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii));
739566063dSJacob Faibussowitsch   if (iascii) PetscCall(PetscPartitionerView_MatPartitioning_ASCII(part, viewer));
74abe9303eSLisandro Dalcin   PetscFunctionReturn(0);
75abe9303eSLisandro Dalcin }
76abe9303eSLisandro Dalcin 
77abe9303eSLisandro Dalcin static PetscErrorCode PetscPartitionerSetFromOptions_MatPartitioning(PetscOptionItems *PetscOptionsObject, PetscPartitioner part)
78abe9303eSLisandro Dalcin {
79abe9303eSLisandro Dalcin   PetscPartitioner_MatPartitioning  *p = (PetscPartitioner_MatPartitioning *) part->data;
80abe9303eSLisandro Dalcin 
81abe9303eSLisandro Dalcin   PetscFunctionBegin;
829566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)p->mp,((PetscObject)part)->prefix));
839566063dSJacob Faibussowitsch   PetscCall(MatPartitioningSetFromOptions(p->mp));
84abe9303eSLisandro Dalcin   PetscFunctionReturn(0);
85abe9303eSLisandro Dalcin }
86abe9303eSLisandro Dalcin 
87abe9303eSLisandro Dalcin static PetscErrorCode PetscPartitionerPartition_MatPartitioning(PetscPartitioner part, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection vertSection, PetscSection targetSection, PetscSection partSection, IS *is)
88abe9303eSLisandro Dalcin {
89abe9303eSLisandro Dalcin   PetscPartitioner_MatPartitioning  *p = (PetscPartitioner_MatPartitioning *) part->data;
90abe9303eSLisandro Dalcin   Mat                               matadj;
91abe9303eSLisandro Dalcin   IS                                is1, is2, is3;
92abe9303eSLisandro Dalcin   PetscReal                         *tpwgts = NULL;
93abe9303eSLisandro Dalcin   PetscInt                          numVerticesGlobal, numEdges;
94abe9303eSLisandro Dalcin   PetscInt                          *i, *j, *vwgt = NULL;
95abe9303eSLisandro Dalcin   MPI_Comm                          comm;
96abe9303eSLisandro Dalcin 
97abe9303eSLisandro Dalcin   PetscFunctionBegin;
989566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)part, &comm));
99abe9303eSLisandro Dalcin 
100abe9303eSLisandro Dalcin   /* TODO: MatCreateMPIAdj should maybe take global number of ROWS */
101abe9303eSLisandro Dalcin   /* TODO: And vertex distribution in PetscPartitionerPartition_ParMetis should be done using PetscSplitOwnership */
102abe9303eSLisandro Dalcin   numVerticesGlobal = PETSC_DECIDE;
1039566063dSJacob Faibussowitsch   PetscCall(PetscSplitOwnership(comm, &numVertices, &numVerticesGlobal));
104abe9303eSLisandro Dalcin 
105abe9303eSLisandro Dalcin   /* copy arrays to avoid memory errors because MatMPIAdjSetPreallocation copies just pointers */
106abe9303eSLisandro Dalcin   numEdges = start[numVertices];
1079566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(numVertices+1, &i));
1089566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(numEdges, &j));
1099566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(i, start, numVertices+1));
1109566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(j, adjacency, numEdges));
111abe9303eSLisandro Dalcin 
112abe9303eSLisandro Dalcin   /* construct the adjacency matrix */
1139566063dSJacob Faibussowitsch   PetscCall(MatCreateMPIAdj(comm, numVertices, numVerticesGlobal, i, j, NULL, &matadj));
1149566063dSJacob Faibussowitsch   PetscCall(MatPartitioningSetAdjacency(p->mp, matadj));
1159566063dSJacob Faibussowitsch   PetscCall(MatPartitioningSetNParts(p->mp, nparts));
116abe9303eSLisandro Dalcin 
117abe9303eSLisandro Dalcin   /* calculate partition weights */
118abe9303eSLisandro Dalcin   if (targetSection) {
119abe9303eSLisandro Dalcin     PetscReal sumt;
120abe9303eSLisandro Dalcin     PetscInt  p;
121abe9303eSLisandro Dalcin 
122abe9303eSLisandro Dalcin     sumt = 0.0;
1239566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nparts,&tpwgts));
124abe9303eSLisandro Dalcin     for (p = 0; p < nparts; ++p) {
125abe9303eSLisandro Dalcin       PetscInt tpd;
126abe9303eSLisandro Dalcin 
1279566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(targetSection,p,&tpd));
128abe9303eSLisandro Dalcin       sumt += tpd;
129abe9303eSLisandro Dalcin       tpwgts[p] = tpd;
130abe9303eSLisandro Dalcin     }
131abe9303eSLisandro Dalcin     if (sumt) { /* METIS/ParMETIS do not like exactly zero weight */
132abe9303eSLisandro Dalcin       for (p = 0, sumt = 0.0; p < nparts; ++p) {
133abe9303eSLisandro Dalcin         tpwgts[p] = PetscMax(tpwgts[p],PETSC_SMALL);
134abe9303eSLisandro Dalcin         sumt += tpwgts[p];
135abe9303eSLisandro Dalcin       }
136abe9303eSLisandro Dalcin       for (p = 0; p < nparts; ++p) tpwgts[p] /= sumt;
137abe9303eSLisandro Dalcin       for (p = 0, sumt = 0.0; p < nparts-1; ++p) sumt += tpwgts[p];
138abe9303eSLisandro Dalcin       tpwgts[nparts - 1] = 1. - sumt;
139abe9303eSLisandro Dalcin     } else {
1409566063dSJacob Faibussowitsch       PetscCall(PetscFree(tpwgts));
141abe9303eSLisandro Dalcin     }
142abe9303eSLisandro Dalcin   }
1439566063dSJacob Faibussowitsch   PetscCall(MatPartitioningSetPartitionWeights(p->mp, tpwgts));
144abe9303eSLisandro Dalcin 
145abe9303eSLisandro Dalcin   /* calculate vertex weights */
146abe9303eSLisandro Dalcin   if (vertSection) {
147abe9303eSLisandro Dalcin     PetscInt v;
148abe9303eSLisandro Dalcin 
1499566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(numVertices,&vwgt));
150abe9303eSLisandro Dalcin     for (v = 0; v < numVertices; ++v) {
1519566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(vertSection, v, &vwgt[v]));
152abe9303eSLisandro Dalcin     }
153abe9303eSLisandro Dalcin   }
1549566063dSJacob Faibussowitsch   PetscCall(MatPartitioningSetVertexWeights(p->mp, vwgt));
155abe9303eSLisandro Dalcin 
156abe9303eSLisandro Dalcin   /* apply the partitioning */
1579566063dSJacob Faibussowitsch   PetscCall(MatPartitioningApply(p->mp, &is1));
158abe9303eSLisandro Dalcin 
159abe9303eSLisandro Dalcin   /* construct the PetscSection */
160abe9303eSLisandro Dalcin   {
161abe9303eSLisandro Dalcin     PetscInt v;
162abe9303eSLisandro Dalcin     const PetscInt *assignment_arr;
163abe9303eSLisandro Dalcin 
1649566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(is1, &assignment_arr));
1659566063dSJacob Faibussowitsch     for (v = 0; v < numVertices; ++v) PetscCall(PetscSectionAddDof(partSection, assignment_arr[v], 1));
1669566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(is1, &assignment_arr));
167abe9303eSLisandro Dalcin   }
168abe9303eSLisandro Dalcin 
169abe9303eSLisandro Dalcin   /* convert assignment IS to global numbering IS */
1709566063dSJacob Faibussowitsch   PetscCall(ISPartitioningToNumbering(is1, &is2));
1719566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is1));
172abe9303eSLisandro Dalcin 
173abe9303eSLisandro Dalcin   /* renumber IS into local numbering */
1749566063dSJacob Faibussowitsch   PetscCall(ISOnComm(is2, PETSC_COMM_SELF, PETSC_USE_POINTER, &is1));
1759566063dSJacob Faibussowitsch   PetscCall(ISRenumber(is1, NULL, NULL, &is3));
1769566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is1));
1779566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is2));
178abe9303eSLisandro Dalcin 
179abe9303eSLisandro Dalcin   /* invert IS */
1809566063dSJacob Faibussowitsch   PetscCall(ISSetPermutation(is3));
1819566063dSJacob Faibussowitsch   PetscCall(ISInvertPermutation(is3, numVertices, &is1));
1829566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is3));
183abe9303eSLisandro Dalcin 
1849566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&matadj));
185abe9303eSLisandro Dalcin   *is = is1;
186abe9303eSLisandro Dalcin   PetscFunctionReturn(0);
187abe9303eSLisandro Dalcin }
188abe9303eSLisandro Dalcin 
189abe9303eSLisandro Dalcin static PetscErrorCode PetscPartitionerInitialize_MatPartitioning(PetscPartitioner part)
190abe9303eSLisandro Dalcin {
191abe9303eSLisandro Dalcin   PetscFunctionBegin;
192abe9303eSLisandro Dalcin   part->ops->view           = PetscPartitionerView_MatPartitioning;
193abe9303eSLisandro Dalcin   part->ops->setfromoptions = PetscPartitionerSetFromOptions_MatPartitioning;
194abe9303eSLisandro Dalcin   part->ops->destroy        = PetscPartitionerDestroy_MatPartitioning;
195abe9303eSLisandro Dalcin   part->ops->partition      = PetscPartitionerPartition_MatPartitioning;
1969566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)part,"PetscPartitionerMatPartitioningGetMatPartitioning_C",PetscPartitionerMatPartitioningGetMatPartitioning_MatPartitioning));
197abe9303eSLisandro Dalcin   PetscFunctionReturn(0);
198abe9303eSLisandro Dalcin }
199abe9303eSLisandro Dalcin 
200abe9303eSLisandro Dalcin /*MC
201abe9303eSLisandro Dalcin   PETSCPARTITIONERMATPARTITIONING = "matpartitioning" - A PetscPartitioner object
202abe9303eSLisandro Dalcin 
203abe9303eSLisandro Dalcin   Level: developer
204abe9303eSLisandro Dalcin 
205abe9303eSLisandro Dalcin .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType()
206abe9303eSLisandro Dalcin M*/
207abe9303eSLisandro Dalcin 
208abe9303eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_MatPartitioning(PetscPartitioner part)
209abe9303eSLisandro Dalcin {
210abe9303eSLisandro Dalcin   PetscPartitioner_MatPartitioning  *p;
211abe9303eSLisandro Dalcin 
212abe9303eSLisandro Dalcin   PetscFunctionBegin;
213abe9303eSLisandro Dalcin   PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1);
2149566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(part, &p));
215abe9303eSLisandro Dalcin   part->data = p;
2169566063dSJacob Faibussowitsch   PetscCall(PetscPartitionerInitialize_MatPartitioning(part));
2179566063dSJacob Faibussowitsch   PetscCall(MatPartitioningCreate(PetscObjectComm((PetscObject)part), &p->mp));
218abe9303eSLisandro Dalcin   PetscFunctionReturn(0);
219abe9303eSLisandro Dalcin }
220