Date: 2026-05-01T06:11:55+00:00

Actual source code: valid.c

      1: #include <petsc/private/matimpl.h>
      2: #include <petscsf.h>

      4: PETSC_EXTERN PetscErrorCode MatColoringCreateBipartiteGraph(MatColoring, PetscSF *, PetscSF *);

      6: PETSC_EXTERN PetscErrorCode MatColoringTest(MatColoring mc, ISColoring coloring)
      7: {
      8:   Mat             m = mc->mat;
      9:   PetscSF         etor, etoc;
     10:   PetscInt        s, e;
     11:   PetscInt        ncolors, nrows, ncols;
     12:   IS             *colors;
     13:   PetscInt        i, j, k, l;
     14:   PetscInt       *staterow, *statecol, *statespread;
     15:   PetscInt        nindices;
     16:   const PetscInt *indices;
     17:   PetscInt        dist = mc->dist;
     18:   const PetscInt *degrees;
     19:   PetscInt       *stateleafrow, *stateleafcol, nleafrows, nleafcols, idx, nentries, maxcolors;
     20:   MPI_Datatype    itype = MPIU_INT;

     22:   PetscFunctionBegin;
     23:   PetscCall(MatColoringGetMaxColors(mc, &maxcolors));
     24:   /* get the communication structures and the colors */
     25:   PetscCall(MatColoringCreateBipartiteGraph(mc, &etoc, &etor));
     26:   PetscCall(ISColoringGetIS(coloring, PETSC_USE_POINTER, &ncolors, &colors));
     27:   PetscCall(PetscSFGetGraph(etor, &nrows, &nleafrows, NULL, NULL));
     28:   PetscCall(PetscSFGetGraph(etoc, &ncols, &nleafcols, NULL, NULL));
     29:   PetscCall(MatGetOwnershipRangeColumn(m, &s, &e));
     30:   PetscCall(PetscMalloc1(ncols, &statecol));
     31:   PetscCall(PetscMalloc1(nrows, &staterow));
     32:   PetscCall(PetscMalloc1(nleafcols, &stateleafcol));
     33:   PetscCall(PetscMalloc1(nleafrows, &stateleafrow));

     35:   for (l = 0; l < ncolors; l++) {
     36:     if (l > maxcolors) break;
     37:     for (k = 0; k < ncols; k++) statecol[k] = -1;
     38:     PetscCall(ISGetLocalSize(colors[l], &nindices));
     39:     PetscCall(ISGetIndices(colors[l], &indices));
     40:     for (k = 0; k < nindices; k++) statecol[indices[k] - s] = indices[k];
     41:     PetscCall(ISRestoreIndices(colors[l], &indices));
     42:     statespread = statecol;
     43:     for (k = 0; k < dist; k++) {
     44:       if (k % 2 == 1) {
     45:         PetscCall(PetscSFComputeDegreeBegin(etor, &degrees));
     46:         PetscCall(PetscSFComputeDegreeEnd(etor, &degrees));
     47:         nentries = 0;
     48:         for (i = 0; i < nrows; i++) nentries += degrees[i];
     49:         idx = 0;
     50:         for (i = 0; i < nrows; i++) {
     51:           for (j = 0; j < degrees[i]; j++) {
     52:             stateleafrow[idx] = staterow[i];
     53:             idx++;
     54:           }
     55:           statecol[i] = 0.;
     56:         }
     57:         PetscCheck(idx == nentries, PetscObjectComm((PetscObject)mc), PETSC_ERR_NOT_CONVERGED, "Bad number of entries %" PetscInt_FMT " vs %" PetscInt_FMT, idx, nentries);
     58:         PetscCall(PetscLogEventBegin(MATCOLORING_Comm, mc, 0, 0, 0));
     59:         PetscCall(PetscSFReduceBegin(etoc, itype, stateleafrow, statecol, MPI_MAX));
     60:         PetscCall(PetscSFReduceEnd(etoc, itype, stateleafrow, statecol, MPI_MAX));
     61:         PetscCall(PetscLogEventEnd(MATCOLORING_Comm, mc, 0, 0, 0));
     62:         statespread = statecol;
     63:       } else {
     64:         PetscCall(PetscSFComputeDegreeBegin(etoc, &degrees));
     65:         PetscCall(PetscSFComputeDegreeEnd(etoc, &degrees));
     66:         nentries = 0;
     67:         for (i = 0; i < ncols; i++) nentries += degrees[i];
     68:         idx = 0;
     69:         for (i = 0; i < ncols; i++) {
     70:           for (j = 0; j < degrees[i]; j++) {
     71:             stateleafcol[idx] = statecol[i];
     72:             idx++;
     73:           }
     74:           staterow[i] = 0.;
     75:         }
     76:         PetscCheck(idx == nentries, PetscObjectComm((PetscObject)mc), PETSC_ERR_NOT_CONVERGED, "Bad number of entries %" PetscInt_FMT " vs %" PetscInt_FMT, idx, nentries);
     77:         PetscCall(PetscLogEventBegin(MATCOLORING_Comm, mc, 0, 0, 0));
     78:         PetscCall(PetscSFReduceBegin(etor, itype, stateleafcol, staterow, MPI_MAX));
     79:         PetscCall(PetscSFReduceEnd(etor, itype, stateleafcol, staterow, MPI_MAX));
     80:         PetscCall(PetscLogEventEnd(MATCOLORING_Comm, mc, 0, 0, 0));
     81:         statespread = staterow;
     82:       }
     83:     }
     84:     for (k = 0; k < nindices; k++) {
     85:       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]));
     86:     }
     87:     PetscCall(ISRestoreIndices(colors[l], &indices));
     88:   }
     89:   PetscCall(PetscFree(statecol));
     90:   PetscCall(PetscFree(staterow));
     91:   PetscCall(PetscFree(stateleafcol));
     92:   PetscCall(PetscFree(stateleafrow));
     93:   PetscCall(PetscSFDestroy(&etor));
     94:   PetscCall(PetscSFDestroy(&etoc));
     95:   PetscFunctionReturn(PETSC_SUCCESS);
     96: }

     98: PETSC_EXTERN PetscErrorCode MatISColoringTest(Mat A, ISColoring iscoloring)
     99: {
    100:   PetscInt        nn, c, i, j, M, N, nc, nnz, col, row;
    101:   const PetscInt *cia, *cja, *cols;
    102:   IS             *isis;
    103:   MPI_Comm        comm;
    104:   PetscMPIInt     size;
    105:   PetscBool       done;
    106:   PetscBT         table;

    108:   PetscFunctionBegin;
    109:   PetscCall(ISColoringGetIS(iscoloring, PETSC_USE_POINTER, &nn, &isis));

    111:   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
    112:   PetscCallMPI(MPI_Comm_size(comm, &size));
    113:   PetscCheck(size <= 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only support sequential matrix");

    115:   PetscCall(MatGetColumnIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &N, &cia, &cja, &done));
    116:   PetscCheck(done, PETSC_COMM_SELF, PETSC_ERR_SUP, "Ordering requires IJ");

    118:   PetscCall(MatGetSize(A, &M, NULL));
    119:   PetscCall(PetscBTCreate(M, &table));
    120:   for (c = 0; c < nn; c++) { /* for each color */
    121:     PetscCall(ISGetSize(isis[c], &nc));
    122:     if (nc <= 1) continue;

    124:     PetscCall(PetscBTMemzero(M, table));
    125:     PetscCall(ISGetIndices(isis[c], &cols));
    126:     for (j = 0; j < nc; j++) { /* for each column */
    127:       col = cols[j];
    128:       nnz = cia[col + 1] - cia[col];
    129:       for (i = 0; i < nnz; i++) {
    130:         row = cja[cia[col] + i];
    131:         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);
    132:       }
    133:     }
    134:     PetscCall(ISRestoreIndices(isis[c], &cols));
    135:   }
    136:   PetscCall(PetscBTDestroy(&table));

    138:   PetscCall(MatRestoreColumnIJ(A, 1, PETSC_FALSE, PETSC_TRUE, NULL, &cia, &cja, &done));
    139:   PetscFunctionReturn(PETSC_SUCCESS);
    140: }