Actual source code: natural.c

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

  4: static PetscErrorCode MatColoringApply_Natural(MatColoring mc, ISColoring *iscoloring)
  5: {
  6:   PetscInt         start, end, i, bs = 1, n;
  7:   ISColoringValue *colors;
  8:   MPI_Comm         comm;
  9:   PetscBool        flg1, flg2;
 10:   Mat              mat     = mc->mat;
 11:   Mat              mat_seq = mc->mat;
 12:   PetscMPIInt      size;
 13:   ISColoring       iscoloring_seq;
 14:   ISColoringValue *colors_loc;
 15:   PetscInt         rstart, rend, N_loc, nc;

 17:   PetscFunctionBegin;
 18:   /* this is ugly way to get blocksize but cannot call MatGetBlockSize() because AIJ can have bs > 1 */
 19:   PetscCall(PetscObjectTypeCompare((PetscObject)mat, MATSEQBAIJ, &flg1));
 20:   PetscCall(PetscObjectTypeCompare((PetscObject)mat, MATMPIBAIJ, &flg2));
 21:   if (flg1 || flg2) PetscCall(MatGetBlockSize(mat, &bs));

 23:   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
 24:   PetscCallMPI(MPI_Comm_size(comm, &size));
 25:   if (size > 1) {
 26:     /* create a sequential iscoloring on all processors */
 27:     PetscCall(MatGetSeqNonzeroStructure(mat, &mat_seq));
 28:   }

 30:   PetscCall(MatGetSize(mat_seq, &n, NULL));
 31:   PetscCall(MatGetOwnershipRange(mat_seq, &start, &end));
 32:   n = n / bs;
 33:   PetscCheck(n <= IS_COLORING_MAX - 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Maximum color size exceeded");

 35:   start = start / bs;
 36:   end   = end / bs;
 37:   PetscCall(PetscMalloc1(end - start + 1, &colors));
 38:   for (i = start; i < end; i++) colors[i - start] = (ISColoringValue)i;
 39:   PetscCall(ISColoringCreate(comm, n, end - start, colors, PETSC_OWN_POINTER, iscoloring));

 41:   if (size > 1) {
 42:     PetscCall(MatDestroySeqNonzeroStructure(&mat_seq));

 44:     /* convert iscoloring_seq to a parallel iscoloring */
 45:     iscoloring_seq = *iscoloring;
 46:     rstart         = mat->rmap->rstart / bs;
 47:     rend           = mat->rmap->rend / bs;
 48:     N_loc          = rend - rstart; /* number of local nodes */

 50:     /* get local colors for each local node */
 51:     PetscCall(PetscMalloc1(N_loc + 1, &colors_loc));
 52:     for (i = rstart; i < rend; i++) colors_loc[i - rstart] = iscoloring_seq->colors[i];
 53:     /* create a parallel iscoloring */
 54:     nc = iscoloring_seq->n;
 55:     PetscCall(ISColoringCreate(comm, nc, N_loc, colors_loc, PETSC_OWN_POINTER, iscoloring));
 56:     PetscCall(ISColoringDestroy(&iscoloring_seq));
 57:   }
 58:   PetscFunctionReturn(PETSC_SUCCESS);
 59: }

 61: /*MC
 62:   MATCOLORINGNATURAL - implements a trivial coloring routine with one color per column

 64:   Level: beginner

 66:   Note:
 67:   Using this coloring would be extremely inefficient but it is useful for testing

 69: .seealso: `MatColoring`, `MatColoringType`, `MatColoringCreate()`, `MatColoring`, `MatColoringSetType()`, `MatColoringType`
 70: M*/
 71: PETSC_EXTERN PetscErrorCode MatColoringCreate_Natural(MatColoring mc)
 72: {
 73:   PetscFunctionBegin;
 74:   mc->data                = NULL;
 75:   mc->ops->apply          = MatColoringApply_Natural;
 76:   mc->ops->view           = NULL;
 77:   mc->ops->destroy        = NULL;
 78:   mc->ops->setfromoptions = NULL;
 79:   PetscFunctionReturn(PETSC_SUCCESS);
 80: }