6 #if PETSC_VERSION_GE(3, 6, 0)
7 #include <petsc/private/matimpl.h>
9 #include <petsc-private/matimpl.h>
24 PetscBool repartition;
25 } MatPartitioning_Parmetis;
41 PetscBool freeaijwithfree;
42 PetscScalar *rowvalues;
43 PetscInt rowvalues_alloc;
46 #define CHKERRQPARMETIS(n, func) \
47 if (n == METIS_ERROR_INPUT) \
48 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_LIB, \
49 "ParMETIS error due to wrong inputs and/or options for %s", \
51 else if (n == METIS_ERROR_MEMORY) \
52 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_LIB, \
53 "ParMETIS error due to insufficient memory in %s", func); \
54 else if (n == METIS_ERROR) \
55 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_LIB, "ParMETIS general error in %s", \
58 #define PetscStackCallParmetis(func, args) \
60 PetscStackPush(#func); \
63 CHKERRQPARMETIS(status, #func); \
69 #define __FUNCT__ "MatPartitioningApply_Parmetis_MoFEM"
70 PetscErrorCode MatPartitioningApply_Parmetis_MoFEM(MatPartitioning part,
72 MatPartitioning_Parmetis *pmetis = (MatPartitioning_Parmetis *)part->data;
74 PetscInt *locals = NULL;
75 Mat mat = part->adj, amat, pmat;
80 ierr = PetscObjectTypeCompare((PetscObject)mat, MATMPIADJ, &flg);
84 PetscObjectReference((PetscObject)amat);
90 ierr = MatConvert(mat, MATMPIADJ, MAT_INITIAL_MATRIX, &amat);
92 if (amat->rmap->n > 0)
93 bs = mat->rmap->n / amat->rmap->n;
95 ierr = MatMPIAdjCreateNonemptySubcommMat(amat, &pmat);
97 ierr = MPI_Barrier(PetscObjectComm((PetscObject)part));
101 MPI_Comm pcomm, comm;
102 Mat_MPIAdj *adj = (Mat_MPIAdj *)pmat->data;
103 PetscInt *vtxdist = pmat->rmap->range;
104 PetscInt *xadj = adj->i;
105 PetscInt *adjncy = adj->j;
106 PetscInt itmp = 0, wgtflag = 0, numflag = 0, ncon = 1, nparts = part->n,
108 real_t *tpwgts, *ubvec, itr = 0.1;
111 ierr = PetscObjectGetComm((PetscObject)pmat, &pcomm);
113 #if defined(PETSC_USE_DEBUG)
117 ierr = MatGetOwnershipRange(pmat, &rstart, NULL);
119 for (
i = 0;
i < pmat->rmap->n;
i++) {
120 for (
j = xadj[
i];
j < xadj[
i + 1];
j++) {
121 if (adjncy[
j] ==
i + rstart)
123 PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,
124 "Row %d has diagonal entry; Parmetis forbids diagonal entry",
132 if (part->vertex_weights) {
136 ierr = PetscMalloc1(amat->rmap->n, &locals);
139 if (PetscLogPrintInfo) {
140 itmp = pmetis->printout;
141 pmetis->printout = 127;
143 ierr = PetscMalloc1(ncon * nparts, &tpwgts);
145 for (
i = 0;
i < ncon;
i++) {
146 for (
j = 0;
j < nparts;
j++) {
147 if (part->part_weights) {
148 tpwgts[
i * nparts +
j] = part->part_weights[
i * nparts +
j];
150 tpwgts[
i * nparts +
j] = 1. / nparts;
154 ierr = PetscMalloc1(ncon, &ubvec);
156 for (
i = 0;
i < ncon;
i++) {
161 for (
i = 1;
i < 24;
i++) {
166 ierr = MPI_Comm_dup(pcomm, &comm);
168 if (pmetis->repartition) {
169 PetscStackCallParmetis(
170 ParMETIS_V3_AdaptiveRepart,
171 ((idx_t *)vtxdist, (idx_t *)xadj, (idx_t *)adjncy,
172 (idx_t *)part->vertex_weights, (idx_t *)part->vertex_weights,
173 (idx_t *)adj->values, (idx_t *)&wgtflag, (idx_t *)&numflag,
174 (idx_t *)&ncon, (idx_t *)&nparts, tpwgts, ubvec, &itr,
175 (idx_t *)options, (idx_t *)&pmetis->cuts, (idx_t *)locals, &comm));
177 PetscStackCallParmetis(ParMETIS_V3_PartKway,
178 ((idx_t *)vtxdist, (idx_t *)xadj, (idx_t *)adjncy,
179 (idx_t *)part->vertex_weights,
180 (idx_t *)adj->values, (idx_t *)&wgtflag,
181 (idx_t *)&numflag, (idx_t *)&ncon,
182 (idx_t *)&nparts, tpwgts, ubvec, (idx_t *)options,
183 (idx_t *)&pmetis->cuts, (idx_t *)locals, &comm));
185 ierr = MPI_Comm_free(&comm);
188 ierr = PetscFree(tpwgts);
190 ierr = PetscFree(ubvec);
192 if (PetscLogPrintInfo)
193 pmetis->printout = itmp;
197 PetscInt
i,
j, *newlocals;
198 ierr = PetscMalloc1(bs * amat->rmap->n, &newlocals);
200 for (
i = 0;
i < amat->rmap->n;
i++) {
201 for (
j = 0;
j < bs;
j++) {
202 newlocals[bs *
i +
j] = locals[
i];
205 ierr = PetscFree(locals);
208 ISCreateGeneral(PetscObjectComm((PetscObject)part), bs * amat->rmap->n,
209 newlocals, PETSC_OWN_POINTER, partitioning);
212 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)part), amat->rmap->n,
213 locals, PETSC_OWN_POINTER, partitioning);
217 ierr = MatDestroy(&pmat);
219 ierr = MatDestroy(&amat);