#include /*I "petscmat.h" I*/ #include PETSC_EXTERN PetscErrorCode MatColoringCreateBipartiteGraph(MatColoring, PetscSF *, PetscSF *); PETSC_EXTERN PetscErrorCode MatColoringTest(MatColoring mc, ISColoring coloring) { Mat m = mc->mat; PetscSF etor, etoc; PetscInt s, e; PetscInt ncolors, nrows, ncols; IS *colors; PetscInt i, j, k, l; PetscInt *staterow, *statecol, *statespread; PetscInt nindices; const PetscInt *indices; PetscInt dist = mc->dist; const PetscInt *degrees; PetscInt *stateleafrow, *stateleafcol, nleafrows, nleafcols, idx, nentries, maxcolors; MPI_Datatype itype = MPIU_INT; PetscFunctionBegin; PetscCall(MatColoringGetMaxColors(mc, &maxcolors)); /* get the communication structures and the colors */ PetscCall(MatColoringCreateBipartiteGraph(mc, &etoc, &etor)); PetscCall(ISColoringGetIS(coloring, PETSC_USE_POINTER, &ncolors, &colors)); PetscCall(PetscSFGetGraph(etor, &nrows, &nleafrows, NULL, NULL)); PetscCall(PetscSFGetGraph(etoc, &ncols, &nleafcols, NULL, NULL)); PetscCall(MatGetOwnershipRangeColumn(m, &s, &e)); PetscCall(PetscMalloc1(ncols, &statecol)); PetscCall(PetscMalloc1(nrows, &staterow)); PetscCall(PetscMalloc1(nleafcols, &stateleafcol)); PetscCall(PetscMalloc1(nleafrows, &stateleafrow)); for (l = 0; l < ncolors; l++) { if (l > maxcolors) break; for (k = 0; k < ncols; k++) statecol[k] = -1; PetscCall(ISGetLocalSize(colors[l], &nindices)); PetscCall(ISGetIndices(colors[l], &indices)); for (k = 0; k < nindices; k++) statecol[indices[k] - s] = indices[k]; PetscCall(ISRestoreIndices(colors[l], &indices)); statespread = statecol; for (k = 0; k < dist; k++) { if (k % 2 == 1) { PetscCall(PetscSFComputeDegreeBegin(etor, °rees)); PetscCall(PetscSFComputeDegreeEnd(etor, °rees)); nentries = 0; for (i = 0; i < nrows; i++) nentries += degrees[i]; idx = 0; for (i = 0; i < nrows; i++) { for (j = 0; j < degrees[i]; j++) { stateleafrow[idx] = staterow[i]; idx++; } statecol[i] = 0.; } PetscCheck(idx == nentries, PetscObjectComm((PetscObject)mc), PETSC_ERR_NOT_CONVERGED, "Bad number of entries %" PetscInt_FMT " vs %" PetscInt_FMT, idx, nentries); PetscCall(PetscLogEventBegin(MATCOLORING_Comm, mc, 0, 0, 0)); PetscCall(PetscSFReduceBegin(etoc, itype, stateleafrow, statecol, MPI_MAX)); PetscCall(PetscSFReduceEnd(etoc, itype, stateleafrow, statecol, MPI_MAX)); PetscCall(PetscLogEventEnd(MATCOLORING_Comm, mc, 0, 0, 0)); statespread = statecol; } else { PetscCall(PetscSFComputeDegreeBegin(etoc, °rees)); PetscCall(PetscSFComputeDegreeEnd(etoc, °rees)); nentries = 0; for (i = 0; i < ncols; i++) nentries += degrees[i]; idx = 0; for (i = 0; i < ncols; i++) { for (j = 0; j < degrees[i]; j++) { stateleafcol[idx] = statecol[i]; idx++; } staterow[i] = 0.; } PetscCheck(idx == nentries, PetscObjectComm((PetscObject)mc), PETSC_ERR_NOT_CONVERGED, "Bad number of entries %" PetscInt_FMT " vs %" PetscInt_FMT, idx, nentries); PetscCall(PetscLogEventBegin(MATCOLORING_Comm, mc, 0, 0, 0)); PetscCall(PetscSFReduceBegin(etor, itype, stateleafcol, staterow, MPI_MAX)); PetscCall(PetscSFReduceEnd(etor, itype, stateleafcol, staterow, MPI_MAX)); PetscCall(PetscLogEventEnd(MATCOLORING_Comm, mc, 0, 0, 0)); statespread = staterow; } } for (k = 0; k < nindices; k++) { if (statespread[indices[k] - s] != indices[k]) PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mc), "%" PetscInt_FMT " of color %" PetscInt_FMT " conflicts with %" PetscInt_FMT "\n", indices[k], l, statespread[indices[k] - s])); } PetscCall(ISRestoreIndices(colors[l], &indices)); } PetscCall(PetscFree(statecol)); PetscCall(PetscFree(staterow)); PetscCall(PetscFree(stateleafcol)); PetscCall(PetscFree(stateleafrow)); PetscCall(PetscSFDestroy(&etor)); PetscCall(PetscSFDestroy(&etoc)); PetscFunctionReturn(PETSC_SUCCESS); } PETSC_EXTERN PetscErrorCode MatISColoringTest(Mat A, ISColoring iscoloring) { PetscInt nn, c, i, j, M, N, nc, nnz, col, row; const PetscInt *cia, *cja, *cols; IS *isis; MPI_Comm comm; PetscMPIInt size; PetscBool done; PetscBT table; PetscFunctionBegin; PetscCall(ISColoringGetIS(iscoloring, PETSC_USE_POINTER, &nn, &isis)); PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); PetscCallMPI(MPI_Comm_size(comm, &size)); PetscCheck(size <= 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only support sequential matrix"); PetscCall(MatGetColumnIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &N, &cia, &cja, &done)); PetscCheck(done, PETSC_COMM_SELF, PETSC_ERR_SUP, "Ordering requires IJ"); PetscCall(MatGetSize(A, &M, NULL)); PetscCall(PetscBTCreate(M, &table)); for (c = 0; c < nn; c++) { /* for each color */ PetscCall(ISGetSize(isis[c], &nc)); if (nc <= 1) continue; PetscCall(PetscBTMemzero(M, table)); PetscCall(ISGetIndices(isis[c], &cols)); for (j = 0; j < nc; j++) { /* for each column */ col = cols[j]; nnz = cia[col + 1] - cia[col]; for (i = 0; i < nnz; i++) { row = cja[cia[col] + i]; PetscCheck(!PetscBTLookupSet(table, row), PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "color %" PetscInt_FMT ", col %" PetscInt_FMT ": row %" PetscInt_FMT " already in this color", c, col, row); } } PetscCall(ISRestoreIndices(isis[c], &cols)); } PetscCall(PetscBTDestroy(&table)); PetscCall(MatRestoreColumnIJ(A, 1, PETSC_FALSE, PETSC_TRUE, NULL, &cia, &cja, &done)); PetscFunctionReturn(PETSC_SUCCESS); }