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: 18*20f4b53cSBarry Smith . -mat_type sell - sets the matrix type to `MATSELL` during a call to `MatSetFromOptions()` 19d4002b98SHong Zhang 20d4002b98SHong Zhang Level: beginner 21d4002b98SHong Zhang 2267be906fSBarry Smith .seealso: `Mat`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSELL()`, `MatCreateSeqSELL()`, `MATSEQSELL`, `MATMPISELL` 23d4002b98SHong Zhang M*/ 24d4002b98SHong Zhang 25d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDiagonalSet_MPISELL(Mat Y, Vec D, InsertMode is) 26d71ae5a4SJacob Faibussowitsch { 27d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)Y->data; 28d4002b98SHong Zhang 29d4002b98SHong Zhang PetscFunctionBegin; 30d4002b98SHong Zhang if (Y->assembled && Y->rmap->rstart == Y->cmap->rstart && Y->rmap->rend == Y->cmap->rend) { 319566063dSJacob Faibussowitsch PetscCall(MatDiagonalSet(sell->A, D, is)); 32d4002b98SHong Zhang } else { 339566063dSJacob Faibussowitsch PetscCall(MatDiagonalSet_Default(Y, D, is)); 34d4002b98SHong Zhang } 353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 36d4002b98SHong Zhang } 37d4002b98SHong Zhang 38d4002b98SHong Zhang /* 39d4002b98SHong Zhang Local utility routine that creates a mapping from the global column 40d4002b98SHong Zhang number to the local number in the off-diagonal part of the local 41d4002b98SHong Zhang storage of the matrix. When PETSC_USE_CTABLE is used this is scalable at 42d4002b98SHong Zhang a slightly higher hash table cost; without it it is not scalable (each processor 43da81f932SPierre Jolivet has an order N integer array but is fast to access. 44d4002b98SHong Zhang */ 45d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateColmap_MPISELL_Private(Mat mat) 46d71ae5a4SJacob Faibussowitsch { 47d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)mat->data; 48d4002b98SHong Zhang PetscInt n = sell->B->cmap->n, i; 49d4002b98SHong Zhang 50d4002b98SHong Zhang PetscFunctionBegin; 5128b400f6SJacob Faibussowitsch PetscCheck(sell->garray, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MPISELL Matrix was assembled but is missing garray"); 52d4002b98SHong Zhang #if defined(PETSC_USE_CTABLE) 53eec179cfSJacob Faibussowitsch PetscCall(PetscHMapICreateWithSize(n, &sell->colmap)); 54c76ffc5fSJacob Faibussowitsch for (i = 0; i < n; i++) PetscCall(PetscHMapISet(sell->colmap, sell->garray[i] + 1, i + 1)); 55d4002b98SHong Zhang #else 569566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(mat->cmap->N + 1, &sell->colmap)); 57d4002b98SHong Zhang for (i = 0; i < n; i++) sell->colmap[sell->garray[i]] = i + 1; 58d4002b98SHong Zhang #endif 593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 60d4002b98SHong Zhang } 61d4002b98SHong Zhang 62d4002b98SHong Zhang #define MatSetValues_SeqSELL_A_Private(row, col, value, addv, orow, ocol) \ 63d4002b98SHong Zhang { \ 64d4002b98SHong Zhang if (col <= lastcol1) low1 = 0; \ 65d4002b98SHong Zhang else high1 = nrow1; \ 66d4002b98SHong Zhang lastcol1 = col; \ 67d4002b98SHong Zhang while (high1 - low1 > 5) { \ 68d4002b98SHong Zhang t = (low1 + high1) / 2; \ 69d4002b98SHong Zhang if (*(cp1 + 8 * t) > col) high1 = t; \ 70d4002b98SHong Zhang else low1 = t; \ 71d4002b98SHong Zhang } \ 72d4002b98SHong Zhang for (_i = low1; _i < high1; _i++) { \ 73d4002b98SHong Zhang if (*(cp1 + 8 * _i) > col) break; \ 74d4002b98SHong Zhang if (*(cp1 + 8 * _i) == col) { \ 75d4002b98SHong Zhang if (addv == ADD_VALUES) *(vp1 + 8 * _i) += value; \ 76d4002b98SHong Zhang else *(vp1 + 8 * _i) = value; \ 77d4002b98SHong Zhang goto a_noinsert; \ 78d4002b98SHong Zhang } \ 79d4002b98SHong Zhang } \ 809371c9d4SSatish Balay if (value == 0.0 && ignorezeroentries) { \ 819371c9d4SSatish Balay low1 = 0; \ 829371c9d4SSatish Balay high1 = nrow1; \ 839371c9d4SSatish Balay goto a_noinsert; \ 849371c9d4SSatish Balay } \ 859371c9d4SSatish Balay if (nonew == 1) { \ 869371c9d4SSatish Balay low1 = 0; \ 879371c9d4SSatish Balay high1 = nrow1; \ 889371c9d4SSatish Balay goto a_noinsert; \ 899371c9d4SSatish Balay } \ 9008401ef6SPierre 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); \ 91d4002b98SHong Zhang MatSeqXSELLReallocateSELL(A, am, 1, nrow1, a->sliidx, row / 8, row, col, a->colidx, a->val, cp1, vp1, nonew, MatScalar); \ 92d4002b98SHong Zhang /* shift up all the later entries in this row */ \ 93d4002b98SHong Zhang for (ii = nrow1 - 1; ii >= _i; ii--) { \ 94d4002b98SHong Zhang *(cp1 + 8 * (ii + 1)) = *(cp1 + 8 * ii); \ 95d4002b98SHong Zhang *(vp1 + 8 * (ii + 1)) = *(vp1 + 8 * ii); \ 96d4002b98SHong Zhang } \ 97d4002b98SHong Zhang *(cp1 + 8 * _i) = col; \ 98d4002b98SHong Zhang *(vp1 + 8 * _i) = value; \ 999371c9d4SSatish Balay a->nz++; \ 1009371c9d4SSatish Balay nrow1++; \ 1019371c9d4SSatish Balay A->nonzerostate++; \ 102d4002b98SHong Zhang a_noinsert:; \ 103d4002b98SHong Zhang a->rlen[row] = nrow1; \ 104d4002b98SHong Zhang } 105d4002b98SHong Zhang 106d4002b98SHong Zhang #define MatSetValues_SeqSELL_B_Private(row, col, value, addv, orow, ocol) \ 107d4002b98SHong Zhang { \ 108d4002b98SHong Zhang if (col <= lastcol2) low2 = 0; \ 109d4002b98SHong Zhang else high2 = nrow2; \ 110d4002b98SHong Zhang lastcol2 = col; \ 111d4002b98SHong Zhang while (high2 - low2 > 5) { \ 112d4002b98SHong Zhang t = (low2 + high2) / 2; \ 113d4002b98SHong Zhang if (*(cp2 + 8 * t) > col) high2 = t; \ 114d4002b98SHong Zhang else low2 = t; \ 115d4002b98SHong Zhang } \ 116d4002b98SHong Zhang for (_i = low2; _i < high2; _i++) { \ 117d4002b98SHong Zhang if (*(cp2 + 8 * _i) > col) break; \ 118d4002b98SHong Zhang if (*(cp2 + 8 * _i) == col) { \ 119d4002b98SHong Zhang if (addv == ADD_VALUES) *(vp2 + 8 * _i) += value; \ 120d4002b98SHong Zhang else *(vp2 + 8 * _i) = value; \ 121d4002b98SHong Zhang goto b_noinsert; \ 122d4002b98SHong Zhang } \ 123d4002b98SHong Zhang } \ 1249371c9d4SSatish Balay if (value == 0.0 && ignorezeroentries) { \ 1259371c9d4SSatish Balay low2 = 0; \ 1269371c9d4SSatish Balay high2 = nrow2; \ 1279371c9d4SSatish Balay goto b_noinsert; \ 1289371c9d4SSatish Balay } \ 1299371c9d4SSatish Balay if (nonew == 1) { \ 1309371c9d4SSatish Balay low2 = 0; \ 1319371c9d4SSatish Balay high2 = nrow2; \ 1329371c9d4SSatish Balay goto b_noinsert; \ 1339371c9d4SSatish Balay } \ 13408401ef6SPierre 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); \ 135d4002b98SHong Zhang MatSeqXSELLReallocateSELL(B, bm, 1, nrow2, b->sliidx, row / 8, row, col, b->colidx, b->val, cp2, vp2, nonew, MatScalar); \ 136d4002b98SHong Zhang /* shift up all the later entries in this row */ \ 137d4002b98SHong Zhang for (ii = nrow2 - 1; ii >= _i; ii--) { \ 138d4002b98SHong Zhang *(cp2 + 8 * (ii + 1)) = *(cp2 + 8 * ii); \ 139d4002b98SHong Zhang *(vp2 + 8 * (ii + 1)) = *(vp2 + 8 * ii); \ 140d4002b98SHong Zhang } \ 141d4002b98SHong Zhang *(cp2 + 8 * _i) = col; \ 142d4002b98SHong Zhang *(vp2 + 8 * _i) = value; \ 1439371c9d4SSatish Balay b->nz++; \ 1449371c9d4SSatish Balay nrow2++; \ 1459371c9d4SSatish Balay B->nonzerostate++; \ 146d4002b98SHong Zhang b_noinsert:; \ 147d4002b98SHong Zhang b->rlen[row] = nrow2; \ 148d4002b98SHong Zhang } 149d4002b98SHong Zhang 150d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetValues_MPISELL(Mat mat, PetscInt m, const PetscInt im[], PetscInt n, const PetscInt in[], const PetscScalar v[], InsertMode addv) 151d71ae5a4SJacob Faibussowitsch { 152d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)mat->data; 153d4002b98SHong Zhang PetscScalar value; 154d4002b98SHong Zhang PetscInt i, j, rstart = mat->rmap->rstart, rend = mat->rmap->rend, shift1, shift2; 155d4002b98SHong Zhang PetscInt cstart = mat->cmap->rstart, cend = mat->cmap->rend, row, col; 156d4002b98SHong Zhang PetscBool roworiented = sell->roworiented; 157d4002b98SHong Zhang 158d4002b98SHong Zhang /* Some Variables required in the macro */ 159d4002b98SHong Zhang Mat A = sell->A; 160d4002b98SHong Zhang Mat_SeqSELL *a = (Mat_SeqSELL *)A->data; 161d4002b98SHong Zhang PetscBool ignorezeroentries = a->ignorezeroentries, found; 162d4002b98SHong Zhang Mat B = sell->B; 163d4002b98SHong Zhang Mat_SeqSELL *b = (Mat_SeqSELL *)B->data; 164d4002b98SHong Zhang PetscInt *cp1, *cp2, ii, _i, nrow1, nrow2, low1, high1, low2, high2, t, lastcol1, lastcol2; 165d4002b98SHong Zhang MatScalar *vp1, *vp2; 166d4002b98SHong Zhang 167d4002b98SHong Zhang PetscFunctionBegin; 168d4002b98SHong Zhang for (i = 0; i < m; i++) { 169d4002b98SHong Zhang if (im[i] < 0) continue; 1706bdcaf15SBarry Smith PetscCheck(im[i] < mat->rmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row too large: row %" PetscInt_FMT " max %" PetscInt_FMT, im[i], mat->rmap->N - 1); 171d4002b98SHong Zhang if (im[i] >= rstart && im[i] < rend) { 172d4002b98SHong Zhang row = im[i] - rstart; 173d4002b98SHong Zhang lastcol1 = -1; 174d4002b98SHong Zhang shift1 = a->sliidx[row >> 3] + (row & 0x07); /* starting index of the row */ 175d4002b98SHong Zhang cp1 = a->colidx + shift1; 176d4002b98SHong Zhang vp1 = a->val + shift1; 177d4002b98SHong Zhang nrow1 = a->rlen[row]; 178d4002b98SHong Zhang low1 = 0; 179d4002b98SHong Zhang high1 = nrow1; 180d4002b98SHong Zhang lastcol2 = -1; 181d4002b98SHong Zhang shift2 = b->sliidx[row >> 3] + (row & 0x07); /* starting index of the row */ 182d4002b98SHong Zhang cp2 = b->colidx + shift2; 183d4002b98SHong Zhang vp2 = b->val + shift2; 184d4002b98SHong Zhang nrow2 = b->rlen[row]; 185d4002b98SHong Zhang low2 = 0; 186d4002b98SHong Zhang high2 = nrow2; 187d4002b98SHong Zhang 188d4002b98SHong Zhang for (j = 0; j < n; j++) { 189d4002b98SHong Zhang if (roworiented) value = v[i * n + j]; 190d4002b98SHong Zhang else value = v[i + j * m]; 191d4002b98SHong Zhang if (ignorezeroentries && value == 0.0 && (addv == ADD_VALUES)) continue; 192d4002b98SHong Zhang if (in[j] >= cstart && in[j] < cend) { 193d4002b98SHong Zhang col = in[j] - cstart; 194d4002b98SHong Zhang MatSetValue_SeqSELL_Private(A, row, col, value, addv, im[i], in[j], cp1, vp1, lastcol1, low1, high1); /* set one value */ 195f7d195e4SLawrence Mitchell } else if (in[j] < 0) { 196f7d195e4SLawrence Mitchell continue; 197f7d195e4SLawrence Mitchell } else { 198f7d195e4SLawrence 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); 199d4002b98SHong Zhang if (mat->was_assembled) { 20048a46eb9SPierre Jolivet if (!sell->colmap) PetscCall(MatCreateColmap_MPISELL_Private(mat)); 201d4002b98SHong Zhang #if defined(PETSC_USE_CTABLE) 202eec179cfSJacob Faibussowitsch PetscCall(PetscHMapIGetWithDefault(sell->colmap, in[j] + 1, 0, &col)); 203d4002b98SHong Zhang col--; 204d4002b98SHong Zhang #else 205d4002b98SHong Zhang col = sell->colmap[in[j]] - 1; 206d4002b98SHong Zhang #endif 207d4002b98SHong Zhang if (col < 0 && !((Mat_SeqSELL *)(sell->B->data))->nonew) { 2089566063dSJacob Faibussowitsch PetscCall(MatDisAssemble_MPISELL(mat)); 209d4002b98SHong Zhang col = in[j]; 210d4002b98SHong Zhang /* Reinitialize the variables required by MatSetValues_SeqSELL_B_Private() */ 211d4002b98SHong Zhang B = sell->B; 212d4002b98SHong Zhang b = (Mat_SeqSELL *)B->data; 213d4002b98SHong Zhang shift2 = b->sliidx[row >> 3] + (row & 0x07); /* starting index of the row */ 214d4002b98SHong Zhang cp2 = b->colidx + shift2; 215d4002b98SHong Zhang vp2 = b->val + shift2; 216d4002b98SHong Zhang nrow2 = b->rlen[row]; 217d4002b98SHong Zhang low2 = 0; 218d4002b98SHong Zhang high2 = nrow2; 219f7d195e4SLawrence Mitchell } else { 220f7d195e4SLawrence 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]); 221f7d195e4SLawrence Mitchell } 222d4002b98SHong Zhang } else col = in[j]; 223d4002b98SHong Zhang MatSetValue_SeqSELL_Private(B, row, col, value, addv, im[i], in[j], cp2, vp2, lastcol2, low2, high2); /* set one value */ 224d4002b98SHong Zhang } 225d4002b98SHong Zhang } 226d4002b98SHong Zhang } else { 22728b400f6SJacob 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]); 228d4002b98SHong Zhang if (!sell->donotstash) { 229d4002b98SHong Zhang mat->assembled = PETSC_FALSE; 230d4002b98SHong Zhang if (roworiented) { 2319566063dSJacob Faibussowitsch PetscCall(MatStashValuesRow_Private(&mat->stash, im[i], n, in, v + i * n, (PetscBool)(ignorezeroentries && (addv == ADD_VALUES)))); 232d4002b98SHong Zhang } else { 2339566063dSJacob Faibussowitsch PetscCall(MatStashValuesCol_Private(&mat->stash, im[i], n, in, v + i, m, (PetscBool)(ignorezeroentries && (addv == ADD_VALUES)))); 234d4002b98SHong Zhang } 235d4002b98SHong Zhang } 236d4002b98SHong Zhang } 237d4002b98SHong Zhang } 2383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 239d4002b98SHong Zhang } 240d4002b98SHong Zhang 241d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetValues_MPISELL(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 242d71ae5a4SJacob Faibussowitsch { 243d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)mat->data; 244d4002b98SHong Zhang PetscInt i, j, rstart = mat->rmap->rstart, rend = mat->rmap->rend; 245d4002b98SHong Zhang PetscInt cstart = mat->cmap->rstart, cend = mat->cmap->rend, row, col; 246d4002b98SHong Zhang 247d4002b98SHong Zhang PetscFunctionBegin; 248d4002b98SHong Zhang for (i = 0; i < m; i++) { 24954c59aa7SJacob Faibussowitsch if (idxm[i] < 0) continue; /* negative row */ 25054c59aa7SJacob 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); 251d4002b98SHong Zhang if (idxm[i] >= rstart && idxm[i] < rend) { 252d4002b98SHong Zhang row = idxm[i] - rstart; 253d4002b98SHong Zhang for (j = 0; j < n; j++) { 25454c59aa7SJacob Faibussowitsch if (idxn[j] < 0) continue; /* negative column */ 25554c59aa7SJacob 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); 256d4002b98SHong Zhang if (idxn[j] >= cstart && idxn[j] < cend) { 257d4002b98SHong Zhang col = idxn[j] - cstart; 2589566063dSJacob Faibussowitsch PetscCall(MatGetValues(sell->A, 1, &row, 1, &col, v + i * n + j)); 259d4002b98SHong Zhang } else { 26048a46eb9SPierre Jolivet if (!sell->colmap) PetscCall(MatCreateColmap_MPISELL_Private(mat)); 261d4002b98SHong Zhang #if defined(PETSC_USE_CTABLE) 262eec179cfSJacob Faibussowitsch PetscCall(PetscHMapIGetWithDefault(sell->colmap, idxn[j] + 1, 0, &col)); 263d4002b98SHong Zhang col--; 264d4002b98SHong Zhang #else 265d4002b98SHong Zhang col = sell->colmap[idxn[j]] - 1; 266d4002b98SHong Zhang #endif 267d4002b98SHong Zhang if ((col < 0) || (sell->garray[col] != idxn[j])) *(v + i * n + j) = 0.0; 26848a46eb9SPierre Jolivet else PetscCall(MatGetValues(sell->B, 1, &row, 1, &col, v + i * n + j)); 269d4002b98SHong Zhang } 270d4002b98SHong Zhang } 271d4002b98SHong Zhang } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only local values currently supported"); 272d4002b98SHong Zhang } 2733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 274d4002b98SHong Zhang } 275d4002b98SHong Zhang 276d4002b98SHong Zhang extern PetscErrorCode MatMultDiagonalBlock_MPISELL(Mat, Vec, Vec); 277d4002b98SHong Zhang 278d71ae5a4SJacob Faibussowitsch PetscErrorCode MatAssemblyBegin_MPISELL(Mat mat, MatAssemblyType mode) 279d71ae5a4SJacob Faibussowitsch { 280d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)mat->data; 281d4002b98SHong Zhang PetscInt nstash, reallocs; 282d4002b98SHong Zhang 283d4002b98SHong Zhang PetscFunctionBegin; 2843ba16761SJacob Faibussowitsch if (sell->donotstash || mat->nooffprocentries) PetscFunctionReturn(PETSC_SUCCESS); 285d4002b98SHong Zhang 2869566063dSJacob Faibussowitsch PetscCall(MatStashScatterBegin_Private(mat, &mat->stash, mat->rmap->range)); 2879566063dSJacob Faibussowitsch PetscCall(MatStashGetInfo_Private(&mat->stash, &nstash, &reallocs)); 2889566063dSJacob Faibussowitsch PetscCall(PetscInfo(sell->A, "Stash has %" PetscInt_FMT " entries, uses %" PetscInt_FMT " mallocs.\n", nstash, reallocs)); 2893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 290d4002b98SHong Zhang } 291d4002b98SHong Zhang 292d71ae5a4SJacob Faibussowitsch PetscErrorCode MatAssemblyEnd_MPISELL(Mat mat, MatAssemblyType mode) 293d71ae5a4SJacob Faibussowitsch { 294d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)mat->data; 295d4002b98SHong Zhang PetscMPIInt n; 296d4002b98SHong Zhang PetscInt i, flg; 297d4002b98SHong Zhang PetscInt *row, *col; 298d4002b98SHong Zhang PetscScalar *val; 299d4002b98SHong Zhang PetscBool other_disassembled; 300d4002b98SHong Zhang /* do not use 'b = (Mat_SeqSELL*)sell->B->data' as B can be reset in disassembly */ 301d4002b98SHong Zhang PetscFunctionBegin; 302d4002b98SHong Zhang if (!sell->donotstash && !mat->nooffprocentries) { 303d4002b98SHong Zhang while (1) { 3049566063dSJacob Faibussowitsch PetscCall(MatStashScatterGetMesg_Private(&mat->stash, &n, &row, &col, &val, &flg)); 305d4002b98SHong Zhang if (!flg) break; 306d4002b98SHong Zhang 307d4002b98SHong Zhang for (i = 0; i < n; i++) { /* assemble one by one */ 3089566063dSJacob Faibussowitsch PetscCall(MatSetValues_MPISELL(mat, 1, row + i, 1, col + i, val + i, mat->insertmode)); 309d4002b98SHong Zhang } 310d4002b98SHong Zhang } 3119566063dSJacob Faibussowitsch PetscCall(MatStashScatterEnd_Private(&mat->stash)); 312d4002b98SHong Zhang } 3139566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(sell->A, mode)); 3149566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(sell->A, mode)); 315d4002b98SHong Zhang 316d4002b98SHong Zhang /* 317d4002b98SHong Zhang determine if any processor has disassembled, if so we must 3186aad120cSJose E. Roman also disassemble ourselves, in order that we may reassemble. 319d4002b98SHong Zhang */ 320d4002b98SHong Zhang /* 321d4002b98SHong Zhang if nonzero structure of submatrix B cannot change then we know that 322d4002b98SHong Zhang no processor disassembled thus we can skip this stuff 323d4002b98SHong Zhang */ 324d4002b98SHong Zhang if (!((Mat_SeqSELL *)sell->B->data)->nonew) { 3255f9db2b2SJunchao Zhang PetscCall(MPIU_Allreduce(&mat->was_assembled, &other_disassembled, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)mat))); 32608401ef6SPierre Jolivet PetscCheck(!mat->was_assembled || other_disassembled, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatDisAssemble not implemented yet"); 327d4002b98SHong Zhang } 32848a46eb9SPierre Jolivet if (!mat->was_assembled && mode == MAT_FINAL_ASSEMBLY) PetscCall(MatSetUpMultiply_MPISELL(mat)); 329d4002b98SHong Zhang /* 3309566063dSJacob Faibussowitsch PetscCall(MatSetOption(sell->B,MAT_USE_INODES,PETSC_FALSE)); 331d4002b98SHong Zhang */ 3329566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(sell->B, mode)); 3339566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(sell->B, mode)); 3349566063dSJacob Faibussowitsch PetscCall(PetscFree2(sell->rowvalues, sell->rowindices)); 335f4259b30SLisandro Dalcin sell->rowvalues = NULL; 3369566063dSJacob Faibussowitsch PetscCall(VecDestroy(&sell->diag)); 337d4002b98SHong Zhang 338d4002b98SHong Zhang /* if no new nonzero locations are allowed in matrix then only set the matrix state the first time through */ 339d4002b98SHong Zhang if ((!mat->was_assembled && mode == MAT_FINAL_ASSEMBLY) || !((Mat_SeqSELL *)(sell->A->data))->nonew) { 340d4002b98SHong Zhang PetscObjectState state = sell->A->nonzerostate + sell->B->nonzerostate; 3411c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&state, &mat->nonzerostate, 1, MPIU_INT64, MPI_SUM, PetscObjectComm((PetscObject)mat))); 342d4002b98SHong Zhang } 3433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 344d4002b98SHong Zhang } 345d4002b98SHong Zhang 346d71ae5a4SJacob Faibussowitsch PetscErrorCode MatZeroEntries_MPISELL(Mat A) 347d71ae5a4SJacob Faibussowitsch { 348d4002b98SHong Zhang Mat_MPISELL *l = (Mat_MPISELL *)A->data; 349d4002b98SHong Zhang 350d4002b98SHong Zhang PetscFunctionBegin; 3519566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(l->A)); 3529566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(l->B)); 3533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 354d4002b98SHong Zhang } 355d4002b98SHong Zhang 356d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMult_MPISELL(Mat A, Vec xx, Vec yy) 357d71ae5a4SJacob Faibussowitsch { 358d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 359d4002b98SHong Zhang PetscInt nt; 360d4002b98SHong Zhang 361d4002b98SHong Zhang PetscFunctionBegin; 3629566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(xx, &nt)); 36308401ef6SPierre 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); 3649566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(a->Mvctx, xx, a->lvec, INSERT_VALUES, SCATTER_FORWARD)); 3659566063dSJacob Faibussowitsch PetscCall((*a->A->ops->mult)(a->A, xx, yy)); 3669566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(a->Mvctx, xx, a->lvec, INSERT_VALUES, SCATTER_FORWARD)); 3679566063dSJacob Faibussowitsch PetscCall((*a->B->ops->multadd)(a->B, a->lvec, yy, yy)); 3683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 369d4002b98SHong Zhang } 370d4002b98SHong Zhang 371d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultDiagonalBlock_MPISELL(Mat A, Vec bb, Vec xx) 372d71ae5a4SJacob Faibussowitsch { 373d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 374d4002b98SHong Zhang 375d4002b98SHong Zhang PetscFunctionBegin; 3769566063dSJacob Faibussowitsch PetscCall(MatMultDiagonalBlock(a->A, bb, xx)); 3773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 378d4002b98SHong Zhang } 379d4002b98SHong Zhang 380d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultAdd_MPISELL(Mat A, Vec xx, Vec yy, Vec zz) 381d71ae5a4SJacob Faibussowitsch { 382d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 383d4002b98SHong Zhang 384d4002b98SHong Zhang PetscFunctionBegin; 3859566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(a->Mvctx, xx, a->lvec, INSERT_VALUES, SCATTER_FORWARD)); 3869566063dSJacob Faibussowitsch PetscCall((*a->A->ops->multadd)(a->A, xx, yy, zz)); 3879566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(a->Mvctx, xx, a->lvec, INSERT_VALUES, SCATTER_FORWARD)); 3889566063dSJacob Faibussowitsch PetscCall((*a->B->ops->multadd)(a->B, a->lvec, zz, zz)); 3893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 390d4002b98SHong Zhang } 391d4002b98SHong Zhang 392d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultTranspose_MPISELL(Mat A, Vec xx, Vec yy) 393d71ae5a4SJacob Faibussowitsch { 394d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 395d4002b98SHong Zhang 396d4002b98SHong Zhang PetscFunctionBegin; 397d4002b98SHong Zhang /* do nondiagonal part */ 3989566063dSJacob Faibussowitsch PetscCall((*a->B->ops->multtranspose)(a->B, xx, a->lvec)); 399d4002b98SHong Zhang /* do local part */ 4009566063dSJacob Faibussowitsch PetscCall((*a->A->ops->multtranspose)(a->A, xx, yy)); 401a29b4eb7SJunchao Zhang /* add partial results together */ 4029566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(a->Mvctx, a->lvec, yy, ADD_VALUES, SCATTER_REVERSE)); 4039566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(a->Mvctx, a->lvec, yy, ADD_VALUES, SCATTER_REVERSE)); 4043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 405d4002b98SHong Zhang } 406d4002b98SHong Zhang 407d71ae5a4SJacob Faibussowitsch PetscErrorCode MatIsTranspose_MPISELL(Mat Amat, Mat Bmat, PetscReal tol, PetscBool *f) 408d71ae5a4SJacob Faibussowitsch { 409d4002b98SHong Zhang MPI_Comm comm; 410d4002b98SHong Zhang Mat_MPISELL *Asell = (Mat_MPISELL *)Amat->data, *Bsell; 411d4002b98SHong Zhang Mat Adia = Asell->A, Bdia, Aoff, Boff, *Aoffs, *Boffs; 412d4002b98SHong Zhang IS Me, Notme; 413d4002b98SHong Zhang PetscInt M, N, first, last, *notme, i; 414d4002b98SHong Zhang PetscMPIInt size; 415d4002b98SHong Zhang 416d4002b98SHong Zhang PetscFunctionBegin; 417d4002b98SHong Zhang /* Easy test: symmetric diagonal block */ 4189371c9d4SSatish Balay Bsell = (Mat_MPISELL *)Bmat->data; 4199371c9d4SSatish Balay Bdia = Bsell->A; 4209566063dSJacob Faibussowitsch PetscCall(MatIsTranspose(Adia, Bdia, tol, f)); 4213ba16761SJacob Faibussowitsch if (!*f) PetscFunctionReturn(PETSC_SUCCESS); 4229566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)Amat, &comm)); 4239566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 4243ba16761SJacob Faibussowitsch if (size == 1) PetscFunctionReturn(PETSC_SUCCESS); 425d4002b98SHong Zhang 426d4002b98SHong Zhang /* Hard test: off-diagonal block. This takes a MatCreateSubMatrix. */ 4279566063dSJacob Faibussowitsch PetscCall(MatGetSize(Amat, &M, &N)); 4289566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(Amat, &first, &last)); 4299566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(N - last + first, ¬me)); 430d4002b98SHong Zhang for (i = 0; i < first; i++) notme[i] = i; 431d4002b98SHong Zhang for (i = last; i < M; i++) notme[i - last + first] = i; 4329566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(MPI_COMM_SELF, N - last + first, notme, PETSC_COPY_VALUES, &Notme)); 4339566063dSJacob Faibussowitsch PetscCall(ISCreateStride(MPI_COMM_SELF, last - first, first, 1, &Me)); 4349566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrices(Amat, 1, &Me, &Notme, MAT_INITIAL_MATRIX, &Aoffs)); 435d4002b98SHong Zhang Aoff = Aoffs[0]; 4369566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrices(Bmat, 1, &Notme, &Me, MAT_INITIAL_MATRIX, &Boffs)); 437d4002b98SHong Zhang Boff = Boffs[0]; 4389566063dSJacob Faibussowitsch PetscCall(MatIsTranspose(Aoff, Boff, tol, f)); 4399566063dSJacob Faibussowitsch PetscCall(MatDestroyMatrices(1, &Aoffs)); 4409566063dSJacob Faibussowitsch PetscCall(MatDestroyMatrices(1, &Boffs)); 4419566063dSJacob Faibussowitsch PetscCall(ISDestroy(&Me)); 4429566063dSJacob Faibussowitsch PetscCall(ISDestroy(&Notme)); 4439566063dSJacob Faibussowitsch PetscCall(PetscFree(notme)); 4443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 445d4002b98SHong Zhang } 446d4002b98SHong Zhang 447d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultTransposeAdd_MPISELL(Mat A, Vec xx, Vec yy, Vec zz) 448d71ae5a4SJacob Faibussowitsch { 449d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 450d4002b98SHong Zhang 451d4002b98SHong Zhang PetscFunctionBegin; 452d4002b98SHong Zhang /* do nondiagonal part */ 4539566063dSJacob Faibussowitsch PetscCall((*a->B->ops->multtranspose)(a->B, xx, a->lvec)); 454d4002b98SHong Zhang /* do local part */ 4559566063dSJacob Faibussowitsch PetscCall((*a->A->ops->multtransposeadd)(a->A, xx, yy, zz)); 456e4a140f6SJunchao Zhang /* add partial results together */ 4579566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(a->Mvctx, a->lvec, zz, ADD_VALUES, SCATTER_REVERSE)); 4589566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(a->Mvctx, a->lvec, zz, ADD_VALUES, SCATTER_REVERSE)); 4593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 460d4002b98SHong Zhang } 461d4002b98SHong Zhang 462d4002b98SHong Zhang /* 463d4002b98SHong Zhang This only works correctly for square matrices where the subblock A->A is the 464d4002b98SHong Zhang diagonal block 465d4002b98SHong Zhang */ 466d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetDiagonal_MPISELL(Mat A, Vec v) 467d71ae5a4SJacob Faibussowitsch { 468d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 469d4002b98SHong Zhang 470d4002b98SHong Zhang PetscFunctionBegin; 47108401ef6SPierre Jolivet PetscCheck(A->rmap->N == A->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Supports only square matrix where A->A is diag block"); 472aed4548fSBarry 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"); 4739566063dSJacob Faibussowitsch PetscCall(MatGetDiagonal(a->A, v)); 4743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 475d4002b98SHong Zhang } 476d4002b98SHong Zhang 477d71ae5a4SJacob Faibussowitsch PetscErrorCode MatScale_MPISELL(Mat A, PetscScalar aa) 478d71ae5a4SJacob Faibussowitsch { 479d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 480d4002b98SHong Zhang 481d4002b98SHong Zhang PetscFunctionBegin; 4829566063dSJacob Faibussowitsch PetscCall(MatScale(a->A, aa)); 4839566063dSJacob Faibussowitsch PetscCall(MatScale(a->B, aa)); 4843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 485d4002b98SHong Zhang } 486d4002b98SHong Zhang 487d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDestroy_MPISELL(Mat mat) 488d71ae5a4SJacob Faibussowitsch { 489d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)mat->data; 490d4002b98SHong Zhang 491d4002b98SHong Zhang PetscFunctionBegin; 492d4002b98SHong Zhang #if defined(PETSC_USE_LOG) 4933ba16761SJacob Faibussowitsch PetscCall(PetscLogObjectState((PetscObject)mat, "Rows=%" PetscInt_FMT ", Cols=%" PetscInt_FMT, mat->rmap->N, mat->cmap->N)); 494d4002b98SHong Zhang #endif 4959566063dSJacob Faibussowitsch PetscCall(MatStashDestroy_Private(&mat->stash)); 4969566063dSJacob Faibussowitsch PetscCall(VecDestroy(&sell->diag)); 4979566063dSJacob Faibussowitsch PetscCall(MatDestroy(&sell->A)); 4989566063dSJacob Faibussowitsch PetscCall(MatDestroy(&sell->B)); 499d4002b98SHong Zhang #if defined(PETSC_USE_CTABLE) 500eec179cfSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&sell->colmap)); 501d4002b98SHong Zhang #else 5029566063dSJacob Faibussowitsch PetscCall(PetscFree(sell->colmap)); 503d4002b98SHong Zhang #endif 5049566063dSJacob Faibussowitsch PetscCall(PetscFree(sell->garray)); 5059566063dSJacob Faibussowitsch PetscCall(VecDestroy(&sell->lvec)); 5069566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&sell->Mvctx)); 5079566063dSJacob Faibussowitsch PetscCall(PetscFree2(sell->rowvalues, sell->rowindices)); 5089566063dSJacob Faibussowitsch PetscCall(PetscFree(sell->ld)); 5099566063dSJacob Faibussowitsch PetscCall(PetscFree(mat->data)); 510d4002b98SHong Zhang 5119566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)mat, NULL)); 5129566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatStoreValues_C", NULL)); 5139566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatRetrieveValues_C", NULL)); 5149566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatIsTranspose_C", NULL)); 5159566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatMPISELLSetPreallocation_C", NULL)); 5169566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_mpisell_mpiaij_C", NULL)); 5179566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDiagonalScaleLocal_C", NULL)); 5183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 519d4002b98SHong Zhang } 520d4002b98SHong Zhang 521d4002b98SHong Zhang #include <petscdraw.h> 522d71ae5a4SJacob Faibussowitsch PetscErrorCode MatView_MPISELL_ASCIIorDraworSocket(Mat mat, PetscViewer viewer) 523d71ae5a4SJacob Faibussowitsch { 524d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)mat->data; 525d4002b98SHong Zhang PetscMPIInt rank = sell->rank, size = sell->size; 526d4002b98SHong Zhang PetscBool isdraw, iascii, isbinary; 527d4002b98SHong Zhang PetscViewer sviewer; 528d4002b98SHong Zhang PetscViewerFormat format; 529d4002b98SHong Zhang 530d4002b98SHong Zhang PetscFunctionBegin; 5319566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 5329566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 5339566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 534d4002b98SHong Zhang if (iascii) { 5359566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 536d4002b98SHong Zhang if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 537d4002b98SHong Zhang MatInfo info; 5386335e310SSatish Balay PetscInt *inodes; 539d4002b98SHong Zhang 5409566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)mat), &rank)); 5419566063dSJacob Faibussowitsch PetscCall(MatGetInfo(mat, MAT_LOCAL, &info)); 5429566063dSJacob Faibussowitsch PetscCall(MatInodeGetInodeSizes(sell->A, NULL, &inodes, NULL)); 5439566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 544d4002b98SHong Zhang if (!inodes) { 5459371c9d4SSatish 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, 5469371c9d4SSatish Balay (PetscInt)info.nz_allocated, (PetscInt)info.memory)); 547d4002b98SHong Zhang } else { 5489371c9d4SSatish 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, 5499371c9d4SSatish Balay (PetscInt)info.nz_allocated, (PetscInt)info.memory)); 550d4002b98SHong Zhang } 5519566063dSJacob Faibussowitsch PetscCall(MatGetInfo(sell->A, MAT_LOCAL, &info)); 5529566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] on-diagonal part: nz %" PetscInt_FMT " \n", rank, (PetscInt)info.nz_used)); 5539566063dSJacob Faibussowitsch PetscCall(MatGetInfo(sell->B, MAT_LOCAL, &info)); 5549566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] off-diagonal part: nz %" PetscInt_FMT " \n", rank, (PetscInt)info.nz_used)); 5559566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 5569566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 5579566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Information on VecScatter used in matrix-vector product: \n")); 5589566063dSJacob Faibussowitsch PetscCall(VecScatterView(sell->Mvctx, viewer)); 5593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 560d4002b98SHong Zhang } else if (format == PETSC_VIEWER_ASCII_INFO) { 561d4002b98SHong Zhang PetscInt inodecount, inodelimit, *inodes; 5629566063dSJacob Faibussowitsch PetscCall(MatInodeGetInodeSizes(sell->A, &inodecount, &inodes, &inodelimit)); 563d4002b98SHong Zhang if (inodes) { 5649566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "using I-node (on process 0) routines: found %" PetscInt_FMT " nodes, limit used is %" PetscInt_FMT "\n", inodecount, inodelimit)); 565d4002b98SHong Zhang } else { 5669566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "not using I-node (on process 0) routines\n")); 567d4002b98SHong Zhang } 5683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 569d4002b98SHong Zhang } else if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) { 5703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 571d4002b98SHong Zhang } 572d4002b98SHong Zhang } else if (isbinary) { 573d4002b98SHong Zhang if (size == 1) { 5749566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)sell->A, ((PetscObject)mat)->name)); 5759566063dSJacob Faibussowitsch PetscCall(MatView(sell->A, viewer)); 576d4002b98SHong Zhang } else { 5779566063dSJacob Faibussowitsch /* PetscCall(MatView_MPISELL_Binary(mat,viewer)); */ 578d4002b98SHong Zhang } 5793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 580d4002b98SHong Zhang } else if (isdraw) { 581d4002b98SHong Zhang PetscDraw draw; 582d4002b98SHong Zhang PetscBool isnull; 5839566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 5849566063dSJacob Faibussowitsch PetscCall(PetscDrawIsNull(draw, &isnull)); 5853ba16761SJacob Faibussowitsch if (isnull) PetscFunctionReturn(PETSC_SUCCESS); 586d4002b98SHong Zhang } 587d4002b98SHong Zhang 588d4002b98SHong Zhang { 589d4002b98SHong Zhang /* assemble the entire matrix onto first processor. */ 590d4002b98SHong Zhang Mat A; 591d4002b98SHong Zhang Mat_SeqSELL *Aloc; 592d4002b98SHong Zhang PetscInt M = mat->rmap->N, N = mat->cmap->N, *acolidx, row, col, i, j; 593d4002b98SHong Zhang MatScalar *aval; 594d4002b98SHong Zhang PetscBool isnonzero; 595d4002b98SHong Zhang 5969566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &A)); 597dd400576SPatrick Sanan if (rank == 0) { 5989566063dSJacob Faibussowitsch PetscCall(MatSetSizes(A, M, N, M, N)); 599d4002b98SHong Zhang } else { 6009566063dSJacob Faibussowitsch PetscCall(MatSetSizes(A, 0, 0, M, N)); 601d4002b98SHong Zhang } 602d4002b98SHong Zhang /* This is just a temporary matrix, so explicitly using MATMPISELL is probably best */ 6039566063dSJacob Faibussowitsch PetscCall(MatSetType(A, MATMPISELL)); 6049566063dSJacob Faibussowitsch PetscCall(MatMPISELLSetPreallocation(A, 0, NULL, 0, NULL)); 6059566063dSJacob Faibussowitsch PetscCall(MatSetOption(A, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_FALSE)); 606d4002b98SHong Zhang 607d4002b98SHong Zhang /* copy over the A part */ 608d4002b98SHong Zhang Aloc = (Mat_SeqSELL *)sell->A->data; 6099371c9d4SSatish Balay acolidx = Aloc->colidx; 6109371c9d4SSatish Balay aval = Aloc->val; 611d4002b98SHong Zhang for (i = 0; i < Aloc->totalslices; i++) { /* loop over slices */ 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) { /* check the mask bit */ 615d4002b98SHong Zhang row = (i << 3) + (j & 0x07) + mat->rmap->rstart; /* i<<3 is the starting row of this slice */ 616d4002b98SHong Zhang col = *acolidx + mat->rmap->rstart; 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 624d4002b98SHong Zhang /* copy over the B part */ 625d4002b98SHong Zhang Aloc = (Mat_SeqSELL *)sell->B->data; 6269371c9d4SSatish Balay acolidx = Aloc->colidx; 6279371c9d4SSatish Balay aval = Aloc->val; 628d4002b98SHong Zhang for (i = 0; i < Aloc->totalslices; i++) { 629d4002b98SHong Zhang for (j = Aloc->sliidx[i]; j < Aloc->sliidx[i + 1]; j++) { 630d4002b98SHong Zhang isnonzero = (PetscBool)((j - Aloc->sliidx[i]) / 8 < Aloc->rlen[(i << 3) + (j & 0x07)]); 631d4002b98SHong Zhang if (isnonzero) { 632d4002b98SHong Zhang row = (i << 3) + (j & 0x07) + mat->rmap->rstart; 633d4002b98SHong Zhang col = sell->garray[*acolidx]; 6349566063dSJacob Faibussowitsch PetscCall(MatSetValues(A, 1, &row, 1, &col, aval, INSERT_VALUES)); 635d4002b98SHong Zhang } 6369371c9d4SSatish Balay aval++; 6379371c9d4SSatish Balay acolidx++; 638d4002b98SHong Zhang } 639d4002b98SHong Zhang } 640d4002b98SHong Zhang 6419566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 6429566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 643d4002b98SHong Zhang /* 644d4002b98SHong Zhang Everyone has to call to draw the matrix since the graphics waits are 645d4002b98SHong Zhang synchronized across all processors that share the PetscDraw object 646d4002b98SHong Zhang */ 6479566063dSJacob Faibussowitsch PetscCall(PetscViewerGetSubViewer(viewer, PETSC_COMM_SELF, &sviewer)); 648dd400576SPatrick Sanan if (rank == 0) { 6499566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)((Mat_MPISELL *)(A->data))->A, ((PetscObject)mat)->name)); 6509566063dSJacob Faibussowitsch PetscCall(MatView_SeqSELL(((Mat_MPISELL *)(A->data))->A, sviewer)); 651d4002b98SHong Zhang } 6529566063dSJacob Faibussowitsch PetscCall(PetscViewerRestoreSubViewer(viewer, PETSC_COMM_SELF, &sviewer)); 6539566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 6549566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A)); 655d4002b98SHong Zhang } 6563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 657d4002b98SHong Zhang } 658d4002b98SHong Zhang 659d71ae5a4SJacob Faibussowitsch PetscErrorCode MatView_MPISELL(Mat mat, PetscViewer viewer) 660d71ae5a4SJacob Faibussowitsch { 661d4002b98SHong Zhang PetscBool iascii, isdraw, issocket, isbinary; 662d4002b98SHong Zhang 663d4002b98SHong Zhang PetscFunctionBegin; 6649566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 6659566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 6669566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 6679566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSOCKET, &issocket)); 66848a46eb9SPierre Jolivet if (iascii || isdraw || isbinary || issocket) PetscCall(MatView_MPISELL_ASCIIorDraworSocket(mat, viewer)); 6693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 670d4002b98SHong Zhang } 671d4002b98SHong Zhang 672d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetGhosts_MPISELL(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[]) 673d71ae5a4SJacob Faibussowitsch { 674d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)mat->data; 675d4002b98SHong Zhang 676d4002b98SHong Zhang PetscFunctionBegin; 6779566063dSJacob Faibussowitsch PetscCall(MatGetSize(sell->B, NULL, nghosts)); 678d4002b98SHong Zhang if (ghosts) *ghosts = sell->garray; 6793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 680d4002b98SHong Zhang } 681d4002b98SHong Zhang 682d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetInfo_MPISELL(Mat matin, MatInfoType flag, MatInfo *info) 683d71ae5a4SJacob Faibussowitsch { 684d4002b98SHong Zhang Mat_MPISELL *mat = (Mat_MPISELL *)matin->data; 685d4002b98SHong Zhang Mat A = mat->A, B = mat->B; 6863966268fSBarry Smith PetscLogDouble isend[5], irecv[5]; 687d4002b98SHong Zhang 688d4002b98SHong Zhang PetscFunctionBegin; 689d4002b98SHong Zhang info->block_size = 1.0; 6909566063dSJacob Faibussowitsch PetscCall(MatGetInfo(A, MAT_LOCAL, info)); 691d4002b98SHong Zhang 6929371c9d4SSatish Balay isend[0] = info->nz_used; 6939371c9d4SSatish Balay isend[1] = info->nz_allocated; 6949371c9d4SSatish Balay isend[2] = info->nz_unneeded; 6959371c9d4SSatish Balay isend[3] = info->memory; 6969371c9d4SSatish Balay isend[4] = info->mallocs; 697d4002b98SHong Zhang 6989566063dSJacob Faibussowitsch PetscCall(MatGetInfo(B, MAT_LOCAL, info)); 699d4002b98SHong Zhang 7009371c9d4SSatish Balay isend[0] += info->nz_used; 7019371c9d4SSatish Balay isend[1] += info->nz_allocated; 7029371c9d4SSatish Balay isend[2] += info->nz_unneeded; 7039371c9d4SSatish Balay isend[3] += info->memory; 7049371c9d4SSatish Balay isend[4] += info->mallocs; 705d4002b98SHong Zhang if (flag == MAT_LOCAL) { 706d4002b98SHong Zhang info->nz_used = isend[0]; 707d4002b98SHong Zhang info->nz_allocated = isend[1]; 708d4002b98SHong Zhang info->nz_unneeded = isend[2]; 709d4002b98SHong Zhang info->memory = isend[3]; 710d4002b98SHong Zhang info->mallocs = isend[4]; 711d4002b98SHong Zhang } else if (flag == MAT_GLOBAL_MAX) { 7121c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(isend, irecv, 5, MPIU_PETSCLOGDOUBLE, MPI_MAX, PetscObjectComm((PetscObject)matin))); 713d4002b98SHong Zhang 714d4002b98SHong Zhang info->nz_used = irecv[0]; 715d4002b98SHong Zhang info->nz_allocated = irecv[1]; 716d4002b98SHong Zhang info->nz_unneeded = irecv[2]; 717d4002b98SHong Zhang info->memory = irecv[3]; 718d4002b98SHong Zhang info->mallocs = irecv[4]; 719d4002b98SHong Zhang } else if (flag == MAT_GLOBAL_SUM) { 7201c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(isend, irecv, 5, MPIU_PETSCLOGDOUBLE, MPI_SUM, PetscObjectComm((PetscObject)matin))); 721d4002b98SHong Zhang 722d4002b98SHong Zhang info->nz_used = irecv[0]; 723d4002b98SHong Zhang info->nz_allocated = irecv[1]; 724d4002b98SHong Zhang info->nz_unneeded = irecv[2]; 725d4002b98SHong Zhang info->memory = irecv[3]; 726d4002b98SHong Zhang info->mallocs = irecv[4]; 727d4002b98SHong Zhang } 728d4002b98SHong Zhang info->fill_ratio_given = 0; /* no parallel LU/ILU/Cholesky */ 729d4002b98SHong Zhang info->fill_ratio_needed = 0; 730d4002b98SHong Zhang info->factor_mallocs = 0; 7313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 732d4002b98SHong Zhang } 733d4002b98SHong Zhang 734d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetOption_MPISELL(Mat A, MatOption op, PetscBool flg) 735d71ae5a4SJacob Faibussowitsch { 736d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 737d4002b98SHong Zhang 738d4002b98SHong Zhang PetscFunctionBegin; 739d4002b98SHong Zhang switch (op) { 740d4002b98SHong Zhang case MAT_NEW_NONZERO_LOCATIONS: 741d4002b98SHong Zhang case MAT_NEW_NONZERO_ALLOCATION_ERR: 742d4002b98SHong Zhang case MAT_UNUSED_NONZERO_LOCATION_ERR: 743d4002b98SHong Zhang case MAT_KEEP_NONZERO_PATTERN: 744d4002b98SHong Zhang case MAT_NEW_NONZERO_LOCATION_ERR: 745d4002b98SHong Zhang case MAT_USE_INODES: 746d4002b98SHong Zhang case MAT_IGNORE_ZERO_ENTRIES: 747d4002b98SHong Zhang MatCheckPreallocated(A, 1); 7489566063dSJacob Faibussowitsch PetscCall(MatSetOption(a->A, op, flg)); 7499566063dSJacob Faibussowitsch PetscCall(MatSetOption(a->B, op, flg)); 750d4002b98SHong Zhang break; 751d4002b98SHong Zhang case MAT_ROW_ORIENTED: 752d4002b98SHong Zhang MatCheckPreallocated(A, 1); 753d4002b98SHong Zhang a->roworiented = flg; 754d4002b98SHong Zhang 7559566063dSJacob Faibussowitsch PetscCall(MatSetOption(a->A, op, flg)); 7569566063dSJacob Faibussowitsch PetscCall(MatSetOption(a->B, op, flg)); 757d4002b98SHong Zhang break; 7588c78258cSHong Zhang case MAT_FORCE_DIAGONAL_ENTRIES: 759d71ae5a4SJacob Faibussowitsch case MAT_SORTED_FULL: 760d71ae5a4SJacob Faibussowitsch PetscCall(PetscInfo(A, "Option %s ignored\n", MatOptions[op])); 761d71ae5a4SJacob Faibussowitsch break; 762d71ae5a4SJacob Faibussowitsch case MAT_IGNORE_OFF_PROC_ENTRIES: 763d71ae5a4SJacob Faibussowitsch a->donotstash = flg; 764d71ae5a4SJacob Faibussowitsch break; 765d4002b98SHong Zhang case MAT_SPD: 766d71ae5a4SJacob Faibussowitsch case MAT_SPD_ETERNAL: 767d71ae5a4SJacob Faibussowitsch break; 768d4002b98SHong Zhang case MAT_SYMMETRIC: 769d4002b98SHong Zhang MatCheckPreallocated(A, 1); 7709566063dSJacob Faibussowitsch PetscCall(MatSetOption(a->A, op, flg)); 771d4002b98SHong Zhang break; 772d4002b98SHong Zhang case MAT_STRUCTURALLY_SYMMETRIC: 773d4002b98SHong Zhang MatCheckPreallocated(A, 1); 7749566063dSJacob Faibussowitsch PetscCall(MatSetOption(a->A, op, flg)); 775d4002b98SHong Zhang break; 776d4002b98SHong Zhang case MAT_HERMITIAN: 777d4002b98SHong Zhang MatCheckPreallocated(A, 1); 7789566063dSJacob Faibussowitsch PetscCall(MatSetOption(a->A, op, flg)); 779d4002b98SHong Zhang break; 780d4002b98SHong Zhang case MAT_SYMMETRY_ETERNAL: 781d4002b98SHong Zhang MatCheckPreallocated(A, 1); 7829566063dSJacob Faibussowitsch PetscCall(MatSetOption(a->A, op, flg)); 783d4002b98SHong Zhang break; 784b94d7dedSBarry Smith case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 785b94d7dedSBarry Smith MatCheckPreallocated(A, 1); 786b94d7dedSBarry Smith PetscCall(MatSetOption(a->A, op, flg)); 787b94d7dedSBarry Smith break; 788d71ae5a4SJacob Faibussowitsch default: 789d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "unknown option %d", op); 790d4002b98SHong Zhang } 7913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 792d4002b98SHong Zhang } 793d4002b98SHong Zhang 794d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDiagonalScale_MPISELL(Mat mat, Vec ll, Vec rr) 795d71ae5a4SJacob Faibussowitsch { 796d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)mat->data; 797d4002b98SHong Zhang Mat a = sell->A, b = sell->B; 798d4002b98SHong Zhang PetscInt s1, s2, s3; 799d4002b98SHong Zhang 800d4002b98SHong Zhang PetscFunctionBegin; 8019566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(mat, &s2, &s3)); 802d4002b98SHong Zhang if (rr) { 8039566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(rr, &s1)); 80408401ef6SPierre Jolivet PetscCheck(s1 == s3, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "right vector non-conforming local size"); 805d4002b98SHong Zhang /* Overlap communication with computation. */ 8069566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(sell->Mvctx, rr, sell->lvec, INSERT_VALUES, SCATTER_FORWARD)); 807d4002b98SHong Zhang } 808d4002b98SHong Zhang if (ll) { 8099566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(ll, &s1)); 81008401ef6SPierre Jolivet PetscCheck(s1 == s2, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "left vector non-conforming local size"); 811dbbe0bcdSBarry Smith PetscUseTypeMethod(b, diagonalscale, ll, NULL); 812d4002b98SHong Zhang } 813d4002b98SHong Zhang /* scale the diagonal block */ 814dbbe0bcdSBarry Smith PetscUseTypeMethod(a, diagonalscale, ll, rr); 815d4002b98SHong Zhang 816d4002b98SHong Zhang if (rr) { 817d4002b98SHong Zhang /* Do a scatter end and then right scale the off-diagonal block */ 8189566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(sell->Mvctx, rr, sell->lvec, INSERT_VALUES, SCATTER_FORWARD)); 819dbbe0bcdSBarry Smith PetscUseTypeMethod(b, diagonalscale, NULL, sell->lvec); 820d4002b98SHong Zhang } 8213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 822d4002b98SHong Zhang } 823d4002b98SHong Zhang 824d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetUnfactored_MPISELL(Mat A) 825d71ae5a4SJacob Faibussowitsch { 826d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 827d4002b98SHong Zhang 828d4002b98SHong Zhang PetscFunctionBegin; 8299566063dSJacob Faibussowitsch PetscCall(MatSetUnfactored(a->A)); 8303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 831d4002b98SHong Zhang } 832d4002b98SHong Zhang 833d71ae5a4SJacob Faibussowitsch PetscErrorCode MatEqual_MPISELL(Mat A, Mat B, PetscBool *flag) 834d71ae5a4SJacob Faibussowitsch { 835d4002b98SHong Zhang Mat_MPISELL *matB = (Mat_MPISELL *)B->data, *matA = (Mat_MPISELL *)A->data; 836d4002b98SHong Zhang Mat a, b, c, d; 837d4002b98SHong Zhang PetscBool flg; 838d4002b98SHong Zhang 839d4002b98SHong Zhang PetscFunctionBegin; 8409371c9d4SSatish Balay a = matA->A; 8419371c9d4SSatish Balay b = matA->B; 8429371c9d4SSatish Balay c = matB->A; 8439371c9d4SSatish Balay d = matB->B; 844d4002b98SHong Zhang 8459566063dSJacob Faibussowitsch PetscCall(MatEqual(a, c, &flg)); 84648a46eb9SPierre Jolivet if (flg) PetscCall(MatEqual(b, d, &flg)); 8471c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&flg, flag, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)A))); 8483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 849d4002b98SHong Zhang } 850d4002b98SHong Zhang 851d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCopy_MPISELL(Mat A, Mat B, MatStructure str) 852d71ae5a4SJacob Faibussowitsch { 853d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 854d4002b98SHong Zhang Mat_MPISELL *b = (Mat_MPISELL *)B->data; 855d4002b98SHong Zhang 856d4002b98SHong Zhang PetscFunctionBegin; 857d4002b98SHong Zhang /* If the two matrices don't have the same copy implementation, they aren't compatible for fast copy. */ 858d4002b98SHong Zhang if ((str != SAME_NONZERO_PATTERN) || (A->ops->copy != B->ops->copy)) { 859d4002b98SHong Zhang /* because of the column compression in the off-processor part of the matrix a->B, 860d4002b98SHong Zhang the number of columns in a->B and b->B may be different, hence we cannot call 861d4002b98SHong Zhang the MatCopy() directly on the two parts. If need be, we can provide a more 862d4002b98SHong Zhang efficient copy than the MatCopy_Basic() by first uncompressing the a->B matrices 863d4002b98SHong Zhang then copying the submatrices */ 8649566063dSJacob Faibussowitsch PetscCall(MatCopy_Basic(A, B, str)); 865d4002b98SHong Zhang } else { 8669566063dSJacob Faibussowitsch PetscCall(MatCopy(a->A, b->A, str)); 8679566063dSJacob Faibussowitsch PetscCall(MatCopy(a->B, b->B, str)); 868d4002b98SHong Zhang } 8693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 870d4002b98SHong Zhang } 871d4002b98SHong Zhang 872d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetUp_MPISELL(Mat A) 873d71ae5a4SJacob Faibussowitsch { 874d4002b98SHong Zhang PetscFunctionBegin; 8759566063dSJacob Faibussowitsch PetscCall(MatMPISELLSetPreallocation(A, PETSC_DEFAULT, NULL, PETSC_DEFAULT, NULL)); 8763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 877d4002b98SHong Zhang } 878d4002b98SHong Zhang 879d4002b98SHong Zhang extern PetscErrorCode MatConjugate_SeqSELL(Mat); 880d4002b98SHong Zhang 881d71ae5a4SJacob Faibussowitsch PetscErrorCode MatConjugate_MPISELL(Mat mat) 882d71ae5a4SJacob Faibussowitsch { 8835f80ce2aSJacob Faibussowitsch PetscFunctionBegin; 8845f80ce2aSJacob Faibussowitsch if (PetscDefined(USE_COMPLEX)) { 885d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)mat->data; 886d4002b98SHong Zhang 8879566063dSJacob Faibussowitsch PetscCall(MatConjugate_SeqSELL(sell->A)); 8889566063dSJacob Faibussowitsch PetscCall(MatConjugate_SeqSELL(sell->B)); 8895f80ce2aSJacob Faibussowitsch } 8903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 891d4002b98SHong Zhang } 892d4002b98SHong Zhang 893d71ae5a4SJacob Faibussowitsch PetscErrorCode MatRealPart_MPISELL(Mat A) 894d71ae5a4SJacob Faibussowitsch { 895d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 896d4002b98SHong Zhang 897d4002b98SHong Zhang PetscFunctionBegin; 8989566063dSJacob Faibussowitsch PetscCall(MatRealPart(a->A)); 8999566063dSJacob Faibussowitsch PetscCall(MatRealPart(a->B)); 9003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 901d4002b98SHong Zhang } 902d4002b98SHong Zhang 903d71ae5a4SJacob Faibussowitsch PetscErrorCode MatImaginaryPart_MPISELL(Mat A) 904d71ae5a4SJacob Faibussowitsch { 905d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 906d4002b98SHong Zhang 907d4002b98SHong Zhang PetscFunctionBegin; 9089566063dSJacob Faibussowitsch PetscCall(MatImaginaryPart(a->A)); 9099566063dSJacob Faibussowitsch PetscCall(MatImaginaryPart(a->B)); 9103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 911d4002b98SHong Zhang } 912d4002b98SHong Zhang 913d71ae5a4SJacob Faibussowitsch PetscErrorCode MatInvertBlockDiagonal_MPISELL(Mat A, const PetscScalar **values) 914d71ae5a4SJacob Faibussowitsch { 915d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 916d4002b98SHong Zhang 917d4002b98SHong Zhang PetscFunctionBegin; 9189566063dSJacob Faibussowitsch PetscCall(MatInvertBlockDiagonal(a->A, values)); 919d4002b98SHong Zhang A->factorerrortype = a->A->factorerrortype; 9203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 921d4002b98SHong Zhang } 922d4002b98SHong Zhang 923d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetRandom_MPISELL(Mat x, PetscRandom rctx) 924d71ae5a4SJacob Faibussowitsch { 925d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)x->data; 926d4002b98SHong Zhang 927d4002b98SHong Zhang PetscFunctionBegin; 9289566063dSJacob Faibussowitsch PetscCall(MatSetRandom(sell->A, rctx)); 9299566063dSJacob Faibussowitsch PetscCall(MatSetRandom(sell->B, rctx)); 9309566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 9319566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 9323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 933d4002b98SHong Zhang } 934d4002b98SHong Zhang 935d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetFromOptions_MPISELL(Mat A, PetscOptionItems *PetscOptionsObject) 936d71ae5a4SJacob Faibussowitsch { 937d4002b98SHong Zhang PetscFunctionBegin; 938d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "MPISELL options"); 939d0609cedSBarry Smith PetscOptionsHeadEnd(); 9403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 941d4002b98SHong Zhang } 942d4002b98SHong Zhang 943d71ae5a4SJacob Faibussowitsch PetscErrorCode MatShift_MPISELL(Mat Y, PetscScalar a) 944d71ae5a4SJacob Faibussowitsch { 945d4002b98SHong Zhang Mat_MPISELL *msell = (Mat_MPISELL *)Y->data; 946d4002b98SHong Zhang Mat_SeqSELL *sell = (Mat_SeqSELL *)msell->A->data; 947d4002b98SHong Zhang 948d4002b98SHong Zhang PetscFunctionBegin; 949d4002b98SHong Zhang if (!Y->preallocated) { 9509566063dSJacob Faibussowitsch PetscCall(MatMPISELLSetPreallocation(Y, 1, NULL, 0, NULL)); 951d4002b98SHong Zhang } else if (!sell->nz) { 952d4002b98SHong Zhang PetscInt nonew = sell->nonew; 9539566063dSJacob Faibussowitsch PetscCall(MatSeqSELLSetPreallocation(msell->A, 1, NULL)); 954d4002b98SHong Zhang sell->nonew = nonew; 955d4002b98SHong Zhang } 9569566063dSJacob Faibussowitsch PetscCall(MatShift_Basic(Y, a)); 9573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 958d4002b98SHong Zhang } 959d4002b98SHong Zhang 960d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMissingDiagonal_MPISELL(Mat A, PetscBool *missing, PetscInt *d) 961d71ae5a4SJacob Faibussowitsch { 962d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 963d4002b98SHong Zhang 964d4002b98SHong Zhang PetscFunctionBegin; 96508401ef6SPierre Jolivet PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only works for square matrices"); 9669566063dSJacob Faibussowitsch PetscCall(MatMissingDiagonal(a->A, missing, d)); 967d4002b98SHong Zhang if (d) { 968d4002b98SHong Zhang PetscInt rstart; 9699566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A, &rstart, NULL)); 970d4002b98SHong Zhang *d += rstart; 971d4002b98SHong Zhang } 9723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 973d4002b98SHong Zhang } 974d4002b98SHong Zhang 975d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetDiagonalBlock_MPISELL(Mat A, Mat *a) 976d71ae5a4SJacob Faibussowitsch { 977d4002b98SHong Zhang PetscFunctionBegin; 978d4002b98SHong Zhang *a = ((Mat_MPISELL *)A->data)->A; 9793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 980d4002b98SHong Zhang } 981d4002b98SHong Zhang 982d4002b98SHong Zhang static struct _MatOps MatOps_Values = {MatSetValues_MPISELL, 983f4259b30SLisandro Dalcin NULL, 984f4259b30SLisandro Dalcin NULL, 985d4002b98SHong Zhang MatMult_MPISELL, 986d4002b98SHong Zhang /* 4*/ MatMultAdd_MPISELL, 987d4002b98SHong Zhang MatMultTranspose_MPISELL, 988d4002b98SHong Zhang MatMultTransposeAdd_MPISELL, 989f4259b30SLisandro Dalcin NULL, 990f4259b30SLisandro Dalcin NULL, 991f4259b30SLisandro Dalcin NULL, 992f4259b30SLisandro Dalcin /*10*/ NULL, 993f4259b30SLisandro Dalcin NULL, 994f4259b30SLisandro Dalcin NULL, 995d4002b98SHong Zhang MatSOR_MPISELL, 996f4259b30SLisandro Dalcin NULL, 997d4002b98SHong Zhang /*15*/ MatGetInfo_MPISELL, 998d4002b98SHong Zhang MatEqual_MPISELL, 999d4002b98SHong Zhang MatGetDiagonal_MPISELL, 1000d4002b98SHong Zhang MatDiagonalScale_MPISELL, 1001f4259b30SLisandro Dalcin NULL, 1002d4002b98SHong Zhang /*20*/ MatAssemblyBegin_MPISELL, 1003d4002b98SHong Zhang MatAssemblyEnd_MPISELL, 1004d4002b98SHong Zhang MatSetOption_MPISELL, 1005d4002b98SHong Zhang MatZeroEntries_MPISELL, 1006f4259b30SLisandro Dalcin /*24*/ NULL, 1007f4259b30SLisandro Dalcin NULL, 1008f4259b30SLisandro Dalcin NULL, 1009f4259b30SLisandro Dalcin NULL, 1010f4259b30SLisandro Dalcin NULL, 1011d4002b98SHong Zhang /*29*/ MatSetUp_MPISELL, 1012f4259b30SLisandro Dalcin NULL, 1013f4259b30SLisandro Dalcin NULL, 1014d4002b98SHong Zhang MatGetDiagonalBlock_MPISELL, 1015f4259b30SLisandro Dalcin NULL, 1016d4002b98SHong Zhang /*34*/ MatDuplicate_MPISELL, 1017f4259b30SLisandro Dalcin NULL, 1018f4259b30SLisandro Dalcin NULL, 1019f4259b30SLisandro Dalcin NULL, 1020f4259b30SLisandro Dalcin NULL, 1021f4259b30SLisandro Dalcin /*39*/ NULL, 1022f4259b30SLisandro Dalcin NULL, 1023f4259b30SLisandro Dalcin NULL, 1024d4002b98SHong Zhang MatGetValues_MPISELL, 1025d4002b98SHong Zhang MatCopy_MPISELL, 1026f4259b30SLisandro Dalcin /*44*/ NULL, 1027d4002b98SHong Zhang MatScale_MPISELL, 1028d4002b98SHong Zhang MatShift_MPISELL, 1029d4002b98SHong Zhang MatDiagonalSet_MPISELL, 1030f4259b30SLisandro Dalcin NULL, 1031d4002b98SHong Zhang /*49*/ MatSetRandom_MPISELL, 1032f4259b30SLisandro Dalcin NULL, 1033f4259b30SLisandro Dalcin NULL, 1034f4259b30SLisandro Dalcin NULL, 1035f4259b30SLisandro Dalcin NULL, 1036d4002b98SHong Zhang /*54*/ MatFDColoringCreate_MPIXAIJ, 1037f4259b30SLisandro Dalcin NULL, 1038d4002b98SHong Zhang MatSetUnfactored_MPISELL, 1039f4259b30SLisandro Dalcin NULL, 1040f4259b30SLisandro Dalcin NULL, 1041f4259b30SLisandro Dalcin /*59*/ NULL, 1042d4002b98SHong Zhang MatDestroy_MPISELL, 1043d4002b98SHong Zhang MatView_MPISELL, 1044f4259b30SLisandro Dalcin NULL, 1045f4259b30SLisandro Dalcin NULL, 1046f4259b30SLisandro Dalcin /*64*/ NULL, 1047f4259b30SLisandro Dalcin NULL, 1048f4259b30SLisandro Dalcin NULL, 1049f4259b30SLisandro Dalcin NULL, 1050f4259b30SLisandro Dalcin NULL, 1051f4259b30SLisandro Dalcin /*69*/ NULL, 1052f4259b30SLisandro Dalcin NULL, 1053f4259b30SLisandro Dalcin NULL, 1054f4259b30SLisandro Dalcin NULL, 1055f4259b30SLisandro Dalcin NULL, 1056f4259b30SLisandro Dalcin NULL, 1057d4002b98SHong Zhang /*75*/ MatFDColoringApply_AIJ, /* reuse AIJ function */ 1058d4002b98SHong Zhang MatSetFromOptions_MPISELL, 1059f4259b30SLisandro Dalcin NULL, 1060f4259b30SLisandro Dalcin NULL, 1061f4259b30SLisandro Dalcin NULL, 1062f4259b30SLisandro Dalcin /*80*/ NULL, 1063f4259b30SLisandro Dalcin NULL, 1064f4259b30SLisandro Dalcin NULL, 1065f4259b30SLisandro Dalcin /*83*/ NULL, 1066f4259b30SLisandro Dalcin NULL, 1067f4259b30SLisandro Dalcin NULL, 1068f4259b30SLisandro Dalcin NULL, 1069f4259b30SLisandro Dalcin NULL, 1070f4259b30SLisandro Dalcin NULL, 1071f4259b30SLisandro Dalcin /*89*/ NULL, 1072f4259b30SLisandro Dalcin NULL, 1073f4259b30SLisandro Dalcin NULL, 1074f4259b30SLisandro Dalcin NULL, 1075f4259b30SLisandro Dalcin NULL, 1076f4259b30SLisandro Dalcin /*94*/ NULL, 1077f4259b30SLisandro Dalcin NULL, 1078f4259b30SLisandro Dalcin NULL, 1079f4259b30SLisandro Dalcin NULL, 1080f4259b30SLisandro Dalcin NULL, 1081f4259b30SLisandro Dalcin /*99*/ NULL, 1082f4259b30SLisandro Dalcin NULL, 1083f4259b30SLisandro Dalcin NULL, 1084d4002b98SHong Zhang MatConjugate_MPISELL, 1085f4259b30SLisandro Dalcin NULL, 1086f4259b30SLisandro Dalcin /*104*/ NULL, 1087d4002b98SHong Zhang MatRealPart_MPISELL, 1088d4002b98SHong Zhang MatImaginaryPart_MPISELL, 1089f4259b30SLisandro Dalcin NULL, 1090f4259b30SLisandro Dalcin NULL, 1091f4259b30SLisandro Dalcin /*109*/ NULL, 1092f4259b30SLisandro Dalcin NULL, 1093f4259b30SLisandro Dalcin NULL, 1094f4259b30SLisandro Dalcin NULL, 1095d4002b98SHong Zhang MatMissingDiagonal_MPISELL, 1096f4259b30SLisandro Dalcin /*114*/ NULL, 1097f4259b30SLisandro Dalcin NULL, 1098d4002b98SHong Zhang MatGetGhosts_MPISELL, 1099f4259b30SLisandro Dalcin NULL, 1100f4259b30SLisandro Dalcin NULL, 1101f4259b30SLisandro Dalcin /*119*/ NULL, 1102f4259b30SLisandro Dalcin NULL, 1103f4259b30SLisandro Dalcin NULL, 1104f4259b30SLisandro Dalcin NULL, 1105f4259b30SLisandro Dalcin NULL, 1106f4259b30SLisandro Dalcin /*124*/ NULL, 1107f4259b30SLisandro Dalcin NULL, 1108d4002b98SHong Zhang MatInvertBlockDiagonal_MPISELL, 1109f4259b30SLisandro Dalcin NULL, 1110f4259b30SLisandro Dalcin NULL, 1111f4259b30SLisandro Dalcin /*129*/ NULL, 1112f4259b30SLisandro Dalcin NULL, 1113f4259b30SLisandro Dalcin NULL, 1114f4259b30SLisandro Dalcin NULL, 1115f4259b30SLisandro Dalcin NULL, 1116f4259b30SLisandro Dalcin /*134*/ NULL, 1117f4259b30SLisandro Dalcin NULL, 1118f4259b30SLisandro Dalcin NULL, 1119f4259b30SLisandro Dalcin NULL, 1120f4259b30SLisandro Dalcin NULL, 1121f4259b30SLisandro Dalcin /*139*/ NULL, 1122f4259b30SLisandro Dalcin NULL, 1123f4259b30SLisandro Dalcin NULL, 1124d4002b98SHong Zhang MatFDColoringSetUp_MPIXAIJ, 1125f4259b30SLisandro Dalcin NULL, 1126d70f29a3SPierre Jolivet /*144*/ NULL, 1127d70f29a3SPierre Jolivet NULL, 1128d70f29a3SPierre Jolivet NULL, 112999a7f59eSMark Adams NULL, 113099a7f59eSMark Adams NULL, 11317fb60732SBarry Smith NULL, 1132dec0b466SHong Zhang /*150*/ NULL, 1133dec0b466SHong Zhang NULL}; 1134d4002b98SHong Zhang 1135d71ae5a4SJacob Faibussowitsch PetscErrorCode MatStoreValues_MPISELL(Mat mat) 1136d71ae5a4SJacob Faibussowitsch { 1137d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)mat->data; 1138d4002b98SHong Zhang 1139d4002b98SHong Zhang PetscFunctionBegin; 11409566063dSJacob Faibussowitsch PetscCall(MatStoreValues(sell->A)); 11419566063dSJacob Faibussowitsch PetscCall(MatStoreValues(sell->B)); 11423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1143d4002b98SHong Zhang } 1144d4002b98SHong Zhang 1145d71ae5a4SJacob Faibussowitsch PetscErrorCode MatRetrieveValues_MPISELL(Mat mat) 1146d71ae5a4SJacob Faibussowitsch { 1147d4002b98SHong Zhang Mat_MPISELL *sell = (Mat_MPISELL *)mat->data; 1148d4002b98SHong Zhang 1149d4002b98SHong Zhang PetscFunctionBegin; 11509566063dSJacob Faibussowitsch PetscCall(MatRetrieveValues(sell->A)); 11519566063dSJacob Faibussowitsch PetscCall(MatRetrieveValues(sell->B)); 11523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1153d4002b98SHong Zhang } 1154d4002b98SHong Zhang 1155d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMPISELLSetPreallocation_MPISELL(Mat B, PetscInt d_rlenmax, const PetscInt d_rlen[], PetscInt o_rlenmax, const PetscInt o_rlen[]) 1156d71ae5a4SJacob Faibussowitsch { 1157d4002b98SHong Zhang Mat_MPISELL *b; 1158d4002b98SHong Zhang 1159d4002b98SHong Zhang PetscFunctionBegin; 11609566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->rmap)); 11619566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->cmap)); 1162d4002b98SHong Zhang b = (Mat_MPISELL *)B->data; 1163d4002b98SHong Zhang 1164d4002b98SHong Zhang if (!B->preallocated) { 1165d4002b98SHong Zhang /* Explicitly create 2 MATSEQSELL matrices. */ 11669566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &b->A)); 11679566063dSJacob Faibussowitsch PetscCall(MatSetSizes(b->A, B->rmap->n, B->cmap->n, B->rmap->n, B->cmap->n)); 11689566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(b->A, B, B)); 11699566063dSJacob Faibussowitsch PetscCall(MatSetType(b->A, MATSEQSELL)); 11709566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &b->B)); 11719566063dSJacob Faibussowitsch PetscCall(MatSetSizes(b->B, B->rmap->n, B->cmap->N, B->rmap->n, B->cmap->N)); 11729566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(b->B, B, B)); 11739566063dSJacob Faibussowitsch PetscCall(MatSetType(b->B, MATSEQSELL)); 1174d4002b98SHong Zhang } 1175d4002b98SHong Zhang 11769566063dSJacob Faibussowitsch PetscCall(MatSeqSELLSetPreallocation(b->A, d_rlenmax, d_rlen)); 11779566063dSJacob Faibussowitsch PetscCall(MatSeqSELLSetPreallocation(b->B, o_rlenmax, o_rlen)); 1178d4002b98SHong Zhang B->preallocated = PETSC_TRUE; 1179d4002b98SHong Zhang B->was_assembled = PETSC_FALSE; 1180d4002b98SHong Zhang /* 1181d4002b98SHong Zhang critical for MatAssemblyEnd to work. 1182d4002b98SHong Zhang MatAssemblyBegin checks it to set up was_assembled 1183d4002b98SHong Zhang and MatAssemblyEnd checks was_assembled to determine whether to build garray 1184d4002b98SHong Zhang */ 1185d4002b98SHong Zhang B->assembled = PETSC_FALSE; 11863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1187d4002b98SHong Zhang } 1188d4002b98SHong Zhang 1189d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDuplicate_MPISELL(Mat matin, MatDuplicateOption cpvalues, Mat *newmat) 1190d71ae5a4SJacob Faibussowitsch { 1191d4002b98SHong Zhang Mat mat; 1192d4002b98SHong Zhang Mat_MPISELL *a, *oldmat = (Mat_MPISELL *)matin->data; 1193d4002b98SHong Zhang 1194d4002b98SHong Zhang PetscFunctionBegin; 1195f4259b30SLisandro Dalcin *newmat = NULL; 11969566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)matin), &mat)); 11979566063dSJacob Faibussowitsch PetscCall(MatSetSizes(mat, matin->rmap->n, matin->cmap->n, matin->rmap->N, matin->cmap->N)); 11989566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(mat, matin, matin)); 11999566063dSJacob Faibussowitsch PetscCall(MatSetType(mat, ((PetscObject)matin)->type_name)); 1200d4002b98SHong Zhang a = (Mat_MPISELL *)mat->data; 1201d4002b98SHong Zhang 1202d4002b98SHong Zhang mat->factortype = matin->factortype; 1203d4002b98SHong Zhang mat->assembled = PETSC_TRUE; 1204d4002b98SHong Zhang mat->insertmode = NOT_SET_VALUES; 1205d4002b98SHong Zhang mat->preallocated = PETSC_TRUE; 1206d4002b98SHong Zhang 1207d4002b98SHong Zhang a->size = oldmat->size; 1208d4002b98SHong Zhang a->rank = oldmat->rank; 1209d4002b98SHong Zhang a->donotstash = oldmat->donotstash; 1210d4002b98SHong Zhang a->roworiented = oldmat->roworiented; 1211f4259b30SLisandro Dalcin a->rowindices = NULL; 1212f4259b30SLisandro Dalcin a->rowvalues = NULL; 1213d4002b98SHong Zhang a->getrowactive = PETSC_FALSE; 1214d4002b98SHong Zhang 12159566063dSJacob Faibussowitsch PetscCall(PetscLayoutReference(matin->rmap, &mat->rmap)); 12169566063dSJacob Faibussowitsch PetscCall(PetscLayoutReference(matin->cmap, &mat->cmap)); 1217d4002b98SHong Zhang 1218d4002b98SHong Zhang if (oldmat->colmap) { 1219d4002b98SHong Zhang #if defined(PETSC_USE_CTABLE) 1220eec179cfSJacob Faibussowitsch PetscCall(PetscHMapIDuplicate(oldmat->colmap, &a->colmap)); 1221d4002b98SHong Zhang #else 12229566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(mat->cmap->N, &a->colmap)); 12239566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(a->colmap, oldmat->colmap, mat->cmap->N)); 1224d4002b98SHong Zhang #endif 1225f4259b30SLisandro Dalcin } else a->colmap = NULL; 1226d4002b98SHong Zhang if (oldmat->garray) { 1227d4002b98SHong Zhang PetscInt len; 1228d4002b98SHong Zhang len = oldmat->B->cmap->n; 12299566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(len + 1, &a->garray)); 12309566063dSJacob Faibussowitsch if (len) PetscCall(PetscArraycpy(a->garray, oldmat->garray, len)); 1231f4259b30SLisandro Dalcin } else a->garray = NULL; 1232d4002b98SHong Zhang 12339566063dSJacob Faibussowitsch PetscCall(VecDuplicate(oldmat->lvec, &a->lvec)); 12349566063dSJacob Faibussowitsch PetscCall(VecScatterCopy(oldmat->Mvctx, &a->Mvctx)); 12359566063dSJacob Faibussowitsch PetscCall(MatDuplicate(oldmat->A, cpvalues, &a->A)); 12369566063dSJacob Faibussowitsch PetscCall(MatDuplicate(oldmat->B, cpvalues, &a->B)); 12379566063dSJacob Faibussowitsch PetscCall(PetscFunctionListDuplicate(((PetscObject)matin)->qlist, &((PetscObject)mat)->qlist)); 1238d4002b98SHong Zhang *newmat = mat; 12393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1240d4002b98SHong Zhang } 1241d4002b98SHong Zhang 1242d4002b98SHong Zhang /*@C 124311a5261eSBarry Smith MatMPISELLSetPreallocation - Preallocates memory for a `MATMPISELL` sparse parallel matrix in sell format. 1244d4002b98SHong Zhang For good matrix assembly performance the user should preallocate the matrix storage by 124567be906fSBarry Smith setting the parameters `d_nz` (or `d_nnz`) and `o_nz` (or `o_nnz`). 1246d4002b98SHong Zhang 1247d083f849SBarry Smith Collective 1248d4002b98SHong Zhang 1249d4002b98SHong Zhang Input Parameters: 1250d4002b98SHong Zhang + B - the matrix 1251d4002b98SHong Zhang . d_nz - number of nonzeros per row in DIAGONAL portion of local submatrix 1252d4002b98SHong Zhang (same value is used for all local rows) 1253d4002b98SHong Zhang . d_nnz - array containing the number of nonzeros in the various rows of the 1254d4002b98SHong Zhang DIAGONAL portion of the local submatrix (possibly different for each row) 125567be906fSBarry Smith or NULL (`PETSC_NULL_INTEGER` in Fortran), if `d_nz` is used to specify the nonzero structure. 1256d4002b98SHong Zhang The size of this array is equal to the number of local rows, i.e 'm'. 1257d4002b98SHong Zhang For matrices that will be factored, you must leave room for (and set) 1258d4002b98SHong Zhang the diagonal entry even if it is zero. 1259d4002b98SHong Zhang . o_nz - number of nonzeros per row in the OFF-DIAGONAL portion of local 1260d4002b98SHong Zhang submatrix (same value is used for all local rows). 1261d4002b98SHong Zhang - o_nnz - array containing the number of nonzeros in the various rows of the 1262d4002b98SHong Zhang OFF-DIAGONAL portion of the local submatrix (possibly different for 126367be906fSBarry Smith each row) or NULL (`PETSC_NULL_INTEGER` in Fortran), if `o_nz` is used to specify the nonzero 1264d4002b98SHong Zhang structure. The size of this array is equal to the number 1265d4002b98SHong Zhang of local rows, i.e 'm'. 1266d4002b98SHong Zhang 1267d4002b98SHong Zhang Example usage: 1268d4002b98SHong Zhang Consider the following 8x8 matrix with 34 non-zero values, that is 1269d4002b98SHong Zhang assembled across 3 processors. Lets assume that proc0 owns 3 rows, 1270d4002b98SHong Zhang proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 127167be906fSBarry Smith as follows 1272d4002b98SHong Zhang 1273d4002b98SHong Zhang .vb 1274d4002b98SHong Zhang 1 2 0 | 0 3 0 | 0 4 1275d4002b98SHong Zhang Proc0 0 5 6 | 7 0 0 | 8 0 1276d4002b98SHong Zhang 9 0 10 | 11 0 0 | 12 0 1277d4002b98SHong Zhang ------------------------------------- 1278d4002b98SHong Zhang 13 0 14 | 15 16 17 | 0 0 1279d4002b98SHong Zhang Proc1 0 18 0 | 19 20 21 | 0 0 1280d4002b98SHong Zhang 0 0 0 | 22 23 0 | 24 0 1281d4002b98SHong Zhang ------------------------------------- 1282d4002b98SHong Zhang Proc2 25 26 27 | 0 0 28 | 29 0 1283d4002b98SHong Zhang 30 0 0 | 31 32 33 | 0 34 1284d4002b98SHong Zhang .ve 1285d4002b98SHong Zhang 128627430b45SBarry Smith This can be represented as a collection of submatrices as 1287d4002b98SHong Zhang 1288d4002b98SHong Zhang .vb 1289d4002b98SHong Zhang A B C 1290d4002b98SHong Zhang D E F 1291d4002b98SHong Zhang G H I 1292d4002b98SHong Zhang .ve 1293d4002b98SHong Zhang 1294d4002b98SHong Zhang Where the submatrices A,B,C are owned by proc0, D,E,F are 1295d4002b98SHong Zhang owned by proc1, G,H,I are owned by proc2. 1296d4002b98SHong Zhang 1297d4002b98SHong Zhang The 'm' parameters for proc0,proc1,proc2 are 3,3,2 respectively. 1298d4002b98SHong Zhang The 'n' parameters for proc0,proc1,proc2 are 3,3,2 respectively. 1299d4002b98SHong Zhang The 'M','N' parameters are 8,8, and have the same values on all procs. 1300d4002b98SHong Zhang 1301d4002b98SHong Zhang The DIAGONAL submatrices corresponding to proc0,proc1,proc2 are 1302d4002b98SHong Zhang submatrices [A], [E], [I] respectively. The OFF-DIAGONAL submatrices 1303d4002b98SHong Zhang corresponding to proc0,proc1,proc2 are [BC], [DF], [GH] respectively. 1304d4002b98SHong Zhang Internally, each processor stores the DIAGONAL part, and the OFF-DIAGONAL 130527430b45SBarry Smith part as `MATSEQSELL` matrices. For example, proc1 will store [E] as a `MATSEQSELL` 1306d4002b98SHong Zhang matrix, ans [DF] as another SeqSELL matrix. 1307d4002b98SHong Zhang 130867be906fSBarry Smith When `d_nz`, `o_nz` parameters are specified, `d_nz` storage elements are 1309d4002b98SHong Zhang allocated for every row of the local diagonal submatrix, and o_nz 1310d4002b98SHong Zhang storage locations are allocated for every row of the OFF-DIAGONAL submat. 131167be906fSBarry Smith One way to choose `d_nz` and `o_nz` is to use the max nonzerors per local 1312d4002b98SHong Zhang rows for each of the local DIAGONAL, and the OFF-DIAGONAL submatrices. 131327430b45SBarry Smith In this case, the values of d_nz,o_nz are 1314d4002b98SHong Zhang .vb 131527430b45SBarry Smith proc0 dnz = 2, o_nz = 2 131627430b45SBarry Smith proc1 dnz = 3, o_nz = 2 131727430b45SBarry Smith proc2 dnz = 1, o_nz = 4 1318d4002b98SHong Zhang .ve 1319d4002b98SHong Zhang We are allocating m*(d_nz+o_nz) storage locations for every proc. This 1320d4002b98SHong Zhang translates to 3*(2+2)=12 for proc0, 3*(3+2)=15 for proc1, 2*(1+4)=10 1321d4002b98SHong Zhang for proc3. i.e we are using 12+15+10=37 storage locations to store 1322d4002b98SHong Zhang 34 values. 1323d4002b98SHong Zhang 132467be906fSBarry Smith When `d_nnz`, `o_nnz` parameters are specified, the storage is specified 1325a5b23f4aSJose E. Roman for every row, corresponding to both DIAGONAL and OFF-DIAGONAL submatrices. 132627430b45SBarry Smith In the above case the values for d_nnz,o_nnz are 1327d4002b98SHong Zhang .vb 132827430b45SBarry Smith proc0 d_nnz = [2,2,2] and o_nnz = [2,2,2] 132927430b45SBarry Smith proc1 d_nnz = [3,3,2] and o_nnz = [2,1,1] 133027430b45SBarry Smith proc2 d_nnz = [1,1] and o_nnz = [4,4] 1331d4002b98SHong Zhang .ve 1332d4002b98SHong Zhang Here the space allocated is according to nz (or maximum values in the nnz 1333d4002b98SHong Zhang if nnz is provided) for DIAGONAL and OFF-DIAGONAL submatrices, i.e (2+2+3+2)*3+(1+4)*2=37 1334d4002b98SHong Zhang 1335d4002b98SHong Zhang Level: intermediate 1336d4002b98SHong Zhang 133767be906fSBarry Smith Notes: 133867be906fSBarry Smith If the *_nnz parameter is given then the *_nz parameter is ignored 133967be906fSBarry Smith 134067be906fSBarry Smith The stored row and column indices begin with zero. 134167be906fSBarry Smith 134267be906fSBarry Smith The parallel matrix is partitioned such that the first m0 rows belong to 134367be906fSBarry Smith process 0, the next m1 rows belong to process 1, the next m2 rows belong 134467be906fSBarry Smith to process 2 etc.. where m0,m1,m2... are the input parameter 'm'. 134567be906fSBarry Smith 134667be906fSBarry Smith The DIAGONAL portion of the local submatrix of a processor can be defined 134767be906fSBarry Smith as the submatrix which is obtained by extraction the part corresponding to 134867be906fSBarry Smith the rows r1-r2 and columns c1-c2 of the global matrix, where r1 is the 134967be906fSBarry Smith first row that belongs to the processor, r2 is the last row belonging to 135067be906fSBarry Smith the this processor, and c1-c2 is range of indices of the local part of a 135167be906fSBarry Smith vector suitable for applying the matrix to. This is an mxn matrix. In the 135267be906fSBarry Smith common case of a square matrix, the row and column ranges are the same and 135367be906fSBarry Smith the DIAGONAL part is also square. The remaining portion of the local 135467be906fSBarry Smith submatrix (mxN) constitute the OFF-DIAGONAL portion. 135567be906fSBarry Smith 135667be906fSBarry Smith If `o_nnz`, `d_nnz` are specified, then `o_nz`, and `d_nz` are ignored. 135767be906fSBarry Smith 135867be906fSBarry Smith You can call `MatGetInfo()` to get information on how effective the preallocation was; 135967be906fSBarry Smith for example the fields mallocs,nz_allocated,nz_used,nz_unneeded; 136067be906fSBarry Smith You can also run with the option -info and look for messages with the string 136167be906fSBarry Smith malloc in them to see if additional memory allocation was needed. 136267be906fSBarry Smith 136367be906fSBarry Smith .seealso: `Mat`, `MatCreate()`, `MatCreateSeqSELL()`, `MatSetValues()`, `MatCreatesell()`, 136411a5261eSBarry Smith `MATMPISELL`, `MatGetInfo()`, `PetscSplitOwnership()`, `MATSELL` 1365d4002b98SHong Zhang @*/ 1366d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMPISELLSetPreallocation(Mat B, PetscInt d_nz, const PetscInt d_nnz[], PetscInt o_nz, const PetscInt o_nnz[]) 1367d71ae5a4SJacob Faibussowitsch { 1368d4002b98SHong Zhang PetscFunctionBegin; 1369d4002b98SHong Zhang PetscValidHeaderSpecific(B, MAT_CLASSID, 1); 1370d4002b98SHong Zhang PetscValidType(B, 1); 1371cac4c232SBarry Smith PetscTryMethod(B, "MatMPISELLSetPreallocation_C", (Mat, PetscInt, const PetscInt[], PetscInt, const PetscInt[]), (B, d_nz, d_nnz, o_nz, o_nnz)); 13723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1373d4002b98SHong Zhang } 1374d4002b98SHong Zhang 1375ed73aabaSBarry Smith /*MC 1376ed73aabaSBarry Smith MATMPISELL - MATMPISELL = "mpisell" - A matrix type to be used for MPI sparse matrices, 1377ed73aabaSBarry Smith based on the sliced Ellpack format 1378ed73aabaSBarry Smith 137927430b45SBarry Smith Options Database Key: 1380*20f4b53cSBarry Smith . -mat_type sell - sets the matrix type to `MATSELL` during a call to `MatSetFromOptions()` 1381ed73aabaSBarry Smith 1382ed73aabaSBarry Smith Level: beginner 1383ed73aabaSBarry Smith 138467be906fSBarry Smith .seealso: `Mat`, `MatCreateSell()`, `MATSEQSELL`, `MATSELL`, `MATSEQAIJ`, `MATAIJ`, `MATMPIAIJ` 1385ed73aabaSBarry Smith M*/ 1386ed73aabaSBarry Smith 1387d4002b98SHong Zhang /*@C 138811a5261eSBarry Smith MatCreateSELL - Creates a sparse parallel matrix in `MATSELL` format. 1389d4002b98SHong Zhang 1390d083f849SBarry Smith Collective 1391d4002b98SHong Zhang 1392d4002b98SHong Zhang Input Parameters: 1393d4002b98SHong Zhang + comm - MPI communicator 139411a5261eSBarry Smith . m - number of local rows (or `PETSC_DECIDE` to have calculated if M is given) 1395d4002b98SHong Zhang This value should be the same as the local size used in creating the 1396d4002b98SHong Zhang y vector for the matrix-vector product y = Ax. 1397d4002b98SHong Zhang . n - This value should be the same as the local size used in creating the 1398*20f4b53cSBarry Smith x vector for the matrix-vector product y = Ax. (or `PETSC_DECIDE` to have 1399*20f4b53cSBarry Smith calculated if `N` is given) For square matrices n is almost always `m`. 1400*20f4b53cSBarry Smith . M - number of global rows (or `PETSC_DETERMINE` to have calculated if `m` is given) 1401*20f4b53cSBarry Smith . N - number of global columns (or `PETSC_DETERMINE` to have calculated if `n` is given) 1402d4002b98SHong Zhang . d_rlenmax - max number of nonzeros per row in DIAGONAL portion of local submatrix 1403d4002b98SHong Zhang (same value is used for all local rows) 1404d4002b98SHong Zhang . d_rlen - array containing the number of nonzeros in the various rows of the 1405d4002b98SHong Zhang DIAGONAL portion of the local submatrix (possibly different for each row) 1406*20f4b53cSBarry Smith or `NULL`, if d_rlenmax is used to specify the nonzero structure. 1407*20f4b53cSBarry Smith The size of this array is equal to the number of local rows, i.e `m`. 1408d4002b98SHong Zhang . o_rlenmax - max number of nonzeros per row in the OFF-DIAGONAL portion of local 1409d4002b98SHong Zhang submatrix (same value is used for all local rows). 1410d4002b98SHong Zhang - o_rlen - array containing the number of nonzeros in the various rows of the 1411d4002b98SHong Zhang OFF-DIAGONAL portion of the local submatrix (possibly different for 1412*20f4b53cSBarry Smith each row) or `NULL`, if `o_rlenmax` is used to specify the nonzero 1413d4002b98SHong Zhang structure. The size of this array is equal to the number 1414*20f4b53cSBarry Smith of local rows, i.e `m`. 1415d4002b98SHong Zhang 1416d4002b98SHong Zhang Output Parameter: 1417d4002b98SHong Zhang . A - the matrix 1418d4002b98SHong Zhang 141927430b45SBarry Smith Options Database Key: 142027430b45SBarry Smith - -mat_sell_oneindex - Internally use indexing starting at 1 142127430b45SBarry Smith rather than 0. When calling `MatSetValues()`, 142227430b45SBarry Smith the user still MUST index entries starting at 0! 142327430b45SBarry Smith 142427430b45SBarry Smith Example: 142527430b45SBarry Smith Consider the following 8x8 matrix with 34 non-zero values, that is 142627430b45SBarry Smith assembled across 3 processors. Lets assume that proc0 owns 3 rows, 142727430b45SBarry Smith proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 142827430b45SBarry Smith as follows 142927430b45SBarry Smith 143027430b45SBarry Smith .vb 143127430b45SBarry Smith 1 2 0 | 0 3 0 | 0 4 143227430b45SBarry Smith Proc0 0 5 6 | 7 0 0 | 8 0 143327430b45SBarry Smith 9 0 10 | 11 0 0 | 12 0 143427430b45SBarry Smith ------------------------------------- 143527430b45SBarry Smith 13 0 14 | 15 16 17 | 0 0 143627430b45SBarry Smith Proc1 0 18 0 | 19 20 21 | 0 0 143727430b45SBarry Smith 0 0 0 | 22 23 0 | 24 0 143827430b45SBarry Smith ------------------------------------- 143927430b45SBarry Smith Proc2 25 26 27 | 0 0 28 | 29 0 144027430b45SBarry Smith 30 0 0 | 31 32 33 | 0 34 144127430b45SBarry Smith .ve 144227430b45SBarry Smith 1443*20f4b53cSBarry Smith This can be represented as a collection of submatrices as 144427430b45SBarry Smith .vb 144527430b45SBarry Smith A B C 144627430b45SBarry Smith D E F 144727430b45SBarry Smith G H I 144827430b45SBarry Smith .ve 144927430b45SBarry Smith 145027430b45SBarry Smith Where the submatrices A,B,C are owned by proc0, D,E,F are 145127430b45SBarry Smith owned by proc1, G,H,I are owned by proc2. 145227430b45SBarry Smith 145327430b45SBarry Smith The 'm' parameters for proc0,proc1,proc2 are 3,3,2 respectively. 145427430b45SBarry Smith The 'n' parameters for proc0,proc1,proc2 are 3,3,2 respectively. 145527430b45SBarry Smith The 'M','N' parameters are 8,8, and have the same values on all procs. 145627430b45SBarry Smith 145727430b45SBarry Smith The DIAGONAL submatrices corresponding to proc0,proc1,proc2 are 145827430b45SBarry Smith submatrices [A], [E], [I] respectively. The OFF-DIAGONAL submatrices 145927430b45SBarry Smith corresponding to proc0,proc1,proc2 are [BC], [DF], [GH] respectively. 146027430b45SBarry Smith Internally, each processor stores the DIAGONAL part, and the OFF-DIAGONAL 146127430b45SBarry Smith part as `MATSEQSELL` matrices. For example, proc1 will store [E] as a `MATSEQSELL` 146227430b45SBarry Smith matrix, ans [DF] as another `MATSEQSELL` matrix. 146327430b45SBarry Smith 146427430b45SBarry Smith When d_rlenmax, o_rlenmax parameters are specified, d_rlenmax storage elements are 146527430b45SBarry Smith allocated for every row of the local diagonal submatrix, and o_rlenmax 146627430b45SBarry Smith storage locations are allocated for every row of the OFF-DIAGONAL submat. 146727430b45SBarry Smith One way to choose d_rlenmax and o_rlenmax is to use the max nonzerors per local 146827430b45SBarry Smith rows for each of the local DIAGONAL, and the OFF-DIAGONAL submatrices. 1469*20f4b53cSBarry Smith In this case, the values of d_rlenmax,o_rlenmax are 147027430b45SBarry Smith .vb 1471*20f4b53cSBarry Smith proc0 - d_rlenmax = 2, o_rlenmax = 2 1472*20f4b53cSBarry Smith proc1 - d_rlenmax = 3, o_rlenmax = 2 1473*20f4b53cSBarry Smith proc2 - d_rlenmax = 1, o_rlenmax = 4 147427430b45SBarry Smith .ve 147527430b45SBarry Smith We are allocating m*(d_rlenmax+o_rlenmax) storage locations for every proc. This 147627430b45SBarry Smith translates to 3*(2+2)=12 for proc0, 3*(3+2)=15 for proc1, 2*(1+4)=10 147727430b45SBarry Smith for proc3. i.e we are using 12+15+10=37 storage locations to store 147827430b45SBarry Smith 34 values. 147927430b45SBarry Smith 1480*20f4b53cSBarry Smith When `d_rlen`, `o_rlen` parameters are specified, the storage is specified 148127430b45SBarry Smith for every row, corresponding to both DIAGONAL and OFF-DIAGONAL submatrices. 1482*20f4b53cSBarry Smith In the above case the values for `d_nnz`, `o_nnz` are 148327430b45SBarry Smith .vb 1484*20f4b53cSBarry Smith proc0 - d_nnz = [2,2,2] and o_nnz = [2,2,2] 1485*20f4b53cSBarry Smith proc1 - d_nnz = [3,3,2] and o_nnz = [2,1,1] 1486*20f4b53cSBarry Smith proc2 - d_nnz = [1,1] and o_nnz = [4,4] 148727430b45SBarry Smith .ve 148827430b45SBarry Smith Here the space allocated is still 37 though there are 34 nonzeros because 148927430b45SBarry Smith the allocation is always done according to rlenmax. 149027430b45SBarry Smith 149127430b45SBarry Smith Level: intermediate 149227430b45SBarry Smith 149327430b45SBarry Smith Notes: 149411a5261eSBarry Smith It is recommended that one use the `MatCreate()`, `MatSetType()` and/or `MatSetFromOptions()`, 1495f6f02116SRichard Tran Mills MatXXXXSetPreallocation() paradigm instead of this routine directly. 149611a5261eSBarry Smith [MatXXXXSetPreallocation() is, for example, `MatSeqSELLSetPreallocation()`] 1497d4002b98SHong Zhang 1498d4002b98SHong Zhang If the *_rlen parameter is given then the *_rlenmax parameter is ignored 1499d4002b98SHong Zhang 1500*20f4b53cSBarry Smith `m`, `n`, `M`, `N` parameters specify the size of the matrix, and its partitioning across 1501*20f4b53cSBarry Smith processors, while `d_rlenmax`, `d_rlen`, `o_rlenmax` , `o_rlen` parameters specify the approximate 1502d4002b98SHong Zhang storage requirements for this matrix. 1503d4002b98SHong Zhang 150411a5261eSBarry Smith If `PETSC_DECIDE` or `PETSC_DETERMINE` is used for a particular argument on one 1505d4002b98SHong Zhang processor than it must be used on all processors that share the object for 1506d4002b98SHong Zhang that argument. 1507d4002b98SHong Zhang 1508d4002b98SHong Zhang The user MUST specify either the local or global matrix dimensions 1509d4002b98SHong Zhang (possibly both). 1510d4002b98SHong Zhang 1511d4002b98SHong Zhang The parallel matrix is partitioned across processors such that the 1512d4002b98SHong Zhang first m0 rows belong to process 0, the next m1 rows belong to 1513d4002b98SHong Zhang process 1, the next m2 rows belong to process 2 etc.. where 1514d4002b98SHong Zhang m0,m1,m2,.. are the input parameter 'm'. i.e each processor stores 1515*20f4b53cSBarry Smith values corresponding to [`m` x `N`] submatrix. 1516d4002b98SHong Zhang 1517d4002b98SHong Zhang The columns are logically partitioned with the n0 columns belonging 1518d4002b98SHong Zhang to 0th partition, the next n1 columns belonging to the next 1519*20f4b53cSBarry Smith partition etc.. where n0,n1,n2... are the input parameter `n`. 1520d4002b98SHong Zhang 1521d4002b98SHong Zhang The DIAGONAL portion of the local submatrix on any given processor 1522*20f4b53cSBarry Smith is the submatrix corresponding to the rows and columns `m`, `n` 1523d4002b98SHong Zhang corresponding to the given processor. i.e diagonal matrix on 1524d4002b98SHong Zhang process 0 is [m0 x n0], diagonal matrix on process 1 is [m1 x n1] 1525d4002b98SHong Zhang etc. The remaining portion of the local submatrix [m x (N-n)] 1526d4002b98SHong Zhang constitute the OFF-DIAGONAL portion. The example below better 1527d4002b98SHong Zhang illustrates this concept. 1528d4002b98SHong Zhang 1529d4002b98SHong Zhang For a square global matrix we define each processor's diagonal portion 1530d4002b98SHong Zhang to be its local rows and the corresponding columns (a square submatrix); 1531d4002b98SHong Zhang each processor's off-diagonal portion encompasses the remainder of the 1532d4002b98SHong Zhang local matrix (a rectangular submatrix). 1533d4002b98SHong Zhang 1534*20f4b53cSBarry Smith If `o_rlen`, `d_rlen` are specified, then `o_rlenmax`, and `d_rlenmax` are ignored. 1535d4002b98SHong Zhang 1536d4002b98SHong Zhang When calling this routine with a single process communicator, a matrix of 153711a5261eSBarry Smith type `MATSEQSELL` is returned. If a matrix of type `MATMPISELL` is desired for this 153827430b45SBarry Smith type of communicator, use the construction mechanism 1539d4002b98SHong Zhang .vb 154027430b45SBarry Smith MatCreate(...,&A); 154127430b45SBarry Smith MatSetType(A,MATMPISELL); 154227430b45SBarry Smith MatSetSizes(A, m,n,M,N); 154327430b45SBarry Smith MatMPISELLSetPreallocation(A,...); 1544d4002b98SHong Zhang .ve 1545d4002b98SHong Zhang 154667be906fSBarry Smith .seealso: `Mat`, `MATSELL`, `MatCreate()`, `MatCreateSeqSELL()`, `MatSetValues()`, `MatMPISELLSetPreallocation()`, `MatMPISELLSetPreallocationSELL()`, 1547db781477SPatrick Sanan `MATMPISELL`, `MatCreateMPISELLWithArrays()` 1548d4002b98SHong Zhang @*/ 1549d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateSELL(MPI_Comm comm, PetscInt m, PetscInt n, PetscInt M, PetscInt N, PetscInt d_rlenmax, const PetscInt d_rlen[], PetscInt o_rlenmax, const PetscInt o_rlen[], Mat *A) 1550d71ae5a4SJacob Faibussowitsch { 1551d4002b98SHong Zhang PetscMPIInt size; 1552d4002b98SHong Zhang 1553d4002b98SHong Zhang PetscFunctionBegin; 15549566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, A)); 15559566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*A, m, n, M, N)); 15569566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 1557d4002b98SHong Zhang if (size > 1) { 15589566063dSJacob Faibussowitsch PetscCall(MatSetType(*A, MATMPISELL)); 15599566063dSJacob Faibussowitsch PetscCall(MatMPISELLSetPreallocation(*A, d_rlenmax, d_rlen, o_rlenmax, o_rlen)); 1560d4002b98SHong Zhang } else { 15619566063dSJacob Faibussowitsch PetscCall(MatSetType(*A, MATSEQSELL)); 15629566063dSJacob Faibussowitsch PetscCall(MatSeqSELLSetPreallocation(*A, d_rlenmax, d_rlen)); 1563d4002b98SHong Zhang } 15643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1565d4002b98SHong Zhang } 1566d4002b98SHong Zhang 1567d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMPISELLGetSeqSELL(Mat A, Mat *Ad, Mat *Ao, const PetscInt *colmap[]) 1568d71ae5a4SJacob Faibussowitsch { 1569d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 1570d4002b98SHong Zhang PetscBool flg; 1571d4002b98SHong Zhang 1572d4002b98SHong Zhang PetscFunctionBegin; 15739566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMPISELL, &flg)); 157428b400f6SJacob Faibussowitsch PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "This function requires a MATMPISELL matrix as input"); 1575d4002b98SHong Zhang if (Ad) *Ad = a->A; 1576d4002b98SHong Zhang if (Ao) *Ao = a->B; 1577d4002b98SHong Zhang if (colmap) *colmap = a->garray; 15783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1579d4002b98SHong Zhang } 1580d4002b98SHong Zhang 1581d4002b98SHong Zhang /*@C 158211a5261eSBarry Smith MatMPISELLGetLocalMatCondensed - Creates a `MATSEQSELL` matrix from an `MATMPISELL` matrix by taking all its local rows and NON-ZERO columns 1583d4002b98SHong Zhang 1584d4002b98SHong Zhang Not Collective 1585d4002b98SHong Zhang 1586d4002b98SHong Zhang Input Parameters: 1587d4002b98SHong Zhang + A - the matrix 158811a5261eSBarry Smith . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 158967be906fSBarry Smith . row - index sets of rows to extract (or `NULL`) 159067be906fSBarry Smith - col - index sets of columns to extract (or `NULL`) 1591d4002b98SHong Zhang 1592d4002b98SHong Zhang Output Parameter: 1593d4002b98SHong Zhang . A_loc - the local sequential matrix generated 1594d4002b98SHong Zhang 1595d4002b98SHong Zhang Level: developer 1596d4002b98SHong Zhang 159767be906fSBarry Smith .seealso: `Mat`, `MATSEQSELL`, `MATMPISELL`, `MatGetOwnershipRange()`, `MatMPISELLGetLocalMat()` 1598d4002b98SHong Zhang @*/ 1599d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMPISELLGetLocalMatCondensed(Mat A, MatReuse scall, IS *row, IS *col, Mat *A_loc) 1600d71ae5a4SJacob Faibussowitsch { 1601d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 1602d4002b98SHong Zhang PetscInt i, start, end, ncols, nzA, nzB, *cmap, imark, *idx; 1603d4002b98SHong Zhang IS isrowa, iscola; 1604d4002b98SHong Zhang Mat *aloc; 1605d4002b98SHong Zhang PetscBool match; 1606d4002b98SHong Zhang 1607d4002b98SHong Zhang PetscFunctionBegin; 16089566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMPISELL, &match)); 160928b400f6SJacob Faibussowitsch PetscCheck(match, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Requires MATMPISELL matrix as input"); 16109566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(MAT_Getlocalmatcondensed, A, 0, 0, 0)); 1611d4002b98SHong Zhang if (!row) { 16129371c9d4SSatish Balay start = A->rmap->rstart; 16139371c9d4SSatish Balay end = A->rmap->rend; 16149566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, end - start, start, 1, &isrowa)); 1615d4002b98SHong Zhang } else { 1616d4002b98SHong Zhang isrowa = *row; 1617d4002b98SHong Zhang } 1618d4002b98SHong Zhang if (!col) { 1619d4002b98SHong Zhang start = A->cmap->rstart; 1620d4002b98SHong Zhang cmap = a->garray; 1621d4002b98SHong Zhang nzA = a->A->cmap->n; 1622d4002b98SHong Zhang nzB = a->B->cmap->n; 16239566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nzA + nzB, &idx)); 1624d4002b98SHong Zhang ncols = 0; 1625d4002b98SHong Zhang for (i = 0; i < nzB; i++) { 1626d4002b98SHong Zhang if (cmap[i] < start) idx[ncols++] = cmap[i]; 1627d4002b98SHong Zhang else break; 1628d4002b98SHong Zhang } 1629d4002b98SHong Zhang imark = i; 1630d4002b98SHong Zhang for (i = 0; i < nzA; i++) idx[ncols++] = start + i; 1631d4002b98SHong Zhang for (i = imark; i < nzB; i++) idx[ncols++] = cmap[i]; 16329566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, ncols, idx, PETSC_OWN_POINTER, &iscola)); 1633d4002b98SHong Zhang } else { 1634d4002b98SHong Zhang iscola = *col; 1635d4002b98SHong Zhang } 1636d4002b98SHong Zhang if (scall != MAT_INITIAL_MATRIX) { 16379566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1, &aloc)); 1638d4002b98SHong Zhang aloc[0] = *A_loc; 1639d4002b98SHong Zhang } 16409566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrices(A, 1, &isrowa, &iscola, scall, &aloc)); 1641d4002b98SHong Zhang *A_loc = aloc[0]; 16429566063dSJacob Faibussowitsch PetscCall(PetscFree(aloc)); 164348a46eb9SPierre Jolivet if (!row) PetscCall(ISDestroy(&isrowa)); 164448a46eb9SPierre Jolivet if (!col) PetscCall(ISDestroy(&iscola)); 16459566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(MAT_Getlocalmatcondensed, A, 0, 0, 0)); 16463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1647d4002b98SHong Zhang } 1648d4002b98SHong Zhang 1649d4002b98SHong Zhang #include <../src/mat/impls/aij/mpi/mpiaij.h> 1650d4002b98SHong Zhang 1651d71ae5a4SJacob Faibussowitsch PetscErrorCode MatConvert_MPISELL_MPIAIJ(Mat A, MatType newtype, MatReuse reuse, Mat *newmat) 1652d71ae5a4SJacob Faibussowitsch { 1653d4002b98SHong Zhang Mat_MPISELL *a = (Mat_MPISELL *)A->data; 1654d4002b98SHong Zhang Mat B; 1655d4002b98SHong Zhang Mat_MPIAIJ *b; 1656d4002b98SHong Zhang 1657d4002b98SHong Zhang PetscFunctionBegin; 165828b400f6SJacob Faibussowitsch PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Matrix must be assembled"); 1659d4002b98SHong Zhang 166094a8b381SRichard Tran Mills if (reuse == MAT_REUSE_MATRIX) { 166194a8b381SRichard Tran Mills B = *newmat; 166294a8b381SRichard Tran Mills } else { 16639566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B)); 16649566063dSJacob Faibussowitsch PetscCall(MatSetType(B, MATMPIAIJ)); 16659566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N)); 16669566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(B, A->rmap->bs, A->cmap->bs)); 16679566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(B, 0, NULL)); 16689566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(B, 0, NULL, 0, NULL)); 166994a8b381SRichard Tran Mills } 1670d4002b98SHong Zhang b = (Mat_MPIAIJ *)B->data; 167194a8b381SRichard Tran Mills 167294a8b381SRichard Tran Mills if (reuse == MAT_REUSE_MATRIX) { 16739566063dSJacob Faibussowitsch PetscCall(MatConvert_SeqSELL_SeqAIJ(a->A, MATSEQAIJ, MAT_REUSE_MATRIX, &b->A)); 16749566063dSJacob Faibussowitsch PetscCall(MatConvert_SeqSELL_SeqAIJ(a->B, MATSEQAIJ, MAT_REUSE_MATRIX, &b->B)); 167594a8b381SRichard Tran Mills } else { 16769566063dSJacob Faibussowitsch PetscCall(MatDestroy(&b->A)); 16779566063dSJacob Faibussowitsch PetscCall(MatDestroy(&b->B)); 16789566063dSJacob Faibussowitsch PetscCall(MatDisAssemble_MPISELL(A)); 16799566063dSJacob Faibussowitsch PetscCall(MatConvert_SeqSELL_SeqAIJ(a->A, MATSEQAIJ, MAT_INITIAL_MATRIX, &b->A)); 16809566063dSJacob Faibussowitsch PetscCall(MatConvert_SeqSELL_SeqAIJ(a->B, MATSEQAIJ, MAT_INITIAL_MATRIX, &b->B)); 16819566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 16829566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 16839566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 16849566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 168594a8b381SRichard Tran Mills } 1686d4002b98SHong Zhang 1687d4002b98SHong Zhang if (reuse == MAT_INPLACE_MATRIX) { 16889566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(A, &B)); 1689d4002b98SHong Zhang } else { 1690d4002b98SHong Zhang *newmat = B; 1691d4002b98SHong Zhang } 16923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1693d4002b98SHong Zhang } 1694d4002b98SHong Zhang 1695d71ae5a4SJacob Faibussowitsch PetscErrorCode MatConvert_MPIAIJ_MPISELL(Mat A, MatType newtype, MatReuse reuse, Mat *newmat) 1696d71ae5a4SJacob Faibussowitsch { 1697d4002b98SHong Zhang Mat_MPIAIJ *a = (Mat_MPIAIJ *)A->data; 1698d4002b98SHong Zhang Mat B; 1699d4002b98SHong Zhang Mat_MPISELL *b; 1700d4002b98SHong Zhang 1701d4002b98SHong Zhang PetscFunctionBegin; 170228b400f6SJacob Faibussowitsch PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Matrix must be assembled"); 1703d4002b98SHong Zhang 170494a8b381SRichard Tran Mills if (reuse == MAT_REUSE_MATRIX) { 170594a8b381SRichard Tran Mills B = *newmat; 170694a8b381SRichard Tran Mills } else { 17079566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B)); 17089566063dSJacob Faibussowitsch PetscCall(MatSetType(B, MATMPISELL)); 17099566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N)); 17109566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(B, A->rmap->bs, A->cmap->bs)); 17119566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(B, 0, NULL)); 17129566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(B, 0, NULL, 0, NULL)); 171394a8b381SRichard Tran Mills } 1714d4002b98SHong Zhang b = (Mat_MPISELL *)B->data; 171594a8b381SRichard Tran Mills 171694a8b381SRichard Tran Mills if (reuse == MAT_REUSE_MATRIX) { 17179566063dSJacob Faibussowitsch PetscCall(MatConvert_SeqAIJ_SeqSELL(a->A, MATSEQSELL, MAT_REUSE_MATRIX, &b->A)); 17189566063dSJacob Faibussowitsch PetscCall(MatConvert_SeqAIJ_SeqSELL(a->B, MATSEQSELL, MAT_REUSE_MATRIX, &b->B)); 171994a8b381SRichard Tran Mills } else { 17209566063dSJacob Faibussowitsch PetscCall(MatDestroy(&b->A)); 17219566063dSJacob Faibussowitsch PetscCall(MatDestroy(&b->B)); 17229566063dSJacob Faibussowitsch PetscCall(MatDisAssemble_MPIAIJ(A)); 17239566063dSJacob Faibussowitsch PetscCall(MatConvert_SeqAIJ_SeqSELL(a->A, MATSEQSELL, MAT_INITIAL_MATRIX, &b->A)); 17249566063dSJacob Faibussowitsch PetscCall(MatConvert_SeqAIJ_SeqSELL(a->B, MATSEQSELL, MAT_INITIAL_MATRIX, &b->B)); 17259566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 17269566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 17279566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 17289566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 172994a8b381SRichard Tran Mills } 1730d4002b98SHong Zhang 1731d4002b98SHong Zhang if (reuse == MAT_INPLACE_MATRIX) { 17329566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(A, &B)); 1733d4002b98SHong Zhang } else { 1734d4002b98SHong Zhang *newmat = B; 1735d4002b98SHong Zhang } 17363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1737d4002b98SHong Zhang } 1738d4002b98SHong Zhang 1739d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSOR_MPISELL(Mat matin, Vec bb, PetscReal omega, MatSORType flag, PetscReal fshift, PetscInt its, PetscInt lits, Vec xx) 1740d71ae5a4SJacob Faibussowitsch { 1741d4002b98SHong Zhang Mat_MPISELL *mat = (Mat_MPISELL *)matin->data; 1742f4259b30SLisandro Dalcin Vec bb1 = NULL; 1743d4002b98SHong Zhang 1744d4002b98SHong Zhang PetscFunctionBegin; 1745d4002b98SHong Zhang if (flag == SOR_APPLY_UPPER) { 17469566063dSJacob Faibussowitsch PetscCall((*mat->A->ops->sor)(mat->A, bb, omega, flag, fshift, lits, 1, xx)); 17473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1748d4002b98SHong Zhang } 1749d4002b98SHong Zhang 175048a46eb9SPierre Jolivet if (its > 1 || ~flag & SOR_ZERO_INITIAL_GUESS || flag & SOR_EISENSTAT) PetscCall(VecDuplicate(bb, &bb1)); 1751d4002b98SHong Zhang 1752d4002b98SHong Zhang if ((flag & SOR_LOCAL_SYMMETRIC_SWEEP) == SOR_LOCAL_SYMMETRIC_SWEEP) { 1753d4002b98SHong Zhang if (flag & SOR_ZERO_INITIAL_GUESS) { 17549566063dSJacob Faibussowitsch PetscCall((*mat->A->ops->sor)(mat->A, bb, omega, flag, fshift, lits, 1, xx)); 1755d4002b98SHong Zhang its--; 1756d4002b98SHong Zhang } 1757d4002b98SHong Zhang 1758d4002b98SHong Zhang while (its--) { 17599566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat->Mvctx, xx, mat->lvec, INSERT_VALUES, SCATTER_FORWARD)); 17609566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat->Mvctx, xx, mat->lvec, INSERT_VALUES, SCATTER_FORWARD)); 1761d4002b98SHong Zhang 1762d4002b98SHong Zhang /* update rhs: bb1 = bb - B*x */ 17639566063dSJacob Faibussowitsch PetscCall(VecScale(mat->lvec, -1.0)); 17649566063dSJacob Faibussowitsch PetscCall((*mat->B->ops->multadd)(mat->B, mat->lvec, bb, bb1)); 1765d4002b98SHong Zhang 1766d4002b98SHong Zhang /* local sweep */ 17679566063dSJacob Faibussowitsch PetscCall((*mat->A->ops->sor)(mat->A, bb1, omega, SOR_SYMMETRIC_SWEEP, fshift, lits, 1, xx)); 1768d4002b98SHong Zhang } 1769d4002b98SHong Zhang } else if (flag & SOR_LOCAL_FORWARD_SWEEP) { 1770d4002b98SHong Zhang if (flag & SOR_ZERO_INITIAL_GUESS) { 17719566063dSJacob Faibussowitsch PetscCall((*mat->A->ops->sor)(mat->A, bb, omega, flag, fshift, lits, 1, xx)); 1772d4002b98SHong Zhang its--; 1773d4002b98SHong Zhang } 1774d4002b98SHong Zhang while (its--) { 17759566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat->Mvctx, xx, mat->lvec, INSERT_VALUES, SCATTER_FORWARD)); 17769566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat->Mvctx, xx, mat->lvec, INSERT_VALUES, SCATTER_FORWARD)); 1777d4002b98SHong Zhang 1778d4002b98SHong Zhang /* update rhs: bb1 = bb - B*x */ 17799566063dSJacob Faibussowitsch PetscCall(VecScale(mat->lvec, -1.0)); 17809566063dSJacob Faibussowitsch PetscCall((*mat->B->ops->multadd)(mat->B, mat->lvec, bb, bb1)); 1781d4002b98SHong Zhang 1782d4002b98SHong Zhang /* local sweep */ 17839566063dSJacob Faibussowitsch PetscCall((*mat->A->ops->sor)(mat->A, bb1, omega, SOR_FORWARD_SWEEP, fshift, lits, 1, xx)); 1784d4002b98SHong Zhang } 1785d4002b98SHong Zhang } else if (flag & SOR_LOCAL_BACKWARD_SWEEP) { 1786d4002b98SHong Zhang if (flag & SOR_ZERO_INITIAL_GUESS) { 17879566063dSJacob Faibussowitsch PetscCall((*mat->A->ops->sor)(mat->A, bb, omega, flag, fshift, lits, 1, xx)); 1788d4002b98SHong Zhang its--; 1789d4002b98SHong Zhang } 1790d4002b98SHong Zhang while (its--) { 17919566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat->Mvctx, xx, mat->lvec, INSERT_VALUES, SCATTER_FORWARD)); 17929566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat->Mvctx, xx, mat->lvec, INSERT_VALUES, SCATTER_FORWARD)); 1793d4002b98SHong Zhang 1794d4002b98SHong Zhang /* update rhs: bb1 = bb - B*x */ 17959566063dSJacob Faibussowitsch PetscCall(VecScale(mat->lvec, -1.0)); 17969566063dSJacob Faibussowitsch PetscCall((*mat->B->ops->multadd)(mat->B, mat->lvec, bb, bb1)); 1797d4002b98SHong Zhang 1798d4002b98SHong Zhang /* local sweep */ 17999566063dSJacob Faibussowitsch PetscCall((*mat->A->ops->sor)(mat->A, bb1, omega, SOR_BACKWARD_SWEEP, fshift, lits, 1, xx)); 1800d4002b98SHong Zhang } 1801d4002b98SHong Zhang } else SETERRQ(PetscObjectComm((PetscObject)matin), PETSC_ERR_SUP, "Parallel SOR not supported"); 1802d4002b98SHong Zhang 18039566063dSJacob Faibussowitsch PetscCall(VecDestroy(&bb1)); 1804d4002b98SHong Zhang 1805d4002b98SHong Zhang matin->factorerrortype = mat->A->factorerrortype; 18063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1807d4002b98SHong Zhang } 1808d4002b98SHong Zhang 1809d4002b98SHong Zhang /*MC 1810d4002b98SHong Zhang MATMPISELL - MATMPISELL = "MPISELL" - A matrix type to be used for parallel sparse matrices. 1811d4002b98SHong Zhang 1812d4002b98SHong Zhang Options Database Keys: 181311a5261eSBarry Smith . -mat_type mpisell - sets the matrix type to `MATMPISELL` during a call to `MatSetFromOptions()` 1814d4002b98SHong Zhang 1815d4002b98SHong Zhang Level: beginner 1816d4002b98SHong Zhang 181767be906fSBarry Smith .seealso: `Mat`, `MATSELL`, `MATSEQSELL` `MatCreateSELL()` 1818d4002b98SHong Zhang M*/ 1819d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_MPISELL(Mat B) 1820d71ae5a4SJacob Faibussowitsch { 1821d4002b98SHong Zhang Mat_MPISELL *b; 1822d4002b98SHong Zhang PetscMPIInt size; 1823d4002b98SHong Zhang 1824d4002b98SHong Zhang PetscFunctionBegin; 18259566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)B), &size)); 18264dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&b)); 1827d4002b98SHong Zhang B->data = (void *)b; 18289566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(B->ops, &MatOps_Values, sizeof(struct _MatOps))); 1829d4002b98SHong Zhang B->assembled = PETSC_FALSE; 1830d4002b98SHong Zhang B->insertmode = NOT_SET_VALUES; 1831d4002b98SHong Zhang b->size = size; 18329566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)B), &b->rank)); 1833d4002b98SHong Zhang /* build cache for off array entries formed */ 18349566063dSJacob Faibussowitsch PetscCall(MatStashCreate_Private(PetscObjectComm((PetscObject)B), 1, &B->stash)); 1835d4002b98SHong Zhang 1836d4002b98SHong Zhang b->donotstash = PETSC_FALSE; 1837f4259b30SLisandro Dalcin b->colmap = NULL; 1838f4259b30SLisandro Dalcin b->garray = NULL; 1839d4002b98SHong Zhang b->roworiented = PETSC_TRUE; 1840d4002b98SHong Zhang 1841d4002b98SHong Zhang /* stuff used for matrix vector multiply */ 1842d4002b98SHong Zhang b->lvec = NULL; 1843d4002b98SHong Zhang b->Mvctx = NULL; 1844d4002b98SHong Zhang 1845d4002b98SHong Zhang /* stuff for MatGetRow() */ 1846f4259b30SLisandro Dalcin b->rowindices = NULL; 1847f4259b30SLisandro Dalcin b->rowvalues = NULL; 1848d4002b98SHong Zhang b->getrowactive = PETSC_FALSE; 1849d4002b98SHong Zhang 18509566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatStoreValues_C", MatStoreValues_MPISELL)); 18519566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatRetrieveValues_C", MatRetrieveValues_MPISELL)); 18529566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatIsTranspose_C", MatIsTranspose_MPISELL)); 18539566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatMPISELLSetPreallocation_C", MatMPISELLSetPreallocation_MPISELL)); 18549566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_mpisell_mpiaij_C", MatConvert_MPISELL_MPIAIJ)); 18559566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDiagonalScaleLocal_C", MatDiagonalScaleLocal_MPISELL)); 18569566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATMPISELL)); 18573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1858d4002b98SHong Zhang } 1859