#include #include #include /* MatGetOrdering_METISND - Find the nested dissection ordering of a given matrix. */ PETSC_INTERN PetscErrorCode MatGetOrdering_METISND(Mat mat, MatOrderingType type, IS *row, IS *col) { PetscInt i, j, iptr, ival, nrow, *xadj, *adjncy, *perm, *iperm; const PetscInt *ia, *ja; int status; Mat B = NULL; idx_t options[METIS_NOPTIONS]; PetscBool done; PetscFunctionBegin; PetscCall(MatGetRowIJ(mat, 0, PETSC_TRUE, PETSC_TRUE, &nrow, &ia, &ja, &done)); if (!done) { PetscCall(MatConvert(mat, MATSEQAIJ, MAT_INITIAL_MATRIX, &B)); PetscCall(MatGetRowIJ(B, 0, PETSC_TRUE, PETSC_TRUE, &nrow, &ia, &ja, &done)); } METIS_SetDefaultOptions(options); options[METIS_OPTION_NUMBERING] = 0; PetscOptionsBegin(PetscObjectComm((PetscObject)mat), ((PetscObject)mat)->prefix, "METISND Options", "Mat"); ival = (PetscInt)options[METIS_OPTION_NSEPS]; PetscCall(PetscOptionsInt("-mat_ordering_metisnd_nseps", "number of different separators per level", "None", ival, &ival, NULL)); options[METIS_OPTION_NSEPS] = (idx_t)ival; ival = (PetscInt)options[METIS_OPTION_NITER]; PetscCall(PetscOptionsInt("-mat_ordering_metisnd_niter", "number of refinement iterations", "None", ival, &ival, NULL)); options[METIS_OPTION_NITER] = (idx_t)ival; ival = (PetscInt)options[METIS_OPTION_UFACTOR]; PetscCall(PetscOptionsInt("-mat_ordering_metisnd_ufactor", "maximum allowed imbalance", "None", ival, &ival, NULL)); options[METIS_OPTION_UFACTOR] = (idx_t)ival; ival = (PetscInt)options[METIS_OPTION_PFACTOR]; PetscCall(PetscOptionsInt("-mat_ordering_metisnd_pfactor", "minimum degree of vertices that will be ordered last", "None", ival, &ival, NULL)); options[METIS_OPTION_PFACTOR] = (idx_t)ival; PetscOptionsEnd(); PetscCall(PetscMalloc4(nrow + 1, &xadj, ia[nrow], &adjncy, nrow, &perm, nrow, &iperm)); /* The adjacency list of a vertex should not contain the vertex itself. */ iptr = 0; xadj[iptr] = 0; for (j = 0; j < nrow; j++) { for (i = ia[j]; i < ia[j + 1]; i++) { if (ja[i] != j) adjncy[iptr++] = ja[i]; } xadj[j + 1] = iptr; } status = METIS_NodeND(&nrow, (idx_t *)xadj, (idx_t *)adjncy, NULL, options, (idx_t *)perm, (idx_t *)iperm); switch (status) { case METIS_OK: break; case METIS_ERROR: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_LIB, "METIS returned with an unspecified error"); case METIS_ERROR_INPUT: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_LIB, "METIS received an invalid input"); case METIS_ERROR_MEMORY: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_MEM, "METIS could not compute ordering"); default: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_LIB, "Unexpected return value"); } if (B) { PetscCall(MatRestoreRowIJ(B, 0, PETSC_TRUE, PETSC_TRUE, NULL, &ia, &ja, &done)); PetscCall(MatDestroy(&B)); } else { PetscCall(MatRestoreRowIJ(mat, 0, PETSC_TRUE, PETSC_TRUE, NULL, &ia, &ja, &done)); } PetscCall(ISCreateGeneral(PETSC_COMM_SELF, nrow, perm, PETSC_COPY_VALUES, row)); PetscCall(ISCreateGeneral(PETSC_COMM_SELF, nrow, perm, PETSC_COPY_VALUES, col)); PetscCall(PetscFree4(xadj, adjncy, perm, iperm)); PetscFunctionReturn(PETSC_SUCCESS); }