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