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