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 8d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscPartitionerMatPartitioningGetMatPartitioning_MatPartitioning(PetscPartitioner part, MatPartitioning *mp) 9d71ae5a4SJacob Faibussowitsch { 10abe9303eSLisandro Dalcin PetscPartitioner_MatPartitioning *p = (PetscPartitioner_MatPartitioning *)part->data; 11abe9303eSLisandro Dalcin 12abe9303eSLisandro Dalcin PetscFunctionBegin; 13abe9303eSLisandro Dalcin *mp = p->mp; 143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 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 222fe279fdSBarry Smith Input Parameter: 23abe9303eSLisandro Dalcin . part - The PetscPartitioner 24abe9303eSLisandro Dalcin 252fe279fdSBarry Smith Output Parameter: 26abe9303eSLisandro Dalcin . mp - The MatPartitioning 27abe9303eSLisandro Dalcin 28abe9303eSLisandro Dalcin Level: developer 29abe9303eSLisandro Dalcin 30*a4e35b19SJacob Faibussowitsch .seealso: `DMPlexDistribute()`, `PetscPartitionerCreate()` 31abe9303eSLisandro Dalcin @*/ 32d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscPartitionerMatPartitioningGetMatPartitioning(PetscPartitioner part, MatPartitioning *mp) 33d71ae5a4SJacob Faibussowitsch { 34abe9303eSLisandro Dalcin PetscFunctionBegin; 35abe9303eSLisandro Dalcin PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 364f572ea9SToby Isaac PetscAssertPointer(mp, 2); 37cac4c232SBarry Smith PetscUseMethod(part, "PetscPartitionerMatPartitioningGetMatPartitioning_C", (PetscPartitioner, MatPartitioning *), (part, mp)); 383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 39abe9303eSLisandro Dalcin } 40abe9303eSLisandro Dalcin 41d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscPartitionerDestroy_MatPartitioning(PetscPartitioner part) 42d71ae5a4SJacob Faibussowitsch { 43abe9303eSLisandro Dalcin PetscPartitioner_MatPartitioning *p = (PetscPartitioner_MatPartitioning *)part->data; 44abe9303eSLisandro Dalcin 45abe9303eSLisandro Dalcin PetscFunctionBegin; 469566063dSJacob Faibussowitsch PetscCall(MatPartitioningDestroy(&p->mp)); 472e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)part, "PetscPartitionerMatPartitioningGetMatPartitioning_C", NULL)); 489566063dSJacob Faibussowitsch PetscCall(PetscFree(part->data)); 493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50abe9303eSLisandro Dalcin } 51abe9303eSLisandro Dalcin 52d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscPartitionerView_MatPartitioning_ASCII(PetscPartitioner part, PetscViewer viewer) 53d71ae5a4SJacob Faibussowitsch { 54abe9303eSLisandro Dalcin PetscPartitioner_MatPartitioning *p = (PetscPartitioner_MatPartitioning *)part->data; 55abe9303eSLisandro Dalcin PetscViewerFormat format; 56abe9303eSLisandro Dalcin 57abe9303eSLisandro Dalcin PetscFunctionBegin; 589566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 599566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "MatPartitioning Graph Partitioner:\n")); 609566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 619566063dSJacob Faibussowitsch if (p->mp) PetscCall(MatPartitioningView(p->mp, viewer)); 629566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 64abe9303eSLisandro Dalcin } 65abe9303eSLisandro Dalcin 66d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscPartitionerView_MatPartitioning(PetscPartitioner part, PetscViewer viewer) 67d71ae5a4SJacob Faibussowitsch { 68abe9303eSLisandro Dalcin PetscBool iascii; 69abe9303eSLisandro Dalcin 70abe9303eSLisandro Dalcin PetscFunctionBegin; 71abe9303eSLisandro Dalcin PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 72abe9303eSLisandro Dalcin PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 739566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 749566063dSJacob Faibussowitsch if (iascii) PetscCall(PetscPartitionerView_MatPartitioning_ASCII(part, viewer)); 753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 76abe9303eSLisandro Dalcin } 77abe9303eSLisandro Dalcin 78d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscPartitionerSetFromOptions_MatPartitioning(PetscPartitioner part, PetscOptionItems *PetscOptionsObject) 79d71ae5a4SJacob Faibussowitsch { 80abe9303eSLisandro Dalcin PetscPartitioner_MatPartitioning *p = (PetscPartitioner_MatPartitioning *)part->data; 81abe9303eSLisandro Dalcin 82abe9303eSLisandro Dalcin PetscFunctionBegin; 839566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)p->mp, ((PetscObject)part)->prefix)); 849566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetFromOptions(p->mp)); 853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 86abe9303eSLisandro Dalcin } 87abe9303eSLisandro Dalcin 88d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscPartitionerPartition_MatPartitioning(PetscPartitioner part, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection vertSection, PetscSection targetSection, PetscSection partSection, IS *is) 89d71ae5a4SJacob Faibussowitsch { 90abe9303eSLisandro Dalcin PetscPartitioner_MatPartitioning *p = (PetscPartitioner_MatPartitioning *)part->data; 91abe9303eSLisandro Dalcin Mat matadj; 92abe9303eSLisandro Dalcin IS is1, is2, is3; 93abe9303eSLisandro Dalcin PetscReal *tpwgts = NULL; 94abe9303eSLisandro Dalcin PetscInt numVerticesGlobal, numEdges; 95abe9303eSLisandro Dalcin PetscInt *i, *j, *vwgt = NULL; 96abe9303eSLisandro Dalcin MPI_Comm comm; 97abe9303eSLisandro Dalcin 98abe9303eSLisandro Dalcin PetscFunctionBegin; 999566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)part, &comm)); 100abe9303eSLisandro Dalcin 101abe9303eSLisandro Dalcin /* TODO: MatCreateMPIAdj should maybe take global number of ROWS */ 102abe9303eSLisandro Dalcin /* TODO: And vertex distribution in PetscPartitionerPartition_ParMetis should be done using PetscSplitOwnership */ 103abe9303eSLisandro Dalcin numVerticesGlobal = PETSC_DECIDE; 1049566063dSJacob Faibussowitsch PetscCall(PetscSplitOwnership(comm, &numVertices, &numVerticesGlobal)); 105abe9303eSLisandro Dalcin 106abe9303eSLisandro Dalcin /* copy arrays to avoid memory errors because MatMPIAdjSetPreallocation copies just pointers */ 107abe9303eSLisandro Dalcin numEdges = start[numVertices]; 1089566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numVertices + 1, &i)); 1099566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numEdges, &j)); 1109566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(i, start, numVertices + 1)); 1119566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(j, adjacency, numEdges)); 112abe9303eSLisandro Dalcin 113abe9303eSLisandro Dalcin /* construct the adjacency matrix */ 1149566063dSJacob Faibussowitsch PetscCall(MatCreateMPIAdj(comm, numVertices, numVerticesGlobal, i, j, NULL, &matadj)); 1159566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetAdjacency(p->mp, matadj)); 1169566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetNParts(p->mp, nparts)); 117abe9303eSLisandro Dalcin 118abe9303eSLisandro Dalcin /* calculate partition weights */ 119abe9303eSLisandro Dalcin if (targetSection) { 120abe9303eSLisandro Dalcin PetscReal sumt; 121abe9303eSLisandro Dalcin PetscInt p; 122abe9303eSLisandro Dalcin 123abe9303eSLisandro Dalcin sumt = 0.0; 1249566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nparts, &tpwgts)); 125abe9303eSLisandro Dalcin for (p = 0; p < nparts; ++p) { 126abe9303eSLisandro Dalcin PetscInt tpd; 127abe9303eSLisandro Dalcin 1289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(targetSection, p, &tpd)); 129abe9303eSLisandro Dalcin sumt += tpd; 130abe9303eSLisandro Dalcin tpwgts[p] = tpd; 131abe9303eSLisandro Dalcin } 132abe9303eSLisandro Dalcin if (sumt) { /* METIS/ParMETIS do not like exactly zero weight */ 133abe9303eSLisandro Dalcin for (p = 0, sumt = 0.0; p < nparts; ++p) { 134abe9303eSLisandro Dalcin tpwgts[p] = PetscMax(tpwgts[p], PETSC_SMALL); 135abe9303eSLisandro Dalcin sumt += tpwgts[p]; 136abe9303eSLisandro Dalcin } 137abe9303eSLisandro Dalcin for (p = 0; p < nparts; ++p) tpwgts[p] /= sumt; 138abe9303eSLisandro Dalcin for (p = 0, sumt = 0.0; p < nparts - 1; ++p) sumt += tpwgts[p]; 139abe9303eSLisandro Dalcin tpwgts[nparts - 1] = 1. - sumt; 140abe9303eSLisandro Dalcin } else { 1419566063dSJacob Faibussowitsch PetscCall(PetscFree(tpwgts)); 142abe9303eSLisandro Dalcin } 143abe9303eSLisandro Dalcin } 1449566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetPartitionWeights(p->mp, tpwgts)); 145abe9303eSLisandro Dalcin 146abe9303eSLisandro Dalcin /* calculate vertex weights */ 147abe9303eSLisandro Dalcin if (vertSection) { 148abe9303eSLisandro Dalcin PetscInt v; 149abe9303eSLisandro Dalcin 1509566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numVertices, &vwgt)); 15148a46eb9SPierre Jolivet for (v = 0; v < numVertices; ++v) PetscCall(PetscSectionGetDof(vertSection, v, &vwgt[v])); 152abe9303eSLisandro Dalcin } 1539566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetVertexWeights(p->mp, vwgt)); 154abe9303eSLisandro Dalcin 155abe9303eSLisandro Dalcin /* apply the partitioning */ 1569566063dSJacob Faibussowitsch PetscCall(MatPartitioningApply(p->mp, &is1)); 157abe9303eSLisandro Dalcin 158abe9303eSLisandro Dalcin /* construct the PetscSection */ 159abe9303eSLisandro Dalcin { 160abe9303eSLisandro Dalcin PetscInt v; 161abe9303eSLisandro Dalcin const PetscInt *assignment_arr; 162abe9303eSLisandro Dalcin 1639566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is1, &assignment_arr)); 1649566063dSJacob Faibussowitsch for (v = 0; v < numVertices; ++v) PetscCall(PetscSectionAddDof(partSection, assignment_arr[v], 1)); 1659566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is1, &assignment_arr)); 166abe9303eSLisandro Dalcin } 167abe9303eSLisandro Dalcin 168abe9303eSLisandro Dalcin /* convert assignment IS to global numbering IS */ 1699566063dSJacob Faibussowitsch PetscCall(ISPartitioningToNumbering(is1, &is2)); 1709566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is1)); 171abe9303eSLisandro Dalcin 172abe9303eSLisandro Dalcin /* renumber IS into local numbering */ 1739566063dSJacob Faibussowitsch PetscCall(ISOnComm(is2, PETSC_COMM_SELF, PETSC_USE_POINTER, &is1)); 1749566063dSJacob Faibussowitsch PetscCall(ISRenumber(is1, NULL, NULL, &is3)); 1759566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is1)); 1769566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is2)); 177abe9303eSLisandro Dalcin 178abe9303eSLisandro Dalcin /* invert IS */ 1799566063dSJacob Faibussowitsch PetscCall(ISSetPermutation(is3)); 1809566063dSJacob Faibussowitsch PetscCall(ISInvertPermutation(is3, numVertices, &is1)); 1819566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is3)); 182abe9303eSLisandro Dalcin 1839566063dSJacob Faibussowitsch PetscCall(MatDestroy(&matadj)); 184abe9303eSLisandro Dalcin *is = is1; 1853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 186abe9303eSLisandro Dalcin } 187abe9303eSLisandro Dalcin 188d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscPartitionerInitialize_MatPartitioning(PetscPartitioner part) 189d71ae5a4SJacob Faibussowitsch { 190abe9303eSLisandro Dalcin PetscFunctionBegin; 191abe9303eSLisandro Dalcin part->ops->view = PetscPartitionerView_MatPartitioning; 192abe9303eSLisandro Dalcin part->ops->setfromoptions = PetscPartitionerSetFromOptions_MatPartitioning; 193abe9303eSLisandro Dalcin part->ops->destroy = PetscPartitionerDestroy_MatPartitioning; 194abe9303eSLisandro Dalcin part->ops->partition = PetscPartitionerPartition_MatPartitioning; 1959566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)part, "PetscPartitionerMatPartitioningGetMatPartitioning_C", PetscPartitionerMatPartitioningGetMatPartitioning_MatPartitioning)); 1963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 197abe9303eSLisandro Dalcin } 198abe9303eSLisandro Dalcin 199abe9303eSLisandro Dalcin /*MC 200abe9303eSLisandro Dalcin PETSCPARTITIONERMATPARTITIONING = "matpartitioning" - A PetscPartitioner object 201abe9303eSLisandro Dalcin 202abe9303eSLisandro Dalcin Level: developer 203abe9303eSLisandro Dalcin 204db781477SPatrick Sanan .seealso: `PetscPartitionerType`, `PetscPartitionerCreate()`, `PetscPartitionerSetType()` 205abe9303eSLisandro Dalcin M*/ 206abe9303eSLisandro Dalcin 207d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_MatPartitioning(PetscPartitioner part) 208d71ae5a4SJacob Faibussowitsch { 209abe9303eSLisandro Dalcin PetscPartitioner_MatPartitioning *p; 210abe9303eSLisandro Dalcin 211abe9303eSLisandro Dalcin PetscFunctionBegin; 212abe9303eSLisandro Dalcin PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 2134dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&p)); 214abe9303eSLisandro Dalcin part->data = p; 2159566063dSJacob Faibussowitsch PetscCall(PetscPartitionerInitialize_MatPartitioning(part)); 2169566063dSJacob Faibussowitsch PetscCall(MatPartitioningCreate(PetscObjectComm((PetscObject)part), &p->mp)); 2173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 218abe9303eSLisandro Dalcin } 219