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); 378011973bSJunchao Zhang /* Do not bother bstash since MatPreallocator does not implement MatSetValuesBlocked */ 388011973bSJunchao 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); 146*050c3c49SStefano Zampini ierr = MatSetUp(A);CHKERRQ(ierr); 147c094ef40SMatthew G. Knepley ierr = MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE);CHKERRQ(ierr); 148380bf85aSDave May if (fill) { 149380bf85aSDave May PetscHashIter hi; 150380bf85aSDave May PetscHashIJKey key; 151380bf85aSDave May PetscScalar *zeros; 152380bf85aSDave May 153380bf85aSDave May ierr = PetscCalloc1(bs*bs,&zeros);CHKERRQ(ierr); 154380bf85aSDave May 155380bf85aSDave May PetscHashIterBegin(p->ht,hi); 156380bf85aSDave May while (!PetscHashIterAtEnd(p->ht,hi)) { 157380bf85aSDave May PetscHashIterGetKey(p->ht,hi,key); 158380bf85aSDave May PetscHashIterNext(p->ht,hi); 159380bf85aSDave May ierr = MatSetValuesBlocked(A,1,&key.i,1,&key.j,zeros,INSERT_VALUES);CHKERRQ(ierr); 160380bf85aSDave May } 161380bf85aSDave May ierr = PetscFree(zeros);CHKERRQ(ierr); 162380bf85aSDave May 163380bf85aSDave May ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 164380bf85aSDave May ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 165380bf85aSDave May } 166c094ef40SMatthew G. Knepley PetscFunctionReturn(0); 167c094ef40SMatthew G. Knepley } 168c094ef40SMatthew G. Knepley 169c094ef40SMatthew G. Knepley /*@ 170380bf85aSDave May MatPreallocatorPreallocate - Preallocates the A matrix, using information from mat, optionally filling A with zeros 171c094ef40SMatthew G. Knepley 172c094ef40SMatthew G. Knepley Input Parameter: 173c094ef40SMatthew G. Knepley + mat - the preallocator 174380bf85aSDave May . fill - fill the matrix with zeros 175380bf85aSDave May - A - the matrix to be preallocated 176c094ef40SMatthew G. Knepley 177380bf85aSDave May Notes: 178380bf85aSDave May This Mat implementation provides a helper utility to define the correct 179380bf85aSDave May preallocation data for a given nonzero structure. Use this object like a 180380bf85aSDave May regular matrix, e.g. loop over the nonzero structure of the matrix and 181380bf85aSDave May call MatSetValues() or MatSetValuesBlocked() to indicate the nonzero locations. 182380bf85aSDave May The matrix entires provided to MatSetValues() will be ignored, it only uses 183380bf85aSDave May the row / col indices provided to determine the information required to be 184380bf85aSDave May passed to MatXAIJSetPreallocation(). Once you have looped over the nonzero 185380bf85aSDave May structure, you must call MatAssemblyBegin(), MatAssemblyEnd() on mat. 186380bf85aSDave May 187380bf85aSDave May After you have assembled the preallocator matrix (mat), call MatPreallocatorPreallocate() 188380bf85aSDave May to define the preallocation information on the matrix (A). Setting the parameter 189380bf85aSDave May fill = PETSC_TRUE will insert zeros into the matrix A. Internally MatPreallocatorPreallocate() 190380bf85aSDave May will call MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE); 191c094ef40SMatthew G. Knepley 192c094ef40SMatthew G. Knepley Level: advanced 193c094ef40SMatthew G. Knepley 194c094ef40SMatthew G. Knepley .seealso: MATPREALLOCATOR 195c094ef40SMatthew G. Knepley @*/ 196c094ef40SMatthew G. Knepley PetscErrorCode MatPreallocatorPreallocate(Mat mat, PetscBool fill, Mat A) 197c094ef40SMatthew G. Knepley { 198c094ef40SMatthew G. Knepley PetscErrorCode ierr; 199c094ef40SMatthew G. Knepley 200c094ef40SMatthew G. Knepley PetscFunctionBegin; 201c094ef40SMatthew G. Knepley PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 202c094ef40SMatthew G. Knepley PetscValidHeaderSpecific(A, MAT_CLASSID, 3); 203c094ef40SMatthew G. Knepley ierr = PetscUseMethod(mat, "MatPreallocatorPreallocate_C", (Mat,PetscBool,Mat),(mat,fill,A));CHKERRQ(ierr); 204c094ef40SMatthew G. Knepley PetscFunctionReturn(0); 205c094ef40SMatthew G. Knepley } 206c094ef40SMatthew G. Knepley 207c094ef40SMatthew G. Knepley /*MC 208c094ef40SMatthew G. Knepley MATPREALLOCATOR - MATPREALLOCATOR = "preallocator" - A matrix type to be used for computing a matrix preallocation. 209c094ef40SMatthew G. Knepley 210c094ef40SMatthew G. Knepley Operations Provided: 211c094ef40SMatthew G. Knepley . MatSetValues() 212c094ef40SMatthew G. Knepley 213c094ef40SMatthew G. Knepley Options Database Keys: 214c094ef40SMatthew G. Knepley . -mat_type preallocator - sets the matrix type to "preallocator" during a call to MatSetFromOptions() 215c094ef40SMatthew G. Knepley 216c094ef40SMatthew G. Knepley Level: advanced 217c094ef40SMatthew G. Knepley 218c094ef40SMatthew G. Knepley .seealso: Mat 219c094ef40SMatthew G. Knepley 220c094ef40SMatthew G. Knepley M*/ 221c094ef40SMatthew G. Knepley 222c094ef40SMatthew G. Knepley PETSC_EXTERN PetscErrorCode MatCreate_Preallocator(Mat A) 223c094ef40SMatthew G. Knepley { 224c094ef40SMatthew G. Knepley Mat_Preallocator *p; 225c094ef40SMatthew G. Knepley PetscErrorCode ierr; 226c094ef40SMatthew G. Knepley 227c094ef40SMatthew G. Knepley PetscFunctionBegin; 228c094ef40SMatthew G. Knepley ierr = PetscNewLog(A, &p);CHKERRQ(ierr); 229c094ef40SMatthew G. Knepley A->data = (void *) p; 230c094ef40SMatthew G. Knepley 231c094ef40SMatthew G. Knepley p->ht = NULL; 232c094ef40SMatthew G. Knepley p->dnz = NULL; 233c094ef40SMatthew G. Knepley p->onz = NULL; 234c09129f1SStefano Zampini p->dnzu = NULL; 235c09129f1SStefano Zampini p->onzu = NULL; 236c094ef40SMatthew G. Knepley 237c094ef40SMatthew G. Knepley /* matrix ops */ 238c094ef40SMatthew G. Knepley ierr = PetscMemzero(A->ops, sizeof(struct _MatOps));CHKERRQ(ierr); 239c09129f1SStefano Zampini 240c094ef40SMatthew G. Knepley A->ops->destroy = MatDestroy_Preallocator; 241c094ef40SMatthew G. Knepley A->ops->setup = MatSetUp_Preallocator; 242c094ef40SMatthew G. Knepley A->ops->setvalues = MatSetValues_Preallocator; 243c094ef40SMatthew G. Knepley A->ops->assemblybegin = MatAssemblyBegin_Preallocator; 244c094ef40SMatthew G. Knepley A->ops->assemblyend = MatAssemblyEnd_Preallocator; 245c094ef40SMatthew G. Knepley A->ops->view = MatView_Preallocator; 246c094ef40SMatthew G. Knepley A->ops->setoption = MatSetOption_Preallocator; 2475dca1104SStefano Zampini A->ops->setblocksizes = MatSetBlockSizes_Default; /* once set, user is not allowed to change the block sizes */ 248c094ef40SMatthew G. Knepley 249c094ef40SMatthew G. Knepley /* special MATPREALLOCATOR functions */ 250c094ef40SMatthew G. Knepley ierr = PetscObjectComposeFunction((PetscObject) A, "MatPreallocatorPreallocate_C", MatPreallocatorPreallocate_Preallocator);CHKERRQ(ierr); 251c094ef40SMatthew G. Knepley ierr = PetscObjectChangeTypeName((PetscObject) A, MATPREALLOCATOR);CHKERRQ(ierr); 252c094ef40SMatthew G. Knepley PetscFunctionReturn(0); 253c094ef40SMatthew G. Knepley } 254