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; 149880e7892SJed Brown if (!fill) {ierr = PetscHSetIJDestroy(&p->ht);CHKERRQ(ierr);} 150c094ef40SMatthew G. Knepley ierr = MatGetBlockSize(mat, &bs);CHKERRQ(ierr); 151c09129f1SStefano Zampini ierr = MatXAIJSetPreallocation(A, bs, p->dnz, p->onz, p->dnzu, p->onzu);CHKERRQ(ierr); 152050c3c49SStefano Zampini ierr = MatSetUp(A);CHKERRQ(ierr); 153c094ef40SMatthew G. Knepley ierr = MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE);CHKERRQ(ierr); 154f8f6e9aeSStefano Zampini ierr = MatSetOption(A, MAT_NO_OFF_PROC_ENTRIES, p->nooffproc);CHKERRQ(ierr); 155380bf85aSDave May if (fill) { 156380bf85aSDave May PetscHashIter hi; 157380bf85aSDave May PetscHashIJKey key; 158380bf85aSDave May PetscScalar *zeros; 159880e7892SJed Brown PetscInt n,maxrow=1,*cols,rStart,rEnd,*rowstarts; 160380bf85aSDave May 161880e7892SJed Brown ierr = MatGetOwnershipRange(A, &rStart, &rEnd);CHKERRQ(ierr); 162880e7892SJed Brown // Ownership range is in terms of scalar entries, but we deal with blocks 163880e7892SJed Brown rStart /= bs; 164880e7892SJed Brown rEnd /= bs; 165146543f8SJed Brown ierr = PetscHSetIJGetSize(p->ht,&n);CHKERRQ(ierr); 166880e7892SJed Brown ierr = PetscMalloc2(n,&cols,rEnd-rStart+1,&rowstarts);CHKERRQ(ierr); 167880e7892SJed Brown rowstarts[0] = 0; 168880e7892SJed Brown for (PetscInt i=0; i<rEnd-rStart; i++) { 169880e7892SJed Brown rowstarts[i+1] = rowstarts[i] + p->dnz[i] + p->onz[i]; 170880e7892SJed Brown maxrow = PetscMax(maxrow, p->dnz[i] + p->onz[i]); 171880e7892SJed Brown } 172880e7892SJed Brown if (rowstarts[rEnd-rStart] != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Hash claims %D entries, but dnz+onz counts %D",n,rowstarts[rEnd-rStart]); 173880e7892SJed Brown 174380bf85aSDave May PetscHashIterBegin(p->ht,hi); 175146543f8SJed Brown for (PetscInt i=0; !PetscHashIterAtEnd(p->ht,hi); i++) { 176380bf85aSDave May PetscHashIterGetKey(p->ht,hi,key); 177880e7892SJed Brown PetscInt lrow = key.i - rStart; 178880e7892SJed Brown cols[rowstarts[lrow]] = key.j; 179880e7892SJed Brown rowstarts[lrow]++; 180380bf85aSDave May PetscHashIterNext(p->ht,hi); 181146543f8SJed Brown } 182146543f8SJed Brown ierr = PetscHSetIJDestroy(&p->ht);CHKERRQ(ierr); 183146543f8SJed Brown 184146543f8SJed Brown ierr = PetscCalloc1(maxrow*bs*bs,&zeros);CHKERRQ(ierr); 185880e7892SJed Brown for (PetscInt i=0; i<rEnd-rStart; i++) { 186880e7892SJed Brown PetscInt grow = rStart + i; 187880e7892SJed Brown PetscInt end = rowstarts[i], start = end - p->dnz[i] - p->onz[i]; 188146543f8SJed Brown ierr = PetscSortInt(end-start,&cols[start]);CHKERRQ(ierr); 189880e7892SJed Brown ierr = MatSetValuesBlocked(A, 1, &grow, end-start, &cols[start], zeros, INSERT_VALUES);CHKERRQ(ierr); 190380bf85aSDave May } 191380bf85aSDave May ierr = PetscFree(zeros);CHKERRQ(ierr); 192880e7892SJed Brown ierr = PetscFree2(cols,rowstarts);CHKERRQ(ierr); 193380bf85aSDave May 194380bf85aSDave May ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 195380bf85aSDave May ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 196380bf85aSDave May } 197c094ef40SMatthew G. Knepley PetscFunctionReturn(0); 198c094ef40SMatthew G. Knepley } 199c094ef40SMatthew G. Knepley 200c094ef40SMatthew G. Knepley /*@ 201380bf85aSDave May MatPreallocatorPreallocate - Preallocates the A matrix, using information from mat, optionally filling A with zeros 202c094ef40SMatthew G. Knepley 203*d8d19677SJose E. Roman Input Parameters: 204c094ef40SMatthew G. Knepley + mat - the preallocator 205380bf85aSDave May . fill - fill the matrix with zeros 206380bf85aSDave May - A - the matrix to be preallocated 207c094ef40SMatthew G. Knepley 208380bf85aSDave May Notes: 209380bf85aSDave May This Mat implementation provides a helper utility to define the correct 210380bf85aSDave May preallocation data for a given nonzero structure. Use this object like a 211380bf85aSDave May regular matrix, e.g. loop over the nonzero structure of the matrix and 212380bf85aSDave May call MatSetValues() or MatSetValuesBlocked() to indicate the nonzero locations. 213a5b23f4aSJose E. Roman The matrix entries provided to MatSetValues() will be ignored, it only uses 214380bf85aSDave May the row / col indices provided to determine the information required to be 215380bf85aSDave May passed to MatXAIJSetPreallocation(). Once you have looped over the nonzero 216380bf85aSDave May structure, you must call MatAssemblyBegin(), MatAssemblyEnd() on mat. 217380bf85aSDave May 218380bf85aSDave May After you have assembled the preallocator matrix (mat), call MatPreallocatorPreallocate() 219380bf85aSDave May to define the preallocation information on the matrix (A). Setting the parameter 220380bf85aSDave May fill = PETSC_TRUE will insert zeros into the matrix A. Internally MatPreallocatorPreallocate() 221380bf85aSDave May will call MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE); 222c094ef40SMatthew G. Knepley 223c094ef40SMatthew G. Knepley Level: advanced 224c094ef40SMatthew G. Knepley 225c094ef40SMatthew G. Knepley .seealso: MATPREALLOCATOR 226c094ef40SMatthew G. Knepley @*/ 227c094ef40SMatthew G. Knepley PetscErrorCode MatPreallocatorPreallocate(Mat mat, PetscBool fill, Mat A) 228c094ef40SMatthew G. Knepley { 229c094ef40SMatthew G. Knepley PetscErrorCode ierr; 230c094ef40SMatthew G. Knepley 231c094ef40SMatthew G. Knepley PetscFunctionBegin; 232c094ef40SMatthew G. Knepley PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 233c094ef40SMatthew G. Knepley PetscValidHeaderSpecific(A, MAT_CLASSID, 3); 234c094ef40SMatthew G. Knepley ierr = PetscUseMethod(mat, "MatPreallocatorPreallocate_C", (Mat,PetscBool,Mat),(mat,fill,A));CHKERRQ(ierr); 235c094ef40SMatthew G. Knepley PetscFunctionReturn(0); 236c094ef40SMatthew G. Knepley } 237c094ef40SMatthew G. Knepley 238c094ef40SMatthew G. Knepley /*MC 239c094ef40SMatthew G. Knepley MATPREALLOCATOR - MATPREALLOCATOR = "preallocator" - A matrix type to be used for computing a matrix preallocation. 240c094ef40SMatthew G. Knepley 241c094ef40SMatthew G. Knepley Operations Provided: 242c094ef40SMatthew G. Knepley . MatSetValues() 243c094ef40SMatthew G. Knepley 244c094ef40SMatthew G. Knepley Options Database Keys: 245c094ef40SMatthew G. Knepley . -mat_type preallocator - sets the matrix type to "preallocator" during a call to MatSetFromOptions() 246c094ef40SMatthew G. Knepley 247c094ef40SMatthew G. Knepley Level: advanced 248c094ef40SMatthew G. Knepley 249c094ef40SMatthew G. Knepley .seealso: Mat 250c094ef40SMatthew G. Knepley 251c094ef40SMatthew G. Knepley M*/ 252c094ef40SMatthew G. Knepley 253c094ef40SMatthew G. Knepley PETSC_EXTERN PetscErrorCode MatCreate_Preallocator(Mat A) 254c094ef40SMatthew G. Knepley { 255c094ef40SMatthew G. Knepley Mat_Preallocator *p; 256c094ef40SMatthew G. Knepley PetscErrorCode ierr; 257c094ef40SMatthew G. Knepley 258c094ef40SMatthew G. Knepley PetscFunctionBegin; 259c094ef40SMatthew G. Knepley ierr = PetscNewLog(A, &p);CHKERRQ(ierr); 260c094ef40SMatthew G. Knepley A->data = (void *) p; 261c094ef40SMatthew G. Knepley 262c094ef40SMatthew G. Knepley p->ht = NULL; 263c094ef40SMatthew G. Knepley p->dnz = NULL; 264c094ef40SMatthew G. Knepley p->onz = NULL; 265c09129f1SStefano Zampini p->dnzu = NULL; 266c09129f1SStefano Zampini p->onzu = NULL; 267c094ef40SMatthew G. Knepley 268c094ef40SMatthew G. Knepley /* matrix ops */ 269c094ef40SMatthew G. Knepley ierr = PetscMemzero(A->ops, sizeof(struct _MatOps));CHKERRQ(ierr); 270c09129f1SStefano Zampini 271c094ef40SMatthew G. Knepley A->ops->destroy = MatDestroy_Preallocator; 272c094ef40SMatthew G. Knepley A->ops->setup = MatSetUp_Preallocator; 273c094ef40SMatthew G. Knepley A->ops->setvalues = MatSetValues_Preallocator; 274c094ef40SMatthew G. Knepley A->ops->assemblybegin = MatAssemblyBegin_Preallocator; 275c094ef40SMatthew G. Knepley A->ops->assemblyend = MatAssemblyEnd_Preallocator; 276c094ef40SMatthew G. Knepley A->ops->view = MatView_Preallocator; 277c094ef40SMatthew G. Knepley A->ops->setoption = MatSetOption_Preallocator; 2785dca1104SStefano Zampini A->ops->setblocksizes = MatSetBlockSizes_Default; /* once set, user is not allowed to change the block sizes */ 279c094ef40SMatthew G. Knepley 280c094ef40SMatthew G. Knepley /* special MATPREALLOCATOR functions */ 281c094ef40SMatthew G. Knepley ierr = PetscObjectComposeFunction((PetscObject) A, "MatPreallocatorPreallocate_C", MatPreallocatorPreallocate_Preallocator);CHKERRQ(ierr); 282c094ef40SMatthew G. Knepley ierr = PetscObjectChangeTypeName((PetscObject) A, MATPREALLOCATOR);CHKERRQ(ierr); 283c094ef40SMatthew G. Knepley PetscFunctionReturn(0); 284c094ef40SMatthew G. Knepley } 285