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); 37*8011973bSJunchao Zhang /* Do not bother bstash since MatPreallocator does not implement MatSetValuesBlocked */ 38*8011973bSJunchao Zhang ierr = MatStashCreate_Private(PetscObjectComm((PetscObject) A), 1, &A->stash);CHKERRQ(ierr); 395dca1104SStefano Zampini /* arrays are for blocked rows/cols */ 405dca1104SStefano Zampini mbs = m/bs; 415dca1104SStefano Zampini ierr = PetscCalloc4(mbs, &p->dnz, mbs, &p->onz, mbs, &p->dnzu, mbs, &p->onzu);CHKERRQ(ierr); 42c094ef40SMatthew G. Knepley PetscFunctionReturn(0); 43c094ef40SMatthew G. Knepley } 44c094ef40SMatthew G. Knepley 45c094ef40SMatthew G. Knepley PetscErrorCode MatSetValues_Preallocator(Mat A, PetscInt m, const PetscInt *rows, PetscInt n, const PetscInt *cols, const PetscScalar *values, InsertMode addv) 46c094ef40SMatthew G. Knepley { 47c094ef40SMatthew G. Knepley Mat_Preallocator *p = (Mat_Preallocator *) A->data; 485dca1104SStefano Zampini PetscInt rStart, rEnd, r, cStart, cEnd, c, bs; 49c094ef40SMatthew G. Knepley PetscErrorCode ierr; 50c094ef40SMatthew G. Knepley 51c094ef40SMatthew G. Knepley PetscFunctionBegin; 525dca1104SStefano Zampini ierr = MatGetBlockSize(A, &bs);CHKERRQ(ierr); 53c094ef40SMatthew G. Knepley ierr = MatGetOwnershipRange(A, &rStart, &rEnd);CHKERRQ(ierr); 54c094ef40SMatthew G. Knepley ierr = MatGetOwnershipRangeColumn(A, &cStart, &cEnd);CHKERRQ(ierr); 55c094ef40SMatthew G. Knepley for (r = 0; r < m; ++r) { 56e8f14785SLisandro Dalcin PetscHashIJKey key; 57e8f14785SLisandro Dalcin PetscBool missing; 58c094ef40SMatthew G. Knepley 59e8f14785SLisandro Dalcin key.i = rows[r]; 60e8f14785SLisandro Dalcin if (key.i < 0) continue; 61e8f14785SLisandro Dalcin if ((key.i < rStart) || (key.i >= rEnd)) { 62e8f14785SLisandro Dalcin ierr = MatStashValuesRow_Private(&A->stash, key.i, n, cols, values, PETSC_FALSE);CHKERRQ(ierr); 635dca1104SStefano Zampini } else { /* Hash table is for blocked rows/cols */ 645dca1104SStefano Zampini key.i = rows[r]/bs; 65c094ef40SMatthew G. Knepley for (c = 0; c < n; ++c) { 665dca1104SStefano Zampini key.j = cols[c]/bs; 67e8f14785SLisandro Dalcin if (key.j < 0) continue; 68e8f14785SLisandro Dalcin ierr = PetscHSetIJQueryAdd(p->ht, key, &missing);CHKERRQ(ierr); 69c094ef40SMatthew G. Knepley if (missing) { 705dca1104SStefano Zampini if ((key.j >= cStart/bs) && (key.j < cEnd/bs)) { 715dca1104SStefano Zampini ++p->dnz[key.i-rStart/bs]; 725dca1104SStefano Zampini if (key.j >= key.i) ++p->dnzu[key.i-rStart/bs]; 73c09129f1SStefano Zampini } else { 745dca1104SStefano Zampini ++p->onz[key.i-rStart/bs]; 755dca1104SStefano Zampini if (key.j >= key.i) ++p->onzu[key.i-rStart/bs]; 76c09129f1SStefano Zampini } 77c094ef40SMatthew G. Knepley } 78c094ef40SMatthew G. Knepley } 79c094ef40SMatthew G. Knepley } 80c094ef40SMatthew G. Knepley } 81c094ef40SMatthew G. Knepley PetscFunctionReturn(0); 82c094ef40SMatthew G. Knepley } 83c094ef40SMatthew G. Knepley 84c094ef40SMatthew G. Knepley PetscErrorCode MatAssemblyBegin_Preallocator(Mat A, MatAssemblyType type) 85c094ef40SMatthew G. Knepley { 86c094ef40SMatthew G. Knepley PetscInt nstash, reallocs; 87c094ef40SMatthew G. Knepley PetscErrorCode ierr; 88c094ef40SMatthew G. Knepley 89c094ef40SMatthew G. Knepley PetscFunctionBegin; 90c094ef40SMatthew G. Knepley ierr = MatStashScatterBegin_Private(A, &A->stash, A->rmap->range);CHKERRQ(ierr); 91c094ef40SMatthew G. Knepley ierr = MatStashGetInfo_Private(&A->stash, &nstash, &reallocs);CHKERRQ(ierr); 92c094ef40SMatthew G. Knepley ierr = PetscInfo2(A, "Stash has %D entries, uses %D mallocs.\n", nstash, reallocs);CHKERRQ(ierr); 93c094ef40SMatthew G. Knepley PetscFunctionReturn(0); 94c094ef40SMatthew G. Knepley } 95c094ef40SMatthew G. Knepley 96c094ef40SMatthew G. Knepley PetscErrorCode MatAssemblyEnd_Preallocator(Mat A, MatAssemblyType type) 97c094ef40SMatthew G. Knepley { 98c094ef40SMatthew G. Knepley PetscScalar *val; 99c094ef40SMatthew G. Knepley PetscInt *row, *col; 100c094ef40SMatthew G. Knepley PetscInt i, j, rstart, ncols, flg; 101c094ef40SMatthew G. Knepley PetscMPIInt n; 102c094ef40SMatthew G. Knepley PetscErrorCode ierr; 103c094ef40SMatthew G. Knepley 104c094ef40SMatthew G. Knepley PetscFunctionBegin; 105c094ef40SMatthew G. Knepley while (1) { 106c094ef40SMatthew G. Knepley ierr = MatStashScatterGetMesg_Private(&A->stash, &n, &row, &col, &val, &flg);CHKERRQ(ierr); 107c094ef40SMatthew G. Knepley if (!flg) break; 108c094ef40SMatthew G. Knepley 109c094ef40SMatthew G. Knepley for (i = 0; i < n; ) { 110c094ef40SMatthew G. Knepley /* Now identify the consecutive vals belonging to the same row */ 111c094ef40SMatthew G. Knepley for (j = i, rstart = row[j]; j < n; j++) { 112c094ef40SMatthew G. Knepley if (row[j] != rstart) break; 113c094ef40SMatthew G. Knepley } 114c094ef40SMatthew G. Knepley if (j < n) ncols = j-i; 115c094ef40SMatthew G. Knepley else ncols = n-i; 116c094ef40SMatthew G. Knepley /* Now assemble all these values with a single function call */ 117c094ef40SMatthew G. Knepley ierr = MatSetValues_Preallocator(A, 1, row+i, ncols, col+i, val+i, INSERT_VALUES);CHKERRQ(ierr); 118c094ef40SMatthew G. Knepley i = j; 119c094ef40SMatthew G. Knepley } 120c094ef40SMatthew G. Knepley } 121c094ef40SMatthew G. Knepley ierr = MatStashScatterEnd_Private(&A->stash);CHKERRQ(ierr); 122c094ef40SMatthew G. Knepley PetscFunctionReturn(0); 123c094ef40SMatthew G. Knepley } 124c094ef40SMatthew G. Knepley 125c094ef40SMatthew G. Knepley PetscErrorCode MatView_Preallocator(Mat A, PetscViewer viewer) 126c094ef40SMatthew G. Knepley { 127c094ef40SMatthew G. Knepley PetscFunctionBegin; 128c094ef40SMatthew G. Knepley PetscFunctionReturn(0); 129c094ef40SMatthew G. Knepley } 130c094ef40SMatthew G. Knepley 131c094ef40SMatthew G. Knepley PetscErrorCode MatSetOption_Preallocator(Mat A, MatOption op, PetscBool flg) 132c094ef40SMatthew G. Knepley { 133c094ef40SMatthew G. Knepley PetscFunctionBegin; 134c094ef40SMatthew G. Knepley PetscFunctionReturn(0); 135c094ef40SMatthew G. Knepley } 136c094ef40SMatthew G. Knepley 137c094ef40SMatthew G. Knepley PetscErrorCode MatPreallocatorPreallocate_Preallocator(Mat mat, PetscBool fill, Mat A) 138c094ef40SMatthew G. Knepley { 139c094ef40SMatthew G. Knepley Mat_Preallocator *p = (Mat_Preallocator *) mat->data; 140c094ef40SMatthew G. Knepley PetscInt bs; 141c094ef40SMatthew G. Knepley PetscErrorCode ierr; 142c094ef40SMatthew G. Knepley 143c094ef40SMatthew G. Knepley PetscFunctionBegin; 144c094ef40SMatthew G. Knepley ierr = MatGetBlockSize(mat, &bs);CHKERRQ(ierr); 145c09129f1SStefano Zampini ierr = MatXAIJSetPreallocation(A, bs, p->dnz, p->onz, p->dnzu, p->onzu);CHKERRQ(ierr); 146c094ef40SMatthew G. Knepley ierr = MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE);CHKERRQ(ierr); 147380bf85aSDave May if (fill) { 148380bf85aSDave May PetscHashIter hi; 149380bf85aSDave May PetscHashIJKey key; 150380bf85aSDave May PetscScalar *zeros; 151380bf85aSDave May 152380bf85aSDave May ierr = PetscCalloc1(bs*bs,&zeros);CHKERRQ(ierr); 153380bf85aSDave May 154380bf85aSDave May PetscHashIterBegin(p->ht,hi); 155380bf85aSDave May while (!PetscHashIterAtEnd(p->ht,hi)) { 156380bf85aSDave May PetscHashIterGetKey(p->ht,hi,key); 157380bf85aSDave May PetscHashIterNext(p->ht,hi); 158380bf85aSDave May ierr = MatSetValuesBlocked(A,1,&key.i,1,&key.j,zeros,INSERT_VALUES);CHKERRQ(ierr); 159380bf85aSDave May } 160380bf85aSDave May ierr = PetscFree(zeros);CHKERRQ(ierr); 161380bf85aSDave May 162380bf85aSDave May ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 163380bf85aSDave May ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 164380bf85aSDave May } 165c094ef40SMatthew G. Knepley PetscFunctionReturn(0); 166c094ef40SMatthew G. Knepley } 167c094ef40SMatthew G. Knepley 168c094ef40SMatthew G. Knepley /*@ 169380bf85aSDave May MatPreallocatorPreallocate - Preallocates the A matrix, using information from mat, optionally filling A with zeros 170c094ef40SMatthew G. Knepley 171c094ef40SMatthew G. Knepley Input Parameter: 172c094ef40SMatthew G. Knepley + mat - the preallocator 173380bf85aSDave May . fill - fill the matrix with zeros 174380bf85aSDave May - A - the matrix to be preallocated 175c094ef40SMatthew G. Knepley 176380bf85aSDave May Notes: 177380bf85aSDave May This Mat implementation provides a helper utility to define the correct 178380bf85aSDave May preallocation data for a given nonzero structure. Use this object like a 179380bf85aSDave May regular matrix, e.g. loop over the nonzero structure of the matrix and 180380bf85aSDave May call MatSetValues() or MatSetValuesBlocked() to indicate the nonzero locations. 181380bf85aSDave May The matrix entires provided to MatSetValues() will be ignored, it only uses 182380bf85aSDave May the row / col indices provided to determine the information required to be 183380bf85aSDave May passed to MatXAIJSetPreallocation(). Once you have looped over the nonzero 184380bf85aSDave May structure, you must call MatAssemblyBegin(), MatAssemblyEnd() on mat. 185380bf85aSDave May 186380bf85aSDave May After you have assembled the preallocator matrix (mat), call MatPreallocatorPreallocate() 187380bf85aSDave May to define the preallocation information on the matrix (A). Setting the parameter 188380bf85aSDave May fill = PETSC_TRUE will insert zeros into the matrix A. Internally MatPreallocatorPreallocate() 189380bf85aSDave May will call MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE); 190c094ef40SMatthew G. Knepley 191c094ef40SMatthew G. Knepley Level: advanced 192c094ef40SMatthew G. Knepley 193c094ef40SMatthew G. Knepley .seealso: MATPREALLOCATOR 194c094ef40SMatthew G. Knepley @*/ 195c094ef40SMatthew G. Knepley PetscErrorCode MatPreallocatorPreallocate(Mat mat, PetscBool fill, Mat A) 196c094ef40SMatthew G. Knepley { 197c094ef40SMatthew G. Knepley PetscErrorCode ierr; 198c094ef40SMatthew G. Knepley 199c094ef40SMatthew G. Knepley PetscFunctionBegin; 200c094ef40SMatthew G. Knepley PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 201c094ef40SMatthew G. Knepley PetscValidHeaderSpecific(A, MAT_CLASSID, 3); 202c094ef40SMatthew G. Knepley ierr = PetscUseMethod(mat, "MatPreallocatorPreallocate_C", (Mat,PetscBool,Mat),(mat,fill,A));CHKERRQ(ierr); 203c094ef40SMatthew G. Knepley PetscFunctionReturn(0); 204c094ef40SMatthew G. Knepley } 205c094ef40SMatthew G. Knepley 206c094ef40SMatthew G. Knepley /*MC 207c094ef40SMatthew G. Knepley MATPREALLOCATOR - MATPREALLOCATOR = "preallocator" - A matrix type to be used for computing a matrix preallocation. 208c094ef40SMatthew G. Knepley 209c094ef40SMatthew G. Knepley Operations Provided: 210c094ef40SMatthew G. Knepley . MatSetValues() 211c094ef40SMatthew G. Knepley 212c094ef40SMatthew G. Knepley Options Database Keys: 213c094ef40SMatthew G. Knepley . -mat_type preallocator - sets the matrix type to "preallocator" during a call to MatSetFromOptions() 214c094ef40SMatthew G. Knepley 215c094ef40SMatthew G. Knepley Level: advanced 216c094ef40SMatthew G. Knepley 217c094ef40SMatthew G. Knepley .seealso: Mat 218c094ef40SMatthew G. Knepley 219c094ef40SMatthew G. Knepley M*/ 220c094ef40SMatthew G. Knepley 221c094ef40SMatthew G. Knepley PETSC_EXTERN PetscErrorCode MatCreate_Preallocator(Mat A) 222c094ef40SMatthew G. Knepley { 223c094ef40SMatthew G. Knepley Mat_Preallocator *p; 224c094ef40SMatthew G. Knepley PetscErrorCode ierr; 225c094ef40SMatthew G. Knepley 226c094ef40SMatthew G. Knepley PetscFunctionBegin; 227c094ef40SMatthew G. Knepley ierr = PetscNewLog(A, &p);CHKERRQ(ierr); 228c094ef40SMatthew G. Knepley A->data = (void *) p; 229c094ef40SMatthew G. Knepley 230c094ef40SMatthew G. Knepley p->ht = NULL; 231c094ef40SMatthew G. Knepley p->dnz = NULL; 232c094ef40SMatthew G. Knepley p->onz = NULL; 233c09129f1SStefano Zampini p->dnzu = NULL; 234c09129f1SStefano Zampini p->onzu = NULL; 235c094ef40SMatthew G. Knepley 236c094ef40SMatthew G. Knepley /* matrix ops */ 237c094ef40SMatthew G. Knepley ierr = PetscMemzero(A->ops, sizeof(struct _MatOps));CHKERRQ(ierr); 238c09129f1SStefano Zampini 239c094ef40SMatthew G. Knepley A->ops->destroy = MatDestroy_Preallocator; 240c094ef40SMatthew G. Knepley A->ops->setup = MatSetUp_Preallocator; 241c094ef40SMatthew G. Knepley A->ops->setvalues = MatSetValues_Preallocator; 242c094ef40SMatthew G. Knepley A->ops->assemblybegin = MatAssemblyBegin_Preallocator; 243c094ef40SMatthew G. Knepley A->ops->assemblyend = MatAssemblyEnd_Preallocator; 244c094ef40SMatthew G. Knepley A->ops->view = MatView_Preallocator; 245c094ef40SMatthew G. Knepley A->ops->setoption = MatSetOption_Preallocator; 2465dca1104SStefano Zampini A->ops->setblocksizes = MatSetBlockSizes_Default; /* once set, user is not allowed to change the block sizes */ 247c094ef40SMatthew G. Knepley 248c094ef40SMatthew G. Knepley /* special MATPREALLOCATOR functions */ 249c094ef40SMatthew G. Knepley ierr = PetscObjectComposeFunction((PetscObject) A, "MatPreallocatorPreallocate_C", MatPreallocatorPreallocate_Preallocator);CHKERRQ(ierr); 250c094ef40SMatthew G. Knepley ierr = PetscObjectChangeTypeName((PetscObject) A, MATPREALLOCATOR);CHKERRQ(ierr); 251c094ef40SMatthew G. Knepley PetscFunctionReturn(0); 252c094ef40SMatthew G. Knepley } 253