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;
9fcc385faSPatrick Sanan PetscBool used;
10c094ef40SMatthew G. Knepley } Mat_Preallocator;
11c094ef40SMatthew G. Knepley
MatDestroy_Preallocator(Mat A)1266976f2fSJacob Faibussowitsch static PetscErrorCode MatDestroy_Preallocator(Mat A)
13d71ae5a4SJacob Faibussowitsch {
14c094ef40SMatthew G. Knepley Mat_Preallocator *p = (Mat_Preallocator *)A->data;
15c094ef40SMatthew G. Knepley
16c094ef40SMatthew G. Knepley PetscFunctionBegin;
179566063dSJacob Faibussowitsch PetscCall(MatStashDestroy_Private(&A->stash));
189566063dSJacob Faibussowitsch PetscCall(PetscHSetIJDestroy(&p->ht));
199566063dSJacob Faibussowitsch PetscCall(PetscFree4(p->dnz, p->onz, p->dnzu, p->onzu));
209566063dSJacob Faibussowitsch PetscCall(PetscFree(A->data));
219566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)A, NULL));
229566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatPreallocatorPreallocate_C", NULL));
233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
24c094ef40SMatthew G. Knepley }
25c094ef40SMatthew G. Knepley
MatSetUp_Preallocator(Mat A)2666976f2fSJacob Faibussowitsch static PetscErrorCode MatSetUp_Preallocator(Mat A)
27d71ae5a4SJacob Faibussowitsch {
28c094ef40SMatthew G. Knepley Mat_Preallocator *p = (Mat_Preallocator *)A->data;
295dca1104SStefano Zampini PetscInt m, bs, mbs;
30c094ef40SMatthew G. Knepley
31c094ef40SMatthew G. Knepley PetscFunctionBegin;
329566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->rmap));
339566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->cmap));
349566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A, &m, NULL));
359566063dSJacob Faibussowitsch PetscCall(PetscHSetIJCreate(&p->ht));
369566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(A, &bs));
378011973bSJunchao Zhang /* Do not bother bstash since MatPreallocator does not implement MatSetValuesBlocked */
389566063dSJacob Faibussowitsch PetscCall(MatStashCreate_Private(PetscObjectComm((PetscObject)A), 1, &A->stash));
395dca1104SStefano Zampini /* arrays are for blocked rows/cols */
405dca1104SStefano Zampini mbs = m / bs;
419566063dSJacob Faibussowitsch PetscCall(PetscCalloc4(mbs, &p->dnz, mbs, &p->onz, mbs, &p->dnzu, mbs, &p->onzu));
423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
43c094ef40SMatthew G. Knepley }
44c094ef40SMatthew G. Knepley
MatSetValues_Preallocator(Mat A,PetscInt m,const PetscInt * rows,PetscInt n,const PetscInt * cols,const PetscScalar * values,InsertMode addv)4566976f2fSJacob Faibussowitsch static PetscErrorCode MatSetValues_Preallocator(Mat A, PetscInt m, const PetscInt *rows, PetscInt n, const PetscInt *cols, const PetscScalar *values, InsertMode addv)
46d71ae5a4SJacob Faibussowitsch {
47c094ef40SMatthew G. Knepley Mat_Preallocator *p = (Mat_Preallocator *)A->data;
485dca1104SStefano Zampini PetscInt rStart, rEnd, r, cStart, cEnd, c, bs;
49c094ef40SMatthew G. Knepley
50c094ef40SMatthew G. Knepley PetscFunctionBegin;
519566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(A, &bs));
529566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A, &rStart, &rEnd));
539566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRangeColumn(A, &cStart, &cEnd));
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)) {
619566063dSJacob Faibussowitsch PetscCall(MatStashValuesRow_Private(&A->stash, key.i, n, cols, values, PETSC_FALSE));
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;
679566063dSJacob Faibussowitsch PetscCall(PetscHSetIJQueryAdd(p->ht, key, &missing));
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 }
803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
81c094ef40SMatthew G. Knepley }
82c094ef40SMatthew G. Knepley
MatAssemblyBegin_Preallocator(Mat A,MatAssemblyType type)8366976f2fSJacob Faibussowitsch static PetscErrorCode MatAssemblyBegin_Preallocator(Mat A, MatAssemblyType type)
84d71ae5a4SJacob Faibussowitsch {
85c094ef40SMatthew G. Knepley PetscInt nstash, reallocs;
86c094ef40SMatthew G. Knepley
87c094ef40SMatthew G. Knepley PetscFunctionBegin;
889566063dSJacob Faibussowitsch PetscCall(MatStashScatterBegin_Private(A, &A->stash, A->rmap->range));
899566063dSJacob Faibussowitsch PetscCall(MatStashGetInfo_Private(&A->stash, &nstash, &reallocs));
909566063dSJacob Faibussowitsch PetscCall(PetscInfo(A, "Stash has %" PetscInt_FMT " entries, uses %" PetscInt_FMT " mallocs.\n", nstash, reallocs));
913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
92c094ef40SMatthew G. Knepley }
93c094ef40SMatthew G. Knepley
MatAssemblyEnd_Preallocator(Mat A,MatAssemblyType type)9466976f2fSJacob Faibussowitsch static PetscErrorCode MatAssemblyEnd_Preallocator(Mat A, MatAssemblyType type)
95d71ae5a4SJacob Faibussowitsch {
96c094ef40SMatthew G. Knepley PetscScalar *val;
97c094ef40SMatthew G. Knepley PetscInt *row, *col;
98c094ef40SMatthew G. Knepley PetscInt i, j, rstart, ncols, flg;
99c094ef40SMatthew G. Knepley PetscMPIInt n;
100f8f6e9aeSStefano Zampini Mat_Preallocator *p = (Mat_Preallocator *)A->data;
101c094ef40SMatthew G. Knepley
102c094ef40SMatthew G. Knepley PetscFunctionBegin;
103f8f6e9aeSStefano Zampini p->nooffproc = PETSC_TRUE;
104c094ef40SMatthew G. Knepley while (1) {
1059566063dSJacob Faibussowitsch PetscCall(MatStashScatterGetMesg_Private(&A->stash, &n, &row, &col, &val, &flg));
106f8f6e9aeSStefano Zampini if (flg) p->nooffproc = PETSC_FALSE;
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 */
1179566063dSJacob Faibussowitsch PetscCall(MatSetValues_Preallocator(A, 1, row + i, ncols, col + i, val + i, INSERT_VALUES));
118c094ef40SMatthew G. Knepley i = j;
119c094ef40SMatthew G. Knepley }
120c094ef40SMatthew G. Knepley }
1219566063dSJacob Faibussowitsch PetscCall(MatStashScatterEnd_Private(&A->stash));
122*5440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &p->nooffproc, 1, MPI_C_BOOL, MPI_LAND, PetscObjectComm((PetscObject)A)));
1233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
124c094ef40SMatthew G. Knepley }
125c094ef40SMatthew G. Knepley
MatView_Preallocator(Mat A,PetscViewer viewer)12666976f2fSJacob Faibussowitsch static PetscErrorCode MatView_Preallocator(Mat A, PetscViewer viewer)
127d71ae5a4SJacob Faibussowitsch {
128c094ef40SMatthew G. Knepley PetscFunctionBegin;
1293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
130c094ef40SMatthew G. Knepley }
131c094ef40SMatthew G. Knepley
MatSetOption_Preallocator(Mat A,MatOption op,PetscBool flg)13266976f2fSJacob Faibussowitsch static PetscErrorCode MatSetOption_Preallocator(Mat A, MatOption op, PetscBool flg)
133d71ae5a4SJacob Faibussowitsch {
134c094ef40SMatthew G. Knepley PetscFunctionBegin;
1353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
136c094ef40SMatthew G. Knepley }
137c094ef40SMatthew G. Knepley
MatPreallocatorPreallocate_Preallocator(Mat mat,PetscBool fill,Mat A)13866976f2fSJacob Faibussowitsch static PetscErrorCode MatPreallocatorPreallocate_Preallocator(Mat mat, PetscBool fill, Mat A)
139d71ae5a4SJacob Faibussowitsch {
140c094ef40SMatthew G. Knepley Mat_Preallocator *p = (Mat_Preallocator *)mat->data;
141c094ef40SMatthew G. Knepley PetscInt bs;
142c094ef40SMatthew G. Knepley
143c094ef40SMatthew G. Knepley PetscFunctionBegin;
1442c71b3e2SJacob Faibussowitsch PetscCheck(!p->used, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MatPreallocatorPreallocate() can only be used once for a give MatPreallocator object. Consider using MatDuplicate() after preallocation.");
145fcc385faSPatrick Sanan p->used = PETSC_TRUE;
1469566063dSJacob Faibussowitsch if (!fill) PetscCall(PetscHSetIJDestroy(&p->ht));
1479566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(mat, &bs));
1489566063dSJacob Faibussowitsch PetscCall(MatXAIJSetPreallocation(A, bs, p->dnz, p->onz, p->dnzu, p->onzu));
1499566063dSJacob Faibussowitsch PetscCall(MatSetUp(A));
1509566063dSJacob Faibussowitsch PetscCall(MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE));
151380bf85aSDave May if (fill) {
152a6f8f0ebSPatrick Sanan PetscCall(MatSetOption(A, MAT_NO_OFF_PROC_ENTRIES, p->nooffproc));
153380bf85aSDave May PetscHashIter hi;
154380bf85aSDave May PetscHashIJKey key;
155380bf85aSDave May PetscScalar *zeros;
156880e7892SJed Brown PetscInt n, maxrow = 1, *cols, rStart, rEnd, *rowstarts;
157380bf85aSDave May
1589566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A, &rStart, &rEnd));
159880e7892SJed Brown // Ownership range is in terms of scalar entries, but we deal with blocks
160880e7892SJed Brown rStart /= bs;
161880e7892SJed Brown rEnd /= bs;
1629566063dSJacob Faibussowitsch PetscCall(PetscHSetIJGetSize(p->ht, &n));
1639566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(n, &cols, rEnd - rStart + 1, &rowstarts));
164880e7892SJed Brown rowstarts[0] = 0;
165880e7892SJed Brown for (PetscInt i = 0; i < rEnd - rStart; i++) {
166880e7892SJed Brown rowstarts[i + 1] = rowstarts[i] + p->dnz[i] + p->onz[i];
167880e7892SJed Brown maxrow = PetscMax(maxrow, p->dnz[i] + p->onz[i]);
168880e7892SJed Brown }
16908401ef6SPierre Jolivet PetscCheck(rowstarts[rEnd - rStart] == n, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Hash claims %" PetscInt_FMT " entries, but dnz+onz counts %" PetscInt_FMT, n, rowstarts[rEnd - rStart]);
170880e7892SJed Brown
171380bf85aSDave May PetscHashIterBegin(p->ht, hi);
172c599c493SJunchao Zhang while (!PetscHashIterAtEnd(p->ht, hi)) {
173380bf85aSDave May PetscHashIterGetKey(p->ht, hi, key);
174880e7892SJed Brown PetscInt lrow = key.i - rStart;
175880e7892SJed Brown cols[rowstarts[lrow]] = key.j;
176880e7892SJed Brown rowstarts[lrow]++;
177380bf85aSDave May PetscHashIterNext(p->ht, hi);
178146543f8SJed Brown }
1799566063dSJacob Faibussowitsch PetscCall(PetscHSetIJDestroy(&p->ht));
180146543f8SJed Brown
1819566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(maxrow * bs * bs, &zeros));
182880e7892SJed Brown for (PetscInt i = 0; i < rEnd - rStart; i++) {
183880e7892SJed Brown PetscInt grow = rStart + i;
184880e7892SJed Brown PetscInt end = rowstarts[i], start = end - p->dnz[i] - p->onz[i];
1858e3a54c0SPierre Jolivet PetscCall(PetscSortInt(end - start, PetscSafePointerPlusOffset(cols, start)));
1868e3a54c0SPierre Jolivet PetscCall(MatSetValuesBlocked(A, 1, &grow, end - start, PetscSafePointerPlusOffset(cols, start), zeros, INSERT_VALUES));
187380bf85aSDave May }
1889566063dSJacob Faibussowitsch PetscCall(PetscFree(zeros));
1899566063dSJacob Faibussowitsch PetscCall(PetscFree2(cols, rowstarts));
190380bf85aSDave May
1919566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
1929566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
193a6f8f0ebSPatrick Sanan PetscCall(MatSetOption(A, MAT_NO_OFF_PROC_ENTRIES, PETSC_FALSE));
194380bf85aSDave May }
1953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
196c094ef40SMatthew G. Knepley }
197c094ef40SMatthew G. Knepley
198c094ef40SMatthew G. Knepley /*@
19911a5261eSBarry Smith MatPreallocatorPreallocate - Preallocates the A matrix, using information from a `MATPREALLOCATOR` mat, optionally filling A with zeros
200c094ef40SMatthew G. Knepley
201d8d19677SJose E. Roman Input Parameters:
20211a5261eSBarry Smith + mat - the `MATPREALLOCATOR` preallocator matrix
203380bf85aSDave May . fill - fill the matrix with zeros
204380bf85aSDave May - A - the matrix to be preallocated
205c094ef40SMatthew G. Knepley
206380bf85aSDave May Notes:
20711a5261eSBarry Smith This `MatType` implementation provides a helper utility to define the correct
208380bf85aSDave May preallocation data for a given nonzero structure. Use this object like a
209380bf85aSDave May regular matrix, e.g. loop over the nonzero structure of the matrix and
21011a5261eSBarry Smith call `MatSetValues()` or `MatSetValuesBlocked()` to indicate the nonzero locations.
21111a5261eSBarry Smith The matrix entries provided to `MatSetValues()` will be ignored, it only uses
212380bf85aSDave May the row / col indices provided to determine the information required to be
21311a5261eSBarry Smith passed to `MatXAIJSetPreallocation()`. Once you have looped over the nonzero
21411a5261eSBarry Smith structure, you must call `MatAssemblyBegin()`, `MatAssemblyEnd()` on mat.
215380bf85aSDave May
21611a5261eSBarry Smith After you have assembled the preallocator matrix (mat), call `MatPreallocatorPreallocate()`
217380bf85aSDave May to define the preallocation information on the matrix (A). Setting the parameter
21811a5261eSBarry Smith fill = PETSC_TRUE will insert zeros into the matrix A. Internally `MatPreallocatorPreallocate()`
21911a5261eSBarry Smith will call `MatSetOption`(A, `MAT_NEW_NONZERO_ALLOCATION_ERR`, `PETSC_TRUE`);
220c094ef40SMatthew G. Knepley
22111a5261eSBarry Smith This function may only be called once for a given `MATPREALLOCATOR` object. If
22211a5261eSBarry Smith multiple `Mat`s need to be preallocated, consider using `MatDuplicate()` after
223fcc385faSPatrick Sanan this function.
224fcc385faSPatrick Sanan
225c094ef40SMatthew G. Knepley Level: advanced
226c094ef40SMatthew G. Knepley
22711a5261eSBarry Smith .seealso: `MATPREALLOCATOR`, `MatXAIJSetPreallocation()`
228c094ef40SMatthew G. Knepley @*/
MatPreallocatorPreallocate(Mat mat,PetscBool fill,Mat A)229d71ae5a4SJacob Faibussowitsch PetscErrorCode MatPreallocatorPreallocate(Mat mat, PetscBool fill, Mat A)
230d71ae5a4SJacob Faibussowitsch {
231c094ef40SMatthew G. Knepley PetscFunctionBegin;
232c094ef40SMatthew G. Knepley PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
233d60670a5SStefano Zampini PetscValidLogicalCollectiveBool(mat, fill, 2);
234c094ef40SMatthew G. Knepley PetscValidHeaderSpecific(A, MAT_CLASSID, 3);
235cac4c232SBarry Smith PetscUseMethod(mat, "MatPreallocatorPreallocate_C", (Mat, PetscBool, Mat), (mat, fill, A));
2363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
237c094ef40SMatthew G. Knepley }
238c094ef40SMatthew G. Knepley
239c094ef40SMatthew G. Knepley /*MC
240c094ef40SMatthew G. Knepley MATPREALLOCATOR - MATPREALLOCATOR = "preallocator" - A matrix type to be used for computing a matrix preallocation.
241c094ef40SMatthew G. Knepley
242c094ef40SMatthew G. Knepley Operations Provided:
24367b8a455SSatish Balay .vb
24467b8a455SSatish Balay MatSetValues()
24567b8a455SSatish Balay .ve
246c094ef40SMatthew G. Knepley
247c094ef40SMatthew G. Knepley Options Database Keys:
24811a5261eSBarry Smith . -mat_type preallocator - sets the matrix type to `MATPREALLOCATOR` during a call to `MatSetFromOptions()`
249c094ef40SMatthew G. Knepley
250c094ef40SMatthew G. Knepley Level: advanced
251c094ef40SMatthew G. Knepley
25211a5261eSBarry Smith .seealso: `MATPREALLOCATOR`, `Mat`, `MatPreallocatorPreallocate()`
253c094ef40SMatthew G. Knepley M*/
254c094ef40SMatthew G. Knepley
MatCreate_Preallocator(Mat A)255d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_Preallocator(Mat A)
256d71ae5a4SJacob Faibussowitsch {
257c094ef40SMatthew G. Knepley Mat_Preallocator *p;
258c094ef40SMatthew G. Knepley
259c094ef40SMatthew G. Knepley PetscFunctionBegin;
2604dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&p));
261c094ef40SMatthew G. Knepley A->data = (void *)p;
262c094ef40SMatthew G. Knepley
263c094ef40SMatthew G. Knepley p->ht = NULL;
264c094ef40SMatthew G. Knepley p->dnz = NULL;
265c094ef40SMatthew G. Knepley p->onz = NULL;
266c09129f1SStefano Zampini p->dnzu = NULL;
267c09129f1SStefano Zampini p->onzu = NULL;
268fcc385faSPatrick Sanan p->used = PETSC_FALSE;
269c094ef40SMatthew G. Knepley
270c094ef40SMatthew G. Knepley /* matrix ops */
2719566063dSJacob Faibussowitsch PetscCall(PetscMemzero(A->ops, sizeof(struct _MatOps)));
272c09129f1SStefano Zampini
273c094ef40SMatthew G. Knepley A->ops->destroy = MatDestroy_Preallocator;
274c094ef40SMatthew G. Knepley A->ops->setup = MatSetUp_Preallocator;
275c094ef40SMatthew G. Knepley A->ops->setvalues = MatSetValues_Preallocator;
276c094ef40SMatthew G. Knepley A->ops->assemblybegin = MatAssemblyBegin_Preallocator;
277c094ef40SMatthew G. Knepley A->ops->assemblyend = MatAssemblyEnd_Preallocator;
278c094ef40SMatthew G. Knepley A->ops->view = MatView_Preallocator;
279c094ef40SMatthew G. Knepley A->ops->setoption = MatSetOption_Preallocator;
2805dca1104SStefano Zampini A->ops->setblocksizes = MatSetBlockSizes_Default; /* once set, user is not allowed to change the block sizes */
281c094ef40SMatthew G. Knepley
282c094ef40SMatthew G. Knepley /* special MATPREALLOCATOR functions */
2839566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatPreallocatorPreallocate_C", MatPreallocatorPreallocate_Preallocator));
2849566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)A, MATPREALLOCATOR));
2853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
286c094ef40SMatthew G. Knepley }
287