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:
1820f4b53cSBarry Smith . -mat_type sell - sets the matrix type to `MATSELL` during a call to `MatSetFromOptions()`
19d4002b98SHong Zhang
20d4002b98SHong Zhang Level: beginner
21d4002b98SHong Zhang
2267be906fSBarry Smith .seealso: `Mat`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSELL()`, `MatCreateSeqSELL()`, `MATSEQSELL`, `MATMPISELL`
23d4002b98SHong Zhang M*/
24d4002b98SHong Zhang
MatDiagonalSet_MPISELL(Mat Y,Vec D,InsertMode is)25ba38deedSJacob Faibussowitsch static PetscErrorCode MatDiagonalSet_MPISELL(Mat Y, Vec D, InsertMode is)
26d71ae5a4SJacob Faibussowitsch {
27d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)Y->data;
28d4002b98SHong Zhang
29d4002b98SHong Zhang PetscFunctionBegin;
30d4002b98SHong Zhang if (Y->assembled && Y->rmap->rstart == Y->cmap->rstart && Y->rmap->rend == Y->cmap->rend) {
319566063dSJacob Faibussowitsch PetscCall(MatDiagonalSet(sell->A, D, is));
32d4002b98SHong Zhang } else {
339566063dSJacob Faibussowitsch PetscCall(MatDiagonalSet_Default(Y, D, is));
34d4002b98SHong Zhang }
353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
36d4002b98SHong Zhang }
37d4002b98SHong Zhang
38d4002b98SHong Zhang /*
39d4002b98SHong Zhang Local utility routine that creates a mapping from the global column
40d4002b98SHong Zhang number to the local number in the off-diagonal part of the local
41d4002b98SHong Zhang storage of the matrix. When PETSC_USE_CTABLE is used this is scalable at
42d4002b98SHong Zhang a slightly higher hash table cost; without it it is not scalable (each processor
43da81f932SPierre Jolivet has an order N integer array but is fast to access.
44d4002b98SHong Zhang */
MatCreateColmap_MPISELL_Private(Mat mat)45d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateColmap_MPISELL_Private(Mat mat)
46d71ae5a4SJacob Faibussowitsch {
47d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)mat->data;
48d4002b98SHong Zhang PetscInt n = sell->B->cmap->n, i;
49d4002b98SHong Zhang
50d4002b98SHong Zhang PetscFunctionBegin;
5128b400f6SJacob Faibussowitsch PetscCheck(sell->garray, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MPISELL Matrix was assembled but is missing garray");
52d4002b98SHong Zhang #if defined(PETSC_USE_CTABLE)
53eec179cfSJacob Faibussowitsch PetscCall(PetscHMapICreateWithSize(n, &sell->colmap));
54c76ffc5fSJacob Faibussowitsch for (i = 0; i < n; i++) PetscCall(PetscHMapISet(sell->colmap, sell->garray[i] + 1, i + 1));
55d4002b98SHong Zhang #else
569566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(mat->cmap->N + 1, &sell->colmap));
57d4002b98SHong Zhang for (i = 0; i < n; i++) sell->colmap[sell->garray[i]] = i + 1;
58d4002b98SHong Zhang #endif
593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
60d4002b98SHong Zhang }
61d4002b98SHong Zhang
62d4002b98SHong Zhang #define MatSetValues_SeqSELL_A_Private(row, col, value, addv, orow, ocol) \
63d4002b98SHong Zhang { \
64d4002b98SHong Zhang if (col <= lastcol1) low1 = 0; \
65d4002b98SHong Zhang else high1 = nrow1; \
66d4002b98SHong Zhang lastcol1 = col; \
67d4002b98SHong Zhang while (high1 - low1 > 5) { \
68d4002b98SHong Zhang t = (low1 + high1) / 2; \
694f8ff0b3SHong Zhang if (cp1[sliceheight * t] > col) high1 = t; \
70d4002b98SHong Zhang else low1 = t; \
71d4002b98SHong Zhang } \
72d4002b98SHong Zhang for (_i = low1; _i < high1; _i++) { \
734f8ff0b3SHong Zhang if (cp1[sliceheight * _i] > col) break; \
744f8ff0b3SHong Zhang if (cp1[sliceheight * _i] == col) { \
754f8ff0b3SHong Zhang if (addv == ADD_VALUES) vp1[sliceheight * _i] += value; \
764f8ff0b3SHong Zhang else vp1[sliceheight * _i] = value; \
772d1451d4SHong Zhang inserted = PETSC_TRUE; \
78d4002b98SHong Zhang goto a_noinsert; \
79d4002b98SHong Zhang } \
80d4002b98SHong Zhang } \
819371c9d4SSatish Balay if (value == 0.0 && ignorezeroentries) { \
829371c9d4SSatish Balay low1 = 0; \
839371c9d4SSatish Balay high1 = nrow1; \
849371c9d4SSatish Balay goto a_noinsert; \
859371c9d4SSatish Balay } \
869371c9d4SSatish Balay if (nonew == 1) { \
879371c9d4SSatish Balay low1 = 0; \
889371c9d4SSatish Balay high1 = nrow1; \
899371c9d4SSatish Balay goto a_noinsert; \
909371c9d4SSatish Balay } \
9108401ef6SPierre 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); \
9207e43b41SHong Zhang MatSeqXSELLReallocateSELL(A, am, 1, nrow1, a->sliidx, a->sliceheight, row / sliceheight, row, col, a->colidx, a->val, cp1, vp1, nonew, MatScalar); \
93d4002b98SHong Zhang /* shift up all the later entries in this row */ \
94d4002b98SHong Zhang for (ii = nrow1 - 1; ii >= _i; ii--) { \
954f8ff0b3SHong Zhang cp1[sliceheight * (ii + 1)] = cp1[sliceheight * ii]; \
964f8ff0b3SHong Zhang vp1[sliceheight * (ii + 1)] = vp1[sliceheight * ii]; \
97d4002b98SHong Zhang } \
984f8ff0b3SHong Zhang cp1[sliceheight * _i] = col; \
994f8ff0b3SHong Zhang vp1[sliceheight * _i] = value; \
1009371c9d4SSatish Balay a->nz++; \
1019371c9d4SSatish Balay nrow1++; \
102d4002b98SHong Zhang a_noinsert:; \
103d4002b98SHong Zhang a->rlen[row] = nrow1; \
104d4002b98SHong Zhang }
105d4002b98SHong Zhang
106d4002b98SHong Zhang #define MatSetValues_SeqSELL_B_Private(row, col, value, addv, orow, ocol) \
107d4002b98SHong Zhang { \
108d4002b98SHong Zhang if (col <= lastcol2) low2 = 0; \
109d4002b98SHong Zhang else high2 = nrow2; \
110d4002b98SHong Zhang lastcol2 = col; \
111d4002b98SHong Zhang while (high2 - low2 > 5) { \
112d4002b98SHong Zhang t = (low2 + high2) / 2; \
1134f8ff0b3SHong Zhang if (cp2[sliceheight * t] > col) high2 = t; \
114d4002b98SHong Zhang else low2 = t; \
115d4002b98SHong Zhang } \
116d4002b98SHong Zhang for (_i = low2; _i < high2; _i++) { \
1174f8ff0b3SHong Zhang if (cp2[sliceheight * _i] > col) break; \
1184f8ff0b3SHong Zhang if (cp2[sliceheight * _i] == col) { \
1194f8ff0b3SHong Zhang if (addv == ADD_VALUES) vp2[sliceheight * _i] += value; \
1204f8ff0b3SHong Zhang else vp2[sliceheight * _i] = value; \
1212d1451d4SHong Zhang inserted = PETSC_TRUE; \
122d4002b98SHong Zhang goto b_noinsert; \
123d4002b98SHong Zhang } \
124d4002b98SHong Zhang } \
1259371c9d4SSatish Balay if (value == 0.0 && ignorezeroentries) { \
1269371c9d4SSatish Balay low2 = 0; \
1279371c9d4SSatish Balay high2 = nrow2; \
1289371c9d4SSatish Balay goto b_noinsert; \
1299371c9d4SSatish Balay } \
1309371c9d4SSatish Balay if (nonew == 1) { \
1319371c9d4SSatish Balay low2 = 0; \
1329371c9d4SSatish Balay high2 = nrow2; \
1339371c9d4SSatish Balay goto b_noinsert; \
1349371c9d4SSatish Balay } \
13508401ef6SPierre 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); \
13607e43b41SHong Zhang MatSeqXSELLReallocateSELL(B, bm, 1, nrow2, b->sliidx, b->sliceheight, row / sliceheight, row, col, b->colidx, b->val, cp2, vp2, nonew, MatScalar); \
137d4002b98SHong Zhang /* shift up all the later entries in this row */ \
138d4002b98SHong Zhang for (ii = nrow2 - 1; ii >= _i; ii--) { \
1394f8ff0b3SHong Zhang cp2[sliceheight * (ii + 1)] = cp2[sliceheight * ii]; \
1404f8ff0b3SHong Zhang vp2[sliceheight * (ii + 1)] = vp2[sliceheight * ii]; \
141d4002b98SHong Zhang } \
1424f8ff0b3SHong Zhang cp2[sliceheight * _i] = col; \
1434f8ff0b3SHong Zhang vp2[sliceheight * _i] = value; \
1449371c9d4SSatish Balay b->nz++; \
1459371c9d4SSatish Balay nrow2++; \
146d4002b98SHong Zhang b_noinsert:; \
147d4002b98SHong Zhang b->rlen[row] = nrow2; \
148d4002b98SHong Zhang }
149d4002b98SHong Zhang
MatSetValues_MPISELL(Mat mat,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode addv)15043b34f9dSJacob Faibussowitsch static PetscErrorCode MatSetValues_MPISELL(Mat mat, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode addv)
151d71ae5a4SJacob Faibussowitsch {
152d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)mat->data;
153d4002b98SHong Zhang PetscScalar value;
154d4002b98SHong Zhang PetscInt i, j, rstart = mat->rmap->rstart, rend = mat->rmap->rend, shift1, shift2;
155d4002b98SHong Zhang PetscInt cstart = mat->cmap->rstart, cend = mat->cmap->rend, row, col;
156d4002b98SHong Zhang PetscBool roworiented = sell->roworiented;
157d4002b98SHong Zhang
158d4002b98SHong Zhang /* Some Variables required in the macro */
159d4002b98SHong Zhang Mat A = sell->A;
160d4002b98SHong Zhang Mat_SeqSELL *a = (Mat_SeqSELL *)A->data;
161d4002b98SHong Zhang PetscBool ignorezeroentries = a->ignorezeroentries, found;
162d4002b98SHong Zhang Mat B = sell->B;
163d4002b98SHong Zhang Mat_SeqSELL *b = (Mat_SeqSELL *)B->data;
16407e43b41SHong Zhang PetscInt *cp1, *cp2, ii, _i, nrow1, nrow2, low1, high1, low2, high2, t, lastcol1, lastcol2, sliceheight = a->sliceheight;
165d4002b98SHong Zhang MatScalar *vp1, *vp2;
166d4002b98SHong Zhang
167d4002b98SHong Zhang PetscFunctionBegin;
168d4002b98SHong Zhang for (i = 0; i < m; i++) {
169d4002b98SHong Zhang if (im[i] < 0) continue;
1706bdcaf15SBarry 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);
171d4002b98SHong Zhang if (im[i] >= rstart && im[i] < rend) {
172d4002b98SHong Zhang row = im[i] - rstart;
173d4002b98SHong Zhang lastcol1 = -1;
17407e43b41SHong Zhang shift1 = a->sliidx[row / sliceheight] + (row % sliceheight); /* starting index of the row */
1758e3a54c0SPierre Jolivet cp1 = PetscSafePointerPlusOffset(a->colidx, shift1);
1768e3a54c0SPierre Jolivet vp1 = PetscSafePointerPlusOffset(a->val, shift1);
177d4002b98SHong Zhang nrow1 = a->rlen[row];
178d4002b98SHong Zhang low1 = 0;
179d4002b98SHong Zhang high1 = nrow1;
180d4002b98SHong Zhang lastcol2 = -1;
18107e43b41SHong Zhang shift2 = b->sliidx[row / sliceheight] + (row % sliceheight); /* starting index of the row */
1828e3a54c0SPierre Jolivet cp2 = PetscSafePointerPlusOffset(b->colidx, shift2);
1838e3a54c0SPierre Jolivet vp2 = PetscSafePointerPlusOffset(b->val, shift2);
184d4002b98SHong Zhang nrow2 = b->rlen[row];
185d4002b98SHong Zhang low2 = 0;
186d4002b98SHong Zhang high2 = nrow2;
187d4002b98SHong Zhang
188d4002b98SHong Zhang for (j = 0; j < n; j++) {
189d4002b98SHong Zhang if (roworiented) value = v[i * n + j];
190d4002b98SHong Zhang else value = v[i + j * m];
191d4002b98SHong Zhang if (ignorezeroentries && value == 0.0 && (addv == ADD_VALUES)) continue;
192d4002b98SHong Zhang if (in[j] >= cstart && in[j] < cend) {
193d4002b98SHong Zhang col = in[j] - cstart;
194d4002b98SHong Zhang MatSetValue_SeqSELL_Private(A, row, col, value, addv, im[i], in[j], cp1, vp1, lastcol1, low1, high1); /* set one value */
1952d1451d4SHong Zhang #if defined(PETSC_HAVE_CUDA)
1962d1451d4SHong Zhang if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED && found) A->offloadmask = PETSC_OFFLOAD_CPU;
1972d1451d4SHong Zhang #endif
198f7d195e4SLawrence Mitchell } else if (in[j] < 0) {
199f7d195e4SLawrence Mitchell continue;
200f7d195e4SLawrence Mitchell } else {
201f7d195e4SLawrence 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);
202d4002b98SHong Zhang if (mat->was_assembled) {
20348a46eb9SPierre Jolivet if (!sell->colmap) PetscCall(MatCreateColmap_MPISELL_Private(mat));
204d4002b98SHong Zhang #if defined(PETSC_USE_CTABLE)
205eec179cfSJacob Faibussowitsch PetscCall(PetscHMapIGetWithDefault(sell->colmap, in[j] + 1, 0, &col));
206d4002b98SHong Zhang col--;
207d4002b98SHong Zhang #else
208d4002b98SHong Zhang col = sell->colmap[in[j]] - 1;
209d4002b98SHong Zhang #endif
210f4f49eeaSPierre Jolivet if (col < 0 && !((Mat_SeqSELL *)sell->B->data)->nonew) {
2119566063dSJacob Faibussowitsch PetscCall(MatDisAssemble_MPISELL(mat));
212d4002b98SHong Zhang col = in[j];
213d4002b98SHong Zhang /* Reinitialize the variables required by MatSetValues_SeqSELL_B_Private() */
214d4002b98SHong Zhang B = sell->B;
215d4002b98SHong Zhang b = (Mat_SeqSELL *)B->data;
21607e43b41SHong Zhang shift2 = b->sliidx[row / sliceheight] + (row % sliceheight); /* starting index of the row */
217d4002b98SHong Zhang cp2 = b->colidx + shift2;
218d4002b98SHong Zhang vp2 = b->val + shift2;
219d4002b98SHong Zhang nrow2 = b->rlen[row];
220d4002b98SHong Zhang low2 = 0;
221d4002b98SHong Zhang high2 = nrow2;
2222d1451d4SHong Zhang found = PETSC_FALSE;
223f7d195e4SLawrence Mitchell } else {
224f7d195e4SLawrence 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]);
225f7d195e4SLawrence Mitchell }
226d4002b98SHong Zhang } else col = in[j];
227d4002b98SHong Zhang MatSetValue_SeqSELL_Private(B, row, col, value, addv, im[i], in[j], cp2, vp2, lastcol2, low2, high2); /* set one value */
2282d1451d4SHong Zhang #if defined(PETSC_HAVE_CUDA)
2292d1451d4SHong Zhang if (B->offloadmask != PETSC_OFFLOAD_UNALLOCATED && found) B->offloadmask = PETSC_OFFLOAD_CPU;
2302d1451d4SHong Zhang #endif
231d4002b98SHong Zhang }
232d4002b98SHong Zhang }
233d4002b98SHong Zhang } else {
23428b400f6SJacob 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]);
235d4002b98SHong Zhang if (!sell->donotstash) {
236d4002b98SHong Zhang mat->assembled = PETSC_FALSE;
237d4002b98SHong Zhang if (roworiented) {
2389566063dSJacob Faibussowitsch PetscCall(MatStashValuesRow_Private(&mat->stash, im[i], n, in, v + i * n, (PetscBool)(ignorezeroentries && (addv == ADD_VALUES))));
239d4002b98SHong Zhang } else {
2409566063dSJacob Faibussowitsch PetscCall(MatStashValuesCol_Private(&mat->stash, im[i], n, in, v + i, m, (PetscBool)(ignorezeroentries && (addv == ADD_VALUES))));
241d4002b98SHong Zhang }
242d4002b98SHong Zhang }
243d4002b98SHong Zhang }
244d4002b98SHong Zhang }
2453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
246d4002b98SHong Zhang }
247d4002b98SHong Zhang
MatGetValues_MPISELL(Mat mat,PetscInt m,const PetscInt idxm[],PetscInt n,const PetscInt idxn[],PetscScalar v[])248ba38deedSJacob Faibussowitsch static PetscErrorCode MatGetValues_MPISELL(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
249d71ae5a4SJacob Faibussowitsch {
250d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)mat->data;
251d4002b98SHong Zhang PetscInt i, j, rstart = mat->rmap->rstart, rend = mat->rmap->rend;
252d4002b98SHong Zhang PetscInt cstart = mat->cmap->rstart, cend = mat->cmap->rend, row, col;
253d4002b98SHong Zhang
254d4002b98SHong Zhang PetscFunctionBegin;
255d4002b98SHong Zhang for (i = 0; i < m; i++) {
25654c59aa7SJacob Faibussowitsch if (idxm[i] < 0) continue; /* negative row */
25754c59aa7SJacob 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);
258966bd95aSPierre Jolivet PetscCheck(idxm[i] >= rstart && idxm[i] < rend, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only local values currently supported");
259d4002b98SHong Zhang row = idxm[i] - rstart;
260d4002b98SHong Zhang for (j = 0; j < n; j++) {
26154c59aa7SJacob Faibussowitsch if (idxn[j] < 0) continue; /* negative column */
26254c59aa7SJacob 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);
263d4002b98SHong Zhang if (idxn[j] >= cstart && idxn[j] < cend) {
264d4002b98SHong Zhang col = idxn[j] - cstart;
2659566063dSJacob Faibussowitsch PetscCall(MatGetValues(sell->A, 1, &row, 1, &col, v + i * n + j));
266d4002b98SHong Zhang } else {
26748a46eb9SPierre Jolivet if (!sell->colmap) PetscCall(MatCreateColmap_MPISELL_Private(mat));
268d4002b98SHong Zhang #if defined(PETSC_USE_CTABLE)
269eec179cfSJacob Faibussowitsch PetscCall(PetscHMapIGetWithDefault(sell->colmap, idxn[j] + 1, 0, &col));
270d4002b98SHong Zhang col--;
271d4002b98SHong Zhang #else
272d4002b98SHong Zhang col = sell->colmap[idxn[j]] - 1;
273d4002b98SHong Zhang #endif
274966bd95aSPierre Jolivet if (col < 0 || sell->garray[col] != idxn[j]) *(v + i * n + j) = 0.0;
27548a46eb9SPierre Jolivet else PetscCall(MatGetValues(sell->B, 1, &row, 1, &col, v + i * n + j));
276d4002b98SHong Zhang }
277d4002b98SHong Zhang }
278d4002b98SHong Zhang }
2793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
280d4002b98SHong Zhang }
281d4002b98SHong Zhang
MatAssemblyBegin_MPISELL(Mat mat,MatAssemblyType mode)282ba38deedSJacob Faibussowitsch static PetscErrorCode MatAssemblyBegin_MPISELL(Mat mat, MatAssemblyType mode)
283d71ae5a4SJacob Faibussowitsch {
284d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)mat->data;
285d4002b98SHong Zhang PetscInt nstash, reallocs;
286d4002b98SHong Zhang
287d4002b98SHong Zhang PetscFunctionBegin;
2883ba16761SJacob Faibussowitsch if (sell->donotstash || mat->nooffprocentries) PetscFunctionReturn(PETSC_SUCCESS);
289d4002b98SHong Zhang
2909566063dSJacob Faibussowitsch PetscCall(MatStashScatterBegin_Private(mat, &mat->stash, mat->rmap->range));
2919566063dSJacob Faibussowitsch PetscCall(MatStashGetInfo_Private(&mat->stash, &nstash, &reallocs));
2929566063dSJacob Faibussowitsch PetscCall(PetscInfo(sell->A, "Stash has %" PetscInt_FMT " entries, uses %" PetscInt_FMT " mallocs.\n", nstash, reallocs));
2933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
294d4002b98SHong Zhang }
295d4002b98SHong Zhang
MatAssemblyEnd_MPISELL(Mat mat,MatAssemblyType mode)296d71ae5a4SJacob Faibussowitsch PetscErrorCode MatAssemblyEnd_MPISELL(Mat mat, MatAssemblyType mode)
297d71ae5a4SJacob Faibussowitsch {
298d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)mat->data;
299d4002b98SHong Zhang PetscMPIInt n;
300d4002b98SHong Zhang PetscInt i, flg;
301d4002b98SHong Zhang PetscInt *row, *col;
302d4002b98SHong Zhang PetscScalar *val;
303c0edf612SJunchao Zhang PetscBool all_assembled;
304d4002b98SHong Zhang /* do not use 'b = (Mat_SeqSELL*)sell->B->data' as B can be reset in disassembly */
305d4002b98SHong Zhang PetscFunctionBegin;
306d4002b98SHong Zhang if (!sell->donotstash && !mat->nooffprocentries) {
307d4002b98SHong Zhang while (1) {
3089566063dSJacob Faibussowitsch PetscCall(MatStashScatterGetMesg_Private(&mat->stash, &n, &row, &col, &val, &flg));
309d4002b98SHong Zhang if (!flg) break;
310d4002b98SHong Zhang
311d4002b98SHong Zhang for (i = 0; i < n; i++) { /* assemble one by one */
3129566063dSJacob Faibussowitsch PetscCall(MatSetValues_MPISELL(mat, 1, row + i, 1, col + i, val + i, mat->insertmode));
313d4002b98SHong Zhang }
314d4002b98SHong Zhang }
3159566063dSJacob Faibussowitsch PetscCall(MatStashScatterEnd_Private(&mat->stash));
316d4002b98SHong Zhang }
3172d1451d4SHong Zhang #if defined(PETSC_HAVE_CUDA)
3182d1451d4SHong Zhang if (mat->offloadmask == PETSC_OFFLOAD_CPU) sell->A->offloadmask = PETSC_OFFLOAD_CPU;
3192d1451d4SHong Zhang #endif
3209566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(sell->A, mode));
3219566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(sell->A, mode));
322d4002b98SHong Zhang
323d4002b98SHong Zhang /*
324b638e6b4SJunchao Zhang determine if any process has disassembled, if so we must
3256aad120cSJose E. Roman also disassemble ourselves, in order that we may reassemble.
326d4002b98SHong Zhang */
327d4002b98SHong Zhang /*
328d4002b98SHong Zhang if nonzero structure of submatrix B cannot change then we know that
329b638e6b4SJunchao Zhang no process disassembled thus we can skip this stuff
330d4002b98SHong Zhang */
331d4002b98SHong Zhang if (!((Mat_SeqSELL *)sell->B->data)->nonew) {
3325440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(&mat->was_assembled, &all_assembled, 1, MPI_C_BOOL, MPI_LAND, PetscObjectComm((PetscObject)mat)));
333c0edf612SJunchao Zhang if (mat->was_assembled && !all_assembled) PetscCall(MatDisAssemble_MPISELL(mat));
334d4002b98SHong Zhang }
33548a46eb9SPierre Jolivet if (!mat->was_assembled && mode == MAT_FINAL_ASSEMBLY) PetscCall(MatSetUpMultiply_MPISELL(mat));
3362d1451d4SHong Zhang #if defined(PETSC_HAVE_CUDA)
3372d1451d4SHong Zhang if (mat->offloadmask == PETSC_OFFLOAD_CPU && sell->B->offloadmask != PETSC_OFFLOAD_UNALLOCATED) sell->B->offloadmask = PETSC_OFFLOAD_CPU;
3382d1451d4SHong Zhang #endif
3399566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(sell->B, mode));
3409566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(sell->B, mode));
3419566063dSJacob Faibussowitsch PetscCall(PetscFree2(sell->rowvalues, sell->rowindices));
342f4259b30SLisandro Dalcin sell->rowvalues = NULL;
3439566063dSJacob Faibussowitsch PetscCall(VecDestroy(&sell->diag));
344d4002b98SHong Zhang
345d4002b98SHong Zhang /* if no new nonzero locations are allowed in matrix then only set the matrix state the first time through */
346f4f49eeaSPierre Jolivet if ((!mat->was_assembled && mode == MAT_FINAL_ASSEMBLY) || !((Mat_SeqSELL *)sell->A->data)->nonew) {
347d4002b98SHong Zhang PetscObjectState state = sell->A->nonzerostate + sell->B->nonzerostate;
348462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&state, &mat->nonzerostate, 1, MPIU_INT64, MPI_SUM, PetscObjectComm((PetscObject)mat)));
349d4002b98SHong Zhang }
3502d1451d4SHong Zhang #if defined(PETSC_HAVE_CUDA)
3512d1451d4SHong Zhang mat->offloadmask = PETSC_OFFLOAD_BOTH;
3522d1451d4SHong Zhang #endif
3533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
354d4002b98SHong Zhang }
355d4002b98SHong Zhang
MatZeroEntries_MPISELL(Mat A)356ba38deedSJacob Faibussowitsch static PetscErrorCode MatZeroEntries_MPISELL(Mat A)
357d71ae5a4SJacob Faibussowitsch {
358d4002b98SHong Zhang Mat_MPISELL *l = (Mat_MPISELL *)A->data;
359d4002b98SHong Zhang
360d4002b98SHong Zhang PetscFunctionBegin;
3619566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(l->A));
3629566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(l->B));
3633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
364d4002b98SHong Zhang }
365d4002b98SHong Zhang
MatMult_MPISELL(Mat A,Vec xx,Vec yy)366ba38deedSJacob Faibussowitsch static PetscErrorCode MatMult_MPISELL(Mat A, Vec xx, Vec yy)
367d71ae5a4SJacob Faibussowitsch {
368d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data;
369d4002b98SHong Zhang PetscInt nt;
370d4002b98SHong Zhang
371d4002b98SHong Zhang PetscFunctionBegin;
3729566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(xx, &nt));
37308401ef6SPierre 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);
3749566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(a->Mvctx, xx, a->lvec, INSERT_VALUES, SCATTER_FORWARD));
3759566063dSJacob Faibussowitsch PetscCall((*a->A->ops->mult)(a->A, xx, yy));
3769566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(a->Mvctx, xx, a->lvec, INSERT_VALUES, SCATTER_FORWARD));
3779566063dSJacob Faibussowitsch PetscCall((*a->B->ops->multadd)(a->B, a->lvec, yy, yy));
3783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
379d4002b98SHong Zhang }
380d4002b98SHong Zhang
MatMultDiagonalBlock_MPISELL(Mat A,Vec bb,Vec xx)381fa078d78SJacob Faibussowitsch static PetscErrorCode MatMultDiagonalBlock_MPISELL(Mat A, Vec bb, Vec xx)
382d71ae5a4SJacob Faibussowitsch {
383d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data;
384d4002b98SHong Zhang
385d4002b98SHong Zhang PetscFunctionBegin;
3869566063dSJacob Faibussowitsch PetscCall(MatMultDiagonalBlock(a->A, bb, xx));
3873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
388d4002b98SHong Zhang }
389d4002b98SHong Zhang
MatMultAdd_MPISELL(Mat A,Vec xx,Vec yy,Vec zz)390ba38deedSJacob Faibussowitsch static PetscErrorCode MatMultAdd_MPISELL(Mat A, Vec xx, Vec yy, Vec zz)
391d71ae5a4SJacob Faibussowitsch {
392d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data;
393d4002b98SHong Zhang
394d4002b98SHong Zhang PetscFunctionBegin;
3959566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(a->Mvctx, xx, a->lvec, INSERT_VALUES, SCATTER_FORWARD));
3969566063dSJacob Faibussowitsch PetscCall((*a->A->ops->multadd)(a->A, xx, yy, zz));
3979566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(a->Mvctx, xx, a->lvec, INSERT_VALUES, SCATTER_FORWARD));
3989566063dSJacob Faibussowitsch PetscCall((*a->B->ops->multadd)(a->B, a->lvec, zz, zz));
3993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
400d4002b98SHong Zhang }
401d4002b98SHong Zhang
MatMultTranspose_MPISELL(Mat A,Vec xx,Vec yy)402ba38deedSJacob Faibussowitsch static PetscErrorCode MatMultTranspose_MPISELL(Mat A, Vec xx, Vec yy)
403d71ae5a4SJacob Faibussowitsch {
404d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data;
405d4002b98SHong Zhang
406d4002b98SHong Zhang PetscFunctionBegin;
407d4002b98SHong Zhang /* do nondiagonal part */
4089566063dSJacob Faibussowitsch PetscCall((*a->B->ops->multtranspose)(a->B, xx, a->lvec));
409d4002b98SHong Zhang /* do local part */
4109566063dSJacob Faibussowitsch PetscCall((*a->A->ops->multtranspose)(a->A, xx, yy));
411a29b4eb7SJunchao Zhang /* add partial results together */
4129566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(a->Mvctx, a->lvec, yy, ADD_VALUES, SCATTER_REVERSE));
4139566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(a->Mvctx, a->lvec, yy, ADD_VALUES, SCATTER_REVERSE));
4143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
415d4002b98SHong Zhang }
416d4002b98SHong Zhang
MatIsTranspose_MPISELL(Mat Amat,Mat Bmat,PetscReal tol,PetscBool * f)417ba38deedSJacob Faibussowitsch static PetscErrorCode MatIsTranspose_MPISELL(Mat Amat, Mat Bmat, PetscReal tol, PetscBool *f)
418d71ae5a4SJacob Faibussowitsch {
419d4002b98SHong Zhang MPI_Comm comm;
420d4002b98SHong Zhang Mat_MPISELL *Asell = (Mat_MPISELL *)Amat->data, *Bsell;
421d4002b98SHong Zhang Mat Adia = Asell->A, Bdia, Aoff, Boff, *Aoffs, *Boffs;
422d4002b98SHong Zhang IS Me, Notme;
423d4002b98SHong Zhang PetscInt M, N, first, last, *notme, i;
424d4002b98SHong Zhang PetscMPIInt size;
425d4002b98SHong Zhang
426d4002b98SHong Zhang PetscFunctionBegin;
427d4002b98SHong Zhang /* Easy test: symmetric diagonal block */
4289371c9d4SSatish Balay Bsell = (Mat_MPISELL *)Bmat->data;
4299371c9d4SSatish Balay Bdia = Bsell->A;
4309566063dSJacob Faibussowitsch PetscCall(MatIsTranspose(Adia, Bdia, tol, f));
4313ba16761SJacob Faibussowitsch if (!*f) PetscFunctionReturn(PETSC_SUCCESS);
4329566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)Amat, &comm));
4339566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size));
4343ba16761SJacob Faibussowitsch if (size == 1) PetscFunctionReturn(PETSC_SUCCESS);
435d4002b98SHong Zhang
436d4002b98SHong Zhang /* Hard test: off-diagonal block. This takes a MatCreateSubMatrix. */
4379566063dSJacob Faibussowitsch PetscCall(MatGetSize(Amat, &M, &N));
4389566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(Amat, &first, &last));
4399566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(N - last + first, ¬me));
440d4002b98SHong Zhang for (i = 0; i < first; i++) notme[i] = i;
441d4002b98SHong Zhang for (i = last; i < M; i++) notme[i - last + first] = i;
4429566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(MPI_COMM_SELF, N - last + first, notme, PETSC_COPY_VALUES, &Notme));
4439566063dSJacob Faibussowitsch PetscCall(ISCreateStride(MPI_COMM_SELF, last - first, first, 1, &Me));
4449566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrices(Amat, 1, &Me, &Notme, MAT_INITIAL_MATRIX, &Aoffs));
445d4002b98SHong Zhang Aoff = Aoffs[0];
4469566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrices(Bmat, 1, &Notme, &Me, MAT_INITIAL_MATRIX, &Boffs));
447d4002b98SHong Zhang Boff = Boffs[0];
4489566063dSJacob Faibussowitsch PetscCall(MatIsTranspose(Aoff, Boff, tol, f));
4499566063dSJacob Faibussowitsch PetscCall(MatDestroyMatrices(1, &Aoffs));
4509566063dSJacob Faibussowitsch PetscCall(MatDestroyMatrices(1, &Boffs));
4519566063dSJacob Faibussowitsch PetscCall(ISDestroy(&Me));
4529566063dSJacob Faibussowitsch PetscCall(ISDestroy(&Notme));
4539566063dSJacob Faibussowitsch PetscCall(PetscFree(notme));
4543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
455d4002b98SHong Zhang }
456d4002b98SHong Zhang
MatMultTransposeAdd_MPISELL(Mat A,Vec xx,Vec yy,Vec zz)457ba38deedSJacob Faibussowitsch static PetscErrorCode MatMultTransposeAdd_MPISELL(Mat A, Vec xx, Vec yy, Vec zz)
458d71ae5a4SJacob Faibussowitsch {
459d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data;
460d4002b98SHong Zhang
461d4002b98SHong Zhang PetscFunctionBegin;
462d4002b98SHong Zhang /* do nondiagonal part */
4639566063dSJacob Faibussowitsch PetscCall((*a->B->ops->multtranspose)(a->B, xx, a->lvec));
464d4002b98SHong Zhang /* do local part */
4659566063dSJacob Faibussowitsch PetscCall((*a->A->ops->multtransposeadd)(a->A, xx, yy, zz));
466e4a140f6SJunchao Zhang /* add partial results together */
4679566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(a->Mvctx, a->lvec, zz, ADD_VALUES, SCATTER_REVERSE));
4689566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(a->Mvctx, a->lvec, zz, ADD_VALUES, SCATTER_REVERSE));
4693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
470d4002b98SHong Zhang }
471d4002b98SHong Zhang
472d4002b98SHong Zhang /*
473d4002b98SHong Zhang This only works correctly for square matrices where the subblock A->A is the
474d4002b98SHong Zhang diagonal block
475d4002b98SHong Zhang */
MatGetDiagonal_MPISELL(Mat A,Vec v)476ba38deedSJacob Faibussowitsch static PetscErrorCode MatGetDiagonal_MPISELL(Mat A, Vec v)
477d71ae5a4SJacob Faibussowitsch {
478d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data;
479d4002b98SHong Zhang
480d4002b98SHong Zhang PetscFunctionBegin;
48108401ef6SPierre Jolivet PetscCheck(A->rmap->N == A->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Supports only square matrix where A->A is diag block");
482aed4548fSBarry 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");
4839566063dSJacob Faibussowitsch PetscCall(MatGetDiagonal(a->A, v));
4843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
485d4002b98SHong Zhang }
486d4002b98SHong Zhang
MatScale_MPISELL(Mat A,PetscScalar aa)487ba38deedSJacob Faibussowitsch static PetscErrorCode MatScale_MPISELL(Mat A, PetscScalar aa)
488d71ae5a4SJacob Faibussowitsch {
489d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data;
490d4002b98SHong Zhang
491d4002b98SHong Zhang PetscFunctionBegin;
4929566063dSJacob Faibussowitsch PetscCall(MatScale(a->A, aa));
4939566063dSJacob Faibussowitsch PetscCall(MatScale(a->B, aa));
4943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
495d4002b98SHong Zhang }
496d4002b98SHong Zhang
MatDestroy_MPISELL(Mat mat)497d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDestroy_MPISELL(Mat mat)
498d71ae5a4SJacob Faibussowitsch {
499d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)mat->data;
500d4002b98SHong Zhang
501d4002b98SHong Zhang PetscFunctionBegin;
5023ba16761SJacob Faibussowitsch PetscCall(PetscLogObjectState((PetscObject)mat, "Rows=%" PetscInt_FMT ", Cols=%" PetscInt_FMT, mat->rmap->N, mat->cmap->N));
5039566063dSJacob Faibussowitsch PetscCall(MatStashDestroy_Private(&mat->stash));
5049566063dSJacob Faibussowitsch PetscCall(VecDestroy(&sell->diag));
5059566063dSJacob Faibussowitsch PetscCall(MatDestroy(&sell->A));
5069566063dSJacob Faibussowitsch PetscCall(MatDestroy(&sell->B));
507d4002b98SHong Zhang #if defined(PETSC_USE_CTABLE)
508eec179cfSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&sell->colmap));
509d4002b98SHong Zhang #else
5109566063dSJacob Faibussowitsch PetscCall(PetscFree(sell->colmap));
511d4002b98SHong Zhang #endif
5129566063dSJacob Faibussowitsch PetscCall(PetscFree(sell->garray));
5139566063dSJacob Faibussowitsch PetscCall(VecDestroy(&sell->lvec));
5149566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&sell->Mvctx));
5159566063dSJacob Faibussowitsch PetscCall(PetscFree2(sell->rowvalues, sell->rowindices));
5169566063dSJacob Faibussowitsch PetscCall(PetscFree(sell->ld));
5179566063dSJacob Faibussowitsch PetscCall(PetscFree(mat->data));
518d4002b98SHong Zhang
5199566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)mat, NULL));
5209566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatStoreValues_C", NULL));
5219566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatRetrieveValues_C", NULL));
5229566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatIsTranspose_C", NULL));
5239566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatMPISELLSetPreallocation_C", NULL));
5249566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_mpisell_mpiaij_C", NULL));
525b5917f1bSHong Zhang #if defined(PETSC_HAVE_CUDA)
526b5917f1bSHong Zhang PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_mpisell_mpisellcuda_C", NULL));
527b5917f1bSHong Zhang #endif
5289566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDiagonalScaleLocal_C", NULL));
5293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
530d4002b98SHong Zhang }
531d4002b98SHong Zhang
532d4002b98SHong Zhang #include <petscdraw.h>
MatView_MPISELL_ASCIIorDraworSocket(Mat mat,PetscViewer viewer)533ba38deedSJacob Faibussowitsch static PetscErrorCode MatView_MPISELL_ASCIIorDraworSocket(Mat mat, PetscViewer viewer)
534d71ae5a4SJacob Faibussowitsch {
535d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)mat->data;
536d4002b98SHong Zhang PetscMPIInt rank = sell->rank, size = sell->size;
5379f196a02SMartin Diehl PetscBool isdraw, isascii, isbinary;
538d4002b98SHong Zhang PetscViewer sviewer;
539d4002b98SHong Zhang PetscViewerFormat format;
540d4002b98SHong Zhang
541d4002b98SHong Zhang PetscFunctionBegin;
5429566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
5439f196a02SMartin Diehl PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
5449566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
5459f196a02SMartin Diehl if (isascii) {
5469566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format));
547d4002b98SHong Zhang if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
548d4002b98SHong Zhang MatInfo info;
5496335e310SSatish Balay PetscInt *inodes;
550d4002b98SHong Zhang
5519566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)mat), &rank));
5529566063dSJacob Faibussowitsch PetscCall(MatGetInfo(mat, MAT_LOCAL, &info));
5539566063dSJacob Faibussowitsch PetscCall(MatInodeGetInodeSizes(sell->A, NULL, &inodes, NULL));
5549566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer));
555d4002b98SHong Zhang if (!inodes) {
5569371c9d4SSatish 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,
5579371c9d4SSatish Balay (PetscInt)info.nz_allocated, (PetscInt)info.memory));
558d4002b98SHong Zhang } else {
5599371c9d4SSatish 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,
5609371c9d4SSatish Balay (PetscInt)info.nz_allocated, (PetscInt)info.memory));
561d4002b98SHong Zhang }
5629566063dSJacob Faibussowitsch PetscCall(MatGetInfo(sell->A, MAT_LOCAL, &info));
5639566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] on-diagonal part: nz %" PetscInt_FMT " \n", rank, (PetscInt)info.nz_used));
5649566063dSJacob Faibussowitsch PetscCall(MatGetInfo(sell->B, MAT_LOCAL, &info));
5659566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] off-diagonal part: nz %" PetscInt_FMT " \n", rank, (PetscInt)info.nz_used));
5669566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer));
5679566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer));
5689566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Information on VecScatter used in matrix-vector product: \n"));
5699566063dSJacob Faibussowitsch PetscCall(VecScatterView(sell->Mvctx, viewer));
5703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
571d4002b98SHong Zhang } else if (format == PETSC_VIEWER_ASCII_INFO) {
572d4002b98SHong Zhang PetscInt inodecount, inodelimit, *inodes;
5739566063dSJacob Faibussowitsch PetscCall(MatInodeGetInodeSizes(sell->A, &inodecount, &inodes, &inodelimit));
574d4002b98SHong Zhang if (inodes) {
5759566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "using I-node (on process 0) routines: found %" PetscInt_FMT " nodes, limit used is %" PetscInt_FMT "\n", inodecount, inodelimit));
576d4002b98SHong Zhang } else {
5779566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "not using I-node (on process 0) routines\n"));
578d4002b98SHong Zhang }
5793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
580d4002b98SHong Zhang } else if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) {
5813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
582d4002b98SHong Zhang }
583d4002b98SHong Zhang } else if (isbinary) {
584d4002b98SHong Zhang if (size == 1) {
5859566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)sell->A, ((PetscObject)mat)->name));
5869566063dSJacob Faibussowitsch PetscCall(MatView(sell->A, viewer));
587d4002b98SHong Zhang } else {
5889566063dSJacob Faibussowitsch /* PetscCall(MatView_MPISELL_Binary(mat,viewer)); */
589d4002b98SHong Zhang }
5903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
591d4002b98SHong Zhang } else if (isdraw) {
592d4002b98SHong Zhang PetscDraw draw;
593d4002b98SHong Zhang PetscBool isnull;
5949566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
5959566063dSJacob Faibussowitsch PetscCall(PetscDrawIsNull(draw, &isnull));
5963ba16761SJacob Faibussowitsch if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
597d4002b98SHong Zhang }
598d4002b98SHong Zhang
599d4002b98SHong Zhang {
600d4002b98SHong Zhang /* assemble the entire matrix onto first processor. */
601d4002b98SHong Zhang Mat A;
602d4002b98SHong Zhang Mat_SeqSELL *Aloc;
603d4002b98SHong Zhang PetscInt M = mat->rmap->N, N = mat->cmap->N, *acolidx, row, col, i, j;
604d4002b98SHong Zhang MatScalar *aval;
605d4002b98SHong Zhang PetscBool isnonzero;
606d4002b98SHong Zhang
6079566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &A));
608dd400576SPatrick Sanan if (rank == 0) {
6099566063dSJacob Faibussowitsch PetscCall(MatSetSizes(A, M, N, M, N));
610d4002b98SHong Zhang } else {
6119566063dSJacob Faibussowitsch PetscCall(MatSetSizes(A, 0, 0, M, N));
612d4002b98SHong Zhang }
613d4002b98SHong Zhang /* This is just a temporary matrix, so explicitly using MATMPISELL is probably best */
6149566063dSJacob Faibussowitsch PetscCall(MatSetType(A, MATMPISELL));
6159566063dSJacob Faibussowitsch PetscCall(MatMPISELLSetPreallocation(A, 0, NULL, 0, NULL));
6169566063dSJacob Faibussowitsch PetscCall(MatSetOption(A, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_FALSE));
617d4002b98SHong Zhang
618d4002b98SHong Zhang /* copy over the A part */
619d4002b98SHong Zhang Aloc = (Mat_SeqSELL *)sell->A->data;
6209371c9d4SSatish Balay acolidx = Aloc->colidx;
6219371c9d4SSatish Balay aval = Aloc->val;
622d4002b98SHong Zhang for (i = 0; i < Aloc->totalslices; i++) { /* loop over slices */
623d4002b98SHong Zhang for (j = Aloc->sliidx[i]; j < Aloc->sliidx[i + 1]; j++) {
62407e43b41SHong Zhang isnonzero = (PetscBool)((j - Aloc->sliidx[i]) / Aloc->sliceheight < Aloc->rlen[i * Aloc->sliceheight + j % Aloc->sliceheight]);
625d4002b98SHong Zhang if (isnonzero) { /* check the mask bit */
62607e43b41SHong Zhang row = i * Aloc->sliceheight + j % Aloc->sliceheight + mat->rmap->rstart;
627d4002b98SHong Zhang col = *acolidx + mat->rmap->rstart;
6289566063dSJacob Faibussowitsch PetscCall(MatSetValues(A, 1, &row, 1, &col, aval, INSERT_VALUES));
629d4002b98SHong Zhang }
6309371c9d4SSatish Balay aval++;
6319371c9d4SSatish Balay acolidx++;
632d4002b98SHong Zhang }
633d4002b98SHong Zhang }
634d4002b98SHong Zhang
635d4002b98SHong Zhang /* copy over the B part */
636d4002b98SHong Zhang Aloc = (Mat_SeqSELL *)sell->B->data;
6379371c9d4SSatish Balay acolidx = Aloc->colidx;
6389371c9d4SSatish Balay aval = Aloc->val;
639d4002b98SHong Zhang for (i = 0; i < Aloc->totalslices; i++) {
640d4002b98SHong Zhang for (j = Aloc->sliidx[i]; j < Aloc->sliidx[i + 1]; j++) {
64107e43b41SHong Zhang isnonzero = (PetscBool)((j - Aloc->sliidx[i]) / Aloc->sliceheight < Aloc->rlen[i * Aloc->sliceheight + j % Aloc->sliceheight]);
642d4002b98SHong Zhang if (isnonzero) {
64307e43b41SHong Zhang row = i * Aloc->sliceheight + j % Aloc->sliceheight + mat->rmap->rstart;
644d4002b98SHong Zhang col = sell->garray[*acolidx];
6459566063dSJacob Faibussowitsch PetscCall(MatSetValues(A, 1, &row, 1, &col, aval, INSERT_VALUES));
646d4002b98SHong Zhang }
6479371c9d4SSatish Balay aval++;
6489371c9d4SSatish Balay acolidx++;
649d4002b98SHong Zhang }
650d4002b98SHong Zhang }
651d4002b98SHong Zhang
6529566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
6539566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
654d4002b98SHong Zhang /*
655d4002b98SHong Zhang Everyone has to call to draw the matrix since the graphics waits are
656d4002b98SHong Zhang synchronized across all processors that share the PetscDraw object
657d4002b98SHong Zhang */
6589566063dSJacob Faibussowitsch PetscCall(PetscViewerGetSubViewer(viewer, PETSC_COMM_SELF, &sviewer));
659dd400576SPatrick Sanan if (rank == 0) {
660f4f49eeaSPierre Jolivet PetscCall(PetscObjectSetName((PetscObject)((Mat_MPISELL *)A->data)->A, ((PetscObject)mat)->name));
661f4f49eeaSPierre Jolivet PetscCall(MatView_SeqSELL(((Mat_MPISELL *)A->data)->A, sviewer));
662d4002b98SHong Zhang }
6639566063dSJacob Faibussowitsch PetscCall(PetscViewerRestoreSubViewer(viewer, PETSC_COMM_SELF, &sviewer));
6649566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A));
665d4002b98SHong Zhang }
6663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
667d4002b98SHong Zhang }
668d4002b98SHong Zhang
MatView_MPISELL(Mat mat,PetscViewer viewer)669ba38deedSJacob Faibussowitsch static PetscErrorCode MatView_MPISELL(Mat mat, PetscViewer viewer)
670d71ae5a4SJacob Faibussowitsch {
6719f196a02SMartin Diehl PetscBool isascii, isdraw, issocket, isbinary;
672d4002b98SHong Zhang
673d4002b98SHong Zhang PetscFunctionBegin;
6749f196a02SMartin Diehl PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
6759566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
6769566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
6779566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSOCKET, &issocket));
6789f196a02SMartin Diehl if (isascii || isdraw || isbinary || issocket) PetscCall(MatView_MPISELL_ASCIIorDraworSocket(mat, viewer));
6793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
680d4002b98SHong Zhang }
681d4002b98SHong Zhang
MatGetGhosts_MPISELL(Mat mat,PetscInt * nghosts,const PetscInt * ghosts[])682ba38deedSJacob Faibussowitsch static PetscErrorCode MatGetGhosts_MPISELL(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[])
683d71ae5a4SJacob Faibussowitsch {
684d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)mat->data;
685d4002b98SHong Zhang
686d4002b98SHong Zhang PetscFunctionBegin;
6879566063dSJacob Faibussowitsch PetscCall(MatGetSize(sell->B, NULL, nghosts));
688d4002b98SHong Zhang if (ghosts) *ghosts = sell->garray;
6893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
690d4002b98SHong Zhang }
691d4002b98SHong Zhang
MatGetInfo_MPISELL(Mat matin,MatInfoType flag,MatInfo * info)692ba38deedSJacob Faibussowitsch static PetscErrorCode MatGetInfo_MPISELL(Mat matin, MatInfoType flag, MatInfo *info)
693d71ae5a4SJacob Faibussowitsch {
694d4002b98SHong Zhang Mat_MPISELL *mat = (Mat_MPISELL *)matin->data;
695d4002b98SHong Zhang Mat A = mat->A, B = mat->B;
6963966268fSBarry Smith PetscLogDouble isend[5], irecv[5];
697d4002b98SHong Zhang
698d4002b98SHong Zhang PetscFunctionBegin;
699d4002b98SHong Zhang info->block_size = 1.0;
7009566063dSJacob Faibussowitsch PetscCall(MatGetInfo(A, MAT_LOCAL, info));
701d4002b98SHong Zhang
7029371c9d4SSatish Balay isend[0] = info->nz_used;
7039371c9d4SSatish Balay isend[1] = info->nz_allocated;
7049371c9d4SSatish Balay isend[2] = info->nz_unneeded;
7059371c9d4SSatish Balay isend[3] = info->memory;
7069371c9d4SSatish Balay isend[4] = info->mallocs;
707d4002b98SHong Zhang
7089566063dSJacob Faibussowitsch PetscCall(MatGetInfo(B, MAT_LOCAL, info));
709d4002b98SHong Zhang
7109371c9d4SSatish Balay isend[0] += info->nz_used;
7119371c9d4SSatish Balay isend[1] += info->nz_allocated;
7129371c9d4SSatish Balay isend[2] += info->nz_unneeded;
7139371c9d4SSatish Balay isend[3] += info->memory;
7149371c9d4SSatish Balay isend[4] += info->mallocs;
715d4002b98SHong Zhang if (flag == MAT_LOCAL) {
716d4002b98SHong Zhang info->nz_used = isend[0];
717d4002b98SHong Zhang info->nz_allocated = isend[1];
718d4002b98SHong Zhang info->nz_unneeded = isend[2];
719d4002b98SHong Zhang info->memory = isend[3];
720d4002b98SHong Zhang info->mallocs = isend[4];
721d4002b98SHong Zhang } else if (flag == MAT_GLOBAL_MAX) {
722462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(isend, irecv, 5, MPIU_PETSCLOGDOUBLE, MPI_MAX, PetscObjectComm((PetscObject)matin)));
723d4002b98SHong Zhang
724d4002b98SHong Zhang info->nz_used = irecv[0];
725d4002b98SHong Zhang info->nz_allocated = irecv[1];
726d4002b98SHong Zhang info->nz_unneeded = irecv[2];
727d4002b98SHong Zhang info->memory = irecv[3];
728d4002b98SHong Zhang info->mallocs = irecv[4];
729d4002b98SHong Zhang } else if (flag == MAT_GLOBAL_SUM) {
730462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(isend, irecv, 5, MPIU_PETSCLOGDOUBLE, MPI_SUM, PetscObjectComm((PetscObject)matin)));
731d4002b98SHong Zhang
732d4002b98SHong Zhang info->nz_used = irecv[0];
733d4002b98SHong Zhang info->nz_allocated = irecv[1];
734d4002b98SHong Zhang info->nz_unneeded = irecv[2];
735d4002b98SHong Zhang info->memory = irecv[3];
736d4002b98SHong Zhang info->mallocs = irecv[4];
737d4002b98SHong Zhang }
738d4002b98SHong Zhang info->fill_ratio_given = 0; /* no parallel LU/ILU/Cholesky */
739d4002b98SHong Zhang info->fill_ratio_needed = 0;
740d4002b98SHong Zhang info->factor_mallocs = 0;
7413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
742d4002b98SHong Zhang }
743d4002b98SHong Zhang
MatSetOption_MPISELL(Mat A,MatOption op,PetscBool flg)74443b34f9dSJacob Faibussowitsch static PetscErrorCode MatSetOption_MPISELL(Mat A, MatOption op, PetscBool flg)
745d71ae5a4SJacob Faibussowitsch {
746d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data;
747d4002b98SHong Zhang
748d4002b98SHong Zhang PetscFunctionBegin;
749d4002b98SHong Zhang switch (op) {
750d4002b98SHong Zhang case MAT_NEW_NONZERO_LOCATIONS:
751d4002b98SHong Zhang case MAT_NEW_NONZERO_ALLOCATION_ERR:
752d4002b98SHong Zhang case MAT_UNUSED_NONZERO_LOCATION_ERR:
753d4002b98SHong Zhang case MAT_KEEP_NONZERO_PATTERN:
754d4002b98SHong Zhang case MAT_NEW_NONZERO_LOCATION_ERR:
755d4002b98SHong Zhang case MAT_USE_INODES:
756d4002b98SHong Zhang case MAT_IGNORE_ZERO_ENTRIES:
757d4002b98SHong Zhang MatCheckPreallocated(A, 1);
7589566063dSJacob Faibussowitsch PetscCall(MatSetOption(a->A, op, flg));
7599566063dSJacob Faibussowitsch PetscCall(MatSetOption(a->B, op, flg));
760d4002b98SHong Zhang break;
761d4002b98SHong Zhang case MAT_ROW_ORIENTED:
762d4002b98SHong Zhang MatCheckPreallocated(A, 1);
763d4002b98SHong Zhang a->roworiented = flg;
764d4002b98SHong Zhang
7659566063dSJacob Faibussowitsch PetscCall(MatSetOption(a->A, op, flg));
7669566063dSJacob Faibussowitsch PetscCall(MatSetOption(a->B, op, flg));
767d4002b98SHong Zhang break;
768d71ae5a4SJacob Faibussowitsch case MAT_IGNORE_OFF_PROC_ENTRIES:
769d71ae5a4SJacob Faibussowitsch a->donotstash = flg;
770d71ae5a4SJacob Faibussowitsch break;
771d4002b98SHong Zhang case MAT_SYMMETRIC:
772d4002b98SHong Zhang MatCheckPreallocated(A, 1);
7739566063dSJacob Faibussowitsch PetscCall(MatSetOption(a->A, op, flg));
774d4002b98SHong Zhang break;
775d4002b98SHong Zhang case MAT_STRUCTURALLY_SYMMETRIC:
776d4002b98SHong Zhang MatCheckPreallocated(A, 1);
7779566063dSJacob Faibussowitsch PetscCall(MatSetOption(a->A, op, flg));
778d4002b98SHong Zhang break;
779d4002b98SHong Zhang case MAT_HERMITIAN:
780d4002b98SHong Zhang MatCheckPreallocated(A, 1);
7819566063dSJacob Faibussowitsch PetscCall(MatSetOption(a->A, op, flg));
782d4002b98SHong Zhang break;
783d4002b98SHong Zhang case MAT_SYMMETRY_ETERNAL:
784d4002b98SHong Zhang MatCheckPreallocated(A, 1);
7859566063dSJacob Faibussowitsch PetscCall(MatSetOption(a->A, op, flg));
786d4002b98SHong Zhang break;
787b94d7dedSBarry Smith case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
788b94d7dedSBarry Smith MatCheckPreallocated(A, 1);
789b94d7dedSBarry Smith PetscCall(MatSetOption(a->A, op, flg));
790b94d7dedSBarry Smith break;
791d71ae5a4SJacob Faibussowitsch default:
792888c827cSStefano Zampini break;
793d4002b98SHong Zhang }
7943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
795d4002b98SHong Zhang }
796d4002b98SHong Zhang
MatDiagonalScale_MPISELL(Mat mat,Vec ll,Vec rr)797ba38deedSJacob Faibussowitsch static PetscErrorCode MatDiagonalScale_MPISELL(Mat mat, Vec ll, Vec rr)
798d71ae5a4SJacob Faibussowitsch {
799d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)mat->data;
800d4002b98SHong Zhang Mat a = sell->A, b = sell->B;
801d4002b98SHong Zhang PetscInt s1, s2, s3;
802d4002b98SHong Zhang
803d4002b98SHong Zhang PetscFunctionBegin;
8049566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(mat, &s2, &s3));
805d4002b98SHong Zhang if (rr) {
8069566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(rr, &s1));
80708401ef6SPierre Jolivet PetscCheck(s1 == s3, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "right vector non-conforming local size");
808d4002b98SHong Zhang /* Overlap communication with computation. */
8099566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(sell->Mvctx, rr, sell->lvec, INSERT_VALUES, SCATTER_FORWARD));
810d4002b98SHong Zhang }
811d4002b98SHong Zhang if (ll) {
8129566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(ll, &s1));
81308401ef6SPierre Jolivet PetscCheck(s1 == s2, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "left vector non-conforming local size");
814dbbe0bcdSBarry Smith PetscUseTypeMethod(b, diagonalscale, ll, NULL);
815d4002b98SHong Zhang }
816d4002b98SHong Zhang /* scale the diagonal block */
817dbbe0bcdSBarry Smith PetscUseTypeMethod(a, diagonalscale, ll, rr);
818d4002b98SHong Zhang
819d4002b98SHong Zhang if (rr) {
820d4002b98SHong Zhang /* Do a scatter end and then right scale the off-diagonal block */
8219566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(sell->Mvctx, rr, sell->lvec, INSERT_VALUES, SCATTER_FORWARD));
822dbbe0bcdSBarry Smith PetscUseTypeMethod(b, diagonalscale, NULL, sell->lvec);
823d4002b98SHong Zhang }
8243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
825d4002b98SHong Zhang }
826d4002b98SHong Zhang
MatSetUnfactored_MPISELL(Mat A)827ba38deedSJacob Faibussowitsch static PetscErrorCode MatSetUnfactored_MPISELL(Mat A)
828d71ae5a4SJacob Faibussowitsch {
829d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data;
830d4002b98SHong Zhang
831d4002b98SHong Zhang PetscFunctionBegin;
8329566063dSJacob Faibussowitsch PetscCall(MatSetUnfactored(a->A));
8333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
834d4002b98SHong Zhang }
835d4002b98SHong Zhang
MatEqual_MPISELL(Mat A,Mat B,PetscBool * flag)836ba38deedSJacob Faibussowitsch static PetscErrorCode MatEqual_MPISELL(Mat A, Mat B, PetscBool *flag)
837d71ae5a4SJacob Faibussowitsch {
838d4002b98SHong Zhang Mat_MPISELL *matB = (Mat_MPISELL *)B->data, *matA = (Mat_MPISELL *)A->data;
839d4002b98SHong Zhang Mat a, b, c, d;
840d4002b98SHong Zhang PetscBool flg;
841d4002b98SHong Zhang
842d4002b98SHong Zhang PetscFunctionBegin;
8439371c9d4SSatish Balay a = matA->A;
8449371c9d4SSatish Balay b = matA->B;
8459371c9d4SSatish Balay c = matB->A;
8469371c9d4SSatish Balay d = matB->B;
847d4002b98SHong Zhang
8489566063dSJacob Faibussowitsch PetscCall(MatEqual(a, c, &flg));
84948a46eb9SPierre Jolivet if (flg) PetscCall(MatEqual(b, d, &flg));
8505440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(&flg, flag, 1, MPI_C_BOOL, MPI_LAND, PetscObjectComm((PetscObject)A)));
8513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
852d4002b98SHong Zhang }
853d4002b98SHong Zhang
MatCopy_MPISELL(Mat A,Mat B,MatStructure str)854ba38deedSJacob Faibussowitsch static PetscErrorCode MatCopy_MPISELL(Mat A, Mat B, MatStructure str)
855d71ae5a4SJacob Faibussowitsch {
856d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data;
857d4002b98SHong Zhang Mat_MPISELL *b = (Mat_MPISELL *)B->data;
858d4002b98SHong Zhang
859d4002b98SHong Zhang PetscFunctionBegin;
860d4002b98SHong Zhang /* If the two matrices don't have the same copy implementation, they aren't compatible for fast copy. */
861d4002b98SHong Zhang if ((str != SAME_NONZERO_PATTERN) || (A->ops->copy != B->ops->copy)) {
862d4002b98SHong Zhang /* because of the column compression in the off-processor part of the matrix a->B,
863d4002b98SHong Zhang the number of columns in a->B and b->B may be different, hence we cannot call
864d4002b98SHong Zhang the MatCopy() directly on the two parts. If need be, we can provide a more
865d4002b98SHong Zhang efficient copy than the MatCopy_Basic() by first uncompressing the a->B matrices
866d4002b98SHong Zhang then copying the submatrices */
8679566063dSJacob Faibussowitsch PetscCall(MatCopy_Basic(A, B, str));
868d4002b98SHong Zhang } else {
8699566063dSJacob Faibussowitsch PetscCall(MatCopy(a->A, b->A, str));
8709566063dSJacob Faibussowitsch PetscCall(MatCopy(a->B, b->B, str));
871d4002b98SHong Zhang }
8723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
873d4002b98SHong Zhang }
874d4002b98SHong Zhang
MatSetUp_MPISELL(Mat A)875ba38deedSJacob Faibussowitsch static PetscErrorCode MatSetUp_MPISELL(Mat A)
876d71ae5a4SJacob Faibussowitsch {
877d4002b98SHong Zhang PetscFunctionBegin;
8789566063dSJacob Faibussowitsch PetscCall(MatMPISELLSetPreallocation(A, PETSC_DEFAULT, NULL, PETSC_DEFAULT, NULL));
8793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
880d4002b98SHong Zhang }
881d4002b98SHong Zhang
MatConjugate_MPISELL(Mat mat)882ba38deedSJacob Faibussowitsch static PetscErrorCode MatConjugate_MPISELL(Mat mat)
883d71ae5a4SJacob Faibussowitsch {
884d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)mat->data;
885d4002b98SHong Zhang
886*65d0d443SPierre Jolivet PetscFunctionBegin;
8879566063dSJacob Faibussowitsch PetscCall(MatConjugate_SeqSELL(sell->A));
8889566063dSJacob Faibussowitsch PetscCall(MatConjugate_SeqSELL(sell->B));
8893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
890d4002b98SHong Zhang }
891d4002b98SHong Zhang
MatInvertBlockDiagonal_MPISELL(Mat A,const PetscScalar ** values)892ba38deedSJacob Faibussowitsch static PetscErrorCode MatInvertBlockDiagonal_MPISELL(Mat A, const PetscScalar **values)
893d71ae5a4SJacob Faibussowitsch {
894d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data;
895d4002b98SHong Zhang
896d4002b98SHong Zhang PetscFunctionBegin;
8979566063dSJacob Faibussowitsch PetscCall(MatInvertBlockDiagonal(a->A, values));
898d4002b98SHong Zhang A->factorerrortype = a->A->factorerrortype;
8993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
900d4002b98SHong Zhang }
901d4002b98SHong Zhang
MatSetRandom_MPISELL(Mat x,PetscRandom rctx)902d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetRandom_MPISELL(Mat x, PetscRandom rctx)
903d71ae5a4SJacob Faibussowitsch {
904d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)x->data;
905d4002b98SHong Zhang
906d4002b98SHong Zhang PetscFunctionBegin;
9079566063dSJacob Faibussowitsch PetscCall(MatSetRandom(sell->A, rctx));
9089566063dSJacob Faibussowitsch PetscCall(MatSetRandom(sell->B, rctx));
9099566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY));
9109566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY));
9113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
912d4002b98SHong Zhang }
913d4002b98SHong Zhang
MatSetFromOptions_MPISELL(Mat A,PetscOptionItems PetscOptionsObject)914ce78bad3SBarry Smith static PetscErrorCode MatSetFromOptions_MPISELL(Mat A, PetscOptionItems PetscOptionsObject)
915d71ae5a4SJacob Faibussowitsch {
916d4002b98SHong Zhang PetscFunctionBegin;
917d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "MPISELL options");
918d0609cedSBarry Smith PetscOptionsHeadEnd();
9193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
920d4002b98SHong Zhang }
921d4002b98SHong Zhang
MatShift_MPISELL(Mat Y,PetscScalar a)922ba38deedSJacob Faibussowitsch static PetscErrorCode MatShift_MPISELL(Mat Y, PetscScalar a)
923d71ae5a4SJacob Faibussowitsch {
924d4002b98SHong Zhang Mat_MPISELL *msell = (Mat_MPISELL *)Y->data;
925d4002b98SHong Zhang Mat_SeqSELL *sell = (Mat_SeqSELL *)msell->A->data;
926d4002b98SHong Zhang
927d4002b98SHong Zhang PetscFunctionBegin;
928d4002b98SHong Zhang if (!Y->preallocated) {
9299566063dSJacob Faibussowitsch PetscCall(MatMPISELLSetPreallocation(Y, 1, NULL, 0, NULL));
930d4002b98SHong Zhang } else if (!sell->nz) {
931d4002b98SHong Zhang PetscInt nonew = sell->nonew;
9329566063dSJacob Faibussowitsch PetscCall(MatSeqSELLSetPreallocation(msell->A, 1, NULL));
933d4002b98SHong Zhang sell->nonew = nonew;
934d4002b98SHong Zhang }
9359566063dSJacob Faibussowitsch PetscCall(MatShift_Basic(Y, a));
9363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
937d4002b98SHong Zhang }
938d4002b98SHong Zhang
MatGetDiagonalBlock_MPISELL(Mat A,Mat * a)939ba38deedSJacob Faibussowitsch static PetscErrorCode MatGetDiagonalBlock_MPISELL(Mat A, Mat *a)
940d71ae5a4SJacob Faibussowitsch {
941d4002b98SHong Zhang PetscFunctionBegin;
942d4002b98SHong Zhang *a = ((Mat_MPISELL *)A->data)->A;
9433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
944d4002b98SHong Zhang }
945d4002b98SHong Zhang
MatStoreValues_MPISELL(Mat mat)94643b34f9dSJacob Faibussowitsch static PetscErrorCode MatStoreValues_MPISELL(Mat mat)
94743b34f9dSJacob Faibussowitsch {
94843b34f9dSJacob Faibussowitsch Mat_MPISELL *sell = (Mat_MPISELL *)mat->data;
94943b34f9dSJacob Faibussowitsch
95043b34f9dSJacob Faibussowitsch PetscFunctionBegin;
95143b34f9dSJacob Faibussowitsch PetscCall(MatStoreValues(sell->A));
95243b34f9dSJacob Faibussowitsch PetscCall(MatStoreValues(sell->B));
95343b34f9dSJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
95443b34f9dSJacob Faibussowitsch }
95543b34f9dSJacob Faibussowitsch
MatRetrieveValues_MPISELL(Mat mat)95643b34f9dSJacob Faibussowitsch static PetscErrorCode MatRetrieveValues_MPISELL(Mat mat)
95743b34f9dSJacob Faibussowitsch {
95843b34f9dSJacob Faibussowitsch Mat_MPISELL *sell = (Mat_MPISELL *)mat->data;
95943b34f9dSJacob Faibussowitsch
96043b34f9dSJacob Faibussowitsch PetscFunctionBegin;
96143b34f9dSJacob Faibussowitsch PetscCall(MatRetrieveValues(sell->A));
96243b34f9dSJacob Faibussowitsch PetscCall(MatRetrieveValues(sell->B));
96343b34f9dSJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
96443b34f9dSJacob Faibussowitsch }
96543b34f9dSJacob Faibussowitsch
MatMPISELLSetPreallocation_MPISELL(Mat B,PetscInt d_rlenmax,const PetscInt d_rlen[],PetscInt o_rlenmax,const PetscInt o_rlen[])96643b34f9dSJacob Faibussowitsch static PetscErrorCode MatMPISELLSetPreallocation_MPISELL(Mat B, PetscInt d_rlenmax, const PetscInt d_rlen[], PetscInt o_rlenmax, const PetscInt o_rlen[])
96743b34f9dSJacob Faibussowitsch {
96843b34f9dSJacob Faibussowitsch Mat_MPISELL *b;
96943b34f9dSJacob Faibussowitsch
97043b34f9dSJacob Faibussowitsch PetscFunctionBegin;
97143b34f9dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->rmap));
97243b34f9dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->cmap));
97343b34f9dSJacob Faibussowitsch b = (Mat_MPISELL *)B->data;
97443b34f9dSJacob Faibussowitsch
97543b34f9dSJacob Faibussowitsch if (!B->preallocated) {
97643b34f9dSJacob Faibussowitsch /* Explicitly create 2 MATSEQSELL matrices. */
97743b34f9dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &b->A));
97843b34f9dSJacob Faibussowitsch PetscCall(MatSetSizes(b->A, B->rmap->n, B->cmap->n, B->rmap->n, B->cmap->n));
97943b34f9dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(b->A, B, B));
98043b34f9dSJacob Faibussowitsch PetscCall(MatSetType(b->A, MATSEQSELL));
98143b34f9dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &b->B));
98243b34f9dSJacob Faibussowitsch PetscCall(MatSetSizes(b->B, B->rmap->n, B->cmap->N, B->rmap->n, B->cmap->N));
98343b34f9dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(b->B, B, B));
98443b34f9dSJacob Faibussowitsch PetscCall(MatSetType(b->B, MATSEQSELL));
98543b34f9dSJacob Faibussowitsch }
98643b34f9dSJacob Faibussowitsch
98743b34f9dSJacob Faibussowitsch PetscCall(MatSeqSELLSetPreallocation(b->A, d_rlenmax, d_rlen));
98843b34f9dSJacob Faibussowitsch PetscCall(MatSeqSELLSetPreallocation(b->B, o_rlenmax, o_rlen));
98943b34f9dSJacob Faibussowitsch B->preallocated = PETSC_TRUE;
99043b34f9dSJacob Faibussowitsch B->was_assembled = PETSC_FALSE;
99143b34f9dSJacob Faibussowitsch /*
99243b34f9dSJacob Faibussowitsch critical for MatAssemblyEnd to work.
99343b34f9dSJacob Faibussowitsch MatAssemblyBegin checks it to set up was_assembled
99443b34f9dSJacob Faibussowitsch and MatAssemblyEnd checks was_assembled to determine whether to build garray
99543b34f9dSJacob Faibussowitsch */
99643b34f9dSJacob Faibussowitsch B->assembled = PETSC_FALSE;
99743b34f9dSJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
99843b34f9dSJacob Faibussowitsch }
99943b34f9dSJacob Faibussowitsch
MatDuplicate_MPISELL(Mat matin,MatDuplicateOption cpvalues,Mat * newmat)100043b34f9dSJacob Faibussowitsch static PetscErrorCode MatDuplicate_MPISELL(Mat matin, MatDuplicateOption cpvalues, Mat *newmat)
100143b34f9dSJacob Faibussowitsch {
100243b34f9dSJacob Faibussowitsch Mat mat;
100343b34f9dSJacob Faibussowitsch Mat_MPISELL *a, *oldmat = (Mat_MPISELL *)matin->data;
100443b34f9dSJacob Faibussowitsch
100543b34f9dSJacob Faibussowitsch PetscFunctionBegin;
100643b34f9dSJacob Faibussowitsch *newmat = NULL;
100743b34f9dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)matin), &mat));
100843b34f9dSJacob Faibussowitsch PetscCall(MatSetSizes(mat, matin->rmap->n, matin->cmap->n, matin->rmap->N, matin->cmap->N));
100943b34f9dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(mat, matin, matin));
101043b34f9dSJacob Faibussowitsch PetscCall(MatSetType(mat, ((PetscObject)matin)->type_name));
101143b34f9dSJacob Faibussowitsch a = (Mat_MPISELL *)mat->data;
101243b34f9dSJacob Faibussowitsch
101343b34f9dSJacob Faibussowitsch mat->factortype = matin->factortype;
101443b34f9dSJacob Faibussowitsch mat->assembled = PETSC_TRUE;
101543b34f9dSJacob Faibussowitsch mat->insertmode = NOT_SET_VALUES;
101643b34f9dSJacob Faibussowitsch mat->preallocated = PETSC_TRUE;
101743b34f9dSJacob Faibussowitsch
101843b34f9dSJacob Faibussowitsch a->size = oldmat->size;
101943b34f9dSJacob Faibussowitsch a->rank = oldmat->rank;
102043b34f9dSJacob Faibussowitsch a->donotstash = oldmat->donotstash;
102143b34f9dSJacob Faibussowitsch a->roworiented = oldmat->roworiented;
102243b34f9dSJacob Faibussowitsch a->rowindices = NULL;
102343b34f9dSJacob Faibussowitsch a->rowvalues = NULL;
102443b34f9dSJacob Faibussowitsch a->getrowactive = PETSC_FALSE;
102543b34f9dSJacob Faibussowitsch
102643b34f9dSJacob Faibussowitsch PetscCall(PetscLayoutReference(matin->rmap, &mat->rmap));
102743b34f9dSJacob Faibussowitsch PetscCall(PetscLayoutReference(matin->cmap, &mat->cmap));
102843b34f9dSJacob Faibussowitsch
102943b34f9dSJacob Faibussowitsch if (oldmat->colmap) {
103043b34f9dSJacob Faibussowitsch #if defined(PETSC_USE_CTABLE)
103143b34f9dSJacob Faibussowitsch PetscCall(PetscHMapIDuplicate(oldmat->colmap, &a->colmap));
103243b34f9dSJacob Faibussowitsch #else
103343b34f9dSJacob Faibussowitsch PetscCall(PetscMalloc1(mat->cmap->N, &a->colmap));
103443b34f9dSJacob Faibussowitsch PetscCall(PetscArraycpy(a->colmap, oldmat->colmap, mat->cmap->N));
103543b34f9dSJacob Faibussowitsch #endif
103643b34f9dSJacob Faibussowitsch } else a->colmap = NULL;
103743b34f9dSJacob Faibussowitsch if (oldmat->garray) {
103843b34f9dSJacob Faibussowitsch PetscInt len;
103943b34f9dSJacob Faibussowitsch len = oldmat->B->cmap->n;
104043b34f9dSJacob Faibussowitsch PetscCall(PetscMalloc1(len + 1, &a->garray));
104143b34f9dSJacob Faibussowitsch if (len) PetscCall(PetscArraycpy(a->garray, oldmat->garray, len));
104243b34f9dSJacob Faibussowitsch } else a->garray = NULL;
104343b34f9dSJacob Faibussowitsch
104443b34f9dSJacob Faibussowitsch PetscCall(VecDuplicate(oldmat->lvec, &a->lvec));
104543b34f9dSJacob Faibussowitsch PetscCall(VecScatterCopy(oldmat->Mvctx, &a->Mvctx));
104643b34f9dSJacob Faibussowitsch PetscCall(MatDuplicate(oldmat->A, cpvalues, &a->A));
104743b34f9dSJacob Faibussowitsch PetscCall(MatDuplicate(oldmat->B, cpvalues, &a->B));
104843b34f9dSJacob Faibussowitsch PetscCall(PetscFunctionListDuplicate(((PetscObject)matin)->qlist, &((PetscObject)mat)->qlist));
104943b34f9dSJacob Faibussowitsch *newmat = mat;
105043b34f9dSJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
105143b34f9dSJacob Faibussowitsch }
105243b34f9dSJacob Faibussowitsch
105343b34f9dSJacob Faibussowitsch static const struct _MatOps MatOps_Values = {MatSetValues_MPISELL,
1054f4259b30SLisandro Dalcin NULL,
1055f4259b30SLisandro Dalcin NULL,
1056d4002b98SHong Zhang MatMult_MPISELL,
1057d4002b98SHong Zhang /* 4*/ MatMultAdd_MPISELL,
1058d4002b98SHong Zhang MatMultTranspose_MPISELL,
1059d4002b98SHong Zhang MatMultTransposeAdd_MPISELL,
1060f4259b30SLisandro Dalcin NULL,
1061f4259b30SLisandro Dalcin NULL,
1062f4259b30SLisandro Dalcin NULL,
1063f4259b30SLisandro Dalcin /*10*/ NULL,
1064f4259b30SLisandro Dalcin NULL,
1065f4259b30SLisandro Dalcin NULL,
1066d4002b98SHong Zhang MatSOR_MPISELL,
1067f4259b30SLisandro Dalcin NULL,
1068d4002b98SHong Zhang /*15*/ MatGetInfo_MPISELL,
1069d4002b98SHong Zhang MatEqual_MPISELL,
1070d4002b98SHong Zhang MatGetDiagonal_MPISELL,
1071d4002b98SHong Zhang MatDiagonalScale_MPISELL,
1072f4259b30SLisandro Dalcin NULL,
1073d4002b98SHong Zhang /*20*/ MatAssemblyBegin_MPISELL,
1074d4002b98SHong Zhang MatAssemblyEnd_MPISELL,
1075d4002b98SHong Zhang MatSetOption_MPISELL,
1076d4002b98SHong Zhang MatZeroEntries_MPISELL,
1077f4259b30SLisandro Dalcin /*24*/ NULL,
1078f4259b30SLisandro Dalcin NULL,
1079f4259b30SLisandro Dalcin NULL,
1080f4259b30SLisandro Dalcin NULL,
1081f4259b30SLisandro Dalcin NULL,
1082d4002b98SHong Zhang /*29*/ MatSetUp_MPISELL,
1083f4259b30SLisandro Dalcin NULL,
1084f4259b30SLisandro Dalcin NULL,
1085d4002b98SHong Zhang MatGetDiagonalBlock_MPISELL,
1086f4259b30SLisandro Dalcin NULL,
1087d4002b98SHong Zhang /*34*/ MatDuplicate_MPISELL,
1088f4259b30SLisandro Dalcin NULL,
1089f4259b30SLisandro Dalcin NULL,
1090f4259b30SLisandro Dalcin NULL,
1091f4259b30SLisandro Dalcin NULL,
1092f4259b30SLisandro Dalcin /*39*/ NULL,
1093f4259b30SLisandro Dalcin NULL,
1094f4259b30SLisandro Dalcin NULL,
1095d4002b98SHong Zhang MatGetValues_MPISELL,
1096d4002b98SHong Zhang MatCopy_MPISELL,
1097f4259b30SLisandro Dalcin /*44*/ NULL,
1098d4002b98SHong Zhang MatScale_MPISELL,
1099d4002b98SHong Zhang MatShift_MPISELL,
1100d4002b98SHong Zhang MatDiagonalSet_MPISELL,
1101f4259b30SLisandro Dalcin NULL,
1102d4002b98SHong Zhang /*49*/ MatSetRandom_MPISELL,
1103f4259b30SLisandro Dalcin NULL,
1104f4259b30SLisandro Dalcin NULL,
1105f4259b30SLisandro Dalcin NULL,
1106f4259b30SLisandro Dalcin NULL,
1107d4002b98SHong Zhang /*54*/ MatFDColoringCreate_MPIXAIJ,
1108f4259b30SLisandro Dalcin NULL,
1109d4002b98SHong Zhang MatSetUnfactored_MPISELL,
1110f4259b30SLisandro Dalcin NULL,
1111f4259b30SLisandro Dalcin NULL,
1112f4259b30SLisandro Dalcin /*59*/ NULL,
1113d4002b98SHong Zhang MatDestroy_MPISELL,
1114d4002b98SHong Zhang MatView_MPISELL,
1115f4259b30SLisandro Dalcin NULL,
1116f4259b30SLisandro Dalcin NULL,
1117f4259b30SLisandro Dalcin /*64*/ NULL,
1118f4259b30SLisandro Dalcin NULL,
1119f4259b30SLisandro Dalcin NULL,
1120f4259b30SLisandro Dalcin NULL,
1121f4259b30SLisandro Dalcin NULL,
1122f4259b30SLisandro Dalcin /*69*/ NULL,
1123f4259b30SLisandro Dalcin NULL,
1124f4259b30SLisandro Dalcin NULL,
11258bb0f5c6SPierre Jolivet MatFDColoringApply_AIJ, /* reuse AIJ function */
1126d4002b98SHong Zhang MatSetFromOptions_MPISELL,
1127f4259b30SLisandro Dalcin NULL,
11288bb0f5c6SPierre Jolivet /*75*/ NULL,
11298bb0f5c6SPierre Jolivet NULL,
11308bb0f5c6SPierre Jolivet NULL,
1131f4259b30SLisandro Dalcin NULL,
1132f4259b30SLisandro Dalcin NULL,
1133f4259b30SLisandro Dalcin /*80*/ NULL,
1134f4259b30SLisandro Dalcin NULL,
1135f4259b30SLisandro Dalcin NULL,
1136f4259b30SLisandro Dalcin /*83*/ NULL,
1137f4259b30SLisandro Dalcin NULL,
1138f4259b30SLisandro Dalcin NULL,
1139f4259b30SLisandro Dalcin NULL,
1140f4259b30SLisandro Dalcin NULL,
1141f4259b30SLisandro Dalcin NULL,
1142f4259b30SLisandro Dalcin /*89*/ NULL,
1143f4259b30SLisandro Dalcin NULL,
1144f4259b30SLisandro Dalcin NULL,
1145f4259b30SLisandro Dalcin NULL,
11468bb0f5c6SPierre Jolivet MatConjugate_MPISELL,
1147f4259b30SLisandro Dalcin /*94*/ NULL,
1148f4259b30SLisandro Dalcin NULL,
1149bb35897eSPierre Jolivet NULL,
1150bb35897eSPierre Jolivet NULL,
1151f4259b30SLisandro Dalcin NULL,
1152f4259b30SLisandro Dalcin /*99*/ NULL,
1153f4259b30SLisandro Dalcin NULL,
1154f4259b30SLisandro Dalcin NULL,
1155f4259b30SLisandro Dalcin NULL,
1156f4259b30SLisandro Dalcin NULL,
1157421480d9SBarry Smith /*104*/ NULL,
1158f4259b30SLisandro Dalcin NULL,
1159d4002b98SHong Zhang MatGetGhosts_MPISELL,
1160f4259b30SLisandro Dalcin NULL,
1161421480d9SBarry Smith NULL,
1162421480d9SBarry Smith /*109*/ MatMultDiagonalBlock_MPISELL,
1163421480d9SBarry Smith NULL,
1164f4259b30SLisandro Dalcin NULL,
11658bb0f5c6SPierre Jolivet NULL,
11668bb0f5c6SPierre Jolivet NULL,
11678bb0f5c6SPierre Jolivet /*114*/ NULL,
11688bb0f5c6SPierre Jolivet NULL,
11698bb0f5c6SPierre Jolivet MatInvertBlockDiagonal_MPISELL,
11708bb0f5c6SPierre Jolivet NULL,
11718bb0f5c6SPierre Jolivet /*119*/ NULL,
1172f4259b30SLisandro Dalcin NULL,
1173f4259b30SLisandro Dalcin NULL,
1174f4259b30SLisandro Dalcin NULL,
1175f4259b30SLisandro Dalcin NULL,
1176f4259b30SLisandro Dalcin /*124*/ NULL,
1177f4259b30SLisandro Dalcin NULL,
1178f4259b30SLisandro Dalcin NULL,
1179f4259b30SLisandro Dalcin NULL,
11808bb0f5c6SPierre Jolivet NULL,
11818bb0f5c6SPierre Jolivet /*129*/ MatFDColoringSetUp_MPIXAIJ,
1182f4259b30SLisandro Dalcin NULL,
1183f4259b30SLisandro Dalcin NULL,
1184f4259b30SLisandro Dalcin NULL,
1185f4259b30SLisandro Dalcin NULL,
1186f4259b30SLisandro Dalcin /*134*/ NULL,
1187f4259b30SLisandro Dalcin NULL,
1188f4259b30SLisandro Dalcin NULL,
1189f4259b30SLisandro Dalcin NULL,
1190f4259b30SLisandro Dalcin NULL,
1191f4259b30SLisandro Dalcin /*139*/ NULL,
1192f4259b30SLisandro Dalcin NULL,
1193f4259b30SLisandro Dalcin NULL,
119403db1824SAlex Lindsay NULL,
1195c2be7ffeSStefano Zampini NULL,
1196dec0b466SHong Zhang NULL};
1197d4002b98SHong Zhang
1198d4002b98SHong Zhang /*@C
119911a5261eSBarry Smith MatMPISELLSetPreallocation - Preallocates memory for a `MATMPISELL` sparse parallel matrix in sell format.
1200d4002b98SHong Zhang For good matrix assembly performance the user should preallocate the matrix storage by
120167be906fSBarry Smith setting the parameters `d_nz` (or `d_nnz`) and `o_nz` (or `o_nnz`).
1202d4002b98SHong Zhang
1203d083f849SBarry Smith Collective
1204d4002b98SHong Zhang
1205d4002b98SHong Zhang Input Parameters:
1206d4002b98SHong Zhang + B - the matrix
1207d4002b98SHong Zhang . d_nz - number of nonzeros per row in DIAGONAL portion of local submatrix
1208d4002b98SHong Zhang (same value is used for all local rows)
1209d4002b98SHong Zhang . d_nnz - array containing the number of nonzeros in the various rows of the
1210d4002b98SHong Zhang DIAGONAL portion of the local submatrix (possibly different for each row)
121167be906fSBarry Smith or NULL (`PETSC_NULL_INTEGER` in Fortran), if `d_nz` is used to specify the nonzero structure.
1212d4002b98SHong Zhang The size of this array is equal to the number of local rows, i.e 'm'.
1213d4002b98SHong Zhang For matrices that will be factored, you must leave room for (and set)
1214d4002b98SHong Zhang the diagonal entry even if it is zero.
1215d4002b98SHong Zhang . o_nz - number of nonzeros per row in the OFF-DIAGONAL portion of local
1216d4002b98SHong Zhang submatrix (same value is used for all local rows).
1217d4002b98SHong Zhang - o_nnz - array containing the number of nonzeros in the various rows of the
1218d4002b98SHong Zhang OFF-DIAGONAL portion of the local submatrix (possibly different for
121967be906fSBarry Smith each row) or NULL (`PETSC_NULL_INTEGER` in Fortran), if `o_nz` is used to specify the nonzero
1220d4002b98SHong Zhang structure. The size of this array is equal to the number
1221d4002b98SHong Zhang of local rows, i.e 'm'.
1222d4002b98SHong Zhang
1223d4002b98SHong Zhang Example usage:
1224d4002b98SHong Zhang Consider the following 8x8 matrix with 34 non-zero values, that is
1225d4002b98SHong Zhang assembled across 3 processors. Lets assume that proc0 owns 3 rows,
1226d4002b98SHong Zhang proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
122767be906fSBarry Smith as follows
1228d4002b98SHong Zhang
1229d4002b98SHong Zhang .vb
1230d4002b98SHong Zhang 1 2 0 | 0 3 0 | 0 4
1231d4002b98SHong Zhang Proc0 0 5 6 | 7 0 0 | 8 0
1232d4002b98SHong Zhang 9 0 10 | 11 0 0 | 12 0
1233d4002b98SHong Zhang -------------------------------------
1234d4002b98SHong Zhang 13 0 14 | 15 16 17 | 0 0
1235d4002b98SHong Zhang Proc1 0 18 0 | 19 20 21 | 0 0
1236d4002b98SHong Zhang 0 0 0 | 22 23 0 | 24 0
1237d4002b98SHong Zhang -------------------------------------
1238d4002b98SHong Zhang Proc2 25 26 27 | 0 0 28 | 29 0
1239d4002b98SHong Zhang 30 0 0 | 31 32 33 | 0 34
1240d4002b98SHong Zhang .ve
1241d4002b98SHong Zhang
124227430b45SBarry Smith This can be represented as a collection of submatrices as
1243d4002b98SHong Zhang
1244d4002b98SHong Zhang .vb
1245d4002b98SHong Zhang A B C
1246d4002b98SHong Zhang D E F
1247d4002b98SHong Zhang G H I
1248d4002b98SHong Zhang .ve
1249d4002b98SHong Zhang
1250d4002b98SHong Zhang Where the submatrices A,B,C are owned by proc0, D,E,F are
1251d4002b98SHong Zhang owned by proc1, G,H,I are owned by proc2.
1252d4002b98SHong Zhang
1253d4002b98SHong Zhang The 'm' parameters for proc0,proc1,proc2 are 3,3,2 respectively.
1254d4002b98SHong Zhang The 'n' parameters for proc0,proc1,proc2 are 3,3,2 respectively.
1255d4002b98SHong Zhang The 'M','N' parameters are 8,8, and have the same values on all procs.
1256d4002b98SHong Zhang
1257d4002b98SHong Zhang The DIAGONAL submatrices corresponding to proc0,proc1,proc2 are
1258d4002b98SHong Zhang submatrices [A], [E], [I] respectively. The OFF-DIAGONAL submatrices
1259d4002b98SHong Zhang corresponding to proc0,proc1,proc2 are [BC], [DF], [GH] respectively.
1260d4002b98SHong Zhang Internally, each processor stores the DIAGONAL part, and the OFF-DIAGONAL
126127430b45SBarry Smith part as `MATSEQSELL` matrices. For example, proc1 will store [E] as a `MATSEQSELL`
12625163b989SNuno Nobre matrix, and [DF] as another SeqSELL matrix.
1263d4002b98SHong Zhang
126467be906fSBarry Smith When `d_nz`, `o_nz` parameters are specified, `d_nz` storage elements are
12655163b989SNuno Nobre allocated for every row of the local DIAGONAL submatrix, and o_nz
12665163b989SNuno Nobre storage locations are allocated for every row of the OFF-DIAGONAL submatrix.
12675163b989SNuno Nobre One way to choose `d_nz` and `o_nz` is to use the maximum number of nonzeros over
12685163b989SNuno Nobre the local rows for each of the local DIAGONAL, and the OFF-DIAGONAL submatrices.
126927430b45SBarry Smith In this case, the values of d_nz,o_nz are
1270d4002b98SHong Zhang .vb
127127430b45SBarry Smith proc0 dnz = 2, o_nz = 2
127227430b45SBarry Smith proc1 dnz = 3, o_nz = 2
127327430b45SBarry Smith proc2 dnz = 1, o_nz = 4
1274d4002b98SHong Zhang .ve
1275d4002b98SHong Zhang We are allocating m*(d_nz+o_nz) storage locations for every proc. This
1276d4002b98SHong Zhang translates to 3*(2+2)=12 for proc0, 3*(3+2)=15 for proc1, 2*(1+4)=10
1277d4002b98SHong Zhang for proc3. i.e we are using 12+15+10=37 storage locations to store
1278d4002b98SHong Zhang 34 values.
1279d4002b98SHong Zhang
128067be906fSBarry Smith When `d_nnz`, `o_nnz` parameters are specified, the storage is specified
1281a5b23f4aSJose E. Roman for every row, corresponding to both DIAGONAL and OFF-DIAGONAL submatrices.
128227430b45SBarry Smith In the above case the values for d_nnz,o_nnz are
1283d4002b98SHong Zhang .vb
128427430b45SBarry Smith proc0 d_nnz = [2,2,2] and o_nnz = [2,2,2]
128527430b45SBarry Smith proc1 d_nnz = [3,3,2] and o_nnz = [2,1,1]
128627430b45SBarry Smith proc2 d_nnz = [1,1] and o_nnz = [4,4]
1287d4002b98SHong Zhang .ve
1288d4002b98SHong Zhang Here the space allocated is according to nz (or maximum values in the nnz
1289d4002b98SHong Zhang if nnz is provided) for DIAGONAL and OFF-DIAGONAL submatrices, i.e (2+2+3+2)*3+(1+4)*2=37
1290d4002b98SHong Zhang
1291d4002b98SHong Zhang Level: intermediate
1292d4002b98SHong Zhang
129367be906fSBarry Smith Notes:
129467be906fSBarry Smith If the *_nnz parameter is given then the *_nz parameter is ignored
129567be906fSBarry Smith
129667be906fSBarry Smith The stored row and column indices begin with zero.
129767be906fSBarry Smith
129867be906fSBarry Smith The parallel matrix is partitioned such that the first m0 rows belong to
129967be906fSBarry Smith process 0, the next m1 rows belong to process 1, the next m2 rows belong
130067be906fSBarry Smith to process 2 etc.. where m0,m1,m2... are the input parameter 'm'.
130167be906fSBarry Smith
130267be906fSBarry Smith The DIAGONAL portion of the local submatrix of a processor can be defined
130367be906fSBarry Smith as the submatrix which is obtained by extraction the part corresponding to
130467be906fSBarry Smith the rows r1-r2 and columns c1-c2 of the global matrix, where r1 is the
130567be906fSBarry Smith first row that belongs to the processor, r2 is the last row belonging to
130667be906fSBarry Smith the this processor, and c1-c2 is range of indices of the local part of a
130767be906fSBarry Smith vector suitable for applying the matrix to. This is an mxn matrix. In the
130867be906fSBarry Smith common case of a square matrix, the row and column ranges are the same and
130967be906fSBarry Smith the DIAGONAL part is also square. The remaining portion of the local
131067be906fSBarry Smith submatrix (mxN) constitute the OFF-DIAGONAL portion.
131167be906fSBarry Smith
131267be906fSBarry Smith If `o_nnz`, `d_nnz` are specified, then `o_nz`, and `d_nz` are ignored.
131367be906fSBarry Smith
131467be906fSBarry Smith You can call `MatGetInfo()` to get information on how effective the preallocation was;
131567be906fSBarry Smith for example the fields mallocs,nz_allocated,nz_used,nz_unneeded;
131667be906fSBarry Smith You can also run with the option -info and look for messages with the string
131767be906fSBarry Smith malloc in them to see if additional memory allocation was needed.
131867be906fSBarry Smith
131994764886SPierre Jolivet .seealso: `Mat`, `MatCreate()`, `MatCreateSeqSELL()`, `MatSetValues()`, `MatCreateSELL()`,
132011a5261eSBarry Smith `MATMPISELL`, `MatGetInfo()`, `PetscSplitOwnership()`, `MATSELL`
1321d4002b98SHong Zhang @*/
MatMPISELLSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])1322d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMPISELLSetPreallocation(Mat B, PetscInt d_nz, const PetscInt d_nnz[], PetscInt o_nz, const PetscInt o_nnz[])
1323d71ae5a4SJacob Faibussowitsch {
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));
13283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
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
133527430b45SBarry Smith Options Database Key:
133620f4b53cSBarry Smith . -mat_type sell - sets the matrix type to `MATSELL` during a call to `MatSetFromOptions()`
1337ed73aabaSBarry Smith
1338ed73aabaSBarry Smith Level: beginner
1339ed73aabaSBarry Smith
134094764886SPierre Jolivet .seealso: `Mat`, `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
135420f4b53cSBarry Smith x vector for the matrix-vector product y = Ax. (or `PETSC_DECIDE` to have
135520f4b53cSBarry Smith calculated if `N` is given) For square matrices n is almost always `m`.
135620f4b53cSBarry Smith . M - number of global rows (or `PETSC_DETERMINE` to have calculated if `m` is given)
135720f4b53cSBarry 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)
136220f4b53cSBarry Smith or `NULL`, if d_rlenmax is used to specify the nonzero structure.
136320f4b53cSBarry Smith 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
136820f4b53cSBarry Smith 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
137020f4b53cSBarry Smith of local rows, i.e `m`.
1371d4002b98SHong Zhang
1372d4002b98SHong Zhang Output Parameter:
1373d4002b98SHong Zhang . A - the matrix
1374d4002b98SHong Zhang
137527430b45SBarry Smith Options Database Key:
1376fe59aa6dSJacob Faibussowitsch . -mat_sell_oneindex - Internally use indexing starting at 1
137727430b45SBarry Smith rather than 0. When calling `MatSetValues()`,
137827430b45SBarry Smith the user still MUST index entries starting at 0!
137927430b45SBarry Smith
138027430b45SBarry Smith Example:
138127430b45SBarry Smith Consider the following 8x8 matrix with 34 non-zero values, that is
138227430b45SBarry Smith assembled across 3 processors. Lets assume that proc0 owns 3 rows,
138327430b45SBarry Smith proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
138427430b45SBarry Smith as follows
138527430b45SBarry Smith
138627430b45SBarry Smith .vb
138727430b45SBarry Smith 1 2 0 | 0 3 0 | 0 4
138827430b45SBarry Smith Proc0 0 5 6 | 7 0 0 | 8 0
138927430b45SBarry Smith 9 0 10 | 11 0 0 | 12 0
139027430b45SBarry Smith -------------------------------------
139127430b45SBarry Smith 13 0 14 | 15 16 17 | 0 0
139227430b45SBarry Smith Proc1 0 18 0 | 19 20 21 | 0 0
139327430b45SBarry Smith 0 0 0 | 22 23 0 | 24 0
139427430b45SBarry Smith -------------------------------------
139527430b45SBarry Smith Proc2 25 26 27 | 0 0 28 | 29 0
139627430b45SBarry Smith 30 0 0 | 31 32 33 | 0 34
139727430b45SBarry Smith .ve
139827430b45SBarry Smith
139920f4b53cSBarry Smith This can be represented as a collection of submatrices as
140027430b45SBarry Smith .vb
140127430b45SBarry Smith A B C
140227430b45SBarry Smith D E F
140327430b45SBarry Smith G H I
140427430b45SBarry Smith .ve
140527430b45SBarry Smith
140627430b45SBarry Smith Where the submatrices A,B,C are owned by proc0, D,E,F are
140727430b45SBarry Smith owned by proc1, G,H,I are owned by proc2.
140827430b45SBarry Smith
140927430b45SBarry Smith The 'm' parameters for proc0,proc1,proc2 are 3,3,2 respectively.
141027430b45SBarry Smith The 'n' parameters for proc0,proc1,proc2 are 3,3,2 respectively.
141127430b45SBarry Smith The 'M','N' parameters are 8,8, and have the same values on all procs.
141227430b45SBarry Smith
141327430b45SBarry Smith The DIAGONAL submatrices corresponding to proc0,proc1,proc2 are
141427430b45SBarry Smith submatrices [A], [E], [I] respectively. The OFF-DIAGONAL submatrices
141527430b45SBarry Smith corresponding to proc0,proc1,proc2 are [BC], [DF], [GH] respectively.
141627430b45SBarry Smith Internally, each processor stores the DIAGONAL part, and the OFF-DIAGONAL
141727430b45SBarry Smith part as `MATSEQSELL` matrices. For example, proc1 will store [E] as a `MATSEQSELL`
14185163b989SNuno Nobre matrix, and [DF] as another `MATSEQSELL` matrix.
141927430b45SBarry Smith
142027430b45SBarry Smith When d_rlenmax, o_rlenmax parameters are specified, d_rlenmax storage elements are
14215163b989SNuno Nobre allocated for every row of the local DIAGONAL submatrix, and o_rlenmax
14225163b989SNuno Nobre storage locations are allocated for every row of the OFF-DIAGONAL submatrix.
14235163b989SNuno Nobre One way to choose `d_rlenmax` and `o_rlenmax` is to use the maximum number of nonzeros over
14245163b989SNuno Nobre the local rows for each of the local DIAGONAL, and the OFF-DIAGONAL submatrices.
142520f4b53cSBarry Smith In this case, the values of d_rlenmax,o_rlenmax are
142627430b45SBarry Smith .vb
142720f4b53cSBarry Smith proc0 - d_rlenmax = 2, o_rlenmax = 2
142820f4b53cSBarry Smith proc1 - d_rlenmax = 3, o_rlenmax = 2
142920f4b53cSBarry Smith proc2 - d_rlenmax = 1, o_rlenmax = 4
143027430b45SBarry Smith .ve
143127430b45SBarry Smith We are allocating m*(d_rlenmax+o_rlenmax) storage locations for every proc. This
143227430b45SBarry Smith translates to 3*(2+2)=12 for proc0, 3*(3+2)=15 for proc1, 2*(1+4)=10
143327430b45SBarry Smith for proc3. i.e we are using 12+15+10=37 storage locations to store
143427430b45SBarry Smith 34 values.
143527430b45SBarry Smith
143620f4b53cSBarry Smith When `d_rlen`, `o_rlen` parameters are specified, the storage is specified
143727430b45SBarry Smith for every row, corresponding to both DIAGONAL and OFF-DIAGONAL submatrices.
143820f4b53cSBarry Smith In the above case the values for `d_nnz`, `o_nnz` are
143927430b45SBarry Smith .vb
144020f4b53cSBarry Smith proc0 - d_nnz = [2,2,2] and o_nnz = [2,2,2]
144120f4b53cSBarry Smith proc1 - d_nnz = [3,3,2] and o_nnz = [2,1,1]
144220f4b53cSBarry Smith proc2 - d_nnz = [1,1] and o_nnz = [4,4]
144327430b45SBarry Smith .ve
144427430b45SBarry Smith Here the space allocated is still 37 though there are 34 nonzeros because
144527430b45SBarry Smith the allocation is always done according to rlenmax.
144627430b45SBarry Smith
144727430b45SBarry Smith Level: intermediate
144827430b45SBarry Smith
144927430b45SBarry Smith Notes:
145011a5261eSBarry Smith It is recommended that one use the `MatCreate()`, `MatSetType()` and/or `MatSetFromOptions()`,
1451f6f02116SRichard Tran Mills MatXXXXSetPreallocation() paradigm instead of this routine directly.
145211a5261eSBarry Smith [MatXXXXSetPreallocation() is, for example, `MatSeqSELLSetPreallocation()`]
1453d4002b98SHong Zhang
1454d4002b98SHong Zhang If the *_rlen parameter is given then the *_rlenmax parameter is ignored
1455d4002b98SHong Zhang
145620f4b53cSBarry Smith `m`, `n`, `M`, `N` parameters specify the size of the matrix, and its partitioning across
145720f4b53cSBarry Smith processors, while `d_rlenmax`, `d_rlen`, `o_rlenmax` , `o_rlen` parameters specify the approximate
1458d4002b98SHong Zhang storage requirements for this matrix.
1459d4002b98SHong Zhang
146011a5261eSBarry Smith If `PETSC_DECIDE` or `PETSC_DETERMINE` is used for a particular argument on one
1461d4002b98SHong Zhang processor than it must be used on all processors that share the object for
1462d4002b98SHong Zhang that argument.
1463d4002b98SHong Zhang
1464d4002b98SHong Zhang The user MUST specify either the local or global matrix dimensions
1465d4002b98SHong Zhang (possibly both).
1466d4002b98SHong Zhang
1467d4002b98SHong Zhang The parallel matrix is partitioned across processors such that the
1468d4002b98SHong Zhang first m0 rows belong to process 0, the next m1 rows belong to
1469d4002b98SHong Zhang process 1, the next m2 rows belong to process 2 etc.. where
1470d4002b98SHong Zhang m0,m1,m2,.. are the input parameter 'm'. i.e each processor stores
147120f4b53cSBarry Smith values corresponding to [`m` x `N`] submatrix.
1472d4002b98SHong Zhang
1473d4002b98SHong Zhang The columns are logically partitioned with the n0 columns belonging
1474d4002b98SHong Zhang to 0th partition, the next n1 columns belonging to the next
147520f4b53cSBarry Smith partition etc.. where n0,n1,n2... are the input parameter `n`.
1476d4002b98SHong Zhang
1477d4002b98SHong Zhang The DIAGONAL portion of the local submatrix on any given processor
147820f4b53cSBarry Smith is the submatrix corresponding to the rows and columns `m`, `n`
1479d4002b98SHong Zhang corresponding to the given processor. i.e diagonal matrix on
1480d4002b98SHong Zhang process 0 is [m0 x n0], diagonal matrix on process 1 is [m1 x n1]
1481d4002b98SHong Zhang etc. The remaining portion of the local submatrix [m x (N-n)]
1482d4002b98SHong Zhang constitute the OFF-DIAGONAL portion. The example below better
1483d4002b98SHong Zhang illustrates this concept.
1484d4002b98SHong Zhang
1485d4002b98SHong Zhang For a square global matrix we define each processor's diagonal portion
1486d4002b98SHong Zhang to be its local rows and the corresponding columns (a square submatrix);
1487d4002b98SHong Zhang each processor's off-diagonal portion encompasses the remainder of the
1488d4002b98SHong Zhang local matrix (a rectangular submatrix).
1489d4002b98SHong Zhang
149020f4b53cSBarry Smith If `o_rlen`, `d_rlen` are specified, then `o_rlenmax`, and `d_rlenmax` are ignored.
1491d4002b98SHong Zhang
1492d4002b98SHong Zhang When calling this routine with a single process communicator, a matrix of
149311a5261eSBarry Smith type `MATSEQSELL` is returned. If a matrix of type `MATMPISELL` is desired for this
149427430b45SBarry Smith type of communicator, use the construction mechanism
1495d4002b98SHong Zhang .vb
149627430b45SBarry Smith MatCreate(...,&A);
149727430b45SBarry Smith MatSetType(A,MATMPISELL);
149827430b45SBarry Smith MatSetSizes(A, m,n,M,N);
149927430b45SBarry Smith MatMPISELLSetPreallocation(A,...);
1500d4002b98SHong Zhang .ve
1501d4002b98SHong Zhang
150294764886SPierre Jolivet .seealso: `Mat`, `MATSELL`, `MatCreate()`, `MatCreateSeqSELL()`, `MatSetValues()`, `MatMPISELLSetPreallocation()`, `MATMPISELL`
1503d4002b98SHong Zhang @*/
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)1504d71ae5a4SJacob Faibussowitsch 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)
1505d71ae5a4SJacob Faibussowitsch {
1506d4002b98SHong Zhang PetscMPIInt size;
1507d4002b98SHong Zhang
1508d4002b98SHong Zhang PetscFunctionBegin;
15099566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, A));
15109566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*A, m, n, M, N));
15119566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size));
1512d4002b98SHong Zhang if (size > 1) {
15139566063dSJacob Faibussowitsch PetscCall(MatSetType(*A, MATMPISELL));
15149566063dSJacob Faibussowitsch PetscCall(MatMPISELLSetPreallocation(*A, d_rlenmax, d_rlen, o_rlenmax, o_rlen));
1515d4002b98SHong Zhang } else {
15169566063dSJacob Faibussowitsch PetscCall(MatSetType(*A, MATSEQSELL));
15179566063dSJacob Faibussowitsch PetscCall(MatSeqSELLSetPreallocation(*A, d_rlenmax, d_rlen));
1518d4002b98SHong Zhang }
15193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1520d4002b98SHong Zhang }
1521d4002b98SHong Zhang
1522fa078d78SJacob Faibussowitsch /*@C
1523fa078d78SJacob Faibussowitsch MatMPISELLGetSeqSELL - Returns the local pieces of this distributed matrix
1524fa078d78SJacob Faibussowitsch
1525fa078d78SJacob Faibussowitsch Not Collective
1526fa078d78SJacob Faibussowitsch
1527fa078d78SJacob Faibussowitsch Input Parameter:
1528fa078d78SJacob Faibussowitsch . A - the `MATMPISELL` matrix
1529fa078d78SJacob Faibussowitsch
1530fa078d78SJacob Faibussowitsch Output Parameters:
1531fa078d78SJacob Faibussowitsch + Ad - The diagonal portion of `A`
15324cf0e950SBarry Smith . Ao - The off-diagonal portion of `A`
1533fa078d78SJacob Faibussowitsch - colmap - An array mapping local column numbers of `Ao` to global column numbers of the parallel matrix
1534fa078d78SJacob Faibussowitsch
1535fa078d78SJacob Faibussowitsch Level: advanced
1536fa078d78SJacob Faibussowitsch
1537fa078d78SJacob Faibussowitsch .seealso: `Mat`, `MATSEQSELL`, `MATMPISELL`
1538fa078d78SJacob Faibussowitsch @*/
MatMPISELLGetSeqSELL(Mat A,Mat * Ad,Mat * Ao,const PetscInt * colmap[])1539fa078d78SJacob Faibussowitsch PetscErrorCode MatMPISELLGetSeqSELL(Mat A, Mat *Ad, Mat *Ao, const PetscInt *colmap[])
1540fa078d78SJacob Faibussowitsch {
1541fa078d78SJacob Faibussowitsch Mat_MPISELL *a = (Mat_MPISELL *)A->data;
1542fa078d78SJacob Faibussowitsch PetscBool flg;
1543fa078d78SJacob Faibussowitsch
1544fa078d78SJacob Faibussowitsch PetscFunctionBegin;
1545fa078d78SJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMPISELL, &flg));
1546fa078d78SJacob Faibussowitsch PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "This function requires a MATMPISELL matrix as input");
1547fa078d78SJacob Faibussowitsch if (Ad) *Ad = a->A;
1548fa078d78SJacob Faibussowitsch if (Ao) *Ao = a->B;
1549fa078d78SJacob Faibussowitsch if (colmap) *colmap = a->garray;
1550fa078d78SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1551fa078d78SJacob Faibussowitsch }
1552fa078d78SJacob Faibussowitsch
1553fa078d78SJacob Faibussowitsch /*@C
1554fa078d78SJacob Faibussowitsch MatMPISELLGetLocalMatCondensed - Creates a `MATSEQSELL` matrix from an `MATMPISELL` matrix by
1555fa078d78SJacob Faibussowitsch taking all its local rows and NON-ZERO columns
1556fa078d78SJacob Faibussowitsch
1557fa078d78SJacob Faibussowitsch Not Collective
1558fa078d78SJacob Faibussowitsch
1559fa078d78SJacob Faibussowitsch Input Parameters:
1560fa078d78SJacob Faibussowitsch + A - the matrix
1561fa078d78SJacob Faibussowitsch . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
1562fa078d78SJacob Faibussowitsch . row - index sets of rows to extract (or `NULL`)
1563fa078d78SJacob Faibussowitsch - col - index sets of columns to extract (or `NULL`)
1564fa078d78SJacob Faibussowitsch
1565fa078d78SJacob Faibussowitsch Output Parameter:
1566fa078d78SJacob Faibussowitsch . A_loc - the local sequential matrix generated
1567fa078d78SJacob Faibussowitsch
1568fa078d78SJacob Faibussowitsch Level: advanced
1569fa078d78SJacob Faibussowitsch
1570fa078d78SJacob Faibussowitsch .seealso: `Mat`, `MATSEQSELL`, `MATMPISELL`, `MatGetOwnershipRange()`, `MatMPISELLGetLocalMat()`
1571fa078d78SJacob Faibussowitsch @*/
MatMPISELLGetLocalMatCondensed(Mat A,MatReuse scall,IS * row,IS * col,Mat * A_loc)1572fa078d78SJacob Faibussowitsch PetscErrorCode MatMPISELLGetLocalMatCondensed(Mat A, MatReuse scall, IS *row, IS *col, Mat *A_loc)
1573fa078d78SJacob Faibussowitsch {
1574fa078d78SJacob Faibussowitsch Mat_MPISELL *a = (Mat_MPISELL *)A->data;
1575fa078d78SJacob Faibussowitsch PetscInt i, start, end, ncols, nzA, nzB, *cmap, imark, *idx;
1576fa078d78SJacob Faibussowitsch IS isrowa, iscola;
1577fa078d78SJacob Faibussowitsch Mat *aloc;
1578fa078d78SJacob Faibussowitsch PetscBool match;
1579fa078d78SJacob Faibussowitsch
1580fa078d78SJacob Faibussowitsch PetscFunctionBegin;
1581fa078d78SJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMPISELL, &match));
1582fa078d78SJacob Faibussowitsch PetscCheck(match, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Requires MATMPISELL matrix as input");
1583fa078d78SJacob Faibussowitsch PetscCall(PetscLogEventBegin(MAT_Getlocalmatcondensed, A, 0, 0, 0));
1584fa078d78SJacob Faibussowitsch if (!row) {
1585fa078d78SJacob Faibussowitsch start = A->rmap->rstart;
1586fa078d78SJacob Faibussowitsch end = A->rmap->rend;
1587fa078d78SJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, end - start, start, 1, &isrowa));
1588fa078d78SJacob Faibussowitsch } else {
1589fa078d78SJacob Faibussowitsch isrowa = *row;
1590fa078d78SJacob Faibussowitsch }
1591fa078d78SJacob Faibussowitsch if (!col) {
1592fa078d78SJacob Faibussowitsch start = A->cmap->rstart;
1593fa078d78SJacob Faibussowitsch cmap = a->garray;
1594fa078d78SJacob Faibussowitsch nzA = a->A->cmap->n;
1595fa078d78SJacob Faibussowitsch nzB = a->B->cmap->n;
1596fa078d78SJacob Faibussowitsch PetscCall(PetscMalloc1(nzA + nzB, &idx));
1597fa078d78SJacob Faibussowitsch ncols = 0;
1598fa078d78SJacob Faibussowitsch for (i = 0; i < nzB; i++) {
1599fa078d78SJacob Faibussowitsch if (cmap[i] < start) idx[ncols++] = cmap[i];
1600fa078d78SJacob Faibussowitsch else break;
1601fa078d78SJacob Faibussowitsch }
1602fa078d78SJacob Faibussowitsch imark = i;
1603fa078d78SJacob Faibussowitsch for (i = 0; i < nzA; i++) idx[ncols++] = start + i;
1604fa078d78SJacob Faibussowitsch for (i = imark; i < nzB; i++) idx[ncols++] = cmap[i];
1605fa078d78SJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, ncols, idx, PETSC_OWN_POINTER, &iscola));
1606fa078d78SJacob Faibussowitsch } else {
1607fa078d78SJacob Faibussowitsch iscola = *col;
1608fa078d78SJacob Faibussowitsch }
1609fa078d78SJacob Faibussowitsch if (scall != MAT_INITIAL_MATRIX) {
1610fa078d78SJacob Faibussowitsch PetscCall(PetscMalloc1(1, &aloc));
1611fa078d78SJacob Faibussowitsch aloc[0] = *A_loc;
1612fa078d78SJacob Faibussowitsch }
1613fa078d78SJacob Faibussowitsch PetscCall(MatCreateSubMatrices(A, 1, &isrowa, &iscola, scall, &aloc));
1614fa078d78SJacob Faibussowitsch *A_loc = aloc[0];
1615fa078d78SJacob Faibussowitsch PetscCall(PetscFree(aloc));
1616fa078d78SJacob Faibussowitsch if (!row) PetscCall(ISDestroy(&isrowa));
1617fa078d78SJacob Faibussowitsch if (!col) PetscCall(ISDestroy(&iscola));
1618fa078d78SJacob Faibussowitsch PetscCall(PetscLogEventEnd(MAT_Getlocalmatcondensed, A, 0, 0, 0));
1619fa078d78SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1620fa078d78SJacob Faibussowitsch }
1621fa078d78SJacob Faibussowitsch
1622d4002b98SHong Zhang #include <../src/mat/impls/aij/mpi/mpiaij.h>
1623d4002b98SHong Zhang
MatConvert_MPISELL_MPIAIJ(Mat A,MatType newtype,MatReuse reuse,Mat * newmat)1624d71ae5a4SJacob Faibussowitsch PetscErrorCode MatConvert_MPISELL_MPIAIJ(Mat A, MatType newtype, MatReuse reuse, Mat *newmat)
1625d71ae5a4SJacob Faibussowitsch {
1626d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data;
1627d4002b98SHong Zhang Mat B;
1628d4002b98SHong Zhang Mat_MPIAIJ *b;
1629d4002b98SHong Zhang
1630d4002b98SHong Zhang PetscFunctionBegin;
163128b400f6SJacob Faibussowitsch PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Matrix must be assembled");
1632d4002b98SHong Zhang
163394a8b381SRichard Tran Mills if (reuse == MAT_REUSE_MATRIX) {
163494a8b381SRichard Tran Mills B = *newmat;
163594a8b381SRichard Tran Mills } else {
16369566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
16379566063dSJacob Faibussowitsch PetscCall(MatSetType(B, MATMPIAIJ));
16389566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N));
16399566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(B, A->rmap->bs, A->cmap->bs));
16409566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(B, 0, NULL));
16419566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(B, 0, NULL, 0, NULL));
164294a8b381SRichard Tran Mills }
1643d4002b98SHong Zhang b = (Mat_MPIAIJ *)B->data;
164494a8b381SRichard Tran Mills
164594a8b381SRichard Tran Mills if (reuse == MAT_REUSE_MATRIX) {
16469566063dSJacob Faibussowitsch PetscCall(MatConvert_SeqSELL_SeqAIJ(a->A, MATSEQAIJ, MAT_REUSE_MATRIX, &b->A));
16479566063dSJacob Faibussowitsch PetscCall(MatConvert_SeqSELL_SeqAIJ(a->B, MATSEQAIJ, MAT_REUSE_MATRIX, &b->B));
164894a8b381SRichard Tran Mills } else {
16499566063dSJacob Faibussowitsch PetscCall(MatDestroy(&b->A));
16509566063dSJacob Faibussowitsch PetscCall(MatDestroy(&b->B));
16519566063dSJacob Faibussowitsch PetscCall(MatDisAssemble_MPISELL(A));
16529566063dSJacob Faibussowitsch PetscCall(MatConvert_SeqSELL_SeqAIJ(a->A, MATSEQAIJ, MAT_INITIAL_MATRIX, &b->A));
16539566063dSJacob Faibussowitsch PetscCall(MatConvert_SeqSELL_SeqAIJ(a->B, MATSEQAIJ, MAT_INITIAL_MATRIX, &b->B));
16549566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
16559566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
16569566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
16579566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
165894a8b381SRichard Tran Mills }
1659d4002b98SHong Zhang
1660d4002b98SHong Zhang if (reuse == MAT_INPLACE_MATRIX) {
16619566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(A, &B));
1662d4002b98SHong Zhang } else {
1663d4002b98SHong Zhang *newmat = B;
1664d4002b98SHong Zhang }
16653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1666d4002b98SHong Zhang }
1667d4002b98SHong Zhang
MatConvert_MPIAIJ_MPISELL(Mat A,MatType newtype,MatReuse reuse,Mat * newmat)1668d71ae5a4SJacob Faibussowitsch PetscErrorCode MatConvert_MPIAIJ_MPISELL(Mat A, MatType newtype, MatReuse reuse, Mat *newmat)
1669d71ae5a4SJacob Faibussowitsch {
1670d4002b98SHong Zhang Mat_MPIAIJ *a = (Mat_MPIAIJ *)A->data;
1671d4002b98SHong Zhang Mat B;
1672d4002b98SHong Zhang Mat_MPISELL *b;
1673d4002b98SHong Zhang
1674d4002b98SHong Zhang PetscFunctionBegin;
167528b400f6SJacob Faibussowitsch PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Matrix must be assembled");
1676d4002b98SHong Zhang
167794a8b381SRichard Tran Mills if (reuse == MAT_REUSE_MATRIX) {
167894a8b381SRichard Tran Mills B = *newmat;
167994a8b381SRichard Tran Mills } else {
16802d1451d4SHong Zhang Mat_SeqAIJ *Aa = (Mat_SeqAIJ *)a->A->data, *Ba = (Mat_SeqAIJ *)a->B->data;
16812d1451d4SHong Zhang PetscInt i, d_nz = 0, o_nz = 0, m = A->rmap->N, n = A->cmap->N, lm = A->rmap->n, ln = A->cmap->n;
16822d1451d4SHong Zhang PetscInt *d_nnz, *o_nnz;
16832d1451d4SHong Zhang PetscCall(PetscMalloc2(lm, &d_nnz, lm, &o_nnz));
16842d1451d4SHong Zhang for (i = 0; i < lm; i++) {
16852d1451d4SHong Zhang d_nnz[i] = Aa->i[i + 1] - Aa->i[i];
16862d1451d4SHong Zhang o_nnz[i] = Ba->i[i + 1] - Ba->i[i];
16872d1451d4SHong Zhang if (d_nnz[i] > d_nz) d_nz = d_nnz[i];
16882d1451d4SHong Zhang if (o_nnz[i] > o_nz) o_nz = o_nnz[i];
16892d1451d4SHong Zhang }
16909566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
16919566063dSJacob Faibussowitsch PetscCall(MatSetType(B, MATMPISELL));
16922d1451d4SHong Zhang PetscCall(MatSetSizes(B, lm, ln, m, n));
16939566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(B, A->rmap->bs, A->cmap->bs));
16942d1451d4SHong Zhang PetscCall(MatSeqSELLSetPreallocation(B, d_nz, d_nnz));
16952d1451d4SHong Zhang PetscCall(MatMPISELLSetPreallocation(B, d_nz, d_nnz, o_nz, o_nnz));
16962d1451d4SHong Zhang PetscCall(PetscFree2(d_nnz, o_nnz));
169794a8b381SRichard Tran Mills }
1698d4002b98SHong Zhang b = (Mat_MPISELL *)B->data;
169994a8b381SRichard Tran Mills
170094a8b381SRichard Tran Mills if (reuse == MAT_REUSE_MATRIX) {
17019566063dSJacob Faibussowitsch PetscCall(MatConvert_SeqAIJ_SeqSELL(a->A, MATSEQSELL, MAT_REUSE_MATRIX, &b->A));
17029566063dSJacob Faibussowitsch PetscCall(MatConvert_SeqAIJ_SeqSELL(a->B, MATSEQSELL, MAT_REUSE_MATRIX, &b->B));
170394a8b381SRichard Tran Mills } else {
17049566063dSJacob Faibussowitsch PetscCall(MatDestroy(&b->A));
17059566063dSJacob Faibussowitsch PetscCall(MatDestroy(&b->B));
17069566063dSJacob Faibussowitsch PetscCall(MatConvert_SeqAIJ_SeqSELL(a->A, MATSEQSELL, MAT_INITIAL_MATRIX, &b->A));
17079566063dSJacob Faibussowitsch PetscCall(MatConvert_SeqAIJ_SeqSELL(a->B, MATSEQSELL, MAT_INITIAL_MATRIX, &b->B));
17089566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
17099566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
17102d1451d4SHong Zhang PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
17112d1451d4SHong Zhang PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
171294a8b381SRichard Tran Mills }
1713d4002b98SHong Zhang
1714d4002b98SHong Zhang if (reuse == MAT_INPLACE_MATRIX) {
17159566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(A, &B));
1716d4002b98SHong Zhang } else {
1717d4002b98SHong Zhang *newmat = B;
1718d4002b98SHong Zhang }
17193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1720d4002b98SHong Zhang }
1721d4002b98SHong Zhang
MatSOR_MPISELL(Mat matin,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx)1722d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSOR_MPISELL(Mat matin, Vec bb, PetscReal omega, MatSORType flag, PetscReal fshift, PetscInt its, PetscInt lits, Vec xx)
1723d71ae5a4SJacob Faibussowitsch {
1724d4002b98SHong Zhang Mat_MPISELL *mat = (Mat_MPISELL *)matin->data;
1725f4259b30SLisandro Dalcin Vec bb1 = NULL;
1726d4002b98SHong Zhang
1727d4002b98SHong Zhang PetscFunctionBegin;
1728d4002b98SHong Zhang if (flag == SOR_APPLY_UPPER) {
17299566063dSJacob Faibussowitsch PetscCall((*mat->A->ops->sor)(mat->A, bb, omega, flag, fshift, lits, 1, xx));
17303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1731d4002b98SHong Zhang }
1732d4002b98SHong Zhang
173348a46eb9SPierre Jolivet if (its > 1 || ~flag & SOR_ZERO_INITIAL_GUESS || flag & SOR_EISENSTAT) PetscCall(VecDuplicate(bb, &bb1));
1734d4002b98SHong Zhang
1735d4002b98SHong Zhang if ((flag & SOR_LOCAL_SYMMETRIC_SWEEP) == SOR_LOCAL_SYMMETRIC_SWEEP) {
1736d4002b98SHong Zhang if (flag & SOR_ZERO_INITIAL_GUESS) {
17379566063dSJacob Faibussowitsch PetscCall((*mat->A->ops->sor)(mat->A, bb, omega, flag, fshift, lits, 1, xx));
1738d4002b98SHong Zhang its--;
1739d4002b98SHong Zhang }
1740d4002b98SHong Zhang
1741d4002b98SHong Zhang while (its--) {
17429566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat->Mvctx, xx, mat->lvec, INSERT_VALUES, SCATTER_FORWARD));
17439566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat->Mvctx, xx, mat->lvec, INSERT_VALUES, SCATTER_FORWARD));
1744d4002b98SHong Zhang
1745d4002b98SHong Zhang /* update rhs: bb1 = bb - B*x */
17469566063dSJacob Faibussowitsch PetscCall(VecScale(mat->lvec, -1.0));
17479566063dSJacob Faibussowitsch PetscCall((*mat->B->ops->multadd)(mat->B, mat->lvec, bb, bb1));
1748d4002b98SHong Zhang
1749d4002b98SHong Zhang /* local sweep */
17509566063dSJacob Faibussowitsch PetscCall((*mat->A->ops->sor)(mat->A, bb1, omega, SOR_SYMMETRIC_SWEEP, fshift, lits, 1, xx));
1751d4002b98SHong Zhang }
1752d4002b98SHong Zhang } else if (flag & SOR_LOCAL_FORWARD_SWEEP) {
1753d4002b98SHong Zhang if (flag & SOR_ZERO_INITIAL_GUESS) {
17549566063dSJacob Faibussowitsch PetscCall((*mat->A->ops->sor)(mat->A, bb, omega, flag, fshift, lits, 1, xx));
1755d4002b98SHong Zhang its--;
1756d4002b98SHong Zhang }
1757d4002b98SHong Zhang while (its--) {
17589566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat->Mvctx, xx, mat->lvec, INSERT_VALUES, SCATTER_FORWARD));
17599566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat->Mvctx, xx, mat->lvec, INSERT_VALUES, SCATTER_FORWARD));
1760d4002b98SHong Zhang
1761d4002b98SHong Zhang /* update rhs: bb1 = bb - B*x */
17629566063dSJacob Faibussowitsch PetscCall(VecScale(mat->lvec, -1.0));
17639566063dSJacob Faibussowitsch PetscCall((*mat->B->ops->multadd)(mat->B, mat->lvec, bb, bb1));
1764d4002b98SHong Zhang
1765d4002b98SHong Zhang /* local sweep */
17669566063dSJacob Faibussowitsch PetscCall((*mat->A->ops->sor)(mat->A, bb1, omega, SOR_FORWARD_SWEEP, fshift, lits, 1, xx));
1767d4002b98SHong Zhang }
1768d4002b98SHong Zhang } else if (flag & SOR_LOCAL_BACKWARD_SWEEP) {
1769d4002b98SHong Zhang if (flag & SOR_ZERO_INITIAL_GUESS) {
17709566063dSJacob Faibussowitsch PetscCall((*mat->A->ops->sor)(mat->A, bb, omega, flag, fshift, lits, 1, xx));
1771d4002b98SHong Zhang its--;
1772d4002b98SHong Zhang }
1773d4002b98SHong Zhang while (its--) {
17749566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat->Mvctx, xx, mat->lvec, INSERT_VALUES, SCATTER_FORWARD));
17759566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat->Mvctx, xx, mat->lvec, INSERT_VALUES, SCATTER_FORWARD));
1776d4002b98SHong Zhang
1777d4002b98SHong Zhang /* update rhs: bb1 = bb - B*x */
17789566063dSJacob Faibussowitsch PetscCall(VecScale(mat->lvec, -1.0));
17799566063dSJacob Faibussowitsch PetscCall((*mat->B->ops->multadd)(mat->B, mat->lvec, bb, bb1));
1780d4002b98SHong Zhang
1781d4002b98SHong Zhang /* local sweep */
17829566063dSJacob Faibussowitsch PetscCall((*mat->A->ops->sor)(mat->A, bb1, omega, SOR_BACKWARD_SWEEP, fshift, lits, 1, xx));
1783d4002b98SHong Zhang }
1784d4002b98SHong Zhang } else SETERRQ(PetscObjectComm((PetscObject)matin), PETSC_ERR_SUP, "Parallel SOR not supported");
1785d4002b98SHong Zhang
17869566063dSJacob Faibussowitsch PetscCall(VecDestroy(&bb1));
1787d4002b98SHong Zhang
1788d4002b98SHong Zhang matin->factorerrortype = mat->A->factorerrortype;
17893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1790d4002b98SHong Zhang }
1791d4002b98SHong Zhang
1792b5917f1bSHong Zhang #if defined(PETSC_HAVE_CUDA)
1793b5917f1bSHong Zhang PETSC_INTERN PetscErrorCode MatConvert_MPISELL_MPISELLCUDA(Mat, MatType, MatReuse, Mat *);
1794b5917f1bSHong Zhang #endif
1795b5917f1bSHong Zhang
1796d4002b98SHong Zhang /*MC
1797d4002b98SHong Zhang MATMPISELL - MATMPISELL = "MPISELL" - A matrix type to be used for parallel sparse matrices.
1798d4002b98SHong Zhang
1799d4002b98SHong Zhang Options Database Keys:
180011a5261eSBarry Smith . -mat_type mpisell - sets the matrix type to `MATMPISELL` during a call to `MatSetFromOptions()`
1801d4002b98SHong Zhang
1802d4002b98SHong Zhang Level: beginner
1803d4002b98SHong Zhang
180467be906fSBarry Smith .seealso: `Mat`, `MATSELL`, `MATSEQSELL` `MatCreateSELL()`
1805d4002b98SHong Zhang M*/
MatCreate_MPISELL(Mat B)1806d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_MPISELL(Mat B)
1807d71ae5a4SJacob Faibussowitsch {
1808d4002b98SHong Zhang Mat_MPISELL *b;
1809d4002b98SHong Zhang PetscMPIInt size;
1810d4002b98SHong Zhang
1811d4002b98SHong Zhang PetscFunctionBegin;
18129566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)B), &size));
18134dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&b));
1814d4002b98SHong Zhang B->data = (void *)b;
1815aea10558SJacob Faibussowitsch B->ops[0] = MatOps_Values;
1816d4002b98SHong Zhang B->assembled = PETSC_FALSE;
1817d4002b98SHong Zhang B->insertmode = NOT_SET_VALUES;
1818d4002b98SHong Zhang b->size = size;
18199566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)B), &b->rank));
1820d4002b98SHong Zhang /* build cache for off array entries formed */
18219566063dSJacob Faibussowitsch PetscCall(MatStashCreate_Private(PetscObjectComm((PetscObject)B), 1, &B->stash));
1822d4002b98SHong Zhang
1823d4002b98SHong Zhang b->donotstash = PETSC_FALSE;
1824f4259b30SLisandro Dalcin b->colmap = NULL;
1825f4259b30SLisandro Dalcin b->garray = NULL;
1826d4002b98SHong Zhang b->roworiented = PETSC_TRUE;
1827d4002b98SHong Zhang
1828d4002b98SHong Zhang /* stuff used for matrix vector multiply */
1829d4002b98SHong Zhang b->lvec = NULL;
1830d4002b98SHong Zhang b->Mvctx = NULL;
1831d4002b98SHong Zhang
1832d4002b98SHong Zhang /* stuff for MatGetRow() */
1833f4259b30SLisandro Dalcin b->rowindices = NULL;
1834f4259b30SLisandro Dalcin b->rowvalues = NULL;
1835d4002b98SHong Zhang b->getrowactive = PETSC_FALSE;
1836d4002b98SHong Zhang
18379566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatStoreValues_C", MatStoreValues_MPISELL));
18389566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatRetrieveValues_C", MatRetrieveValues_MPISELL));
18399566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatIsTranspose_C", MatIsTranspose_MPISELL));
18409566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatMPISELLSetPreallocation_C", MatMPISELLSetPreallocation_MPISELL));
18419566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_mpisell_mpiaij_C", MatConvert_MPISELL_MPIAIJ));
1842b5917f1bSHong Zhang #if defined(PETSC_HAVE_CUDA)
1843b5917f1bSHong Zhang PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_mpisell_mpisellcuda_C", MatConvert_MPISELL_MPISELLCUDA));
1844b5917f1bSHong Zhang #endif
18459566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDiagonalScaleLocal_C", MatDiagonalScaleLocal_MPISELL));
18469566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATMPISELL));
18473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1848d4002b98SHong Zhang }
1849