/* MatGetOrdering_RCM - Find the Reverse Cuthill-McKee ordering of a given matrix. */ PETSC_INTERN PetscErrorCode MatGetOrdering_RCM(Mat mat,MatOrderingType type,IS *row,IS *col) { PetscErrorCode ierr; PetscInt i,*mask,*xls,nrow,*perm; const PetscInt *ia,*ja; PetscBool done; PetscFunctionBegin; ierr = MatGetRowIJ(mat,1,PETSC_TRUE,PETSC_TRUE,&nrow,&ia,&ja,&done); CHKERRQ(ierr); if (!done) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot get rows for matrix"); ierr = PetscMalloc3(nrow,&mask,nrow,&perm,2*nrow,&xls); CHKERRQ(ierr); SPARSEPACKgenrcm(&nrow,ia,ja,perm,mask,xls); ierr = MatRestoreRowIJ(mat,1,PETSC_TRUE,PETSC_TRUE,NULL,&ia,&ja,&done); CHKERRQ(ierr); /* shift because Sparsepack indices start at one */ for (i=0; i<nrow; i++) perm[i]--; ierr = ISCreateGeneral(PETSC_COMM_SELF,nrow,perm,PETSC_COPY_VALUES,row); CHKERRQ(ierr); ierr = ISCreateGeneral(PETSC_COMM_SELF,nrow,perm,PETSC_COPY_VALUES,col); CHKERRQ(ierr); ierr = PetscFree3(mask,perm,xls); CHKERRQ(ierr); PetscFunctionReturn(0); }
EXTERN_C_BEGIN /* MatOrdering_RCM - Find the Reverse Cuthill-McKee ordering of a given matrix. */ #undef __FUNCT__ #define __FUNCT__ "MatOrdering_RCM" PetscErrorCode PETSCMAT_DLLEXPORT MatOrdering_RCM(Mat mat,const MatOrderingType type,IS *row,IS *col) { PetscErrorCode ierr; PetscInt i,*mask,*xls,nrow,*ia,*ja,*perm; PetscTruth done; PetscFunctionBegin; ierr = MatGetRowIJ(mat,1,PETSC_TRUE,PETSC_TRUE,&nrow,&ia,&ja,&done);CHKERRQ(ierr); if (!done) SETERRQ(PETSC_ERR_SUP,"Cannot get rows for matrix"); ierr = PetscMalloc3(nrow,PetscInt,&mask,nrow,PetscInt,&perm,2*nrow,PetscInt,&xls);CHKERRQ(ierr); SPARSEPACKgenrcm(&nrow,ia,ja,perm,mask,xls); ierr = MatRestoreRowIJ(mat,1,PETSC_TRUE,PETSC_TRUE,&nrow,&ia,&ja,&done);CHKERRQ(ierr); /* shift because Sparsepack indices start at one */ for (i=0; i<nrow; i++) perm[i]--; ierr = ISCreateGeneral(PETSC_COMM_SELF,nrow,perm,row);CHKERRQ(ierr); ierr = ISCreateGeneral(PETSC_COMM_SELF,nrow,perm,col);CHKERRQ(ierr); ierr = PetscFree3(mask,perm,xls);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*@ DMPlexGetOrdering - Calculate a reordering of the mesh Collective on DM Input Parameter: + dm - The DMPlex object . otype - type of reordering, one of the following: $ MATORDERINGNATURAL - Natural $ MATORDERINGND - Nested Dissection $ MATORDERING1WD - One-way Dissection $ MATORDERINGRCM - Reverse Cuthill-McKee $ MATORDERINGQMD - Quotient Minimum Degree - label - [Optional] Label used to segregate ordering into sets, or NULL Output Parameter: . perm - The point permutation as an IS, perm[old point number] = new point number Note: The label is used to group sets of points together by label value. This makes it easy to reorder a mesh which has different types of cells, and then loop over each set of reordered cells for assembly. Level: intermediate .keywords: mesh .seealso: MatGetOrdering() @*/ PetscErrorCode DMPlexGetOrdering(DM dm, MatOrderingType otype, DMLabel label, IS *perm) { PetscInt numCells = 0; PetscInt *start = NULL, *adjacency = NULL, *cperm, *clperm, *invclperm, *mask, *xls, pStart, pEnd, c, i; PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); PetscValidPointer(perm, 3); ierr = DMPlexCreateNeighborCSR(dm, 0, &numCells, &start, &adjacency);CHKERRQ(ierr); ierr = PetscMalloc3(numCells,&cperm,numCells,&mask,numCells*2,&xls);CHKERRQ(ierr); if (numCells) { /* Shift for Fortran numbering */ for (i = 0; i < start[numCells]; ++i) ++adjacency[i]; for (i = 0; i <= numCells; ++i) ++start[i]; ierr = SPARSEPACKgenrcm(&numCells, start, adjacency, cperm, mask, xls);CHKERRQ(ierr); } ierr = PetscFree(start);CHKERRQ(ierr); ierr = PetscFree(adjacency);CHKERRQ(ierr); /* Shift for Fortran numbering */ for (c = 0; c < numCells; ++c) --cperm[c]; /* Segregate */ if (label) { IS valueIS; const PetscInt *values; PetscInt numValues, numPoints = 0; PetscInt *sperm, *vsize, *voff, v; ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); ierr = ISSort(valueIS);CHKERRQ(ierr); ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); ierr = PetscCalloc3(numCells,&sperm,numValues,&vsize,numValues+1,&voff);CHKERRQ(ierr); for (v = 0; v < numValues; ++v) { ierr = DMLabelGetStratumSize(label, values[v], &vsize[v]);CHKERRQ(ierr); if (v < numValues-1) voff[v+2] += vsize[v] + voff[v+1]; numPoints += vsize[v]; } if (numPoints != numCells) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label only covers %D cells < %D total", numPoints, numCells); for (c = 0; c < numCells; ++c) { const PetscInt oldc = cperm[c]; PetscInt val, vloc; ierr = DMLabelGetValue(label, oldc, &val);CHKERRQ(ierr); if (val == -1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %D not present in label", oldc); ierr = PetscFindInt(val, numValues, values, &vloc);CHKERRQ(ierr); if (vloc < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Value %D not present label", val); sperm[voff[vloc+1]++] = oldc; } for (v = 0; v < numValues; ++v) { if (voff[v+1] - voff[v] != vsize[v]) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Number of %D values found is %D != %D", values[v], voff[v+1] - voff[v], vsize[v]); } ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); ierr = ISDestroy(&valueIS);CHKERRQ(ierr); ierr = PetscMemcpy(cperm, sperm, numCells * sizeof(PetscInt));CHKERRQ(ierr); ierr = PetscFree3(sperm, vsize, voff);CHKERRQ(ierr); } /* Construct closure */ ierr = DMPlexCreateOrderingClosure_Static(dm, numCells, cperm, &clperm, &invclperm);CHKERRQ(ierr); ierr = PetscFree3(cperm,mask,xls);CHKERRQ(ierr); ierr = PetscFree(clperm);CHKERRQ(ierr); /* Invert permutation */ ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), pEnd-pStart, invclperm, PETSC_OWN_POINTER, perm);CHKERRQ(ierr); PetscFunctionReturn(0); }