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