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 25d71ae5a4SJacob Faibussowitsch 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 */ 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; \ 69*4f8ff0b3SHong Zhang if (cp1[sliceheight * t] > col) high1 = t; \ 70d4002b98SHong Zhang else low1 = t; \ 71d4002b98SHong Zhang } \ 72d4002b98SHong Zhang for (_i = low1; _i < high1; _i++) { \ 73*4f8ff0b3SHong Zhang if (cp1[sliceheight * _i] > col) break; \ 74*4f8ff0b3SHong Zhang if (cp1[sliceheight * _i] == col) { \ 75*4f8ff0b3SHong Zhang if (addv == ADD_VALUES) vp1[sliceheight * _i] += value; \ 76*4f8ff0b3SHong 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--) { \ 95*4f8ff0b3SHong Zhang cp1[sliceheight * (ii + 1)] = cp1[sliceheight * ii]; \ 96*4f8ff0b3SHong Zhang vp1[sliceheight * (ii + 1)] = vp1[sliceheight * ii]; \ 97d4002b98SHong Zhang } \ 98*4f8ff0b3SHong Zhang cp1[sliceheight * _i] = col; \ 99*4f8ff0b3SHong Zhang vp1[sliceheight * _i] = value; \ 1009371c9d4SSatish Balay a->nz++; \ 1019371c9d4SSatish Balay nrow1++; \ 1029371c9d4SSatish Balay A->nonzerostate++; \ 103d4002b98SHong Zhang a_noinsert:; \ 104d4002b98SHong Zhang a->rlen[row] = nrow1; \ 105d4002b98SHong Zhang } 106d4002b98SHong Zhang 107d4002b98SHong Zhang #define MatSetValues_SeqSELL_B_Private(row, col, value, addv, orow, ocol) \ 108d4002b98SHong Zhang { \ 109d4002b98SHong Zhang if (col <= lastcol2) low2 = 0; \ 110d4002b98SHong Zhang else high2 = nrow2; \ 111d4002b98SHong Zhang lastcol2 = col; \ 112d4002b98SHong Zhang while (high2 - low2 > 5) { \ 113d4002b98SHong Zhang t = (low2 + high2) / 2; \ 114*4f8ff0b3SHong Zhang if (cp2[sliceheight * t] > col) high2 = t; \ 115d4002b98SHong Zhang else low2 = t; \ 116d4002b98SHong Zhang } \ 117d4002b98SHong Zhang for (_i = low2; _i < high2; _i++) { \ 118*4f8ff0b3SHong Zhang if (cp2[sliceheight * _i] > col) break; \ 119*4f8ff0b3SHong Zhang if (cp2[sliceheight * _i] == col) { \ 120*4f8ff0b3SHong Zhang if (addv == ADD_VALUES) vp2[sliceheight * _i] += value; \ 121*4f8ff0b3SHong Zhang else vp2[sliceheight * _i] = value; \ 1222d1451d4SHong Zhang inserted = PETSC_TRUE; \ 123d4002b98SHong Zhang goto b_noinsert; \ 124d4002b98SHong Zhang } \ 125d4002b98SHong Zhang } \ 1269371c9d4SSatish Balay if (value == 0.0 && ignorezeroentries) { \ 1279371c9d4SSatish Balay low2 = 0; \ 1289371c9d4SSatish Balay high2 = nrow2; \ 1299371c9d4SSatish Balay goto b_noinsert; \ 1309371c9d4SSatish Balay } \ 1319371c9d4SSatish Balay if (nonew == 1) { \ 1329371c9d4SSatish Balay low2 = 0; \ 1339371c9d4SSatish Balay high2 = nrow2; \ 1349371c9d4SSatish Balay goto b_noinsert; \ 1359371c9d4SSatish Balay } \ 13608401ef6SPierre 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); \ 13707e43b41SHong Zhang MatSeqXSELLReallocateSELL(B, bm, 1, nrow2, b->sliidx, b->sliceheight, row / sliceheight, row, col, b->colidx, b->val, cp2, vp2, nonew, MatScalar); \ 138d4002b98SHong Zhang /* shift up all the later entries in this row */ \ 139d4002b98SHong Zhang for (ii = nrow2 - 1; ii >= _i; ii--) { \ 140*4f8ff0b3SHong Zhang cp2[sliceheight * (ii + 1)] = cp2[sliceheight * ii]; \ 141*4f8ff0b3SHong Zhang vp2[sliceheight * (ii + 1)] = vp2[sliceheight * ii]; \ 142d4002b98SHong Zhang } \ 143*4f8ff0b3SHong Zhang cp2[sliceheight * _i] = col; \ 144*4f8ff0b3SHong Zhang vp2[sliceheight * _i] = value; \ 1459371c9d4SSatish Balay b->nz++; \ 1469371c9d4SSatish Balay nrow2++; \ 1479371c9d4SSatish Balay B->nonzerostate++; \ 148d4002b98SHong Zhang b_noinsert:; \ 149d4002b98SHong Zhang b->rlen[row] = nrow2; \ 150d4002b98SHong Zhang } 151d4002b98SHong Zhang 152d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetValues_MPISELL(Mat mat, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode addv) 153d71ae5a4SJacob Faibussowitsch { 154d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)mat->data; 155d4002b98SHong Zhang PetscScalar value; 156d4002b98SHong Zhang PetscInt i, j, rstart = mat->rmap->rstart, rend = mat->rmap->rend, shift1, shift2; 157d4002b98SHong Zhang PetscInt cstart = mat->cmap->rstart, cend = mat->cmap->rend, row, col; 158d4002b98SHong Zhang PetscBool roworiented = sell->roworiented; 159d4002b98SHong Zhang 160d4002b98SHong Zhang /* Some Variables required in the macro */ 161d4002b98SHong Zhang Mat A = sell->A; 162d4002b98SHong Zhang Mat_SeqSELL *a = (Mat_SeqSELL *)A->data; 163d4002b98SHong Zhang PetscBool ignorezeroentries = a->ignorezeroentries, found; 164d4002b98SHong Zhang Mat B = sell->B; 165d4002b98SHong Zhang Mat_SeqSELL *b = (Mat_SeqSELL *)B->data; 16607e43b41SHong Zhang PetscInt *cp1, *cp2, ii, _i, nrow1, nrow2, low1, high1, low2, high2, t, lastcol1, lastcol2, sliceheight = a->sliceheight; 167d4002b98SHong Zhang MatScalar *vp1, *vp2; 168d4002b98SHong Zhang 169d4002b98SHong Zhang PetscFunctionBegin; 170d4002b98SHong Zhang for (i = 0; i < m; i++) { 171d4002b98SHong Zhang if (im[i] < 0) continue; 1726bdcaf15SBarry 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); 173d4002b98SHong Zhang if (im[i] >= rstart && im[i] < rend) { 174d4002b98SHong Zhang row = im[i] - rstart; 175d4002b98SHong Zhang lastcol1 = -1; 17607e43b41SHong Zhang shift1 = a->sliidx[row / sliceheight] + (row % sliceheight); /* starting index of the row */ 177d4002b98SHong Zhang cp1 = a->colidx + shift1; 178d4002b98SHong Zhang vp1 = a->val + shift1; 179d4002b98SHong Zhang nrow1 = a->rlen[row]; 180d4002b98SHong Zhang low1 = 0; 181d4002b98SHong Zhang high1 = nrow1; 182d4002b98SHong Zhang lastcol2 = -1; 18307e43b41SHong Zhang shift2 = b->sliidx[row / sliceheight] + (row % sliceheight); /* starting index of the row */ 184d4002b98SHong Zhang cp2 = b->colidx + shift2; 185d4002b98SHong Zhang vp2 = b->val + shift2; 186d4002b98SHong Zhang nrow2 = b->rlen[row]; 187d4002b98SHong Zhang low2 = 0; 188d4002b98SHong Zhang high2 = nrow2; 189d4002b98SHong Zhang 190d4002b98SHong Zhang for (j = 0; j < n; j++) { 191d4002b98SHong Zhang if (roworiented) value = v[i * n + j]; 192d4002b98SHong Zhang else value = v[i + j * m]; 193d4002b98SHong Zhang if (ignorezeroentries && value == 0.0 && (addv == ADD_VALUES)) continue; 194d4002b98SHong Zhang if (in[j] >= cstart && in[j] < cend) { 195d4002b98SHong Zhang col = in[j] - cstart; 196d4002b98SHong Zhang MatSetValue_SeqSELL_Private(A, row, col, value, addv, im[i], in[j], cp1, vp1, lastcol1, low1, high1); /* set one value */ 1972d1451d4SHong Zhang #if defined(PETSC_HAVE_CUDA) 1982d1451d4SHong Zhang if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED && found) A->offloadmask = PETSC_OFFLOAD_CPU; 1992d1451d4SHong Zhang #endif 200f7d195e4SLawrence Mitchell } else if (in[j] < 0) { 201f7d195e4SLawrence Mitchell continue; 202f7d195e4SLawrence Mitchell } else { 203f7d195e4SLawrence 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); 204d4002b98SHong Zhang if (mat->was_assembled) { 20548a46eb9SPierre Jolivet if (!sell->colmap) PetscCall(MatCreateColmap_MPISELL_Private(mat)); 206d4002b98SHong Zhang #if defined(PETSC_USE_CTABLE) 207eec179cfSJacob Faibussowitsch PetscCall(PetscHMapIGetWithDefault(sell->colmap, in[j] + 1, 0, &col)); 208d4002b98SHong Zhang col--; 209d4002b98SHong Zhang #else 210d4002b98SHong Zhang col = sell->colmap[in[j]] - 1; 211d4002b98SHong Zhang #endif 212d4002b98SHong Zhang if (col < 0 && !((Mat_SeqSELL *)(sell->B->data))->nonew) { 2139566063dSJacob Faibussowitsch PetscCall(MatDisAssemble_MPISELL(mat)); 214d4002b98SHong Zhang col = in[j]; 215d4002b98SHong Zhang /* Reinitialize the variables required by MatSetValues_SeqSELL_B_Private() */ 216d4002b98SHong Zhang B = sell->B; 217d4002b98SHong Zhang b = (Mat_SeqSELL *)B->data; 21807e43b41SHong Zhang shift2 = b->sliidx[row / sliceheight] + (row % sliceheight); /* starting index of the row */ 219d4002b98SHong Zhang cp2 = b->colidx + shift2; 220d4002b98SHong Zhang vp2 = b->val + shift2; 221d4002b98SHong Zhang nrow2 = b->rlen[row]; 222d4002b98SHong Zhang low2 = 0; 223d4002b98SHong Zhang high2 = nrow2; 2242d1451d4SHong Zhang found = PETSC_FALSE; 225f7d195e4SLawrence Mitchell } else { 226f7d195e4SLawrence 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]); 227f7d195e4SLawrence Mitchell } 228d4002b98SHong Zhang } else col = in[j]; 229d4002b98SHong Zhang MatSetValue_SeqSELL_Private(B, row, col, value, addv, im[i], in[j], cp2, vp2, lastcol2, low2, high2); /* set one value */ 2302d1451d4SHong Zhang #if defined(PETSC_HAVE_CUDA) 2312d1451d4SHong Zhang if (B->offloadmask != PETSC_OFFLOAD_UNALLOCATED && found) B->offloadmask = PETSC_OFFLOAD_CPU; 2322d1451d4SHong Zhang #endif 233d4002b98SHong Zhang } 234d4002b98SHong Zhang } 235d4002b98SHong Zhang } else { 23628b400f6SJacob 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]); 237d4002b98SHong Zhang if (!sell->donotstash) { 238d4002b98SHong Zhang mat->assembled = PETSC_FALSE; 239d4002b98SHong Zhang if (roworiented) { 2409566063dSJacob Faibussowitsch PetscCall(MatStashValuesRow_Private(&mat->stash, im[i], n, in, v + i * n, (PetscBool)(ignorezeroentries && (addv == ADD_VALUES)))); 241d4002b98SHong Zhang } else { 2429566063dSJacob Faibussowitsch PetscCall(MatStashValuesCol_Private(&mat->stash, im[i], n, in, v + i, m, (PetscBool)(ignorezeroentries && (addv == ADD_VALUES)))); 243d4002b98SHong Zhang } 244d4002b98SHong Zhang } 245d4002b98SHong Zhang } 246d4002b98SHong Zhang } 2473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 248d4002b98SHong Zhang } 249d4002b98SHong Zhang 250d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetValues_MPISELL(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 251d71ae5a4SJacob Faibussowitsch { 252d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)mat->data; 253d4002b98SHong Zhang PetscInt i, j, rstart = mat->rmap->rstart, rend = mat->rmap->rend; 254d4002b98SHong Zhang PetscInt cstart = mat->cmap->rstart, cend = mat->cmap->rend, row, col; 255d4002b98SHong Zhang 256d4002b98SHong Zhang PetscFunctionBegin; 257d4002b98SHong Zhang for (i = 0; i < m; i++) { 25854c59aa7SJacob Faibussowitsch if (idxm[i] < 0) continue; /* negative row */ 25954c59aa7SJacob 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); 260d4002b98SHong Zhang if (idxm[i] >= rstart && idxm[i] < rend) { 261d4002b98SHong Zhang row = idxm[i] - rstart; 262d4002b98SHong Zhang for (j = 0; j < n; j++) { 26354c59aa7SJacob Faibussowitsch if (idxn[j] < 0) continue; /* negative column */ 26454c59aa7SJacob 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); 265d4002b98SHong Zhang if (idxn[j] >= cstart && idxn[j] < cend) { 266d4002b98SHong Zhang col = idxn[j] - cstart; 2679566063dSJacob Faibussowitsch PetscCall(MatGetValues(sell->A, 1, &row, 1, &col, v + i * n + j)); 268d4002b98SHong Zhang } else { 26948a46eb9SPierre Jolivet if (!sell->colmap) PetscCall(MatCreateColmap_MPISELL_Private(mat)); 270d4002b98SHong Zhang #if defined(PETSC_USE_CTABLE) 271eec179cfSJacob Faibussowitsch PetscCall(PetscHMapIGetWithDefault(sell->colmap, idxn[j] + 1, 0, &col)); 272d4002b98SHong Zhang col--; 273d4002b98SHong Zhang #else 274d4002b98SHong Zhang col = sell->colmap[idxn[j]] - 1; 275d4002b98SHong Zhang #endif 276d4002b98SHong Zhang if ((col < 0) || (sell->garray[col] != idxn[j])) *(v + i * n + j) = 0.0; 27748a46eb9SPierre Jolivet else PetscCall(MatGetValues(sell->B, 1, &row, 1, &col, v + i * n + j)); 278d4002b98SHong Zhang } 279d4002b98SHong Zhang } 280d4002b98SHong Zhang } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only local values currently supported"); 281d4002b98SHong Zhang } 2823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 283d4002b98SHong Zhang } 284d4002b98SHong Zhang 285d4002b98SHong Zhang extern PetscErrorCode MatMultDiagonalBlock_MPISELL(Mat, Vec, Vec); 286d4002b98SHong Zhang 287d71ae5a4SJacob Faibussowitsch PetscErrorCode MatAssemblyBegin_MPISELL(Mat mat, MatAssemblyType mode) 288d71ae5a4SJacob Faibussowitsch { 289d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)mat->data; 290d4002b98SHong Zhang PetscInt nstash, reallocs; 291d4002b98SHong Zhang 292d4002b98SHong Zhang PetscFunctionBegin; 2933ba16761SJacob Faibussowitsch if (sell->donotstash || mat->nooffprocentries) PetscFunctionReturn(PETSC_SUCCESS); 294d4002b98SHong Zhang 2959566063dSJacob Faibussowitsch PetscCall(MatStashScatterBegin_Private(mat, &mat->stash, mat->rmap->range)); 2969566063dSJacob Faibussowitsch PetscCall(MatStashGetInfo_Private(&mat->stash, &nstash, &reallocs)); 2979566063dSJacob Faibussowitsch PetscCall(PetscInfo(sell->A, "Stash has %" PetscInt_FMT " entries, uses %" PetscInt_FMT " mallocs.\n", nstash, reallocs)); 2983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 299d4002b98SHong Zhang } 300d4002b98SHong Zhang 301d71ae5a4SJacob Faibussowitsch PetscErrorCode MatAssemblyEnd_MPISELL(Mat mat, MatAssemblyType mode) 302d71ae5a4SJacob Faibussowitsch { 303d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)mat->data; 304d4002b98SHong Zhang PetscMPIInt n; 305d4002b98SHong Zhang PetscInt i, flg; 306d4002b98SHong Zhang PetscInt *row, *col; 307d4002b98SHong Zhang PetscScalar *val; 308d4002b98SHong Zhang PetscBool other_disassembled; 309d4002b98SHong Zhang /* do not use 'b = (Mat_SeqSELL*)sell->B->data' as B can be reset in disassembly */ 310d4002b98SHong Zhang PetscFunctionBegin; 311d4002b98SHong Zhang if (!sell->donotstash && !mat->nooffprocentries) { 312d4002b98SHong Zhang while (1) { 3139566063dSJacob Faibussowitsch PetscCall(MatStashScatterGetMesg_Private(&mat->stash, &n, &row, &col, &val, &flg)); 314d4002b98SHong Zhang if (!flg) break; 315d4002b98SHong Zhang 316d4002b98SHong Zhang for (i = 0; i < n; i++) { /* assemble one by one */ 3179566063dSJacob Faibussowitsch PetscCall(MatSetValues_MPISELL(mat, 1, row + i, 1, col + i, val + i, mat->insertmode)); 318d4002b98SHong Zhang } 319d4002b98SHong Zhang } 3209566063dSJacob Faibussowitsch PetscCall(MatStashScatterEnd_Private(&mat->stash)); 321d4002b98SHong Zhang } 3222d1451d4SHong Zhang #if defined(PETSC_HAVE_CUDA) 3232d1451d4SHong Zhang if (mat->offloadmask == PETSC_OFFLOAD_CPU) sell->A->offloadmask = PETSC_OFFLOAD_CPU; 3242d1451d4SHong Zhang #endif 3259566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(sell->A, mode)); 3269566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(sell->A, mode)); 327d4002b98SHong Zhang 328d4002b98SHong Zhang /* 329d4002b98SHong Zhang determine if any processor has disassembled, if so we must 3306aad120cSJose E. Roman also disassemble ourselves, in order that we may reassemble. 331d4002b98SHong Zhang */ 332d4002b98SHong Zhang /* 333d4002b98SHong Zhang if nonzero structure of submatrix B cannot change then we know that 334d4002b98SHong Zhang no processor disassembled thus we can skip this stuff 335d4002b98SHong Zhang */ 336d4002b98SHong Zhang if (!((Mat_SeqSELL *)sell->B->data)->nonew) { 3375f9db2b2SJunchao Zhang PetscCall(MPIU_Allreduce(&mat->was_assembled, &other_disassembled, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)mat))); 3382d1451d4SHong Zhang if (mat->was_assembled && !other_disassembled) PetscCall(MatDisAssemble_MPISELL(mat)); 339d4002b98SHong Zhang } 34048a46eb9SPierre Jolivet if (!mat->was_assembled && mode == MAT_FINAL_ASSEMBLY) PetscCall(MatSetUpMultiply_MPISELL(mat)); 3412d1451d4SHong Zhang #if defined(PETSC_HAVE_CUDA) 3422d1451d4SHong Zhang if (mat->offloadmask == PETSC_OFFLOAD_CPU && sell->B->offloadmask != PETSC_OFFLOAD_UNALLOCATED) sell->B->offloadmask = PETSC_OFFLOAD_CPU; 3432d1451d4SHong Zhang #endif 3449566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(sell->B, mode)); 3459566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(sell->B, mode)); 3469566063dSJacob Faibussowitsch PetscCall(PetscFree2(sell->rowvalues, sell->rowindices)); 347f4259b30SLisandro Dalcin sell->rowvalues = NULL; 3489566063dSJacob Faibussowitsch PetscCall(VecDestroy(&sell->diag)); 349d4002b98SHong Zhang 350d4002b98SHong Zhang /* if no new nonzero locations are allowed in matrix then only set the matrix state the first time through */ 351d4002b98SHong Zhang if ((!mat->was_assembled && mode == MAT_FINAL_ASSEMBLY) || !((Mat_SeqSELL *)(sell->A->data))->nonew) { 352d4002b98SHong Zhang PetscObjectState state = sell->A->nonzerostate + sell->B->nonzerostate; 3531c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&state, &mat->nonzerostate, 1, MPIU_INT64, MPI_SUM, PetscObjectComm((PetscObject)mat))); 354d4002b98SHong Zhang } 3552d1451d4SHong Zhang #if defined(PETSC_HAVE_CUDA) 3562d1451d4SHong Zhang mat->offloadmask = PETSC_OFFLOAD_BOTH; 3572d1451d4SHong Zhang #endif 3583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 359d4002b98SHong Zhang } 360d4002b98SHong Zhang 361d71ae5a4SJacob Faibussowitsch PetscErrorCode MatZeroEntries_MPISELL(Mat A) 362d71ae5a4SJacob Faibussowitsch { 363d4002b98SHong Zhang Mat_MPISELL *l = (Mat_MPISELL *)A->data; 364d4002b98SHong Zhang 365d4002b98SHong Zhang PetscFunctionBegin; 3669566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(l->A)); 3679566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(l->B)); 3683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 369d4002b98SHong Zhang } 370d4002b98SHong Zhang 371d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMult_MPISELL(Mat A, Vec xx, Vec yy) 372d71ae5a4SJacob Faibussowitsch { 373d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 374d4002b98SHong Zhang PetscInt nt; 375d4002b98SHong Zhang 376d4002b98SHong Zhang PetscFunctionBegin; 3779566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(xx, &nt)); 37808401ef6SPierre 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); 3799566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(a->Mvctx, xx, a->lvec, INSERT_VALUES, SCATTER_FORWARD)); 3809566063dSJacob Faibussowitsch PetscCall((*a->A->ops->mult)(a->A, xx, yy)); 3819566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(a->Mvctx, xx, a->lvec, INSERT_VALUES, SCATTER_FORWARD)); 3829566063dSJacob Faibussowitsch PetscCall((*a->B->ops->multadd)(a->B, a->lvec, yy, yy)); 3833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 384d4002b98SHong Zhang } 385d4002b98SHong Zhang 386d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultDiagonalBlock_MPISELL(Mat A, Vec bb, Vec xx) 387d71ae5a4SJacob Faibussowitsch { 388d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 389d4002b98SHong Zhang 390d4002b98SHong Zhang PetscFunctionBegin; 3919566063dSJacob Faibussowitsch PetscCall(MatMultDiagonalBlock(a->A, bb, xx)); 3923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 393d4002b98SHong Zhang } 394d4002b98SHong Zhang 395d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultAdd_MPISELL(Mat A, Vec xx, Vec yy, Vec zz) 396d71ae5a4SJacob Faibussowitsch { 397d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 398d4002b98SHong Zhang 399d4002b98SHong Zhang PetscFunctionBegin; 4009566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(a->Mvctx, xx, a->lvec, INSERT_VALUES, SCATTER_FORWARD)); 4019566063dSJacob Faibussowitsch PetscCall((*a->A->ops->multadd)(a->A, xx, yy, zz)); 4029566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(a->Mvctx, xx, a->lvec, INSERT_VALUES, SCATTER_FORWARD)); 4039566063dSJacob Faibussowitsch PetscCall((*a->B->ops->multadd)(a->B, a->lvec, zz, zz)); 4043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 405d4002b98SHong Zhang } 406d4002b98SHong Zhang 407d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultTranspose_MPISELL(Mat A, Vec xx, Vec yy) 408d71ae5a4SJacob Faibussowitsch { 409d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 410d4002b98SHong Zhang 411d4002b98SHong Zhang PetscFunctionBegin; 412d4002b98SHong Zhang /* do nondiagonal part */ 4139566063dSJacob Faibussowitsch PetscCall((*a->B->ops->multtranspose)(a->B, xx, a->lvec)); 414d4002b98SHong Zhang /* do local part */ 4159566063dSJacob Faibussowitsch PetscCall((*a->A->ops->multtranspose)(a->A, xx, yy)); 416a29b4eb7SJunchao Zhang /* add partial results together */ 4179566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(a->Mvctx, a->lvec, yy, ADD_VALUES, SCATTER_REVERSE)); 4189566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(a->Mvctx, a->lvec, yy, ADD_VALUES, SCATTER_REVERSE)); 4193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 420d4002b98SHong Zhang } 421d4002b98SHong Zhang 422d71ae5a4SJacob Faibussowitsch PetscErrorCode MatIsTranspose_MPISELL(Mat Amat, Mat Bmat, PetscReal tol, PetscBool *f) 423d71ae5a4SJacob Faibussowitsch { 424d4002b98SHong Zhang MPI_Comm comm; 425d4002b98SHong Zhang Mat_MPISELL *Asell = (Mat_MPISELL *)Amat->data, *Bsell; 426d4002b98SHong Zhang Mat Adia = Asell->A, Bdia, Aoff, Boff, *Aoffs, *Boffs; 427d4002b98SHong Zhang IS Me, Notme; 428d4002b98SHong Zhang PetscInt M, N, first, last, *notme, i; 429d4002b98SHong Zhang PetscMPIInt size; 430d4002b98SHong Zhang 431d4002b98SHong Zhang PetscFunctionBegin; 432d4002b98SHong Zhang /* Easy test: symmetric diagonal block */ 4339371c9d4SSatish Balay Bsell = (Mat_MPISELL *)Bmat->data; 4349371c9d4SSatish Balay Bdia = Bsell->A; 4359566063dSJacob Faibussowitsch PetscCall(MatIsTranspose(Adia, Bdia, tol, f)); 4363ba16761SJacob Faibussowitsch if (!*f) PetscFunctionReturn(PETSC_SUCCESS); 4379566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)Amat, &comm)); 4389566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 4393ba16761SJacob Faibussowitsch if (size == 1) PetscFunctionReturn(PETSC_SUCCESS); 440d4002b98SHong Zhang 441d4002b98SHong Zhang /* Hard test: off-diagonal block. This takes a MatCreateSubMatrix. */ 4429566063dSJacob Faibussowitsch PetscCall(MatGetSize(Amat, &M, &N)); 4439566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(Amat, &first, &last)); 4449566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(N - last + first, ¬me)); 445d4002b98SHong Zhang for (i = 0; i < first; i++) notme[i] = i; 446d4002b98SHong Zhang for (i = last; i < M; i++) notme[i - last + first] = i; 4479566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(MPI_COMM_SELF, N - last + first, notme, PETSC_COPY_VALUES, &Notme)); 4489566063dSJacob Faibussowitsch PetscCall(ISCreateStride(MPI_COMM_SELF, last - first, first, 1, &Me)); 4499566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrices(Amat, 1, &Me, &Notme, MAT_INITIAL_MATRIX, &Aoffs)); 450d4002b98SHong Zhang Aoff = Aoffs[0]; 4519566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrices(Bmat, 1, &Notme, &Me, MAT_INITIAL_MATRIX, &Boffs)); 452d4002b98SHong Zhang Boff = Boffs[0]; 4539566063dSJacob Faibussowitsch PetscCall(MatIsTranspose(Aoff, Boff, tol, f)); 4549566063dSJacob Faibussowitsch PetscCall(MatDestroyMatrices(1, &Aoffs)); 4559566063dSJacob Faibussowitsch PetscCall(MatDestroyMatrices(1, &Boffs)); 4569566063dSJacob Faibussowitsch PetscCall(ISDestroy(&Me)); 4579566063dSJacob Faibussowitsch PetscCall(ISDestroy(&Notme)); 4589566063dSJacob Faibussowitsch PetscCall(PetscFree(notme)); 4593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 460d4002b98SHong Zhang } 461d4002b98SHong Zhang 462d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultTransposeAdd_MPISELL(Mat A, Vec xx, Vec yy, Vec zz) 463d71ae5a4SJacob Faibussowitsch { 464d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 465d4002b98SHong Zhang 466d4002b98SHong Zhang PetscFunctionBegin; 467d4002b98SHong Zhang /* do nondiagonal part */ 4689566063dSJacob Faibussowitsch PetscCall((*a->B->ops->multtranspose)(a->B, xx, a->lvec)); 469d4002b98SHong Zhang /* do local part */ 4709566063dSJacob Faibussowitsch PetscCall((*a->A->ops->multtransposeadd)(a->A, xx, yy, zz)); 471e4a140f6SJunchao Zhang /* add partial results together */ 4729566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(a->Mvctx, a->lvec, zz, ADD_VALUES, SCATTER_REVERSE)); 4739566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(a->Mvctx, a->lvec, zz, ADD_VALUES, SCATTER_REVERSE)); 4743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 475d4002b98SHong Zhang } 476d4002b98SHong Zhang 477d4002b98SHong Zhang /* 478d4002b98SHong Zhang This only works correctly for square matrices where the subblock A->A is the 479d4002b98SHong Zhang diagonal block 480d4002b98SHong Zhang */ 481d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetDiagonal_MPISELL(Mat A, Vec v) 482d71ae5a4SJacob Faibussowitsch { 483d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 484d4002b98SHong Zhang 485d4002b98SHong Zhang PetscFunctionBegin; 48608401ef6SPierre Jolivet PetscCheck(A->rmap->N == A->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Supports only square matrix where A->A is diag block"); 487aed4548fSBarry 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"); 4889566063dSJacob Faibussowitsch PetscCall(MatGetDiagonal(a->A, v)); 4893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 490d4002b98SHong Zhang } 491d4002b98SHong Zhang 492d71ae5a4SJacob Faibussowitsch PetscErrorCode MatScale_MPISELL(Mat A, PetscScalar aa) 493d71ae5a4SJacob Faibussowitsch { 494d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 495d4002b98SHong Zhang 496d4002b98SHong Zhang PetscFunctionBegin; 4979566063dSJacob Faibussowitsch PetscCall(MatScale(a->A, aa)); 4989566063dSJacob Faibussowitsch PetscCall(MatScale(a->B, aa)); 4993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 500d4002b98SHong Zhang } 501d4002b98SHong Zhang 502d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDestroy_MPISELL(Mat mat) 503d71ae5a4SJacob Faibussowitsch { 504d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)mat->data; 505d4002b98SHong Zhang 506d4002b98SHong Zhang PetscFunctionBegin; 507d4002b98SHong Zhang #if defined(PETSC_USE_LOG) 5083ba16761SJacob Faibussowitsch PetscCall(PetscLogObjectState((PetscObject)mat, "Rows=%" PetscInt_FMT ", Cols=%" PetscInt_FMT, mat->rmap->N, mat->cmap->N)); 509d4002b98SHong Zhang #endif 5109566063dSJacob Faibussowitsch PetscCall(MatStashDestroy_Private(&mat->stash)); 5119566063dSJacob Faibussowitsch PetscCall(VecDestroy(&sell->diag)); 5129566063dSJacob Faibussowitsch PetscCall(MatDestroy(&sell->A)); 5139566063dSJacob Faibussowitsch PetscCall(MatDestroy(&sell->B)); 514d4002b98SHong Zhang #if defined(PETSC_USE_CTABLE) 515eec179cfSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&sell->colmap)); 516d4002b98SHong Zhang #else 5179566063dSJacob Faibussowitsch PetscCall(PetscFree(sell->colmap)); 518d4002b98SHong Zhang #endif 5199566063dSJacob Faibussowitsch PetscCall(PetscFree(sell->garray)); 5209566063dSJacob Faibussowitsch PetscCall(VecDestroy(&sell->lvec)); 5219566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&sell->Mvctx)); 5229566063dSJacob Faibussowitsch PetscCall(PetscFree2(sell->rowvalues, sell->rowindices)); 5239566063dSJacob Faibussowitsch PetscCall(PetscFree(sell->ld)); 5249566063dSJacob Faibussowitsch PetscCall(PetscFree(mat->data)); 525d4002b98SHong Zhang 5269566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)mat, NULL)); 5279566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatStoreValues_C", NULL)); 5289566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatRetrieveValues_C", NULL)); 5299566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatIsTranspose_C", NULL)); 5309566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatMPISELLSetPreallocation_C", NULL)); 5319566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_mpisell_mpiaij_C", NULL)); 5329566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDiagonalScaleLocal_C", NULL)); 5333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 534d4002b98SHong Zhang } 535d4002b98SHong Zhang 536d4002b98SHong Zhang #include <petscdraw.h> 537d71ae5a4SJacob Faibussowitsch PetscErrorCode MatView_MPISELL_ASCIIorDraworSocket(Mat mat, PetscViewer viewer) 538d71ae5a4SJacob Faibussowitsch { 539d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)mat->data; 540d4002b98SHong Zhang PetscMPIInt rank = sell->rank, size = sell->size; 541d4002b98SHong Zhang PetscBool isdraw, iascii, isbinary; 542d4002b98SHong Zhang PetscViewer sviewer; 543d4002b98SHong Zhang PetscViewerFormat format; 544d4002b98SHong Zhang 545d4002b98SHong Zhang PetscFunctionBegin; 5469566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 5479566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 5489566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 549d4002b98SHong Zhang if (iascii) { 5509566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 551d4002b98SHong Zhang if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 552d4002b98SHong Zhang MatInfo info; 5536335e310SSatish Balay PetscInt *inodes; 554d4002b98SHong Zhang 5559566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)mat), &rank)); 5569566063dSJacob Faibussowitsch PetscCall(MatGetInfo(mat, MAT_LOCAL, &info)); 5579566063dSJacob Faibussowitsch PetscCall(MatInodeGetInodeSizes(sell->A, NULL, &inodes, NULL)); 5589566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 559d4002b98SHong Zhang if (!inodes) { 5609371c9d4SSatish 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, 5619371c9d4SSatish Balay (PetscInt)info.nz_allocated, (PetscInt)info.memory)); 562d4002b98SHong Zhang } else { 5639371c9d4SSatish 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, 5649371c9d4SSatish Balay (PetscInt)info.nz_allocated, (PetscInt)info.memory)); 565d4002b98SHong Zhang } 5669566063dSJacob Faibussowitsch PetscCall(MatGetInfo(sell->A, MAT_LOCAL, &info)); 5679566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] on-diagonal part: nz %" PetscInt_FMT " \n", rank, (PetscInt)info.nz_used)); 5689566063dSJacob Faibussowitsch PetscCall(MatGetInfo(sell->B, MAT_LOCAL, &info)); 5699566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] off-diagonal part: nz %" PetscInt_FMT " \n", rank, (PetscInt)info.nz_used)); 5709566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 5719566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 5729566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Information on VecScatter used in matrix-vector product: \n")); 5739566063dSJacob Faibussowitsch PetscCall(VecScatterView(sell->Mvctx, viewer)); 5743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 575d4002b98SHong Zhang } else if (format == PETSC_VIEWER_ASCII_INFO) { 576d4002b98SHong Zhang PetscInt inodecount, inodelimit, *inodes; 5779566063dSJacob Faibussowitsch PetscCall(MatInodeGetInodeSizes(sell->A, &inodecount, &inodes, &inodelimit)); 578d4002b98SHong Zhang if (inodes) { 5799566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "using I-node (on process 0) routines: found %" PetscInt_FMT " nodes, limit used is %" PetscInt_FMT "\n", inodecount, inodelimit)); 580d4002b98SHong Zhang } else { 5819566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "not using I-node (on process 0) routines\n")); 582d4002b98SHong Zhang } 5833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 584d4002b98SHong Zhang } else if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) { 5853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 586d4002b98SHong Zhang } 587d4002b98SHong Zhang } else if (isbinary) { 588d4002b98SHong Zhang if (size == 1) { 5899566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)sell->A, ((PetscObject)mat)->name)); 5909566063dSJacob Faibussowitsch PetscCall(MatView(sell->A, viewer)); 591d4002b98SHong Zhang } else { 5929566063dSJacob Faibussowitsch /* PetscCall(MatView_MPISELL_Binary(mat,viewer)); */ 593d4002b98SHong Zhang } 5943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 595d4002b98SHong Zhang } else if (isdraw) { 596d4002b98SHong Zhang PetscDraw draw; 597d4002b98SHong Zhang PetscBool isnull; 5989566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 5999566063dSJacob Faibussowitsch PetscCall(PetscDrawIsNull(draw, &isnull)); 6003ba16761SJacob Faibussowitsch if (isnull) PetscFunctionReturn(PETSC_SUCCESS); 601d4002b98SHong Zhang } 602d4002b98SHong Zhang 603d4002b98SHong Zhang { 604d4002b98SHong Zhang /* assemble the entire matrix onto first processor. */ 605d4002b98SHong Zhang Mat A; 606d4002b98SHong Zhang Mat_SeqSELL *Aloc; 607d4002b98SHong Zhang PetscInt M = mat->rmap->N, N = mat->cmap->N, *acolidx, row, col, i, j; 608d4002b98SHong Zhang MatScalar *aval; 609d4002b98SHong Zhang PetscBool isnonzero; 610d4002b98SHong Zhang 6119566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &A)); 612dd400576SPatrick Sanan if (rank == 0) { 6139566063dSJacob Faibussowitsch PetscCall(MatSetSizes(A, M, N, M, N)); 614d4002b98SHong Zhang } else { 6159566063dSJacob Faibussowitsch PetscCall(MatSetSizes(A, 0, 0, M, N)); 616d4002b98SHong Zhang } 617d4002b98SHong Zhang /* This is just a temporary matrix, so explicitly using MATMPISELL is probably best */ 6189566063dSJacob Faibussowitsch PetscCall(MatSetType(A, MATMPISELL)); 6199566063dSJacob Faibussowitsch PetscCall(MatMPISELLSetPreallocation(A, 0, NULL, 0, NULL)); 6209566063dSJacob Faibussowitsch PetscCall(MatSetOption(A, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_FALSE)); 621d4002b98SHong Zhang 622d4002b98SHong Zhang /* copy over the A part */ 623d4002b98SHong Zhang Aloc = (Mat_SeqSELL *)sell->A->data; 6249371c9d4SSatish Balay acolidx = Aloc->colidx; 6259371c9d4SSatish Balay aval = Aloc->val; 626d4002b98SHong Zhang for (i = 0; i < Aloc->totalslices; i++) { /* loop over slices */ 627d4002b98SHong Zhang for (j = Aloc->sliidx[i]; j < Aloc->sliidx[i + 1]; j++) { 62807e43b41SHong Zhang isnonzero = (PetscBool)((j - Aloc->sliidx[i]) / Aloc->sliceheight < Aloc->rlen[i * Aloc->sliceheight + j % Aloc->sliceheight]); 629d4002b98SHong Zhang if (isnonzero) { /* check the mask bit */ 63007e43b41SHong Zhang row = i * Aloc->sliceheight + j % Aloc->sliceheight + mat->rmap->rstart; 631d4002b98SHong Zhang col = *acolidx + mat->rmap->rstart; 6329566063dSJacob Faibussowitsch PetscCall(MatSetValues(A, 1, &row, 1, &col, aval, INSERT_VALUES)); 633d4002b98SHong Zhang } 6349371c9d4SSatish Balay aval++; 6359371c9d4SSatish Balay acolidx++; 636d4002b98SHong Zhang } 637d4002b98SHong Zhang } 638d4002b98SHong Zhang 639d4002b98SHong Zhang /* copy over the B part */ 640d4002b98SHong Zhang Aloc = (Mat_SeqSELL *)sell->B->data; 6419371c9d4SSatish Balay acolidx = Aloc->colidx; 6429371c9d4SSatish Balay aval = Aloc->val; 643d4002b98SHong Zhang for (i = 0; i < Aloc->totalslices; i++) { 644d4002b98SHong Zhang for (j = Aloc->sliidx[i]; j < Aloc->sliidx[i + 1]; j++) { 64507e43b41SHong Zhang isnonzero = (PetscBool)((j - Aloc->sliidx[i]) / Aloc->sliceheight < Aloc->rlen[i * Aloc->sliceheight + j % Aloc->sliceheight]); 646d4002b98SHong Zhang if (isnonzero) { 64707e43b41SHong Zhang row = i * Aloc->sliceheight + j % Aloc->sliceheight + mat->rmap->rstart; 648d4002b98SHong Zhang col = sell->garray[*acolidx]; 6499566063dSJacob Faibussowitsch PetscCall(MatSetValues(A, 1, &row, 1, &col, aval, INSERT_VALUES)); 650d4002b98SHong Zhang } 6519371c9d4SSatish Balay aval++; 6529371c9d4SSatish Balay acolidx++; 653d4002b98SHong Zhang } 654d4002b98SHong Zhang } 655d4002b98SHong Zhang 6569566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 6579566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 658d4002b98SHong Zhang /* 659d4002b98SHong Zhang Everyone has to call to draw the matrix since the graphics waits are 660d4002b98SHong Zhang synchronized across all processors that share the PetscDraw object 661d4002b98SHong Zhang */ 6629566063dSJacob Faibussowitsch PetscCall(PetscViewerGetSubViewer(viewer, PETSC_COMM_SELF, &sviewer)); 663dd400576SPatrick Sanan if (rank == 0) { 6649566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)((Mat_MPISELL *)(A->data))->A, ((PetscObject)mat)->name)); 6659566063dSJacob Faibussowitsch PetscCall(MatView_SeqSELL(((Mat_MPISELL *)(A->data))->A, sviewer)); 666d4002b98SHong Zhang } 6679566063dSJacob Faibussowitsch PetscCall(PetscViewerRestoreSubViewer(viewer, PETSC_COMM_SELF, &sviewer)); 6689566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 6699566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A)); 670d4002b98SHong Zhang } 6713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 672d4002b98SHong Zhang } 673d4002b98SHong Zhang 674d71ae5a4SJacob Faibussowitsch PetscErrorCode MatView_MPISELL(Mat mat, PetscViewer viewer) 675d71ae5a4SJacob Faibussowitsch { 676d4002b98SHong Zhang PetscBool iascii, isdraw, issocket, isbinary; 677d4002b98SHong Zhang 678d4002b98SHong Zhang PetscFunctionBegin; 6799566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 6809566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 6819566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 6829566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSOCKET, &issocket)); 68348a46eb9SPierre Jolivet if (iascii || isdraw || isbinary || issocket) PetscCall(MatView_MPISELL_ASCIIorDraworSocket(mat, viewer)); 6843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 685d4002b98SHong Zhang } 686d4002b98SHong Zhang 687d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetGhosts_MPISELL(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[]) 688d71ae5a4SJacob Faibussowitsch { 689d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)mat->data; 690d4002b98SHong Zhang 691d4002b98SHong Zhang PetscFunctionBegin; 6929566063dSJacob Faibussowitsch PetscCall(MatGetSize(sell->B, NULL, nghosts)); 693d4002b98SHong Zhang if (ghosts) *ghosts = sell->garray; 6943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 695d4002b98SHong Zhang } 696d4002b98SHong Zhang 697d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetInfo_MPISELL(Mat matin, MatInfoType flag, MatInfo *info) 698d71ae5a4SJacob Faibussowitsch { 699d4002b98SHong Zhang Mat_MPISELL *mat = (Mat_MPISELL *)matin->data; 700d4002b98SHong Zhang Mat A = mat->A, B = mat->B; 7013966268fSBarry Smith PetscLogDouble isend[5], irecv[5]; 702d4002b98SHong Zhang 703d4002b98SHong Zhang PetscFunctionBegin; 704d4002b98SHong Zhang info->block_size = 1.0; 7059566063dSJacob Faibussowitsch PetscCall(MatGetInfo(A, MAT_LOCAL, info)); 706d4002b98SHong Zhang 7079371c9d4SSatish Balay isend[0] = info->nz_used; 7089371c9d4SSatish Balay isend[1] = info->nz_allocated; 7099371c9d4SSatish Balay isend[2] = info->nz_unneeded; 7109371c9d4SSatish Balay isend[3] = info->memory; 7119371c9d4SSatish Balay isend[4] = info->mallocs; 712d4002b98SHong Zhang 7139566063dSJacob Faibussowitsch PetscCall(MatGetInfo(B, MAT_LOCAL, info)); 714d4002b98SHong Zhang 7159371c9d4SSatish Balay isend[0] += info->nz_used; 7169371c9d4SSatish Balay isend[1] += info->nz_allocated; 7179371c9d4SSatish Balay isend[2] += info->nz_unneeded; 7189371c9d4SSatish Balay isend[3] += info->memory; 7199371c9d4SSatish Balay isend[4] += info->mallocs; 720d4002b98SHong Zhang if (flag == MAT_LOCAL) { 721d4002b98SHong Zhang info->nz_used = isend[0]; 722d4002b98SHong Zhang info->nz_allocated = isend[1]; 723d4002b98SHong Zhang info->nz_unneeded = isend[2]; 724d4002b98SHong Zhang info->memory = isend[3]; 725d4002b98SHong Zhang info->mallocs = isend[4]; 726d4002b98SHong Zhang } else if (flag == MAT_GLOBAL_MAX) { 7271c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(isend, irecv, 5, MPIU_PETSCLOGDOUBLE, MPI_MAX, PetscObjectComm((PetscObject)matin))); 728d4002b98SHong Zhang 729d4002b98SHong Zhang info->nz_used = irecv[0]; 730d4002b98SHong Zhang info->nz_allocated = irecv[1]; 731d4002b98SHong Zhang info->nz_unneeded = irecv[2]; 732d4002b98SHong Zhang info->memory = irecv[3]; 733d4002b98SHong Zhang info->mallocs = irecv[4]; 734d4002b98SHong Zhang } else if (flag == MAT_GLOBAL_SUM) { 7351c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(isend, irecv, 5, MPIU_PETSCLOGDOUBLE, MPI_SUM, PetscObjectComm((PetscObject)matin))); 736d4002b98SHong Zhang 737d4002b98SHong Zhang info->nz_used = irecv[0]; 738d4002b98SHong Zhang info->nz_allocated = irecv[1]; 739d4002b98SHong Zhang info->nz_unneeded = irecv[2]; 740d4002b98SHong Zhang info->memory = irecv[3]; 741d4002b98SHong Zhang info->mallocs = irecv[4]; 742d4002b98SHong Zhang } 743d4002b98SHong Zhang info->fill_ratio_given = 0; /* no parallel LU/ILU/Cholesky */ 744d4002b98SHong Zhang info->fill_ratio_needed = 0; 745d4002b98SHong Zhang info->factor_mallocs = 0; 7463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 747d4002b98SHong Zhang } 748d4002b98SHong Zhang 749d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetOption_MPISELL(Mat A, MatOption op, PetscBool flg) 750d71ae5a4SJacob Faibussowitsch { 751d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 752d4002b98SHong Zhang 753d4002b98SHong Zhang PetscFunctionBegin; 754d4002b98SHong Zhang switch (op) { 755d4002b98SHong Zhang case MAT_NEW_NONZERO_LOCATIONS: 756d4002b98SHong Zhang case MAT_NEW_NONZERO_ALLOCATION_ERR: 757d4002b98SHong Zhang case MAT_UNUSED_NONZERO_LOCATION_ERR: 758d4002b98SHong Zhang case MAT_KEEP_NONZERO_PATTERN: 759d4002b98SHong Zhang case MAT_NEW_NONZERO_LOCATION_ERR: 760d4002b98SHong Zhang case MAT_USE_INODES: 761d4002b98SHong Zhang case MAT_IGNORE_ZERO_ENTRIES: 762d4002b98SHong Zhang MatCheckPreallocated(A, 1); 7639566063dSJacob Faibussowitsch PetscCall(MatSetOption(a->A, op, flg)); 7649566063dSJacob Faibussowitsch PetscCall(MatSetOption(a->B, op, flg)); 765d4002b98SHong Zhang break; 766d4002b98SHong Zhang case MAT_ROW_ORIENTED: 767d4002b98SHong Zhang MatCheckPreallocated(A, 1); 768d4002b98SHong Zhang a->roworiented = flg; 769d4002b98SHong Zhang 7709566063dSJacob Faibussowitsch PetscCall(MatSetOption(a->A, op, flg)); 7719566063dSJacob Faibussowitsch PetscCall(MatSetOption(a->B, op, flg)); 772d4002b98SHong Zhang break; 7738c78258cSHong Zhang case MAT_FORCE_DIAGONAL_ENTRIES: 774d71ae5a4SJacob Faibussowitsch case MAT_SORTED_FULL: 775d71ae5a4SJacob Faibussowitsch PetscCall(PetscInfo(A, "Option %s ignored\n", MatOptions[op])); 776d71ae5a4SJacob Faibussowitsch break; 777d71ae5a4SJacob Faibussowitsch case MAT_IGNORE_OFF_PROC_ENTRIES: 778d71ae5a4SJacob Faibussowitsch a->donotstash = flg; 779d71ae5a4SJacob Faibussowitsch break; 780d4002b98SHong Zhang case MAT_SPD: 781d71ae5a4SJacob Faibussowitsch case MAT_SPD_ETERNAL: 782d71ae5a4SJacob Faibussowitsch break; 783d4002b98SHong Zhang case MAT_SYMMETRIC: 784d4002b98SHong Zhang MatCheckPreallocated(A, 1); 7859566063dSJacob Faibussowitsch PetscCall(MatSetOption(a->A, op, flg)); 786d4002b98SHong Zhang break; 787d4002b98SHong Zhang case MAT_STRUCTURALLY_SYMMETRIC: 788d4002b98SHong Zhang MatCheckPreallocated(A, 1); 7899566063dSJacob Faibussowitsch PetscCall(MatSetOption(a->A, op, flg)); 790d4002b98SHong Zhang break; 791d4002b98SHong Zhang case MAT_HERMITIAN: 792d4002b98SHong Zhang MatCheckPreallocated(A, 1); 7939566063dSJacob Faibussowitsch PetscCall(MatSetOption(a->A, op, flg)); 794d4002b98SHong Zhang break; 795d4002b98SHong Zhang case MAT_SYMMETRY_ETERNAL: 796d4002b98SHong Zhang MatCheckPreallocated(A, 1); 7979566063dSJacob Faibussowitsch PetscCall(MatSetOption(a->A, op, flg)); 798d4002b98SHong Zhang break; 799b94d7dedSBarry Smith case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 800b94d7dedSBarry Smith MatCheckPreallocated(A, 1); 801b94d7dedSBarry Smith PetscCall(MatSetOption(a->A, op, flg)); 802b94d7dedSBarry Smith break; 803d71ae5a4SJacob Faibussowitsch default: 804d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "unknown option %d", op); 805d4002b98SHong Zhang } 8063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 807d4002b98SHong Zhang } 808d4002b98SHong Zhang 809d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDiagonalScale_MPISELL(Mat mat, Vec ll, Vec rr) 810d71ae5a4SJacob Faibussowitsch { 811d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)mat->data; 812d4002b98SHong Zhang Mat a = sell->A, b = sell->B; 813d4002b98SHong Zhang PetscInt s1, s2, s3; 814d4002b98SHong Zhang 815d4002b98SHong Zhang PetscFunctionBegin; 8169566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(mat, &s2, &s3)); 817d4002b98SHong Zhang if (rr) { 8189566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(rr, &s1)); 81908401ef6SPierre Jolivet PetscCheck(s1 == s3, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "right vector non-conforming local size"); 820d4002b98SHong Zhang /* Overlap communication with computation. */ 8219566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(sell->Mvctx, rr, sell->lvec, INSERT_VALUES, SCATTER_FORWARD)); 822d4002b98SHong Zhang } 823d4002b98SHong Zhang if (ll) { 8249566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(ll, &s1)); 82508401ef6SPierre Jolivet PetscCheck(s1 == s2, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "left vector non-conforming local size"); 826dbbe0bcdSBarry Smith PetscUseTypeMethod(b, diagonalscale, ll, NULL); 827d4002b98SHong Zhang } 828d4002b98SHong Zhang /* scale the diagonal block */ 829dbbe0bcdSBarry Smith PetscUseTypeMethod(a, diagonalscale, ll, rr); 830d4002b98SHong Zhang 831d4002b98SHong Zhang if (rr) { 832d4002b98SHong Zhang /* Do a scatter end and then right scale the off-diagonal block */ 8339566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(sell->Mvctx, rr, sell->lvec, INSERT_VALUES, SCATTER_FORWARD)); 834dbbe0bcdSBarry Smith PetscUseTypeMethod(b, diagonalscale, NULL, sell->lvec); 835d4002b98SHong Zhang } 8363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 837d4002b98SHong Zhang } 838d4002b98SHong Zhang 839d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetUnfactored_MPISELL(Mat A) 840d71ae5a4SJacob Faibussowitsch { 841d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 842d4002b98SHong Zhang 843d4002b98SHong Zhang PetscFunctionBegin; 8449566063dSJacob Faibussowitsch PetscCall(MatSetUnfactored(a->A)); 8453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 846d4002b98SHong Zhang } 847d4002b98SHong Zhang 848d71ae5a4SJacob Faibussowitsch PetscErrorCode MatEqual_MPISELL(Mat A, Mat B, PetscBool *flag) 849d71ae5a4SJacob Faibussowitsch { 850d4002b98SHong Zhang Mat_MPISELL *matB = (Mat_MPISELL *)B->data, *matA = (Mat_MPISELL *)A->data; 851d4002b98SHong Zhang Mat a, b, c, d; 852d4002b98SHong Zhang PetscBool flg; 853d4002b98SHong Zhang 854d4002b98SHong Zhang PetscFunctionBegin; 8559371c9d4SSatish Balay a = matA->A; 8569371c9d4SSatish Balay b = matA->B; 8579371c9d4SSatish Balay c = matB->A; 8589371c9d4SSatish Balay d = matB->B; 859d4002b98SHong Zhang 8609566063dSJacob Faibussowitsch PetscCall(MatEqual(a, c, &flg)); 86148a46eb9SPierre Jolivet if (flg) PetscCall(MatEqual(b, d, &flg)); 8621c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&flg, flag, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)A))); 8633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 864d4002b98SHong Zhang } 865d4002b98SHong Zhang 866d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCopy_MPISELL(Mat A, Mat B, MatStructure str) 867d71ae5a4SJacob Faibussowitsch { 868d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 869d4002b98SHong Zhang Mat_MPISELL *b = (Mat_MPISELL *)B->data; 870d4002b98SHong Zhang 871d4002b98SHong Zhang PetscFunctionBegin; 872d4002b98SHong Zhang /* If the two matrices don't have the same copy implementation, they aren't compatible for fast copy. */ 873d4002b98SHong Zhang if ((str != SAME_NONZERO_PATTERN) || (A->ops->copy != B->ops->copy)) { 874d4002b98SHong Zhang /* because of the column compression in the off-processor part of the matrix a->B, 875d4002b98SHong Zhang the number of columns in a->B and b->B may be different, hence we cannot call 876d4002b98SHong Zhang the MatCopy() directly on the two parts. If need be, we can provide a more 877d4002b98SHong Zhang efficient copy than the MatCopy_Basic() by first uncompressing the a->B matrices 878d4002b98SHong Zhang then copying the submatrices */ 8799566063dSJacob Faibussowitsch PetscCall(MatCopy_Basic(A, B, str)); 880d4002b98SHong Zhang } else { 8819566063dSJacob Faibussowitsch PetscCall(MatCopy(a->A, b->A, str)); 8829566063dSJacob Faibussowitsch PetscCall(MatCopy(a->B, b->B, str)); 883d4002b98SHong Zhang } 8843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 885d4002b98SHong Zhang } 886d4002b98SHong Zhang 887d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetUp_MPISELL(Mat A) 888d71ae5a4SJacob Faibussowitsch { 889d4002b98SHong Zhang PetscFunctionBegin; 8909566063dSJacob Faibussowitsch PetscCall(MatMPISELLSetPreallocation(A, PETSC_DEFAULT, NULL, PETSC_DEFAULT, NULL)); 8913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 892d4002b98SHong Zhang } 893d4002b98SHong Zhang 894d4002b98SHong Zhang extern PetscErrorCode MatConjugate_SeqSELL(Mat); 895d4002b98SHong Zhang 896d71ae5a4SJacob Faibussowitsch PetscErrorCode MatConjugate_MPISELL(Mat mat) 897d71ae5a4SJacob Faibussowitsch { 8985f80ce2aSJacob Faibussowitsch PetscFunctionBegin; 8995f80ce2aSJacob Faibussowitsch if (PetscDefined(USE_COMPLEX)) { 900d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)mat->data; 901d4002b98SHong Zhang 9029566063dSJacob Faibussowitsch PetscCall(MatConjugate_SeqSELL(sell->A)); 9039566063dSJacob Faibussowitsch PetscCall(MatConjugate_SeqSELL(sell->B)); 9045f80ce2aSJacob Faibussowitsch } 9053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 906d4002b98SHong Zhang } 907d4002b98SHong Zhang 908d71ae5a4SJacob Faibussowitsch PetscErrorCode MatRealPart_MPISELL(Mat A) 909d71ae5a4SJacob Faibussowitsch { 910d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 911d4002b98SHong Zhang 912d4002b98SHong Zhang PetscFunctionBegin; 9139566063dSJacob Faibussowitsch PetscCall(MatRealPart(a->A)); 9149566063dSJacob Faibussowitsch PetscCall(MatRealPart(a->B)); 9153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 916d4002b98SHong Zhang } 917d4002b98SHong Zhang 918d71ae5a4SJacob Faibussowitsch PetscErrorCode MatImaginaryPart_MPISELL(Mat A) 919d71ae5a4SJacob Faibussowitsch { 920d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 921d4002b98SHong Zhang 922d4002b98SHong Zhang PetscFunctionBegin; 9239566063dSJacob Faibussowitsch PetscCall(MatImaginaryPart(a->A)); 9249566063dSJacob Faibussowitsch PetscCall(MatImaginaryPart(a->B)); 9253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 926d4002b98SHong Zhang } 927d4002b98SHong Zhang 928d71ae5a4SJacob Faibussowitsch PetscErrorCode MatInvertBlockDiagonal_MPISELL(Mat A, const PetscScalar **values) 929d71ae5a4SJacob Faibussowitsch { 930d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 931d4002b98SHong Zhang 932d4002b98SHong Zhang PetscFunctionBegin; 9339566063dSJacob Faibussowitsch PetscCall(MatInvertBlockDiagonal(a->A, values)); 934d4002b98SHong Zhang A->factorerrortype = a->A->factorerrortype; 9353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 936d4002b98SHong Zhang } 937d4002b98SHong Zhang 938d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetRandom_MPISELL(Mat x, PetscRandom rctx) 939d71ae5a4SJacob Faibussowitsch { 940d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)x->data; 941d4002b98SHong Zhang 942d4002b98SHong Zhang PetscFunctionBegin; 9439566063dSJacob Faibussowitsch PetscCall(MatSetRandom(sell->A, rctx)); 9449566063dSJacob Faibussowitsch PetscCall(MatSetRandom(sell->B, rctx)); 9459566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 9469566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 9473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 948d4002b98SHong Zhang } 949d4002b98SHong Zhang 950d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetFromOptions_MPISELL(Mat A, PetscOptionItems *PetscOptionsObject) 951d71ae5a4SJacob Faibussowitsch { 952d4002b98SHong Zhang PetscFunctionBegin; 953d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "MPISELL options"); 954d0609cedSBarry Smith PetscOptionsHeadEnd(); 9553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 956d4002b98SHong Zhang } 957d4002b98SHong Zhang 958d71ae5a4SJacob Faibussowitsch PetscErrorCode MatShift_MPISELL(Mat Y, PetscScalar a) 959d71ae5a4SJacob Faibussowitsch { 960d4002b98SHong Zhang Mat_MPISELL *msell = (Mat_MPISELL *)Y->data; 961d4002b98SHong Zhang Mat_SeqSELL *sell = (Mat_SeqSELL *)msell->A->data; 962d4002b98SHong Zhang 963d4002b98SHong Zhang PetscFunctionBegin; 964d4002b98SHong Zhang if (!Y->preallocated) { 9659566063dSJacob Faibussowitsch PetscCall(MatMPISELLSetPreallocation(Y, 1, NULL, 0, NULL)); 966d4002b98SHong Zhang } else if (!sell->nz) { 967d4002b98SHong Zhang PetscInt nonew = sell->nonew; 9689566063dSJacob Faibussowitsch PetscCall(MatSeqSELLSetPreallocation(msell->A, 1, NULL)); 969d4002b98SHong Zhang sell->nonew = nonew; 970d4002b98SHong Zhang } 9719566063dSJacob Faibussowitsch PetscCall(MatShift_Basic(Y, a)); 9723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 973d4002b98SHong Zhang } 974d4002b98SHong Zhang 975d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMissingDiagonal_MPISELL(Mat A, PetscBool *missing, PetscInt *d) 976d71ae5a4SJacob Faibussowitsch { 977d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 978d4002b98SHong Zhang 979d4002b98SHong Zhang PetscFunctionBegin; 98008401ef6SPierre Jolivet PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only works for square matrices"); 9819566063dSJacob Faibussowitsch PetscCall(MatMissingDiagonal(a->A, missing, d)); 982d4002b98SHong Zhang if (d) { 983d4002b98SHong Zhang PetscInt rstart; 9849566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A, &rstart, NULL)); 985d4002b98SHong Zhang *d += rstart; 986d4002b98SHong Zhang } 9873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 988d4002b98SHong Zhang } 989d4002b98SHong Zhang 990d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetDiagonalBlock_MPISELL(Mat A, Mat *a) 991d71ae5a4SJacob Faibussowitsch { 992d4002b98SHong Zhang PetscFunctionBegin; 993d4002b98SHong Zhang *a = ((Mat_MPISELL *)A->data)->A; 9943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 995d4002b98SHong Zhang } 996d4002b98SHong Zhang 997d4002b98SHong Zhang static struct _MatOps MatOps_Values = {MatSetValues_MPISELL, 998f4259b30SLisandro Dalcin NULL, 999f4259b30SLisandro Dalcin NULL, 1000d4002b98SHong Zhang MatMult_MPISELL, 1001d4002b98SHong Zhang /* 4*/ MatMultAdd_MPISELL, 1002d4002b98SHong Zhang MatMultTranspose_MPISELL, 1003d4002b98SHong Zhang MatMultTransposeAdd_MPISELL, 1004f4259b30SLisandro Dalcin NULL, 1005f4259b30SLisandro Dalcin NULL, 1006f4259b30SLisandro Dalcin NULL, 1007f4259b30SLisandro Dalcin /*10*/ NULL, 1008f4259b30SLisandro Dalcin NULL, 1009f4259b30SLisandro Dalcin NULL, 1010d4002b98SHong Zhang MatSOR_MPISELL, 1011f4259b30SLisandro Dalcin NULL, 1012d4002b98SHong Zhang /*15*/ MatGetInfo_MPISELL, 1013d4002b98SHong Zhang MatEqual_MPISELL, 1014d4002b98SHong Zhang MatGetDiagonal_MPISELL, 1015d4002b98SHong Zhang MatDiagonalScale_MPISELL, 1016f4259b30SLisandro Dalcin NULL, 1017d4002b98SHong Zhang /*20*/ MatAssemblyBegin_MPISELL, 1018d4002b98SHong Zhang MatAssemblyEnd_MPISELL, 1019d4002b98SHong Zhang MatSetOption_MPISELL, 1020d4002b98SHong Zhang MatZeroEntries_MPISELL, 1021f4259b30SLisandro Dalcin /*24*/ NULL, 1022f4259b30SLisandro Dalcin NULL, 1023f4259b30SLisandro Dalcin NULL, 1024f4259b30SLisandro Dalcin NULL, 1025f4259b30SLisandro Dalcin NULL, 1026d4002b98SHong Zhang /*29*/ MatSetUp_MPISELL, 1027f4259b30SLisandro Dalcin NULL, 1028f4259b30SLisandro Dalcin NULL, 1029d4002b98SHong Zhang MatGetDiagonalBlock_MPISELL, 1030f4259b30SLisandro Dalcin NULL, 1031d4002b98SHong Zhang /*34*/ MatDuplicate_MPISELL, 1032f4259b30SLisandro Dalcin NULL, 1033f4259b30SLisandro Dalcin NULL, 1034f4259b30SLisandro Dalcin NULL, 1035f4259b30SLisandro Dalcin NULL, 1036f4259b30SLisandro Dalcin /*39*/ NULL, 1037f4259b30SLisandro Dalcin NULL, 1038f4259b30SLisandro Dalcin NULL, 1039d4002b98SHong Zhang MatGetValues_MPISELL, 1040d4002b98SHong Zhang MatCopy_MPISELL, 1041f4259b30SLisandro Dalcin /*44*/ NULL, 1042d4002b98SHong Zhang MatScale_MPISELL, 1043d4002b98SHong Zhang MatShift_MPISELL, 1044d4002b98SHong Zhang MatDiagonalSet_MPISELL, 1045f4259b30SLisandro Dalcin NULL, 1046d4002b98SHong Zhang /*49*/ MatSetRandom_MPISELL, 1047f4259b30SLisandro Dalcin NULL, 1048f4259b30SLisandro Dalcin NULL, 1049f4259b30SLisandro Dalcin NULL, 1050f4259b30SLisandro Dalcin NULL, 1051d4002b98SHong Zhang /*54*/ MatFDColoringCreate_MPIXAIJ, 1052f4259b30SLisandro Dalcin NULL, 1053d4002b98SHong Zhang MatSetUnfactored_MPISELL, 1054f4259b30SLisandro Dalcin NULL, 1055f4259b30SLisandro Dalcin NULL, 1056f4259b30SLisandro Dalcin /*59*/ NULL, 1057d4002b98SHong Zhang MatDestroy_MPISELL, 1058d4002b98SHong Zhang MatView_MPISELL, 1059f4259b30SLisandro Dalcin NULL, 1060f4259b30SLisandro Dalcin NULL, 1061f4259b30SLisandro Dalcin /*64*/ NULL, 1062f4259b30SLisandro Dalcin NULL, 1063f4259b30SLisandro Dalcin NULL, 1064f4259b30SLisandro Dalcin NULL, 1065f4259b30SLisandro Dalcin NULL, 1066f4259b30SLisandro Dalcin /*69*/ NULL, 1067f4259b30SLisandro Dalcin NULL, 1068f4259b30SLisandro Dalcin NULL, 1069f4259b30SLisandro Dalcin NULL, 1070f4259b30SLisandro Dalcin NULL, 1071f4259b30SLisandro Dalcin NULL, 1072d4002b98SHong Zhang /*75*/ MatFDColoringApply_AIJ, /* reuse AIJ function */ 1073d4002b98SHong Zhang MatSetFromOptions_MPISELL, 1074f4259b30SLisandro Dalcin NULL, 1075f4259b30SLisandro Dalcin NULL, 1076f4259b30SLisandro Dalcin NULL, 1077f4259b30SLisandro Dalcin /*80*/ NULL, 1078f4259b30SLisandro Dalcin NULL, 1079f4259b30SLisandro Dalcin NULL, 1080f4259b30SLisandro Dalcin /*83*/ NULL, 1081f4259b30SLisandro Dalcin NULL, 1082f4259b30SLisandro Dalcin NULL, 1083f4259b30SLisandro Dalcin NULL, 1084f4259b30SLisandro Dalcin NULL, 1085f4259b30SLisandro Dalcin NULL, 1086f4259b30SLisandro Dalcin /*89*/ NULL, 1087f4259b30SLisandro Dalcin NULL, 1088f4259b30SLisandro Dalcin NULL, 1089f4259b30SLisandro Dalcin NULL, 1090f4259b30SLisandro Dalcin NULL, 1091f4259b30SLisandro Dalcin /*94*/ NULL, 1092f4259b30SLisandro Dalcin NULL, 1093f4259b30SLisandro Dalcin NULL, 1094f4259b30SLisandro Dalcin NULL, 1095f4259b30SLisandro Dalcin NULL, 1096f4259b30SLisandro Dalcin /*99*/ NULL, 1097f4259b30SLisandro Dalcin NULL, 1098f4259b30SLisandro Dalcin NULL, 1099d4002b98SHong Zhang MatConjugate_MPISELL, 1100f4259b30SLisandro Dalcin NULL, 1101f4259b30SLisandro Dalcin /*104*/ NULL, 1102d4002b98SHong Zhang MatRealPart_MPISELL, 1103d4002b98SHong Zhang MatImaginaryPart_MPISELL, 1104f4259b30SLisandro Dalcin NULL, 1105f4259b30SLisandro Dalcin NULL, 1106f4259b30SLisandro Dalcin /*109*/ NULL, 1107f4259b30SLisandro Dalcin NULL, 1108f4259b30SLisandro Dalcin NULL, 1109f4259b30SLisandro Dalcin NULL, 1110d4002b98SHong Zhang MatMissingDiagonal_MPISELL, 1111f4259b30SLisandro Dalcin /*114*/ NULL, 1112f4259b30SLisandro Dalcin NULL, 1113d4002b98SHong Zhang MatGetGhosts_MPISELL, 1114f4259b30SLisandro Dalcin NULL, 1115f4259b30SLisandro Dalcin NULL, 1116f4259b30SLisandro Dalcin /*119*/ NULL, 1117f4259b30SLisandro Dalcin NULL, 1118f4259b30SLisandro Dalcin NULL, 1119f4259b30SLisandro Dalcin NULL, 1120f4259b30SLisandro Dalcin NULL, 1121f4259b30SLisandro Dalcin /*124*/ NULL, 1122f4259b30SLisandro Dalcin NULL, 1123d4002b98SHong Zhang MatInvertBlockDiagonal_MPISELL, 1124f4259b30SLisandro Dalcin NULL, 1125f4259b30SLisandro Dalcin NULL, 1126f4259b30SLisandro Dalcin /*129*/ NULL, 1127f4259b30SLisandro Dalcin NULL, 1128f4259b30SLisandro Dalcin NULL, 1129f4259b30SLisandro Dalcin NULL, 1130f4259b30SLisandro Dalcin NULL, 1131f4259b30SLisandro Dalcin /*134*/ NULL, 1132f4259b30SLisandro Dalcin NULL, 1133f4259b30SLisandro Dalcin NULL, 1134f4259b30SLisandro Dalcin NULL, 1135f4259b30SLisandro Dalcin NULL, 1136f4259b30SLisandro Dalcin /*139*/ NULL, 1137f4259b30SLisandro Dalcin NULL, 1138f4259b30SLisandro Dalcin NULL, 1139d4002b98SHong Zhang MatFDColoringSetUp_MPIXAIJ, 1140f4259b30SLisandro Dalcin NULL, 1141d70f29a3SPierre Jolivet /*144*/ NULL, 1142d70f29a3SPierre Jolivet NULL, 1143d70f29a3SPierre Jolivet NULL, 114499a7f59eSMark Adams NULL, 114599a7f59eSMark Adams NULL, 11467fb60732SBarry Smith NULL, 1147dec0b466SHong Zhang /*150*/ NULL, 1148dec0b466SHong Zhang NULL}; 1149d4002b98SHong Zhang 1150d71ae5a4SJacob Faibussowitsch PetscErrorCode MatStoreValues_MPISELL(Mat mat) 1151d71ae5a4SJacob Faibussowitsch { 1152d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)mat->data; 1153d4002b98SHong Zhang 1154d4002b98SHong Zhang PetscFunctionBegin; 11559566063dSJacob Faibussowitsch PetscCall(MatStoreValues(sell->A)); 11569566063dSJacob Faibussowitsch PetscCall(MatStoreValues(sell->B)); 11573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1158d4002b98SHong Zhang } 1159d4002b98SHong Zhang 1160d71ae5a4SJacob Faibussowitsch PetscErrorCode MatRetrieveValues_MPISELL(Mat mat) 1161d71ae5a4SJacob Faibussowitsch { 1162d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)mat->data; 1163d4002b98SHong Zhang 1164d4002b98SHong Zhang PetscFunctionBegin; 11659566063dSJacob Faibussowitsch PetscCall(MatRetrieveValues(sell->A)); 11669566063dSJacob Faibussowitsch PetscCall(MatRetrieveValues(sell->B)); 11673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1168d4002b98SHong Zhang } 1169d4002b98SHong Zhang 1170d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMPISELLSetPreallocation_MPISELL(Mat B, PetscInt d_rlenmax, const PetscInt d_rlen[], PetscInt o_rlenmax, const PetscInt o_rlen[]) 1171d71ae5a4SJacob Faibussowitsch { 1172d4002b98SHong Zhang Mat_MPISELL *b; 1173d4002b98SHong Zhang 1174d4002b98SHong Zhang PetscFunctionBegin; 11759566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->rmap)); 11769566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->cmap)); 1177d4002b98SHong Zhang b = (Mat_MPISELL *)B->data; 1178d4002b98SHong Zhang 1179d4002b98SHong Zhang if (!B->preallocated) { 1180d4002b98SHong Zhang /* Explicitly create 2 MATSEQSELL matrices. */ 11819566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &b->A)); 11829566063dSJacob Faibussowitsch PetscCall(MatSetSizes(b->A, B->rmap->n, B->cmap->n, B->rmap->n, B->cmap->n)); 11839566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(b->A, B, B)); 11849566063dSJacob Faibussowitsch PetscCall(MatSetType(b->A, MATSEQSELL)); 11859566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &b->B)); 11869566063dSJacob Faibussowitsch PetscCall(MatSetSizes(b->B, B->rmap->n, B->cmap->N, B->rmap->n, B->cmap->N)); 11879566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(b->B, B, B)); 11889566063dSJacob Faibussowitsch PetscCall(MatSetType(b->B, MATSEQSELL)); 1189d4002b98SHong Zhang } 1190d4002b98SHong Zhang 11919566063dSJacob Faibussowitsch PetscCall(MatSeqSELLSetPreallocation(b->A, d_rlenmax, d_rlen)); 11929566063dSJacob Faibussowitsch PetscCall(MatSeqSELLSetPreallocation(b->B, o_rlenmax, o_rlen)); 1193d4002b98SHong Zhang B->preallocated = PETSC_TRUE; 1194d4002b98SHong Zhang B->was_assembled = PETSC_FALSE; 1195d4002b98SHong Zhang /* 1196d4002b98SHong Zhang critical for MatAssemblyEnd to work. 1197d4002b98SHong Zhang MatAssemblyBegin checks it to set up was_assembled 1198d4002b98SHong Zhang and MatAssemblyEnd checks was_assembled to determine whether to build garray 1199d4002b98SHong Zhang */ 1200d4002b98SHong Zhang B->assembled = PETSC_FALSE; 12013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1202d4002b98SHong Zhang } 1203d4002b98SHong Zhang 1204d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDuplicate_MPISELL(Mat matin, MatDuplicateOption cpvalues, Mat *newmat) 1205d71ae5a4SJacob Faibussowitsch { 1206d4002b98SHong Zhang Mat mat; 1207d4002b98SHong Zhang Mat_MPISELL *a, *oldmat = (Mat_MPISELL *)matin->data; 1208d4002b98SHong Zhang 1209d4002b98SHong Zhang PetscFunctionBegin; 1210f4259b30SLisandro Dalcin *newmat = NULL; 12119566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)matin), &mat)); 12129566063dSJacob Faibussowitsch PetscCall(MatSetSizes(mat, matin->rmap->n, matin->cmap->n, matin->rmap->N, matin->cmap->N)); 12139566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(mat, matin, matin)); 12149566063dSJacob Faibussowitsch PetscCall(MatSetType(mat, ((PetscObject)matin)->type_name)); 1215d4002b98SHong Zhang a = (Mat_MPISELL *)mat->data; 1216d4002b98SHong Zhang 1217d4002b98SHong Zhang mat->factortype = matin->factortype; 1218d4002b98SHong Zhang mat->assembled = PETSC_TRUE; 1219d4002b98SHong Zhang mat->insertmode = NOT_SET_VALUES; 1220d4002b98SHong Zhang mat->preallocated = PETSC_TRUE; 1221d4002b98SHong Zhang 1222d4002b98SHong Zhang a->size = oldmat->size; 1223d4002b98SHong Zhang a->rank = oldmat->rank; 1224d4002b98SHong Zhang a->donotstash = oldmat->donotstash; 1225d4002b98SHong Zhang a->roworiented = oldmat->roworiented; 1226f4259b30SLisandro Dalcin a->rowindices = NULL; 1227f4259b30SLisandro Dalcin a->rowvalues = NULL; 1228d4002b98SHong Zhang a->getrowactive = PETSC_FALSE; 1229d4002b98SHong Zhang 12309566063dSJacob Faibussowitsch PetscCall(PetscLayoutReference(matin->rmap, &mat->rmap)); 12319566063dSJacob Faibussowitsch PetscCall(PetscLayoutReference(matin->cmap, &mat->cmap)); 1232d4002b98SHong Zhang 1233d4002b98SHong Zhang if (oldmat->colmap) { 1234d4002b98SHong Zhang #if defined(PETSC_USE_CTABLE) 1235eec179cfSJacob Faibussowitsch PetscCall(PetscHMapIDuplicate(oldmat->colmap, &a->colmap)); 1236d4002b98SHong Zhang #else 12379566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(mat->cmap->N, &a->colmap)); 12389566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(a->colmap, oldmat->colmap, mat->cmap->N)); 1239d4002b98SHong Zhang #endif 1240f4259b30SLisandro Dalcin } else a->colmap = NULL; 1241d4002b98SHong Zhang if (oldmat->garray) { 1242d4002b98SHong Zhang PetscInt len; 1243d4002b98SHong Zhang len = oldmat->B->cmap->n; 12449566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(len + 1, &a->garray)); 12459566063dSJacob Faibussowitsch if (len) PetscCall(PetscArraycpy(a->garray, oldmat->garray, len)); 1246f4259b30SLisandro Dalcin } else a->garray = NULL; 1247d4002b98SHong Zhang 12489566063dSJacob Faibussowitsch PetscCall(VecDuplicate(oldmat->lvec, &a->lvec)); 12499566063dSJacob Faibussowitsch PetscCall(VecScatterCopy(oldmat->Mvctx, &a->Mvctx)); 12509566063dSJacob Faibussowitsch PetscCall(MatDuplicate(oldmat->A, cpvalues, &a->A)); 12519566063dSJacob Faibussowitsch PetscCall(MatDuplicate(oldmat->B, cpvalues, &a->B)); 12529566063dSJacob Faibussowitsch PetscCall(PetscFunctionListDuplicate(((PetscObject)matin)->qlist, &((PetscObject)mat)->qlist)); 1253d4002b98SHong Zhang *newmat = mat; 12543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1255d4002b98SHong Zhang } 1256d4002b98SHong Zhang 1257d4002b98SHong Zhang /*@C 125811a5261eSBarry Smith MatMPISELLSetPreallocation - Preallocates memory for a `MATMPISELL` sparse parallel matrix in sell format. 1259d4002b98SHong Zhang For good matrix assembly performance the user should preallocate the matrix storage by 126067be906fSBarry Smith setting the parameters `d_nz` (or `d_nnz`) and `o_nz` (or `o_nnz`). 1261d4002b98SHong Zhang 1262d083f849SBarry Smith Collective 1263d4002b98SHong Zhang 1264d4002b98SHong Zhang Input Parameters: 1265d4002b98SHong Zhang + B - the matrix 1266d4002b98SHong Zhang . d_nz - number of nonzeros per row in DIAGONAL portion of local submatrix 1267d4002b98SHong Zhang (same value is used for all local rows) 1268d4002b98SHong Zhang . d_nnz - array containing the number of nonzeros in the various rows of the 1269d4002b98SHong Zhang DIAGONAL portion of the local submatrix (possibly different for each row) 127067be906fSBarry Smith or NULL (`PETSC_NULL_INTEGER` in Fortran), if `d_nz` is used to specify the nonzero structure. 1271d4002b98SHong Zhang The size of this array is equal to the number of local rows, i.e 'm'. 1272d4002b98SHong Zhang For matrices that will be factored, you must leave room for (and set) 1273d4002b98SHong Zhang the diagonal entry even if it is zero. 1274d4002b98SHong Zhang . o_nz - number of nonzeros per row in the OFF-DIAGONAL portion of local 1275d4002b98SHong Zhang submatrix (same value is used for all local rows). 1276d4002b98SHong Zhang - o_nnz - array containing the number of nonzeros in the various rows of the 1277d4002b98SHong Zhang OFF-DIAGONAL portion of the local submatrix (possibly different for 127867be906fSBarry Smith each row) or NULL (`PETSC_NULL_INTEGER` in Fortran), if `o_nz` is used to specify the nonzero 1279d4002b98SHong Zhang structure. The size of this array is equal to the number 1280d4002b98SHong Zhang of local rows, i.e 'm'. 1281d4002b98SHong Zhang 1282d4002b98SHong Zhang Example usage: 1283d4002b98SHong Zhang Consider the following 8x8 matrix with 34 non-zero values, that is 1284d4002b98SHong Zhang assembled across 3 processors. Lets assume that proc0 owns 3 rows, 1285d4002b98SHong Zhang proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 128667be906fSBarry Smith as follows 1287d4002b98SHong Zhang 1288d4002b98SHong Zhang .vb 1289d4002b98SHong Zhang 1 2 0 | 0 3 0 | 0 4 1290d4002b98SHong Zhang Proc0 0 5 6 | 7 0 0 | 8 0 1291d4002b98SHong Zhang 9 0 10 | 11 0 0 | 12 0 1292d4002b98SHong Zhang ------------------------------------- 1293d4002b98SHong Zhang 13 0 14 | 15 16 17 | 0 0 1294d4002b98SHong Zhang Proc1 0 18 0 | 19 20 21 | 0 0 1295d4002b98SHong Zhang 0 0 0 | 22 23 0 | 24 0 1296d4002b98SHong Zhang ------------------------------------- 1297d4002b98SHong Zhang Proc2 25 26 27 | 0 0 28 | 29 0 1298d4002b98SHong Zhang 30 0 0 | 31 32 33 | 0 34 1299d4002b98SHong Zhang .ve 1300d4002b98SHong Zhang 130127430b45SBarry Smith This can be represented as a collection of submatrices as 1302d4002b98SHong Zhang 1303d4002b98SHong Zhang .vb 1304d4002b98SHong Zhang A B C 1305d4002b98SHong Zhang D E F 1306d4002b98SHong Zhang G H I 1307d4002b98SHong Zhang .ve 1308d4002b98SHong Zhang 1309d4002b98SHong Zhang Where the submatrices A,B,C are owned by proc0, D,E,F are 1310d4002b98SHong Zhang owned by proc1, G,H,I are owned by proc2. 1311d4002b98SHong Zhang 1312d4002b98SHong Zhang The 'm' parameters for proc0,proc1,proc2 are 3,3,2 respectively. 1313d4002b98SHong Zhang The 'n' parameters for proc0,proc1,proc2 are 3,3,2 respectively. 1314d4002b98SHong Zhang The 'M','N' parameters are 8,8, and have the same values on all procs. 1315d4002b98SHong Zhang 1316d4002b98SHong Zhang The DIAGONAL submatrices corresponding to proc0,proc1,proc2 are 1317d4002b98SHong Zhang submatrices [A], [E], [I] respectively. The OFF-DIAGONAL submatrices 1318d4002b98SHong Zhang corresponding to proc0,proc1,proc2 are [BC], [DF], [GH] respectively. 1319d4002b98SHong Zhang Internally, each processor stores the DIAGONAL part, and the OFF-DIAGONAL 132027430b45SBarry Smith part as `MATSEQSELL` matrices. For example, proc1 will store [E] as a `MATSEQSELL` 1321d4002b98SHong Zhang matrix, ans [DF] as another SeqSELL matrix. 1322d4002b98SHong Zhang 132367be906fSBarry Smith When `d_nz`, `o_nz` parameters are specified, `d_nz` storage elements are 1324d4002b98SHong Zhang allocated for every row of the local diagonal submatrix, and o_nz 1325d4002b98SHong Zhang storage locations are allocated for every row of the OFF-DIAGONAL submat. 132667be906fSBarry Smith One way to choose `d_nz` and `o_nz` is to use the max nonzerors per local 1327d4002b98SHong Zhang rows for each of the local DIAGONAL, and the OFF-DIAGONAL submatrices. 132827430b45SBarry Smith In this case, the values of d_nz,o_nz are 1329d4002b98SHong Zhang .vb 133027430b45SBarry Smith proc0 dnz = 2, o_nz = 2 133127430b45SBarry Smith proc1 dnz = 3, o_nz = 2 133227430b45SBarry Smith proc2 dnz = 1, o_nz = 4 1333d4002b98SHong Zhang .ve 1334d4002b98SHong Zhang We are allocating m*(d_nz+o_nz) storage locations for every proc. This 1335d4002b98SHong Zhang translates to 3*(2+2)=12 for proc0, 3*(3+2)=15 for proc1, 2*(1+4)=10 1336d4002b98SHong Zhang for proc3. i.e we are using 12+15+10=37 storage locations to store 1337d4002b98SHong Zhang 34 values. 1338d4002b98SHong Zhang 133967be906fSBarry Smith When `d_nnz`, `o_nnz` parameters are specified, the storage is specified 1340a5b23f4aSJose E. Roman for every row, corresponding to both DIAGONAL and OFF-DIAGONAL submatrices. 134127430b45SBarry Smith In the above case the values for d_nnz,o_nnz are 1342d4002b98SHong Zhang .vb 134327430b45SBarry Smith proc0 d_nnz = [2,2,2] and o_nnz = [2,2,2] 134427430b45SBarry Smith proc1 d_nnz = [3,3,2] and o_nnz = [2,1,1] 134527430b45SBarry Smith proc2 d_nnz = [1,1] and o_nnz = [4,4] 1346d4002b98SHong Zhang .ve 1347d4002b98SHong Zhang Here the space allocated is according to nz (or maximum values in the nnz 1348d4002b98SHong Zhang if nnz is provided) for DIAGONAL and OFF-DIAGONAL submatrices, i.e (2+2+3+2)*3+(1+4)*2=37 1349d4002b98SHong Zhang 1350d4002b98SHong Zhang Level: intermediate 1351d4002b98SHong Zhang 135267be906fSBarry Smith Notes: 135367be906fSBarry Smith If the *_nnz parameter is given then the *_nz parameter is ignored 135467be906fSBarry Smith 135567be906fSBarry Smith The stored row and column indices begin with zero. 135667be906fSBarry Smith 135767be906fSBarry Smith The parallel matrix is partitioned such that the first m0 rows belong to 135867be906fSBarry Smith process 0, the next m1 rows belong to process 1, the next m2 rows belong 135967be906fSBarry Smith to process 2 etc.. where m0,m1,m2... are the input parameter 'm'. 136067be906fSBarry Smith 136167be906fSBarry Smith The DIAGONAL portion of the local submatrix of a processor can be defined 136267be906fSBarry Smith as the submatrix which is obtained by extraction the part corresponding to 136367be906fSBarry Smith the rows r1-r2 and columns c1-c2 of the global matrix, where r1 is the 136467be906fSBarry Smith first row that belongs to the processor, r2 is the last row belonging to 136567be906fSBarry Smith the this processor, and c1-c2 is range of indices of the local part of a 136667be906fSBarry Smith vector suitable for applying the matrix to. This is an mxn matrix. In the 136767be906fSBarry Smith common case of a square matrix, the row and column ranges are the same and 136867be906fSBarry Smith the DIAGONAL part is also square. The remaining portion of the local 136967be906fSBarry Smith submatrix (mxN) constitute the OFF-DIAGONAL portion. 137067be906fSBarry Smith 137167be906fSBarry Smith If `o_nnz`, `d_nnz` are specified, then `o_nz`, and `d_nz` are ignored. 137267be906fSBarry Smith 137367be906fSBarry Smith You can call `MatGetInfo()` to get information on how effective the preallocation was; 137467be906fSBarry Smith for example the fields mallocs,nz_allocated,nz_used,nz_unneeded; 137567be906fSBarry Smith You can also run with the option -info and look for messages with the string 137667be906fSBarry Smith malloc in them to see if additional memory allocation was needed. 137767be906fSBarry Smith 137867be906fSBarry Smith .seealso: `Mat`, `MatCreate()`, `MatCreateSeqSELL()`, `MatSetValues()`, `MatCreatesell()`, 137911a5261eSBarry Smith `MATMPISELL`, `MatGetInfo()`, `PetscSplitOwnership()`, `MATSELL` 1380d4002b98SHong Zhang @*/ 1381d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMPISELLSetPreallocation(Mat B, PetscInt d_nz, const PetscInt d_nnz[], PetscInt o_nz, const PetscInt o_nnz[]) 1382d71ae5a4SJacob Faibussowitsch { 1383d4002b98SHong Zhang PetscFunctionBegin; 1384d4002b98SHong Zhang PetscValidHeaderSpecific(B, MAT_CLASSID, 1); 1385d4002b98SHong Zhang PetscValidType(B, 1); 1386cac4c232SBarry Smith PetscTryMethod(B, "MatMPISELLSetPreallocation_C", (Mat, PetscInt, const PetscInt[], PetscInt, const PetscInt[]), (B, d_nz, d_nnz, o_nz, o_nnz)); 13873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1388d4002b98SHong Zhang } 1389d4002b98SHong Zhang 1390ed73aabaSBarry Smith /*MC 1391ed73aabaSBarry Smith MATMPISELL - MATMPISELL = "mpisell" - A matrix type to be used for MPI sparse matrices, 1392ed73aabaSBarry Smith based on the sliced Ellpack format 1393ed73aabaSBarry Smith 139427430b45SBarry Smith Options Database Key: 139520f4b53cSBarry Smith . -mat_type sell - sets the matrix type to `MATSELL` during a call to `MatSetFromOptions()` 1396ed73aabaSBarry Smith 1397ed73aabaSBarry Smith Level: beginner 1398ed73aabaSBarry Smith 139967be906fSBarry Smith .seealso: `Mat`, `MatCreateSell()`, `MATSEQSELL`, `MATSELL`, `MATSEQAIJ`, `MATAIJ`, `MATMPIAIJ` 1400ed73aabaSBarry Smith M*/ 1401ed73aabaSBarry Smith 1402d4002b98SHong Zhang /*@C 140311a5261eSBarry Smith MatCreateSELL - Creates a sparse parallel matrix in `MATSELL` format. 1404d4002b98SHong Zhang 1405d083f849SBarry Smith Collective 1406d4002b98SHong Zhang 1407d4002b98SHong Zhang Input Parameters: 1408d4002b98SHong Zhang + comm - MPI communicator 140911a5261eSBarry Smith . m - number of local rows (or `PETSC_DECIDE` to have calculated if M is given) 1410d4002b98SHong Zhang This value should be the same as the local size used in creating the 1411d4002b98SHong Zhang y vector for the matrix-vector product y = Ax. 1412d4002b98SHong Zhang . n - This value should be the same as the local size used in creating the 141320f4b53cSBarry Smith x vector for the matrix-vector product y = Ax. (or `PETSC_DECIDE` to have 141420f4b53cSBarry Smith calculated if `N` is given) For square matrices n is almost always `m`. 141520f4b53cSBarry Smith . M - number of global rows (or `PETSC_DETERMINE` to have calculated if `m` is given) 141620f4b53cSBarry Smith . N - number of global columns (or `PETSC_DETERMINE` to have calculated if `n` is given) 1417d4002b98SHong Zhang . d_rlenmax - max number of nonzeros per row in DIAGONAL portion of local submatrix 1418d4002b98SHong Zhang (same value is used for all local rows) 1419d4002b98SHong Zhang . d_rlen - array containing the number of nonzeros in the various rows of the 1420d4002b98SHong Zhang DIAGONAL portion of the local submatrix (possibly different for each row) 142120f4b53cSBarry Smith or `NULL`, if d_rlenmax is used to specify the nonzero structure. 142220f4b53cSBarry Smith The size of this array is equal to the number of local rows, i.e `m`. 1423d4002b98SHong Zhang . o_rlenmax - max number of nonzeros per row in the OFF-DIAGONAL portion of local 1424d4002b98SHong Zhang submatrix (same value is used for all local rows). 1425d4002b98SHong Zhang - o_rlen - array containing the number of nonzeros in the various rows of the 1426d4002b98SHong Zhang OFF-DIAGONAL portion of the local submatrix (possibly different for 142720f4b53cSBarry Smith each row) or `NULL`, if `o_rlenmax` is used to specify the nonzero 1428d4002b98SHong Zhang structure. The size of this array is equal to the number 142920f4b53cSBarry Smith of local rows, i.e `m`. 1430d4002b98SHong Zhang 1431d4002b98SHong Zhang Output Parameter: 1432d4002b98SHong Zhang . A - the matrix 1433d4002b98SHong Zhang 143427430b45SBarry Smith Options Database Key: 143527430b45SBarry Smith - -mat_sell_oneindex - Internally use indexing starting at 1 143627430b45SBarry Smith rather than 0. When calling `MatSetValues()`, 143727430b45SBarry Smith the user still MUST index entries starting at 0! 143827430b45SBarry Smith 143927430b45SBarry Smith Example: 144027430b45SBarry Smith Consider the following 8x8 matrix with 34 non-zero values, that is 144127430b45SBarry Smith assembled across 3 processors. Lets assume that proc0 owns 3 rows, 144227430b45SBarry Smith proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 144327430b45SBarry Smith as follows 144427430b45SBarry Smith 144527430b45SBarry Smith .vb 144627430b45SBarry Smith 1 2 0 | 0 3 0 | 0 4 144727430b45SBarry Smith Proc0 0 5 6 | 7 0 0 | 8 0 144827430b45SBarry Smith 9 0 10 | 11 0 0 | 12 0 144927430b45SBarry Smith ------------------------------------- 145027430b45SBarry Smith 13 0 14 | 15 16 17 | 0 0 145127430b45SBarry Smith Proc1 0 18 0 | 19 20 21 | 0 0 145227430b45SBarry Smith 0 0 0 | 22 23 0 | 24 0 145327430b45SBarry Smith ------------------------------------- 145427430b45SBarry Smith Proc2 25 26 27 | 0 0 28 | 29 0 145527430b45SBarry Smith 30 0 0 | 31 32 33 | 0 34 145627430b45SBarry Smith .ve 145727430b45SBarry Smith 145820f4b53cSBarry Smith This can be represented as a collection of submatrices as 145927430b45SBarry Smith .vb 146027430b45SBarry Smith A B C 146127430b45SBarry Smith D E F 146227430b45SBarry Smith G H I 146327430b45SBarry Smith .ve 146427430b45SBarry Smith 146527430b45SBarry Smith Where the submatrices A,B,C are owned by proc0, D,E,F are 146627430b45SBarry Smith owned by proc1, G,H,I are owned by proc2. 146727430b45SBarry Smith 146827430b45SBarry Smith The 'm' parameters for proc0,proc1,proc2 are 3,3,2 respectively. 146927430b45SBarry Smith The 'n' parameters for proc0,proc1,proc2 are 3,3,2 respectively. 147027430b45SBarry Smith The 'M','N' parameters are 8,8, and have the same values on all procs. 147127430b45SBarry Smith 147227430b45SBarry Smith The DIAGONAL submatrices corresponding to proc0,proc1,proc2 are 147327430b45SBarry Smith submatrices [A], [E], [I] respectively. The OFF-DIAGONAL submatrices 147427430b45SBarry Smith corresponding to proc0,proc1,proc2 are [BC], [DF], [GH] respectively. 147527430b45SBarry Smith Internally, each processor stores the DIAGONAL part, and the OFF-DIAGONAL 147627430b45SBarry Smith part as `MATSEQSELL` matrices. For example, proc1 will store [E] as a `MATSEQSELL` 147727430b45SBarry Smith matrix, ans [DF] as another `MATSEQSELL` matrix. 147827430b45SBarry Smith 147927430b45SBarry Smith When d_rlenmax, o_rlenmax parameters are specified, d_rlenmax storage elements are 148027430b45SBarry Smith allocated for every row of the local diagonal submatrix, and o_rlenmax 148127430b45SBarry Smith storage locations are allocated for every row of the OFF-DIAGONAL submat. 148227430b45SBarry Smith One way to choose d_rlenmax and o_rlenmax is to use the max nonzerors per local 148327430b45SBarry Smith rows for each of the local DIAGONAL, and the OFF-DIAGONAL submatrices. 148420f4b53cSBarry Smith In this case, the values of d_rlenmax,o_rlenmax are 148527430b45SBarry Smith .vb 148620f4b53cSBarry Smith proc0 - d_rlenmax = 2, o_rlenmax = 2 148720f4b53cSBarry Smith proc1 - d_rlenmax = 3, o_rlenmax = 2 148820f4b53cSBarry Smith proc2 - d_rlenmax = 1, o_rlenmax = 4 148927430b45SBarry Smith .ve 149027430b45SBarry Smith We are allocating m*(d_rlenmax+o_rlenmax) storage locations for every proc. This 149127430b45SBarry Smith translates to 3*(2+2)=12 for proc0, 3*(3+2)=15 for proc1, 2*(1+4)=10 149227430b45SBarry Smith for proc3. i.e we are using 12+15+10=37 storage locations to store 149327430b45SBarry Smith 34 values. 149427430b45SBarry Smith 149520f4b53cSBarry Smith When `d_rlen`, `o_rlen` parameters are specified, the storage is specified 149627430b45SBarry Smith for every row, corresponding to both DIAGONAL and OFF-DIAGONAL submatrices. 149720f4b53cSBarry Smith In the above case the values for `d_nnz`, `o_nnz` are 149827430b45SBarry Smith .vb 149920f4b53cSBarry Smith proc0 - d_nnz = [2,2,2] and o_nnz = [2,2,2] 150020f4b53cSBarry Smith proc1 - d_nnz = [3,3,2] and o_nnz = [2,1,1] 150120f4b53cSBarry Smith proc2 - d_nnz = [1,1] and o_nnz = [4,4] 150227430b45SBarry Smith .ve 150327430b45SBarry Smith Here the space allocated is still 37 though there are 34 nonzeros because 150427430b45SBarry Smith the allocation is always done according to rlenmax. 150527430b45SBarry Smith 150627430b45SBarry Smith Level: intermediate 150727430b45SBarry Smith 150827430b45SBarry Smith Notes: 150911a5261eSBarry Smith It is recommended that one use the `MatCreate()`, `MatSetType()` and/or `MatSetFromOptions()`, 1510f6f02116SRichard Tran Mills MatXXXXSetPreallocation() paradigm instead of this routine directly. 151111a5261eSBarry Smith [MatXXXXSetPreallocation() is, for example, `MatSeqSELLSetPreallocation()`] 1512d4002b98SHong Zhang 1513d4002b98SHong Zhang If the *_rlen parameter is given then the *_rlenmax parameter is ignored 1514d4002b98SHong Zhang 151520f4b53cSBarry Smith `m`, `n`, `M`, `N` parameters specify the size of the matrix, and its partitioning across 151620f4b53cSBarry Smith processors, while `d_rlenmax`, `d_rlen`, `o_rlenmax` , `o_rlen` parameters specify the approximate 1517d4002b98SHong Zhang storage requirements for this matrix. 1518d4002b98SHong Zhang 151911a5261eSBarry Smith If `PETSC_DECIDE` or `PETSC_DETERMINE` is used for a particular argument on one 1520d4002b98SHong Zhang processor than it must be used on all processors that share the object for 1521d4002b98SHong Zhang that argument. 1522d4002b98SHong Zhang 1523d4002b98SHong Zhang The user MUST specify either the local or global matrix dimensions 1524d4002b98SHong Zhang (possibly both). 1525d4002b98SHong Zhang 1526d4002b98SHong Zhang The parallel matrix is partitioned across processors such that the 1527d4002b98SHong Zhang first m0 rows belong to process 0, the next m1 rows belong to 1528d4002b98SHong Zhang process 1, the next m2 rows belong to process 2 etc.. where 1529d4002b98SHong Zhang m0,m1,m2,.. are the input parameter 'm'. i.e each processor stores 153020f4b53cSBarry Smith values corresponding to [`m` x `N`] submatrix. 1531d4002b98SHong Zhang 1532d4002b98SHong Zhang The columns are logically partitioned with the n0 columns belonging 1533d4002b98SHong Zhang to 0th partition, the next n1 columns belonging to the next 153420f4b53cSBarry Smith partition etc.. where n0,n1,n2... are the input parameter `n`. 1535d4002b98SHong Zhang 1536d4002b98SHong Zhang The DIAGONAL portion of the local submatrix on any given processor 153720f4b53cSBarry Smith is the submatrix corresponding to the rows and columns `m`, `n` 1538d4002b98SHong Zhang corresponding to the given processor. i.e diagonal matrix on 1539d4002b98SHong Zhang process 0 is [m0 x n0], diagonal matrix on process 1 is [m1 x n1] 1540d4002b98SHong Zhang etc. The remaining portion of the local submatrix [m x (N-n)] 1541d4002b98SHong Zhang constitute the OFF-DIAGONAL portion. The example below better 1542d4002b98SHong Zhang illustrates this concept. 1543d4002b98SHong Zhang 1544d4002b98SHong Zhang For a square global matrix we define each processor's diagonal portion 1545d4002b98SHong Zhang to be its local rows and the corresponding columns (a square submatrix); 1546d4002b98SHong Zhang each processor's off-diagonal portion encompasses the remainder of the 1547d4002b98SHong Zhang local matrix (a rectangular submatrix). 1548d4002b98SHong Zhang 154920f4b53cSBarry Smith If `o_rlen`, `d_rlen` are specified, then `o_rlenmax`, and `d_rlenmax` are ignored. 1550d4002b98SHong Zhang 1551d4002b98SHong Zhang When calling this routine with a single process communicator, a matrix of 155211a5261eSBarry Smith type `MATSEQSELL` is returned. If a matrix of type `MATMPISELL` is desired for this 155327430b45SBarry Smith type of communicator, use the construction mechanism 1554d4002b98SHong Zhang .vb 155527430b45SBarry Smith MatCreate(...,&A); 155627430b45SBarry Smith MatSetType(A,MATMPISELL); 155727430b45SBarry Smith MatSetSizes(A, m,n,M,N); 155827430b45SBarry Smith MatMPISELLSetPreallocation(A,...); 1559d4002b98SHong Zhang .ve 1560d4002b98SHong Zhang 156167be906fSBarry Smith .seealso: `Mat`, `MATSELL`, `MatCreate()`, `MatCreateSeqSELL()`, `MatSetValues()`, `MatMPISELLSetPreallocation()`, `MatMPISELLSetPreallocationSELL()`, 1562db781477SPatrick Sanan `MATMPISELL`, `MatCreateMPISELLWithArrays()` 1563d4002b98SHong Zhang @*/ 1564d71ae5a4SJacob 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) 1565d71ae5a4SJacob Faibussowitsch { 1566d4002b98SHong Zhang PetscMPIInt size; 1567d4002b98SHong Zhang 1568d4002b98SHong Zhang PetscFunctionBegin; 15699566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, A)); 15709566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*A, m, n, M, N)); 15719566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 1572d4002b98SHong Zhang if (size > 1) { 15739566063dSJacob Faibussowitsch PetscCall(MatSetType(*A, MATMPISELL)); 15749566063dSJacob Faibussowitsch PetscCall(MatMPISELLSetPreallocation(*A, d_rlenmax, d_rlen, o_rlenmax, o_rlen)); 1575d4002b98SHong Zhang } else { 15769566063dSJacob Faibussowitsch PetscCall(MatSetType(*A, MATSEQSELL)); 15779566063dSJacob Faibussowitsch PetscCall(MatSeqSELLSetPreallocation(*A, d_rlenmax, d_rlen)); 1578d4002b98SHong Zhang } 15793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1580d4002b98SHong Zhang } 1581d4002b98SHong Zhang 1582d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMPISELLGetSeqSELL(Mat A, Mat *Ad, Mat *Ao, const PetscInt *colmap[]) 1583d71ae5a4SJacob Faibussowitsch { 1584d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 1585d4002b98SHong Zhang PetscBool flg; 1586d4002b98SHong Zhang 1587d4002b98SHong Zhang PetscFunctionBegin; 15889566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMPISELL, &flg)); 158928b400f6SJacob Faibussowitsch PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "This function requires a MATMPISELL matrix as input"); 1590d4002b98SHong Zhang if (Ad) *Ad = a->A; 1591d4002b98SHong Zhang if (Ao) *Ao = a->B; 1592d4002b98SHong Zhang if (colmap) *colmap = a->garray; 15933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1594d4002b98SHong Zhang } 1595d4002b98SHong Zhang 1596d4002b98SHong Zhang /*@C 159711a5261eSBarry Smith MatMPISELLGetLocalMatCondensed - Creates a `MATSEQSELL` matrix from an `MATMPISELL` matrix by taking all its local rows and NON-ZERO columns 1598d4002b98SHong Zhang 1599d4002b98SHong Zhang Not Collective 1600d4002b98SHong Zhang 1601d4002b98SHong Zhang Input Parameters: 1602d4002b98SHong Zhang + A - the matrix 160311a5261eSBarry Smith . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 160467be906fSBarry Smith . row - index sets of rows to extract (or `NULL`) 160567be906fSBarry Smith - col - index sets of columns to extract (or `NULL`) 1606d4002b98SHong Zhang 1607d4002b98SHong Zhang Output Parameter: 1608d4002b98SHong Zhang . A_loc - the local sequential matrix generated 1609d4002b98SHong Zhang 1610d4002b98SHong Zhang Level: developer 1611d4002b98SHong Zhang 161267be906fSBarry Smith .seealso: `Mat`, `MATSEQSELL`, `MATMPISELL`, `MatGetOwnershipRange()`, `MatMPISELLGetLocalMat()` 1613d4002b98SHong Zhang @*/ 1614d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMPISELLGetLocalMatCondensed(Mat A, MatReuse scall, IS *row, IS *col, Mat *A_loc) 1615d71ae5a4SJacob Faibussowitsch { 1616d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 1617d4002b98SHong Zhang PetscInt i, start, end, ncols, nzA, nzB, *cmap, imark, *idx; 1618d4002b98SHong Zhang IS isrowa, iscola; 1619d4002b98SHong Zhang Mat *aloc; 1620d4002b98SHong Zhang PetscBool match; 1621d4002b98SHong Zhang 1622d4002b98SHong Zhang PetscFunctionBegin; 16239566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMPISELL, &match)); 162428b400f6SJacob Faibussowitsch PetscCheck(match, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Requires MATMPISELL matrix as input"); 16259566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(MAT_Getlocalmatcondensed, A, 0, 0, 0)); 1626d4002b98SHong Zhang if (!row) { 16279371c9d4SSatish Balay start = A->rmap->rstart; 16289371c9d4SSatish Balay end = A->rmap->rend; 16299566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, end - start, start, 1, &isrowa)); 1630d4002b98SHong Zhang } else { 1631d4002b98SHong Zhang isrowa = *row; 1632d4002b98SHong Zhang } 1633d4002b98SHong Zhang if (!col) { 1634d4002b98SHong Zhang start = A->cmap->rstart; 1635d4002b98SHong Zhang cmap = a->garray; 1636d4002b98SHong Zhang nzA = a->A->cmap->n; 1637d4002b98SHong Zhang nzB = a->B->cmap->n; 16389566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nzA + nzB, &idx)); 1639d4002b98SHong Zhang ncols = 0; 1640d4002b98SHong Zhang for (i = 0; i < nzB; i++) { 1641d4002b98SHong Zhang if (cmap[i] < start) idx[ncols++] = cmap[i]; 1642d4002b98SHong Zhang else break; 1643d4002b98SHong Zhang } 1644d4002b98SHong Zhang imark = i; 1645d4002b98SHong Zhang for (i = 0; i < nzA; i++) idx[ncols++] = start + i; 1646d4002b98SHong Zhang for (i = imark; i < nzB; i++) idx[ncols++] = cmap[i]; 16479566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, ncols, idx, PETSC_OWN_POINTER, &iscola)); 1648d4002b98SHong Zhang } else { 1649d4002b98SHong Zhang iscola = *col; 1650d4002b98SHong Zhang } 1651d4002b98SHong Zhang if (scall != MAT_INITIAL_MATRIX) { 16529566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1, &aloc)); 1653d4002b98SHong Zhang aloc[0] = *A_loc; 1654d4002b98SHong Zhang } 16559566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrices(A, 1, &isrowa, &iscola, scall, &aloc)); 1656d4002b98SHong Zhang *A_loc = aloc[0]; 16579566063dSJacob Faibussowitsch PetscCall(PetscFree(aloc)); 165848a46eb9SPierre Jolivet if (!row) PetscCall(ISDestroy(&isrowa)); 165948a46eb9SPierre Jolivet if (!col) PetscCall(ISDestroy(&iscola)); 16609566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(MAT_Getlocalmatcondensed, A, 0, 0, 0)); 16613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1662d4002b98SHong Zhang } 1663d4002b98SHong Zhang 1664d4002b98SHong Zhang #include <../src/mat/impls/aij/mpi/mpiaij.h> 1665d4002b98SHong Zhang 1666d71ae5a4SJacob Faibussowitsch PetscErrorCode MatConvert_MPISELL_MPIAIJ(Mat A, MatType newtype, MatReuse reuse, Mat *newmat) 1667d71ae5a4SJacob Faibussowitsch { 1668d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 1669d4002b98SHong Zhang Mat B; 1670d4002b98SHong Zhang Mat_MPIAIJ *b; 1671d4002b98SHong Zhang 1672d4002b98SHong Zhang PetscFunctionBegin; 167328b400f6SJacob Faibussowitsch PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Matrix must be assembled"); 1674d4002b98SHong Zhang 167594a8b381SRichard Tran Mills if (reuse == MAT_REUSE_MATRIX) { 167694a8b381SRichard Tran Mills B = *newmat; 167794a8b381SRichard Tran Mills } else { 16789566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B)); 16799566063dSJacob Faibussowitsch PetscCall(MatSetType(B, MATMPIAIJ)); 16809566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N)); 16819566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(B, A->rmap->bs, A->cmap->bs)); 16829566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(B, 0, NULL)); 16839566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(B, 0, NULL, 0, NULL)); 168494a8b381SRichard Tran Mills } 1685d4002b98SHong Zhang b = (Mat_MPIAIJ *)B->data; 168694a8b381SRichard Tran Mills 168794a8b381SRichard Tran Mills if (reuse == MAT_REUSE_MATRIX) { 16889566063dSJacob Faibussowitsch PetscCall(MatConvert_SeqSELL_SeqAIJ(a->A, MATSEQAIJ, MAT_REUSE_MATRIX, &b->A)); 16899566063dSJacob Faibussowitsch PetscCall(MatConvert_SeqSELL_SeqAIJ(a->B, MATSEQAIJ, MAT_REUSE_MATRIX, &b->B)); 169094a8b381SRichard Tran Mills } else { 16919566063dSJacob Faibussowitsch PetscCall(MatDestroy(&b->A)); 16929566063dSJacob Faibussowitsch PetscCall(MatDestroy(&b->B)); 16939566063dSJacob Faibussowitsch PetscCall(MatDisAssemble_MPISELL(A)); 16949566063dSJacob Faibussowitsch PetscCall(MatConvert_SeqSELL_SeqAIJ(a->A, MATSEQAIJ, MAT_INITIAL_MATRIX, &b->A)); 16959566063dSJacob Faibussowitsch PetscCall(MatConvert_SeqSELL_SeqAIJ(a->B, MATSEQAIJ, MAT_INITIAL_MATRIX, &b->B)); 16969566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 16979566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 16989566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 16999566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 170094a8b381SRichard Tran Mills } 1701d4002b98SHong Zhang 1702d4002b98SHong Zhang if (reuse == MAT_INPLACE_MATRIX) { 17039566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(A, &B)); 1704d4002b98SHong Zhang } else { 1705d4002b98SHong Zhang *newmat = B; 1706d4002b98SHong Zhang } 17073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1708d4002b98SHong Zhang } 1709d4002b98SHong Zhang 1710d71ae5a4SJacob Faibussowitsch PetscErrorCode MatConvert_MPIAIJ_MPISELL(Mat A, MatType newtype, MatReuse reuse, Mat *newmat) 1711d71ae5a4SJacob Faibussowitsch { 1712d4002b98SHong Zhang Mat_MPIAIJ *a = (Mat_MPIAIJ *)A->data; 1713d4002b98SHong Zhang Mat B; 1714d4002b98SHong Zhang Mat_MPISELL *b; 1715d4002b98SHong Zhang 1716d4002b98SHong Zhang PetscFunctionBegin; 171728b400f6SJacob Faibussowitsch PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Matrix must be assembled"); 1718d4002b98SHong Zhang 171994a8b381SRichard Tran Mills if (reuse == MAT_REUSE_MATRIX) { 172094a8b381SRichard Tran Mills B = *newmat; 172194a8b381SRichard Tran Mills } else { 17222d1451d4SHong Zhang Mat_SeqAIJ *Aa = (Mat_SeqAIJ *)a->A->data, *Ba = (Mat_SeqAIJ *)a->B->data; 17232d1451d4SHong 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; 17242d1451d4SHong Zhang PetscInt *d_nnz, *o_nnz; 17252d1451d4SHong Zhang PetscCall(PetscMalloc2(lm, &d_nnz, lm, &o_nnz)); 17262d1451d4SHong Zhang for (i = 0; i < lm; i++) { 17272d1451d4SHong Zhang d_nnz[i] = Aa->i[i + 1] - Aa->i[i]; 17282d1451d4SHong Zhang o_nnz[i] = Ba->i[i + 1] - Ba->i[i]; 17292d1451d4SHong Zhang if (d_nnz[i] > d_nz) d_nz = d_nnz[i]; 17302d1451d4SHong Zhang if (o_nnz[i] > o_nz) o_nz = o_nnz[i]; 17312d1451d4SHong Zhang } 17329566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B)); 17339566063dSJacob Faibussowitsch PetscCall(MatSetType(B, MATMPISELL)); 17342d1451d4SHong Zhang PetscCall(MatSetSizes(B, lm, ln, m, n)); 17359566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(B, A->rmap->bs, A->cmap->bs)); 17362d1451d4SHong Zhang PetscCall(MatSeqSELLSetPreallocation(B, d_nz, d_nnz)); 17372d1451d4SHong Zhang PetscCall(MatMPISELLSetPreallocation(B, d_nz, d_nnz, o_nz, o_nnz)); 17382d1451d4SHong Zhang PetscCall(PetscFree2(d_nnz, o_nnz)); 173994a8b381SRichard Tran Mills } 1740d4002b98SHong Zhang b = (Mat_MPISELL *)B->data; 174194a8b381SRichard Tran Mills 174294a8b381SRichard Tran Mills if (reuse == MAT_REUSE_MATRIX) { 17439566063dSJacob Faibussowitsch PetscCall(MatConvert_SeqAIJ_SeqSELL(a->A, MATSEQSELL, MAT_REUSE_MATRIX, &b->A)); 17449566063dSJacob Faibussowitsch PetscCall(MatConvert_SeqAIJ_SeqSELL(a->B, MATSEQSELL, MAT_REUSE_MATRIX, &b->B)); 174594a8b381SRichard Tran Mills } else { 17469566063dSJacob Faibussowitsch PetscCall(MatDestroy(&b->A)); 17479566063dSJacob Faibussowitsch PetscCall(MatDestroy(&b->B)); 17489566063dSJacob Faibussowitsch PetscCall(MatConvert_SeqAIJ_SeqSELL(a->A, MATSEQSELL, MAT_INITIAL_MATRIX, &b->A)); 17499566063dSJacob Faibussowitsch PetscCall(MatConvert_SeqAIJ_SeqSELL(a->B, MATSEQSELL, MAT_INITIAL_MATRIX, &b->B)); 17509566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 17519566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 17522d1451d4SHong Zhang PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 17532d1451d4SHong Zhang PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 175494a8b381SRichard Tran Mills } 1755d4002b98SHong Zhang 1756d4002b98SHong Zhang if (reuse == MAT_INPLACE_MATRIX) { 17579566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(A, &B)); 1758d4002b98SHong Zhang } else { 1759d4002b98SHong Zhang *newmat = B; 1760d4002b98SHong Zhang } 17613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1762d4002b98SHong Zhang } 1763d4002b98SHong Zhang 1764d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSOR_MPISELL(Mat matin, Vec bb, PetscReal omega, MatSORType flag, PetscReal fshift, PetscInt its, PetscInt lits, Vec xx) 1765d71ae5a4SJacob Faibussowitsch { 1766d4002b98SHong Zhang Mat_MPISELL *mat = (Mat_MPISELL *)matin->data; 1767f4259b30SLisandro Dalcin Vec bb1 = NULL; 1768d4002b98SHong Zhang 1769d4002b98SHong Zhang PetscFunctionBegin; 1770d4002b98SHong Zhang if (flag == SOR_APPLY_UPPER) { 17719566063dSJacob Faibussowitsch PetscCall((*mat->A->ops->sor)(mat->A, bb, omega, flag, fshift, lits, 1, xx)); 17723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1773d4002b98SHong Zhang } 1774d4002b98SHong Zhang 177548a46eb9SPierre Jolivet if (its > 1 || ~flag & SOR_ZERO_INITIAL_GUESS || flag & SOR_EISENSTAT) PetscCall(VecDuplicate(bb, &bb1)); 1776d4002b98SHong Zhang 1777d4002b98SHong Zhang if ((flag & SOR_LOCAL_SYMMETRIC_SWEEP) == SOR_LOCAL_SYMMETRIC_SWEEP) { 1778d4002b98SHong Zhang if (flag & SOR_ZERO_INITIAL_GUESS) { 17799566063dSJacob Faibussowitsch PetscCall((*mat->A->ops->sor)(mat->A, bb, omega, flag, fshift, lits, 1, xx)); 1780d4002b98SHong Zhang its--; 1781d4002b98SHong Zhang } 1782d4002b98SHong Zhang 1783d4002b98SHong Zhang while (its--) { 17849566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat->Mvctx, xx, mat->lvec, INSERT_VALUES, SCATTER_FORWARD)); 17859566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat->Mvctx, xx, mat->lvec, INSERT_VALUES, SCATTER_FORWARD)); 1786d4002b98SHong Zhang 1787d4002b98SHong Zhang /* update rhs: bb1 = bb - B*x */ 17889566063dSJacob Faibussowitsch PetscCall(VecScale(mat->lvec, -1.0)); 17899566063dSJacob Faibussowitsch PetscCall((*mat->B->ops->multadd)(mat->B, mat->lvec, bb, bb1)); 1790d4002b98SHong Zhang 1791d4002b98SHong Zhang /* local sweep */ 17929566063dSJacob Faibussowitsch PetscCall((*mat->A->ops->sor)(mat->A, bb1, omega, SOR_SYMMETRIC_SWEEP, fshift, lits, 1, xx)); 1793d4002b98SHong Zhang } 1794d4002b98SHong Zhang } else if (flag & SOR_LOCAL_FORWARD_SWEEP) { 1795d4002b98SHong Zhang if (flag & SOR_ZERO_INITIAL_GUESS) { 17969566063dSJacob Faibussowitsch PetscCall((*mat->A->ops->sor)(mat->A, bb, omega, flag, fshift, lits, 1, xx)); 1797d4002b98SHong Zhang its--; 1798d4002b98SHong Zhang } 1799d4002b98SHong Zhang while (its--) { 18009566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat->Mvctx, xx, mat->lvec, INSERT_VALUES, SCATTER_FORWARD)); 18019566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat->Mvctx, xx, mat->lvec, INSERT_VALUES, SCATTER_FORWARD)); 1802d4002b98SHong Zhang 1803d4002b98SHong Zhang /* update rhs: bb1 = bb - B*x */ 18049566063dSJacob Faibussowitsch PetscCall(VecScale(mat->lvec, -1.0)); 18059566063dSJacob Faibussowitsch PetscCall((*mat->B->ops->multadd)(mat->B, mat->lvec, bb, bb1)); 1806d4002b98SHong Zhang 1807d4002b98SHong Zhang /* local sweep */ 18089566063dSJacob Faibussowitsch PetscCall((*mat->A->ops->sor)(mat->A, bb1, omega, SOR_FORWARD_SWEEP, fshift, lits, 1, xx)); 1809d4002b98SHong Zhang } 1810d4002b98SHong Zhang } else if (flag & SOR_LOCAL_BACKWARD_SWEEP) { 1811d4002b98SHong Zhang if (flag & SOR_ZERO_INITIAL_GUESS) { 18129566063dSJacob Faibussowitsch PetscCall((*mat->A->ops->sor)(mat->A, bb, omega, flag, fshift, lits, 1, xx)); 1813d4002b98SHong Zhang its--; 1814d4002b98SHong Zhang } 1815d4002b98SHong Zhang while (its--) { 18169566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat->Mvctx, xx, mat->lvec, INSERT_VALUES, SCATTER_FORWARD)); 18179566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat->Mvctx, xx, mat->lvec, INSERT_VALUES, SCATTER_FORWARD)); 1818d4002b98SHong Zhang 1819d4002b98SHong Zhang /* update rhs: bb1 = bb - B*x */ 18209566063dSJacob Faibussowitsch PetscCall(VecScale(mat->lvec, -1.0)); 18219566063dSJacob Faibussowitsch PetscCall((*mat->B->ops->multadd)(mat->B, mat->lvec, bb, bb1)); 1822d4002b98SHong Zhang 1823d4002b98SHong Zhang /* local sweep */ 18249566063dSJacob Faibussowitsch PetscCall((*mat->A->ops->sor)(mat->A, bb1, omega, SOR_BACKWARD_SWEEP, fshift, lits, 1, xx)); 1825d4002b98SHong Zhang } 1826d4002b98SHong Zhang } else SETERRQ(PetscObjectComm((PetscObject)matin), PETSC_ERR_SUP, "Parallel SOR not supported"); 1827d4002b98SHong Zhang 18289566063dSJacob Faibussowitsch PetscCall(VecDestroy(&bb1)); 1829d4002b98SHong Zhang 1830d4002b98SHong Zhang matin->factorerrortype = mat->A->factorerrortype; 18313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1832d4002b98SHong Zhang } 1833d4002b98SHong Zhang 1834d4002b98SHong Zhang /*MC 1835d4002b98SHong Zhang MATMPISELL - MATMPISELL = "MPISELL" - A matrix type to be used for parallel sparse matrices. 1836d4002b98SHong Zhang 1837d4002b98SHong Zhang Options Database Keys: 183811a5261eSBarry Smith . -mat_type mpisell - sets the matrix type to `MATMPISELL` during a call to `MatSetFromOptions()` 1839d4002b98SHong Zhang 1840d4002b98SHong Zhang Level: beginner 1841d4002b98SHong Zhang 184267be906fSBarry Smith .seealso: `Mat`, `MATSELL`, `MATSEQSELL` `MatCreateSELL()` 1843d4002b98SHong Zhang M*/ 1844d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_MPISELL(Mat B) 1845d71ae5a4SJacob Faibussowitsch { 1846d4002b98SHong Zhang Mat_MPISELL *b; 1847d4002b98SHong Zhang PetscMPIInt size; 1848d4002b98SHong Zhang 1849d4002b98SHong Zhang PetscFunctionBegin; 18509566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)B), &size)); 18514dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&b)); 1852d4002b98SHong Zhang B->data = (void *)b; 18539566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(B->ops, &MatOps_Values, sizeof(struct _MatOps))); 1854d4002b98SHong Zhang B->assembled = PETSC_FALSE; 1855d4002b98SHong Zhang B->insertmode = NOT_SET_VALUES; 1856d4002b98SHong Zhang b->size = size; 18579566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)B), &b->rank)); 1858d4002b98SHong Zhang /* build cache for off array entries formed */ 18599566063dSJacob Faibussowitsch PetscCall(MatStashCreate_Private(PetscObjectComm((PetscObject)B), 1, &B->stash)); 1860d4002b98SHong Zhang 1861d4002b98SHong Zhang b->donotstash = PETSC_FALSE; 1862f4259b30SLisandro Dalcin b->colmap = NULL; 1863f4259b30SLisandro Dalcin b->garray = NULL; 1864d4002b98SHong Zhang b->roworiented = PETSC_TRUE; 1865d4002b98SHong Zhang 1866d4002b98SHong Zhang /* stuff used for matrix vector multiply */ 1867d4002b98SHong Zhang b->lvec = NULL; 1868d4002b98SHong Zhang b->Mvctx = NULL; 1869d4002b98SHong Zhang 1870d4002b98SHong Zhang /* stuff for MatGetRow() */ 1871f4259b30SLisandro Dalcin b->rowindices = NULL; 1872f4259b30SLisandro Dalcin b->rowvalues = NULL; 1873d4002b98SHong Zhang b->getrowactive = PETSC_FALSE; 1874d4002b98SHong Zhang 18759566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatStoreValues_C", MatStoreValues_MPISELL)); 18769566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatRetrieveValues_C", MatRetrieveValues_MPISELL)); 18779566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatIsTranspose_C", MatIsTranspose_MPISELL)); 18789566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatMPISELLSetPreallocation_C", MatMPISELLSetPreallocation_MPISELL)); 18799566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_mpisell_mpiaij_C", MatConvert_MPISELL_MPIAIJ)); 18809566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDiagonalScaleLocal_C", MatDiagonalScaleLocal_MPISELL)); 18819566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATMPISELL)); 18823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1883d4002b98SHong Zhang } 1884