xref: /petsc/src/mat/impls/preallocator/matpreallocator.c (revision fcc385fa3aba2f3ddcbd911b4593c6f42459fd18)
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;
8f8f6e9aeSStefano Zampini   PetscBool   nooffproc;
9*fcc385faSPatrick Sanan   PetscBool   used;
10c094ef40SMatthew G. Knepley } Mat_Preallocator;
11c094ef40SMatthew G. Knepley 
12c094ef40SMatthew G. Knepley PetscErrorCode MatDestroy_Preallocator(Mat A)
13c094ef40SMatthew G. Knepley {
14c094ef40SMatthew G. Knepley   Mat_Preallocator *p = (Mat_Preallocator *) A->data;
15c094ef40SMatthew G. Knepley   PetscErrorCode    ierr;
16c094ef40SMatthew G. Knepley 
17c094ef40SMatthew G. Knepley   PetscFunctionBegin;
18c094ef40SMatthew G. Knepley   ierr = MatStashDestroy_Private(&A->stash);CHKERRQ(ierr);
19e8f14785SLisandro Dalcin   ierr = PetscHSetIJDestroy(&p->ht);CHKERRQ(ierr);
20c09129f1SStefano Zampini   ierr = PetscFree4(p->dnz, p->onz, p->dnzu, p->onzu);CHKERRQ(ierr);
21c094ef40SMatthew G. Knepley   ierr = PetscFree(A->data);CHKERRQ(ierr);
22f4259b30SLisandro Dalcin   ierr = PetscObjectChangeTypeName((PetscObject) A, NULL);CHKERRQ(ierr);
23c094ef40SMatthew G. Knepley   ierr = PetscObjectComposeFunction((PetscObject) A, "MatPreallocatorPreallocate_C", NULL);CHKERRQ(ierr);
24c094ef40SMatthew G. Knepley   PetscFunctionReturn(0);
25c094ef40SMatthew G. Knepley }
26c094ef40SMatthew G. Knepley 
27c094ef40SMatthew G. Knepley PetscErrorCode MatSetUp_Preallocator(Mat A)
28c094ef40SMatthew G. Knepley {
29c094ef40SMatthew G. Knepley   Mat_Preallocator *p = (Mat_Preallocator *) A->data;
305dca1104SStefano Zampini   PetscInt          m, bs, mbs;
31c094ef40SMatthew G. Knepley   PetscErrorCode    ierr;
32c094ef40SMatthew G. Knepley 
33c094ef40SMatthew G. Knepley   PetscFunctionBegin;
34c094ef40SMatthew G. Knepley   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
35c094ef40SMatthew G. Knepley   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
36c094ef40SMatthew G. Knepley   ierr = MatGetLocalSize(A, &m, NULL);CHKERRQ(ierr);
37e8f14785SLisandro Dalcin   ierr = PetscHSetIJCreate(&p->ht);CHKERRQ(ierr);
38c094ef40SMatthew G. Knepley   ierr = MatGetBlockSize(A, &bs);CHKERRQ(ierr);
398011973bSJunchao Zhang   /* Do not bother bstash since MatPreallocator does not implement MatSetValuesBlocked */
408011973bSJunchao Zhang   ierr = MatStashCreate_Private(PetscObjectComm((PetscObject) A), 1, &A->stash);CHKERRQ(ierr);
415dca1104SStefano Zampini   /* arrays are for blocked rows/cols */
425dca1104SStefano Zampini   mbs  = m/bs;
435dca1104SStefano Zampini   ierr = PetscCalloc4(mbs, &p->dnz, mbs, &p->onz, mbs, &p->dnzu, mbs, &p->onzu);CHKERRQ(ierr);
44c094ef40SMatthew G. Knepley   PetscFunctionReturn(0);
45c094ef40SMatthew G. Knepley }
46c094ef40SMatthew G. Knepley 
47c094ef40SMatthew G. Knepley PetscErrorCode MatSetValues_Preallocator(Mat A, PetscInt m, const PetscInt *rows, PetscInt n, const PetscInt *cols, const PetscScalar *values, InsertMode addv)
48c094ef40SMatthew G. Knepley {
49c094ef40SMatthew G. Knepley   Mat_Preallocator *p = (Mat_Preallocator *) A->data;
505dca1104SStefano Zampini   PetscInt          rStart, rEnd, r, cStart, cEnd, c, bs;
51c094ef40SMatthew G. Knepley   PetscErrorCode    ierr;
52c094ef40SMatthew G. Knepley 
53c094ef40SMatthew G. Knepley   PetscFunctionBegin;
545dca1104SStefano Zampini   ierr = MatGetBlockSize(A, &bs);CHKERRQ(ierr);
55c094ef40SMatthew G. Knepley   ierr = MatGetOwnershipRange(A, &rStart, &rEnd);CHKERRQ(ierr);
56c094ef40SMatthew G. Knepley   ierr = MatGetOwnershipRangeColumn(A, &cStart, &cEnd);CHKERRQ(ierr);
57c094ef40SMatthew G. Knepley   for (r = 0; r < m; ++r) {
58e8f14785SLisandro Dalcin     PetscHashIJKey key;
59e8f14785SLisandro Dalcin     PetscBool      missing;
60c094ef40SMatthew G. Knepley 
61e8f14785SLisandro Dalcin     key.i = rows[r];
62e8f14785SLisandro Dalcin     if (key.i < 0) continue;
63e8f14785SLisandro Dalcin     if ((key.i < rStart) || (key.i >= rEnd)) {
64e8f14785SLisandro Dalcin       ierr = MatStashValuesRow_Private(&A->stash, key.i, n, cols, values, PETSC_FALSE);CHKERRQ(ierr);
655dca1104SStefano Zampini     } else { /* Hash table is for blocked rows/cols */
665dca1104SStefano Zampini       key.i = rows[r]/bs;
67c094ef40SMatthew G. Knepley       for (c = 0; c < n; ++c) {
685dca1104SStefano Zampini         key.j = cols[c]/bs;
69e8f14785SLisandro Dalcin         if (key.j < 0) continue;
70e8f14785SLisandro Dalcin         ierr = PetscHSetIJQueryAdd(p->ht, key, &missing);CHKERRQ(ierr);
71c094ef40SMatthew G. Knepley         if (missing) {
725dca1104SStefano Zampini           if ((key.j >= cStart/bs) && (key.j < cEnd/bs)) {
735dca1104SStefano Zampini             ++p->dnz[key.i-rStart/bs];
745dca1104SStefano Zampini             if (key.j >= key.i) ++p->dnzu[key.i-rStart/bs];
75c09129f1SStefano Zampini           } else {
765dca1104SStefano Zampini             ++p->onz[key.i-rStart/bs];
775dca1104SStefano Zampini             if (key.j >= key.i) ++p->onzu[key.i-rStart/bs];
78c09129f1SStefano Zampini           }
79c094ef40SMatthew G. Knepley         }
80c094ef40SMatthew G. Knepley       }
81c094ef40SMatthew G. Knepley     }
82c094ef40SMatthew G. Knepley   }
83c094ef40SMatthew G. Knepley   PetscFunctionReturn(0);
84c094ef40SMatthew G. Knepley }
85c094ef40SMatthew G. Knepley 
86c094ef40SMatthew G. Knepley PetscErrorCode MatAssemblyBegin_Preallocator(Mat A, MatAssemblyType type)
87c094ef40SMatthew G. Knepley {
88c094ef40SMatthew G. Knepley   PetscInt       nstash, reallocs;
89c094ef40SMatthew G. Knepley   PetscErrorCode ierr;
90c094ef40SMatthew G. Knepley 
91c094ef40SMatthew G. Knepley   PetscFunctionBegin;
92c094ef40SMatthew G. Knepley   ierr = MatStashScatterBegin_Private(A, &A->stash, A->rmap->range);CHKERRQ(ierr);
93c094ef40SMatthew G. Knepley   ierr = MatStashGetInfo_Private(&A->stash, &nstash, &reallocs);CHKERRQ(ierr);
94c094ef40SMatthew G. Knepley   ierr = PetscInfo2(A, "Stash has %D entries, uses %D mallocs.\n", nstash, reallocs);CHKERRQ(ierr);
95c094ef40SMatthew G. Knepley   PetscFunctionReturn(0);
96c094ef40SMatthew G. Knepley }
97c094ef40SMatthew G. Knepley 
98c094ef40SMatthew G. Knepley PetscErrorCode MatAssemblyEnd_Preallocator(Mat A, MatAssemblyType type)
99c094ef40SMatthew G. Knepley {
100c094ef40SMatthew G. Knepley   PetscScalar      *val;
101c094ef40SMatthew G. Knepley   PetscInt         *row, *col;
102c094ef40SMatthew G. Knepley   PetscInt         i, j, rstart, ncols, flg;
103c094ef40SMatthew G. Knepley   PetscMPIInt      n;
104f8f6e9aeSStefano Zampini   Mat_Preallocator *p = (Mat_Preallocator *) A->data;
105c094ef40SMatthew G. Knepley   PetscErrorCode   ierr;
106c094ef40SMatthew G. Knepley 
107c094ef40SMatthew G. Knepley   PetscFunctionBegin;
108f8f6e9aeSStefano Zampini   p->nooffproc = PETSC_TRUE;
109c094ef40SMatthew G. Knepley   while (1) {
110c094ef40SMatthew G. Knepley     ierr = MatStashScatterGetMesg_Private(&A->stash, &n, &row, &col, &val, &flg);CHKERRQ(ierr);
111f8f6e9aeSStefano Zampini     if (flg) p->nooffproc = PETSC_FALSE;
112c094ef40SMatthew G. Knepley     if (!flg) break;
113c094ef40SMatthew G. Knepley 
114c094ef40SMatthew G. Knepley     for (i = 0; i < n;) {
115c094ef40SMatthew G. Knepley       /* Now identify the consecutive vals belonging to the same row */
116c094ef40SMatthew G. Knepley       for (j = i, rstart = row[j]; j < n; j++) {
117c094ef40SMatthew G. Knepley         if (row[j] != rstart) break;
118c094ef40SMatthew G. Knepley       }
119c094ef40SMatthew G. Knepley       if (j < n) ncols = j-i;
120c094ef40SMatthew G. Knepley       else       ncols = n-i;
121c094ef40SMatthew G. Knepley       /* Now assemble all these values with a single function call */
122c094ef40SMatthew G. Knepley       ierr = MatSetValues_Preallocator(A, 1, row+i, ncols, col+i, val+i, INSERT_VALUES);CHKERRQ(ierr);
123c094ef40SMatthew G. Knepley       i = j;
124c094ef40SMatthew G. Knepley     }
125c094ef40SMatthew G. Knepley   }
126c094ef40SMatthew G. Knepley   ierr = MatStashScatterEnd_Private(&A->stash);CHKERRQ(ierr);
127820f2d46SBarry Smith   ierr = MPIU_Allreduce(MPI_IN_PLACE,&p->nooffproc,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRMPI(ierr);
128c094ef40SMatthew G. Knepley   PetscFunctionReturn(0);
129c094ef40SMatthew G. Knepley }
130c094ef40SMatthew G. Knepley 
131c094ef40SMatthew G. Knepley PetscErrorCode MatView_Preallocator(Mat A, PetscViewer viewer)
132c094ef40SMatthew G. Knepley {
133c094ef40SMatthew G. Knepley   PetscFunctionBegin;
134c094ef40SMatthew G. Knepley   PetscFunctionReturn(0);
135c094ef40SMatthew G. Knepley }
136c094ef40SMatthew G. Knepley 
137c094ef40SMatthew G. Knepley PetscErrorCode MatSetOption_Preallocator(Mat A, MatOption op, PetscBool flg)
138c094ef40SMatthew G. Knepley {
139c094ef40SMatthew G. Knepley   PetscFunctionBegin;
140c094ef40SMatthew G. Knepley   PetscFunctionReturn(0);
141c094ef40SMatthew G. Knepley }
142c094ef40SMatthew G. Knepley 
143c094ef40SMatthew G. Knepley PetscErrorCode MatPreallocatorPreallocate_Preallocator(Mat mat, PetscBool fill, Mat A)
144c094ef40SMatthew G. Knepley {
145c094ef40SMatthew G. Knepley   Mat_Preallocator *p = (Mat_Preallocator *) mat->data;
146c094ef40SMatthew G. Knepley   PetscInt          bs;
147c094ef40SMatthew G. Knepley   PetscErrorCode    ierr;
148c094ef40SMatthew G. Knepley 
149c094ef40SMatthew G. Knepley   PetscFunctionBegin;
150*fcc385faSPatrick Sanan   if (p->used) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"MatPreallocatorPreallocate() can only be used once for a give MatPreallocator object. Consider using MatDuplicate() after preallocation.");
151*fcc385faSPatrick Sanan   p->used = PETSC_TRUE;
152880e7892SJed Brown   if (!fill) {ierr = PetscHSetIJDestroy(&p->ht);CHKERRQ(ierr);}
153c094ef40SMatthew G. Knepley   ierr = MatGetBlockSize(mat, &bs);CHKERRQ(ierr);
154c09129f1SStefano Zampini   ierr = MatXAIJSetPreallocation(A, bs, p->dnz, p->onz, p->dnzu, p->onzu);CHKERRQ(ierr);
155050c3c49SStefano Zampini   ierr = MatSetUp(A);CHKERRQ(ierr);
156c094ef40SMatthew G. Knepley   ierr = MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE);CHKERRQ(ierr);
157f8f6e9aeSStefano Zampini   ierr = MatSetOption(A, MAT_NO_OFF_PROC_ENTRIES, p->nooffproc);CHKERRQ(ierr);
158380bf85aSDave May   if (fill) {
159380bf85aSDave May     PetscHashIter  hi;
160380bf85aSDave May     PetscHashIJKey key;
161380bf85aSDave May     PetscScalar    *zeros;
162880e7892SJed Brown     PetscInt       n,maxrow=1,*cols,rStart,rEnd,*rowstarts;
163380bf85aSDave May 
164880e7892SJed Brown     ierr = MatGetOwnershipRange(A, &rStart, &rEnd);CHKERRQ(ierr);
165880e7892SJed Brown     // Ownership range is in terms of scalar entries, but we deal with blocks
166880e7892SJed Brown     rStart /= bs;
167880e7892SJed Brown     rEnd /= bs;
168146543f8SJed Brown     ierr = PetscHSetIJGetSize(p->ht,&n);CHKERRQ(ierr);
169880e7892SJed Brown     ierr = PetscMalloc2(n,&cols,rEnd-rStart+1,&rowstarts);CHKERRQ(ierr);
170880e7892SJed Brown     rowstarts[0] = 0;
171880e7892SJed Brown     for (PetscInt i=0; i<rEnd-rStart; i++) {
172880e7892SJed Brown       rowstarts[i+1] = rowstarts[i] + p->dnz[i] + p->onz[i];
173880e7892SJed Brown       maxrow = PetscMax(maxrow, p->dnz[i] + p->onz[i]);
174880e7892SJed Brown     }
175880e7892SJed Brown     if (rowstarts[rEnd-rStart] != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Hash claims %D entries, but dnz+onz counts %D",n,rowstarts[rEnd-rStart]);
176880e7892SJed Brown 
177380bf85aSDave May     PetscHashIterBegin(p->ht,hi);
178146543f8SJed Brown     for (PetscInt i=0; !PetscHashIterAtEnd(p->ht,hi); i++) {
179380bf85aSDave May       PetscHashIterGetKey(p->ht,hi,key);
180880e7892SJed Brown       PetscInt lrow = key.i - rStart;
181880e7892SJed Brown       cols[rowstarts[lrow]] = key.j;
182880e7892SJed Brown       rowstarts[lrow]++;
183380bf85aSDave May       PetscHashIterNext(p->ht,hi);
184146543f8SJed Brown     }
185146543f8SJed Brown     ierr = PetscHSetIJDestroy(&p->ht);CHKERRQ(ierr);
186146543f8SJed Brown 
187146543f8SJed Brown     ierr = PetscCalloc1(maxrow*bs*bs,&zeros);CHKERRQ(ierr);
188880e7892SJed Brown     for (PetscInt i=0; i<rEnd-rStart; i++) {
189880e7892SJed Brown       PetscInt grow = rStart + i;
190880e7892SJed Brown       PetscInt end = rowstarts[i], start = end - p->dnz[i] - p->onz[i];
191146543f8SJed Brown       ierr = PetscSortInt(end-start,&cols[start]);CHKERRQ(ierr);
192880e7892SJed Brown       ierr = MatSetValuesBlocked(A, 1, &grow, end-start, &cols[start], zeros, INSERT_VALUES);CHKERRQ(ierr);
193380bf85aSDave May     }
194380bf85aSDave May     ierr = PetscFree(zeros);CHKERRQ(ierr);
195880e7892SJed Brown     ierr = PetscFree2(cols,rowstarts);CHKERRQ(ierr);
196380bf85aSDave May 
197380bf85aSDave May     ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
198380bf85aSDave May     ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
199380bf85aSDave May   }
200c094ef40SMatthew G. Knepley   PetscFunctionReturn(0);
201c094ef40SMatthew G. Knepley }
202c094ef40SMatthew G. Knepley 
203c094ef40SMatthew G. Knepley /*@
204380bf85aSDave May   MatPreallocatorPreallocate - Preallocates the A matrix, using information from mat, optionally filling A with zeros
205c094ef40SMatthew G. Knepley 
206d8d19677SJose E. Roman   Input Parameters:
207c094ef40SMatthew G. Knepley + mat  - the preallocator
208380bf85aSDave May . fill - fill the matrix with zeros
209380bf85aSDave May - A    - the matrix to be preallocated
210c094ef40SMatthew G. Knepley 
211380bf85aSDave May   Notes:
212380bf85aSDave May   This Mat implementation provides a helper utility to define the correct
213380bf85aSDave May   preallocation data for a given nonzero structure. Use this object like a
214380bf85aSDave May   regular matrix, e.g. loop over the nonzero structure of the matrix and
215380bf85aSDave May   call MatSetValues() or MatSetValuesBlocked() to indicate the nonzero locations.
216a5b23f4aSJose E. Roman   The matrix entries provided to MatSetValues() will be ignored, it only uses
217380bf85aSDave May   the row / col indices provided to determine the information required to be
218380bf85aSDave May   passed to MatXAIJSetPreallocation(). Once you have looped over the nonzero
219380bf85aSDave May   structure, you must call MatAssemblyBegin(), MatAssemblyEnd() on mat.
220380bf85aSDave May 
221380bf85aSDave May   After you have assembled the preallocator matrix (mat), call MatPreallocatorPreallocate()
222380bf85aSDave May   to define the preallocation information on the matrix (A). Setting the parameter
223380bf85aSDave May   fill = PETSC_TRUE will insert zeros into the matrix A. Internally MatPreallocatorPreallocate()
224380bf85aSDave May   will call MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE);
225c094ef40SMatthew G. Knepley 
226*fcc385faSPatrick Sanan   This function may only be called once for a given MatPreallocator object. If
227*fcc385faSPatrick Sanan   multiple Mats need to be preallocated, consider using MatDuplicate() after
228*fcc385faSPatrick Sanan   this function.
229*fcc385faSPatrick Sanan 
230c094ef40SMatthew G. Knepley   Level: advanced
231c094ef40SMatthew G. Knepley 
232c094ef40SMatthew G. Knepley .seealso: MATPREALLOCATOR
233c094ef40SMatthew G. Knepley @*/
234c094ef40SMatthew G. Knepley PetscErrorCode MatPreallocatorPreallocate(Mat mat, PetscBool fill, Mat A)
235c094ef40SMatthew G. Knepley {
236c094ef40SMatthew G. Knepley   PetscErrorCode ierr;
237c094ef40SMatthew G. Knepley 
238c094ef40SMatthew G. Knepley   PetscFunctionBegin;
239c094ef40SMatthew G. Knepley   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
240c094ef40SMatthew G. Knepley   PetscValidHeaderSpecific(A,   MAT_CLASSID, 3);
241c094ef40SMatthew G. Knepley   ierr = PetscUseMethod(mat, "MatPreallocatorPreallocate_C", (Mat,PetscBool,Mat),(mat,fill,A));CHKERRQ(ierr);
242c094ef40SMatthew G. Knepley   PetscFunctionReturn(0);
243c094ef40SMatthew G. Knepley }
244c094ef40SMatthew G. Knepley 
245c094ef40SMatthew G. Knepley /*MC
246c094ef40SMatthew G. Knepley    MATPREALLOCATOR - MATPREALLOCATOR = "preallocator" - A matrix type to be used for computing a matrix preallocation.
247c094ef40SMatthew G. Knepley 
248c094ef40SMatthew G. Knepley    Operations Provided:
249c094ef40SMatthew G. Knepley .  MatSetValues()
250c094ef40SMatthew G. Knepley 
251c094ef40SMatthew G. Knepley    Options Database Keys:
252c094ef40SMatthew G. Knepley . -mat_type preallocator - sets the matrix type to "preallocator" during a call to MatSetFromOptions()
253c094ef40SMatthew G. Knepley 
254c094ef40SMatthew G. Knepley   Level: advanced
255c094ef40SMatthew G. Knepley 
256c74f52fcSPatrick Sanan .seealso: Mat, MatPreallocatorPreallocate()
257c094ef40SMatthew G. Knepley 
258c094ef40SMatthew G. Knepley M*/
259c094ef40SMatthew G. Knepley 
260c094ef40SMatthew G. Knepley PETSC_EXTERN PetscErrorCode MatCreate_Preallocator(Mat A)
261c094ef40SMatthew G. Knepley {
262c094ef40SMatthew G. Knepley   Mat_Preallocator *p;
263c094ef40SMatthew G. Knepley   PetscErrorCode    ierr;
264c094ef40SMatthew G. Knepley 
265c094ef40SMatthew G. Knepley   PetscFunctionBegin;
266c094ef40SMatthew G. Knepley   ierr = PetscNewLog(A, &p);CHKERRQ(ierr);
267c094ef40SMatthew G. Knepley   A->data = (void *) p;
268c094ef40SMatthew G. Knepley 
269c094ef40SMatthew G. Knepley   p->ht   = NULL;
270c094ef40SMatthew G. Knepley   p->dnz  = NULL;
271c094ef40SMatthew G. Knepley   p->onz  = NULL;
272c09129f1SStefano Zampini   p->dnzu = NULL;
273c09129f1SStefano Zampini   p->onzu = NULL;
274*fcc385faSPatrick Sanan   p->used = PETSC_FALSE;
275c094ef40SMatthew G. Knepley 
276c094ef40SMatthew G. Knepley   /* matrix ops */
277c094ef40SMatthew G. Knepley   ierr = PetscMemzero(A->ops, sizeof(struct _MatOps));CHKERRQ(ierr);
278c09129f1SStefano Zampini 
279c094ef40SMatthew G. Knepley   A->ops->destroy       = MatDestroy_Preallocator;
280c094ef40SMatthew G. Knepley   A->ops->setup         = MatSetUp_Preallocator;
281c094ef40SMatthew G. Knepley   A->ops->setvalues     = MatSetValues_Preallocator;
282c094ef40SMatthew G. Knepley   A->ops->assemblybegin = MatAssemblyBegin_Preallocator;
283c094ef40SMatthew G. Knepley   A->ops->assemblyend   = MatAssemblyEnd_Preallocator;
284c094ef40SMatthew G. Knepley   A->ops->view          = MatView_Preallocator;
285c094ef40SMatthew G. Knepley   A->ops->setoption     = MatSetOption_Preallocator;
2865dca1104SStefano Zampini   A->ops->setblocksizes = MatSetBlockSizes_Default; /* once set, user is not allowed to change the block sizes */
287c094ef40SMatthew G. Knepley 
288c094ef40SMatthew G. Knepley   /* special MATPREALLOCATOR functions */
289c094ef40SMatthew G. Knepley   ierr = PetscObjectComposeFunction((PetscObject) A, "MatPreallocatorPreallocate_C", MatPreallocatorPreallocate_Preallocator);CHKERRQ(ierr);
290c094ef40SMatthew G. Knepley   ierr = PetscObjectChangeTypeName((PetscObject) A, MATPREALLOCATOR);CHKERRQ(ierr);
291c094ef40SMatthew G. Knepley   PetscFunctionReturn(0);
292c094ef40SMatthew G. Knepley }
293