xref: /petsc/src/mat/impls/sell/mpi/mpisell.c (revision 4dfa11a44d5adf2389f1d3acbc8f3c1116dc6c3a)
1d4002b98SHong Zhang #include <../src/mat/impls/aij/mpi/mpiaij.h>   /*I "petscmat.h" I*/
2d4002b98SHong Zhang #include <../src/mat/impls/sell/mpi/mpisell.h> /*I "petscmat.h" I*/
3d4002b98SHong Zhang #include <petsc/private/vecimpl.h>
4d4002b98SHong Zhang #include <petsc/private/isimpl.h>
5d4002b98SHong Zhang #include <petscblaslapack.h>
6d4002b98SHong Zhang #include <petscsf.h>
7d4002b98SHong Zhang 
8d4002b98SHong Zhang /*MC
9d4002b98SHong Zhang    MATSELL - MATSELL = "sell" - A matrix type to be used for sparse matrices.
10d4002b98SHong Zhang 
1111a5261eSBarry Smith    This matrix type is identical to `MATSEQSELL` when constructed with a single process communicator,
1211a5261eSBarry Smith    and `MATMPISELL` otherwise.  As a result, for single process communicators,
1311a5261eSBarry Smith   `MatSeqSELLSetPreallocation()` is supported, and similarly `MatMPISELLSetPreallocation()` is supported
14d4002b98SHong Zhang   for communicators controlling multiple processes.  It is recommended that you call both of
15d4002b98SHong Zhang   the above preallocation routines for simplicity.
16d4002b98SHong Zhang 
17d4002b98SHong Zhang    Options Database Keys:
18d4002b98SHong Zhang . -mat_type sell - sets the matrix type to "sell" during a call to MatSetFromOptions()
19d4002b98SHong Zhang 
20d4002b98SHong Zhang   Level: beginner
21d4002b98SHong Zhang 
2211a5261eSBarry Smith .seealso: `MATAIJ`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSELL()`, `MatCreateSeqSELL()`, `MATSEQSELL`, `MATMPISELL`
23d4002b98SHong Zhang M*/
24d4002b98SHong Zhang 
259371c9d4SSatish Balay PetscErrorCode MatDiagonalSet_MPISELL(Mat Y, Vec D, InsertMode is) {
26d4002b98SHong Zhang   Mat_MPISELL *sell = (Mat_MPISELL *)Y->data;
27d4002b98SHong Zhang 
28d4002b98SHong Zhang   PetscFunctionBegin;
29d4002b98SHong Zhang   if (Y->assembled && Y->rmap->rstart == Y->cmap->rstart && Y->rmap->rend == Y->cmap->rend) {
309566063dSJacob Faibussowitsch     PetscCall(MatDiagonalSet(sell->A, D, is));
31d4002b98SHong Zhang   } else {
329566063dSJacob Faibussowitsch     PetscCall(MatDiagonalSet_Default(Y, D, is));
33d4002b98SHong Zhang   }
34d4002b98SHong Zhang   PetscFunctionReturn(0);
35d4002b98SHong Zhang }
36d4002b98SHong Zhang 
37d4002b98SHong Zhang /*
38d4002b98SHong Zhang   Local utility routine that creates a mapping from the global column
39d4002b98SHong Zhang number to the local number in the off-diagonal part of the local
40d4002b98SHong Zhang storage of the matrix.  When PETSC_USE_CTABLE is used this is scalable at
41d4002b98SHong Zhang a slightly higher hash table cost; without it it is not scalable (each processor
42d4002b98SHong Zhang has an order N integer array but is fast to acess.
43d4002b98SHong Zhang */
449371c9d4SSatish Balay PetscErrorCode MatCreateColmap_MPISELL_Private(Mat mat) {
45d4002b98SHong Zhang   Mat_MPISELL *sell = (Mat_MPISELL *)mat->data;
46d4002b98SHong Zhang   PetscInt     n    = sell->B->cmap->n, i;
47d4002b98SHong Zhang 
48d4002b98SHong Zhang   PetscFunctionBegin;
4928b400f6SJacob Faibussowitsch   PetscCheck(sell->garray, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MPISELL Matrix was assembled but is missing garray");
50d4002b98SHong Zhang #if defined(PETSC_USE_CTABLE)
519566063dSJacob Faibussowitsch   PetscCall(PetscTableCreate(n, mat->cmap->N + 1, &sell->colmap));
5248a46eb9SPierre Jolivet   for (i = 0; i < n; i++) PetscCall(PetscTableAdd(sell->colmap, sell->garray[i] + 1, i + 1, INSERT_VALUES));
53d4002b98SHong Zhang #else
549566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(mat->cmap->N + 1, &sell->colmap));
55d4002b98SHong Zhang   for (i = 0; i < n; i++) sell->colmap[sell->garray[i]] = i + 1;
56d4002b98SHong Zhang #endif
57d4002b98SHong Zhang   PetscFunctionReturn(0);
58d4002b98SHong Zhang }
59d4002b98SHong Zhang 
60d4002b98SHong Zhang #define MatSetValues_SeqSELL_A_Private(row, col, value, addv, orow, ocol) \
61d4002b98SHong Zhang   { \
62d4002b98SHong Zhang     if (col <= lastcol1) low1 = 0; \
63d4002b98SHong Zhang     else high1 = nrow1; \
64d4002b98SHong Zhang     lastcol1 = col; \
65d4002b98SHong Zhang     while (high1 - low1 > 5) { \
66d4002b98SHong Zhang       t = (low1 + high1) / 2; \
67d4002b98SHong Zhang       if (*(cp1 + 8 * t) > col) high1 = t; \
68d4002b98SHong Zhang       else low1 = t; \
69d4002b98SHong Zhang     } \
70d4002b98SHong Zhang     for (_i = low1; _i < high1; _i++) { \
71d4002b98SHong Zhang       if (*(cp1 + 8 * _i) > col) break; \
72d4002b98SHong Zhang       if (*(cp1 + 8 * _i) == col) { \
73d4002b98SHong Zhang         if (addv == ADD_VALUES) *(vp1 + 8 * _i) += value; \
74d4002b98SHong Zhang         else *(vp1 + 8 * _i) = value; \
75d4002b98SHong Zhang         goto a_noinsert; \
76d4002b98SHong Zhang       } \
77d4002b98SHong Zhang     } \
789371c9d4SSatish Balay     if (value == 0.0 && ignorezeroentries) { \
799371c9d4SSatish Balay       low1  = 0; \
809371c9d4SSatish Balay       high1 = nrow1; \
819371c9d4SSatish Balay       goto a_noinsert; \
829371c9d4SSatish Balay     } \
839371c9d4SSatish Balay     if (nonew == 1) { \
849371c9d4SSatish Balay       low1  = 0; \
859371c9d4SSatish Balay       high1 = nrow1; \
869371c9d4SSatish Balay       goto a_noinsert; \
879371c9d4SSatish Balay     } \
8808401ef6SPierre Jolivet     PetscCheck(nonew != -1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Inserting a new nonzero at global row/column (%" PetscInt_FMT ", %" PetscInt_FMT ") into matrix", orow, ocol); \
89d4002b98SHong Zhang     MatSeqXSELLReallocateSELL(A, am, 1, nrow1, a->sliidx, row / 8, row, col, a->colidx, a->val, cp1, vp1, nonew, MatScalar); \
90d4002b98SHong Zhang     /* shift up all the later entries in this row */ \
91d4002b98SHong Zhang     for (ii = nrow1 - 1; ii >= _i; ii--) { \
92d4002b98SHong Zhang       *(cp1 + 8 * (ii + 1)) = *(cp1 + 8 * ii); \
93d4002b98SHong Zhang       *(vp1 + 8 * (ii + 1)) = *(vp1 + 8 * ii); \
94d4002b98SHong Zhang     } \
95d4002b98SHong Zhang     *(cp1 + 8 * _i) = col; \
96d4002b98SHong Zhang     *(vp1 + 8 * _i) = value; \
979371c9d4SSatish Balay     a->nz++; \
989371c9d4SSatish Balay     nrow1++; \
999371c9d4SSatish Balay     A->nonzerostate++; \
100d4002b98SHong Zhang   a_noinsert:; \
101d4002b98SHong Zhang     a->rlen[row] = nrow1; \
102d4002b98SHong Zhang   }
103d4002b98SHong Zhang 
104d4002b98SHong Zhang #define MatSetValues_SeqSELL_B_Private(row, col, value, addv, orow, ocol) \
105d4002b98SHong Zhang   { \
106d4002b98SHong Zhang     if (col <= lastcol2) low2 = 0; \
107d4002b98SHong Zhang     else high2 = nrow2; \
108d4002b98SHong Zhang     lastcol2 = col; \
109d4002b98SHong Zhang     while (high2 - low2 > 5) { \
110d4002b98SHong Zhang       t = (low2 + high2) / 2; \
111d4002b98SHong Zhang       if (*(cp2 + 8 * t) > col) high2 = t; \
112d4002b98SHong Zhang       else low2 = t; \
113d4002b98SHong Zhang     } \
114d4002b98SHong Zhang     for (_i = low2; _i < high2; _i++) { \
115d4002b98SHong Zhang       if (*(cp2 + 8 * _i) > col) break; \
116d4002b98SHong Zhang       if (*(cp2 + 8 * _i) == col) { \
117d4002b98SHong Zhang         if (addv == ADD_VALUES) *(vp2 + 8 * _i) += value; \
118d4002b98SHong Zhang         else *(vp2 + 8 * _i) = value; \
119d4002b98SHong Zhang         goto b_noinsert; \
120d4002b98SHong Zhang       } \
121d4002b98SHong Zhang     } \
1229371c9d4SSatish Balay     if (value == 0.0 && ignorezeroentries) { \
1239371c9d4SSatish Balay       low2  = 0; \
1249371c9d4SSatish Balay       high2 = nrow2; \
1259371c9d4SSatish Balay       goto b_noinsert; \
1269371c9d4SSatish Balay     } \
1279371c9d4SSatish Balay     if (nonew == 1) { \
1289371c9d4SSatish Balay       low2  = 0; \
1299371c9d4SSatish Balay       high2 = nrow2; \
1309371c9d4SSatish Balay       goto b_noinsert; \
1319371c9d4SSatish Balay     } \
13208401ef6SPierre Jolivet     PetscCheck(nonew != -1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Inserting a new nonzero at global row/column (%" PetscInt_FMT ", %" PetscInt_FMT ") into matrix", orow, ocol); \
133d4002b98SHong Zhang     MatSeqXSELLReallocateSELL(B, bm, 1, nrow2, b->sliidx, row / 8, row, col, b->colidx, b->val, cp2, vp2, nonew, MatScalar); \
134d4002b98SHong Zhang     /* shift up all the later entries in this row */ \
135d4002b98SHong Zhang     for (ii = nrow2 - 1; ii >= _i; ii--) { \
136d4002b98SHong Zhang       *(cp2 + 8 * (ii + 1)) = *(cp2 + 8 * ii); \
137d4002b98SHong Zhang       *(vp2 + 8 * (ii + 1)) = *(vp2 + 8 * ii); \
138d4002b98SHong Zhang     } \
139d4002b98SHong Zhang     *(cp2 + 8 * _i) = col; \
140d4002b98SHong Zhang     *(vp2 + 8 * _i) = value; \
1419371c9d4SSatish Balay     b->nz++; \
1429371c9d4SSatish Balay     nrow2++; \
1439371c9d4SSatish Balay     B->nonzerostate++; \
144d4002b98SHong Zhang   b_noinsert:; \
145d4002b98SHong Zhang     b->rlen[row] = nrow2; \
146d4002b98SHong Zhang   }
147d4002b98SHong Zhang 
1489371c9d4SSatish Balay PetscErrorCode MatSetValues_MPISELL(Mat mat, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode addv) {
149d4002b98SHong Zhang   Mat_MPISELL *sell = (Mat_MPISELL *)mat->data;
150d4002b98SHong Zhang   PetscScalar  value;
151d4002b98SHong Zhang   PetscInt     i, j, rstart = mat->rmap->rstart, rend = mat->rmap->rend, shift1, shift2;
152d4002b98SHong Zhang   PetscInt     cstart = mat->cmap->rstart, cend = mat->cmap->rend, row, col;
153d4002b98SHong Zhang   PetscBool    roworiented = sell->roworiented;
154d4002b98SHong Zhang 
155d4002b98SHong Zhang   /* Some Variables required in the macro */
156d4002b98SHong Zhang   Mat          A                 = sell->A;
157d4002b98SHong Zhang   Mat_SeqSELL *a                 = (Mat_SeqSELL *)A->data;
158d4002b98SHong Zhang   PetscBool    ignorezeroentries = a->ignorezeroentries, found;
159d4002b98SHong Zhang   Mat          B                 = sell->B;
160d4002b98SHong Zhang   Mat_SeqSELL *b                 = (Mat_SeqSELL *)B->data;
161d4002b98SHong Zhang   PetscInt    *cp1, *cp2, ii, _i, nrow1, nrow2, low1, high1, low2, high2, t, lastcol1, lastcol2;
162d4002b98SHong Zhang   MatScalar   *vp1, *vp2;
163d4002b98SHong Zhang 
164d4002b98SHong Zhang   PetscFunctionBegin;
165d4002b98SHong Zhang   for (i = 0; i < m; i++) {
166d4002b98SHong Zhang     if (im[i] < 0) continue;
1676bdcaf15SBarry Smith     PetscCheck(im[i] < mat->rmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row too large: row %" PetscInt_FMT " max %" PetscInt_FMT, im[i], mat->rmap->N - 1);
168d4002b98SHong Zhang     if (im[i] >= rstart && im[i] < rend) {
169d4002b98SHong Zhang       row      = im[i] - rstart;
170d4002b98SHong Zhang       lastcol1 = -1;
171d4002b98SHong Zhang       shift1   = a->sliidx[row >> 3] + (row & 0x07); /* starting index of the row */
172d4002b98SHong Zhang       cp1      = a->colidx + shift1;
173d4002b98SHong Zhang       vp1      = a->val + shift1;
174d4002b98SHong Zhang       nrow1    = a->rlen[row];
175d4002b98SHong Zhang       low1     = 0;
176d4002b98SHong Zhang       high1    = nrow1;
177d4002b98SHong Zhang       lastcol2 = -1;
178d4002b98SHong Zhang       shift2   = b->sliidx[row >> 3] + (row & 0x07); /* starting index of the row */
179d4002b98SHong Zhang       cp2      = b->colidx + shift2;
180d4002b98SHong Zhang       vp2      = b->val + shift2;
181d4002b98SHong Zhang       nrow2    = b->rlen[row];
182d4002b98SHong Zhang       low2     = 0;
183d4002b98SHong Zhang       high2    = nrow2;
184d4002b98SHong Zhang 
185d4002b98SHong Zhang       for (j = 0; j < n; j++) {
186d4002b98SHong Zhang         if (roworiented) value = v[i * n + j];
187d4002b98SHong Zhang         else value = v[i + j * m];
188d4002b98SHong Zhang         if (ignorezeroentries && value == 0.0 && (addv == ADD_VALUES)) continue;
189d4002b98SHong Zhang         if (in[j] >= cstart && in[j] < cend) {
190d4002b98SHong Zhang           col = in[j] - cstart;
191d4002b98SHong Zhang           MatSetValue_SeqSELL_Private(A, row, col, value, addv, im[i], in[j], cp1, vp1, lastcol1, low1, high1); /* set one value */
192f7d195e4SLawrence Mitchell         } else if (in[j] < 0) {
193f7d195e4SLawrence Mitchell           continue;
194f7d195e4SLawrence Mitchell         } else {
195f7d195e4SLawrence Mitchell           PetscCheck(in[j] < mat->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column too large: col %" PetscInt_FMT " max %" PetscInt_FMT, in[j], mat->cmap->N - 1);
196d4002b98SHong Zhang           if (mat->was_assembled) {
19748a46eb9SPierre Jolivet             if (!sell->colmap) PetscCall(MatCreateColmap_MPISELL_Private(mat));
198d4002b98SHong Zhang #if defined(PETSC_USE_CTABLE)
1999566063dSJacob Faibussowitsch             PetscCall(PetscTableFind(sell->colmap, in[j] + 1, &col));
200d4002b98SHong Zhang             col--;
201d4002b98SHong Zhang #else
202d4002b98SHong Zhang             col = sell->colmap[in[j]] - 1;
203d4002b98SHong Zhang #endif
204d4002b98SHong Zhang             if (col < 0 && !((Mat_SeqSELL *)(sell->B->data))->nonew) {
2059566063dSJacob Faibussowitsch               PetscCall(MatDisAssemble_MPISELL(mat));
206d4002b98SHong Zhang               col    = in[j];
207d4002b98SHong Zhang               /* Reinitialize the variables required by MatSetValues_SeqSELL_B_Private() */
208d4002b98SHong Zhang               B      = sell->B;
209d4002b98SHong Zhang               b      = (Mat_SeqSELL *)B->data;
210d4002b98SHong Zhang               shift2 = b->sliidx[row >> 3] + (row & 0x07); /* starting index of the row */
211d4002b98SHong Zhang               cp2    = b->colidx + shift2;
212d4002b98SHong Zhang               vp2    = b->val + shift2;
213d4002b98SHong Zhang               nrow2  = b->rlen[row];
214d4002b98SHong Zhang               low2   = 0;
215d4002b98SHong Zhang               high2  = nrow2;
216f7d195e4SLawrence Mitchell             } else {
217f7d195e4SLawrence Mitchell               PetscCheck(col >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Inserting a new nonzero at global row/column (%" PetscInt_FMT ", %" PetscInt_FMT ") into matrix", im[i], in[j]);
218f7d195e4SLawrence Mitchell             }
219d4002b98SHong Zhang           } else col = in[j];
220d4002b98SHong Zhang           MatSetValue_SeqSELL_Private(B, row, col, value, addv, im[i], in[j], cp2, vp2, lastcol2, low2, high2); /* set one value */
221d4002b98SHong Zhang         }
222d4002b98SHong Zhang       }
223d4002b98SHong Zhang     } else {
22428b400f6SJacob Faibussowitsch       PetscCheck(!mat->nooffprocentries, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Setting off process row %" PetscInt_FMT " even though MatSetOption(,MAT_NO_OFF_PROC_ENTRIES,PETSC_TRUE) was set", im[i]);
225d4002b98SHong Zhang       if (!sell->donotstash) {
226d4002b98SHong Zhang         mat->assembled = PETSC_FALSE;
227d4002b98SHong Zhang         if (roworiented) {
2289566063dSJacob Faibussowitsch           PetscCall(MatStashValuesRow_Private(&mat->stash, im[i], n, in, v + i * n, (PetscBool)(ignorezeroentries && (addv == ADD_VALUES))));
229d4002b98SHong Zhang         } else {
2309566063dSJacob Faibussowitsch           PetscCall(MatStashValuesCol_Private(&mat->stash, im[i], n, in, v + i, m, (PetscBool)(ignorezeroentries && (addv == ADD_VALUES))));
231d4002b98SHong Zhang         }
232d4002b98SHong Zhang       }
233d4002b98SHong Zhang     }
234d4002b98SHong Zhang   }
235d4002b98SHong Zhang   PetscFunctionReturn(0);
236d4002b98SHong Zhang }
237d4002b98SHong Zhang 
2389371c9d4SSatish Balay PetscErrorCode MatGetValues_MPISELL(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) {
239d4002b98SHong Zhang   Mat_MPISELL *sell = (Mat_MPISELL *)mat->data;
240d4002b98SHong Zhang   PetscInt     i, j, rstart = mat->rmap->rstart, rend = mat->rmap->rend;
241d4002b98SHong Zhang   PetscInt     cstart = mat->cmap->rstart, cend = mat->cmap->rend, row, col;
242d4002b98SHong Zhang 
243d4002b98SHong Zhang   PetscFunctionBegin;
244d4002b98SHong Zhang   for (i = 0; i < m; i++) {
24554c59aa7SJacob Faibussowitsch     if (idxm[i] < 0) continue; /* negative row */
24654c59aa7SJacob Faibussowitsch     PetscCheck(idxm[i] < mat->rmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row too large: row %" PetscInt_FMT " max %" PetscInt_FMT, idxm[i], mat->rmap->N - 1);
247d4002b98SHong Zhang     if (idxm[i] >= rstart && idxm[i] < rend) {
248d4002b98SHong Zhang       row = idxm[i] - rstart;
249d4002b98SHong Zhang       for (j = 0; j < n; j++) {
25054c59aa7SJacob Faibussowitsch         if (idxn[j] < 0) continue; /* negative column */
25154c59aa7SJacob Faibussowitsch         PetscCheck(idxn[j] < mat->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column too large: col %" PetscInt_FMT " max %" PetscInt_FMT, idxn[j], mat->cmap->N - 1);
252d4002b98SHong Zhang         if (idxn[j] >= cstart && idxn[j] < cend) {
253d4002b98SHong Zhang           col = idxn[j] - cstart;
2549566063dSJacob Faibussowitsch           PetscCall(MatGetValues(sell->A, 1, &row, 1, &col, v + i * n + j));
255d4002b98SHong Zhang         } else {
25648a46eb9SPierre Jolivet           if (!sell->colmap) PetscCall(MatCreateColmap_MPISELL_Private(mat));
257d4002b98SHong Zhang #if defined(PETSC_USE_CTABLE)
2589566063dSJacob Faibussowitsch           PetscCall(PetscTableFind(sell->colmap, idxn[j] + 1, &col));
259d4002b98SHong Zhang           col--;
260d4002b98SHong Zhang #else
261d4002b98SHong Zhang           col = sell->colmap[idxn[j]] - 1;
262d4002b98SHong Zhang #endif
263d4002b98SHong Zhang           if ((col < 0) || (sell->garray[col] != idxn[j])) *(v + i * n + j) = 0.0;
26448a46eb9SPierre Jolivet           else PetscCall(MatGetValues(sell->B, 1, &row, 1, &col, v + i * n + j));
265d4002b98SHong Zhang         }
266d4002b98SHong Zhang       }
267d4002b98SHong Zhang     } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only local values currently supported");
268d4002b98SHong Zhang   }
269d4002b98SHong Zhang   PetscFunctionReturn(0);
270d4002b98SHong Zhang }
271d4002b98SHong Zhang 
272d4002b98SHong Zhang extern PetscErrorCode MatMultDiagonalBlock_MPISELL(Mat, Vec, Vec);
273d4002b98SHong Zhang 
2749371c9d4SSatish Balay PetscErrorCode MatAssemblyBegin_MPISELL(Mat mat, MatAssemblyType mode) {
275d4002b98SHong Zhang   Mat_MPISELL *sell = (Mat_MPISELL *)mat->data;
276d4002b98SHong Zhang   PetscInt     nstash, reallocs;
277d4002b98SHong Zhang 
278d4002b98SHong Zhang   PetscFunctionBegin;
279d4002b98SHong Zhang   if (sell->donotstash || mat->nooffprocentries) PetscFunctionReturn(0);
280d4002b98SHong Zhang 
2819566063dSJacob Faibussowitsch   PetscCall(MatStashScatterBegin_Private(mat, &mat->stash, mat->rmap->range));
2829566063dSJacob Faibussowitsch   PetscCall(MatStashGetInfo_Private(&mat->stash, &nstash, &reallocs));
2839566063dSJacob Faibussowitsch   PetscCall(PetscInfo(sell->A, "Stash has %" PetscInt_FMT " entries, uses %" PetscInt_FMT " mallocs.\n", nstash, reallocs));
284d4002b98SHong Zhang   PetscFunctionReturn(0);
285d4002b98SHong Zhang }
286d4002b98SHong Zhang 
2879371c9d4SSatish Balay PetscErrorCode MatAssemblyEnd_MPISELL(Mat mat, MatAssemblyType mode) {
288d4002b98SHong Zhang   Mat_MPISELL *sell = (Mat_MPISELL *)mat->data;
289d4002b98SHong Zhang   PetscMPIInt  n;
290d4002b98SHong Zhang   PetscInt     i, flg;
291d4002b98SHong Zhang   PetscInt    *row, *col;
292d4002b98SHong Zhang   PetscScalar *val;
293d4002b98SHong Zhang   PetscBool    other_disassembled;
294d4002b98SHong Zhang   /* do not use 'b = (Mat_SeqSELL*)sell->B->data' as B can be reset in disassembly */
295d4002b98SHong Zhang   PetscFunctionBegin;
296d4002b98SHong Zhang   if (!sell->donotstash && !mat->nooffprocentries) {
297d4002b98SHong Zhang     while (1) {
2989566063dSJacob Faibussowitsch       PetscCall(MatStashScatterGetMesg_Private(&mat->stash, &n, &row, &col, &val, &flg));
299d4002b98SHong Zhang       if (!flg) break;
300d4002b98SHong Zhang 
301d4002b98SHong Zhang       for (i = 0; i < n; i++) { /* assemble one by one */
3029566063dSJacob Faibussowitsch         PetscCall(MatSetValues_MPISELL(mat, 1, row + i, 1, col + i, val + i, mat->insertmode));
303d4002b98SHong Zhang       }
304d4002b98SHong Zhang     }
3059566063dSJacob Faibussowitsch     PetscCall(MatStashScatterEnd_Private(&mat->stash));
306d4002b98SHong Zhang   }
3079566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(sell->A, mode));
3089566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(sell->A, mode));
309d4002b98SHong Zhang 
310d4002b98SHong Zhang   /*
311d4002b98SHong Zhang      determine if any processor has disassembled, if so we must
3126aad120cSJose E. Roman      also disassemble ourselves, in order that we may reassemble.
313d4002b98SHong Zhang   */
314d4002b98SHong Zhang   /*
315d4002b98SHong Zhang      if nonzero structure of submatrix B cannot change then we know that
316d4002b98SHong Zhang      no processor disassembled thus we can skip this stuff
317d4002b98SHong Zhang   */
318d4002b98SHong Zhang   if (!((Mat_SeqSELL *)sell->B->data)->nonew) {
3195f9db2b2SJunchao Zhang     PetscCall(MPIU_Allreduce(&mat->was_assembled, &other_disassembled, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)mat)));
32008401ef6SPierre Jolivet     PetscCheck(!mat->was_assembled || other_disassembled, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatDisAssemble not implemented yet");
321d4002b98SHong Zhang   }
32248a46eb9SPierre Jolivet   if (!mat->was_assembled && mode == MAT_FINAL_ASSEMBLY) PetscCall(MatSetUpMultiply_MPISELL(mat));
323d4002b98SHong Zhang   /*
3249566063dSJacob Faibussowitsch   PetscCall(MatSetOption(sell->B,MAT_USE_INODES,PETSC_FALSE));
325d4002b98SHong Zhang   */
3269566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(sell->B, mode));
3279566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(sell->B, mode));
3289566063dSJacob Faibussowitsch   PetscCall(PetscFree2(sell->rowvalues, sell->rowindices));
329f4259b30SLisandro Dalcin   sell->rowvalues = NULL;
3309566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&sell->diag));
331d4002b98SHong Zhang 
332d4002b98SHong Zhang   /* if no new nonzero locations are allowed in matrix then only set the matrix state the first time through */
333d4002b98SHong Zhang   if ((!mat->was_assembled && mode == MAT_FINAL_ASSEMBLY) || !((Mat_SeqSELL *)(sell->A->data))->nonew) {
334d4002b98SHong Zhang     PetscObjectState state = sell->A->nonzerostate + sell->B->nonzerostate;
3351c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(&state, &mat->nonzerostate, 1, MPIU_INT64, MPI_SUM, PetscObjectComm((PetscObject)mat)));
336d4002b98SHong Zhang   }
337d4002b98SHong Zhang   PetscFunctionReturn(0);
338d4002b98SHong Zhang }
339d4002b98SHong Zhang 
3409371c9d4SSatish Balay PetscErrorCode MatZeroEntries_MPISELL(Mat A) {
341d4002b98SHong Zhang   Mat_MPISELL *l = (Mat_MPISELL *)A->data;
342d4002b98SHong Zhang 
343d4002b98SHong Zhang   PetscFunctionBegin;
3449566063dSJacob Faibussowitsch   PetscCall(MatZeroEntries(l->A));
3459566063dSJacob Faibussowitsch   PetscCall(MatZeroEntries(l->B));
346d4002b98SHong Zhang   PetscFunctionReturn(0);
347d4002b98SHong Zhang }
348d4002b98SHong Zhang 
3499371c9d4SSatish Balay PetscErrorCode MatMult_MPISELL(Mat A, Vec xx, Vec yy) {
350d4002b98SHong Zhang   Mat_MPISELL *a = (Mat_MPISELL *)A->data;
351d4002b98SHong Zhang   PetscInt     nt;
352d4002b98SHong Zhang 
353d4002b98SHong Zhang   PetscFunctionBegin;
3549566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(xx, &nt));
35508401ef6SPierre Jolivet   PetscCheck(nt == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Incompatible partition of A (%" PetscInt_FMT ") and xx (%" PetscInt_FMT ")", A->cmap->n, nt);
3569566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(a->Mvctx, xx, a->lvec, INSERT_VALUES, SCATTER_FORWARD));
3579566063dSJacob Faibussowitsch   PetscCall((*a->A->ops->mult)(a->A, xx, yy));
3589566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(a->Mvctx, xx, a->lvec, INSERT_VALUES, SCATTER_FORWARD));
3599566063dSJacob Faibussowitsch   PetscCall((*a->B->ops->multadd)(a->B, a->lvec, yy, yy));
360d4002b98SHong Zhang   PetscFunctionReturn(0);
361d4002b98SHong Zhang }
362d4002b98SHong Zhang 
3639371c9d4SSatish Balay PetscErrorCode MatMultDiagonalBlock_MPISELL(Mat A, Vec bb, Vec xx) {
364d4002b98SHong Zhang   Mat_MPISELL *a = (Mat_MPISELL *)A->data;
365d4002b98SHong Zhang 
366d4002b98SHong Zhang   PetscFunctionBegin;
3679566063dSJacob Faibussowitsch   PetscCall(MatMultDiagonalBlock(a->A, bb, xx));
368d4002b98SHong Zhang   PetscFunctionReturn(0);
369d4002b98SHong Zhang }
370d4002b98SHong Zhang 
3719371c9d4SSatish Balay PetscErrorCode MatMultAdd_MPISELL(Mat A, Vec xx, Vec yy, Vec zz) {
372d4002b98SHong Zhang   Mat_MPISELL *a = (Mat_MPISELL *)A->data;
373d4002b98SHong Zhang 
374d4002b98SHong Zhang   PetscFunctionBegin;
3759566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(a->Mvctx, xx, a->lvec, INSERT_VALUES, SCATTER_FORWARD));
3769566063dSJacob Faibussowitsch   PetscCall((*a->A->ops->multadd)(a->A, xx, yy, zz));
3779566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(a->Mvctx, xx, a->lvec, INSERT_VALUES, SCATTER_FORWARD));
3789566063dSJacob Faibussowitsch   PetscCall((*a->B->ops->multadd)(a->B, a->lvec, zz, zz));
379d4002b98SHong Zhang   PetscFunctionReturn(0);
380d4002b98SHong Zhang }
381d4002b98SHong Zhang 
3829371c9d4SSatish Balay PetscErrorCode MatMultTranspose_MPISELL(Mat A, Vec xx, Vec yy) {
383d4002b98SHong Zhang   Mat_MPISELL *a = (Mat_MPISELL *)A->data;
384d4002b98SHong Zhang 
385d4002b98SHong Zhang   PetscFunctionBegin;
386d4002b98SHong Zhang   /* do nondiagonal part */
3879566063dSJacob Faibussowitsch   PetscCall((*a->B->ops->multtranspose)(a->B, xx, a->lvec));
388d4002b98SHong Zhang   /* do local part */
3899566063dSJacob Faibussowitsch   PetscCall((*a->A->ops->multtranspose)(a->A, xx, yy));
390a29b4eb7SJunchao Zhang   /* add partial results together */
3919566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(a->Mvctx, a->lvec, yy, ADD_VALUES, SCATTER_REVERSE));
3929566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(a->Mvctx, a->lvec, yy, ADD_VALUES, SCATTER_REVERSE));
393d4002b98SHong Zhang   PetscFunctionReturn(0);
394d4002b98SHong Zhang }
395d4002b98SHong Zhang 
3969371c9d4SSatish Balay PetscErrorCode MatIsTranspose_MPISELL(Mat Amat, Mat Bmat, PetscReal tol, PetscBool *f) {
397d4002b98SHong Zhang   MPI_Comm     comm;
398d4002b98SHong Zhang   Mat_MPISELL *Asell = (Mat_MPISELL *)Amat->data, *Bsell;
399d4002b98SHong Zhang   Mat          Adia  = Asell->A, Bdia, Aoff, Boff, *Aoffs, *Boffs;
400d4002b98SHong Zhang   IS           Me, Notme;
401d4002b98SHong Zhang   PetscInt     M, N, first, last, *notme, i;
402d4002b98SHong Zhang   PetscMPIInt  size;
403d4002b98SHong Zhang 
404d4002b98SHong Zhang   PetscFunctionBegin;
405d4002b98SHong Zhang   /* Easy test: symmetric diagonal block */
4069371c9d4SSatish Balay   Bsell = (Mat_MPISELL *)Bmat->data;
4079371c9d4SSatish Balay   Bdia  = Bsell->A;
4089566063dSJacob Faibussowitsch   PetscCall(MatIsTranspose(Adia, Bdia, tol, f));
409d4002b98SHong Zhang   if (!*f) PetscFunctionReturn(0);
4109566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)Amat, &comm));
4119566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
412d4002b98SHong Zhang   if (size == 1) PetscFunctionReturn(0);
413d4002b98SHong Zhang 
414d4002b98SHong Zhang   /* Hard test: off-diagonal block. This takes a MatCreateSubMatrix. */
4159566063dSJacob Faibussowitsch   PetscCall(MatGetSize(Amat, &M, &N));
4169566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(Amat, &first, &last));
4179566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(N - last + first, &notme));
418d4002b98SHong Zhang   for (i = 0; i < first; i++) notme[i] = i;
419d4002b98SHong Zhang   for (i = last; i < M; i++) notme[i - last + first] = i;
4209566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(MPI_COMM_SELF, N - last + first, notme, PETSC_COPY_VALUES, &Notme));
4219566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(MPI_COMM_SELF, last - first, first, 1, &Me));
4229566063dSJacob Faibussowitsch   PetscCall(MatCreateSubMatrices(Amat, 1, &Me, &Notme, MAT_INITIAL_MATRIX, &Aoffs));
423d4002b98SHong Zhang   Aoff = Aoffs[0];
4249566063dSJacob Faibussowitsch   PetscCall(MatCreateSubMatrices(Bmat, 1, &Notme, &Me, MAT_INITIAL_MATRIX, &Boffs));
425d4002b98SHong Zhang   Boff = Boffs[0];
4269566063dSJacob Faibussowitsch   PetscCall(MatIsTranspose(Aoff, Boff, tol, f));
4279566063dSJacob Faibussowitsch   PetscCall(MatDestroyMatrices(1, &Aoffs));
4289566063dSJacob Faibussowitsch   PetscCall(MatDestroyMatrices(1, &Boffs));
4299566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&Me));
4309566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&Notme));
4319566063dSJacob Faibussowitsch   PetscCall(PetscFree(notme));
432d4002b98SHong Zhang   PetscFunctionReturn(0);
433d4002b98SHong Zhang }
434d4002b98SHong Zhang 
4359371c9d4SSatish Balay PetscErrorCode MatMultTransposeAdd_MPISELL(Mat A, Vec xx, Vec yy, Vec zz) {
436d4002b98SHong Zhang   Mat_MPISELL *a = (Mat_MPISELL *)A->data;
437d4002b98SHong Zhang 
438d4002b98SHong Zhang   PetscFunctionBegin;
439d4002b98SHong Zhang   /* do nondiagonal part */
4409566063dSJacob Faibussowitsch   PetscCall((*a->B->ops->multtranspose)(a->B, xx, a->lvec));
441d4002b98SHong Zhang   /* do local part */
4429566063dSJacob Faibussowitsch   PetscCall((*a->A->ops->multtransposeadd)(a->A, xx, yy, zz));
443e4a140f6SJunchao Zhang   /* add partial results together */
4449566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(a->Mvctx, a->lvec, zz, ADD_VALUES, SCATTER_REVERSE));
4459566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(a->Mvctx, a->lvec, zz, ADD_VALUES, SCATTER_REVERSE));
446d4002b98SHong Zhang   PetscFunctionReturn(0);
447d4002b98SHong Zhang }
448d4002b98SHong Zhang 
449d4002b98SHong Zhang /*
450d4002b98SHong Zhang   This only works correctly for square matrices where the subblock A->A is the
451d4002b98SHong Zhang    diagonal block
452d4002b98SHong Zhang */
4539371c9d4SSatish Balay PetscErrorCode MatGetDiagonal_MPISELL(Mat A, Vec v) {
454d4002b98SHong Zhang   Mat_MPISELL *a = (Mat_MPISELL *)A->data;
455d4002b98SHong Zhang 
456d4002b98SHong Zhang   PetscFunctionBegin;
45708401ef6SPierre Jolivet   PetscCheck(A->rmap->N == A->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Supports only square matrix where A->A is diag block");
458aed4548fSBarry Smith   PetscCheck(A->rmap->rstart == A->cmap->rstart && A->rmap->rend == A->cmap->rend, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "row partition must equal col partition");
4599566063dSJacob Faibussowitsch   PetscCall(MatGetDiagonal(a->A, v));
460d4002b98SHong Zhang   PetscFunctionReturn(0);
461d4002b98SHong Zhang }
462d4002b98SHong Zhang 
4639371c9d4SSatish Balay PetscErrorCode MatScale_MPISELL(Mat A, PetscScalar aa) {
464d4002b98SHong Zhang   Mat_MPISELL *a = (Mat_MPISELL *)A->data;
465d4002b98SHong Zhang 
466d4002b98SHong Zhang   PetscFunctionBegin;
4679566063dSJacob Faibussowitsch   PetscCall(MatScale(a->A, aa));
4689566063dSJacob Faibussowitsch   PetscCall(MatScale(a->B, aa));
469d4002b98SHong Zhang   PetscFunctionReturn(0);
470d4002b98SHong Zhang }
471d4002b98SHong Zhang 
4729371c9d4SSatish Balay PetscErrorCode MatDestroy_MPISELL(Mat mat) {
473d4002b98SHong Zhang   Mat_MPISELL *sell = (Mat_MPISELL *)mat->data;
474d4002b98SHong Zhang 
475d4002b98SHong Zhang   PetscFunctionBegin;
476d4002b98SHong Zhang #if defined(PETSC_USE_LOG)
477c0aa6a63SJacob Faibussowitsch   PetscLogObjectState((PetscObject)mat, "Rows=%" PetscInt_FMT ", Cols=%" PetscInt_FMT, mat->rmap->N, mat->cmap->N);
478d4002b98SHong Zhang #endif
4799566063dSJacob Faibussowitsch   PetscCall(MatStashDestroy_Private(&mat->stash));
4809566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&sell->diag));
4819566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&sell->A));
4829566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&sell->B));
483d4002b98SHong Zhang #if defined(PETSC_USE_CTABLE)
4849566063dSJacob Faibussowitsch   PetscCall(PetscTableDestroy(&sell->colmap));
485d4002b98SHong Zhang #else
4869566063dSJacob Faibussowitsch   PetscCall(PetscFree(sell->colmap));
487d4002b98SHong Zhang #endif
4889566063dSJacob Faibussowitsch   PetscCall(PetscFree(sell->garray));
4899566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&sell->lvec));
4909566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&sell->Mvctx));
4919566063dSJacob Faibussowitsch   PetscCall(PetscFree2(sell->rowvalues, sell->rowindices));
4929566063dSJacob Faibussowitsch   PetscCall(PetscFree(sell->ld));
4939566063dSJacob Faibussowitsch   PetscCall(PetscFree(mat->data));
494d4002b98SHong Zhang 
4959566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)mat, NULL));
4969566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatStoreValues_C", NULL));
4979566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatRetrieveValues_C", NULL));
4989566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatIsTranspose_C", NULL));
4999566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatMPISELLSetPreallocation_C", NULL));
5009566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_mpisell_mpiaij_C", NULL));
5019566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDiagonalScaleLocal_C", NULL));
502d4002b98SHong Zhang   PetscFunctionReturn(0);
503d4002b98SHong Zhang }
504d4002b98SHong Zhang 
505d4002b98SHong Zhang #include <petscdraw.h>
5069371c9d4SSatish Balay PetscErrorCode MatView_MPISELL_ASCIIorDraworSocket(Mat mat, PetscViewer viewer) {
507d4002b98SHong Zhang   Mat_MPISELL      *sell = (Mat_MPISELL *)mat->data;
508d4002b98SHong Zhang   PetscMPIInt       rank = sell->rank, size = sell->size;
509d4002b98SHong Zhang   PetscBool         isdraw, iascii, isbinary;
510d4002b98SHong Zhang   PetscViewer       sviewer;
511d4002b98SHong Zhang   PetscViewerFormat format;
512d4002b98SHong Zhang 
513d4002b98SHong Zhang   PetscFunctionBegin;
5149566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
5159566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
5169566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
517d4002b98SHong Zhang   if (iascii) {
5189566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
519d4002b98SHong Zhang     if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
520d4002b98SHong Zhang       MatInfo   info;
5216335e310SSatish Balay       PetscInt *inodes;
522d4002b98SHong Zhang 
5239566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)mat), &rank));
5249566063dSJacob Faibussowitsch       PetscCall(MatGetInfo(mat, MAT_LOCAL, &info));
5259566063dSJacob Faibussowitsch       PetscCall(MatInodeGetInodeSizes(sell->A, NULL, &inodes, NULL));
5269566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushSynchronized(viewer));
527d4002b98SHong Zhang       if (!inodes) {
5289371c9d4SSatish Balay         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Local rows %" PetscInt_FMT " nz %" PetscInt_FMT " nz alloced %" PetscInt_FMT " mem %" PetscInt_FMT ", not using I-node routines\n", rank, mat->rmap->n, (PetscInt)info.nz_used,
5299371c9d4SSatish Balay                                                      (PetscInt)info.nz_allocated, (PetscInt)info.memory));
530d4002b98SHong Zhang       } else {
5319371c9d4SSatish Balay         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Local rows %" PetscInt_FMT " nz %" PetscInt_FMT " nz alloced %" PetscInt_FMT " mem %" PetscInt_FMT ", using I-node routines\n", rank, mat->rmap->n, (PetscInt)info.nz_used,
5329371c9d4SSatish Balay                                                      (PetscInt)info.nz_allocated, (PetscInt)info.memory));
533d4002b98SHong Zhang       }
5349566063dSJacob Faibussowitsch       PetscCall(MatGetInfo(sell->A, MAT_LOCAL, &info));
5359566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] on-diagonal part: nz %" PetscInt_FMT " \n", rank, (PetscInt)info.nz_used));
5369566063dSJacob Faibussowitsch       PetscCall(MatGetInfo(sell->B, MAT_LOCAL, &info));
5379566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] off-diagonal part: nz %" PetscInt_FMT " \n", rank, (PetscInt)info.nz_used));
5389566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(viewer));
5399566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopSynchronized(viewer));
5409566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "Information on VecScatter used in matrix-vector product: \n"));
5419566063dSJacob Faibussowitsch       PetscCall(VecScatterView(sell->Mvctx, viewer));
542d4002b98SHong Zhang       PetscFunctionReturn(0);
543d4002b98SHong Zhang     } else if (format == PETSC_VIEWER_ASCII_INFO) {
544d4002b98SHong Zhang       PetscInt inodecount, inodelimit, *inodes;
5459566063dSJacob Faibussowitsch       PetscCall(MatInodeGetInodeSizes(sell->A, &inodecount, &inodes, &inodelimit));
546d4002b98SHong Zhang       if (inodes) {
5479566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "using I-node (on process 0) routines: found %" PetscInt_FMT " nodes, limit used is %" PetscInt_FMT "\n", inodecount, inodelimit));
548d4002b98SHong Zhang       } else {
5499566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "not using I-node (on process 0) routines\n"));
550d4002b98SHong Zhang       }
551d4002b98SHong Zhang       PetscFunctionReturn(0);
552d4002b98SHong Zhang     } else if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) {
553d4002b98SHong Zhang       PetscFunctionReturn(0);
554d4002b98SHong Zhang     }
555d4002b98SHong Zhang   } else if (isbinary) {
556d4002b98SHong Zhang     if (size == 1) {
5579566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)sell->A, ((PetscObject)mat)->name));
5589566063dSJacob Faibussowitsch       PetscCall(MatView(sell->A, viewer));
559d4002b98SHong Zhang     } else {
5609566063dSJacob Faibussowitsch       /* PetscCall(MatView_MPISELL_Binary(mat,viewer)); */
561d4002b98SHong Zhang     }
562d4002b98SHong Zhang     PetscFunctionReturn(0);
563d4002b98SHong Zhang   } else if (isdraw) {
564d4002b98SHong Zhang     PetscDraw draw;
565d4002b98SHong Zhang     PetscBool isnull;
5669566063dSJacob Faibussowitsch     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
5679566063dSJacob Faibussowitsch     PetscCall(PetscDrawIsNull(draw, &isnull));
568d4002b98SHong Zhang     if (isnull) PetscFunctionReturn(0);
569d4002b98SHong Zhang   }
570d4002b98SHong Zhang 
571d4002b98SHong Zhang   {
572d4002b98SHong Zhang     /* assemble the entire matrix onto first processor. */
573d4002b98SHong Zhang     Mat          A;
574d4002b98SHong Zhang     Mat_SeqSELL *Aloc;
575d4002b98SHong Zhang     PetscInt     M = mat->rmap->N, N = mat->cmap->N, *acolidx, row, col, i, j;
576d4002b98SHong Zhang     MatScalar   *aval;
577d4002b98SHong Zhang     PetscBool    isnonzero;
578d4002b98SHong Zhang 
5799566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &A));
580dd400576SPatrick Sanan     if (rank == 0) {
5819566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(A, M, N, M, N));
582d4002b98SHong Zhang     } else {
5839566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(A, 0, 0, M, N));
584d4002b98SHong Zhang     }
585d4002b98SHong Zhang     /* This is just a temporary matrix, so explicitly using MATMPISELL is probably best */
5869566063dSJacob Faibussowitsch     PetscCall(MatSetType(A, MATMPISELL));
5879566063dSJacob Faibussowitsch     PetscCall(MatMPISELLSetPreallocation(A, 0, NULL, 0, NULL));
5889566063dSJacob Faibussowitsch     PetscCall(MatSetOption(A, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_FALSE));
589d4002b98SHong Zhang 
590d4002b98SHong Zhang     /* copy over the A part */
591d4002b98SHong Zhang     Aloc    = (Mat_SeqSELL *)sell->A->data;
5929371c9d4SSatish Balay     acolidx = Aloc->colidx;
5939371c9d4SSatish Balay     aval    = Aloc->val;
594d4002b98SHong Zhang     for (i = 0; i < Aloc->totalslices; i++) { /* loop over slices */
595d4002b98SHong Zhang       for (j = Aloc->sliidx[i]; j < Aloc->sliidx[i + 1]; j++) {
596d4002b98SHong Zhang         isnonzero = (PetscBool)((j - Aloc->sliidx[i]) / 8 < Aloc->rlen[(i << 3) + (j & 0x07)]);
597d4002b98SHong Zhang         if (isnonzero) {                                   /* check the mask bit */
598d4002b98SHong Zhang           row = (i << 3) + (j & 0x07) + mat->rmap->rstart; /* i<<3 is the starting row of this slice */
599d4002b98SHong Zhang           col = *acolidx + mat->rmap->rstart;
6009566063dSJacob Faibussowitsch           PetscCall(MatSetValues(A, 1, &row, 1, &col, aval, INSERT_VALUES));
601d4002b98SHong Zhang         }
6029371c9d4SSatish Balay         aval++;
6039371c9d4SSatish Balay         acolidx++;
604d4002b98SHong Zhang       }
605d4002b98SHong Zhang     }
606d4002b98SHong Zhang 
607d4002b98SHong Zhang     /* copy over the B part */
608d4002b98SHong Zhang     Aloc    = (Mat_SeqSELL *)sell->B->data;
6099371c9d4SSatish Balay     acolidx = Aloc->colidx;
6109371c9d4SSatish Balay     aval    = Aloc->val;
611d4002b98SHong Zhang     for (i = 0; i < Aloc->totalslices; i++) {
612d4002b98SHong Zhang       for (j = Aloc->sliidx[i]; j < Aloc->sliidx[i + 1]; j++) {
613d4002b98SHong Zhang         isnonzero = (PetscBool)((j - Aloc->sliidx[i]) / 8 < Aloc->rlen[(i << 3) + (j & 0x07)]);
614d4002b98SHong Zhang         if (isnonzero) {
615d4002b98SHong Zhang           row = (i << 3) + (j & 0x07) + mat->rmap->rstart;
616d4002b98SHong Zhang           col = sell->garray[*acolidx];
6179566063dSJacob Faibussowitsch           PetscCall(MatSetValues(A, 1, &row, 1, &col, aval, INSERT_VALUES));
618d4002b98SHong Zhang         }
6199371c9d4SSatish Balay         aval++;
6209371c9d4SSatish Balay         acolidx++;
621d4002b98SHong Zhang       }
622d4002b98SHong Zhang     }
623d4002b98SHong Zhang 
6249566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
6259566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
626d4002b98SHong Zhang     /*
627d4002b98SHong Zhang        Everyone has to call to draw the matrix since the graphics waits are
628d4002b98SHong Zhang        synchronized across all processors that share the PetscDraw object
629d4002b98SHong Zhang     */
6309566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetSubViewer(viewer, PETSC_COMM_SELF, &sviewer));
631dd400576SPatrick Sanan     if (rank == 0) {
6329566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)((Mat_MPISELL *)(A->data))->A, ((PetscObject)mat)->name));
6339566063dSJacob Faibussowitsch       PetscCall(MatView_SeqSELL(((Mat_MPISELL *)(A->data))->A, sviewer));
634d4002b98SHong Zhang     }
6359566063dSJacob Faibussowitsch     PetscCall(PetscViewerRestoreSubViewer(viewer, PETSC_COMM_SELF, &sviewer));
6369566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
6379566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&A));
638d4002b98SHong Zhang   }
639d4002b98SHong Zhang   PetscFunctionReturn(0);
640d4002b98SHong Zhang }
641d4002b98SHong Zhang 
6429371c9d4SSatish Balay PetscErrorCode MatView_MPISELL(Mat mat, PetscViewer viewer) {
643d4002b98SHong Zhang   PetscBool iascii, isdraw, issocket, isbinary;
644d4002b98SHong Zhang 
645d4002b98SHong Zhang   PetscFunctionBegin;
6469566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
6479566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
6489566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
6499566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSOCKET, &issocket));
65048a46eb9SPierre Jolivet   if (iascii || isdraw || isbinary || issocket) PetscCall(MatView_MPISELL_ASCIIorDraworSocket(mat, viewer));
651d4002b98SHong Zhang   PetscFunctionReturn(0);
652d4002b98SHong Zhang }
653d4002b98SHong Zhang 
6549371c9d4SSatish Balay PetscErrorCode MatGetGhosts_MPISELL(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[]) {
655d4002b98SHong Zhang   Mat_MPISELL *sell = (Mat_MPISELL *)mat->data;
656d4002b98SHong Zhang 
657d4002b98SHong Zhang   PetscFunctionBegin;
6589566063dSJacob Faibussowitsch   PetscCall(MatGetSize(sell->B, NULL, nghosts));
659d4002b98SHong Zhang   if (ghosts) *ghosts = sell->garray;
660d4002b98SHong Zhang   PetscFunctionReturn(0);
661d4002b98SHong Zhang }
662d4002b98SHong Zhang 
6639371c9d4SSatish Balay PetscErrorCode MatGetInfo_MPISELL(Mat matin, MatInfoType flag, MatInfo *info) {
664d4002b98SHong Zhang   Mat_MPISELL   *mat = (Mat_MPISELL *)matin->data;
665d4002b98SHong Zhang   Mat            A = mat->A, B = mat->B;
6663966268fSBarry Smith   PetscLogDouble isend[5], irecv[5];
667d4002b98SHong Zhang 
668d4002b98SHong Zhang   PetscFunctionBegin;
669d4002b98SHong Zhang   info->block_size = 1.0;
6709566063dSJacob Faibussowitsch   PetscCall(MatGetInfo(A, MAT_LOCAL, info));
671d4002b98SHong Zhang 
6729371c9d4SSatish Balay   isend[0] = info->nz_used;
6739371c9d4SSatish Balay   isend[1] = info->nz_allocated;
6749371c9d4SSatish Balay   isend[2] = info->nz_unneeded;
6759371c9d4SSatish Balay   isend[3] = info->memory;
6769371c9d4SSatish Balay   isend[4] = info->mallocs;
677d4002b98SHong Zhang 
6789566063dSJacob Faibussowitsch   PetscCall(MatGetInfo(B, MAT_LOCAL, info));
679d4002b98SHong Zhang 
6809371c9d4SSatish Balay   isend[0] += info->nz_used;
6819371c9d4SSatish Balay   isend[1] += info->nz_allocated;
6829371c9d4SSatish Balay   isend[2] += info->nz_unneeded;
6839371c9d4SSatish Balay   isend[3] += info->memory;
6849371c9d4SSatish Balay   isend[4] += info->mallocs;
685d4002b98SHong Zhang   if (flag == MAT_LOCAL) {
686d4002b98SHong Zhang     info->nz_used      = isend[0];
687d4002b98SHong Zhang     info->nz_allocated = isend[1];
688d4002b98SHong Zhang     info->nz_unneeded  = isend[2];
689d4002b98SHong Zhang     info->memory       = isend[3];
690d4002b98SHong Zhang     info->mallocs      = isend[4];
691d4002b98SHong Zhang   } else if (flag == MAT_GLOBAL_MAX) {
6921c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(isend, irecv, 5, MPIU_PETSCLOGDOUBLE, MPI_MAX, PetscObjectComm((PetscObject)matin)));
693d4002b98SHong Zhang 
694d4002b98SHong Zhang     info->nz_used      = irecv[0];
695d4002b98SHong Zhang     info->nz_allocated = irecv[1];
696d4002b98SHong Zhang     info->nz_unneeded  = irecv[2];
697d4002b98SHong Zhang     info->memory       = irecv[3];
698d4002b98SHong Zhang     info->mallocs      = irecv[4];
699d4002b98SHong Zhang   } else if (flag == MAT_GLOBAL_SUM) {
7001c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(isend, irecv, 5, MPIU_PETSCLOGDOUBLE, MPI_SUM, PetscObjectComm((PetscObject)matin)));
701d4002b98SHong Zhang 
702d4002b98SHong Zhang     info->nz_used      = irecv[0];
703d4002b98SHong Zhang     info->nz_allocated = irecv[1];
704d4002b98SHong Zhang     info->nz_unneeded  = irecv[2];
705d4002b98SHong Zhang     info->memory       = irecv[3];
706d4002b98SHong Zhang     info->mallocs      = irecv[4];
707d4002b98SHong Zhang   }
708d4002b98SHong Zhang   info->fill_ratio_given  = 0; /* no parallel LU/ILU/Cholesky */
709d4002b98SHong Zhang   info->fill_ratio_needed = 0;
710d4002b98SHong Zhang   info->factor_mallocs    = 0;
711d4002b98SHong Zhang   PetscFunctionReturn(0);
712d4002b98SHong Zhang }
713d4002b98SHong Zhang 
7149371c9d4SSatish Balay PetscErrorCode MatSetOption_MPISELL(Mat A, MatOption op, PetscBool flg) {
715d4002b98SHong Zhang   Mat_MPISELL *a = (Mat_MPISELL *)A->data;
716d4002b98SHong Zhang 
717d4002b98SHong Zhang   PetscFunctionBegin;
718d4002b98SHong Zhang   switch (op) {
719d4002b98SHong Zhang   case MAT_NEW_NONZERO_LOCATIONS:
720d4002b98SHong Zhang   case MAT_NEW_NONZERO_ALLOCATION_ERR:
721d4002b98SHong Zhang   case MAT_UNUSED_NONZERO_LOCATION_ERR:
722d4002b98SHong Zhang   case MAT_KEEP_NONZERO_PATTERN:
723d4002b98SHong Zhang   case MAT_NEW_NONZERO_LOCATION_ERR:
724d4002b98SHong Zhang   case MAT_USE_INODES:
725d4002b98SHong Zhang   case MAT_IGNORE_ZERO_ENTRIES:
726d4002b98SHong Zhang     MatCheckPreallocated(A, 1);
7279566063dSJacob Faibussowitsch     PetscCall(MatSetOption(a->A, op, flg));
7289566063dSJacob Faibussowitsch     PetscCall(MatSetOption(a->B, op, flg));
729d4002b98SHong Zhang     break;
730d4002b98SHong Zhang   case MAT_ROW_ORIENTED:
731d4002b98SHong Zhang     MatCheckPreallocated(A, 1);
732d4002b98SHong Zhang     a->roworiented = flg;
733d4002b98SHong Zhang 
7349566063dSJacob Faibussowitsch     PetscCall(MatSetOption(a->A, op, flg));
7359566063dSJacob Faibussowitsch     PetscCall(MatSetOption(a->B, op, flg));
736d4002b98SHong Zhang     break;
7378c78258cSHong Zhang   case MAT_FORCE_DIAGONAL_ENTRIES:
7389371c9d4SSatish Balay   case MAT_SORTED_FULL: PetscCall(PetscInfo(A, "Option %s ignored\n", MatOptions[op])); break;
7399371c9d4SSatish Balay   case MAT_IGNORE_OFF_PROC_ENTRIES: a->donotstash = flg; break;
740d4002b98SHong Zhang   case MAT_SPD:
7419371c9d4SSatish Balay   case MAT_SPD_ETERNAL: break;
742d4002b98SHong Zhang   case MAT_SYMMETRIC:
743d4002b98SHong Zhang     MatCheckPreallocated(A, 1);
7449566063dSJacob Faibussowitsch     PetscCall(MatSetOption(a->A, op, flg));
745d4002b98SHong Zhang     break;
746d4002b98SHong Zhang   case MAT_STRUCTURALLY_SYMMETRIC:
747d4002b98SHong Zhang     MatCheckPreallocated(A, 1);
7489566063dSJacob Faibussowitsch     PetscCall(MatSetOption(a->A, op, flg));
749d4002b98SHong Zhang     break;
750d4002b98SHong Zhang   case MAT_HERMITIAN:
751d4002b98SHong Zhang     MatCheckPreallocated(A, 1);
7529566063dSJacob Faibussowitsch     PetscCall(MatSetOption(a->A, op, flg));
753d4002b98SHong Zhang     break;
754d4002b98SHong Zhang   case MAT_SYMMETRY_ETERNAL:
755d4002b98SHong Zhang     MatCheckPreallocated(A, 1);
7569566063dSJacob Faibussowitsch     PetscCall(MatSetOption(a->A, op, flg));
757d4002b98SHong Zhang     break;
758b94d7dedSBarry Smith   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
759b94d7dedSBarry Smith     MatCheckPreallocated(A, 1);
760b94d7dedSBarry Smith     PetscCall(MatSetOption(a->A, op, flg));
761b94d7dedSBarry Smith     break;
7629371c9d4SSatish Balay   default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "unknown option %d", op);
763d4002b98SHong Zhang   }
764d4002b98SHong Zhang   PetscFunctionReturn(0);
765d4002b98SHong Zhang }
766d4002b98SHong Zhang 
7679371c9d4SSatish Balay PetscErrorCode MatDiagonalScale_MPISELL(Mat mat, Vec ll, Vec rr) {
768d4002b98SHong Zhang   Mat_MPISELL *sell = (Mat_MPISELL *)mat->data;
769d4002b98SHong Zhang   Mat          a = sell->A, b = sell->B;
770d4002b98SHong Zhang   PetscInt     s1, s2, s3;
771d4002b98SHong Zhang 
772d4002b98SHong Zhang   PetscFunctionBegin;
7739566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(mat, &s2, &s3));
774d4002b98SHong Zhang   if (rr) {
7759566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(rr, &s1));
77608401ef6SPierre Jolivet     PetscCheck(s1 == s3, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "right vector non-conforming local size");
777d4002b98SHong Zhang     /* Overlap communication with computation. */
7789566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(sell->Mvctx, rr, sell->lvec, INSERT_VALUES, SCATTER_FORWARD));
779d4002b98SHong Zhang   }
780d4002b98SHong Zhang   if (ll) {
7819566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(ll, &s1));
78208401ef6SPierre Jolivet     PetscCheck(s1 == s2, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "left vector non-conforming local size");
783dbbe0bcdSBarry Smith     PetscUseTypeMethod(b, diagonalscale, ll, NULL);
784d4002b98SHong Zhang   }
785d4002b98SHong Zhang   /* scale  the diagonal block */
786dbbe0bcdSBarry Smith   PetscUseTypeMethod(a, diagonalscale, ll, rr);
787d4002b98SHong Zhang 
788d4002b98SHong Zhang   if (rr) {
789d4002b98SHong Zhang     /* Do a scatter end and then right scale the off-diagonal block */
7909566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(sell->Mvctx, rr, sell->lvec, INSERT_VALUES, SCATTER_FORWARD));
791dbbe0bcdSBarry Smith     PetscUseTypeMethod(b, diagonalscale, NULL, sell->lvec);
792d4002b98SHong Zhang   }
793d4002b98SHong Zhang   PetscFunctionReturn(0);
794d4002b98SHong Zhang }
795d4002b98SHong Zhang 
7969371c9d4SSatish Balay PetscErrorCode MatSetUnfactored_MPISELL(Mat A) {
797d4002b98SHong Zhang   Mat_MPISELL *a = (Mat_MPISELL *)A->data;
798d4002b98SHong Zhang 
799d4002b98SHong Zhang   PetscFunctionBegin;
8009566063dSJacob Faibussowitsch   PetscCall(MatSetUnfactored(a->A));
801d4002b98SHong Zhang   PetscFunctionReturn(0);
802d4002b98SHong Zhang }
803d4002b98SHong Zhang 
8049371c9d4SSatish Balay PetscErrorCode MatEqual_MPISELL(Mat A, Mat B, PetscBool *flag) {
805d4002b98SHong Zhang   Mat_MPISELL *matB = (Mat_MPISELL *)B->data, *matA = (Mat_MPISELL *)A->data;
806d4002b98SHong Zhang   Mat          a, b, c, d;
807d4002b98SHong Zhang   PetscBool    flg;
808d4002b98SHong Zhang 
809d4002b98SHong Zhang   PetscFunctionBegin;
8109371c9d4SSatish Balay   a = matA->A;
8119371c9d4SSatish Balay   b = matA->B;
8129371c9d4SSatish Balay   c = matB->A;
8139371c9d4SSatish Balay   d = matB->B;
814d4002b98SHong Zhang 
8159566063dSJacob Faibussowitsch   PetscCall(MatEqual(a, c, &flg));
81648a46eb9SPierre Jolivet   if (flg) PetscCall(MatEqual(b, d, &flg));
8171c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&flg, flag, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)A)));
818d4002b98SHong Zhang   PetscFunctionReturn(0);
819d4002b98SHong Zhang }
820d4002b98SHong Zhang 
8219371c9d4SSatish Balay PetscErrorCode MatCopy_MPISELL(Mat A, Mat B, MatStructure str) {
822d4002b98SHong Zhang   Mat_MPISELL *a = (Mat_MPISELL *)A->data;
823d4002b98SHong Zhang   Mat_MPISELL *b = (Mat_MPISELL *)B->data;
824d4002b98SHong Zhang 
825d4002b98SHong Zhang   PetscFunctionBegin;
826d4002b98SHong Zhang   /* If the two matrices don't have the same copy implementation, they aren't compatible for fast copy. */
827d4002b98SHong Zhang   if ((str != SAME_NONZERO_PATTERN) || (A->ops->copy != B->ops->copy)) {
828d4002b98SHong Zhang     /* because of the column compression in the off-processor part of the matrix a->B,
829d4002b98SHong Zhang        the number of columns in a->B and b->B may be different, hence we cannot call
830d4002b98SHong Zhang        the MatCopy() directly on the two parts. If need be, we can provide a more
831d4002b98SHong Zhang        efficient copy than the MatCopy_Basic() by first uncompressing the a->B matrices
832d4002b98SHong Zhang        then copying the submatrices */
8339566063dSJacob Faibussowitsch     PetscCall(MatCopy_Basic(A, B, str));
834d4002b98SHong Zhang   } else {
8359566063dSJacob Faibussowitsch     PetscCall(MatCopy(a->A, b->A, str));
8369566063dSJacob Faibussowitsch     PetscCall(MatCopy(a->B, b->B, str));
837d4002b98SHong Zhang   }
838d4002b98SHong Zhang   PetscFunctionReturn(0);
839d4002b98SHong Zhang }
840d4002b98SHong Zhang 
8419371c9d4SSatish Balay PetscErrorCode MatSetUp_MPISELL(Mat A) {
842d4002b98SHong Zhang   PetscFunctionBegin;
8439566063dSJacob Faibussowitsch   PetscCall(MatMPISELLSetPreallocation(A, PETSC_DEFAULT, NULL, PETSC_DEFAULT, NULL));
844d4002b98SHong Zhang   PetscFunctionReturn(0);
845d4002b98SHong Zhang }
846d4002b98SHong Zhang 
847d4002b98SHong Zhang extern PetscErrorCode MatConjugate_SeqSELL(Mat);
848d4002b98SHong Zhang 
8499371c9d4SSatish Balay PetscErrorCode MatConjugate_MPISELL(Mat mat) {
8505f80ce2aSJacob Faibussowitsch   PetscFunctionBegin;
8515f80ce2aSJacob Faibussowitsch   if (PetscDefined(USE_COMPLEX)) {
852d4002b98SHong Zhang     Mat_MPISELL *sell = (Mat_MPISELL *)mat->data;
853d4002b98SHong Zhang 
8549566063dSJacob Faibussowitsch     PetscCall(MatConjugate_SeqSELL(sell->A));
8559566063dSJacob Faibussowitsch     PetscCall(MatConjugate_SeqSELL(sell->B));
8565f80ce2aSJacob Faibussowitsch   }
857d4002b98SHong Zhang   PetscFunctionReturn(0);
858d4002b98SHong Zhang }
859d4002b98SHong Zhang 
8609371c9d4SSatish Balay PetscErrorCode MatRealPart_MPISELL(Mat A) {
861d4002b98SHong Zhang   Mat_MPISELL *a = (Mat_MPISELL *)A->data;
862d4002b98SHong Zhang 
863d4002b98SHong Zhang   PetscFunctionBegin;
8649566063dSJacob Faibussowitsch   PetscCall(MatRealPart(a->A));
8659566063dSJacob Faibussowitsch   PetscCall(MatRealPart(a->B));
866d4002b98SHong Zhang   PetscFunctionReturn(0);
867d4002b98SHong Zhang }
868d4002b98SHong Zhang 
8699371c9d4SSatish Balay PetscErrorCode MatImaginaryPart_MPISELL(Mat A) {
870d4002b98SHong Zhang   Mat_MPISELL *a = (Mat_MPISELL *)A->data;
871d4002b98SHong Zhang 
872d4002b98SHong Zhang   PetscFunctionBegin;
8739566063dSJacob Faibussowitsch   PetscCall(MatImaginaryPart(a->A));
8749566063dSJacob Faibussowitsch   PetscCall(MatImaginaryPart(a->B));
875d4002b98SHong Zhang   PetscFunctionReturn(0);
876d4002b98SHong Zhang }
877d4002b98SHong Zhang 
8789371c9d4SSatish Balay PetscErrorCode MatInvertBlockDiagonal_MPISELL(Mat A, const PetscScalar **values) {
879d4002b98SHong Zhang   Mat_MPISELL *a = (Mat_MPISELL *)A->data;
880d4002b98SHong Zhang 
881d4002b98SHong Zhang   PetscFunctionBegin;
8829566063dSJacob Faibussowitsch   PetscCall(MatInvertBlockDiagonal(a->A, values));
883d4002b98SHong Zhang   A->factorerrortype = a->A->factorerrortype;
884d4002b98SHong Zhang   PetscFunctionReturn(0);
885d4002b98SHong Zhang }
886d4002b98SHong Zhang 
8879371c9d4SSatish Balay static PetscErrorCode MatSetRandom_MPISELL(Mat x, PetscRandom rctx) {
888d4002b98SHong Zhang   Mat_MPISELL *sell = (Mat_MPISELL *)x->data;
889d4002b98SHong Zhang 
890d4002b98SHong Zhang   PetscFunctionBegin;
8919566063dSJacob Faibussowitsch   PetscCall(MatSetRandom(sell->A, rctx));
8929566063dSJacob Faibussowitsch   PetscCall(MatSetRandom(sell->B, rctx));
8939566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY));
8949566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY));
895d4002b98SHong Zhang   PetscFunctionReturn(0);
896d4002b98SHong Zhang }
897d4002b98SHong Zhang 
8989371c9d4SSatish Balay PetscErrorCode MatSetFromOptions_MPISELL(Mat A, PetscOptionItems *PetscOptionsObject) {
899d4002b98SHong Zhang   PetscFunctionBegin;
900d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "MPISELL options");
901d0609cedSBarry Smith   PetscOptionsHeadEnd();
902d4002b98SHong Zhang   PetscFunctionReturn(0);
903d4002b98SHong Zhang }
904d4002b98SHong Zhang 
9059371c9d4SSatish Balay PetscErrorCode MatShift_MPISELL(Mat Y, PetscScalar a) {
906d4002b98SHong Zhang   Mat_MPISELL *msell = (Mat_MPISELL *)Y->data;
907d4002b98SHong Zhang   Mat_SeqSELL *sell  = (Mat_SeqSELL *)msell->A->data;
908d4002b98SHong Zhang 
909d4002b98SHong Zhang   PetscFunctionBegin;
910d4002b98SHong Zhang   if (!Y->preallocated) {
9119566063dSJacob Faibussowitsch     PetscCall(MatMPISELLSetPreallocation(Y, 1, NULL, 0, NULL));
912d4002b98SHong Zhang   } else if (!sell->nz) {
913d4002b98SHong Zhang     PetscInt nonew = sell->nonew;
9149566063dSJacob Faibussowitsch     PetscCall(MatSeqSELLSetPreallocation(msell->A, 1, NULL));
915d4002b98SHong Zhang     sell->nonew = nonew;
916d4002b98SHong Zhang   }
9179566063dSJacob Faibussowitsch   PetscCall(MatShift_Basic(Y, a));
918d4002b98SHong Zhang   PetscFunctionReturn(0);
919d4002b98SHong Zhang }
920d4002b98SHong Zhang 
9219371c9d4SSatish Balay PetscErrorCode MatMissingDiagonal_MPISELL(Mat A, PetscBool *missing, PetscInt *d) {
922d4002b98SHong Zhang   Mat_MPISELL *a = (Mat_MPISELL *)A->data;
923d4002b98SHong Zhang 
924d4002b98SHong Zhang   PetscFunctionBegin;
92508401ef6SPierre Jolivet   PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only works for square matrices");
9269566063dSJacob Faibussowitsch   PetscCall(MatMissingDiagonal(a->A, missing, d));
927d4002b98SHong Zhang   if (d) {
928d4002b98SHong Zhang     PetscInt rstart;
9299566063dSJacob Faibussowitsch     PetscCall(MatGetOwnershipRange(A, &rstart, NULL));
930d4002b98SHong Zhang     *d += rstart;
931d4002b98SHong Zhang   }
932d4002b98SHong Zhang   PetscFunctionReturn(0);
933d4002b98SHong Zhang }
934d4002b98SHong Zhang 
9359371c9d4SSatish Balay PetscErrorCode MatGetDiagonalBlock_MPISELL(Mat A, Mat *a) {
936d4002b98SHong Zhang   PetscFunctionBegin;
937d4002b98SHong Zhang   *a = ((Mat_MPISELL *)A->data)->A;
938d4002b98SHong Zhang   PetscFunctionReturn(0);
939d4002b98SHong Zhang }
940d4002b98SHong Zhang 
941d4002b98SHong Zhang /* -------------------------------------------------------------------*/
942d4002b98SHong Zhang static struct _MatOps MatOps_Values = {MatSetValues_MPISELL,
943f4259b30SLisandro Dalcin                                        NULL,
944f4259b30SLisandro Dalcin                                        NULL,
945d4002b98SHong Zhang                                        MatMult_MPISELL,
946d4002b98SHong Zhang                                        /* 4*/ MatMultAdd_MPISELL,
947d4002b98SHong Zhang                                        MatMultTranspose_MPISELL,
948d4002b98SHong Zhang                                        MatMultTransposeAdd_MPISELL,
949f4259b30SLisandro Dalcin                                        NULL,
950f4259b30SLisandro Dalcin                                        NULL,
951f4259b30SLisandro Dalcin                                        NULL,
952f4259b30SLisandro Dalcin                                        /*10*/ NULL,
953f4259b30SLisandro Dalcin                                        NULL,
954f4259b30SLisandro Dalcin                                        NULL,
955d4002b98SHong Zhang                                        MatSOR_MPISELL,
956f4259b30SLisandro Dalcin                                        NULL,
957d4002b98SHong Zhang                                        /*15*/ MatGetInfo_MPISELL,
958d4002b98SHong Zhang                                        MatEqual_MPISELL,
959d4002b98SHong Zhang                                        MatGetDiagonal_MPISELL,
960d4002b98SHong Zhang                                        MatDiagonalScale_MPISELL,
961f4259b30SLisandro Dalcin                                        NULL,
962d4002b98SHong Zhang                                        /*20*/ MatAssemblyBegin_MPISELL,
963d4002b98SHong Zhang                                        MatAssemblyEnd_MPISELL,
964d4002b98SHong Zhang                                        MatSetOption_MPISELL,
965d4002b98SHong Zhang                                        MatZeroEntries_MPISELL,
966f4259b30SLisandro Dalcin                                        /*24*/ NULL,
967f4259b30SLisandro Dalcin                                        NULL,
968f4259b30SLisandro Dalcin                                        NULL,
969f4259b30SLisandro Dalcin                                        NULL,
970f4259b30SLisandro Dalcin                                        NULL,
971d4002b98SHong Zhang                                        /*29*/ MatSetUp_MPISELL,
972f4259b30SLisandro Dalcin                                        NULL,
973f4259b30SLisandro Dalcin                                        NULL,
974d4002b98SHong Zhang                                        MatGetDiagonalBlock_MPISELL,
975f4259b30SLisandro Dalcin                                        NULL,
976d4002b98SHong Zhang                                        /*34*/ MatDuplicate_MPISELL,
977f4259b30SLisandro Dalcin                                        NULL,
978f4259b30SLisandro Dalcin                                        NULL,
979f4259b30SLisandro Dalcin                                        NULL,
980f4259b30SLisandro Dalcin                                        NULL,
981f4259b30SLisandro Dalcin                                        /*39*/ NULL,
982f4259b30SLisandro Dalcin                                        NULL,
983f4259b30SLisandro Dalcin                                        NULL,
984d4002b98SHong Zhang                                        MatGetValues_MPISELL,
985d4002b98SHong Zhang                                        MatCopy_MPISELL,
986f4259b30SLisandro Dalcin                                        /*44*/ NULL,
987d4002b98SHong Zhang                                        MatScale_MPISELL,
988d4002b98SHong Zhang                                        MatShift_MPISELL,
989d4002b98SHong Zhang                                        MatDiagonalSet_MPISELL,
990f4259b30SLisandro Dalcin                                        NULL,
991d4002b98SHong Zhang                                        /*49*/ MatSetRandom_MPISELL,
992f4259b30SLisandro Dalcin                                        NULL,
993f4259b30SLisandro Dalcin                                        NULL,
994f4259b30SLisandro Dalcin                                        NULL,
995f4259b30SLisandro Dalcin                                        NULL,
996d4002b98SHong Zhang                                        /*54*/ MatFDColoringCreate_MPIXAIJ,
997f4259b30SLisandro Dalcin                                        NULL,
998d4002b98SHong Zhang                                        MatSetUnfactored_MPISELL,
999f4259b30SLisandro Dalcin                                        NULL,
1000f4259b30SLisandro Dalcin                                        NULL,
1001f4259b30SLisandro Dalcin                                        /*59*/ NULL,
1002d4002b98SHong Zhang                                        MatDestroy_MPISELL,
1003d4002b98SHong Zhang                                        MatView_MPISELL,
1004f4259b30SLisandro Dalcin                                        NULL,
1005f4259b30SLisandro Dalcin                                        NULL,
1006f4259b30SLisandro Dalcin                                        /*64*/ NULL,
1007f4259b30SLisandro Dalcin                                        NULL,
1008f4259b30SLisandro Dalcin                                        NULL,
1009f4259b30SLisandro Dalcin                                        NULL,
1010f4259b30SLisandro Dalcin                                        NULL,
1011f4259b30SLisandro Dalcin                                        /*69*/ NULL,
1012f4259b30SLisandro Dalcin                                        NULL,
1013f4259b30SLisandro Dalcin                                        NULL,
1014f4259b30SLisandro Dalcin                                        NULL,
1015f4259b30SLisandro Dalcin                                        NULL,
1016f4259b30SLisandro Dalcin                                        NULL,
1017d4002b98SHong Zhang                                        /*75*/ MatFDColoringApply_AIJ, /* reuse AIJ function */
1018d4002b98SHong Zhang                                        MatSetFromOptions_MPISELL,
1019f4259b30SLisandro Dalcin                                        NULL,
1020f4259b30SLisandro Dalcin                                        NULL,
1021f4259b30SLisandro Dalcin                                        NULL,
1022f4259b30SLisandro Dalcin                                        /*80*/ NULL,
1023f4259b30SLisandro Dalcin                                        NULL,
1024f4259b30SLisandro Dalcin                                        NULL,
1025f4259b30SLisandro Dalcin                                        /*83*/ NULL,
1026f4259b30SLisandro Dalcin                                        NULL,
1027f4259b30SLisandro Dalcin                                        NULL,
1028f4259b30SLisandro Dalcin                                        NULL,
1029f4259b30SLisandro Dalcin                                        NULL,
1030f4259b30SLisandro Dalcin                                        NULL,
1031f4259b30SLisandro Dalcin                                        /*89*/ NULL,
1032f4259b30SLisandro Dalcin                                        NULL,
1033f4259b30SLisandro Dalcin                                        NULL,
1034f4259b30SLisandro Dalcin                                        NULL,
1035f4259b30SLisandro Dalcin                                        NULL,
1036f4259b30SLisandro Dalcin                                        /*94*/ NULL,
1037f4259b30SLisandro Dalcin                                        NULL,
1038f4259b30SLisandro Dalcin                                        NULL,
1039f4259b30SLisandro Dalcin                                        NULL,
1040f4259b30SLisandro Dalcin                                        NULL,
1041f4259b30SLisandro Dalcin                                        /*99*/ NULL,
1042f4259b30SLisandro Dalcin                                        NULL,
1043f4259b30SLisandro Dalcin                                        NULL,
1044d4002b98SHong Zhang                                        MatConjugate_MPISELL,
1045f4259b30SLisandro Dalcin                                        NULL,
1046f4259b30SLisandro Dalcin                                        /*104*/ NULL,
1047d4002b98SHong Zhang                                        MatRealPart_MPISELL,
1048d4002b98SHong Zhang                                        MatImaginaryPart_MPISELL,
1049f4259b30SLisandro Dalcin                                        NULL,
1050f4259b30SLisandro Dalcin                                        NULL,
1051f4259b30SLisandro Dalcin                                        /*109*/ NULL,
1052f4259b30SLisandro Dalcin                                        NULL,
1053f4259b30SLisandro Dalcin                                        NULL,
1054f4259b30SLisandro Dalcin                                        NULL,
1055d4002b98SHong Zhang                                        MatMissingDiagonal_MPISELL,
1056f4259b30SLisandro Dalcin                                        /*114*/ NULL,
1057f4259b30SLisandro Dalcin                                        NULL,
1058d4002b98SHong Zhang                                        MatGetGhosts_MPISELL,
1059f4259b30SLisandro Dalcin                                        NULL,
1060f4259b30SLisandro Dalcin                                        NULL,
1061f4259b30SLisandro Dalcin                                        /*119*/ NULL,
1062f4259b30SLisandro Dalcin                                        NULL,
1063f4259b30SLisandro Dalcin                                        NULL,
1064f4259b30SLisandro Dalcin                                        NULL,
1065f4259b30SLisandro Dalcin                                        NULL,
1066f4259b30SLisandro Dalcin                                        /*124*/ NULL,
1067f4259b30SLisandro Dalcin                                        NULL,
1068d4002b98SHong Zhang                                        MatInvertBlockDiagonal_MPISELL,
1069f4259b30SLisandro Dalcin                                        NULL,
1070f4259b30SLisandro Dalcin                                        NULL,
1071f4259b30SLisandro Dalcin                                        /*129*/ NULL,
1072f4259b30SLisandro Dalcin                                        NULL,
1073f4259b30SLisandro Dalcin                                        NULL,
1074f4259b30SLisandro Dalcin                                        NULL,
1075f4259b30SLisandro Dalcin                                        NULL,
1076f4259b30SLisandro Dalcin                                        /*134*/ NULL,
1077f4259b30SLisandro Dalcin                                        NULL,
1078f4259b30SLisandro Dalcin                                        NULL,
1079f4259b30SLisandro Dalcin                                        NULL,
1080f4259b30SLisandro Dalcin                                        NULL,
1081f4259b30SLisandro Dalcin                                        /*139*/ NULL,
1082f4259b30SLisandro Dalcin                                        NULL,
1083f4259b30SLisandro Dalcin                                        NULL,
1084d4002b98SHong Zhang                                        MatFDColoringSetUp_MPIXAIJ,
1085f4259b30SLisandro Dalcin                                        NULL,
1086d70f29a3SPierre Jolivet                                        /*144*/ NULL,
1087d70f29a3SPierre Jolivet                                        NULL,
1088d70f29a3SPierre Jolivet                                        NULL,
108999a7f59eSMark Adams                                        NULL,
109099a7f59eSMark Adams                                        NULL,
10917fb60732SBarry Smith                                        NULL,
10929371c9d4SSatish Balay                                        /*150*/ NULL};
1093d4002b98SHong Zhang 
1094d4002b98SHong Zhang /* ----------------------------------------------------------------------------------------*/
1095d4002b98SHong Zhang 
10969371c9d4SSatish Balay PetscErrorCode MatStoreValues_MPISELL(Mat mat) {
1097d4002b98SHong Zhang   Mat_MPISELL *sell = (Mat_MPISELL *)mat->data;
1098d4002b98SHong Zhang 
1099d4002b98SHong Zhang   PetscFunctionBegin;
11009566063dSJacob Faibussowitsch   PetscCall(MatStoreValues(sell->A));
11019566063dSJacob Faibussowitsch   PetscCall(MatStoreValues(sell->B));
1102d4002b98SHong Zhang   PetscFunctionReturn(0);
1103d4002b98SHong Zhang }
1104d4002b98SHong Zhang 
11059371c9d4SSatish Balay PetscErrorCode MatRetrieveValues_MPISELL(Mat mat) {
1106d4002b98SHong Zhang   Mat_MPISELL *sell = (Mat_MPISELL *)mat->data;
1107d4002b98SHong Zhang 
1108d4002b98SHong Zhang   PetscFunctionBegin;
11099566063dSJacob Faibussowitsch   PetscCall(MatRetrieveValues(sell->A));
11109566063dSJacob Faibussowitsch   PetscCall(MatRetrieveValues(sell->B));
1111d4002b98SHong Zhang   PetscFunctionReturn(0);
1112d4002b98SHong Zhang }
1113d4002b98SHong Zhang 
11149371c9d4SSatish Balay PetscErrorCode MatMPISELLSetPreallocation_MPISELL(Mat B, PetscInt d_rlenmax, const PetscInt d_rlen[], PetscInt o_rlenmax, const PetscInt o_rlen[]) {
1115d4002b98SHong Zhang   Mat_MPISELL *b;
1116d4002b98SHong Zhang 
1117d4002b98SHong Zhang   PetscFunctionBegin;
11189566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->rmap));
11199566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->cmap));
1120d4002b98SHong Zhang   b = (Mat_MPISELL *)B->data;
1121d4002b98SHong Zhang 
1122d4002b98SHong Zhang   if (!B->preallocated) {
1123d4002b98SHong Zhang     /* Explicitly create 2 MATSEQSELL matrices. */
11249566063dSJacob Faibussowitsch     PetscCall(MatCreate(PETSC_COMM_SELF, &b->A));
11259566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(b->A, B->rmap->n, B->cmap->n, B->rmap->n, B->cmap->n));
11269566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSizesFromMats(b->A, B, B));
11279566063dSJacob Faibussowitsch     PetscCall(MatSetType(b->A, MATSEQSELL));
11289566063dSJacob Faibussowitsch     PetscCall(MatCreate(PETSC_COMM_SELF, &b->B));
11299566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(b->B, B->rmap->n, B->cmap->N, B->rmap->n, B->cmap->N));
11309566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSizesFromMats(b->B, B, B));
11319566063dSJacob Faibussowitsch     PetscCall(MatSetType(b->B, MATSEQSELL));
1132d4002b98SHong Zhang   }
1133d4002b98SHong Zhang 
11349566063dSJacob Faibussowitsch   PetscCall(MatSeqSELLSetPreallocation(b->A, d_rlenmax, d_rlen));
11359566063dSJacob Faibussowitsch   PetscCall(MatSeqSELLSetPreallocation(b->B, o_rlenmax, o_rlen));
1136d4002b98SHong Zhang   B->preallocated  = PETSC_TRUE;
1137d4002b98SHong Zhang   B->was_assembled = PETSC_FALSE;
1138d4002b98SHong Zhang   /*
1139d4002b98SHong Zhang     critical for MatAssemblyEnd to work.
1140d4002b98SHong Zhang     MatAssemblyBegin checks it to set up was_assembled
1141d4002b98SHong Zhang     and MatAssemblyEnd checks was_assembled to determine whether to build garray
1142d4002b98SHong Zhang   */
1143d4002b98SHong Zhang   B->assembled     = PETSC_FALSE;
1144d4002b98SHong Zhang   PetscFunctionReturn(0);
1145d4002b98SHong Zhang }
1146d4002b98SHong Zhang 
11479371c9d4SSatish Balay PetscErrorCode MatDuplicate_MPISELL(Mat matin, MatDuplicateOption cpvalues, Mat *newmat) {
1148d4002b98SHong Zhang   Mat          mat;
1149d4002b98SHong Zhang   Mat_MPISELL *a, *oldmat = (Mat_MPISELL *)matin->data;
1150d4002b98SHong Zhang 
1151d4002b98SHong Zhang   PetscFunctionBegin;
1152f4259b30SLisandro Dalcin   *newmat = NULL;
11539566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)matin), &mat));
11549566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(mat, matin->rmap->n, matin->cmap->n, matin->rmap->N, matin->cmap->N));
11559566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSizesFromMats(mat, matin, matin));
11569566063dSJacob Faibussowitsch   PetscCall(MatSetType(mat, ((PetscObject)matin)->type_name));
1157d4002b98SHong Zhang   a = (Mat_MPISELL *)mat->data;
1158d4002b98SHong Zhang 
1159d4002b98SHong Zhang   mat->factortype   = matin->factortype;
1160d4002b98SHong Zhang   mat->assembled    = PETSC_TRUE;
1161d4002b98SHong Zhang   mat->insertmode   = NOT_SET_VALUES;
1162d4002b98SHong Zhang   mat->preallocated = PETSC_TRUE;
1163d4002b98SHong Zhang 
1164d4002b98SHong Zhang   a->size         = oldmat->size;
1165d4002b98SHong Zhang   a->rank         = oldmat->rank;
1166d4002b98SHong Zhang   a->donotstash   = oldmat->donotstash;
1167d4002b98SHong Zhang   a->roworiented  = oldmat->roworiented;
1168f4259b30SLisandro Dalcin   a->rowindices   = NULL;
1169f4259b30SLisandro Dalcin   a->rowvalues    = NULL;
1170d4002b98SHong Zhang   a->getrowactive = PETSC_FALSE;
1171d4002b98SHong Zhang 
11729566063dSJacob Faibussowitsch   PetscCall(PetscLayoutReference(matin->rmap, &mat->rmap));
11739566063dSJacob Faibussowitsch   PetscCall(PetscLayoutReference(matin->cmap, &mat->cmap));
1174d4002b98SHong Zhang 
1175d4002b98SHong Zhang   if (oldmat->colmap) {
1176d4002b98SHong Zhang #if defined(PETSC_USE_CTABLE)
11779566063dSJacob Faibussowitsch     PetscCall(PetscTableCreateCopy(oldmat->colmap, &a->colmap));
1178d4002b98SHong Zhang #else
11799566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(mat->cmap->N, &a->colmap));
11809566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(a->colmap, oldmat->colmap, mat->cmap->N));
1181d4002b98SHong Zhang #endif
1182f4259b30SLisandro Dalcin   } else a->colmap = NULL;
1183d4002b98SHong Zhang   if (oldmat->garray) {
1184d4002b98SHong Zhang     PetscInt len;
1185d4002b98SHong Zhang     len = oldmat->B->cmap->n;
11869566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(len + 1, &a->garray));
11879566063dSJacob Faibussowitsch     if (len) PetscCall(PetscArraycpy(a->garray, oldmat->garray, len));
1188f4259b30SLisandro Dalcin   } else a->garray = NULL;
1189d4002b98SHong Zhang 
11909566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(oldmat->lvec, &a->lvec));
11919566063dSJacob Faibussowitsch   PetscCall(VecScatterCopy(oldmat->Mvctx, &a->Mvctx));
11929566063dSJacob Faibussowitsch   PetscCall(MatDuplicate(oldmat->A, cpvalues, &a->A));
11939566063dSJacob Faibussowitsch   PetscCall(MatDuplicate(oldmat->B, cpvalues, &a->B));
11949566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListDuplicate(((PetscObject)matin)->qlist, &((PetscObject)mat)->qlist));
1195d4002b98SHong Zhang   *newmat = mat;
1196d4002b98SHong Zhang   PetscFunctionReturn(0);
1197d4002b98SHong Zhang }
1198d4002b98SHong Zhang 
1199d4002b98SHong Zhang /*@C
120011a5261eSBarry Smith    MatMPISELLSetPreallocation - Preallocates memory for a `MATMPISELL` sparse parallel matrix in sell format.
1201d4002b98SHong Zhang    For good matrix assembly performance the user should preallocate the matrix storage by
1202d4002b98SHong Zhang    setting the parameters d_nz (or d_nnz) and o_nz (or o_nnz).
1203d4002b98SHong Zhang 
1204d083f849SBarry Smith    Collective
1205d4002b98SHong Zhang 
1206d4002b98SHong Zhang    Input Parameters:
1207d4002b98SHong Zhang +  B - the matrix
1208d4002b98SHong Zhang .  d_nz  - number of nonzeros per row in DIAGONAL portion of local submatrix
1209d4002b98SHong Zhang            (same value is used for all local rows)
1210d4002b98SHong Zhang .  d_nnz - array containing the number of nonzeros in the various rows of the
1211d4002b98SHong Zhang            DIAGONAL portion of the local submatrix (possibly different for each row)
121211a5261eSBarry Smith            or NULL (`PETSC_NULL_INTEGER` in Fortran), if d_nz is used to specify the nonzero structure.
1213d4002b98SHong Zhang            The size of this array is equal to the number of local rows, i.e 'm'.
1214d4002b98SHong Zhang            For matrices that will be factored, you must leave room for (and set)
1215d4002b98SHong Zhang            the diagonal entry even if it is zero.
1216d4002b98SHong Zhang .  o_nz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
1217d4002b98SHong Zhang            submatrix (same value is used for all local rows).
1218d4002b98SHong Zhang -  o_nnz - array containing the number of nonzeros in the various rows of the
1219d4002b98SHong Zhang            OFF-DIAGONAL portion of the local submatrix (possibly different for
122011a5261eSBarry Smith            each row) or NULL (`PETSC_NULL_INTEGER` in Fortran), if o_nz is used to specify the nonzero
1221d4002b98SHong Zhang            structure. The size of this array is equal to the number
1222d4002b98SHong Zhang            of local rows, i.e 'm'.
1223d4002b98SHong Zhang 
1224d4002b98SHong Zhang    If the *_nnz parameter is given then the *_nz parameter is ignored
1225d4002b98SHong Zhang 
1226d4002b98SHong Zhang    The stored row and column indices begin with zero.
1227d4002b98SHong Zhang 
1228d4002b98SHong Zhang    The parallel matrix is partitioned such that the first m0 rows belong to
1229d4002b98SHong Zhang    process 0, the next m1 rows belong to process 1, the next m2 rows belong
1230d4002b98SHong Zhang    to process 2 etc.. where m0,m1,m2... are the input parameter 'm'.
1231d4002b98SHong Zhang 
1232d4002b98SHong Zhang    The DIAGONAL portion of the local submatrix of a processor can be defined
1233d4002b98SHong Zhang    as the submatrix which is obtained by extraction the part corresponding to
1234d4002b98SHong Zhang    the rows r1-r2 and columns c1-c2 of the global matrix, where r1 is the
1235d4002b98SHong Zhang    first row that belongs to the processor, r2 is the last row belonging to
1236d4002b98SHong Zhang    the this processor, and c1-c2 is range of indices of the local part of a
1237d4002b98SHong Zhang    vector suitable for applying the matrix to.  This is an mxn matrix.  In the
1238d4002b98SHong Zhang    common case of a square matrix, the row and column ranges are the same and
1239d4002b98SHong Zhang    the DIAGONAL part is also square. The remaining portion of the local
1240d4002b98SHong Zhang    submatrix (mxN) constitute the OFF-DIAGONAL portion.
1241d4002b98SHong Zhang 
1242d4002b98SHong Zhang    If o_nnz, d_nnz are specified, then o_nz, and d_nz are ignored.
1243d4002b98SHong Zhang 
124411a5261eSBarry Smith    You can call `MatGetInfo()` to get information on how effective the preallocation was;
1245d4002b98SHong Zhang    for example the fields mallocs,nz_allocated,nz_used,nz_unneeded;
1246d4002b98SHong Zhang    You can also run with the option -info and look for messages with the string
1247d4002b98SHong Zhang    malloc in them to see if additional memory allocation was needed.
1248d4002b98SHong Zhang 
1249d4002b98SHong Zhang    Example usage:
1250d4002b98SHong Zhang 
1251d4002b98SHong Zhang    Consider the following 8x8 matrix with 34 non-zero values, that is
1252d4002b98SHong Zhang    assembled across 3 processors. Lets assume that proc0 owns 3 rows,
1253d4002b98SHong Zhang    proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
1254d4002b98SHong Zhang    as follows:
1255d4002b98SHong Zhang 
1256d4002b98SHong Zhang .vb
1257d4002b98SHong Zhang             1  2  0  |  0  3  0  |  0  4
1258d4002b98SHong Zhang     Proc0   0  5  6  |  7  0  0  |  8  0
1259d4002b98SHong Zhang             9  0 10  | 11  0  0  | 12  0
1260d4002b98SHong Zhang     -------------------------------------
1261d4002b98SHong Zhang            13  0 14  | 15 16 17  |  0  0
1262d4002b98SHong Zhang     Proc1   0 18  0  | 19 20 21  |  0  0
1263d4002b98SHong Zhang             0  0  0  | 22 23  0  | 24  0
1264d4002b98SHong Zhang     -------------------------------------
1265d4002b98SHong Zhang     Proc2  25 26 27  |  0  0 28  | 29  0
1266d4002b98SHong Zhang            30  0  0  | 31 32 33  |  0 34
1267d4002b98SHong Zhang .ve
1268d4002b98SHong Zhang 
1269d4002b98SHong Zhang    This can be represented as a collection of submatrices as:
1270d4002b98SHong Zhang 
1271d4002b98SHong Zhang .vb
1272d4002b98SHong Zhang       A B C
1273d4002b98SHong Zhang       D E F
1274d4002b98SHong Zhang       G H I
1275d4002b98SHong Zhang .ve
1276d4002b98SHong Zhang 
1277d4002b98SHong Zhang    Where the submatrices A,B,C are owned by proc0, D,E,F are
1278d4002b98SHong Zhang    owned by proc1, G,H,I are owned by proc2.
1279d4002b98SHong Zhang 
1280d4002b98SHong Zhang    The 'm' parameters for proc0,proc1,proc2 are 3,3,2 respectively.
1281d4002b98SHong Zhang    The 'n' parameters for proc0,proc1,proc2 are 3,3,2 respectively.
1282d4002b98SHong Zhang    The 'M','N' parameters are 8,8, and have the same values on all procs.
1283d4002b98SHong Zhang 
1284d4002b98SHong Zhang    The DIAGONAL submatrices corresponding to proc0,proc1,proc2 are
1285d4002b98SHong Zhang    submatrices [A], [E], [I] respectively. The OFF-DIAGONAL submatrices
1286d4002b98SHong Zhang    corresponding to proc0,proc1,proc2 are [BC], [DF], [GH] respectively.
1287d4002b98SHong Zhang    Internally, each processor stores the DIAGONAL part, and the OFF-DIAGONAL
1288d4002b98SHong Zhang    part as SeqSELL matrices. for eg: proc1 will store [E] as a SeqSELL
1289d4002b98SHong Zhang    matrix, ans [DF] as another SeqSELL matrix.
1290d4002b98SHong Zhang 
1291d4002b98SHong Zhang    When d_nz, o_nz parameters are specified, d_nz storage elements are
1292d4002b98SHong Zhang    allocated for every row of the local diagonal submatrix, and o_nz
1293d4002b98SHong Zhang    storage locations are allocated for every row of the OFF-DIAGONAL submat.
1294d4002b98SHong Zhang    One way to choose d_nz and o_nz is to use the max nonzerors per local
1295d4002b98SHong Zhang    rows for each of the local DIAGONAL, and the OFF-DIAGONAL submatrices.
1296d4002b98SHong Zhang    In this case, the values of d_nz,o_nz are:
1297d4002b98SHong Zhang .vb
1298d4002b98SHong Zhang      proc0 : dnz = 2, o_nz = 2
1299d4002b98SHong Zhang      proc1 : dnz = 3, o_nz = 2
1300d4002b98SHong Zhang      proc2 : dnz = 1, o_nz = 4
1301d4002b98SHong Zhang .ve
1302d4002b98SHong Zhang    We are allocating m*(d_nz+o_nz) storage locations for every proc. This
1303d4002b98SHong Zhang    translates to 3*(2+2)=12 for proc0, 3*(3+2)=15 for proc1, 2*(1+4)=10
1304d4002b98SHong Zhang    for proc3. i.e we are using 12+15+10=37 storage locations to store
1305d4002b98SHong Zhang    34 values.
1306d4002b98SHong Zhang 
1307d4002b98SHong Zhang    When d_nnz, o_nnz parameters are specified, the storage is specified
1308a5b23f4aSJose E. Roman    for every row, corresponding to both DIAGONAL and OFF-DIAGONAL submatrices.
1309d4002b98SHong Zhang    In the above case the values for d_nnz,o_nnz are:
1310d4002b98SHong Zhang .vb
1311d4002b98SHong Zhang      proc0: d_nnz = [2,2,2] and o_nnz = [2,2,2]
1312d4002b98SHong Zhang      proc1: d_nnz = [3,3,2] and o_nnz = [2,1,1]
1313d4002b98SHong Zhang      proc2: d_nnz = [1,1]   and o_nnz = [4,4]
1314d4002b98SHong Zhang .ve
1315d4002b98SHong Zhang    Here the space allocated is according to nz (or maximum values in the nnz
1316d4002b98SHong Zhang    if nnz is provided) for DIAGONAL and OFF-DIAGONAL submatrices, i.e (2+2+3+2)*3+(1+4)*2=37
1317d4002b98SHong Zhang 
1318d4002b98SHong Zhang    Level: intermediate
1319d4002b98SHong Zhang 
1320db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateSeqSELL()`, `MatSetValues()`, `MatCreatesell()`,
132111a5261eSBarry Smith           `MATMPISELL`, `MatGetInfo()`, `PetscSplitOwnership()`, `MATSELL`
1322d4002b98SHong Zhang @*/
13239371c9d4SSatish Balay PetscErrorCode MatMPISELLSetPreallocation(Mat B, PetscInt d_nz, const PetscInt d_nnz[], PetscInt o_nz, const PetscInt o_nnz[]) {
1324d4002b98SHong Zhang   PetscFunctionBegin;
1325d4002b98SHong Zhang   PetscValidHeaderSpecific(B, MAT_CLASSID, 1);
1326d4002b98SHong Zhang   PetscValidType(B, 1);
1327cac4c232SBarry Smith   PetscTryMethod(B, "MatMPISELLSetPreallocation_C", (Mat, PetscInt, const PetscInt[], PetscInt, const PetscInt[]), (B, d_nz, d_nnz, o_nz, o_nnz));
1328d4002b98SHong Zhang   PetscFunctionReturn(0);
1329d4002b98SHong Zhang }
1330d4002b98SHong Zhang 
1331ed73aabaSBarry Smith /*MC
1332ed73aabaSBarry Smith    MATMPISELL - MATMPISELL = "mpisell" - A matrix type to be used for MPI sparse matrices,
1333ed73aabaSBarry Smith    based on the sliced Ellpack format
1334ed73aabaSBarry Smith 
1335ed73aabaSBarry Smith    Options Database Keys:
1336ed73aabaSBarry Smith . -mat_type sell - sets the matrix type to "seqsell" during a call to MatSetFromOptions()
1337ed73aabaSBarry Smith 
1338ed73aabaSBarry Smith    Level: beginner
1339ed73aabaSBarry Smith 
1340db781477SPatrick Sanan .seealso: `MatCreateSell()`, `MATSEQSELL`, `MATSELL`, `MATSEQAIJ`, `MATAIJ`, `MATMPIAIJ`
1341ed73aabaSBarry Smith M*/
1342ed73aabaSBarry Smith 
1343d4002b98SHong Zhang /*@C
134411a5261eSBarry Smith    MatCreateSELL - Creates a sparse parallel matrix in `MATSELL` format.
1345d4002b98SHong Zhang 
1346d083f849SBarry Smith    Collective
1347d4002b98SHong Zhang 
1348d4002b98SHong Zhang    Input Parameters:
1349d4002b98SHong Zhang +  comm - MPI communicator
135011a5261eSBarry Smith .  m - number of local rows (or `PETSC_DECIDE` to have calculated if M is given)
1351d4002b98SHong Zhang            This value should be the same as the local size used in creating the
1352d4002b98SHong Zhang            y vector for the matrix-vector product y = Ax.
1353d4002b98SHong Zhang .  n - This value should be the same as the local size used in creating the
1354d4002b98SHong Zhang        x vector for the matrix-vector product y = Ax. (or PETSC_DECIDE to have
1355d4002b98SHong Zhang        calculated if N is given) For square matrices n is almost always m.
135611a5261eSBarry Smith .  M - number of global rows (or `PETSC_DETERMINE` to have calculated if m is given)
135711a5261eSBarry Smith .  N - number of global columns (or `PETSC_DETERMINE` to have calculated if n is given)
1358d4002b98SHong Zhang .  d_rlenmax - max number of nonzeros per row in DIAGONAL portion of local submatrix
1359d4002b98SHong Zhang                (same value is used for all local rows)
1360d4002b98SHong Zhang .  d_rlen - array containing the number of nonzeros in the various rows of the
1361d4002b98SHong Zhang             DIAGONAL portion of the local submatrix (possibly different for each row)
1362d4002b98SHong Zhang             or NULL, if d_rlenmax is used to specify the nonzero structure.
1363d4002b98SHong Zhang             The size of this array is equal to the number of local rows, i.e 'm'.
1364d4002b98SHong Zhang .  o_rlenmax - max number of nonzeros per row in the OFF-DIAGONAL portion of local
1365d4002b98SHong Zhang                submatrix (same value is used for all local rows).
1366d4002b98SHong Zhang -  o_rlen - array containing the number of nonzeros in the various rows of the
1367d4002b98SHong Zhang             OFF-DIAGONAL portion of the local submatrix (possibly different for
1368d4002b98SHong Zhang             each row) or NULL, if o_rlenmax is used to specify the nonzero
1369d4002b98SHong Zhang             structure. The size of this array is equal to the number
1370d4002b98SHong Zhang             of local rows, i.e 'm'.
1371d4002b98SHong Zhang 
1372d4002b98SHong Zhang    Output Parameter:
1373d4002b98SHong Zhang .  A - the matrix
1374d4002b98SHong Zhang 
137511a5261eSBarry Smith    It is recommended that one use the `MatCreate()`, `MatSetType()` and/or `MatSetFromOptions()`,
1376f6f02116SRichard Tran Mills    MatXXXXSetPreallocation() paradigm instead of this routine directly.
137711a5261eSBarry Smith    [MatXXXXSetPreallocation() is, for example, `MatSeqSELLSetPreallocation()`]
1378d4002b98SHong Zhang 
1379d4002b98SHong Zhang    Notes:
1380d4002b98SHong Zhang    If the *_rlen parameter is given then the *_rlenmax parameter is ignored
1381d4002b98SHong Zhang 
1382d4002b98SHong Zhang    m,n,M,N parameters specify the size of the matrix, and its partitioning across
1383d4002b98SHong Zhang    processors, while d_rlenmax,d_rlen,o_rlenmax,o_rlen parameters specify the approximate
1384d4002b98SHong Zhang    storage requirements for this matrix.
1385d4002b98SHong Zhang 
138611a5261eSBarry Smith    If `PETSC_DECIDE` or  `PETSC_DETERMINE` is used for a particular argument on one
1387d4002b98SHong Zhang    processor than it must be used on all processors that share the object for
1388d4002b98SHong Zhang    that argument.
1389d4002b98SHong Zhang 
1390d4002b98SHong Zhang    The user MUST specify either the local or global matrix dimensions
1391d4002b98SHong Zhang    (possibly both).
1392d4002b98SHong Zhang 
1393d4002b98SHong Zhang    The parallel matrix is partitioned across processors such that the
1394d4002b98SHong Zhang    first m0 rows belong to process 0, the next m1 rows belong to
1395d4002b98SHong Zhang    process 1, the next m2 rows belong to process 2 etc.. where
1396d4002b98SHong Zhang    m0,m1,m2,.. are the input parameter 'm'. i.e each processor stores
1397d4002b98SHong Zhang    values corresponding to [m x N] submatrix.
1398d4002b98SHong Zhang 
1399d4002b98SHong Zhang    The columns are logically partitioned with the n0 columns belonging
1400d4002b98SHong Zhang    to 0th partition, the next n1 columns belonging to the next
1401d4002b98SHong Zhang    partition etc.. where n0,n1,n2... are the input parameter 'n'.
1402d4002b98SHong Zhang 
1403d4002b98SHong Zhang    The DIAGONAL portion of the local submatrix on any given processor
1404d4002b98SHong Zhang    is the submatrix corresponding to the rows and columns m,n
1405d4002b98SHong Zhang    corresponding to the given processor. i.e diagonal matrix on
1406d4002b98SHong Zhang    process 0 is [m0 x n0], diagonal matrix on process 1 is [m1 x n1]
1407d4002b98SHong Zhang    etc. The remaining portion of the local submatrix [m x (N-n)]
1408d4002b98SHong Zhang    constitute the OFF-DIAGONAL portion. The example below better
1409d4002b98SHong Zhang    illustrates this concept.
1410d4002b98SHong Zhang 
1411d4002b98SHong Zhang    For a square global matrix we define each processor's diagonal portion
1412d4002b98SHong Zhang    to be its local rows and the corresponding columns (a square submatrix);
1413d4002b98SHong Zhang    each processor's off-diagonal portion encompasses the remainder of the
1414d4002b98SHong Zhang    local matrix (a rectangular submatrix).
1415d4002b98SHong Zhang 
1416d4002b98SHong Zhang    If o_rlen, d_rlen are specified, then o_rlenmax, and d_rlenmax are ignored.
1417d4002b98SHong Zhang 
1418d4002b98SHong Zhang    When calling this routine with a single process communicator, a matrix of
141911a5261eSBarry Smith    type `MATSEQSELL` is returned.  If a matrix of type `MATMPISELL` is desired for this
1420d4002b98SHong Zhang    type of communicator, use the construction mechanism:
142111a5261eSBarry Smith      `MatCreate`(...,&A); `MatSetType`(A,`MATMPISELL`); `MatSetSizes`(A, m,n,M,N); `MatMPISELLSetPreallocation`(A,...);
1422d4002b98SHong Zhang 
1423d4002b98SHong Zhang    Options Database Keys:
1424d4002b98SHong Zhang -  -mat_sell_oneindex - Internally use indexing starting at 1
1425d4002b98SHong Zhang         rather than 0.  Note that when calling MatSetValues(),
1426d4002b98SHong Zhang         the user still MUST index entries starting at 0!
1427d4002b98SHong Zhang 
1428d4002b98SHong Zhang    Example usage:
1429d4002b98SHong Zhang 
1430d4002b98SHong Zhang    Consider the following 8x8 matrix with 34 non-zero values, that is
1431d4002b98SHong Zhang    assembled across 3 processors. Lets assume that proc0 owns 3 rows,
1432d4002b98SHong Zhang    proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
1433d4002b98SHong Zhang    as follows:
1434d4002b98SHong Zhang 
1435d4002b98SHong Zhang .vb
1436d4002b98SHong Zhang             1  2  0  |  0  3  0  |  0  4
1437d4002b98SHong Zhang     Proc0   0  5  6  |  7  0  0  |  8  0
1438d4002b98SHong Zhang             9  0 10  | 11  0  0  | 12  0
1439d4002b98SHong Zhang     -------------------------------------
1440d4002b98SHong Zhang            13  0 14  | 15 16 17  |  0  0
1441d4002b98SHong Zhang     Proc1   0 18  0  | 19 20 21  |  0  0
1442d4002b98SHong Zhang             0  0  0  | 22 23  0  | 24  0
1443d4002b98SHong Zhang     -------------------------------------
1444d4002b98SHong Zhang     Proc2  25 26 27  |  0  0 28  | 29  0
1445d4002b98SHong Zhang            30  0  0  | 31 32 33  |  0 34
1446d4002b98SHong Zhang .ve
1447d4002b98SHong Zhang 
1448d4002b98SHong Zhang    This can be represented as a collection of submatrices as:
1449d4002b98SHong Zhang 
1450d4002b98SHong Zhang .vb
1451d4002b98SHong Zhang       A B C
1452d4002b98SHong Zhang       D E F
1453d4002b98SHong Zhang       G H I
1454d4002b98SHong Zhang .ve
1455d4002b98SHong Zhang 
1456d4002b98SHong Zhang    Where the submatrices A,B,C are owned by proc0, D,E,F are
1457d4002b98SHong Zhang    owned by proc1, G,H,I are owned by proc2.
1458d4002b98SHong Zhang 
1459d4002b98SHong Zhang    The 'm' parameters for proc0,proc1,proc2 are 3,3,2 respectively.
1460d4002b98SHong Zhang    The 'n' parameters for proc0,proc1,proc2 are 3,3,2 respectively.
1461d4002b98SHong Zhang    The 'M','N' parameters are 8,8, and have the same values on all procs.
1462d4002b98SHong Zhang 
1463d4002b98SHong Zhang    The DIAGONAL submatrices corresponding to proc0,proc1,proc2 are
1464d4002b98SHong Zhang    submatrices [A], [E], [I] respectively. The OFF-DIAGONAL submatrices
1465d4002b98SHong Zhang    corresponding to proc0,proc1,proc2 are [BC], [DF], [GH] respectively.
1466d4002b98SHong Zhang    Internally, each processor stores the DIAGONAL part, and the OFF-DIAGONAL
146711a5261eSBarry Smith    part as `MATSSESELL` matrices. for eg: proc1 will store [E] as a `MATSEQSELL`
146811a5261eSBarry Smith    matrix, ans [DF] as another `MATSEQSELL` matrix.
1469d4002b98SHong Zhang 
1470d4002b98SHong Zhang    When d_rlenmax, o_rlenmax parameters are specified, d_rlenmax storage elements are
1471d4002b98SHong Zhang    allocated for every row of the local diagonal submatrix, and o_rlenmax
1472d4002b98SHong Zhang    storage locations are allocated for every row of the OFF-DIAGONAL submat.
1473d4002b98SHong Zhang    One way to choose d_rlenmax and o_rlenmax is to use the max nonzerors per local
1474d4002b98SHong Zhang    rows for each of the local DIAGONAL, and the OFF-DIAGONAL submatrices.
1475d4002b98SHong Zhang    In this case, the values of d_rlenmax,o_rlenmax are:
1476d4002b98SHong Zhang .vb
1477d4002b98SHong Zhang      proc0 : d_rlenmax = 2, o_rlenmax = 2
1478d4002b98SHong Zhang      proc1 : d_rlenmax = 3, o_rlenmax = 2
1479d4002b98SHong Zhang      proc2 : d_rlenmax = 1, o_rlenmax = 4
1480d4002b98SHong Zhang .ve
1481d4002b98SHong Zhang    We are allocating m*(d_rlenmax+o_rlenmax) storage locations for every proc. This
1482d4002b98SHong Zhang    translates to 3*(2+2)=12 for proc0, 3*(3+2)=15 for proc1, 2*(1+4)=10
1483d4002b98SHong Zhang    for proc3. i.e we are using 12+15+10=37 storage locations to store
1484d4002b98SHong Zhang    34 values.
1485d4002b98SHong Zhang 
1486d4002b98SHong Zhang    When d_rlen, o_rlen parameters are specified, the storage is specified
1487a5b23f4aSJose E. Roman    for every row, corresponding to both DIAGONAL and OFF-DIAGONAL submatrices.
1488d4002b98SHong Zhang    In the above case the values for d_nnz,o_nnz are:
1489d4002b98SHong Zhang .vb
1490d4002b98SHong Zhang      proc0: d_nnz = [2,2,2] and o_nnz = [2,2,2]
1491d4002b98SHong Zhang      proc1: d_nnz = [3,3,2] and o_nnz = [2,1,1]
1492d4002b98SHong Zhang      proc2: d_nnz = [1,1]   and o_nnz = [4,4]
1493d4002b98SHong Zhang .ve
1494d4002b98SHong Zhang    Here the space allocated is still 37 though there are 34 nonzeros because
1495d4002b98SHong Zhang    the allocation is always done according to rlenmax.
1496d4002b98SHong Zhang 
1497d4002b98SHong Zhang    Level: intermediate
1498d4002b98SHong Zhang 
149911a5261eSBarry Smith .seealso: `MATSELL`, `MatCreate()`, `MatCreateSeqSELL()`, `MatSetValues()`, `MatMPISELLSetPreallocation()`, `MatMPISELLSetPreallocationSELL()`,
1500db781477SPatrick Sanan           `MATMPISELL`, `MatCreateMPISELLWithArrays()`
1501d4002b98SHong Zhang @*/
15029371c9d4SSatish Balay PetscErrorCode MatCreateSELL(MPI_Comm comm, PetscInt m, PetscInt n, PetscInt M, PetscInt N, PetscInt d_rlenmax, const PetscInt d_rlen[], PetscInt o_rlenmax, const PetscInt o_rlen[], Mat *A) {
1503d4002b98SHong Zhang   PetscMPIInt size;
1504d4002b98SHong Zhang 
1505d4002b98SHong Zhang   PetscFunctionBegin;
15069566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, A));
15079566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*A, m, n, M, N));
15089566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
1509d4002b98SHong Zhang   if (size > 1) {
15109566063dSJacob Faibussowitsch     PetscCall(MatSetType(*A, MATMPISELL));
15119566063dSJacob Faibussowitsch     PetscCall(MatMPISELLSetPreallocation(*A, d_rlenmax, d_rlen, o_rlenmax, o_rlen));
1512d4002b98SHong Zhang   } else {
15139566063dSJacob Faibussowitsch     PetscCall(MatSetType(*A, MATSEQSELL));
15149566063dSJacob Faibussowitsch     PetscCall(MatSeqSELLSetPreallocation(*A, d_rlenmax, d_rlen));
1515d4002b98SHong Zhang   }
1516d4002b98SHong Zhang   PetscFunctionReturn(0);
1517d4002b98SHong Zhang }
1518d4002b98SHong Zhang 
15199371c9d4SSatish Balay PetscErrorCode MatMPISELLGetSeqSELL(Mat A, Mat *Ad, Mat *Ao, const PetscInt *colmap[]) {
1520d4002b98SHong Zhang   Mat_MPISELL *a = (Mat_MPISELL *)A->data;
1521d4002b98SHong Zhang   PetscBool    flg;
1522d4002b98SHong Zhang 
1523d4002b98SHong Zhang   PetscFunctionBegin;
15249566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMPISELL, &flg));
152528b400f6SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "This function requires a MATMPISELL matrix as input");
1526d4002b98SHong Zhang   if (Ad) *Ad = a->A;
1527d4002b98SHong Zhang   if (Ao) *Ao = a->B;
1528d4002b98SHong Zhang   if (colmap) *colmap = a->garray;
1529d4002b98SHong Zhang   PetscFunctionReturn(0);
1530d4002b98SHong Zhang }
1531d4002b98SHong Zhang 
1532d4002b98SHong Zhang /*@C
153311a5261eSBarry Smith      MatMPISELLGetLocalMatCondensed - Creates a `MATSEQSELL` matrix from an `MATMPISELL` matrix by taking all its local rows and NON-ZERO columns
1534d4002b98SHong Zhang 
1535d4002b98SHong Zhang     Not Collective
1536d4002b98SHong Zhang 
1537d4002b98SHong Zhang    Input Parameters:
1538d4002b98SHong Zhang +    A - the matrix
153911a5261eSBarry Smith .    scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
1540d4002b98SHong Zhang -    row, col - index sets of rows and columns to extract (or NULL)
1541d4002b98SHong Zhang 
1542d4002b98SHong Zhang    Output Parameter:
1543d4002b98SHong Zhang .    A_loc - the local sequential matrix generated
1544d4002b98SHong Zhang 
1545d4002b98SHong Zhang     Level: developer
1546d4002b98SHong Zhang 
154711a5261eSBarry Smith .seealso: `MATSEQSELL`, `MATMPISELL`, `MatGetOwnershipRange()`, `MatMPISELLGetLocalMat()`
1548d4002b98SHong Zhang @*/
15499371c9d4SSatish Balay PetscErrorCode MatMPISELLGetLocalMatCondensed(Mat A, MatReuse scall, IS *row, IS *col, Mat *A_loc) {
1550d4002b98SHong Zhang   Mat_MPISELL *a = (Mat_MPISELL *)A->data;
1551d4002b98SHong Zhang   PetscInt     i, start, end, ncols, nzA, nzB, *cmap, imark, *idx;
1552d4002b98SHong Zhang   IS           isrowa, iscola;
1553d4002b98SHong Zhang   Mat         *aloc;
1554d4002b98SHong Zhang   PetscBool    match;
1555d4002b98SHong Zhang 
1556d4002b98SHong Zhang   PetscFunctionBegin;
15579566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMPISELL, &match));
155828b400f6SJacob Faibussowitsch   PetscCheck(match, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Requires MATMPISELL matrix as input");
15599566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(MAT_Getlocalmatcondensed, A, 0, 0, 0));
1560d4002b98SHong Zhang   if (!row) {
15619371c9d4SSatish Balay     start = A->rmap->rstart;
15629371c9d4SSatish Balay     end   = A->rmap->rend;
15639566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_SELF, end - start, start, 1, &isrowa));
1564d4002b98SHong Zhang   } else {
1565d4002b98SHong Zhang     isrowa = *row;
1566d4002b98SHong Zhang   }
1567d4002b98SHong Zhang   if (!col) {
1568d4002b98SHong Zhang     start = A->cmap->rstart;
1569d4002b98SHong Zhang     cmap  = a->garray;
1570d4002b98SHong Zhang     nzA   = a->A->cmap->n;
1571d4002b98SHong Zhang     nzB   = a->B->cmap->n;
15729566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nzA + nzB, &idx));
1573d4002b98SHong Zhang     ncols = 0;
1574d4002b98SHong Zhang     for (i = 0; i < nzB; i++) {
1575d4002b98SHong Zhang       if (cmap[i] < start) idx[ncols++] = cmap[i];
1576d4002b98SHong Zhang       else break;
1577d4002b98SHong Zhang     }
1578d4002b98SHong Zhang     imark = i;
1579d4002b98SHong Zhang     for (i = 0; i < nzA; i++) idx[ncols++] = start + i;
1580d4002b98SHong Zhang     for (i = imark; i < nzB; i++) idx[ncols++] = cmap[i];
15819566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, ncols, idx, PETSC_OWN_POINTER, &iscola));
1582d4002b98SHong Zhang   } else {
1583d4002b98SHong Zhang     iscola = *col;
1584d4002b98SHong Zhang   }
1585d4002b98SHong Zhang   if (scall != MAT_INITIAL_MATRIX) {
15869566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(1, &aloc));
1587d4002b98SHong Zhang     aloc[0] = *A_loc;
1588d4002b98SHong Zhang   }
15899566063dSJacob Faibussowitsch   PetscCall(MatCreateSubMatrices(A, 1, &isrowa, &iscola, scall, &aloc));
1590d4002b98SHong Zhang   *A_loc = aloc[0];
15919566063dSJacob Faibussowitsch   PetscCall(PetscFree(aloc));
159248a46eb9SPierre Jolivet   if (!row) PetscCall(ISDestroy(&isrowa));
159348a46eb9SPierre Jolivet   if (!col) PetscCall(ISDestroy(&iscola));
15949566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(MAT_Getlocalmatcondensed, A, 0, 0, 0));
1595d4002b98SHong Zhang   PetscFunctionReturn(0);
1596d4002b98SHong Zhang }
1597d4002b98SHong Zhang 
1598d4002b98SHong Zhang #include <../src/mat/impls/aij/mpi/mpiaij.h>
1599d4002b98SHong Zhang 
16009371c9d4SSatish Balay PetscErrorCode MatConvert_MPISELL_MPIAIJ(Mat A, MatType newtype, MatReuse reuse, Mat *newmat) {
1601d4002b98SHong Zhang   Mat_MPISELL *a = (Mat_MPISELL *)A->data;
1602d4002b98SHong Zhang   Mat          B;
1603d4002b98SHong Zhang   Mat_MPIAIJ  *b;
1604d4002b98SHong Zhang 
1605d4002b98SHong Zhang   PetscFunctionBegin;
160628b400f6SJacob Faibussowitsch   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Matrix must be assembled");
1607d4002b98SHong Zhang 
160894a8b381SRichard Tran Mills   if (reuse == MAT_REUSE_MATRIX) {
160994a8b381SRichard Tran Mills     B = *newmat;
161094a8b381SRichard Tran Mills   } else {
16119566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
16129566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, MATMPIAIJ));
16139566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N));
16149566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSizes(B, A->rmap->bs, A->cmap->bs));
16159566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJSetPreallocation(B, 0, NULL));
16169566063dSJacob Faibussowitsch     PetscCall(MatMPIAIJSetPreallocation(B, 0, NULL, 0, NULL));
161794a8b381SRichard Tran Mills   }
1618d4002b98SHong Zhang   b = (Mat_MPIAIJ *)B->data;
161994a8b381SRichard Tran Mills 
162094a8b381SRichard Tran Mills   if (reuse == MAT_REUSE_MATRIX) {
16219566063dSJacob Faibussowitsch     PetscCall(MatConvert_SeqSELL_SeqAIJ(a->A, MATSEQAIJ, MAT_REUSE_MATRIX, &b->A));
16229566063dSJacob Faibussowitsch     PetscCall(MatConvert_SeqSELL_SeqAIJ(a->B, MATSEQAIJ, MAT_REUSE_MATRIX, &b->B));
162394a8b381SRichard Tran Mills   } else {
16249566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&b->A));
16259566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&b->B));
16269566063dSJacob Faibussowitsch     PetscCall(MatDisAssemble_MPISELL(A));
16279566063dSJacob Faibussowitsch     PetscCall(MatConvert_SeqSELL_SeqAIJ(a->A, MATSEQAIJ, MAT_INITIAL_MATRIX, &b->A));
16289566063dSJacob Faibussowitsch     PetscCall(MatConvert_SeqSELL_SeqAIJ(a->B, MATSEQAIJ, MAT_INITIAL_MATRIX, &b->B));
16299566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
16309566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
16319566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
16329566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
163394a8b381SRichard Tran Mills   }
1634d4002b98SHong Zhang 
1635d4002b98SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
16369566063dSJacob Faibussowitsch     PetscCall(MatHeaderReplace(A, &B));
1637d4002b98SHong Zhang   } else {
1638d4002b98SHong Zhang     *newmat = B;
1639d4002b98SHong Zhang   }
1640d4002b98SHong Zhang   PetscFunctionReturn(0);
1641d4002b98SHong Zhang }
1642d4002b98SHong Zhang 
16439371c9d4SSatish Balay PetscErrorCode MatConvert_MPIAIJ_MPISELL(Mat A, MatType newtype, MatReuse reuse, Mat *newmat) {
1644d4002b98SHong Zhang   Mat_MPIAIJ  *a = (Mat_MPIAIJ *)A->data;
1645d4002b98SHong Zhang   Mat          B;
1646d4002b98SHong Zhang   Mat_MPISELL *b;
1647d4002b98SHong Zhang 
1648d4002b98SHong Zhang   PetscFunctionBegin;
164928b400f6SJacob Faibussowitsch   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Matrix must be assembled");
1650d4002b98SHong Zhang 
165194a8b381SRichard Tran Mills   if (reuse == MAT_REUSE_MATRIX) {
165294a8b381SRichard Tran Mills     B = *newmat;
165394a8b381SRichard Tran Mills   } else {
16549566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
16559566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, MATMPISELL));
16569566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N));
16579566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSizes(B, A->rmap->bs, A->cmap->bs));
16589566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJSetPreallocation(B, 0, NULL));
16599566063dSJacob Faibussowitsch     PetscCall(MatMPIAIJSetPreallocation(B, 0, NULL, 0, NULL));
166094a8b381SRichard Tran Mills   }
1661d4002b98SHong Zhang   b = (Mat_MPISELL *)B->data;
166294a8b381SRichard Tran Mills 
166394a8b381SRichard Tran Mills   if (reuse == MAT_REUSE_MATRIX) {
16649566063dSJacob Faibussowitsch     PetscCall(MatConvert_SeqAIJ_SeqSELL(a->A, MATSEQSELL, MAT_REUSE_MATRIX, &b->A));
16659566063dSJacob Faibussowitsch     PetscCall(MatConvert_SeqAIJ_SeqSELL(a->B, MATSEQSELL, MAT_REUSE_MATRIX, &b->B));
166694a8b381SRichard Tran Mills   } else {
16679566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&b->A));
16689566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&b->B));
16699566063dSJacob Faibussowitsch     PetscCall(MatDisAssemble_MPIAIJ(A));
16709566063dSJacob Faibussowitsch     PetscCall(MatConvert_SeqAIJ_SeqSELL(a->A, MATSEQSELL, MAT_INITIAL_MATRIX, &b->A));
16719566063dSJacob Faibussowitsch     PetscCall(MatConvert_SeqAIJ_SeqSELL(a->B, MATSEQSELL, MAT_INITIAL_MATRIX, &b->B));
16729566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
16739566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
16749566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
16759566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
167694a8b381SRichard Tran Mills   }
1677d4002b98SHong Zhang 
1678d4002b98SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
16799566063dSJacob Faibussowitsch     PetscCall(MatHeaderReplace(A, &B));
1680d4002b98SHong Zhang   } else {
1681d4002b98SHong Zhang     *newmat = B;
1682d4002b98SHong Zhang   }
1683d4002b98SHong Zhang   PetscFunctionReturn(0);
1684d4002b98SHong Zhang }
1685d4002b98SHong Zhang 
16869371c9d4SSatish Balay PetscErrorCode MatSOR_MPISELL(Mat matin, Vec bb, PetscReal omega, MatSORType flag, PetscReal fshift, PetscInt its, PetscInt lits, Vec xx) {
1687d4002b98SHong Zhang   Mat_MPISELL *mat = (Mat_MPISELL *)matin->data;
1688f4259b30SLisandro Dalcin   Vec          bb1 = NULL;
1689d4002b98SHong Zhang 
1690d4002b98SHong Zhang   PetscFunctionBegin;
1691d4002b98SHong Zhang   if (flag == SOR_APPLY_UPPER) {
16929566063dSJacob Faibussowitsch     PetscCall((*mat->A->ops->sor)(mat->A, bb, omega, flag, fshift, lits, 1, xx));
1693d4002b98SHong Zhang     PetscFunctionReturn(0);
1694d4002b98SHong Zhang   }
1695d4002b98SHong Zhang 
169648a46eb9SPierre Jolivet   if (its > 1 || ~flag & SOR_ZERO_INITIAL_GUESS || flag & SOR_EISENSTAT) PetscCall(VecDuplicate(bb, &bb1));
1697d4002b98SHong Zhang 
1698d4002b98SHong Zhang   if ((flag & SOR_LOCAL_SYMMETRIC_SWEEP) == SOR_LOCAL_SYMMETRIC_SWEEP) {
1699d4002b98SHong Zhang     if (flag & SOR_ZERO_INITIAL_GUESS) {
17009566063dSJacob Faibussowitsch       PetscCall((*mat->A->ops->sor)(mat->A, bb, omega, flag, fshift, lits, 1, xx));
1701d4002b98SHong Zhang       its--;
1702d4002b98SHong Zhang     }
1703d4002b98SHong Zhang 
1704d4002b98SHong Zhang     while (its--) {
17059566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(mat->Mvctx, xx, mat->lvec, INSERT_VALUES, SCATTER_FORWARD));
17069566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(mat->Mvctx, xx, mat->lvec, INSERT_VALUES, SCATTER_FORWARD));
1707d4002b98SHong Zhang 
1708d4002b98SHong Zhang       /* update rhs: bb1 = bb - B*x */
17099566063dSJacob Faibussowitsch       PetscCall(VecScale(mat->lvec, -1.0));
17109566063dSJacob Faibussowitsch       PetscCall((*mat->B->ops->multadd)(mat->B, mat->lvec, bb, bb1));
1711d4002b98SHong Zhang 
1712d4002b98SHong Zhang       /* local sweep */
17139566063dSJacob Faibussowitsch       PetscCall((*mat->A->ops->sor)(mat->A, bb1, omega, SOR_SYMMETRIC_SWEEP, fshift, lits, 1, xx));
1714d4002b98SHong Zhang     }
1715d4002b98SHong Zhang   } else if (flag & SOR_LOCAL_FORWARD_SWEEP) {
1716d4002b98SHong Zhang     if (flag & SOR_ZERO_INITIAL_GUESS) {
17179566063dSJacob Faibussowitsch       PetscCall((*mat->A->ops->sor)(mat->A, bb, omega, flag, fshift, lits, 1, xx));
1718d4002b98SHong Zhang       its--;
1719d4002b98SHong Zhang     }
1720d4002b98SHong Zhang     while (its--) {
17219566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(mat->Mvctx, xx, mat->lvec, INSERT_VALUES, SCATTER_FORWARD));
17229566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(mat->Mvctx, xx, mat->lvec, INSERT_VALUES, SCATTER_FORWARD));
1723d4002b98SHong Zhang 
1724d4002b98SHong Zhang       /* update rhs: bb1 = bb - B*x */
17259566063dSJacob Faibussowitsch       PetscCall(VecScale(mat->lvec, -1.0));
17269566063dSJacob Faibussowitsch       PetscCall((*mat->B->ops->multadd)(mat->B, mat->lvec, bb, bb1));
1727d4002b98SHong Zhang 
1728d4002b98SHong Zhang       /* local sweep */
17299566063dSJacob Faibussowitsch       PetscCall((*mat->A->ops->sor)(mat->A, bb1, omega, SOR_FORWARD_SWEEP, fshift, lits, 1, xx));
1730d4002b98SHong Zhang     }
1731d4002b98SHong Zhang   } else if (flag & SOR_LOCAL_BACKWARD_SWEEP) {
1732d4002b98SHong Zhang     if (flag & SOR_ZERO_INITIAL_GUESS) {
17339566063dSJacob Faibussowitsch       PetscCall((*mat->A->ops->sor)(mat->A, bb, omega, flag, fshift, lits, 1, xx));
1734d4002b98SHong Zhang       its--;
1735d4002b98SHong Zhang     }
1736d4002b98SHong Zhang     while (its--) {
17379566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(mat->Mvctx, xx, mat->lvec, INSERT_VALUES, SCATTER_FORWARD));
17389566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(mat->Mvctx, xx, mat->lvec, INSERT_VALUES, SCATTER_FORWARD));
1739d4002b98SHong Zhang 
1740d4002b98SHong Zhang       /* update rhs: bb1 = bb - B*x */
17419566063dSJacob Faibussowitsch       PetscCall(VecScale(mat->lvec, -1.0));
17429566063dSJacob Faibussowitsch       PetscCall((*mat->B->ops->multadd)(mat->B, mat->lvec, bb, bb1));
1743d4002b98SHong Zhang 
1744d4002b98SHong Zhang       /* local sweep */
17459566063dSJacob Faibussowitsch       PetscCall((*mat->A->ops->sor)(mat->A, bb1, omega, SOR_BACKWARD_SWEEP, fshift, lits, 1, xx));
1746d4002b98SHong Zhang     }
1747d4002b98SHong Zhang   } else SETERRQ(PetscObjectComm((PetscObject)matin), PETSC_ERR_SUP, "Parallel SOR not supported");
1748d4002b98SHong Zhang 
17499566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&bb1));
1750d4002b98SHong Zhang 
1751d4002b98SHong Zhang   matin->factorerrortype = mat->A->factorerrortype;
1752d4002b98SHong Zhang   PetscFunctionReturn(0);
1753d4002b98SHong Zhang }
1754d4002b98SHong Zhang 
1755d4002b98SHong Zhang /*MC
1756d4002b98SHong Zhang    MATMPISELL - MATMPISELL = "MPISELL" - A matrix type to be used for parallel sparse matrices.
1757d4002b98SHong Zhang 
1758d4002b98SHong Zhang    Options Database Keys:
175911a5261eSBarry Smith . -mat_type mpisell - sets the matrix type to `MATMPISELL` during a call to `MatSetFromOptions()`
1760d4002b98SHong Zhang 
1761d4002b98SHong Zhang   Level: beginner
1762d4002b98SHong Zhang 
176311a5261eSBarry Smith .seealso: `MATSELL`, `MATSEQSELL` `MatCreateSELL()`
1764d4002b98SHong Zhang M*/
17659371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode MatCreate_MPISELL(Mat B) {
1766d4002b98SHong Zhang   Mat_MPISELL *b;
1767d4002b98SHong Zhang   PetscMPIInt  size;
1768d4002b98SHong Zhang 
1769d4002b98SHong Zhang   PetscFunctionBegin;
17709566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)B), &size));
1771*4dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&b));
1772d4002b98SHong Zhang   B->data = (void *)b;
17739566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(B->ops, &MatOps_Values, sizeof(struct _MatOps)));
1774d4002b98SHong Zhang   B->assembled  = PETSC_FALSE;
1775d4002b98SHong Zhang   B->insertmode = NOT_SET_VALUES;
1776d4002b98SHong Zhang   b->size       = size;
17779566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)B), &b->rank));
1778d4002b98SHong Zhang   /* build cache for off array entries formed */
17799566063dSJacob Faibussowitsch   PetscCall(MatStashCreate_Private(PetscObjectComm((PetscObject)B), 1, &B->stash));
1780d4002b98SHong Zhang 
1781d4002b98SHong Zhang   b->donotstash  = PETSC_FALSE;
1782f4259b30SLisandro Dalcin   b->colmap      = NULL;
1783f4259b30SLisandro Dalcin   b->garray      = NULL;
1784d4002b98SHong Zhang   b->roworiented = PETSC_TRUE;
1785d4002b98SHong Zhang 
1786d4002b98SHong Zhang   /* stuff used for matrix vector multiply */
1787d4002b98SHong Zhang   b->lvec  = NULL;
1788d4002b98SHong Zhang   b->Mvctx = NULL;
1789d4002b98SHong Zhang 
1790d4002b98SHong Zhang   /* stuff for MatGetRow() */
1791f4259b30SLisandro Dalcin   b->rowindices   = NULL;
1792f4259b30SLisandro Dalcin   b->rowvalues    = NULL;
1793d4002b98SHong Zhang   b->getrowactive = PETSC_FALSE;
1794d4002b98SHong Zhang 
17959566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatStoreValues_C", MatStoreValues_MPISELL));
17969566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatRetrieveValues_C", MatRetrieveValues_MPISELL));
17979566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatIsTranspose_C", MatIsTranspose_MPISELL));
17989566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatMPISELLSetPreallocation_C", MatMPISELLSetPreallocation_MPISELL));
17999566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_mpisell_mpiaij_C", MatConvert_MPISELL_MPIAIJ));
18009566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDiagonalScaleLocal_C", MatDiagonalScaleLocal_MPISELL));
18019566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATMPISELL));
1802d4002b98SHong Zhang   PetscFunctionReturn(0);
1803d4002b98SHong Zhang }
1804