xref: /petsc/src/mat/impls/preallocator/matpreallocator.c (revision 8011973b7f6c5a272326feea334a4ca7a65f1856)
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