1c094ef40SMatthew G. Knepley #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/ 2e8f14785SLisandro Dalcin #include <petsc/private/hashsetij.h> 3c094ef40SMatthew G. Knepley 4c094ef40SMatthew G. Knepley typedef struct { 5e8f14785SLisandro Dalcin PetscHSetIJ ht; 6c094ef40SMatthew G. Knepley PetscInt *dnz, *onz; 7c09129f1SStefano Zampini PetscInt *dnzu, *onzu; 8f8f6e9aeSStefano Zampini PetscBool nooffproc; 9c094ef40SMatthew G. Knepley } Mat_Preallocator; 10c094ef40SMatthew G. Knepley 11c094ef40SMatthew G. Knepley PetscErrorCode MatDestroy_Preallocator(Mat A) 12c094ef40SMatthew G. Knepley { 13c094ef40SMatthew G. Knepley Mat_Preallocator *p = (Mat_Preallocator *) A->data; 14c094ef40SMatthew G. Knepley PetscErrorCode ierr; 15c094ef40SMatthew G. Knepley 16c094ef40SMatthew G. Knepley PetscFunctionBegin; 17c094ef40SMatthew G. Knepley ierr = MatStashDestroy_Private(&A->stash);CHKERRQ(ierr); 18e8f14785SLisandro Dalcin ierr = PetscHSetIJDestroy(&p->ht);CHKERRQ(ierr); 19c09129f1SStefano Zampini ierr = PetscFree4(p->dnz, p->onz, p->dnzu, p->onzu);CHKERRQ(ierr); 20c094ef40SMatthew G. Knepley ierr = PetscFree(A->data);CHKERRQ(ierr); 21f4259b30SLisandro Dalcin ierr = PetscObjectChangeTypeName((PetscObject) A, NULL);CHKERRQ(ierr); 22c094ef40SMatthew G. Knepley ierr = PetscObjectComposeFunction((PetscObject) A, "MatPreallocatorPreallocate_C", NULL);CHKERRQ(ierr); 23c094ef40SMatthew G. Knepley PetscFunctionReturn(0); 24c094ef40SMatthew G. Knepley } 25c094ef40SMatthew G. Knepley 26c094ef40SMatthew G. Knepley PetscErrorCode MatSetUp_Preallocator(Mat A) 27c094ef40SMatthew G. Knepley { 28c094ef40SMatthew G. Knepley Mat_Preallocator *p = (Mat_Preallocator *) A->data; 295dca1104SStefano Zampini PetscInt m, bs, mbs; 30c094ef40SMatthew G. Knepley PetscErrorCode ierr; 31c094ef40SMatthew G. Knepley 32c094ef40SMatthew G. Knepley PetscFunctionBegin; 33c094ef40SMatthew G. Knepley ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr); 34c094ef40SMatthew G. Knepley ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr); 35c094ef40SMatthew G. Knepley ierr = MatGetLocalSize(A, &m, NULL);CHKERRQ(ierr); 36e8f14785SLisandro Dalcin ierr = PetscHSetIJCreate(&p->ht);CHKERRQ(ierr); 37c094ef40SMatthew G. Knepley ierr = MatGetBlockSize(A, &bs);CHKERRQ(ierr); 388011973bSJunchao Zhang /* Do not bother bstash since MatPreallocator does not implement MatSetValuesBlocked */ 398011973bSJunchao Zhang ierr = MatStashCreate_Private(PetscObjectComm((PetscObject) A), 1, &A->stash);CHKERRQ(ierr); 405dca1104SStefano Zampini /* arrays are for blocked rows/cols */ 415dca1104SStefano Zampini mbs = m/bs; 425dca1104SStefano Zampini ierr = PetscCalloc4(mbs, &p->dnz, mbs, &p->onz, mbs, &p->dnzu, mbs, &p->onzu);CHKERRQ(ierr); 43c094ef40SMatthew G. Knepley PetscFunctionReturn(0); 44c094ef40SMatthew G. Knepley } 45c094ef40SMatthew G. Knepley 46c094ef40SMatthew G. Knepley PetscErrorCode MatSetValues_Preallocator(Mat A, PetscInt m, const PetscInt *rows, PetscInt n, const PetscInt *cols, const PetscScalar *values, InsertMode addv) 47c094ef40SMatthew G. Knepley { 48c094ef40SMatthew G. Knepley Mat_Preallocator *p = (Mat_Preallocator *) A->data; 495dca1104SStefano Zampini PetscInt rStart, rEnd, r, cStart, cEnd, c, bs; 50c094ef40SMatthew G. Knepley PetscErrorCode ierr; 51c094ef40SMatthew G. Knepley 52c094ef40SMatthew G. Knepley PetscFunctionBegin; 535dca1104SStefano Zampini ierr = MatGetBlockSize(A, &bs);CHKERRQ(ierr); 54c094ef40SMatthew G. Knepley ierr = MatGetOwnershipRange(A, &rStart, &rEnd);CHKERRQ(ierr); 55c094ef40SMatthew G. Knepley ierr = MatGetOwnershipRangeColumn(A, &cStart, &cEnd);CHKERRQ(ierr); 56c094ef40SMatthew G. Knepley for (r = 0; r < m; ++r) { 57e8f14785SLisandro Dalcin PetscHashIJKey key; 58e8f14785SLisandro Dalcin PetscBool missing; 59c094ef40SMatthew G. Knepley 60e8f14785SLisandro Dalcin key.i = rows[r]; 61e8f14785SLisandro Dalcin if (key.i < 0) continue; 62e8f14785SLisandro Dalcin if ((key.i < rStart) || (key.i >= rEnd)) { 63e8f14785SLisandro Dalcin ierr = MatStashValuesRow_Private(&A->stash, key.i, n, cols, values, PETSC_FALSE);CHKERRQ(ierr); 645dca1104SStefano Zampini } else { /* Hash table is for blocked rows/cols */ 655dca1104SStefano Zampini key.i = rows[r]/bs; 66c094ef40SMatthew G. Knepley for (c = 0; c < n; ++c) { 675dca1104SStefano Zampini key.j = cols[c]/bs; 68e8f14785SLisandro Dalcin if (key.j < 0) continue; 69e8f14785SLisandro Dalcin ierr = PetscHSetIJQueryAdd(p->ht, key, &missing);CHKERRQ(ierr); 70c094ef40SMatthew G. Knepley if (missing) { 715dca1104SStefano Zampini if ((key.j >= cStart/bs) && (key.j < cEnd/bs)) { 725dca1104SStefano Zampini ++p->dnz[key.i-rStart/bs]; 735dca1104SStefano Zampini if (key.j >= key.i) ++p->dnzu[key.i-rStart/bs]; 74c09129f1SStefano Zampini } else { 755dca1104SStefano Zampini ++p->onz[key.i-rStart/bs]; 765dca1104SStefano Zampini if (key.j >= key.i) ++p->onzu[key.i-rStart/bs]; 77c09129f1SStefano Zampini } 78c094ef40SMatthew G. Knepley } 79c094ef40SMatthew G. Knepley } 80c094ef40SMatthew G. Knepley } 81c094ef40SMatthew G. Knepley } 82c094ef40SMatthew G. Knepley PetscFunctionReturn(0); 83c094ef40SMatthew G. Knepley } 84c094ef40SMatthew G. Knepley 85c094ef40SMatthew G. Knepley PetscErrorCode MatAssemblyBegin_Preallocator(Mat A, MatAssemblyType type) 86c094ef40SMatthew G. Knepley { 87c094ef40SMatthew G. Knepley PetscInt nstash, reallocs; 88c094ef40SMatthew G. Knepley PetscErrorCode ierr; 89c094ef40SMatthew G. Knepley 90c094ef40SMatthew G. Knepley PetscFunctionBegin; 91c094ef40SMatthew G. Knepley ierr = MatStashScatterBegin_Private(A, &A->stash, A->rmap->range);CHKERRQ(ierr); 92c094ef40SMatthew G. Knepley ierr = MatStashGetInfo_Private(&A->stash, &nstash, &reallocs);CHKERRQ(ierr); 93c094ef40SMatthew G. Knepley ierr = PetscInfo2(A, "Stash has %D entries, uses %D mallocs.\n", nstash, reallocs);CHKERRQ(ierr); 94c094ef40SMatthew G. Knepley PetscFunctionReturn(0); 95c094ef40SMatthew G. Knepley } 96c094ef40SMatthew G. Knepley 97c094ef40SMatthew G. Knepley PetscErrorCode MatAssemblyEnd_Preallocator(Mat A, MatAssemblyType type) 98c094ef40SMatthew G. Knepley { 99c094ef40SMatthew G. Knepley PetscScalar *val; 100c094ef40SMatthew G. Knepley PetscInt *row, *col; 101c094ef40SMatthew G. Knepley PetscInt i, j, rstart, ncols, flg; 102c094ef40SMatthew G. Knepley PetscMPIInt n; 103f8f6e9aeSStefano Zampini Mat_Preallocator *p = (Mat_Preallocator *) A->data; 104c094ef40SMatthew G. Knepley PetscErrorCode ierr; 105c094ef40SMatthew G. Knepley 106c094ef40SMatthew G. Knepley PetscFunctionBegin; 107f8f6e9aeSStefano Zampini p->nooffproc = PETSC_TRUE; 108c094ef40SMatthew G. Knepley while (1) { 109c094ef40SMatthew G. Knepley ierr = MatStashScatterGetMesg_Private(&A->stash, &n, &row, &col, &val, &flg);CHKERRQ(ierr); 110f8f6e9aeSStefano Zampini if (flg) p->nooffproc = PETSC_FALSE; 111c094ef40SMatthew G. Knepley if (!flg) break; 112c094ef40SMatthew G. Knepley 113c094ef40SMatthew G. Knepley for (i = 0; i < n;) { 114c094ef40SMatthew G. Knepley /* Now identify the consecutive vals belonging to the same row */ 115c094ef40SMatthew G. Knepley for (j = i, rstart = row[j]; j < n; j++) { 116c094ef40SMatthew G. Knepley if (row[j] != rstart) break; 117c094ef40SMatthew G. Knepley } 118c094ef40SMatthew G. Knepley if (j < n) ncols = j-i; 119c094ef40SMatthew G. Knepley else ncols = n-i; 120c094ef40SMatthew G. Knepley /* Now assemble all these values with a single function call */ 121c094ef40SMatthew G. Knepley ierr = MatSetValues_Preallocator(A, 1, row+i, ncols, col+i, val+i, INSERT_VALUES);CHKERRQ(ierr); 122c094ef40SMatthew G. Knepley i = j; 123c094ef40SMatthew G. Knepley } 124c094ef40SMatthew G. Knepley } 125c094ef40SMatthew G. Knepley ierr = MatStashScatterEnd_Private(&A->stash);CHKERRQ(ierr); 126820f2d46SBarry Smith ierr = MPIU_Allreduce(MPI_IN_PLACE,&p->nooffproc,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRMPI(ierr); 127c094ef40SMatthew G. Knepley PetscFunctionReturn(0); 128c094ef40SMatthew G. Knepley } 129c094ef40SMatthew G. Knepley 130c094ef40SMatthew G. Knepley PetscErrorCode MatView_Preallocator(Mat A, PetscViewer viewer) 131c094ef40SMatthew G. Knepley { 132c094ef40SMatthew G. Knepley PetscFunctionBegin; 133c094ef40SMatthew G. Knepley PetscFunctionReturn(0); 134c094ef40SMatthew G. Knepley } 135c094ef40SMatthew G. Knepley 136c094ef40SMatthew G. Knepley PetscErrorCode MatSetOption_Preallocator(Mat A, MatOption op, PetscBool flg) 137c094ef40SMatthew G. Knepley { 138c094ef40SMatthew G. Knepley PetscFunctionBegin; 139c094ef40SMatthew G. Knepley PetscFunctionReturn(0); 140c094ef40SMatthew G. Knepley } 141c094ef40SMatthew G. Knepley 142c094ef40SMatthew G. Knepley PetscErrorCode MatPreallocatorPreallocate_Preallocator(Mat mat, PetscBool fill, Mat A) 143c094ef40SMatthew G. Knepley { 144c094ef40SMatthew G. Knepley Mat_Preallocator *p = (Mat_Preallocator *) mat->data; 145c094ef40SMatthew G. Knepley PetscInt bs; 146c094ef40SMatthew G. Knepley PetscErrorCode ierr; 147c094ef40SMatthew G. Knepley 148c094ef40SMatthew G. Knepley PetscFunctionBegin; 149c094ef40SMatthew G. Knepley ierr = MatGetBlockSize(mat, &bs);CHKERRQ(ierr); 150c09129f1SStefano Zampini ierr = MatXAIJSetPreallocation(A, bs, p->dnz, p->onz, p->dnzu, p->onzu);CHKERRQ(ierr); 151050c3c49SStefano Zampini ierr = MatSetUp(A);CHKERRQ(ierr); 152c094ef40SMatthew G. Knepley ierr = MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE);CHKERRQ(ierr); 153f8f6e9aeSStefano Zampini ierr = MatSetOption(A, MAT_NO_OFF_PROC_ENTRIES, p->nooffproc);CHKERRQ(ierr); 154380bf85aSDave May if (fill) { 155380bf85aSDave May PetscHashIter hi; 156380bf85aSDave May PetscHashIJKey key; 157380bf85aSDave May PetscScalar *zeros; 158*146543f8SJed Brown PetscInt n,maxrow=1,*rows,*cols; 159380bf85aSDave May 160*146543f8SJed Brown ierr = PetscHSetIJGetSize(p->ht,&n);CHKERRQ(ierr); 161*146543f8SJed Brown ierr = PetscMalloc2(n,&rows,n,&cols);CHKERRQ(ierr); 162380bf85aSDave May PetscHashIterBegin(p->ht,hi); 163*146543f8SJed Brown for (PetscInt i=0; !PetscHashIterAtEnd(p->ht,hi); i++) { 164380bf85aSDave May PetscHashIterGetKey(p->ht,hi,key); 165*146543f8SJed Brown rows[i] = key.i; 166*146543f8SJed Brown cols[i] = key.j; 167380bf85aSDave May PetscHashIterNext(p->ht,hi); 168*146543f8SJed Brown } 169*146543f8SJed Brown ierr = PetscHSetIJDestroy(&p->ht);CHKERRQ(ierr); 170*146543f8SJed Brown 171*146543f8SJed Brown ierr = PetscCalloc1(maxrow*bs*bs,&zeros);CHKERRQ(ierr); 172*146543f8SJed Brown ierr = PetscSortIntWithArray(n,rows,cols);CHKERRQ(ierr); 173*146543f8SJed Brown for (PetscInt start=0,end=1; start<n; start=end,end++) { 174*146543f8SJed Brown while (end < n && rows[end] == rows[start]) end++; 175*146543f8SJed Brown ierr = PetscSortInt(end-start,&cols[start]);CHKERRQ(ierr); 176*146543f8SJed Brown if (maxrow < end-start) { 177*146543f8SJed Brown maxrow = 2*(end - start); 178*146543f8SJed Brown ierr = PetscRealloc(maxrow*bs*bs*sizeof(zeros[0]),&zeros);CHKERRQ(ierr); 179*146543f8SJed Brown ierr = PetscMemzero(zeros, maxrow*bs*bs*sizeof(zeros[0]));CHKERRQ(ierr); 180*146543f8SJed Brown } 181*146543f8SJed Brown ierr = MatSetValuesBlocked(A, 1, &rows[start], end-start, &cols[start], zeros, INSERT_VALUES);CHKERRQ(ierr); 182380bf85aSDave May } 183380bf85aSDave May ierr = PetscFree(zeros);CHKERRQ(ierr); 184*146543f8SJed Brown ierr = PetscFree2(rows,cols);CHKERRQ(ierr); 185380bf85aSDave May 186380bf85aSDave May ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 187380bf85aSDave May ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 188380bf85aSDave May } 189c094ef40SMatthew G. Knepley PetscFunctionReturn(0); 190c094ef40SMatthew G. Knepley } 191c094ef40SMatthew G. Knepley 192c094ef40SMatthew G. Knepley /*@ 193380bf85aSDave May MatPreallocatorPreallocate - Preallocates the A matrix, using information from mat, optionally filling A with zeros 194c094ef40SMatthew G. Knepley 195c094ef40SMatthew G. Knepley Input Parameter: 196c094ef40SMatthew G. Knepley + mat - the preallocator 197380bf85aSDave May . fill - fill the matrix with zeros 198380bf85aSDave May - A - the matrix to be preallocated 199c094ef40SMatthew G. Knepley 200380bf85aSDave May Notes: 201380bf85aSDave May This Mat implementation provides a helper utility to define the correct 202380bf85aSDave May preallocation data for a given nonzero structure. Use this object like a 203380bf85aSDave May regular matrix, e.g. loop over the nonzero structure of the matrix and 204380bf85aSDave May call MatSetValues() or MatSetValuesBlocked() to indicate the nonzero locations. 205380bf85aSDave May The matrix entires provided to MatSetValues() will be ignored, it only uses 206380bf85aSDave May the row / col indices provided to determine the information required to be 207380bf85aSDave May passed to MatXAIJSetPreallocation(). Once you have looped over the nonzero 208380bf85aSDave May structure, you must call MatAssemblyBegin(), MatAssemblyEnd() on mat. 209380bf85aSDave May 210380bf85aSDave May After you have assembled the preallocator matrix (mat), call MatPreallocatorPreallocate() 211380bf85aSDave May to define the preallocation information on the matrix (A). Setting the parameter 212380bf85aSDave May fill = PETSC_TRUE will insert zeros into the matrix A. Internally MatPreallocatorPreallocate() 213380bf85aSDave May will call MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE); 214c094ef40SMatthew G. Knepley 215c094ef40SMatthew G. Knepley Level: advanced 216c094ef40SMatthew G. Knepley 217c094ef40SMatthew G. Knepley .seealso: MATPREALLOCATOR 218c094ef40SMatthew G. Knepley @*/ 219c094ef40SMatthew G. Knepley PetscErrorCode MatPreallocatorPreallocate(Mat mat, PetscBool fill, Mat A) 220c094ef40SMatthew G. Knepley { 221c094ef40SMatthew G. Knepley PetscErrorCode ierr; 222c094ef40SMatthew G. Knepley 223c094ef40SMatthew G. Knepley PetscFunctionBegin; 224c094ef40SMatthew G. Knepley PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 225c094ef40SMatthew G. Knepley PetscValidHeaderSpecific(A, MAT_CLASSID, 3); 226c094ef40SMatthew G. Knepley ierr = PetscUseMethod(mat, "MatPreallocatorPreallocate_C", (Mat,PetscBool,Mat),(mat,fill,A));CHKERRQ(ierr); 227c094ef40SMatthew G. Knepley PetscFunctionReturn(0); 228c094ef40SMatthew G. Knepley } 229c094ef40SMatthew G. Knepley 230c094ef40SMatthew G. Knepley /*MC 231c094ef40SMatthew G. Knepley MATPREALLOCATOR - MATPREALLOCATOR = "preallocator" - A matrix type to be used for computing a matrix preallocation. 232c094ef40SMatthew G. Knepley 233c094ef40SMatthew G. Knepley Operations Provided: 234c094ef40SMatthew G. Knepley . MatSetValues() 235c094ef40SMatthew G. Knepley 236c094ef40SMatthew G. Knepley Options Database Keys: 237c094ef40SMatthew G. Knepley . -mat_type preallocator - sets the matrix type to "preallocator" during a call to MatSetFromOptions() 238c094ef40SMatthew G. Knepley 239c094ef40SMatthew G. Knepley Level: advanced 240c094ef40SMatthew G. Knepley 241c094ef40SMatthew G. Knepley .seealso: Mat 242c094ef40SMatthew G. Knepley 243c094ef40SMatthew G. Knepley M*/ 244c094ef40SMatthew G. Knepley 245c094ef40SMatthew G. Knepley PETSC_EXTERN PetscErrorCode MatCreate_Preallocator(Mat A) 246c094ef40SMatthew G. Knepley { 247c094ef40SMatthew G. Knepley Mat_Preallocator *p; 248c094ef40SMatthew G. Knepley PetscErrorCode ierr; 249c094ef40SMatthew G. Knepley 250c094ef40SMatthew G. Knepley PetscFunctionBegin; 251c094ef40SMatthew G. Knepley ierr = PetscNewLog(A, &p);CHKERRQ(ierr); 252c094ef40SMatthew G. Knepley A->data = (void *) p; 253c094ef40SMatthew G. Knepley 254c094ef40SMatthew G. Knepley p->ht = NULL; 255c094ef40SMatthew G. Knepley p->dnz = NULL; 256c094ef40SMatthew G. Knepley p->onz = NULL; 257c09129f1SStefano Zampini p->dnzu = NULL; 258c09129f1SStefano Zampini p->onzu = NULL; 259c094ef40SMatthew G. Knepley 260c094ef40SMatthew G. Knepley /* matrix ops */ 261c094ef40SMatthew G. Knepley ierr = PetscMemzero(A->ops, sizeof(struct _MatOps));CHKERRQ(ierr); 262c09129f1SStefano Zampini 263c094ef40SMatthew G. Knepley A->ops->destroy = MatDestroy_Preallocator; 264c094ef40SMatthew G. Knepley A->ops->setup = MatSetUp_Preallocator; 265c094ef40SMatthew G. Knepley A->ops->setvalues = MatSetValues_Preallocator; 266c094ef40SMatthew G. Knepley A->ops->assemblybegin = MatAssemblyBegin_Preallocator; 267c094ef40SMatthew G. Knepley A->ops->assemblyend = MatAssemblyEnd_Preallocator; 268c094ef40SMatthew G. Knepley A->ops->view = MatView_Preallocator; 269c094ef40SMatthew G. Knepley A->ops->setoption = MatSetOption_Preallocator; 2705dca1104SStefano Zampini A->ops->setblocksizes = MatSetBlockSizes_Default; /* once set, user is not allowed to change the block sizes */ 271c094ef40SMatthew G. Knepley 272c094ef40SMatthew G. Knepley /* special MATPREALLOCATOR functions */ 273c094ef40SMatthew G. Knepley ierr = PetscObjectComposeFunction((PetscObject) A, "MatPreallocatorPreallocate_C", MatPreallocatorPreallocate_Preallocator);CHKERRQ(ierr); 274c094ef40SMatthew G. Knepley ierr = PetscObjectChangeTypeName((PetscObject) A, MATPREALLOCATOR);CHKERRQ(ierr); 275c094ef40SMatthew G. Knepley PetscFunctionReturn(0); 276c094ef40SMatthew G. Knepley } 277