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; 8c094ef40SMatthew G. Knepley } Mat_Preallocator; 9c094ef40SMatthew G. Knepley 10c094ef40SMatthew G. Knepley PetscErrorCode MatDestroy_Preallocator(Mat A) 11c094ef40SMatthew G. Knepley { 12c094ef40SMatthew G. Knepley Mat_Preallocator *p = (Mat_Preallocator *) A->data; 13c094ef40SMatthew G. Knepley PetscErrorCode ierr; 14c094ef40SMatthew G. Knepley 15c094ef40SMatthew G. Knepley PetscFunctionBegin; 16c094ef40SMatthew G. Knepley ierr = MatStashDestroy_Private(&A->stash);CHKERRQ(ierr); 17e8f14785SLisandro Dalcin ierr = PetscHSetIJDestroy(&p->ht);CHKERRQ(ierr); 18c09129f1SStefano Zampini ierr = PetscFree4(p->dnz, p->onz, p->dnzu, p->onzu);CHKERRQ(ierr); 19c094ef40SMatthew G. Knepley ierr = PetscFree(A->data);CHKERRQ(ierr); 20c094ef40SMatthew G. Knepley ierr = PetscObjectChangeTypeName((PetscObject) A, 0);CHKERRQ(ierr); 21c094ef40SMatthew G. Knepley ierr = PetscObjectComposeFunction((PetscObject) A, "MatPreallocatorPreallocate_C", NULL);CHKERRQ(ierr); 22c094ef40SMatthew G. Knepley PetscFunctionReturn(0); 23c094ef40SMatthew G. Knepley } 24c094ef40SMatthew G. Knepley 25c094ef40SMatthew G. Knepley PetscErrorCode MatSetUp_Preallocator(Mat A) 26c094ef40SMatthew G. Knepley { 27c094ef40SMatthew G. Knepley Mat_Preallocator *p = (Mat_Preallocator *) A->data; 285dca1104SStefano Zampini PetscInt m, bs, mbs; 29c094ef40SMatthew G. Knepley PetscErrorCode ierr; 30c094ef40SMatthew G. Knepley 31c094ef40SMatthew G. Knepley PetscFunctionBegin; 32c094ef40SMatthew G. Knepley ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr); 33c094ef40SMatthew G. Knepley ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr); 34c094ef40SMatthew G. Knepley ierr = MatGetLocalSize(A, &m, NULL);CHKERRQ(ierr); 35e8f14785SLisandro Dalcin ierr = PetscHSetIJCreate(&p->ht);CHKERRQ(ierr); 36c094ef40SMatthew G. Knepley ierr = MatGetBlockSize(A, &bs);CHKERRQ(ierr); 37c094ef40SMatthew G. Knepley ierr = MatStashCreate_Private(PetscObjectComm((PetscObject) A), bs, &A->stash);CHKERRQ(ierr); 385dca1104SStefano Zampini /* arrays are for blocked rows/cols */ 395dca1104SStefano Zampini mbs = m/bs; 405dca1104SStefano Zampini ierr = PetscCalloc4(mbs, &p->dnz, mbs, &p->onz, mbs, &p->dnzu, mbs, &p->onzu);CHKERRQ(ierr); 41c094ef40SMatthew G. Knepley PetscFunctionReturn(0); 42c094ef40SMatthew G. Knepley } 43c094ef40SMatthew G. Knepley 44c094ef40SMatthew G. Knepley PetscErrorCode MatSetValues_Preallocator(Mat A, PetscInt m, const PetscInt *rows, PetscInt n, const PetscInt *cols, const PetscScalar *values, InsertMode addv) 45c094ef40SMatthew G. Knepley { 46c094ef40SMatthew G. Knepley Mat_Preallocator *p = (Mat_Preallocator *) A->data; 475dca1104SStefano Zampini PetscInt rStart, rEnd, r, cStart, cEnd, c, bs; 48c094ef40SMatthew G. Knepley PetscErrorCode ierr; 49c094ef40SMatthew G. Knepley 50c094ef40SMatthew G. Knepley PetscFunctionBegin; 515dca1104SStefano Zampini ierr = MatGetBlockSize(A, &bs);CHKERRQ(ierr); 52c094ef40SMatthew G. Knepley ierr = MatGetOwnershipRange(A, &rStart, &rEnd);CHKERRQ(ierr); 53c094ef40SMatthew G. Knepley ierr = MatGetOwnershipRangeColumn(A, &cStart, &cEnd);CHKERRQ(ierr); 54c094ef40SMatthew G. Knepley for (r = 0; r < m; ++r) { 55e8f14785SLisandro Dalcin PetscHashIJKey key; 56e8f14785SLisandro Dalcin PetscBool missing; 57c094ef40SMatthew G. Knepley 58e8f14785SLisandro Dalcin key.i = rows[r]; 59e8f14785SLisandro Dalcin if (key.i < 0) continue; 60e8f14785SLisandro Dalcin if ((key.i < rStart) || (key.i >= rEnd)) { 61e8f14785SLisandro Dalcin ierr = MatStashValuesRow_Private(&A->stash, key.i, n, cols, values, PETSC_FALSE);CHKERRQ(ierr); 625dca1104SStefano Zampini } else { /* Hash table is for blocked rows/cols */ 635dca1104SStefano Zampini key.i = rows[r]/bs; 64c094ef40SMatthew G. Knepley for (c = 0; c < n; ++c) { 655dca1104SStefano Zampini key.j = cols[c]/bs; 66e8f14785SLisandro Dalcin if (key.j < 0) continue; 67e8f14785SLisandro Dalcin ierr = PetscHSetIJQueryAdd(p->ht, key, &missing);CHKERRQ(ierr); 68c094ef40SMatthew G. Knepley if (missing) { 695dca1104SStefano Zampini if ((key.j >= cStart/bs) && (key.j < cEnd/bs)) { 705dca1104SStefano Zampini ++p->dnz[key.i-rStart/bs]; 715dca1104SStefano Zampini if (key.j >= key.i) ++p->dnzu[key.i-rStart/bs]; 72c09129f1SStefano Zampini } else { 735dca1104SStefano Zampini ++p->onz[key.i-rStart/bs]; 745dca1104SStefano Zampini if (key.j >= key.i) ++p->onzu[key.i-rStart/bs]; 75c09129f1SStefano Zampini } 76c094ef40SMatthew G. Knepley } 77c094ef40SMatthew G. Knepley } 78c094ef40SMatthew G. Knepley } 79c094ef40SMatthew G. Knepley } 80c094ef40SMatthew G. Knepley PetscFunctionReturn(0); 81c094ef40SMatthew G. Knepley } 82c094ef40SMatthew G. Knepley 83c094ef40SMatthew G. Knepley PetscErrorCode MatAssemblyBegin_Preallocator(Mat A, MatAssemblyType type) 84c094ef40SMatthew G. Knepley { 85c094ef40SMatthew G. Knepley PetscInt nstash, reallocs; 86c094ef40SMatthew G. Knepley PetscErrorCode ierr; 87c094ef40SMatthew G. Knepley 88c094ef40SMatthew G. Knepley PetscFunctionBegin; 89c094ef40SMatthew G. Knepley ierr = MatStashScatterBegin_Private(A, &A->stash, A->rmap->range);CHKERRQ(ierr); 90c094ef40SMatthew G. Knepley ierr = MatStashGetInfo_Private(&A->stash, &nstash, &reallocs);CHKERRQ(ierr); 91c094ef40SMatthew G. Knepley ierr = PetscInfo2(A, "Stash has %D entries, uses %D mallocs.\n", nstash, reallocs);CHKERRQ(ierr); 92c094ef40SMatthew G. Knepley PetscFunctionReturn(0); 93c094ef40SMatthew G. Knepley } 94c094ef40SMatthew G. Knepley 95c094ef40SMatthew G. Knepley PetscErrorCode MatAssemblyEnd_Preallocator(Mat A, MatAssemblyType type) 96c094ef40SMatthew G. Knepley { 97c094ef40SMatthew G. Knepley PetscScalar *val; 98c094ef40SMatthew G. Knepley PetscInt *row, *col; 99c094ef40SMatthew G. Knepley PetscInt i, j, rstart, ncols, flg; 100c094ef40SMatthew G. Knepley PetscMPIInt n; 101c094ef40SMatthew G. Knepley PetscErrorCode ierr; 102c094ef40SMatthew G. Knepley 103c094ef40SMatthew G. Knepley PetscFunctionBegin; 104c094ef40SMatthew G. Knepley while (1) { 105c094ef40SMatthew G. Knepley ierr = MatStashScatterGetMesg_Private(&A->stash, &n, &row, &col, &val, &flg);CHKERRQ(ierr); 106c094ef40SMatthew G. Knepley if (!flg) break; 107c094ef40SMatthew G. Knepley 108c094ef40SMatthew G. Knepley for (i = 0; i < n; ) { 109c094ef40SMatthew G. Knepley /* Now identify the consecutive vals belonging to the same row */ 110c094ef40SMatthew G. Knepley for (j = i, rstart = row[j]; j < n; j++) { 111c094ef40SMatthew G. Knepley if (row[j] != rstart) break; 112c094ef40SMatthew G. Knepley } 113c094ef40SMatthew G. Knepley if (j < n) ncols = j-i; 114c094ef40SMatthew G. Knepley else ncols = n-i; 115c094ef40SMatthew G. Knepley /* Now assemble all these values with a single function call */ 116c094ef40SMatthew G. Knepley ierr = MatSetValues_Preallocator(A, 1, row+i, ncols, col+i, val+i, INSERT_VALUES);CHKERRQ(ierr); 117c094ef40SMatthew G. Knepley i = j; 118c094ef40SMatthew G. Knepley } 119c094ef40SMatthew G. Knepley } 120c094ef40SMatthew G. Knepley ierr = MatStashScatterEnd_Private(&A->stash);CHKERRQ(ierr); 121c094ef40SMatthew G. Knepley PetscFunctionReturn(0); 122c094ef40SMatthew G. Knepley } 123c094ef40SMatthew G. Knepley 124c094ef40SMatthew G. Knepley PetscErrorCode MatView_Preallocator(Mat A, PetscViewer viewer) 125c094ef40SMatthew G. Knepley { 126c094ef40SMatthew G. Knepley PetscFunctionBegin; 127c094ef40SMatthew G. Knepley PetscFunctionReturn(0); 128c094ef40SMatthew G. Knepley } 129c094ef40SMatthew G. Knepley 130c094ef40SMatthew G. Knepley PetscErrorCode MatSetOption_Preallocator(Mat A, MatOption op, PetscBool flg) 131c094ef40SMatthew G. Knepley { 132c094ef40SMatthew G. Knepley PetscFunctionBegin; 133c094ef40SMatthew G. Knepley PetscFunctionReturn(0); 134c094ef40SMatthew G. Knepley } 135c094ef40SMatthew G. Knepley 136c094ef40SMatthew G. Knepley PetscErrorCode MatPreallocatorPreallocate_Preallocator(Mat mat, PetscBool fill, Mat A) 137c094ef40SMatthew G. Knepley { 138c094ef40SMatthew G. Knepley Mat_Preallocator *p = (Mat_Preallocator *) mat->data; 139c094ef40SMatthew G. Knepley PetscInt bs; 140c094ef40SMatthew G. Knepley PetscErrorCode ierr; 141c094ef40SMatthew G. Knepley 142c094ef40SMatthew G. Knepley PetscFunctionBegin; 143c094ef40SMatthew G. Knepley ierr = MatGetBlockSize(mat, &bs);CHKERRQ(ierr); 144c09129f1SStefano Zampini ierr = MatXAIJSetPreallocation(A, bs, p->dnz, p->onz, p->dnzu, p->onzu);CHKERRQ(ierr); 145c094ef40SMatthew G. Knepley ierr = MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE);CHKERRQ(ierr); 146*380bf85aSDave May if (fill) { 147*380bf85aSDave May PetscHashIter hi; 148*380bf85aSDave May PetscHashIJKey key; 149*380bf85aSDave May PetscScalar *zeros; 150*380bf85aSDave May 151*380bf85aSDave May ierr = PetscCalloc1(bs*bs,&zeros);CHKERRQ(ierr); 152*380bf85aSDave May 153*380bf85aSDave May PetscHashIterBegin(p->ht,hi); 154*380bf85aSDave May while (!PetscHashIterAtEnd(p->ht,hi)) { 155*380bf85aSDave May PetscHashIterGetKey(p->ht,hi,key); 156*380bf85aSDave May PetscHashIterNext(p->ht,hi); 157*380bf85aSDave May ierr = MatSetValuesBlocked(A,1,&key.i,1,&key.j,zeros,INSERT_VALUES);CHKERRQ(ierr); 158*380bf85aSDave May } 159*380bf85aSDave May ierr = PetscFree(zeros);CHKERRQ(ierr); 160*380bf85aSDave May 161*380bf85aSDave May ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 162*380bf85aSDave May ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 163*380bf85aSDave May } 164c094ef40SMatthew G. Knepley PetscFunctionReturn(0); 165c094ef40SMatthew G. Knepley } 166c094ef40SMatthew G. Knepley 167c094ef40SMatthew G. Knepley /*@ 168*380bf85aSDave May MatPreallocatorPreallocate - Preallocates the A matrix, using information from mat, optionally filling A with zeros 169c094ef40SMatthew G. Knepley 170c094ef40SMatthew G. Knepley Input Parameter: 171c094ef40SMatthew G. Knepley + mat - the preallocator 172*380bf85aSDave May . fill - fill the matrix with zeros 173*380bf85aSDave May - A - the matrix to be preallocated 174c094ef40SMatthew G. Knepley 175*380bf85aSDave May Notes: 176*380bf85aSDave May This Mat implementation provides a helper utility to define the correct 177*380bf85aSDave May preallocation data for a given nonzero structure. Use this object like a 178*380bf85aSDave May regular matrix, e.g. loop over the nonzero structure of the matrix and 179*380bf85aSDave May call MatSetValues() or MatSetValuesBlocked() to indicate the nonzero locations. 180*380bf85aSDave May The matrix entires provided to MatSetValues() will be ignored, it only uses 181*380bf85aSDave May the row / col indices provided to determine the information required to be 182*380bf85aSDave May passed to MatXAIJSetPreallocation(). Once you have looped over the nonzero 183*380bf85aSDave May structure, you must call MatAssemblyBegin(), MatAssemblyEnd() on mat. 184*380bf85aSDave May 185*380bf85aSDave May After you have assembled the preallocator matrix (mat), call MatPreallocatorPreallocate() 186*380bf85aSDave May to define the preallocation information on the matrix (A). Setting the parameter 187*380bf85aSDave May fill = PETSC_TRUE will insert zeros into the matrix A. Internally MatPreallocatorPreallocate() 188*380bf85aSDave May will call MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE); 189c094ef40SMatthew G. Knepley 190c094ef40SMatthew G. Knepley Level: advanced 191c094ef40SMatthew G. Knepley 192c094ef40SMatthew G. Knepley .seealso: MATPREALLOCATOR 193c094ef40SMatthew G. Knepley @*/ 194c094ef40SMatthew G. Knepley PetscErrorCode MatPreallocatorPreallocate(Mat mat, PetscBool fill, Mat A) 195c094ef40SMatthew G. Knepley { 196c094ef40SMatthew G. Knepley PetscErrorCode ierr; 197c094ef40SMatthew G. Knepley 198c094ef40SMatthew G. Knepley PetscFunctionBegin; 199c094ef40SMatthew G. Knepley PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 200c094ef40SMatthew G. Knepley PetscValidHeaderSpecific(A, MAT_CLASSID, 3); 201c094ef40SMatthew G. Knepley ierr = PetscUseMethod(mat, "MatPreallocatorPreallocate_C", (Mat,PetscBool,Mat),(mat,fill,A));CHKERRQ(ierr); 202c094ef40SMatthew G. Knepley PetscFunctionReturn(0); 203c094ef40SMatthew G. Knepley } 204c094ef40SMatthew G. Knepley 205c094ef40SMatthew G. Knepley /*MC 206c094ef40SMatthew G. Knepley MATPREALLOCATOR - MATPREALLOCATOR = "preallocator" - A matrix type to be used for computing a matrix preallocation. 207c094ef40SMatthew G. Knepley 208c094ef40SMatthew G. Knepley Operations Provided: 209c094ef40SMatthew G. Knepley . MatSetValues() 210c094ef40SMatthew G. Knepley 211c094ef40SMatthew G. Knepley Options Database Keys: 212c094ef40SMatthew G. Knepley . -mat_type preallocator - sets the matrix type to "preallocator" during a call to MatSetFromOptions() 213c094ef40SMatthew G. Knepley 214c094ef40SMatthew G. Knepley Level: advanced 215c094ef40SMatthew G. Knepley 216c094ef40SMatthew G. Knepley .seealso: Mat 217c094ef40SMatthew G. Knepley 218c094ef40SMatthew G. Knepley M*/ 219c094ef40SMatthew G. Knepley 220c094ef40SMatthew G. Knepley PETSC_EXTERN PetscErrorCode MatCreate_Preallocator(Mat A) 221c094ef40SMatthew G. Knepley { 222c094ef40SMatthew G. Knepley Mat_Preallocator *p; 223c094ef40SMatthew G. Knepley PetscErrorCode ierr; 224c094ef40SMatthew G. Knepley 225c094ef40SMatthew G. Knepley PetscFunctionBegin; 226c094ef40SMatthew G. Knepley ierr = PetscNewLog(A, &p);CHKERRQ(ierr); 227c094ef40SMatthew G. Knepley A->data = (void *) p; 228c094ef40SMatthew G. Knepley 229c094ef40SMatthew G. Knepley p->ht = NULL; 230c094ef40SMatthew G. Knepley p->dnz = NULL; 231c094ef40SMatthew G. Knepley p->onz = NULL; 232c09129f1SStefano Zampini p->dnzu = NULL; 233c09129f1SStefano Zampini p->onzu = NULL; 234c094ef40SMatthew G. Knepley 235c094ef40SMatthew G. Knepley /* matrix ops */ 236c094ef40SMatthew G. Knepley ierr = PetscMemzero(A->ops, sizeof(struct _MatOps));CHKERRQ(ierr); 237c09129f1SStefano Zampini 238c094ef40SMatthew G. Knepley A->ops->destroy = MatDestroy_Preallocator; 239c094ef40SMatthew G. Knepley A->ops->setup = MatSetUp_Preallocator; 240c094ef40SMatthew G. Knepley A->ops->setvalues = MatSetValues_Preallocator; 241c094ef40SMatthew G. Knepley A->ops->assemblybegin = MatAssemblyBegin_Preallocator; 242c094ef40SMatthew G. Knepley A->ops->assemblyend = MatAssemblyEnd_Preallocator; 243c094ef40SMatthew G. Knepley A->ops->view = MatView_Preallocator; 244c094ef40SMatthew G. Knepley A->ops->setoption = MatSetOption_Preallocator; 2455dca1104SStefano Zampini A->ops->setblocksizes = MatSetBlockSizes_Default; /* once set, user is not allowed to change the block sizes */ 246c094ef40SMatthew G. Knepley 247c094ef40SMatthew G. Knepley /* special MATPREALLOCATOR functions */ 248c094ef40SMatthew G. Knepley ierr = PetscObjectComposeFunction((PetscObject) A, "MatPreallocatorPreallocate_C", MatPreallocatorPreallocate_Preallocator);CHKERRQ(ierr); 249c094ef40SMatthew G. Knepley ierr = PetscObjectChangeTypeName((PetscObject) A, MATPREALLOCATOR);CHKERRQ(ierr); 250c094ef40SMatthew G. Knepley PetscFunctionReturn(0); 251c094ef40SMatthew G. Knepley } 252