/*@ MatColoringApply - Apply the coloring to the matrix, producing index sets corresponding to a number of independent sets in the induced graph. Collective on MatColoring Input Parameters: . mc - the MatColoring context Output Parameter: . coloring - the ISColoring instance containing the coloring Level: beginner .keywords: Coloring, Apply .seealso: MatColoring, MatColoringCreate() @*/ PetscErrorCode MatColoringApply(MatColoring mc,ISColoring *coloring) { PetscErrorCode ierr; PetscBool flg; PetscViewerFormat format; PetscViewer viewer; PetscInt nc,ncolors; PetscFunctionBegin; PetscValidHeaderSpecific(mc,MAT_COLORING_CLASSID,1); ierr = PetscLogEventBegin(Mat_Coloring_Apply,mc,0,0,0);CHKERRQ(ierr); ierr = (*mc->ops->apply)(mc,coloring);CHKERRQ(ierr); ierr = PetscLogEventEnd(Mat_Coloring_Apply,mc,0,0,0);CHKERRQ(ierr); /* valid */ if (mc->valid) { ierr = MatColoringTestValid(mc,*coloring);CHKERRQ(ierr); } /* view */ ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject)mc),((PetscObject)mc)->prefix,"-mat_coloring_view",&viewer,&format,&flg);CHKERRQ(ierr); if (flg && !PetscPreLoadingOn) { ierr = PetscViewerPushFormat(viewer,format);CHKERRQ(ierr); ierr = MatColoringView(mc,viewer);CHKERRQ(ierr); ierr = MatGetSize(mc->mat,NULL,&nc);CHKERRQ(ierr); ierr = ISColoringGetIS(*coloring,&ncolors,NULL);CHKERRQ(ierr); ierr = PetscViewerASCIIPrintf(viewer," Number of colors %d\n",ncolors);CHKERRQ(ierr); ierr = PetscViewerASCIIPrintf(viewer," Number of total columns %d\n",nc);CHKERRQ(ierr); if (nc <= 1000) {ierr = ISColoringView(*coloring,viewer);CHKERRQ(ierr);} ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); } PetscFunctionReturn(0); }
/*@C ISColoringCreate - Generates an ISColoring context from lists (provided by each processor) of colors for each node. Collective on MPI_Comm Input Parameters: + comm - communicator for the processors creating the coloring . ncolors - max color value . n - number of nodes on this processor - colors - array containing the colors for this processor, color numbers begin at 0. In C/C++ this array must have been obtained with PetscMalloc() and should NOT be freed (The ISColoringDestroy() will free it). Output Parameter: . iscoloring - the resulting coloring data structure Options Database Key: . -is_coloring_view - Activates ISColoringView() Level: advanced Notes: By default sets coloring type to IS_COLORING_GLOBAL .seealso: MatColoringCreate(), ISColoringView(), ISColoringDestroy(), ISColoringSetType() @*/ PetscErrorCode ISColoringCreate(MPI_Comm comm,PetscInt ncolors,PetscInt n,const ISColoringValue colors[],ISColoring *iscoloring) { PetscErrorCode ierr; PetscMPIInt size,rank,tag; PetscInt base,top,i; PetscInt nc,ncwork; PetscBool flg = PETSC_FALSE; MPI_Status status; PetscFunctionBegin; if (ncolors != PETSC_DECIDE && ncolors > IS_COLORING_MAX) { if (ncolors > 65535) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Max color value exeeds 65535 limit. This number is unrealistic. Perhaps a bug in code?\nCurrent max: %d user rewuested: %d",IS_COLORING_MAX,ncolors); else SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Max color value exeeds limit. Perhaps reconfigure PETSc with --with-is-color-value-type=short?\n Current max: %d user rewuested: %d",IS_COLORING_MAX,ncolors); } ierr = PetscNew(struct _n_ISColoring,iscoloring);CHKERRQ(ierr); ierr = PetscCommDuplicate(comm,&(*iscoloring)->comm,&tag);CHKERRQ(ierr); comm = (*iscoloring)->comm; /* compute the number of the first node on my processor */ ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); /* should use MPI_Scan() */ ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); if (!rank) { base = 0; top = n; } else { ierr = MPI_Recv(&base,1,MPIU_INT,rank-1,tag,comm,&status);CHKERRQ(ierr); top = base+n; } if (rank < size-1) { ierr = MPI_Send(&top,1,MPIU_INT,rank+1,tag,comm);CHKERRQ(ierr); } /* compute the total number of colors */ ncwork = 0; for (i=0; i<n; i++) { if (ncwork < colors[i]) ncwork = colors[i]; } ncwork++; ierr = MPI_Allreduce(&ncwork,&nc,1,MPIU_INT,MPI_MAX,comm);CHKERRQ(ierr); if (nc > ncolors) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of colors passed in %D is less then the actual number of colors in array %D",ncolors,nc); (*iscoloring)->n = nc; (*iscoloring)->is = 0; (*iscoloring)->colors = (ISColoringValue*)colors; (*iscoloring)->N = n; (*iscoloring)->refct = 1; (*iscoloring)->ctype = IS_COLORING_GLOBAL; ierr = PetscOptionsGetBool(NULL,"-is_coloring_view",&flg,NULL);CHKERRQ(ierr); if (flg) { PetscViewer viewer; ierr = PetscViewerASCIIGetStdout((*iscoloring)->comm,&viewer);CHKERRQ(ierr); ierr = ISColoringView(*iscoloring,viewer);CHKERRQ(ierr); } ierr = PetscInfo1(0,"Number of colors %D\n",nc);CHKERRQ(ierr); PetscFunctionReturn(0); }
/* ISColoringViewFromOptions - Processes command line options to determine if/how an ISColoring object is to be viewed. Collective on ISColoring Input Parameters: + obj - the ISColoring object . prefix - prefix to use for viewing, or NULL to use prefix of 'mat' - optionname - option to activate viewing Level: intermediate Developer Note: This cannot use PetscObjectViewFromOptions() because ISColoring is not a PetscObject */ PetscErrorCode ISColoringViewFromOptions(ISColoring obj,PetscObject bobj,const char optionname[]) { PetscErrorCode ierr; PetscViewer viewer; PetscBool flg; PetscViewerFormat format; char *prefix; PetscFunctionBegin; prefix = bobj ? bobj->prefix : NULL; ierr = PetscOptionsGetViewer(obj->comm,prefix,optionname,&viewer,&format,&flg);CHKERRQ(ierr); if (flg) { ierr = PetscViewerPushFormat(viewer,format);CHKERRQ(ierr); ierr = ISColoringView(obj,viewer);CHKERRQ(ierr); ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); } PetscFunctionReturn(0); }
/* ISColoringViewFromOptions - Processes command line options to determine if/how an ISColoring object is to be viewed. Collective on ISColoring Input Parameters: + obj - the ISColoring object . prefix - prefix to use for viewing, or NULL to use prefix of 'mat' - optionname - option to activate viewing Level: intermediate Developer Note: This cannot use PetscObjectViewFromOptions() because ISColoring is not a PetscObject */ PetscErrorCode ISColoringViewFromOptions(ISColoring obj,const char prefix[],const char optionname[]) { PetscErrorCode ierr; PetscViewer viewer; PetscBool flg; static PetscBool incall = PETSC_FALSE; PetscViewerFormat format; PetscFunctionBegin; if (incall) PetscFunctionReturn(0); incall = PETSC_TRUE; ierr = PetscOptionsGetViewer(obj->comm,prefix,optionname,&viewer,&format,&flg);CHKERRQ(ierr); if (flg) { ierr = PetscViewerPushFormat(viewer,format);CHKERRQ(ierr); ierr = ISColoringView(obj,viewer);CHKERRQ(ierr); ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); } incall = PETSC_FALSE; PetscFunctionReturn(0); }
/*@C MatGetColoring - Gets a coloring for a matrix, from its sparsity structure, to reduce the number of function evaluations needed to compute a sparse Jacobian via differencing. Collective on Mat Input Parameters: . mat - the matrix . type - type of coloring, one of the following: $ MATCOLORINGNATURAL - natural (one color for each column, very slow) $ MATCOLORINGSL - smallest-last $ MATCOLORINGLF - largest-first $ MATCOLORINGID - incidence-degree Output Parameters: . iscoloring - the coloring Options Database Keys: To specify the coloring through the options database, use one of the following $ -mat_coloring_type natural, -mat_coloring_type sl, -mat_coloring_type lf, $ -mat_coloring_type id To see the coloring use $ -mat_coloring_view Level: intermediate Notes: $ A graph coloring C(A) is a division of vertices so that two vertices of the same color do not share any common edges. $ A suitable coloring for a smoother is simply C(A). $ A suitable coloring for efficient Jacobian computation is a division of the columns so that two columns of the same color do not share any common rows. $ This corresponds to C(A^{T} A). This is what MatGetColoring() computes. The user can define additional colorings; see MatColoringRegisterDynamic(). For parallel matrices currently converts to sequential matrix and uses the sequential coloring on that. The colorings SL, LF, and ID are obtained via the Minpack software that was converted to C using f2c. For BAIJ matrices this colors the blocks. The true number of colors would be block size times the number of colors returned here. References: $ Thomas F. Coleman and Jorge J. More, Estimation of Sparse {J}acobian Matrices and Graph Coloring Problems, $ SIAM Journal on Numerical Analysis, 1983, pages 187-209, volume 20 $ Jorge J. Mor\'{e} and Danny C. Sorenson and Burton S. Garbow and Kenneth E. Hillstrom, The {MINPACK} Project, $ Sources and Development of Mathematical Software, Wayne R. Cowell editor, 1984, pages 88-111 .keywords: matrix, get, coloring .seealso: MatGetColoringTypeFromOptions(), MatColoringRegisterDynamic(), MatFDColoringCreate(), SNESDefaultComputeJacobianColor() @*/ PetscErrorCode MatGetColoring(Mat mat,MatColoringType type,ISColoring *iscoloring) { PetscBool flag; PetscErrorCode ierr,(*r)(Mat,MatColoringType,ISColoring *); char tname[PETSC_MAX_PATH_LEN]; MPI_Comm comm; PetscFunctionBegin; PetscValidHeaderSpecific(mat,MAT_CLASSID,1); PetscValidPointer(iscoloring,3); if (!mat->assembled) SETERRQ(((PetscObject)mat)->comm,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); if (mat->factortype) SETERRQ(((PetscObject)mat)->comm,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); /* look for type on command line */ if (!MatColoringRegisterAllCalled) {ierr = MatColoringRegisterAll(PETSC_NULL);CHKERRQ(ierr);} ierr = PetscOptionsGetString(((PetscObject)mat)->prefix,"-mat_coloring_type",tname,256,&flag);CHKERRQ(ierr); if (flag) { type = tname; } ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr); ierr = PetscFunctionListFind(comm,MatColoringList,type,PETSC_TRUE,(void (**)(void)) &r);CHKERRQ(ierr); if (!r) SETERRQ1(((PetscObject)mat)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Unknown or unregistered type: %s",type); ierr = PetscLogEventBegin(MAT_GetColoring,mat,0,0,0);CHKERRQ(ierr); ierr = (*r)(mat,type,iscoloring);CHKERRQ(ierr); ierr = PetscLogEventEnd(MAT_GetColoring,mat,0,0,0);CHKERRQ(ierr); ierr = PetscInfo1(mat,"Number of colors %d\n",(*iscoloring)->n);CHKERRQ(ierr); flag = PETSC_FALSE; ierr = PetscOptionsGetBool(PETSC_NULL,"-mat_coloring_view",&flag,PETSC_NULL);CHKERRQ(ierr); if (flag) { PetscViewer viewer; ierr = PetscViewerASCIIGetStdout((*iscoloring)->comm,&viewer);CHKERRQ(ierr); ierr = ISColoringView(*iscoloring,viewer);CHKERRQ(ierr); } PetscFunctionReturn(0); }